1301 lines
32 KiB
C
1301 lines
32 KiB
C
/*++
|
||
|
||
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);
|
||
|
||
}
|