mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
482 lines
11 KiB
482 lines
11 KiB
/*++
|
|
|
|
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"
|
|
|
|
//
|
|
// Prototypes for Internal Routines
|
|
//
|
|
|
|
VOID
|
|
DoGlobalInitialization(
|
|
PBOOT_CONTEXT
|
|
);
|
|
|
|
#if defined(ELTORITO)
|
|
BOOLEAN ElToritoCDBoot = FALSE;
|
|
#endif
|
|
|
|
//
|
|
// 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 FwHeapUsed = 0;
|
|
ULONG MachineType = 0;
|
|
ULONG OsLoaderBase;
|
|
ULONG OsLoaderExports;
|
|
extern PUCHAR BlpResourceDirectory;
|
|
extern PUCHAR BlpResourceFileOffset;
|
|
|
|
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;
|
|
|
|
//
|
|
// Initialize the boot loader's video
|
|
//
|
|
|
|
DoGlobalInitialization(BootContextRecord);
|
|
|
|
BlFillInSystemParameters(BootContextRecord);
|
|
|
|
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);
|
|
|
|
#if defined(ELTORITO)
|
|
} 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;
|
|
#endif
|
|
|
|
} 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);
|
|
|
|
}
|
|
|
|
//
|
|
// 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");
|
|
while (1) {
|
|
}
|
|
}
|
|
|
|
//
|
|
// Initialize the OS loader I/O system.
|
|
//
|
|
|
|
Status = BlIoInitialize();
|
|
if (Status != ESUCCESS) {
|
|
BlPrint("Couldn't initialize I/O\n");
|
|
}
|
|
|
|
//
|
|
// Call off to regular startup code
|
|
//
|
|
BlStartup(BootPartitionName);
|
|
|
|
//
|
|
// we should never get here!
|
|
//
|
|
do {
|
|
GET_KEY();
|
|
} while ( 1 );
|
|
|
|
}
|
|
|
|
BOOLEAN
|
|
BlDetectHardware(
|
|
IN ULONG DriveId,
|
|
IN PCHAR LoadOptions
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Loads and runs NTDETECT.COM to populate the ARC configuration tree.
|
|
NTDETECT is assumed to reside in the root directory.
|
|
|
|
Arguments:
|
|
|
|
DriveId - Supplies drive id where NTDETECT is located.
|
|
|
|
LoadOptions - Supplies Load Options string to ntdetect.
|
|
|
|
Return Value:
|
|
|
|
TRUE - NTDETECT successfully run.
|
|
|
|
FALSE - Error
|
|
|
|
--*/
|
|
|
|
{
|
|
ARC_STATUS Status;
|
|
PCONFIGURATION_COMPONENT_DATA TempFwTree;
|
|
ULONG TempFwHeapUsed;
|
|
extern BOOLEAN FwDescriptorsValid;
|
|
ULONG FileSize;
|
|
ULONG DetectFileId;
|
|
FILE_INFORMATION FileInformation;
|
|
PUCHAR DetectionBuffer;
|
|
PUCHAR Options;
|
|
UCHAR Buffer[100];
|
|
LARGE_INTEGER SeekPosition;
|
|
ULONG Read;
|
|
|
|
//
|
|
// 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
|
|
Status = BlOpen( DriveId,
|
|
"\\ntdetect.com",
|
|
ArcOpenReadOnly,
|
|
&DetectFileId );
|
|
#if defined(ELTORITO)
|
|
}
|
|
#endif
|
|
|
|
DetectionBuffer = (PUCHAR)DETECTION_LOADED_ADDRESS;
|
|
|
|
if (Status != ESUCCESS) {
|
|
#if DBG
|
|
BlPrint("Error opening NTDETECT.COM, status = %x\n", Status);
|
|
BlPrint("Press any key to continue\n");
|
|
while (!GET_KEY()) {
|
|
}
|
|
#endif
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// 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");
|
|
while (!GET_KEY()) {
|
|
}
|
|
#endif
|
|
return(FALSE);
|
|
}
|
|
|
|
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");
|
|
while (!GET_KEY()) {
|
|
}
|
|
#endif
|
|
return(FALSE);
|
|
}
|
|
|
|
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");
|
|
while (!GET_KEY()) {
|
|
}
|
|
#endif
|
|
return(FALSE);
|
|
}
|
|
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");
|
|
while (!GET_KEY()) {
|
|
}
|
|
#endif
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// We need to pass NTDETECT pointers < 1Mb, so
|
|
// use local storage off the stack. (which is
|
|
// always < 1Mb.
|
|
//
|
|
|
|
if (LoadOptions) {
|
|
strcpy(Buffer, LoadOptions);
|
|
Options = Buffer;
|
|
} else {
|
|
Options = NULL;
|
|
}
|
|
DETECT_HARDWARE((ULONG)(TEMPORARY_HEAP_START - 0x10) * PAGE_SIZE,
|
|
(ULONG)0x10000, // Heap Size
|
|
(PVOID)&TempFwTree,
|
|
(PULONG)&TempFwHeapUsed,
|
|
(PCHAR)Options,
|
|
(ULONG)(LoadOptions ? strlen(LoadOptions) : 0)
|
|
);
|
|
FwConfigurationTree = TempFwTree;
|
|
FwHeapUsed = TempFwHeapUsed;
|
|
FwDescriptorsValid = FALSE;
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
VOID
|
|
DoGlobalInitialization(
|
|
IN PBOOT_CONTEXT BootContextRecord
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
This routine calls all of the subsytem initialization routines.
|
|
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
Nothing
|
|
|
|
--*/
|
|
|
|
{
|
|
ARC_STATUS Status;
|
|
|
|
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);
|
|
|
|
OsLoaderBase = BootContextRecord->OsLoaderBase;
|
|
OsLoaderExports = BootContextRecord->OsLoaderExports;
|
|
|
|
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];
|
|
UCHAR NameBuffer[80];
|
|
ARC_STATUS Status;
|
|
ULONG FileId;
|
|
ULONG Count;
|
|
int i;
|
|
|
|
//
|
|
// The method we use is to open each partition on the first drive
|
|
// and read in its boot sector. Then we compare that to the boot
|
|
// sector that we used to boot from (at physical address 0x7c00.
|
|
// If they are the same, we've found it. If we run out of partitions,
|
|
// just try partition 1
|
|
//
|
|
i=1;
|
|
do {
|
|
sprintf(NameBuffer, "multi(0)disk(0)rdisk(0)partition(%u)",i);
|
|
Status = ArcOpen(NameBuffer,ArcOpenReadOnly,&FileId);
|
|
if (Status != ESUCCESS) {
|
|
//
|
|
// we've run out of partitions, return the default.
|
|
//
|
|
i=1;
|
|
break;
|
|
} else {
|
|
//
|
|
// Read in the first 512 bytes
|
|
//
|
|
Status = ArcRead(FileId, SectorBuffer, 512, &Count);
|
|
ArcClose(FileId);
|
|
if (Status==ESUCCESS) {
|
|
|
|
//
|
|
// only need to compare the first 36 bytes
|
|
// Jump instr. == 3 bytes
|
|
// Oem field == 8 bytes
|
|
// BPB == 25 bytes
|
|
//
|
|
|
|
if (memcmp(SectorBuffer, (PVOID)0x7c00, 36)==0) {
|
|
//
|
|
// we have found a match.
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
++i;
|
|
} while ( TRUE );
|
|
|
|
sprintf(BootPartitionName, "multi(0)disk(0)rdisk(0)partition(%u)",i);
|
|
return;
|
|
}
|
|
|
|
#if defined(ELTORITO)
|
|
|
|
BOOLEAN
|
|
BlIsElToritoCDBoot(
|
|
ULONG DriveNum
|
|
)
|
|
{
|
|
if (LocalBuffer == NULL) {
|
|
LocalBuffer = FwAllocateHeap(SCRATCH_BUFFER_SIZE);
|
|
if (LocalBuffer==NULL) {
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
// 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(LocalBuffer, DriveNum)) {
|
|
return(TRUE);
|
|
} else {
|
|
return(FALSE);
|
|
}
|
|
} else {
|
|
return(FALSE);
|
|
}
|
|
}
|
|
#endif
|
|
|