// 搜索Ctrl-Z p=BootFile;
while ((*p!='\\0') && (*p!=26)) { ++p; } if (*p != '\\0') {
*p='\\0'; } BlClose(BootFileId); }
if (!AlreadyInitialized) { AbiosInitDataStructures(); }
MdShutoffFloppy();//关闭软驱
TextClearDisplay();//清除显示文本
p=BlSelectKernel(DriveId,BootFile, &LoadOptions, UseTimeOut);
if (!AlreadyInitialized) {
BlPrint(BlFindMessage(BL_NTDETECT_MSG)); if (!BlDetectHardware(DriveId, LoadOptions)) { BlPrint(BlFindMessage(BL_NTDETECT_FAILURE)); return; }
TextClearDisplay();
// 初始化SCSI引导驱动 if(!_strnicmp(p,\,5)) { AEInitializeIo(DriveId); } ArcClose(DriveId);
// 设置标志位表示内存描述符不能被改变. FwDescriptorsValid = FALSE; } else { TextClearDisplay(); }
//设置该标志位用于表示ntdetect和abios的初始化例程已经运行 AlreadyInitialized = TRUE;
//设置引导菜单无等待操作的时间,即用户如不操作则一直停留 UseTimeOut=FALSE; i=0;
while (*p !='\\\\') {
KernelBootDevice[i] = *p; i++; p++; }
KernelBootDevice[i] = '\\0';
strcpy(OsLoadFilename,\); strcat(OsLoadFilename,p);
// 这里只能使用参数”osloader= variable”来指定从哪里加载HAL.DLL.
// 因为x86系统未指定”系统分区 ”所以将从路径\\nt\\system\\HAL.DLL加载HAL.DLL
strcpy(OsLoaderFilename,\); strcat(OsLoaderFilename,p);
strcat(OsLoaderFilename,\);
strcpy(SystemPartition,\); strcat(SystemPartition,KernelBootDevice);
strcpy(OsLoadPartition,\); strcat(OsLoadPartition,KernelBootDevice);
strcpy(OsLoadOptions,\); if (LoadOptions) {
strcat(OsLoadOptions,LoadOptions); }
strcpy(ConsoleInputName,\);
strcpy(ConsoleOutputName,\);
strcpy(X86SystemPartition,\); strcat(X86SystemPartition,PartitionName);
Argv[0]=\;
Argv[1]=OsLoaderFilename; Argv[2]=SystemPartition; Argv[3]=OsLoadFilename; Argv[4]=OsLoadPartition; Argv[5]=OsLoadOptions; Argv[6]=ConsoleInputName; Argv[7]=ConsoleOutputName; Argv[8]=X86SystemPartition;
Status = BlOsLoader(9,Argv,NULL);
BootFailed:
if (Status != ESUCCESS) { // 引导失败就重新启动 while (TRUE) { GET_KEY(); } } else { //重新打开设备
Status = ArcOpen(BootPartitionName, ArcOpenReadOnly, &DriveId); if (Status != ESUCCESS) {
BlPrint(BlFindMessage(BL_DRIVE_ERROR),BootPartitionName); gotoBootFailed; }
}
} while (TRUE);
}
然后,os loader 加载内核模块映像文件,默认为ntoskrnl.exe,以及HAL 映像文件,默认为hal.dll。再加载注册表的SYSTEM 储巢,即\\WINDOWS\\system32\\config\\system 文件。通过检查SYSTEM 储巢中的设置信息,它可以知道哪些设备驱动程序必须被加载进来,即被标记为“引导-启动”(SERVICE_BOOT_START)的设备驱动程序。然后它加载所有这些被标记为“引导-启动”的设备驱动程序,以及访问系统目录所必需的文件系统驱动程序。注意,在此之前os loader 也可以访问系统分区,但并非通过文件系统驱动程序。
代码摘自\\ntos\\boot\\bldr\\osloader.c
// 定义扩展静态数据
ULONGBlConsoleOutDeviceId = 0; ULONGBlConsoleInDeviceId = 0; ULONGBlDcacheFillSize = 32; #ifDBG
BOOLEANBlOutputDots=FALSE; #else
BOOLEANBlOutputDots=TRUE; #endif
CHARKernelFileName[8+1+3+1]=\; CHARHalFileName[8+1+3+1]=\; //此处定义名为\和\的文件
ARC_STATUS BlOsLoader ( INULONGArgc, INPCHARArgv[], INPCHAREnvp[] ) /*++
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. --*/ {
CHARBootDirectoryPath[256]; ULONGCacheLineSize; PCHARConsoleOutDevice; PCHARConsoleInDevice; ULONGCount;
PCONFIGURATION_COMPONENT_DATADataCache; CHARDeviceName[256]; CHARDevicePrefix[256]; PCHARDirectoryEnd; CHARDllName[256];
CHARDriverDirectoryPath[256]; PCHARFileName; ULONGFileSize;
PLDR_DATA_TABLE_ENTRYHalDataTableEntry; CHARHalDirectoryPath[256];
CHARKernelDirectoryPath[256]; PVOIDHalBase; PVOIDSystemBase; ULONGIndex; ULONGLimit;
ULONGLinesPerBlock; PCHARLoadDevice; ULONGLoadDeviceId; PCHARLoadFileName; PCHARLoadOptions; ULONGi;
CHAROutputBuffer[256]; ARC_STATUSStatus;
PLDR_DATA_TABLE_ENTRYSystemDataTableEntry; PCHARSystemDevice; ULONGSystemDeviceId;
PTRANSFER_ROUTINESystemEntry; PIMAGE_NT_HEADERSNtHeaders; PWSTRBootFileSystem; PCHARLastKnownGood; BOOLEANBreakInKey; CHARBadFileName[128]; PBOOTFS_INFOFsInfo;
// 获取控制台输出设备的名字并获取写入权限
ConsoleOutDevice = BlGetArgumentValue(Argc, Argv, \); if (ConsoleOutDevice == NULL) { returnENODEV; }
Status = ArcOpen(ConsoleOutDevice, ArcOpenWriteOnly, &BlConsoleOutDeviceId); if (Status != ESUCCESS) { returnStatus; }
// 获取控制台输入设备的名字并获取读取权限
ConsoleInDevice = BlGetArgumentValue(Argc, Argv, \); if (ConsoleInDevice == NULL) { returnENODEV; }
Status = ArcOpen(ConsoleInDevice, ArcOpenReadOnly, &BlConsoleInDeviceId); if (Status != ESUCCESS) { returnStatus; }
// 声明OS Loader.
strcpy(&OutputBuffer[0], \); ArcWrite(BlConsoleOutDeviceId, &OutputBuffer[0], strlen(&OutputBuffer[0]), &Count);
// 初始化内存描述符列表,OSloader系统堆和参数块 Status = BlMemoryInitialize(); if (Status != ESUCCESS) {
BlFatalError(LOAD_HW_MEM_CLASS, DIAG_BL_MEMORY_INIT, LOAD_HW_MEM_ACT); gotoLoadFailed; }
// 计算数据缓存大小.该值用来对齐I/O缓冲区以防主机系统不支持连续的缓存
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; }
// 初始化OS loader的I/O系统 Status = BlIoInitialize(); if (Status != ESUCCESS) {
BlFatalError(LOAD_HW_DISK_CLASS, DIAG_BL_IO_INIT, LOAD_HW_DISK_ACT); gotoLoadFailed; }
// 初始化资源节
Status = BlInitResources(Argv[0]); if (Status != ESUCCESS) {
BlFatalError(LOAD_HW_DISK_CLASS, DIAG_BL_IO_INIT, LOAD_HW_DISK_ACT); }
// 初始化NT配置树.
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); gotoLoadFailed; }
// 复制osloadoptions参数给LoaderBlock
LoadOptions = BlGetArgumentValue(Argc, Argv, \); if (LoadOptions != NULL) { FileSize = strlen(LoadOptions)+1;
FileName = (PCHAR)BlAllocateHeap(FileSize); strcpy(FileName, LoadOptions);
BlLoaderBlock->LoadOptions = FileName;