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