1 /* 2 * PROJECT: FreeLoader 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: Windows-compatible NT OS Loader. 5 * COPYRIGHT: Copyright 2006-2019 Aleksey Bragin <aleksey@reactos.org> 6 */ 7 8 #include <freeldr.h> 9 #include <ndk/ldrtypes.h> 10 #include "winldr.h" 11 #include "ntldropts.h" 12 #include "registry.h" 13 #include <internal/cmboot.h> 14 15 #include <debug.h> 16 DBG_DEFAULT_CHANNEL(WINDOWS); 17 18 // FIXME: Find a better way to retrieve ARC disk information 19 extern ULONG reactos_disk_count; 20 extern ARC_DISK_SIGNATURE_EX reactos_arc_disk_info[]; 21 22 extern ULONG LoaderPagesSpanned; 23 extern BOOLEAN AcpiPresent; 24 25 extern HEADLESS_LOADER_BLOCK LoaderRedirectionInformation; 26 extern BOOLEAN WinLdrTerminalConnected; 27 extern VOID WinLdrSetupEms(IN PCSTR BootOptions); 28 29 PLOADER_SYSTEM_BLOCK WinLdrSystemBlock; 30 /**/PCWSTR BootFileSystem = NULL;/**/ 31 32 BOOLEAN VirtualBias = FALSE; 33 BOOLEAN SosEnabled = FALSE; 34 BOOLEAN SafeBoot = FALSE; 35 BOOLEAN BootLogo = FALSE; 36 #ifdef _M_IX86 37 BOOLEAN PaeModeOn = FALSE; 38 #endif 39 BOOLEAN NoExecuteEnabled = FALSE; 40 41 // debug stuff 42 VOID DumpMemoryAllocMap(VOID); 43 44 /* PE loader import-DLL loading callback */ 45 static VOID 46 NTAPI 47 NtLdrImportDllLoadCallback( 48 _In_ PCSTR FileName) 49 { 50 NtLdrOutputLoadMsg(FileName, NULL); 51 } 52 53 VOID 54 NtLdrOutputLoadMsg( 55 _In_ PCSTR FileName, 56 _In_opt_ PCSTR Description) 57 { 58 if (SosEnabled) 59 { 60 printf(" %s\n", FileName); 61 TRACE("Loading: %s\n", FileName); 62 } 63 else 64 { 65 /* Inform the user we load a file */ 66 CHAR ProgressString[256]; 67 68 RtlStringCbPrintfA(ProgressString, sizeof(ProgressString), 69 "Loading %s...", 70 (Description ? Description : FileName)); 71 // UiSetProgressBarText(ProgressString); 72 // UiIndicateProgress(); 73 UiDrawStatusText(ProgressString); 74 } 75 } 76 77 // Init "phase 0" 78 VOID 79 AllocateAndInitLPB( 80 IN USHORT VersionToBoot, 81 OUT PLOADER_PARAMETER_BLOCK* OutLoaderBlock) 82 { 83 PLOADER_PARAMETER_BLOCK LoaderBlock; 84 PLOADER_PARAMETER_EXTENSION Extension; 85 86 /* Allocate and zero-init the Loader Parameter Block */ 87 WinLdrSystemBlock = MmAllocateMemoryWithType(sizeof(LOADER_SYSTEM_BLOCK), 88 LoaderSystemBlock); 89 if (WinLdrSystemBlock == NULL) 90 { 91 UiMessageBox("Failed to allocate memory for system block!"); 92 return; 93 } 94 95 RtlZeroMemory(WinLdrSystemBlock, sizeof(LOADER_SYSTEM_BLOCK)); 96 97 LoaderBlock = &WinLdrSystemBlock->LoaderBlock; 98 LoaderBlock->NlsData = &WinLdrSystemBlock->NlsDataBlock; 99 100 /* Initialize the Loader Block Extension */ 101 Extension = &WinLdrSystemBlock->Extension; 102 LoaderBlock->Extension = Extension; 103 Extension->Size = sizeof(LOADER_PARAMETER_EXTENSION); 104 Extension->MajorVersion = (VersionToBoot & 0xFF00) >> 8; 105 Extension->MinorVersion = (VersionToBoot & 0xFF); 106 107 /* Init three critical lists, used right away */ 108 InitializeListHead(&LoaderBlock->LoadOrderListHead); 109 InitializeListHead(&LoaderBlock->MemoryDescriptorListHead); 110 InitializeListHead(&LoaderBlock->BootDriverListHead); 111 112 *OutLoaderBlock = LoaderBlock; 113 } 114 115 // Init "phase 1" 116 VOID 117 WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock, 118 PCSTR Options, 119 PCSTR SystemRoot, 120 PCSTR BootPath, 121 USHORT VersionToBoot) 122 { 123 /* 124 * Examples of correct options and paths: 125 * CHAR Options[] = "/DEBUGPORT=COM1 /BAUDRATE=115200"; 126 * CHAR Options[] = "/NODEBUG"; 127 * CHAR SystemRoot[] = "\\WINNT\\"; 128 * CHAR ArcBoot[] = "multi(0)disk(0)rdisk(0)partition(1)"; 129 */ 130 131 PSTR LoadOptions, NewLoadOptions; 132 CHAR HalPath[] = "\\"; 133 CHAR ArcBoot[MAX_PATH+1]; 134 CHAR MiscFiles[MAX_PATH+1]; 135 ULONG i; 136 ULONG_PTR PathSeparator; 137 PLOADER_PARAMETER_EXTENSION Extension; 138 139 /* Construct SystemRoot and ArcBoot from SystemPath */ 140 PathSeparator = strstr(BootPath, "\\") - BootPath; 141 RtlStringCbCopyNA(ArcBoot, sizeof(ArcBoot), BootPath, PathSeparator); 142 143 TRACE("ArcBoot: '%s'\n", ArcBoot); 144 TRACE("SystemRoot: '%s'\n", SystemRoot); 145 TRACE("Options: '%s'\n", Options); 146 147 /* Fill ARC BootDevice */ 148 LoaderBlock->ArcBootDeviceName = WinLdrSystemBlock->ArcBootDeviceName; 149 RtlStringCbCopyA(LoaderBlock->ArcBootDeviceName, sizeof(WinLdrSystemBlock->ArcBootDeviceName), ArcBoot); 150 LoaderBlock->ArcBootDeviceName = PaToVa(LoaderBlock->ArcBootDeviceName); 151 152 // 153 // IMPROVE!! 154 // SetupBlock->ArcSetupDeviceName must be the path to the setup **SOURCE**, 155 // and not the setup boot path. Indeed they may differ!! 156 // 157 if (LoaderBlock->SetupLdrBlock) 158 { 159 PSETUP_LOADER_BLOCK SetupBlock = LoaderBlock->SetupLdrBlock; 160 161 /* Adjust the ARC path in the setup block - Matches ArcBoot path */ 162 SetupBlock->ArcSetupDeviceName = WinLdrSystemBlock->ArcBootDeviceName; 163 SetupBlock->ArcSetupDeviceName = PaToVa(SetupBlock->ArcSetupDeviceName); 164 165 /* Convert the setup block pointer */ 166 LoaderBlock->SetupLdrBlock = PaToVa(LoaderBlock->SetupLdrBlock); 167 } 168 169 /* Fill ARC HalDevice, it matches ArcBoot path */ 170 LoaderBlock->ArcHalDeviceName = WinLdrSystemBlock->ArcBootDeviceName; 171 LoaderBlock->ArcHalDeviceName = PaToVa(LoaderBlock->ArcHalDeviceName); 172 173 /* Fill SystemRoot */ 174 LoaderBlock->NtBootPathName = WinLdrSystemBlock->NtBootPathName; 175 RtlStringCbCopyA(LoaderBlock->NtBootPathName, sizeof(WinLdrSystemBlock->NtBootPathName), SystemRoot); 176 LoaderBlock->NtBootPathName = PaToVa(LoaderBlock->NtBootPathName); 177 178 /* Fill NtHalPathName */ 179 LoaderBlock->NtHalPathName = WinLdrSystemBlock->NtHalPathName; 180 RtlStringCbCopyA(LoaderBlock->NtHalPathName, sizeof(WinLdrSystemBlock->NtHalPathName), HalPath); 181 LoaderBlock->NtHalPathName = PaToVa(LoaderBlock->NtHalPathName); 182 183 /* Fill LoadOptions and strip the '/' switch symbol in front of each option */ 184 NewLoadOptions = LoadOptions = LoaderBlock->LoadOptions = WinLdrSystemBlock->LoadOptions; 185 RtlStringCbCopyA(LoaderBlock->LoadOptions, sizeof(WinLdrSystemBlock->LoadOptions), Options); 186 187 do 188 { 189 while (*LoadOptions == '/') 190 ++LoadOptions; 191 192 *NewLoadOptions++ = *LoadOptions; 193 } while (*LoadOptions++); 194 195 LoaderBlock->LoadOptions = PaToVa(LoaderBlock->LoadOptions); 196 197 /* ARC devices */ 198 LoaderBlock->ArcDiskInformation = &WinLdrSystemBlock->ArcDiskInformation; 199 InitializeListHead(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead); 200 201 /* Convert ARC disk information from freeldr to a correct format */ 202 for (i = 0; i < reactos_disk_count; i++) 203 { 204 PARC_DISK_SIGNATURE_EX ArcDiskSig; 205 206 /* Allocate the ARC structure */ 207 ArcDiskSig = FrLdrHeapAlloc(sizeof(ARC_DISK_SIGNATURE_EX), 'giSD'); 208 if (!ArcDiskSig) 209 { 210 ERR("Failed to allocate ARC structure! Ignoring remaining ARC disks. (i = %lu, DiskCount = %lu)\n", 211 i, reactos_disk_count); 212 break; 213 } 214 215 /* Copy the data over */ 216 RtlCopyMemory(ArcDiskSig, &reactos_arc_disk_info[i], sizeof(ARC_DISK_SIGNATURE_EX)); 217 218 /* Set the ARC Name pointer */ 219 ArcDiskSig->DiskSignature.ArcName = PaToVa(ArcDiskSig->ArcName); 220 221 /* Insert into the list */ 222 InsertTailList(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead, 223 &ArcDiskSig->DiskSignature.ListEntry); 224 } 225 226 /* Convert all lists to Virtual address */ 227 228 /* Convert the ArcDisks list to virtual address */ 229 List_PaToVa(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead); 230 LoaderBlock->ArcDiskInformation = PaToVa(LoaderBlock->ArcDiskInformation); 231 232 /* Convert configuration entries to VA */ 233 ConvertConfigToVA(LoaderBlock->ConfigurationRoot); 234 LoaderBlock->ConfigurationRoot = PaToVa(LoaderBlock->ConfigurationRoot); 235 236 /* Convert all DTE into virtual addresses */ 237 List_PaToVa(&LoaderBlock->LoadOrderListHead); 238 239 /* This one will be converted right before switching to virtual paging mode */ 240 //List_PaToVa(&LoaderBlock->MemoryDescriptorListHead); 241 242 /* Convert list of boot drivers */ 243 List_PaToVa(&LoaderBlock->BootDriverListHead); 244 245 Extension = LoaderBlock->Extension; 246 247 /* FIXME! HACK value for docking profile */ 248 Extension->Profile.Status = 2; 249 250 /* Check if FreeLdr detected a ACPI table */ 251 if (AcpiPresent) 252 { 253 /* Set the pointer to something for compatibility */ 254 Extension->AcpiTable = (PVOID)1; 255 // FIXME: Extension->AcpiTableSize; 256 } 257 258 #ifdef _M_IX86 259 /* Set headless block pointer */ 260 if (WinLdrTerminalConnected) 261 { 262 Extension->HeadlessLoaderBlock = &WinLdrSystemBlock->HeadlessLoaderBlock; 263 RtlCopyMemory(Extension->HeadlessLoaderBlock, 264 &LoaderRedirectionInformation, 265 sizeof(HEADLESS_LOADER_BLOCK)); 266 Extension->HeadlessLoaderBlock = PaToVa(Extension->HeadlessLoaderBlock); 267 } 268 #endif 269 /* Load drivers database */ 270 RtlStringCbCopyA(MiscFiles, sizeof(MiscFiles), BootPath); 271 RtlStringCbCatA(MiscFiles, sizeof(MiscFiles), "AppPatch\\drvmain.sdb"); 272 Extension->DrvDBImage = PaToVa(WinLdrLoadModule(MiscFiles, 273 &Extension->DrvDBSize, 274 LoaderRegistryData)); 275 276 /* Convert the extension block pointer */ 277 LoaderBlock->Extension = PaToVa(LoaderBlock->Extension); 278 279 TRACE("WinLdrInitializePhase1() completed\n"); 280 } 281 282 static BOOLEAN 283 WinLdrLoadDeviceDriver(PLIST_ENTRY LoadOrderListHead, 284 PCSTR BootPath, 285 PUNICODE_STRING FilePath, 286 ULONG Flags, 287 PLDR_DATA_TABLE_ENTRY *DriverDTE) 288 { 289 CHAR FullPath[1024]; 290 CHAR DriverPath[1024]; 291 CHAR DllName[1024]; 292 PCHAR DriverNamePos; 293 BOOLEAN Success; 294 PVOID DriverBase = NULL; 295 296 // Separate the path to file name and directory path 297 RtlStringCbPrintfA(DriverPath, sizeof(DriverPath), "%wZ", FilePath); 298 DriverNamePos = strrchr(DriverPath, '\\'); 299 if (DriverNamePos != NULL) 300 { 301 // Copy the name 302 RtlStringCbCopyA(DllName, sizeof(DllName), DriverNamePos+1); 303 304 // Cut out the name from the path 305 *(DriverNamePos+1) = ANSI_NULL; 306 } 307 else 308 { 309 // There is no directory in the path 310 RtlStringCbCopyA(DllName, sizeof(DllName), DriverPath); 311 *DriverPath = ANSI_NULL; 312 } 313 314 TRACE("DriverPath: '%s', DllName: '%s', LPB\n", DriverPath, DllName); 315 316 // Check if driver is already loaded 317 Success = PeLdrCheckForLoadedDll(LoadOrderListHead, DllName, DriverDTE); 318 if (Success) 319 { 320 // We've got the pointer to its DTE, just return success 321 return TRUE; 322 } 323 324 // It's not loaded, we have to load it 325 RtlStringCbPrintfA(FullPath, sizeof(FullPath), "%s%wZ", BootPath, FilePath); 326 327 NtLdrOutputLoadMsg(FullPath, NULL); 328 Success = PeLdrLoadImage(FullPath, LoaderBootDriver, &DriverBase); 329 if (!Success) 330 { 331 ERR("PeLdrLoadImage('%s') failed\n", DllName); 332 return FALSE; 333 } 334 335 // Allocate a DTE for it 336 Success = PeLdrAllocateDataTableEntry(LoadOrderListHead, DllName, DllName, DriverBase, DriverDTE); 337 if (!Success) 338 { 339 /* Cleanup and bail out */ 340 ERR("PeLdrAllocateDataTableEntry('%s') failed\n", DllName); 341 MmFreeMemory(DriverBase); 342 return FALSE; 343 } 344 345 // Modify any flags, if needed 346 (*DriverDTE)->Flags |= Flags; 347 348 // Look for any dependencies it may have, and load them too 349 RtlStringCbPrintfA(FullPath, sizeof(FullPath), "%s%s", BootPath, DriverPath); 350 Success = PeLdrScanImportDescriptorTable(LoadOrderListHead, FullPath, *DriverDTE); 351 if (!Success) 352 { 353 /* Cleanup and bail out */ 354 ERR("PeLdrScanImportDescriptorTable('%s') failed\n", FullPath); 355 PeLdrFreeDataTableEntry(*DriverDTE); 356 MmFreeMemory(DriverBase); 357 return FALSE; 358 } 359 360 return TRUE; 361 } 362 363 BOOLEAN 364 WinLdrLoadBootDrivers(PLOADER_PARAMETER_BLOCK LoaderBlock, 365 PCSTR BootPath) 366 { 367 PLIST_ENTRY NextBd; 368 PBOOT_DRIVER_NODE DriverNode; 369 PBOOT_DRIVER_LIST_ENTRY BootDriver; 370 BOOLEAN Success; 371 BOOLEAN ret = TRUE; 372 373 /* Walk through the boot drivers list */ 374 NextBd = LoaderBlock->BootDriverListHead.Flink; 375 while (NextBd != &LoaderBlock->BootDriverListHead) 376 { 377 DriverNode = CONTAINING_RECORD(NextBd, 378 BOOT_DRIVER_NODE, 379 ListEntry.Link); 380 BootDriver = &DriverNode->ListEntry; 381 382 /* Get the next list entry as we may remove the current one on failure */ 383 NextBd = BootDriver->Link.Flink; 384 385 TRACE("BootDriver %wZ DTE %08X RegPath: %wZ\n", 386 &BootDriver->FilePath, BootDriver->LdrEntry, 387 &BootDriver->RegistryPath); 388 389 // Paths are relative (FIXME: Are they always relative?) 390 391 /* Load it */ 392 UiIndicateProgress(); 393 Success = WinLdrLoadDeviceDriver(&LoaderBlock->LoadOrderListHead, 394 BootPath, 395 &BootDriver->FilePath, 396 0, 397 &BootDriver->LdrEntry); 398 if (Success) 399 { 400 /* Convert the addresses to VA since we are not going to use them anymore */ 401 BootDriver->RegistryPath.Buffer = PaToVa(BootDriver->RegistryPath.Buffer); 402 BootDriver->FilePath.Buffer = PaToVa(BootDriver->FilePath.Buffer); 403 BootDriver->LdrEntry = PaToVa(BootDriver->LdrEntry); 404 405 if (DriverNode->Group.Buffer) 406 DriverNode->Group.Buffer = PaToVa(DriverNode->Group.Buffer); 407 DriverNode->Name.Buffer = PaToVa(DriverNode->Name.Buffer); 408 } 409 else 410 { 411 /* Loading failed: cry loudly */ 412 ERR("Cannot load boot driver '%wZ'!\n", &BootDriver->FilePath); 413 UiMessageBox("Cannot load boot driver '%wZ'!", &BootDriver->FilePath); 414 ret = FALSE; 415 416 /* Remove it from the list and try to continue */ 417 RemoveEntryList(&BootDriver->Link); 418 } 419 } 420 421 return ret; 422 } 423 424 PVOID 425 WinLdrLoadModule(PCSTR ModuleName, 426 PULONG Size, 427 TYPE_OF_MEMORY MemoryType) 428 { 429 ULONG FileId; 430 PVOID PhysicalBase; 431 FILEINFORMATION FileInfo; 432 ULONG FileSize; 433 ARC_STATUS Status; 434 ULONG BytesRead; 435 436 *Size = 0; 437 438 /* Open the image file */ 439 NtLdrOutputLoadMsg(ModuleName, NULL); 440 Status = ArcOpen((PSTR)ModuleName, OpenReadOnly, &FileId); 441 if (Status != ESUCCESS) 442 { 443 /* In case of errors, we just return, without complaining to the user */ 444 WARN("Error while opening '%s', Status: %u\n", ModuleName, Status); 445 return NULL; 446 } 447 448 /* Retrieve its size */ 449 Status = ArcGetFileInformation(FileId, &FileInfo); 450 if (Status != ESUCCESS) 451 { 452 ArcClose(FileId); 453 return NULL; 454 } 455 FileSize = FileInfo.EndingAddress.LowPart; 456 *Size = FileSize; 457 458 /* Allocate memory */ 459 PhysicalBase = MmAllocateMemoryWithType(FileSize, MemoryType); 460 if (PhysicalBase == NULL) 461 { 462 ERR("Could not allocate memory for '%s'\n", ModuleName); 463 ArcClose(FileId); 464 return NULL; 465 } 466 467 /* Load the whole file */ 468 Status = ArcRead(FileId, PhysicalBase, FileSize, &BytesRead); 469 ArcClose(FileId); 470 if (Status != ESUCCESS) 471 { 472 WARN("Error while reading '%s', Status: %u\n", ModuleName, Status); 473 return NULL; 474 } 475 476 TRACE("Loaded %s at 0x%x with size 0x%x\n", ModuleName, PhysicalBase, FileSize); 477 478 return PhysicalBase; 479 } 480 481 USHORT 482 WinLdrDetectVersion(VOID) 483 { 484 LONG rc; 485 HKEY hKey; 486 487 rc = RegOpenKey(CurrentControlSetKey, L"Control\\Terminal Server", &hKey); 488 if (rc != ERROR_SUCCESS) 489 { 490 /* Key doesn't exist; assume NT 4.0 */ 491 return _WIN32_WINNT_NT4; 492 } 493 RegCloseKey(hKey); 494 495 /* We may here want to read the value of ProductVersion */ 496 return _WIN32_WINNT_WS03; 497 } 498 499 static 500 PVOID 501 LoadModule( 502 IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, 503 IN PCCH Path, 504 IN PCCH File, 505 IN PCCH ImportName, // BaseDllName 506 IN TYPE_OF_MEMORY MemoryType, 507 OUT PLDR_DATA_TABLE_ENTRY *Dte, 508 IN ULONG Percentage) 509 { 510 BOOLEAN Success; 511 CHAR FullFileName[MAX_PATH]; 512 CHAR ProgressString[256]; 513 PVOID BaseAddress; 514 515 RtlStringCbPrintfA(ProgressString, sizeof(ProgressString), "Loading %s...", File); 516 UiUpdateProgressBar(Percentage, ProgressString); 517 518 RtlStringCbCopyA(FullFileName, sizeof(FullFileName), Path); 519 RtlStringCbCatA(FullFileName, sizeof(FullFileName), File); 520 521 NtLdrOutputLoadMsg(FullFileName, NULL); 522 Success = PeLdrLoadImage(FullFileName, MemoryType, &BaseAddress); 523 if (!Success) 524 { 525 ERR("PeLdrLoadImage('%s') failed\n", File); 526 return NULL; 527 } 528 TRACE("%s loaded successfully at %p\n", File, BaseAddress); 529 530 Success = PeLdrAllocateDataTableEntry(&LoaderBlock->LoadOrderListHead, 531 ImportName, 532 FullFileName, 533 BaseAddress, 534 Dte); 535 if (!Success) 536 { 537 /* Cleanup and bail out */ 538 ERR("PeLdrAllocateDataTableEntry('%s') failed\n", FullFileName); 539 MmFreeMemory(BaseAddress); 540 BaseAddress = NULL; 541 } 542 543 return BaseAddress; 544 } 545 546 #ifdef _M_IX86 547 static 548 BOOLEAN 549 WinLdrIsPaeSupported( 550 _In_ USHORT OperatingSystemVersion, 551 _In_ PLOADER_PARAMETER_BLOCK LoaderBlock, 552 _In_ PCSTR BootOptions, 553 _In_ PCSTR HalFileName, 554 _Inout_updates_bytes_(KernelFileNameSize) _Always_(_Post_z_) 555 PSTR KernelFileName, 556 _In_ SIZE_T KernelFileNameSize) 557 { 558 BOOLEAN PaeEnabled = FALSE; 559 BOOLEAN PaeDisabled = FALSE; 560 BOOLEAN Result; 561 562 if ((OperatingSystemVersion > _WIN32_WINNT_NT4) && 563 NtLdrGetOption(BootOptions, "PAE")) 564 { 565 /* We found the PAE option */ 566 PaeEnabled = TRUE; 567 } 568 569 Result = PaeEnabled; 570 571 if ((OperatingSystemVersion > _WIN32_WINNT_WIN2K) && 572 NtLdrGetOption(BootOptions, "NOPAE")) 573 { 574 PaeDisabled = TRUE; 575 } 576 577 if (SafeBoot) 578 PaeDisabled = TRUE; 579 580 TRACE("PaeEnabled %X, PaeDisabled %X\n", PaeEnabled, PaeDisabled); 581 582 if (PaeDisabled) 583 Result = FALSE; 584 585 /* Enable PAE if DEP is enabled */ 586 if (NoExecuteEnabled) 587 Result = TRUE; 588 589 // TODO: checks for CPU support, hotplug memory support ... other tests 590 // TODO: select kernel name ("ntkrnlpa.exe" or "ntoskrnl.exe"), or, 591 // if KernelFileName is a user-specified kernel file, check whether it 592 // has, if PAE needs to be enabled, the IMAGE_FILE_LARGE_ADDRESS_AWARE 593 // Characteristics bit set, and that the HAL image has a similar support. 594 595 if (Result) UNIMPLEMENTED; 596 597 return Result; 598 } 599 #endif /* _M_IX86 */ 600 601 static 602 BOOLEAN 603 LoadWindowsCore(IN USHORT OperatingSystemVersion, 604 IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, 605 IN PCSTR BootOptions, 606 IN PCSTR BootPath, 607 IN OUT PLDR_DATA_TABLE_ENTRY* KernelDTE) 608 { 609 BOOLEAN Success; 610 PCSTR Option; 611 ULONG OptionLength; 612 PVOID KernelBase, HalBase, KdDllBase = NULL; 613 PLDR_DATA_TABLE_ENTRY HalDTE, KdDllDTE = NULL; 614 CHAR DirPath[MAX_PATH]; 615 CHAR HalFileName[MAX_PATH]; 616 CHAR KernelFileName[MAX_PATH]; 617 CHAR KdDllName[MAX_PATH]; 618 619 if (!KernelDTE) return FALSE; 620 621 /* Initialize SystemRoot\System32 path */ 622 RtlStringCbCopyA(DirPath, sizeof(DirPath), BootPath); 623 RtlStringCbCatA(DirPath, sizeof(DirPath), "system32\\"); 624 625 /* Parse the boot options */ 626 TRACE("LoadWindowsCore: BootOptions '%s'\n", BootOptions); 627 628 #ifdef _M_IX86 629 if (NtLdrGetOption(BootOptions, "3GB")) 630 { 631 /* We found the 3GB option. */ 632 FIXME("LoadWindowsCore: 3GB - TRUE (not implemented)\n"); 633 VirtualBias = TRUE; 634 } 635 // TODO: "USERVA=" for XP/2k3 636 #endif 637 638 if ((OperatingSystemVersion > _WIN32_WINNT_NT4) && 639 (NtLdrGetOption(BootOptions, "SAFEBOOT") || 640 NtLdrGetOption(BootOptions, "SAFEBOOT:"))) 641 { 642 /* We found the SAFEBOOT option. */ 643 FIXME("LoadWindowsCore: SAFEBOOT - TRUE (not implemented)\n"); 644 SafeBoot = TRUE; 645 } 646 647 if ((OperatingSystemVersion > _WIN32_WINNT_WIN2K) && 648 NtLdrGetOption(BootOptions, "BOOTLOGO")) 649 { 650 /* We found the BOOTLOGO option. */ 651 FIXME("LoadWindowsCore: BOOTLOGO - TRUE (not implemented)\n"); 652 BootLogo = TRUE; 653 } 654 655 /* Check the (NO)EXECUTE options */ 656 if ((OperatingSystemVersion > _WIN32_WINNT_WIN2K) && 657 !LoaderBlock->SetupLdrBlock) 658 { 659 /* Disable NX by default on x86, otherwise enable it */ 660 #ifdef _M_IX86 661 NoExecuteEnabled = FALSE; 662 #else 663 NoExecuteEnabled = TRUE; 664 #endif 665 666 #ifdef _M_IX86 667 /* Check the options in decreasing order of precedence */ 668 if (NtLdrGetOption(BootOptions, "NOEXECUTE=OPTIN") || 669 NtLdrGetOption(BootOptions, "NOEXECUTE=OPTOUT") || 670 NtLdrGetOption(BootOptions, "NOEXECUTE=ALWAYSON")) 671 { 672 NoExecuteEnabled = TRUE; 673 } 674 else if (NtLdrGetOption(BootOptions, "NOEXECUTE=ALWAYSOFF")) 675 NoExecuteEnabled = FALSE; 676 else 677 #else 678 /* Only the following two options really apply for x64 and other platforms */ 679 #endif 680 if (NtLdrGetOption(BootOptions, "NOEXECUTE")) 681 NoExecuteEnabled = TRUE; 682 else if (NtLdrGetOption(BootOptions, "EXECUTE")) 683 NoExecuteEnabled = FALSE; 684 685 #ifdef _M_IX86 686 /* Disable DEP in SafeBoot mode for x86 only */ 687 if (SafeBoot) 688 NoExecuteEnabled = FALSE; 689 #endif 690 } 691 TRACE("NoExecuteEnabled %X\n", NoExecuteEnabled); 692 693 /* 694 * Select the HAL and KERNEL file names. 695 * Check for any "/HAL=" or "/KERNEL=" override option. 696 * 697 * See the following links to know how the file names are actually chosen: 698 * https://www.geoffchappell.com/notes/windows/boot/bcd/osloader/detecthal.htm 699 * https://www.geoffchappell.com/notes/windows/boot/bcd/osloader/hal.htm 700 * https://www.geoffchappell.com/notes/windows/boot/bcd/osloader/kernel.htm 701 */ 702 /* Default HAL and KERNEL file names */ 703 RtlStringCbCopyA(HalFileName , sizeof(HalFileName) , "hal.dll"); 704 RtlStringCbCopyA(KernelFileName, sizeof(KernelFileName), "ntoskrnl.exe"); 705 706 Option = NtLdrGetOptionEx(BootOptions, "HAL=", &OptionLength); 707 if (Option && (OptionLength > 4)) 708 { 709 /* Retrieve the HAL file name */ 710 Option += 4; OptionLength -= 4; 711 RtlStringCbCopyNA(HalFileName, sizeof(HalFileName), Option, OptionLength); 712 _strlwr(HalFileName); 713 } 714 715 Option = NtLdrGetOptionEx(BootOptions, "KERNEL=", &OptionLength); 716 if (Option && (OptionLength > 7)) 717 { 718 /* Retrieve the KERNEL file name */ 719 Option += 7; OptionLength -= 7; 720 RtlStringCbCopyNA(KernelFileName, sizeof(KernelFileName), Option, OptionLength); 721 _strlwr(KernelFileName); 722 } 723 724 #ifdef _M_IX86 725 /* Check for PAE support and select the adequate kernel image */ 726 PaeModeOn = WinLdrIsPaeSupported(OperatingSystemVersion, 727 LoaderBlock, 728 BootOptions, 729 HalFileName, 730 KernelFileName, 731 sizeof(KernelFileName)); 732 if (PaeModeOn) FIXME("WinLdrIsPaeSupported: PaeModeOn\n"); 733 #endif 734 735 TRACE("HAL file = '%s' ; Kernel file = '%s'\n", HalFileName, KernelFileName); 736 737 /* 738 * Load the core NT files: Kernel, HAL and KD transport DLL. 739 * Cheat about their base DLL name so as to satisfy the imports/exports, 740 * even if the corresponding underlying files do not have the same names 741 * -- this happens e.g. with UP vs. MP kernel, standard vs. ACPI hal, or 742 * different KD transport DLLs. 743 */ 744 745 /* Load the Kernel */ 746 KernelBase = LoadModule(LoaderBlock, DirPath, KernelFileName, 747 "ntoskrnl.exe", LoaderSystemCode, KernelDTE, 30); 748 if (!KernelBase) 749 { 750 ERR("LoadModule('%s') failed\n", KernelFileName); 751 UiMessageBox("Could not load %s", KernelFileName); 752 return FALSE; 753 } 754 755 /* Load the HAL */ 756 HalBase = LoadModule(LoaderBlock, DirPath, HalFileName, 757 "hal.dll", LoaderHalCode, &HalDTE, 35); 758 if (!HalBase) 759 { 760 ERR("LoadModule('%s') failed\n", HalFileName); 761 UiMessageBox("Could not load %s", HalFileName); 762 PeLdrFreeDataTableEntry(*KernelDTE); 763 MmFreeMemory(KernelBase); 764 return FALSE; 765 } 766 767 /* Load the Kernel Debugger Transport DLL */ 768 if (OperatingSystemVersion > _WIN32_WINNT_WIN2K) 769 { 770 /* 771 * According to http://www.nynaeve.net/?p=173 : 772 * "[...] Another enhancement that could be done Microsoft-side would be 773 * a better interface for replacing KD transport modules. Right now, due 774 * to the fact that ntoskrnl is static linked to KDCOM.DLL, the OS loader 775 * has a hardcoded hack that interprets the KD type in the OS loader options, 776 * loads one of the (hardcoded filenames) "kdcom.dll", "kd1394.dll", or 777 * "kdusb2.dll" modules, and inserts them into the loaded module list under 778 * the name "kdcom.dll". [...]" 779 */ 780 781 /* 782 * A Kernel Debugger Transport DLL is always loaded for Windows XP+ : 783 * either the standard KDCOM.DLL (by default): IsCustomKdDll == FALSE 784 * or an alternative user-provided one via the /DEBUGPORT= option: 785 * IsCustomKdDll == TRUE if it does not specify the default KDCOM. 786 */ 787 BOOLEAN IsCustomKdDll = FALSE; 788 789 /* Check whether there is a DEBUGPORT option */ 790 Option = NtLdrGetOptionEx(BootOptions, "DEBUGPORT=", &OptionLength); 791 if (Option && (OptionLength > 10)) 792 { 793 /* Move to the debug port name */ 794 Option += 10; OptionLength -= 10; 795 796 /* 797 * Parse the port name. 798 * Format: /DEBUGPORT=COM[0-9] 799 * or: /DEBUGPORT=FILE:\Device\HarddiskX\PartitionY\debug.log 800 * or: /DEBUGPORT=FOO 801 * If we only have /DEBUGPORT= (i.e. without any port name), 802 * default to "COM". 803 */ 804 805 /* Get the actual length of the debug port 806 * until the next whitespace or colon. */ 807 OptionLength = (ULONG)strcspn(Option, " \t:"); 808 809 if ((OptionLength == 0) || 810 ( (OptionLength >= 3) && (_strnicmp(Option, "COM", 3) == 0) && 811 ((OptionLength == 3) || ('0' <= Option[3] && Option[3] <= '9')) )) 812 { 813 /* The standard KDCOM.DLL is used */ 814 } 815 else 816 { 817 /* A custom KD DLL is used */ 818 IsCustomKdDll = TRUE; 819 } 820 } 821 if (!IsCustomKdDll) 822 { 823 Option = "COM"; OptionLength = 3; 824 } 825 826 RtlStringCbPrintfA(KdDllName, sizeof(KdDllName), "kd%.*s.dll", 827 OptionLength, Option); 828 _strlwr(KdDllName); 829 830 /* Load the KD DLL. Override its base DLL name to the default "KDCOM.DLL". */ 831 KdDllBase = LoadModule(LoaderBlock, DirPath, KdDllName, 832 "kdcom.dll", LoaderSystemCode, &KdDllDTE, 40); 833 if (!KdDllBase) 834 { 835 /* If we failed to load a custom KD DLL, fall back to the standard one */ 836 if (IsCustomKdDll) 837 { 838 /* The custom KD DLL being optional, just ignore the failure */ 839 WARN("LoadModule('%s') failed\n", KdDllName); 840 841 IsCustomKdDll = FALSE; 842 RtlStringCbCopyA(KdDllName, sizeof(KdDllName), "kdcom.dll"); 843 844 KdDllBase = LoadModule(LoaderBlock, DirPath, KdDllName, 845 "kdcom.dll", LoaderSystemCode, &KdDllDTE, 40); 846 } 847 848 if (!KdDllBase) 849 { 850 /* Ignore the failure; we will fail later when scanning the 851 * kernel import tables, if it really needs the KD DLL. */ 852 ERR("LoadModule('%s') failed\n", KdDllName); 853 } 854 } 855 } 856 857 /* Load all referenced DLLs for Kernel, HAL and Kernel Debugger Transport DLL */ 858 Success = PeLdrScanImportDescriptorTable(&LoaderBlock->LoadOrderListHead, DirPath, *KernelDTE); 859 if (!Success) 860 { 861 UiMessageBox("Could not load %s", KernelFileName); 862 goto Quit; 863 } 864 Success = PeLdrScanImportDescriptorTable(&LoaderBlock->LoadOrderListHead, DirPath, HalDTE); 865 if (!Success) 866 { 867 UiMessageBox("Could not load %s", HalFileName); 868 goto Quit; 869 } 870 if (KdDllDTE) 871 { 872 Success = PeLdrScanImportDescriptorTable(&LoaderBlock->LoadOrderListHead, DirPath, KdDllDTE); 873 if (!Success) 874 { 875 UiMessageBox("Could not load %s", KdDllName); 876 goto Quit; 877 } 878 } 879 880 Quit: 881 if (!Success) 882 { 883 /* Cleanup and bail out */ 884 if (KdDllDTE) 885 PeLdrFreeDataTableEntry(KdDllDTE); 886 if (KdDllBase) // Optional 887 MmFreeMemory(KdDllBase); 888 889 PeLdrFreeDataTableEntry(HalDTE); 890 MmFreeMemory(HalBase); 891 892 PeLdrFreeDataTableEntry(*KernelDTE); 893 MmFreeMemory(KernelBase); 894 } 895 896 return Success; 897 } 898 899 static 900 BOOLEAN 901 WinLdrInitErrataInf( 902 IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, 903 IN USHORT OperatingSystemVersion, 904 IN PCSTR SystemRoot) 905 { 906 LONG rc; 907 HKEY hKey; 908 ULONG BufferSize; 909 ULONG FileSize; 910 PVOID PhysicalBase; 911 WCHAR szFileName[80]; 912 CHAR ErrataFilePath[MAX_PATH]; 913 914 /* Open either the 'BiosInfo' (Windows <= 2003) or the 'Errata' (Vista+) key */ 915 if (OperatingSystemVersion >= _WIN32_WINNT_VISTA) 916 { 917 rc = RegOpenKey(CurrentControlSetKey, L"Control\\Errata", &hKey); 918 } 919 else // (OperatingSystemVersion <= _WIN32_WINNT_WS03) 920 { 921 rc = RegOpenKey(CurrentControlSetKey, L"Control\\BiosInfo", &hKey); 922 } 923 if (rc != ERROR_SUCCESS) 924 { 925 WARN("Could not open the BiosInfo/Errata registry key (Error %u)\n", (int)rc); 926 return FALSE; 927 } 928 929 /* Retrieve the INF file name value */ 930 BufferSize = sizeof(szFileName); 931 rc = RegQueryValue(hKey, L"InfName", NULL, (PUCHAR)szFileName, &BufferSize); 932 if (rc != ERROR_SUCCESS) 933 { 934 WARN("Could not retrieve the InfName value (Error %u)\n", (int)rc); 935 RegCloseKey(hKey); 936 return FALSE; 937 } 938 939 // TODO: "SystemBiosDate" 940 941 RegCloseKey(hKey); 942 943 RtlStringCbPrintfA(ErrataFilePath, sizeof(ErrataFilePath), "%s%s%S", 944 SystemRoot, "inf\\", szFileName); 945 946 /* Load the INF file */ 947 PhysicalBase = WinLdrLoadModule(ErrataFilePath, &FileSize, LoaderRegistryData); 948 if (!PhysicalBase) 949 { 950 WARN("Could not load '%s'\n", ErrataFilePath); 951 return FALSE; 952 } 953 954 LoaderBlock->Extension->EmInfFileImage = PaToVa(PhysicalBase); 955 LoaderBlock->Extension->EmInfFileSize = FileSize; 956 957 return TRUE; 958 } 959 960 ARC_STATUS 961 LoadAndBootWindows( 962 IN ULONG Argc, 963 IN PCHAR Argv[], 964 IN PCHAR Envp[]) 965 { 966 ARC_STATUS Status; 967 PCSTR ArgValue; 968 PCSTR SystemPartition; 969 PCSTR FileName; 970 ULONG FileNameLength; 971 BOOLEAN Success; 972 USHORT OperatingSystemVersion; 973 PLOADER_PARAMETER_BLOCK LoaderBlock; 974 CHAR BootPath[MAX_PATH]; 975 CHAR FilePath[MAX_PATH]; 976 CHAR BootOptions[256]; 977 978 /* Retrieve the (mandatory) boot type */ 979 ArgValue = GetArgumentValue(Argc, Argv, "BootType"); 980 if (!ArgValue || !*ArgValue) 981 { 982 ERR("No 'BootType' value, aborting!\n"); 983 return EINVAL; 984 } 985 986 /* Convert it to an OS version */ 987 if (_stricmp(ArgValue, "Windows") == 0 || 988 _stricmp(ArgValue, "Windows2003") == 0) 989 { 990 OperatingSystemVersion = _WIN32_WINNT_WS03; 991 } 992 else if (_stricmp(ArgValue, "WindowsNT40") == 0) 993 { 994 OperatingSystemVersion = _WIN32_WINNT_NT4; 995 } 996 else 997 { 998 ERR("Unknown 'BootType' value '%s', aborting!\n", ArgValue); 999 return EINVAL; 1000 } 1001 1002 /* Retrieve the (mandatory) system partition */ 1003 SystemPartition = GetArgumentValue(Argc, Argv, "SystemPartition"); 1004 if (!SystemPartition || !*SystemPartition) 1005 { 1006 ERR("No 'SystemPartition' specified, aborting!\n"); 1007 return EINVAL; 1008 } 1009 1010 /* Let the user know we started loading */ 1011 UiDrawBackdrop(); 1012 UiDrawStatusText("Loading..."); 1013 UiDrawProgressBarCenter("Loading NT..."); 1014 1015 /* Retrieve the system path */ 1016 *BootPath = ANSI_NULL; 1017 ArgValue = GetArgumentValue(Argc, Argv, "SystemPath"); 1018 if (ArgValue) 1019 RtlStringCbCopyA(BootPath, sizeof(BootPath), ArgValue); 1020 1021 /* 1022 * Check whether BootPath is a full path 1023 * and if not, create a full boot path. 1024 * 1025 * See FsOpenFile for the technique used. 1026 */ 1027 if (strrchr(BootPath, ')') == NULL) 1028 { 1029 /* Temporarily save the boot path */ 1030 RtlStringCbCopyA(FilePath, sizeof(FilePath), BootPath); 1031 1032 /* This is not a full path: prepend the SystemPartition */ 1033 RtlStringCbCopyA(BootPath, sizeof(BootPath), SystemPartition); 1034 1035 /* Append a path separator if needed */ 1036 if (*FilePath != '\\' && *FilePath != '/') 1037 RtlStringCbCatA(BootPath, sizeof(BootPath), "\\"); 1038 1039 /* Append the remaining path */ 1040 RtlStringCbCatA(BootPath, sizeof(BootPath), FilePath); 1041 } 1042 1043 /* Append a path separator if needed */ 1044 if (!*BootPath || BootPath[strlen(BootPath) - 1] != '\\') 1045 RtlStringCbCatA(BootPath, sizeof(BootPath), "\\"); 1046 1047 TRACE("BootPath: '%s'\n", BootPath); 1048 1049 /* Retrieve the boot options */ 1050 *BootOptions = ANSI_NULL; 1051 ArgValue = GetArgumentValue(Argc, Argv, "Options"); 1052 if (ArgValue && *ArgValue) 1053 RtlStringCbCopyA(BootOptions, sizeof(BootOptions), ArgValue); 1054 1055 /* Append boot-time options */ 1056 AppendBootTimeOptions(BootOptions); 1057 1058 /* 1059 * Set the "/HAL=" and "/KERNEL=" options if needed. 1060 * If already present on the standard "Options=" option line, they take 1061 * precedence over those passed via the separate "Hal=" and "Kernel=" 1062 * options. 1063 */ 1064 if (!NtLdrGetOption(BootOptions, "HAL=")) 1065 { 1066 /* 1067 * Not found in the options, try to retrieve the 1068 * separate value and append it to the options. 1069 */ 1070 ArgValue = GetArgumentValue(Argc, Argv, "Hal"); 1071 if (ArgValue && *ArgValue) 1072 { 1073 RtlStringCbCatA(BootOptions, sizeof(BootOptions), " /HAL="); 1074 RtlStringCbCatA(BootOptions, sizeof(BootOptions), ArgValue); 1075 } 1076 } 1077 if (!NtLdrGetOption(BootOptions, "KERNEL=")) 1078 { 1079 /* 1080 * Not found in the options, try to retrieve the 1081 * separate value and append it to the options. 1082 */ 1083 ArgValue = GetArgumentValue(Argc, Argv, "Kernel"); 1084 if (ArgValue && *ArgValue) 1085 { 1086 RtlStringCbCatA(BootOptions, sizeof(BootOptions), " /KERNEL="); 1087 RtlStringCbCatA(BootOptions, sizeof(BootOptions), ArgValue); 1088 } 1089 } 1090 1091 TRACE("BootOptions: '%s'\n", BootOptions); 1092 1093 /* Check if a RAM disk file was given */ 1094 FileName = NtLdrGetOptionEx(BootOptions, "RDPATH=", &FileNameLength); 1095 if (FileName && (FileNameLength > 7)) 1096 { 1097 /* Load the RAM disk */ 1098 Status = RamDiskInitialize(FALSE, BootOptions, SystemPartition); 1099 if (Status != ESUCCESS) 1100 { 1101 FileName += 7; FileNameLength -= 7; 1102 UiMessageBox("Failed to load RAM disk file '%.*s'", 1103 FileNameLength, FileName); 1104 return Status; 1105 } 1106 } 1107 1108 /* Handle the SOS option */ 1109 SosEnabled = !!NtLdrGetOption(BootOptions, "SOS"); 1110 if (SosEnabled) 1111 UiResetForSOS(); 1112 1113 /* Allocate and minimally-initialize the Loader Parameter Block */ 1114 AllocateAndInitLPB(OperatingSystemVersion, &LoaderBlock); 1115 1116 /* Load the system hive */ 1117 UiUpdateProgressBar(15, "Loading system hive..."); 1118 Success = WinLdrInitSystemHive(LoaderBlock, BootPath, FALSE); 1119 TRACE("SYSTEM hive %s\n", (Success ? "loaded" : "not loaded")); 1120 /* Bail out if failure */ 1121 if (!Success) 1122 return ENOEXEC; 1123 1124 /* Fixup the version number using data from the registry */ 1125 if (OperatingSystemVersion == 0) 1126 OperatingSystemVersion = WinLdrDetectVersion(); 1127 LoaderBlock->Extension->MajorVersion = (OperatingSystemVersion & 0xFF00) >> 8; 1128 LoaderBlock->Extension->MinorVersion = (OperatingSystemVersion & 0xFF); 1129 1130 /* Load NLS data, OEM font, and prepare boot drivers list */ 1131 Success = WinLdrScanSystemHive(LoaderBlock, BootPath); 1132 TRACE("SYSTEM hive %s\n", (Success ? "scanned" : "not scanned")); 1133 /* Bail out if failure */ 1134 if (!Success) 1135 return ENOEXEC; 1136 1137 /* Load the Firmware Errata file */ 1138 Success = WinLdrInitErrataInf(LoaderBlock, OperatingSystemVersion, BootPath); 1139 TRACE("Firmware Errata file %s\n", (Success ? "loaded" : "not loaded")); 1140 /* Not necessarily fatal if not found - carry on going */ 1141 1142 /* Finish loading */ 1143 return LoadAndBootWindowsCommon(OperatingSystemVersion, 1144 LoaderBlock, 1145 BootOptions, 1146 BootPath); 1147 } 1148 1149 ARC_STATUS 1150 LoadAndBootWindowsCommon( 1151 IN USHORT OperatingSystemVersion, 1152 IN PLOADER_PARAMETER_BLOCK LoaderBlock, 1153 IN PCSTR BootOptions, 1154 IN PCSTR BootPath) 1155 { 1156 PLOADER_PARAMETER_BLOCK LoaderBlockVA; 1157 BOOLEAN Success; 1158 PLDR_DATA_TABLE_ENTRY KernelDTE; 1159 KERNEL_ENTRY_POINT KiSystemStartup; 1160 PCSTR SystemRoot; 1161 1162 TRACE("LoadAndBootWindowsCommon()\n"); 1163 1164 ASSERT(OperatingSystemVersion != 0); 1165 1166 #ifdef _M_IX86 1167 /* Setup redirection support */ 1168 WinLdrSetupEms(BootOptions); 1169 #endif 1170 1171 /* Convert BootPath to SystemRoot */ 1172 SystemRoot = strstr(BootPath, "\\"); 1173 1174 /* Detect hardware */ 1175 UiUpdateProgressBar(20, "Detecting hardware..."); 1176 LoaderBlock->ConfigurationRoot = MachHwDetect(); 1177 1178 /* Initialize the PE loader import-DLL callback, so that we can obtain 1179 * feedback (for example during SOS) on the PE images that get loaded. */ 1180 PeLdrImportDllLoadCallback = NtLdrImportDllLoadCallback; 1181 1182 /* Load the operating system core: the Kernel, the HAL and the Kernel Debugger Transport DLL */ 1183 Success = LoadWindowsCore(OperatingSystemVersion, 1184 LoaderBlock, 1185 BootOptions, 1186 BootPath, 1187 &KernelDTE); 1188 if (!Success) 1189 { 1190 /* Reset the PE loader import-DLL callback */ 1191 PeLdrImportDllLoadCallback = NULL; 1192 1193 UiMessageBox("Error loading NTOS core."); 1194 return ENOEXEC; 1195 } 1196 1197 /* Cleanup INI file */ 1198 IniCleanup(); 1199 1200 /**** 1201 **** WE HAVE NOW REACHED THE POINT OF NO RETURN !! 1202 ****/ 1203 1204 UiSetProgressBarSubset(40, 90); // NTOS goes from 25 to 75% 1205 1206 /* Load boot drivers */ 1207 UiSetProgressBarText("Loading boot drivers..."); 1208 Success = WinLdrLoadBootDrivers(LoaderBlock, BootPath); 1209 TRACE("Boot drivers loading %s\n", Success ? "successful" : "failed"); 1210 1211 UiSetProgressBarSubset(0, 100); 1212 1213 /* Reset the PE loader import-DLL callback */ 1214 PeLdrImportDllLoadCallback = NULL; 1215 1216 /* Initialize Phase 1 - no drivers loading anymore */ 1217 WinLdrInitializePhase1(LoaderBlock, 1218 BootOptions, 1219 SystemRoot, 1220 BootPath, 1221 OperatingSystemVersion); 1222 1223 UiUpdateProgressBar(100, NULL); 1224 1225 /* Save entry-point pointer and Loader block VAs */ 1226 KiSystemStartup = (KERNEL_ENTRY_POINT)KernelDTE->EntryPoint; 1227 LoaderBlockVA = PaToVa(LoaderBlock); 1228 1229 /* "Stop all motors", change videomode */ 1230 MachPrepareForReactOS(); 1231 1232 /* Debugging... */ 1233 //DumpMemoryAllocMap(); 1234 1235 /* Do the machine specific initialization */ 1236 WinLdrSetupMachineDependent(LoaderBlock); 1237 1238 /* Map pages and create memory descriptors */ 1239 WinLdrSetupMemoryLayout(LoaderBlock); 1240 1241 /* Set processor context */ 1242 WinLdrSetProcessorContext(); 1243 1244 /* Save final value of LoaderPagesSpanned */ 1245 LoaderBlock->Extension->LoaderPagesSpanned = LoaderPagesSpanned; 1246 1247 TRACE("Hello from paged mode, KiSystemStartup %p, LoaderBlockVA %p!\n", 1248 KiSystemStartup, LoaderBlockVA); 1249 1250 /* Zero KI_USER_SHARED_DATA page */ 1251 RtlZeroMemory((PVOID)KI_USER_SHARED_DATA, MM_PAGE_SIZE); 1252 1253 WinLdrpDumpMemoryDescriptors(LoaderBlockVA); 1254 WinLdrpDumpBootDriver(LoaderBlockVA); 1255 #ifndef _M_AMD64 1256 WinLdrpDumpArcDisks(LoaderBlockVA); 1257 #endif 1258 1259 /* Pass control */ 1260 (*KiSystemStartup)(LoaderBlockVA); 1261 1262 UNREACHABLE; // return ESUCCESS; 1263 } 1264 1265 VOID 1266 WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock) 1267 { 1268 PLIST_ENTRY NextMd; 1269 PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor; 1270 1271 NextMd = LoaderBlock->MemoryDescriptorListHead.Flink; 1272 1273 while (NextMd != &LoaderBlock->MemoryDescriptorListHead) 1274 { 1275 MemoryDescriptor = CONTAINING_RECORD(NextMd, MEMORY_ALLOCATION_DESCRIPTOR, ListEntry); 1276 1277 TRACE("BP %08X PC %04X MT %d\n", MemoryDescriptor->BasePage, 1278 MemoryDescriptor->PageCount, MemoryDescriptor->MemoryType); 1279 1280 NextMd = MemoryDescriptor->ListEntry.Flink; 1281 } 1282 } 1283 1284 VOID 1285 WinLdrpDumpBootDriver(PLOADER_PARAMETER_BLOCK LoaderBlock) 1286 { 1287 PLIST_ENTRY NextBd; 1288 PBOOT_DRIVER_LIST_ENTRY BootDriver; 1289 1290 NextBd = LoaderBlock->BootDriverListHead.Flink; 1291 1292 while (NextBd != &LoaderBlock->BootDriverListHead) 1293 { 1294 BootDriver = CONTAINING_RECORD(NextBd, BOOT_DRIVER_LIST_ENTRY, Link); 1295 1296 TRACE("BootDriver %wZ DTE %08X RegPath: %wZ\n", &BootDriver->FilePath, 1297 BootDriver->LdrEntry, &BootDriver->RegistryPath); 1298 1299 NextBd = BootDriver->Link.Flink; 1300 } 1301 } 1302 1303 VOID 1304 WinLdrpDumpArcDisks(PLOADER_PARAMETER_BLOCK LoaderBlock) 1305 { 1306 PLIST_ENTRY NextBd; 1307 PARC_DISK_SIGNATURE ArcDisk; 1308 1309 NextBd = LoaderBlock->ArcDiskInformation->DiskSignatureListHead.Flink; 1310 1311 while (NextBd != &LoaderBlock->ArcDiskInformation->DiskSignatureListHead) 1312 { 1313 ArcDisk = CONTAINING_RECORD(NextBd, ARC_DISK_SIGNATURE, ListEntry); 1314 1315 TRACE("ArcDisk %s checksum: 0x%X, signature: 0x%X\n", 1316 ArcDisk->ArcName, ArcDisk->CheckSum, ArcDisk->Signature); 1317 1318 NextBd = ArcDisk->ListEntry.Flink; 1319 } 1320 } 1321