NT4/private/ntos/boot/bldr/osloader.c
2020-09-30 17:12:29 +02:00

1301 lines
32 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
osloader.c
Abstract:
This module contains the code that implements the NT operating system
loader.
Author:
David N. Cutler (davec) 10-May-1991
Revision History:
--*/
#include "bldr.h"
#include "ctype.h"
#include "stdio.h"
#include "string.h"
#include "msg.h"
BOOLEAN BlRebootSystem = FALSE;
//
// Define transfer entry of loaded image.
//
typedef
VOID
(*PTRANSFER_ROUTINE) (
PLOADER_PARAMETER_BLOCK LoaderBlock
);
BOOLEAN
BlGetDriveSignature(
IN PCHAR Name,
OUT PULONG Signature
);
PVOID
BlLoadDataFile(
IN ULONG DeviceId,
IN PCHAR LoadDevice,
IN PCHAR SystemPath,
IN PUNICODE_STRING Filename,
IN MEMORY_TYPE MemoryType,
OUT PULONG FileSize
);
//
// Define local static data.
//
PCHAR ArcStatusCodeMessages[] = {
"operation was success",
"E2BIG",
"EACCES",
"EAGAIN",
"EBADF",
"EBUSY",
"EFAULT",
"EINVAL",
"EIO",
"EISDIR",
"EMFILE",
"EMLINK",
"ENAMETOOLONG",
"ENODEV",
"ENOENT",
"ENOEXEC",
"ENOMEM",
"ENOSPC",
"ENOTDIR",
"ENOTTY",
"ENXIO",
"EROFS",
};
//
// Diagnostic load messages
//
VOID
BlFatalError(
IN ULONG ClassMessage,
IN ULONG DetailMessage,
IN ULONG ActionMessage
);
VOID
BlBadFileMessage(
IN PCHAR BadFileName
);
//
// Define external static data.
//
ULONG BlConsoleOutDeviceId = 0;
ULONG BlConsoleInDeviceId = 0;
ULONG BlDcacheFillSize = 32;
#if DBG
BOOLEAN BlOutputDots=FALSE;
#else
BOOLEAN BlOutputDots=TRUE;
#endif
CHAR KernelFileName[8+1+3+1]="ntoskrnl.exe";
CHAR HalFileName[8+1+3+1]="hal.dll";
ARC_STATUS
BlOsLoader (
IN ULONG Argc,
IN PCHAR Argv[],
IN PCHAR Envp[]
)
/*++
Routine Description:
This is the main routine that controls the loading of the NT operating
system on an ARC compliant system. It opens the system partition,
the boot partition, the console input device, and the console output
device. The NT operating system and all its DLLs are loaded and bound
together. Control is then transfered to the loaded system.
Arguments:
Argc - Supplies the number of arguments that were provided on the
command that invoked this program.
Argv - Supplies a pointer to a vector of pointers to null terminated
argument strings.
Envp - Supplies a pointer to a vector of pointers to null terminated
environment variables.
Return Value:
EBADF is returned if the specified OS image cannot be loaded.
--*/
{
CHAR BootDirectoryPath[256];
ULONG CacheLineSize;
PCHAR ConsoleOutDevice;
PCHAR ConsoleInDevice;
ULONG Count;
PCONFIGURATION_COMPONENT_DATA DataCache;
CHAR DeviceName[256];
CHAR DevicePrefix[256];
PCHAR DirectoryEnd;
CHAR DllName[256];
CHAR DriverDirectoryPath[256];
PCHAR FileName;
ULONG FileSize;
PLDR_DATA_TABLE_ENTRY HalDataTableEntry;
CHAR HalDirectoryPath[256];
CHAR KernelDirectoryPath[256];
PVOID HalBase;
PVOID SystemBase;
ULONG Index;
ULONG Limit;
ULONG LinesPerBlock;
PCHAR LoadDevice;
ULONG LoadDeviceId;
PCHAR LoadFileName;
PCHAR LoadOptions;
ULONG i;
CHAR OutputBuffer[256];
ARC_STATUS Status;
PLDR_DATA_TABLE_ENTRY SystemDataTableEntry;
PCHAR SystemDevice;
ULONG SystemDeviceId;
PTRANSFER_ROUTINE SystemEntry;
PIMAGE_NT_HEADERS NtHeaders;
PWSTR BootFileSystem;
PCHAR LastKnownGood;
BOOLEAN BreakInKey;
CHAR BadFileName[128];
PBOOTFS_INFO FsInfo;
//
// Get the name of the console output device and open the device for
// write access.
//
ConsoleOutDevice = BlGetArgumentValue(Argc, Argv, "consoleout");
if (ConsoleOutDevice == NULL) {
return ENODEV;
}
Status = ArcOpen(ConsoleOutDevice, ArcOpenWriteOnly, &BlConsoleOutDeviceId);
if (Status != ESUCCESS) {
return Status;
}
//
// Get the name of the console input device and open the device for
// read access.
//
ConsoleInDevice = BlGetArgumentValue(Argc, Argv, "consolein");
if (ConsoleInDevice == NULL) {
return ENODEV;
}
Status = ArcOpen(ConsoleInDevice, ArcOpenReadOnly, &BlConsoleInDeviceId);
if (Status != ESUCCESS) {
return Status;
}
//
// Announce OS Loader.
//
strcpy(&OutputBuffer[0], "OS Loader V4.00\r\n");
ArcWrite(BlConsoleOutDeviceId,
&OutputBuffer[0],
strlen(&OutputBuffer[0]),
&Count);
//
// Initialize the memory descriptor list, the OS loader heap, and the
// OS loader parameter block.
//
Status = BlMemoryInitialize();
if (Status != ESUCCESS) {
BlFatalError(LOAD_HW_MEM_CLASS,
DIAG_BL_MEMORY_INIT,
LOAD_HW_MEM_ACT);
goto LoadFailed;
}
//
// Compute the data cache fill size. This value is used to align
// I/O buffers in case the host system does not support coherent
// caches.
//
// If a combined secondary cache is present, then use the fill size
// for that cache. Otherwise, if a secondary data cache is present,
// then use the fill size for that cache. Otherwise, if a primary
// data cache is present, then use the fill size for that cache.
// Otherwise, use the default fill size.
//
DataCache = KeFindConfigurationEntry(BlLoaderBlock->ConfigurationRoot,
CacheClass,
SecondaryCache,
NULL);
if (DataCache == NULL) {
DataCache = KeFindConfigurationEntry(BlLoaderBlock->ConfigurationRoot,
CacheClass,
SecondaryDcache,
NULL);
if (DataCache == NULL) {
DataCache = KeFindConfigurationEntry(BlLoaderBlock->ConfigurationRoot,
CacheClass,
PrimaryDcache,
NULL);
}
}
if (DataCache != NULL) {
LinesPerBlock = DataCache->ComponentEntry.Key >> 24;
CacheLineSize = 1 << ((DataCache->ComponentEntry.Key >> 16) & 0xff);
BlDcacheFillSize = LinesPerBlock * CacheLineSize;
}
//
// Initialize the OS loader I/O system.
//
Status = BlIoInitialize();
if (Status != ESUCCESS) {
BlFatalError(LOAD_HW_DISK_CLASS,
DIAG_BL_IO_INIT,
LOAD_HW_DISK_ACT);
goto LoadFailed;
}
//
// Initialize the resource section
//
Status = BlInitResources(Argv[0]);
if (Status != ESUCCESS) {
BlFatalError(LOAD_HW_DISK_CLASS,
DIAG_BL_IO_INIT,
LOAD_HW_DISK_ACT);
}
//
// Initialize the NT configuration tree.
//
BlLoaderBlock->ConfigurationRoot = NULL;
Status = BlConfigurationInitialize(NULL, NULL);
if (Status != ESUCCESS) {
BlFatalError(LOAD_HW_FW_CFG_CLASS,
DIAG_BL_CONFIG_INIT,
LOAD_HW_FW_CFG_ACT);
goto LoadFailed;
}
//
// Copy the osloadoptions argument into the LoaderBlock
//
LoadOptions = BlGetArgumentValue(Argc, Argv, "osloadoptions");
if (LoadOptions != NULL) {
FileSize = strlen(LoadOptions)+1;
FileName = (PCHAR)BlAllocateHeap(FileSize);
strcpy(FileName, LoadOptions);
BlLoaderBlock->LoadOptions = FileName;
//
// check for magic switch that says we should output
// the filenames of the files instead of just dots.
//
if ((strstr(FileName,"SOS")!=NULL) ||
(strstr(FileName,"sos")!=NULL)) {
BlOutputDots=FALSE;
}
FileName=strstr(BlLoaderBlock->LoadOptions,"HAL=");
if (FileName) {
for (i=0; i<sizeof(HalFileName); i++) {
if (FileName[4+i]==' ') {
HalFileName[i]='\0';
break;
}
HalFileName[i]=FileName[4+i];
}
}
HalFileName[sizeof(HalFileName)-1]='\0';
FileName=strstr(BlLoaderBlock->LoadOptions,"KERNEL=");
if (FileName) {
for (i=0; i<sizeof(KernelFileName); i++) {
if (FileName[7+i]==' ') {
KernelFileName[i]='\0';
break;
}
KernelFileName[i]=FileName[7+i];
}
}
KernelFileName[sizeof(KernelFileName)-1]='\0';
} else {
BlLoaderBlock->LoadOptions = NULL;
}
//
// Get the name of the load device and open the device for read access.
//
LoadDevice = BlGetArgumentValue(Argc, Argv, "osloadpartition");
if (LoadDevice == NULL) {
Status = ENODEV;
BlFatalError(LOAD_HW_FW_CFG_CLASS,
DIAG_BL_FW_GET_BOOT_DEVICE,
LOAD_HW_FW_CFG_ACT);
goto LoadFailed;
}
Status = ArcOpen(LoadDevice, ArcOpenReadOnly, &LoadDeviceId);
if (Status != ESUCCESS) {
BlFatalError(LOAD_HW_DISK_CLASS,
DIAG_BL_OPEN_BOOT_DEVICE,
LOAD_HW_DISK_ACT);
goto LoadFailed;
}
//
// Get the name of the system device and open the device for read access.
//
SystemDevice = BlGetArgumentValue(Argc, Argv, "systempartition");
if (SystemDevice == NULL) {
Status = ENODEV;
BlFatalError(LOAD_HW_FW_CFG_CLASS,
DIAG_BL_FW_GET_SYSTEM_DEVICE,
LOAD_HW_FW_CFG_ACT);
goto LoadFailed;
}
Status = ArcOpen(SystemDevice, ArcOpenReadOnly, &SystemDeviceId);
if (Status != ESUCCESS) {
BlFatalError(LOAD_HW_FW_CFG_CLASS,
DIAG_BL_FW_OPEN_SYSTEM_DEVICE,
LOAD_HW_FW_CFG_ACT);
goto LoadFailed;
}
//
// Initialize the debugging system.
//
BlLogInitialize(SystemDeviceId);
//
// Display the Configuration prompt for breakin key at this
// point. No key presses are checked for at this point, but
// this gives the user a little more reaction time.
//
BlStartConfigPrompt();
#if defined(_PPC_)
Status = BlPpcInitialize();
if (Status != ESUCCESS) {
goto LoadFailed;
}
#endif // defined(_PPC_)
//
// Get the path name of the system root directory.
//
LoadFileName = BlGetArgumentValue(Argc, Argv, "osloadfilename");
if (LoadFileName == NULL) {
Status = ENOENT;
BlFatalError(LOAD_HW_FW_CFG_CLASS,
DIAG_BL_FW_GET_BOOT_DEVICE,
LOAD_HW_FW_CFG_ACT);
goto LoadFailed;
}
//
// LoadFileName is of the form <SystemRoot> ( "\winnt" )
//
//
// Generate the directory name of the SYSTEM32 directory.
//
strcpy(BootDirectoryPath, LoadFileName);
strcat(BootDirectoryPath, "\\System32\\");
//
// Generate the full pathname of ntoskrnl.exe
// "\winnt\system32\ntoskrnl.exe"
//
strcpy(KernelDirectoryPath, BootDirectoryPath);
strcat(KernelDirectoryPath, KernelFileName);
//
// Load the system image into memory.
//
BlOutputLoadMessage(LoadDevice, KernelDirectoryPath);
Status = BlLoadImage(LoadDeviceId,
LoaderSystemCode,
KernelDirectoryPath,
TARGET_IMAGE,
&SystemBase);
if (Status != ESUCCESS) {
BlFatalError(LOAD_SW_MIS_FILE_CLASS,
DIAG_BL_LOAD_SYSTEM_IMAGE,
LOAD_SW_FILE_REINST_ACT);
goto LoadFailed;
}
//
// Whatever filesystem was used to load the system image is the
// one that needs to be loaded along with the boot drivers.
//
FsInfo = BlGetFsInfo(LoadDeviceId);
if (FsInfo != NULL) {
BootFileSystem = FsInfo->DriverName;
} else {
BlFatalError(LOAD_SW_MIS_FILE_CLASS,
DIAG_BL_LOAD_SYSTEM_IMAGE,
LOAD_SW_FILE_REINST_ACT);
goto LoadFailed;
}
//
// Get the path name of the OS loader file and isolate the directory
// path so it can be used to load the HAL DLL.
//
FileName = BlGetArgumentValue(Argc, Argv, "osloader");
if (FileName == NULL) {
Status = ENOENT;
BlFatalError(LOAD_HW_FW_CFG_CLASS,
DIAG_BL_FIND_HAL_IMAGE,
LOAD_HW_FW_CFG_ACT);
goto LoadFailed;
}
DirectoryEnd = strrchr(FileName, '\\');
FileName = strchr(FileName, '\\');
HalDirectoryPath[0] = 0;
if (DirectoryEnd != NULL) {
Limit = (ULONG)DirectoryEnd - (ULONG)FileName + 1;
for (Index = 0; Index < Limit; Index += 1) {
HalDirectoryPath[Index] = *FileName++;
}
HalDirectoryPath[Index] = 0;
}
//
// Generate the full path name for the HAL DLL image and load it into
// memory.
//
strcpy(&DllName[0], &HalDirectoryPath[0]);
strcat(&DllName[0], HalFileName);
BlOutputLoadMessage(SystemDevice, &DllName[0]);
Status = BlLoadImage(SystemDeviceId,
LoaderHalCode,
&DllName[0],
TARGET_IMAGE,
&HalBase);
if (Status != ESUCCESS) {
BlFatalError(LOAD_SW_MIS_FILE_CLASS,
DIAG_BL_LOAD_HAL_IMAGE,
LOAD_SW_FILE_REINST_ACT);
goto LoadFailed;
}
//
// Generate a loader data entry for the system image.
//
Status = BlAllocateDataTableEntry("ntoskrnl.exe",
KernelDirectoryPath,
SystemBase,
&SystemDataTableEntry);
if (Status != ESUCCESS) {
BlFatalError(LOAD_SW_INT_ERR_CLASS,
DIAG_BL_LOAD_SYSTEM_IMAGE,
LOAD_SW_INT_ERR_ACT);
goto LoadFailed;
}
//
// Generate a loader data entry for the HAL DLL.
//
Status = BlAllocateDataTableEntry("hal.dll",
&DllName[0],
HalBase,
&HalDataTableEntry);
if (Status != ESUCCESS) {
BlFatalError(LOAD_SW_INT_ERR_CLASS,
DIAG_BL_LOAD_HAL_IMAGE,
LOAD_SW_INT_ERR_ACT);
goto LoadFailed;
}
#if defined(_ALPHA_)
Status = BlLoadPal(SystemDeviceId,
LoaderSystemCode,
&HalDirectoryPath[0],
TARGET_IMAGE,
&BlLoaderBlock->u.Alpha.PalBaseAddress,
SystemDevice);
if (Status != ESUCCESS) {
BlFatalError(LOAD_SW_MIS_FILE_CLASS,
DIAG_BL_LOAD_SYSTEM_DLLS,
LOAD_SW_FILE_REINST_ACT);
goto LoadFailed;
}
#endif // _ALPHA_
//
// Scan the import table for the system image and load all referenced
// DLLs.
//
Status = BlScanImportDescriptorTable(LoadDeviceId,
LoadDevice,
&BootDirectoryPath[0],
SystemDataTableEntry);
if (Status != ESUCCESS) {
BlFatalError(LOAD_SW_INT_ERR_CLASS,
DIAG_BL_LOAD_SYSTEM_DLLS,
LOAD_SW_INT_ERR_ACT);
goto LoadFailed;
}
//
// Scan the import table for the HAL DLL and load all referenced DLLs.
//
Status = BlScanImportDescriptorTable(SystemDeviceId,
SystemDevice,
&HalDirectoryPath[0],
HalDataTableEntry);
if (Status != ESUCCESS) {
BlFatalError(LOAD_SW_INT_ERR_CLASS,
DIAG_BL_LOAD_HAL_DLLS,
LOAD_SW_INT_ERR_ACT);
goto LoadFailed;
}
//
// Relocate the system entry point and set system specific information.
//
NtHeaders = RtlImageNtHeader(SystemBase);
SystemEntry = (PTRANSFER_ROUTINE)((ULONG)SystemBase +
NtHeaders->OptionalHeader.AddressOfEntryPoint);
#ifdef MIPS
BlLoaderBlock->u.Mips.GpBase = (ULONG)SystemBase +
NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_GLOBALPTR].VirtualAddress;
#endif
#if defined(_ALPHA_)
BlLoaderBlock->u.Alpha.GpBase = (ULONG)SystemBase +
NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_GLOBALPTR].VirtualAddress;
#endif
//
// Form the directory path for all device drivers.
//
strcpy(&DriverDirectoryPath[0], &BootDirectoryPath[0]);
strcat(&DriverDirectoryPath[0], "\\Drivers\\");
//
// Allocate structure for NLS data. This will be loaded and filled
// in by BlLoadAndScanSystemHive.
//
BlLoaderBlock->NlsData = BlAllocateHeap(sizeof(NLS_DATA_BLOCK));
if (BlLoaderBlock->NlsData == NULL) {
Status = ENOMEM;
BlFatalError(LOAD_HW_MEM_CLASS,
DIAG_BL_LOAD_SYSTEM_HIVE,
LOAD_HW_MEM_ACT);
goto LoadFailed;
}
//
// Load the registry SYSTEM hive.
//
// DIAG_BL_LOAD_SYSTEM_REGISTRY_HIVE
// "Cannot load system hardware configuration file.\r\n"
Status = BlLoadAndScanSystemHive(LoadDeviceId,
LoadDevice,
LoadFileName,
BootFileSystem,
BadFileName);
if (Status != ESUCCESS) {
if (BlRebootSystem) {
Status = ESUCCESS;
} else {
BlBadFileMessage(BadFileName);
}
goto LoadFailed;
}
//
// Generate the ARC boot device name and NT path name.
//
Status = BlGenerateDeviceNames(LoadDevice, &DeviceName[0], &DevicePrefix[0]);
if (Status != ESUCCESS) {
BlFatalError(LOAD_HW_FW_CFG_CLASS,
DIAG_BL_ARC_BOOT_DEV_NAME,
LOAD_HW_FW_CFG_ACT);
goto LoadFailed;
}
FileSize = strlen(&DeviceName[0]) + 1;
FileName = (PCHAR)BlAllocateHeap(FileSize);
strcpy(FileName, &DeviceName[0]);
BlLoaderBlock->ArcBootDeviceName = FileName;
FileSize = strlen(LoadFileName) + 2;
FileName = (PCHAR)BlAllocateHeap( FileSize);
strcpy(FileName, LoadFileName);
strcat(FileName, "\\");
BlLoaderBlock->NtBootPathName = FileName;
//
// Generate the ARC HAL device name and NT path name.
//
#ifdef i386
//
// On X86, the systempartition variable lies, and instead points to the location
// of the hal. We pass in another variable, 'X86SystemPartition', that tell us
// the real system partition.
//
strcpy(&DeviceName[0], BlGetArgumentValue(Argc, Argv, "x86systempartition"));
#else
Status = BlGenerateDeviceNames(SystemDevice, &DeviceName[0], &DevicePrefix[0]);
if (Status != ESUCCESS) {
BlFatalError(LOAD_HW_FW_CFG_CLASS,
DIAG_BL_ARC_BOOT_DEV_NAME,
LOAD_HW_FW_CFG_ACT);
goto LoadFailed;
}
#endif //i386
FileSize = strlen(&DeviceName[0]) + 1;
FileName = (PCHAR)BlAllocateHeap(FileSize);
strcpy(FileName, &DeviceName[0]);
BlLoaderBlock->ArcHalDeviceName = FileName;
#ifdef i386
//
// On X86, this structure is unfortunately named. What we really need here is the
// osloader path. What we actually have is a path to the HAL. Since this path is
// always at the root of the partition, hardcode it here.
//
FileName = (PCHAR)BlAllocateHeap(2);
FileName[0] = '\\';
FileName[1] = '\0';
#else
FileSize = strlen(&HalDirectoryPath[0]) + 1;
FileName = (PCHAR)BlAllocateHeap(FileSize);
strcpy(FileName, &HalDirectoryPath[0]);
#endif //i386
BlLoaderBlock->NtHalPathName = FileName;
//
// Get the NTFT drive signatures to allow the kernel to create the
// correct ARC name <=> NT name mappings.
//
BlGetArcDiskInformation();
//
// Execute the architecture specific setup code.
//
Status = BlSetupForNt(BlLoaderBlock);
if (Status != ESUCCESS) {
BlFatalError(LOAD_SW_INT_ERR_CLASS,
DIAG_BL_SETUP_FOR_NT,
LOAD_SW_INT_ERR_ACT);
goto LoadFailed;
}
//
// Turn off the debugging system.
//
BlLogTerminate();
//
// Transfer control to loaded image.
//
(SystemEntry)(BlLoaderBlock);
Status = EBADF;
BlFatalError(LOAD_SW_BAD_FILE_CLASS,
DIAG_BL_KERNEL_INIT_XFER,
LOAD_SW_FILE_REINST_ACT);
//
// The load failed.
//
LoadFailed:
return Status;
}
VOID
BlOutputLoadMessage (
IN PCHAR DeviceName,
IN PCHAR FileName
)
/*++
Routine Description:
This routine outputs a loading message to the console output device.
Arguments:
DeviceName - Supplies a pointer to a zero terminated device name.
FileName - Supplies a pointer to a zero terminated file name.
Return Value:
None.
--*/
{
ULONG Count;
CHAR OutputBuffer[256];
//
// Construct and output loading file message.
//
if (!BlOutputDots) {
strcpy(&OutputBuffer[0], " ");
strcat(&OutputBuffer[0], DeviceName);
strcat(&OutputBuffer[0], FileName);
strcat(&OutputBuffer[0], "\r\n");
} else {
strcpy(&OutputBuffer[0],".");
}
BlLog((LOG_LOGFILE,OutputBuffer));
ArcWrite(BlConsoleOutDeviceId,
&OutputBuffer[0],
strlen(&OutputBuffer[0]),
&Count);
return;
}
ARC_STATUS
BlLoadAndScanSystemHive(
IN ULONG DeviceId,
IN PCHAR DeviceName,
IN PCHAR DirectoryPath,
IN PWSTR BootFileSystem,
OUT PCHAR BadFileName
)
/*++
Routine Description:
This function loads the system hive into memory, verifies its
consistency, scans it for the list of boot drivers, and loads
the resulting list of drivers.
If the system hive cannot be loaded or is not a valid hive, it
is rejected and the system.alt hive is used. If this is invalid,
the boot must fail.
Arguments:
DeviceId - Supplies the file id of the device the system tree is on.
DeviceName - Supplies the name of the device the system tree is on.
DirectoryPath - Supplies a pointer to the zero-terminated directory path
of the root of the NT system32 directory.
HiveName - Supplies the name of the SYSTEM hive
BadFileName - Returns the file required for booting that was corrupt
or missing. This will not be filled in if ESUCCESS is returned.
Return Value:
ESUCCESS - System hive valid and all necessary boot drivers successfully
loaded.
!ESUCCESS - System hive corrupt or critical boot drivers not present.
--*/
{
ARC_STATUS Status;
PCHAR FailReason;
CHAR Directory[256];
CHAR FontDirectory[256];
UNICODE_STRING AnsiCodepage;
UNICODE_STRING OemCodepage;
UNICODE_STRING OemHalFont;
UNICODE_STRING LanguageTable;
BOOLEAN RestartSetup;
strcpy(Directory,DirectoryPath);
strcat(Directory,"\\system32\\config\\");
Status = BlLoadAndInitSystemHive(DeviceId,
DeviceName,
Directory,
"system",
FALSE,
&RestartSetup);
if(Status != ESUCCESS) {
//
// bogus hive, try system.alt
//
Status = BlLoadAndInitSystemHive(DeviceId,
DeviceName,
Directory,
"system.alt",
TRUE,
&RestartSetup);
if(Status != ESUCCESS) {
strcpy(BadFileName,DirectoryPath);
strcat(BadFileName,"\\SYSTEM32\\CONFIG\\SYSTEM");
goto HiveScanFailed;
}
}
if(RestartSetup) {
//
// Need to restart setup
//
Status = BlLoadAndInitSystemHive(DeviceId,
DeviceName,
Directory,
"system.sav",
TRUE,
&RestartSetup);
if(Status != ESUCCESS) {
strcpy(BadFileName,DirectoryPath);
strcat(BadFileName,"\\SYSTEM32\\CONFIG\\SYSTEM.SAV");
goto HiveScanFailed;
}
}
//
// Hive is there, it's valid, go compute the driver list and NLS
// filenames. Note that if this fails, there is no point in switching
// to system.alt, since it will always be the same as system.
//
FailReason = BlScanRegistry(BootFileSystem,
&BlLoaderBlock->BootDriverListHead,
&AnsiCodepage,
&OemCodepage,
&LanguageTable,
&OemHalFont);
if (FailReason != NULL) {
Status = EBADF;
strcpy(BadFileName,Directory);
strcat(BadFileName,"SYSTEM");
goto HiveScanFailed;
}
strcpy(Directory,DirectoryPath);
strcat(Directory,"\\system32\\");
//
// Load NLS data tables
//
Status = BlLoadNLSData(DeviceId,
DeviceName,
Directory,
&AnsiCodepage,
&OemCodepage,
&LanguageTable,
BadFileName);
if (Status != ESUCCESS) {
goto HiveScanFailed;
}
//
// Load the OEM font file to be used by the HAL for possible frame
// buffer displays.
//
#ifdef i386
if ( !OemHalFont.Buffer ) {
goto oktoskipfont;
}
#endif
//
// On newer systems fonts are in the FONTS directory.
// On older systems fonts are in the SYSTEM directory.
//
strcpy(FontDirectory, DirectoryPath);
strcat(FontDirectory, "\\FONTS\\");
Status = BlLoadOemHalFont(DeviceId,
DeviceName,
FontDirectory,
&OemHalFont,
BadFileName);
if(Status != ESUCCESS) {
strcpy(FontDirectory, DirectoryPath);
strcat(FontDirectory, "\\SYSTEM\\");
Status = BlLoadOemHalFont(DeviceId,
DeviceName,
FontDirectory,
&OemHalFont,
BadFileName);
}
if (Status != ESUCCESS) {
#ifndef i386
goto HiveScanFailed;
#endif
}
#ifdef i386
oktoskipfont:
#endif
//
// Load boot drivers
//
strcpy(Directory,DirectoryPath);
strcat(Directory,"\\");
Status = BlLoadBootDrivers(DeviceId,
DeviceName,
Directory,
&BlLoaderBlock->BootDriverListHead,
BadFileName);
if (Status == ESUCCESS) {
return(Status);
}
HiveScanFailed:
return(Status);
}
BOOLEAN
BlGetDriveSignature(
IN PCHAR Name,
OUT PULONG Signature
)
/*++
Routine Description:
This routine gets the NTFT disk signature for a specified partition or
path.
Arguments:
Name - Supplies the arcname of the partition or drive.
Signature - Returns the NTFT disk signature for the drive.
Return Value:
TRUE - success, Signature will be filled in.
FALSE - failed, Signature will not be filled in.
--*/
{
UCHAR SectorBuffer[512+256];
CHAR DiskName[256];
ULONG DiskId;
PCHAR p;
ARC_STATUS Status;
ULONG Count;
LARGE_INTEGER SeekValue;
//
// Generate the arcname ("...partition(0)") for the raw disk device
// where the boot partition is, so we can read the MBR.
//
strcpy(DiskName, Name);
p=DiskName;
while (*p != '\0') {
if (_strnicmp(p, "partition(",10) == 0) {
break;
}
++p;
}
if (*p != '\0') {
strcpy(p,"partition(0)");
}
Status = ArcOpen(DiskName,ArcOpenReadOnly, &DiskId);
if (Status!=ESUCCESS) {
return(FALSE);
}
//
// Read the first sector of the physical drive
//
SeekValue.QuadPart = 0;
Status = ArcSeek(DiskId, &SeekValue, SeekAbsolute);
if (Status==ESUCCESS) {
Status = ArcRead(DiskId,
ALIGN_BUFFER(SectorBuffer),
512,
&Count);
}
ArcClose(DiskId);
if (Status!=ESUCCESS) {
return(FALSE);
}
//
// copy NTFT signature.
//
*Signature = ((PULONG)SectorBuffer)[PARTITION_TABLE_OFFSET/2-1];
return(TRUE);
}
VOID
BlBadFileMessage(
IN PCHAR BadFileName
)
/*++
Routine Description:
This function displays the error message for a missing or incorrect
critical file.
Arguments:
BadFileName - Supplies the name of the file that is missing or
corrupt.
Return Value:
None.
--*/
{
ULONG Count;
PCHAR Text;
ArcWrite(BlConsoleOutDeviceId,
"\r\n",
strlen("\r\n"),
&Count);
Text = BlFindMessage(LOAD_SW_MIS_FILE_CLASS);
if (Text != NULL) {
ArcWrite(BlConsoleOutDeviceId,
Text,
strlen(Text),
&Count);
}
ArcWrite(BlConsoleOutDeviceId,
BadFileName,
strlen(BadFileName),
&Count);
ArcWrite(BlConsoleOutDeviceId,
"\r\n\r\n",
strlen("\r\n\r\n"),
&Count);
Text = BlFindMessage(LOAD_SW_FILE_REST_ACT);
if (Text != NULL) {
ArcWrite(BlConsoleOutDeviceId,
Text,
strlen(Text),
&Count);
}
}
VOID
BlClearToEndOfScreen(
VOID
);
VOID
BlFatalError(
IN ULONG ClassMessage,
IN ULONG DetailMessage,
IN ULONG ActionMessage
)
/*++
Routine Description:
This function looks up messages to display at a error condition.
It attempts to locate the string in the resource section of the
osloader. If that fails, it prints a numerical error code.
The only time it should print a numerical error code is if the
resource section could not be located. This will only happen
on ARC machines where boot fails before the osloader.exe file
can be opened.
Arguments:
ClassMessage - General message that describes the class of
problem.
DetailMessage - Detailed description of what caused problem
ActionMessage - Message that describes a course of action
for user to take.
Return Value:
none
--*/
{
PCHAR Text;
CHAR Buffer[40];
ULONG Count;
ArcWrite(BlConsoleOutDeviceId,
"\r\n",
strlen("\r\n"),
&Count);
//
// Remove any remains from the last known good message
//
BlClearToEndOfScreen();
Text = BlFindMessage(ClassMessage);
if (Text == NULL) {
sprintf(Buffer,"%08lx\r\n",ClassMessage);
Text = Buffer;
}
ArcWrite(BlConsoleOutDeviceId,
Text,
strlen(Text),
&Count);
Text = BlFindMessage(DetailMessage);
if (Text == NULL) {
sprintf(Buffer,"%08lx\r\n",DetailMessage);
Text = Buffer;
}
ArcWrite(BlConsoleOutDeviceId,
Text,
strlen(Text),
&Count);
Text = BlFindMessage(ActionMessage);
if (Text == NULL) {
sprintf(Buffer,"%08lx\r\n",ActionMessage);
Text = Buffer;
}
ArcWrite(BlConsoleOutDeviceId,
Text,
strlen(Text),
&Count);
}