840 lines
20 KiB
C
840 lines
20 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1992 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
entry.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
x86-specific startup for setupldr
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
John Vert (jvert) 14-Oct-1993
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
#include "bootx86.h"
|
|||
|
#include "stdio.h"
|
|||
|
#include "flop.h"
|
|||
|
#include <ramdisk.h>
|
|||
|
|
|||
|
#if 0
|
|||
|
#define DBGOUT(x) BlPrint x
|
|||
|
#define DBGPAUSE while(!GET_KEY());
|
|||
|
#else
|
|||
|
#define DBGOUT(x)
|
|||
|
#define DBGPAUSE
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Prototypes for Internal Routines
|
|||
|
//
|
|||
|
|
|||
|
VOID
|
|||
|
DoGlobalInitialization(
|
|||
|
PBOOT_CONTEXT
|
|||
|
);
|
|||
|
|
|||
|
#if defined(ELTORITO)
|
|||
|
BOOLEAN ElToritoCDBoot = FALSE;
|
|||
|
#endif
|
|||
|
|
|||
|
extern CHAR NetBootPath[];
|
|||
|
|
|||
|
//
|
|||
|
// Global context pointers. These are passed to us by the SU module or
|
|||
|
// the bootstrap code.
|
|||
|
//
|
|||
|
|
|||
|
PCONFIGURATION_COMPONENT_DATA FwConfigurationTree = NULL;
|
|||
|
PEXTERNAL_SERVICES_TABLE ExternalServicesTable;
|
|||
|
UCHAR BootPartitionName[80];
|
|||
|
ULONG MachineType = 0;
|
|||
|
ULONG OsLoaderBase;
|
|||
|
ULONG OsLoaderExports;
|
|||
|
extern PUCHAR BlpResourceDirectory;
|
|||
|
extern PUCHAR BlpResourceFileOffset;
|
|||
|
ULONG PcrBasePage;
|
|||
|
ULONG TssBasePage;
|
|||
|
|
|||
|
ULONG BootFlags = 0;
|
|||
|
|
|||
|
ULONG NtDetectStart = 0;
|
|||
|
ULONG NtDetectEnd = 0;
|
|||
|
|
|||
|
#ifdef FORCE_CD_BOOT
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
BlGetCdRomDrive(
|
|||
|
PUCHAR DriveId
|
|||
|
)
|
|||
|
{
|
|||
|
BOOLEAN Result = FALSE;
|
|||
|
UCHAR Id = 0;
|
|||
|
|
|||
|
do {
|
|||
|
if (BlIsElToritoCDBoot(Id)) {
|
|||
|
*DriveId = Id;
|
|||
|
Result = TRUE;
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
Id++;
|
|||
|
}
|
|||
|
while (Id != 0);
|
|||
|
|
|||
|
return Result;
|
|||
|
}
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
VOID
|
|||
|
NtProcessStartup(
|
|||
|
IN PBOOT_CONTEXT BootContextRecord
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Main entry point for setup loader. Control is transferred here by the
|
|||
|
start-up (SU) module.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
BootContextRecord - Supplies the boot context, particularly the
|
|||
|
ExternalServicesTable.
|
|||
|
|
|||
|
Returns:
|
|||
|
|
|||
|
Does not return. Control eventually passed to the kernel.
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ARC_STATUS Status;
|
|||
|
|
|||
|
#ifdef FORCE_CD_BOOT
|
|||
|
BOOLEAN CdFound;
|
|||
|
UCHAR CdId;
|
|||
|
#endif
|
|||
|
|
|||
|
ULONG_PTR pFirmwareHeapAddress;
|
|||
|
ULONG TssSize,TssPages;
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the boot loader's video
|
|||
|
//
|
|||
|
|
|||
|
DoGlobalInitialization(BootContextRecord);
|
|||
|
|
|||
|
BlFillInSystemParameters(BootContextRecord);
|
|||
|
|
|||
|
//
|
|||
|
// Set the global bootflags
|
|||
|
//
|
|||
|
BootFlags = BootContextRecord->BootFlags;
|
|||
|
|
|||
|
#ifdef FORCE_CD_BOOT
|
|||
|
CdFound = BlGetCdRomDrive(&CdId);
|
|||
|
|
|||
|
if (CdFound) {
|
|||
|
BlPrint("CD/DVD-Rom drive found with id:%u\n", CdId);
|
|||
|
BootContextRecord->FSContextPointer->BootDrive = CdId;
|
|||
|
} else {
|
|||
|
BlPrint("CD/DVD-Rom drive not found");
|
|||
|
}
|
|||
|
#endif // for FORCE_CD_BOOT
|
|||
|
|
|||
|
if (BootContextRecord->FSContextPointer->BootDrive == 0) {
|
|||
|
|
|||
|
//
|
|||
|
// Boot was from A:
|
|||
|
//
|
|||
|
|
|||
|
strcpy(BootPartitionName,"multi(0)disk(0)fdisk(0)");
|
|||
|
|
|||
|
//
|
|||
|
// To get around an apparent bug on the BIOS of some MCA machines
|
|||
|
// (specifically the NCR 386sx/MC20 w/ BIOS version 1.04.00 (3421),
|
|||
|
// Phoenix BIOS 1.02.07), whereby the first int13 to floppy results
|
|||
|
// in a garbage buffer, reset drive 0 here.
|
|||
|
//
|
|||
|
|
|||
|
GET_SECTOR(0,0,0,0,0,0,NULL);
|
|||
|
|
|||
|
} else if (BootContextRecord->FSContextPointer->BootDrive == 0x40) {
|
|||
|
|
|||
|
//
|
|||
|
// Boot was from the net
|
|||
|
//
|
|||
|
|
|||
|
strcpy(BootPartitionName,"net(0)");
|
|||
|
BlBootingFromNet = TRUE;
|
|||
|
|
|||
|
#if defined(REMOTE_BOOT)
|
|||
|
BlGetActivePartition(NetBootActivePartitionName);
|
|||
|
NetFindCSCPartitionName();
|
|||
|
#endif
|
|||
|
|
|||
|
} else if (BootContextRecord->FSContextPointer->BootDrive == 0x41) {
|
|||
|
|
|||
|
//
|
|||
|
// Boot was from an SDI image
|
|||
|
//
|
|||
|
|
|||
|
strcpy(BootPartitionName,"ramdisk(0)");
|
|||
|
|
|||
|
} else if (BlIsElToritoCDBoot(BootContextRecord->FSContextPointer->BootDrive)) {
|
|||
|
|
|||
|
//
|
|||
|
// Boot was from El Torito CD
|
|||
|
//
|
|||
|
|
|||
|
sprintf(BootPartitionName, "multi(0)disk(0)cdrom(%u)", BootContextRecord->FSContextPointer->BootDrive);
|
|||
|
ElToritoCDBoot = TRUE;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// Find the partition we have been booted from. Note that this
|
|||
|
// is *NOT* necessarily the active partition. If the system has
|
|||
|
// Boot Mangler installed, it will be the active partition, and
|
|||
|
// we have to go figure out what partition we are actually on.
|
|||
|
//
|
|||
|
BlGetActivePartition(BootPartitionName);
|
|||
|
|
|||
|
#if defined(REMOTE_BOOT)
|
|||
|
strcpy(NetBootActivePartitionName, BootPartitionName);
|
|||
|
NetFindCSCPartitionName();
|
|||
|
#endif
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// We need to make sure that we've got a signature on disk 80.
|
|||
|
// If not, then write one.
|
|||
|
//
|
|||
|
{
|
|||
|
ULONG DriveId;
|
|||
|
ULONG NewSignature;
|
|||
|
UCHAR SectorBuffer[4096+256];
|
|||
|
PUCHAR Sector;
|
|||
|
LARGE_INTEGER SeekValue;
|
|||
|
ULONG Count;
|
|||
|
|
|||
|
|
|||
|
Status = ArcOpen("multi(0)disk(0)rdisk(0)partition(0)", ArcOpenReadWrite, &DriveId);
|
|||
|
|
|||
|
if (Status == ESUCCESS) {
|
|||
|
|
|||
|
//
|
|||
|
// Get a reasonably unique seed to start with.
|
|||
|
//
|
|||
|
NewSignature = ArcGetRelativeTime();
|
|||
|
NewSignature = (NewSignature & 0xFFFF) << 16;
|
|||
|
NewSignature += ArcGetRelativeTime();
|
|||
|
|
|||
|
//
|
|||
|
// Now we have a valid new signature to put on the disk.
|
|||
|
// Read the sector off disk, put the new signature in,
|
|||
|
// write the sector back, and recompute the checksum.
|
|||
|
//
|
|||
|
Sector = ALIGN_BUFFER(SectorBuffer);
|
|||
|
SeekValue.QuadPart = 0;
|
|||
|
Status = ArcSeek(DriveId, &SeekValue, SeekAbsolute);
|
|||
|
if (Status == ESUCCESS) {
|
|||
|
Status = ArcRead(DriveId,Sector,512,&Count);
|
|||
|
|
|||
|
if( Status == ESUCCESS ) {
|
|||
|
if( ((PULONG)Sector)[PARTITION_TABLE_OFFSET/2-1] == 0 ) {
|
|||
|
//
|
|||
|
// He's 0. Write a real signature in there.
|
|||
|
//
|
|||
|
|
|||
|
((PULONG)Sector)[PARTITION_TABLE_OFFSET/2-1] = NewSignature;
|
|||
|
|
|||
|
Status = ArcSeek(DriveId, &SeekValue, SeekAbsolute);
|
|||
|
if (Status == ESUCCESS) {
|
|||
|
Status = ArcWrite(DriveId,Sector,512,&Count);
|
|||
|
if( Status != ESUCCESS ) {
|
|||
|
#if DBG
|
|||
|
BlPrint( "Falied to write the new signature on the boot partition.\n" );
|
|||
|
#endif
|
|||
|
}
|
|||
|
} else {
|
|||
|
#if DBG
|
|||
|
BlPrint( "Failed second ArcSeek on the boot partition to check for a signature.\n" );
|
|||
|
#endif
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
#if DBG
|
|||
|
BlPrint( "Failed to ArcRead the boot partition to check for a signature.\n" );
|
|||
|
#endif
|
|||
|
}
|
|||
|
} else {
|
|||
|
#if DBG
|
|||
|
BlPrint( "Failed to ArcSeek the boot partition to check for a signature.\n" );
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
ArcClose(DriveId);
|
|||
|
} else {
|
|||
|
#if DBG
|
|||
|
BlPrint( "Couldn't Open the boot partition to check for a signature.\n" );
|
|||
|
#endif
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// squirrel away some memory for the PCR and TSS so that we get the
|
|||
|
// preferred memory location (<16MB) for this data.
|
|||
|
//
|
|||
|
pFirmwareHeapAddress = (ULONG_PTR)FwAllocateHeapPermanent( 2 );
|
|||
|
if (!pFirmwareHeapAddress) {
|
|||
|
BlPrint("Couldn't allocate memory for PCR\n");
|
|||
|
goto BootFailed;
|
|||
|
}
|
|||
|
PcrBasePage = (ULONG)(pFirmwareHeapAddress>>PAGE_SHIFT);
|
|||
|
|
|||
|
TssSize = (sizeof(KTSS) + PAGE_SIZE) & ~(PAGE_SIZE - 1);
|
|||
|
TssPages = TssSize / PAGE_SIZE;
|
|||
|
pFirmwareHeapAddress = (ULONG_PTR)FwAllocateHeapPermanent( TssPages );
|
|||
|
if (!pFirmwareHeapAddress) {
|
|||
|
BlPrint("Couldn't allocate memory for TSS\n");
|
|||
|
goto BootFailed;
|
|||
|
}
|
|||
|
TssBasePage = (ULONG)(pFirmwareHeapAddress>>PAGE_SHIFT);
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the memory descriptor list, the OS loader heap, and the
|
|||
|
// OS loader parameter block.
|
|||
|
//
|
|||
|
Status = BlMemoryInitialize();
|
|||
|
if (Status != ESUCCESS) {
|
|||
|
BlPrint("Couldn't initialize memory\n");
|
|||
|
goto BootFailed;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the OS loader I/O system.
|
|||
|
//
|
|||
|
|
|||
|
AEInitializeStall();
|
|||
|
|
|||
|
Status = BlIoInitialize();
|
|||
|
if (Status != ESUCCESS) {
|
|||
|
BlPrint("Couldn't initialize I/O\n");
|
|||
|
goto BootFailed;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Call off to regular startup code
|
|||
|
//
|
|||
|
BlStartup(BootPartitionName);
|
|||
|
|
|||
|
//
|
|||
|
// we should never get here!
|
|||
|
//
|
|||
|
BootFailed:
|
|||
|
if (BootFlags & BOOTFLAG_REBOOT_ON_FAILURE) {
|
|||
|
ULONG StartTime = ArcGetRelativeTime();
|
|||
|
BlPrint(TEXT("\nRebooting in 5 seconds...\n"));
|
|||
|
while ( ArcGetRelativeTime() - StartTime < 5) {}
|
|||
|
ArcRestart();
|
|||
|
}
|
|||
|
|
|||
|
do {
|
|||
|
GET_KEY(); // BOOT FAILED!
|
|||
|
if (BlTerminalHandleLoaderFailure()) {
|
|||
|
ArcRestart();
|
|||
|
}
|
|||
|
} while ( 1 );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
BlDetectHardware(
|
|||
|
IN ULONG DriveId,
|
|||
|
IN PCHAR LoadOptions
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Loads and runs NTDETECT.COM to populate the ARC configuration tree.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
DriveId - Supplies drive id where NTDETECT is located.
|
|||
|
|
|||
|
LoadOptions - Supplies Load Options string to ntdetect.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE - NTDETECT successfully run.
|
|||
|
|
|||
|
FALSE - Error
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
// Current Loader stack size is 8K, so make sure you do not
|
|||
|
// blow that space. Make sure this is not smaller than 140.
|
|||
|
#define LOAD_OPTIONS_BUFFER_SIZE 512
|
|||
|
|
|||
|
ARC_STATUS Status;
|
|||
|
PCONFIGURATION_COMPONENT_DATA TempFwTree;
|
|||
|
ULONG TempFwHeapUsed;
|
|||
|
ULONG FileSize;
|
|||
|
ULONG DetectFileId;
|
|||
|
FILE_INFORMATION FileInformation;
|
|||
|
PUCHAR DetectionBuffer = (PUCHAR)DETECTION_LOADED_ADDRESS;
|
|||
|
PUCHAR Options = NULL;
|
|||
|
UCHAR Buffer[LOAD_OPTIONS_BUFFER_SIZE];
|
|||
|
LARGE_INTEGER SeekPosition;
|
|||
|
ULONG Read;
|
|||
|
BOOLEAN SkipLegacyDetection;
|
|||
|
BOOLEAN Success = FALSE;
|
|||
|
ULONG HeapStart;
|
|||
|
ULONG HeapSize;
|
|||
|
ULONG RequiredLength = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Check if the ntdetect.com was bundled as a data section
|
|||
|
// in the loader executable.
|
|||
|
//
|
|||
|
if (NtDetectStart == 0) {
|
|||
|
|
|||
|
//
|
|||
|
// Now check if we have ntdetect.com in the root directory, if yes,
|
|||
|
// we will load it to predefined location and transfer control to
|
|||
|
// it.
|
|||
|
//
|
|||
|
|
|||
|
#if defined(ELTORITO)
|
|||
|
if (ElToritoCDBoot) {
|
|||
|
// we assume ntdetect.com is in the i386 directory
|
|||
|
Status = BlOpen( DriveId,
|
|||
|
"\\i386\\ntdetect.com",
|
|||
|
ArcOpenReadOnly,
|
|||
|
&DetectFileId );
|
|||
|
} else {
|
|||
|
#endif
|
|||
|
|
|||
|
if (BlBootingFromNet
|
|||
|
#if defined(REMOTE_BOOT)
|
|||
|
&& NetworkBootRom
|
|||
|
#endif // defined(REMOTE_BOOT)
|
|||
|
) {
|
|||
|
|
|||
|
strcpy(Buffer, NetBootPath);
|
|||
|
|
|||
|
#if defined(REMOTE_BOOT)
|
|||
|
//
|
|||
|
// This is the way it was done for remote BOOT, where we were
|
|||
|
// booting out of a client's machine directory.
|
|||
|
//
|
|||
|
strcat(Buffer, "BootDrive\\ntdetect.com");
|
|||
|
#else
|
|||
|
//
|
|||
|
// This is how it is done for remote INSTALL, where we are
|
|||
|
// booting out of the templates directory under a setup directory.
|
|||
|
//
|
|||
|
strcat(Buffer, "ntdetect.com");
|
|||
|
#endif // defined(REMOTE_BOOT)
|
|||
|
|
|||
|
Status = BlOpen( DriveId,
|
|||
|
Buffer,
|
|||
|
ArcOpenReadOnly,
|
|||
|
&DetectFileId );
|
|||
|
} else {
|
|||
|
Status = BlOpen( DriveId,
|
|||
|
"\\ntdetect.com",
|
|||
|
ArcOpenReadOnly,
|
|||
|
&DetectFileId );
|
|||
|
}
|
|||
|
#if defined(ELTORITO)
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
if (Status != ESUCCESS) {
|
|||
|
#if DBG
|
|||
|
BlPrint("Error opening NTDETECT.COM, status = %x\n", Status);
|
|||
|
BlPrint("Press any key to continue\n");
|
|||
|
#endif
|
|||
|
goto Exit;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Determine the length of the ntdetect.com file
|
|||
|
//
|
|||
|
|
|||
|
Status = BlGetFileInformation(DetectFileId, &FileInformation);
|
|||
|
if (Status != ESUCCESS) {
|
|||
|
BlClose(DetectFileId);
|
|||
|
#if DBG
|
|||
|
BlPrint("Error getting NTDETECT.COM file information, status = %x\n", Status);
|
|||
|
BlPrint("Press any key to continue\n");
|
|||
|
#endif
|
|||
|
goto Exit;
|
|||
|
}
|
|||
|
|
|||
|
FileSize = FileInformation.EndingAddress.LowPart;
|
|||
|
if (FileSize == 0) {
|
|||
|
BlClose(DetectFileId);
|
|||
|
#if DBG
|
|||
|
BlPrint("Error: size of NTDETECT.COM is zero.\n");
|
|||
|
BlPrint("Press any key to continue\n");
|
|||
|
#endif
|
|||
|
goto Exit;
|
|||
|
}
|
|||
|
|
|||
|
SeekPosition.QuadPart = 0;
|
|||
|
Status = BlSeek(DetectFileId,
|
|||
|
&SeekPosition,
|
|||
|
SeekAbsolute);
|
|||
|
if (Status != ESUCCESS) {
|
|||
|
BlClose(DetectFileId);
|
|||
|
#if DBG
|
|||
|
BlPrint("Error seeking to start of NTDETECT.COM file\n");
|
|||
|
BlPrint("Press any key to continue\n");
|
|||
|
#endif
|
|||
|
goto Exit;
|
|||
|
}
|
|||
|
|
|||
|
Status = BlRead( DetectFileId,
|
|||
|
DetectionBuffer,
|
|||
|
FileSize,
|
|||
|
&Read );
|
|||
|
|
|||
|
BlClose(DetectFileId);
|
|||
|
if (Status != ESUCCESS) {
|
|||
|
#if DBG
|
|||
|
BlPrint("Error reading from NTDETECT.COM\n");
|
|||
|
BlPrint("Read %lx bytes\n",Read);
|
|||
|
BlPrint("Press any key to continue\n");
|
|||
|
#endif
|
|||
|
goto Exit;
|
|||
|
}
|
|||
|
} else {
|
|||
|
|
|||
|
// ntdetect.com was bundled in the loader image
|
|||
|
// as a data section. We will use it contents
|
|||
|
// instead of opening the file.
|
|||
|
RtlCopyMemory( DetectionBuffer, (PVOID)NtDetectStart, NtDetectEnd - NtDetectStart );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Set the heap start and size used by ntdetect
|
|||
|
//
|
|||
|
HeapStart = (TEMPORARY_HEAP_START - 0x10) * PAGE_SIZE;
|
|||
|
HeapSize = 0x10000; // 64K
|
|||
|
|
|||
|
//
|
|||
|
// We need to pass NTDETECT pointers < 1Mb, so
|
|||
|
// use local storage off the stack if possible. (which is
|
|||
|
// always < 1Mb.) If not possible (boot.ini is too big)
|
|||
|
// and we will add it to the heap used by ntdetect.com, thereby
|
|||
|
// reducing the heap space used by ntdetect.com
|
|||
|
//
|
|||
|
if ( LoadOptions ) {
|
|||
|
// count the characters in LoadOptions + null terminator +
|
|||
|
// room for " NOLEGACY" that might be appended later
|
|||
|
RequiredLength = strlen(LoadOptions) + strlen(" NOLEGACY") + 1;
|
|||
|
|
|||
|
// check if the buffer on the stack is big enough
|
|||
|
if ( RequiredLength > LOAD_OPTIONS_BUFFER_SIZE ) {
|
|||
|
//
|
|||
|
// Buffer is too small. let move it to the
|
|||
|
// end of the ntdetect heap
|
|||
|
//
|
|||
|
Options = (PCHAR)( HeapStart + HeapSize - RequiredLength );
|
|||
|
HeapSize -= RequiredLength;
|
|||
|
|
|||
|
strcpy( Options, LoadOptions );
|
|||
|
|
|||
|
} else {
|
|||
|
//
|
|||
|
// Load options will fit on the stack. copy them there
|
|||
|
//
|
|||
|
strcpy( Buffer, LoadOptions );
|
|||
|
Options = Buffer;
|
|||
|
|
|||
|
}
|
|||
|
} else {
|
|||
|
//
|
|||
|
// No load options
|
|||
|
//
|
|||
|
Options = NULL;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Check whether we need to add the NOLEGACY option
|
|||
|
//
|
|||
|
if (BlDetectLegacyFreeBios()) {
|
|||
|
if (Options != NULL) {
|
|||
|
strcat(Options, " NOLEGACY");
|
|||
|
} else {
|
|||
|
strcpy(Buffer, " NOLEGACY");
|
|||
|
Options = Buffer;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
DETECT_HARDWARE((ULONG)HeapStart,
|
|||
|
(ULONG)HeapSize,
|
|||
|
(PVOID)&TempFwTree,
|
|||
|
(PULONG)&TempFwHeapUsed,
|
|||
|
(PCHAR)Options,
|
|||
|
(Options != NULL) ? strlen(Options) : 0
|
|||
|
);
|
|||
|
|
|||
|
FwConfigurationTree = TempFwTree;
|
|||
|
|
|||
|
Status = BlpMarkExtendedVideoRegionOffLimits();
|
|||
|
|
|||
|
Success = (BOOLEAN)(Status == ESUCCESS);
|
|||
|
|
|||
|
Exit:
|
|||
|
|
|||
|
//
|
|||
|
// Reinitialize the headless port - detect wipes it out.
|
|||
|
//
|
|||
|
BlInitializeHeadlessPort();
|
|||
|
|
|||
|
return(Success);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
DoGlobalInitialization(
|
|||
|
IN PBOOT_CONTEXT BootContextRecord
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description
|
|||
|
|
|||
|
This routine calls all of the subsytem initialization routines.
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
Returns:
|
|||
|
|
|||
|
Nothing
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
ARC_STATUS Status;
|
|||
|
|
|||
|
//
|
|||
|
// Set base address of OS Loader image for the debugger.
|
|||
|
//
|
|||
|
|
|||
|
OsLoaderBase = BootContextRecord->OsLoaderBase;
|
|||
|
OsLoaderExports = BootContextRecord->OsLoaderExports;
|
|||
|
|
|||
|
//
|
|||
|
// Initialize memory.
|
|||
|
//
|
|||
|
|
|||
|
Status = InitializeMemorySubsystem(BootContextRecord);
|
|||
|
if (Status != ESUCCESS) {
|
|||
|
BlPrint("InitializeMemory failed %lx\n",Status);
|
|||
|
while (1) {
|
|||
|
}
|
|||
|
}
|
|||
|
ExternalServicesTable=BootContextRecord->ExternalServicesTable;
|
|||
|
MachineType = BootContextRecord->MachineType;
|
|||
|
|
|||
|
//
|
|||
|
// Turn the cursor off
|
|||
|
//
|
|||
|
|
|||
|
HW_CURSOR(0,127);
|
|||
|
|
|||
|
BlpResourceDirectory = (PUCHAR)(BootContextRecord->ResourceDirectory);
|
|||
|
BlpResourceFileOffset = (PUCHAR)(BootContextRecord->ResourceOffset);
|
|||
|
|
|||
|
NtDetectStart = BootContextRecord->NtDetectStart;
|
|||
|
NtDetectEnd = BootContextRecord->NtDetectEnd;
|
|||
|
|
|||
|
//
|
|||
|
// If this is an SDI boot, copy the address of the SDI image out of the
|
|||
|
// boot context record. SdiAddress is declared in boot\inc\ramdisk.h and
|
|||
|
// initialized to 0 in boot\lib\ramdisk.c.
|
|||
|
//
|
|||
|
|
|||
|
if (BootContextRecord->FSContextPointer->BootDrive == 0x41) {
|
|||
|
SdiAddress = BootContextRecord->SdiAddress;
|
|||
|
}
|
|||
|
|
|||
|
InitializeMemoryDescriptors ();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
BlGetActivePartition(
|
|||
|
OUT PUCHAR BootPartitionName
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Determine the ARC name for the partition NTLDR was started from
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
BootPartitionName - Supplies a buffer where the ARC name of the
|
|||
|
partition will be returned.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Name of the partition is in BootPartitionName.
|
|||
|
|
|||
|
Must always succeed.
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
UCHAR SectorBuffer[512];
|
|||
|
ARC_STATUS Status;
|
|||
|
ULONG FileId;
|
|||
|
ULONG Count;
|
|||
|
int i;
|
|||
|
|
|||
|
//
|
|||
|
// The boot sector used to boot us is still in memory at 0x7c00.
|
|||
|
// The hidden sectors field in the BPB is pretty much guaranteed
|
|||
|
// to be intact, since all boot codes use that field and thus
|
|||
|
// are unlikely to have overwritten it.
|
|||
|
// We open each partition and compare the in-memory hidden sector count
|
|||
|
// at 0x7c1c to the hidden sector value in the BPB.
|
|||
|
//
|
|||
|
i = 1;
|
|||
|
do {
|
|||
|
|
|||
|
sprintf(BootPartitionName,"multi(0)disk(0)rdisk(0)partition(%u)",i);
|
|||
|
|
|||
|
Status = ArcOpen(BootPartitionName,ArcOpenReadOnly,&FileId);
|
|||
|
if(Status == ESUCCESS) {
|
|||
|
|
|||
|
//
|
|||
|
// Read the first part of the partition.
|
|||
|
//
|
|||
|
Status = ArcRead(FileId,SectorBuffer,512,&Count);
|
|||
|
ArcClose(FileId);
|
|||
|
if((Status == ESUCCESS) && !memcmp(SectorBuffer+0x1c,(PVOID)0x7c1c,4)) {
|
|||
|
//
|
|||
|
// Found it, BootPartitionName is already set for return.
|
|||
|
//
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
Status = ESUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
i++;
|
|||
|
|
|||
|
} while (Status == ESUCCESS);
|
|||
|
|
|||
|
//
|
|||
|
// Run out of partitions without finding match. Fall back on partition 1.
|
|||
|
//
|
|||
|
strcpy(BootPartitionName,"multi(0)disk(0)rdisk(0)partition(1)");
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
BlIsElToritoCDBoot(
|
|||
|
UCHAR DriveNum
|
|||
|
)
|
|||
|
{
|
|||
|
|
|||
|
//
|
|||
|
// Note, even though args are short, they are pushed on the stack with
|
|||
|
// 32bit alignment so the effect on the stack seen by the 16bit real
|
|||
|
// mode code is the same as if we were pushing longs here.
|
|||
|
//
|
|||
|
// GET_ELTORITO_STATUS is 0 if we are in emulation mode
|
|||
|
|
|||
|
if (DriveNum > 0x81) {
|
|||
|
if (!GET_ELTORITO_STATUS(FwDiskCache,DriveNum)) {
|
|||
|
return(TRUE);
|
|||
|
} else {
|
|||
|
return(FALSE);
|
|||
|
}
|
|||
|
} else {
|
|||
|
return(FALSE);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#if defined(REMOTE_BOOT)
|
|||
|
BOOLEAN
|
|||
|
NetFindCSCPartitionName(
|
|||
|
)
|
|||
|
{
|
|||
|
UCHAR FileName[80];
|
|||
|
UCHAR DiskName[80];
|
|||
|
UCHAR PartitionName[80];
|
|||
|
PUCHAR p;
|
|||
|
ULONG Part;
|
|||
|
ULONG FileId;
|
|||
|
ULONG DeviceId;
|
|||
|
|
|||
|
if (NetBootSearchedForCSC) {
|
|||
|
return((BOOLEAN)strlen(NetBootCSCPartitionName));
|
|||
|
}
|
|||
|
|
|||
|
if (!strlen(NetBootActivePartitionName)) {
|
|||
|
BlGetActivePartition(NetBootActivePartitionName);
|
|||
|
}
|
|||
|
|
|||
|
strcpy(DiskName, NetBootActivePartitionName);
|
|||
|
p = strstr(DiskName, "partition");
|
|||
|
ASSERT( p != NULL );
|
|||
|
*p = '\0';
|
|||
|
|
|||
|
Part = 1;
|
|||
|
while (TRUE) {
|
|||
|
|
|||
|
sprintf(PartitionName, "%spartition(%u)", DiskName, Part);
|
|||
|
if (ArcOpen(PartitionName, ArcOpenReadOnly, &DeviceId) != ESUCCESS) {
|
|||
|
break;
|
|||
|
}
|
|||
|
ArcClose(DeviceId);
|
|||
|
|
|||
|
sprintf(FileName,
|
|||
|
"%s%s",
|
|||
|
PartitionName,
|
|||
|
REMOTE_BOOT_IMIRROR_PATH_A REMOTE_BOOT_CSC_SUBDIR_A);
|
|||
|
|
|||
|
if (ArcOpen(FileName, ArcOpenReadOnly, &FileId) == ESUCCESS) {
|
|||
|
ArcClose(FileId);
|
|||
|
NetBootSearchedForCSC = TRUE;
|
|||
|
strcpy(NetBootCSCPartitionName, PartitionName);
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
ArcClose(FileId);
|
|||
|
Part++;
|
|||
|
}
|
|||
|
|
|||
|
strcpy(NetBootCSCPartitionName, NetBootActivePartitionName);
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
#endif // defined(REMOTE_BOOT)
|
|||
|
|