|
|
/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
initia64.c
Abstract:
Does any ia64-specific initialization, then starts the common ARC osloader
Author:
John Vert (jvert) 4-Nov-1993
Revision History:
--*/ #include "bldria64.h"
#include "msg.h"
#include <netboot.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <efi.h>
UCHAR Argv0String[100];
UCHAR BootPartitionName[80]; UCHAR KernelBootDevice[80]; UCHAR OsLoadFilename[100]; UCHAR OsLoaderFilename[100]; UCHAR SystemPartition[100]; UCHAR OsLoadPartition[100]; UCHAR OsLoadOptions[100]; UCHAR ConsoleInputName[50]; UCHAR ConsoleOutputName[50]; UCHAR FullKernelPath[200];
ARC_STATUS BlGetEfiBootOptions( OUT PUCHAR Argv0String OPTIONAL, OUT PUCHAR SystemPartition OPTIONAL, OUT PUCHAR OsLoaderFilename OPTIONAL, OUT PUCHAR OsLoadPartition OPTIONAL, OUT PUCHAR OsLoadFilename OPTIONAL, OUT PUCHAR FullKernelPath OPTIONAL, OUT PUCHAR OsLoadOptions OPTIONAL );
BlPreProcessLoadOptions( PCHAR szOsLoadOptions );
#define MAXBOOTVARSIZE 1024
VOID BlpTruncateMemory ( IN ULONG MaxMemory );
#if defined(_MERCED_A0_)
VOID KiProcessorWorkAround( ); #endif
VOID BlStartup( IN PCHAR PartitionName )
/*++
Routine Description:
Does Intel-specific initialization, particularly presenting the boot.ini menu and running NTDETECT, then calls to the common osloader.
Arguments:
PartitionName - Supplies the ARC name of the partition (or floppy) that setupldr was loaded from.
Return Value:
Does not return
--*/
{ ULONG Argc = 0; PUCHAR Argv[10]; ARC_STATUS Status; ULONG BootFileId; PCHAR BootFile; ULONG Read; #if !defined(NO_LEGACY_DRIVERS)
PCHAR p; #endif
ULONG i; ULONG DriveId; ULONG FileSize; ULONG Count; LARGE_INTEGER SeekPosition; PCHAR LoadOptions = NULL; #ifdef FW_HEAP
extern BOOLEAN FwDescriptorsValid; #endif
PCHAR BadLinkName = NULL;
UNREFERENCED_PARAMETER( PartitionName );
//
// Initialize ARC StdIo functionality
//
strcpy(ConsoleInputName,"consolein=multi(0)key(0)keyboard(0)"); strcpy(ConsoleOutputName,"consoleout=multi(0)video(0)monitor(0)"); Argv[0]=ConsoleInputName; Argv[1]=ConsoleOutputName; BlInitStdio (2, Argv);
//
// Check ntldr partition for hiberation image
//
do {
BlClearScreen(); Status = BlGetEfiBootOptions( Argv0String, SystemPartition, OsLoaderFilename, OsLoadPartition, OsLoadFilename, FullKernelPath, OsLoadOptions ); if ( Status != ESUCCESS ) { BlPrint(BlFindMessage(BL_EFI_OPTION_FAILURE)); goto BootFailed; } BlClearScreen(); #if !defined(NO_LEGACY_DRIVERS)
p = FullKernelPath;
//
// Initialize SCSI boot driver, if necessary.
//
if(!_strnicmp(p,"scsi(",5)) { AEInitializeIo(DriveId); }
#endif // NO_LEGACY_DRIVERS
#if FW_HEAP
//
// Indicate that fw memory descriptors cannot be changed from
// now on.
//
FwDescriptorsValid = FALSE; #endif
//
// convert it to all one case
//
if (OsLoadOptions[0]) { _strupr(OsLoadOptions); }
Argv[Argc++]=Argv0String; Argv[Argc++]=OsLoaderFilename; Argv[Argc++]=SystemPartition; Argv[Argc++]=OsLoadFilename; Argv[Argc++]=OsLoadPartition; Argv[Argc++]=OsLoadOptions;
BlPreProcessLoadOptions( OsLoadOptions );
//
// In the x86 case, we would have already initialized the
// headless port so that the user could actually make his
// boot selection over the headless port. However, on ia64,
// that selection is happening during firmware.
//
// If the user wants us to redirect (via the OsLoadOptions), then
// we should try to do it here.
//
if( strstr(OsLoadOptions, "/REDIRECT")) {
//
// Yep, then want us to redirect. Try and initialize the
// port.
//
BlInitializeHeadlessPort();
#if 0
if( LoaderRedirectionInformation.PortNumber == 0 ) {
//
// We couldn't get any redirection information
// from the firmware. But the user really wants
// us to redirect. Better guess.
//
LoaderRedirectionInformation.PortNumber = 1; LoaderRedirectionInformation.BaudRate = 9600;
//
// Now try again, this time with feeling...
//
BlInitializeHeadlessPort();
} #endif
}
Status = BlOsLoader( Argc, Argv, NULL );
BootFailed:
if (Status != ESUCCESS) {
//
// Boot failed, wait for reboot
//
while (TRUE) { while (!BlGetKey()); // BOOT FAILED!
if (BlTerminalHandleLoaderFailure()) { ArcRestart(); } } } } while (TRUE);
}
BlPreProcessLoadOptions( PCHAR szOsLoadOptions ) { CHAR szTemp[MAXBOOTVARSIZE]; PCHAR p; ULONG MaxMemory = 0; ULONG ConfigFlagValue=0;
strcpy( szTemp, szOsLoadOptions ); _strupr( szTemp );
#if 0
if( p = strstr( szTemp, ";" ) ) { *p = '\0'; } #endif
//
// Process MAXMEM
//
if( p = strstr( szTemp, "/MAXMEM=" ) ) { MaxMemory = atoi( p + sizeof("/MAXMEM=") - 1 ); BlpTruncateMemory( MaxMemory ); }
#if defined(_MERCED_A0_)
//
// Process CONFIGFLAG
//
if ( p = strstr(szTemp, "CONFIGFLAG") ) { if ( p = strstr(p, "=") ) { ConfigFlagValue = atol(p+1); KiProcessorWorkAround(ConfigFlagValue); } } #endif
}
BOOLEAN WillMemoryBeUsableByOs( IN MEMORY_TYPE Type ) { BOOLEAN RetVal = FALSE; switch (Type) { case MemoryFree: case MemoryFreeContiguous: case MemoryFirmwareTemporary: case MemorySpecialMemory: RetVal = TRUE; }
return(RetVal); }
VOID BlpTruncateMemory ( IN ULONG MaxMemory )
/*++
Routine Description:
Eliminates all the memory descriptors above a given boundary
Arguments:
MaxMemory - Supplies the maximum memory boundary in megabytes
Return Value:
None.
--*/
{ ULONG MaxPage = (MaxMemory * _1MB ); PLIST_ENTRY Current; PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor;
if (MaxMemory == 0) { return; }
Current = BlLoaderBlock->MemoryDescriptorListHead.Flink;
while (Current != &BlLoaderBlock->MemoryDescriptorListHead) { MemoryDescriptor = CONTAINING_RECORD(Current, MEMORY_ALLOCATION_DESCRIPTOR, ListEntry);
Current = Current->Flink;
if (WillMemoryBeUsableByOs(MemoryDescriptor->MemoryType)) { if (MemoryDescriptor->BasePage >= MaxPage) { //
// This memory descriptor lies entirely above the boundary,
// mark it as firmware permanent. this is easier than
// unlinking the entry and has the same effect since no one
// can use this memory.
//
MemoryDescriptor->MemoryType = MemoryFirmwarePermanent; } else if (MemoryDescriptor->BasePage + MemoryDescriptor->PageCount > MaxPage) { //
// This memory descriptor crosses the boundary, truncate it.
//
MemoryDescriptor->PageCount = MaxPage - MemoryDescriptor->BasePage; } else { //
// This one's ok, keep it.
//
} } else { //
// skip it
//
} }
}
|