1 /* 2 * FreeLoader 3 * 4 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com> 5 * Copyright (C) 2006 Aleksey Bragin <aleksey@reactos.org> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License along 18 * with this program; if not, write to the Free Software Foundation, Inc., 19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 20 */ 21 22 #include <freeldr.h> 23 #include "registry.h" 24 25 #include <ndk/ldrtypes.h> 26 27 #include <debug.h> 28 DBG_DEFAULT_CHANNEL(WINDOWS); 29 30 // FIXME: Find a better way to retrieve ARC disk information 31 extern ULONG reactos_disk_count; 32 extern ARC_DISK_SIGNATURE_EX reactos_arc_disk_info[]; 33 34 extern ULONG LoaderPagesSpanned; 35 extern BOOLEAN AcpiPresent; 36 37 extern HEADLESS_LOADER_BLOCK LoaderRedirectionInformation; 38 extern BOOLEAN WinLdrTerminalConnected; 39 extern void WinLdrSetupEms(IN PCHAR BootOptions); 40 41 PLOADER_SYSTEM_BLOCK WinLdrSystemBlock; 42 43 // debug stuff 44 VOID DumpMemoryAllocMap(VOID); 45 46 // Init "phase 0" 47 VOID 48 AllocateAndInitLPB(PLOADER_PARAMETER_BLOCK *OutLoaderBlock) 49 { 50 PLOADER_PARAMETER_BLOCK LoaderBlock; 51 52 /* Allocate and zero-init the LPB */ 53 WinLdrSystemBlock = MmAllocateMemoryWithType(sizeof(LOADER_SYSTEM_BLOCK), 54 LoaderSystemBlock); 55 if (WinLdrSystemBlock == NULL) 56 { 57 UiMessageBox("Failed to allocate memory for system block!"); 58 return; 59 } 60 61 RtlZeroMemory(WinLdrSystemBlock, sizeof(LOADER_SYSTEM_BLOCK)); 62 63 LoaderBlock = &WinLdrSystemBlock->LoaderBlock; 64 LoaderBlock->NlsData = &WinLdrSystemBlock->NlsDataBlock; 65 66 /* Init three critical lists, used right away */ 67 InitializeListHead(&LoaderBlock->LoadOrderListHead); 68 InitializeListHead(&LoaderBlock->MemoryDescriptorListHead); 69 InitializeListHead(&LoaderBlock->BootDriverListHead); 70 71 *OutLoaderBlock = LoaderBlock; 72 } 73 74 // Init "phase 1" 75 VOID 76 WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock, 77 LPCSTR Options, 78 LPCSTR SystemRoot, 79 LPCSTR BootPath, 80 USHORT VersionToBoot) 81 { 82 /* Examples of correct options and paths */ 83 //CHAR Options[] = "/DEBUGPORT=COM1 /BAUDRATE=115200"; 84 //CHAR Options[] = "/NODEBUG"; 85 //CHAR SystemRoot[] = "\\WINNT\\"; 86 //CHAR ArcBoot[] = "multi(0)disk(0)rdisk(0)partition(1)"; 87 88 LPSTR LoadOptions, NewLoadOptions; 89 CHAR HalPath[] = "\\"; 90 CHAR ArcBoot[256]; 91 CHAR MiscFiles[256]; 92 ULONG i; 93 ULONG_PTR PathSeparator; 94 PLOADER_PARAMETER_EXTENSION Extension; 95 96 /* Construct SystemRoot and ArcBoot from SystemPath */ 97 PathSeparator = strstr(BootPath, "\\") - BootPath; 98 strncpy(ArcBoot, BootPath, PathSeparator); 99 ArcBoot[PathSeparator] = ANSI_NULL; 100 101 TRACE("ArcBoot: %s\n", ArcBoot); 102 TRACE("SystemRoot: %s\n", SystemRoot); 103 TRACE("Options: %s\n", Options); 104 105 /* Fill Arc BootDevice */ 106 LoaderBlock->ArcBootDeviceName = WinLdrSystemBlock->ArcBootDeviceName; 107 strncpy(LoaderBlock->ArcBootDeviceName, ArcBoot, MAX_PATH); 108 LoaderBlock->ArcBootDeviceName = PaToVa(LoaderBlock->ArcBootDeviceName); 109 110 /* Fill Arc HalDevice, it matches ArcBoot path */ 111 LoaderBlock->ArcHalDeviceName = WinLdrSystemBlock->ArcBootDeviceName; 112 LoaderBlock->ArcHalDeviceName = PaToVa(LoaderBlock->ArcHalDeviceName); 113 114 /* Fill SystemRoot */ 115 LoaderBlock->NtBootPathName = WinLdrSystemBlock->NtBootPathName; 116 strncpy(LoaderBlock->NtBootPathName, SystemRoot, MAX_PATH); 117 LoaderBlock->NtBootPathName = PaToVa(LoaderBlock->NtBootPathName); 118 119 /* Fill NtHalPathName */ 120 LoaderBlock->NtHalPathName = WinLdrSystemBlock->NtHalPathName; 121 strncpy(LoaderBlock->NtHalPathName, HalPath, MAX_PATH); 122 LoaderBlock->NtHalPathName = PaToVa(LoaderBlock->NtHalPathName); 123 124 /* Fill LoadOptions and strip the '/' commutator symbol in front of each option */ 125 NewLoadOptions = LoadOptions = LoaderBlock->LoadOptions = WinLdrSystemBlock->LoadOptions; 126 strncpy(LoaderBlock->LoadOptions, Options, MAX_OPTIONS_LENGTH); 127 128 do 129 { 130 while (*LoadOptions == '/') 131 ++LoadOptions; 132 133 *NewLoadOptions++ = *LoadOptions; 134 } while (*LoadOptions++); 135 136 LoaderBlock->LoadOptions = PaToVa(LoaderBlock->LoadOptions); 137 138 /* Arc devices */ 139 LoaderBlock->ArcDiskInformation = &WinLdrSystemBlock->ArcDiskInformation; 140 InitializeListHead(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead); 141 142 /* Convert ARC disk information from freeldr to a correct format */ 143 for (i = 0; i < reactos_disk_count; i++) 144 { 145 PARC_DISK_SIGNATURE_EX ArcDiskSig; 146 147 /* Allocate the ARC structure */ 148 ArcDiskSig = FrLdrHeapAlloc(sizeof(ARC_DISK_SIGNATURE_EX), 'giSD'); 149 150 /* Copy the data over */ 151 RtlCopyMemory(ArcDiskSig, &reactos_arc_disk_info[i], sizeof(ARC_DISK_SIGNATURE_EX)); 152 153 /* Set the ARC Name pointer and mark the partition table as valid */ 154 ArcDiskSig->DiskSignature.ArcName = PaToVa(ArcDiskSig->ArcName); 155 ArcDiskSig->DiskSignature.ValidPartitionTable = TRUE; 156 157 /* Insert into the list */ 158 InsertTailList(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead, 159 &ArcDiskSig->DiskSignature.ListEntry); 160 } 161 162 /* Convert all list's to Virtual address */ 163 164 /* Convert the ArcDisks list to virtual address */ 165 List_PaToVa(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead); 166 LoaderBlock->ArcDiskInformation = PaToVa(LoaderBlock->ArcDiskInformation); 167 168 /* Convert configuration entries to VA */ 169 ConvertConfigToVA(LoaderBlock->ConfigurationRoot); 170 LoaderBlock->ConfigurationRoot = PaToVa(LoaderBlock->ConfigurationRoot); 171 172 /* Convert all DTE into virtual addresses */ 173 List_PaToVa(&LoaderBlock->LoadOrderListHead); 174 175 /* This one will be converted right before switching to virtual paging mode */ 176 //List_PaToVa(&LoaderBlock->MemoryDescriptorListHead); 177 178 /* Convert list of boot drivers */ 179 List_PaToVa(&LoaderBlock->BootDriverListHead); 180 181 /* Initialize Extension now */ 182 Extension = &WinLdrSystemBlock->Extension; 183 Extension->Size = sizeof(LOADER_PARAMETER_EXTENSION); 184 Extension->MajorVersion = (VersionToBoot & 0xFF00) >> 8; 185 Extension->MinorVersion = VersionToBoot & 0xFF; 186 Extension->Profile.Status = 2; 187 188 /* Check if FreeLdr detected a ACPI table */ 189 if (AcpiPresent) 190 { 191 /* Set the pointer to something for compatibility */ 192 Extension->AcpiTable = (PVOID)1; 193 // FIXME: Extension->AcpiTableSize; 194 } 195 196 #ifdef _M_IX86 197 /* Set headless block pointer */ 198 if (WinLdrTerminalConnected) 199 { 200 Extension->HeadlessLoaderBlock = &WinLdrSystemBlock->HeadlessLoaderBlock; 201 RtlCopyMemory(Extension->HeadlessLoaderBlock, 202 &LoaderRedirectionInformation, 203 sizeof(HEADLESS_LOADER_BLOCK)); 204 Extension->HeadlessLoaderBlock = PaToVa(Extension->HeadlessLoaderBlock); 205 } 206 #endif 207 /* Load drivers database */ 208 strcpy(MiscFiles, BootPath); 209 strcat(MiscFiles, "AppPatch\\drvmain.sdb"); 210 Extension->DrvDBImage = PaToVa(WinLdrLoadModule(MiscFiles, 211 &Extension->DrvDBSize, 212 LoaderRegistryData)); 213 214 /* Convert extension and setup block pointers */ 215 LoaderBlock->Extension = PaToVa(Extension); 216 217 if (LoaderBlock->SetupLdrBlock) 218 LoaderBlock->SetupLdrBlock = PaToVa(LoaderBlock->SetupLdrBlock); 219 220 TRACE("WinLdrInitializePhase1() completed\n"); 221 } 222 223 static BOOLEAN 224 WinLdrLoadDeviceDriver(PLIST_ENTRY LoadOrderListHead, 225 LPCSTR BootPath, 226 PUNICODE_STRING FilePath, 227 ULONG Flags, 228 PLDR_DATA_TABLE_ENTRY *DriverDTE) 229 { 230 CHAR FullPath[1024]; 231 CHAR DriverPath[1024]; 232 CHAR DllName[1024]; 233 PCHAR DriverNamePos; 234 BOOLEAN Success; 235 PVOID DriverBase = NULL; 236 237 // Separate the path to file name and directory path 238 _snprintf(DriverPath, sizeof(DriverPath), "%wZ", FilePath); 239 DriverNamePos = strrchr(DriverPath, '\\'); 240 if (DriverNamePos != NULL) 241 { 242 // Copy the name 243 strcpy(DllName, DriverNamePos+1); 244 245 // Cut out the name from the path 246 *(DriverNamePos+1) = 0; 247 } 248 else 249 { 250 // There is no directory in the path 251 strcpy(DllName, DriverPath); 252 DriverPath[0] = ANSI_NULL; 253 } 254 255 TRACE("DriverPath: %s, DllName: %s, LPB\n", DriverPath, DllName); 256 257 // Check if driver is already loaded 258 Success = WinLdrCheckForLoadedDll(LoadOrderListHead, DllName, DriverDTE); 259 if (Success) 260 { 261 // We've got the pointer to its DTE, just return success 262 return TRUE; 263 } 264 265 // It's not loaded, we have to load it 266 _snprintf(FullPath, sizeof(FullPath), "%s%wZ", BootPath, FilePath); 267 Success = WinLdrLoadImage(FullPath, LoaderBootDriver, &DriverBase); 268 if (!Success) 269 return FALSE; 270 271 // Allocate a DTE for it 272 Success = WinLdrAllocateDataTableEntry(LoadOrderListHead, DllName, DllName, DriverBase, DriverDTE); 273 if (!Success) 274 { 275 ERR("WinLdrAllocateDataTableEntry() failed\n"); 276 return FALSE; 277 } 278 279 // Modify any flags, if needed 280 (*DriverDTE)->Flags |= Flags; 281 282 // Look for any dependencies it may have, and load them too 283 sprintf(FullPath,"%s%s", BootPath, DriverPath); 284 Success = WinLdrScanImportDescriptorTable(LoadOrderListHead, FullPath, *DriverDTE); 285 if (!Success) 286 { 287 ERR("WinLdrScanImportDescriptorTable() failed for %s\n", FullPath); 288 return FALSE; 289 } 290 291 return TRUE; 292 } 293 294 BOOLEAN 295 WinLdrLoadBootDrivers(PLOADER_PARAMETER_BLOCK LoaderBlock, 296 LPCSTR BootPath) 297 { 298 PLIST_ENTRY NextBd; 299 PBOOT_DRIVER_LIST_ENTRY BootDriver; 300 BOOLEAN Success; 301 BOOLEAN ret = TRUE; 302 303 // Walk through the boot drivers list 304 NextBd = LoaderBlock->BootDriverListHead.Flink; 305 306 while (NextBd != &LoaderBlock->BootDriverListHead) 307 { 308 BootDriver = CONTAINING_RECORD(NextBd, BOOT_DRIVER_LIST_ENTRY, Link); 309 310 TRACE("BootDriver %wZ DTE %08X RegPath: %wZ\n", &BootDriver->FilePath, 311 BootDriver->LdrEntry, &BootDriver->RegistryPath); 312 313 // Paths are relative (FIXME: Are they always relative?) 314 315 // Load it 316 Success = WinLdrLoadDeviceDriver(&LoaderBlock->LoadOrderListHead, 317 BootPath, 318 &BootDriver->FilePath, 319 0, 320 &BootDriver->LdrEntry); 321 322 if (Success) 323 { 324 // Convert the RegistryPath and DTE addresses to VA since we are not going to use it anymore 325 BootDriver->RegistryPath.Buffer = PaToVa(BootDriver->RegistryPath.Buffer); 326 BootDriver->FilePath.Buffer = PaToVa(BootDriver->FilePath.Buffer); 327 BootDriver->LdrEntry = PaToVa(BootDriver->LdrEntry); 328 } 329 else 330 { 331 // Loading failed - cry loudly 332 ERR("Can't load boot driver '%wZ'!\n", &BootDriver->FilePath); 333 UiMessageBox("Can't load boot driver '%wZ'!", &BootDriver->FilePath); 334 ret = FALSE; 335 336 // Remove it from the list and try to continue 337 RemoveEntryList(NextBd); 338 } 339 340 NextBd = BootDriver->Link.Flink; 341 } 342 343 return ret; 344 } 345 346 PVOID 347 WinLdrLoadModule(PCSTR ModuleName, 348 ULONG *Size, 349 TYPE_OF_MEMORY MemoryType) 350 { 351 ULONG FileId; 352 PVOID PhysicalBase; 353 FILEINFORMATION FileInfo; 354 ULONG FileSize; 355 ARC_STATUS Status; 356 ULONG BytesRead; 357 358 //CHAR ProgressString[256]; 359 360 /* Inform user we are loading files */ 361 //sprintf(ProgressString, "Loading %s...", FileName); 362 //UiDrawProgressBarCenter(1, 100, ProgressString); 363 364 TRACE("Loading module %s\n", ModuleName); 365 *Size = 0; 366 367 /* Open the image file */ 368 Status = ArcOpen((PCHAR)ModuleName, OpenReadOnly, &FileId); 369 if (Status != ESUCCESS) 370 { 371 /* In case of errors, we just return, without complaining to the user */ 372 return NULL; 373 } 374 375 /* Get this file's size */ 376 Status = ArcGetFileInformation(FileId, &FileInfo); 377 if (Status != ESUCCESS) 378 { 379 ArcClose(FileId); 380 return NULL; 381 } 382 FileSize = FileInfo.EndingAddress.LowPart; 383 *Size = FileSize; 384 385 /* Allocate memory */ 386 PhysicalBase = MmAllocateMemoryWithType(FileSize, MemoryType); 387 if (PhysicalBase == NULL) 388 { 389 ArcClose(FileId); 390 return NULL; 391 } 392 393 /* Load whole file */ 394 Status = ArcRead(FileId, PhysicalBase, FileSize, &BytesRead); 395 ArcClose(FileId); 396 if (Status != ESUCCESS) 397 { 398 return NULL; 399 } 400 401 TRACE("Loaded %s at 0x%x with size 0x%x\n", ModuleName, PhysicalBase, FileSize); 402 403 return PhysicalBase; 404 } 405 406 USHORT 407 WinLdrDetectVersion(VOID) 408 { 409 LONG rc; 410 HKEY hKey; 411 412 rc = RegOpenKey( 413 NULL, 414 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Terminal Server", 415 &hKey); 416 if (rc != ERROR_SUCCESS) 417 { 418 // Key doesn't exist; assume NT 4.0 419 return _WIN32_WINNT_NT4; 420 } 421 422 // We may here want to read the value of ProductVersion 423 return _WIN32_WINNT_WS03; 424 } 425 426 static 427 BOOLEAN 428 LoadModule( 429 IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, 430 IN PCCH Path, 431 IN PCCH File, 432 IN PCCH ImportName, // BaseDllName 433 IN TYPE_OF_MEMORY MemoryType, 434 OUT PLDR_DATA_TABLE_ENTRY *Dte, 435 IN ULONG Percentage) 436 { 437 BOOLEAN Success; 438 CHAR FullFileName[MAX_PATH]; 439 CHAR ProgressString[256]; 440 PVOID BaseAddress = NULL; 441 442 UiDrawBackdrop(); 443 sprintf(ProgressString, "Loading %s...", File); 444 UiDrawProgressBarCenter(Percentage, 100, ProgressString); 445 446 strcpy(FullFileName, Path); 447 strcat(FullFileName, File); 448 449 Success = WinLdrLoadImage(FullFileName, MemoryType, &BaseAddress); 450 if (!Success) 451 { 452 TRACE("Loading %s failed\n", File); 453 return FALSE; 454 } 455 TRACE("%s loaded successfully at %p\n", File, BaseAddress); 456 457 /* 458 * Cheat about the base DLL name if we are loading 459 * the Kernel Debugger Transport DLL, to make the 460 * PE loader happy. 461 */ 462 Success = WinLdrAllocateDataTableEntry(&LoaderBlock->LoadOrderListHead, 463 ImportName, 464 FullFileName, 465 BaseAddress, 466 Dte); 467 468 return Success; 469 } 470 471 static 472 BOOLEAN 473 LoadWindowsCore(IN USHORT OperatingSystemVersion, 474 IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, 475 IN PCSTR BootOptions, 476 IN PCSTR BootPath, 477 IN OUT PLDR_DATA_TABLE_ENTRY* KernelDTE) 478 { 479 BOOLEAN Success; 480 PCSTR Options; 481 CHAR DirPath[MAX_PATH]; 482 CHAR KernelFileName[MAX_PATH]; 483 CHAR HalFileName[MAX_PATH]; 484 CHAR KdTransportDllName[MAX_PATH]; 485 PLDR_DATA_TABLE_ENTRY HalDTE, KdComDTE = NULL; 486 487 if (!KernelDTE) return FALSE; 488 489 /* Initialize SystemRoot\System32 path */ 490 strcpy(DirPath, BootPath); 491 strcat(DirPath, "SYSTEM32\\"); 492 493 // 494 // TODO: Parse also the separate INI values "Kernel=" and "Hal=" 495 // 496 497 /* Default KERNEL and HAL file names */ 498 strcpy(KernelFileName, "NTOSKRNL.EXE"); 499 strcpy(HalFileName , "HAL.DLL"); 500 501 /* Find any /KERNEL= or /HAL= switch in the boot options */ 502 Options = BootOptions; 503 while (Options) 504 { 505 /* Skip possible initial whitespace */ 506 Options += strspn(Options, " \t"); 507 508 /* Check whether a new commutator starts and it is either KERNEL or HAL */ 509 if (*Options != '/' || (++Options, 510 !(_strnicmp(Options, "KERNEL=", 7) == 0 || 511 _strnicmp(Options, "HAL=", 4) == 0)) ) 512 { 513 /* Search for another whitespace */ 514 Options = strpbrk(Options, " \t"); 515 continue; 516 } 517 else 518 { 519 size_t i = strcspn(Options, " \t"); /* Skip whitespace */ 520 if (i == 0) 521 { 522 /* Use the default values */ 523 break; 524 } 525 526 /* We have found either KERNEL or HAL commutator */ 527 if (_strnicmp(Options, "KERNEL=", 7) == 0) 528 { 529 Options += 7; i -= 7; 530 strncpy(KernelFileName, Options, i); 531 KernelFileName[i] = ANSI_NULL; 532 _strupr(KernelFileName); 533 } 534 else if (_strnicmp(Options, "HAL=", 4) == 0) 535 { 536 Options += 4; i -= 4; 537 strncpy(HalFileName, Options, i); 538 HalFileName[i] = ANSI_NULL; 539 _strupr(HalFileName); 540 } 541 } 542 } 543 544 TRACE("Kernel file = '%s' ; HAL file = '%s'\n", KernelFileName, HalFileName); 545 546 /* Load the Kernel */ 547 LoadModule(LoaderBlock, DirPath, KernelFileName, "NTOSKRNL.EXE", LoaderSystemCode, KernelDTE, 30); 548 549 /* Load the HAL */ 550 LoadModule(LoaderBlock, DirPath, HalFileName, "HAL.DLL", LoaderHalCode, &HalDTE, 45); 551 552 /* Load the Kernel Debugger Transport DLL */ 553 if (OperatingSystemVersion > _WIN32_WINNT_WIN2K) 554 { 555 /* 556 * According to http://www.nynaeve.net/?p=173 : 557 * "[...] Another enhancement that could be done Microsoft-side would be 558 * a better interface for replacing KD transport modules. Right now, due 559 * to the fact that ntoskrnl is static linked to KDCOM.DLL, the OS loader 560 * has a hardcoded hack that interprets the KD type in the OS loader options, 561 * loads one of the (hardcoded filenames) "kdcom.dll", "kd1394.dll", or 562 * "kdusb2.dll" modules, and inserts them into the loaded module list under 563 * the name "kdcom.dll". [...]" 564 */ 565 566 /* 567 * This loop replaces a dumb call to strstr(..., "DEBUGPORT="). 568 * Indeed I want it to be case-insensitive to allow "debugport=" 569 * or "DeBuGpOrT=" or... , and I don't want it to match malformed 570 * command-line options, such as: 571 * 572 * "...foo DEBUGPORT=xxx bar..." 573 * "...foo/DEBUGPORT=xxx bar..." 574 * "...foo/DEBUGPORT=bar..." 575 * 576 * i.e. the "DEBUGPORT=" switch must start with a slash and be separated 577 * from the rest by whitespace, unless it begins the command-line, e.g.: 578 * 579 * "/DEBUGPORT=COM1 foo...bar..." 580 * "...foo /DEBUGPORT=USB bar..." 581 * or: 582 * "...foo /DEBUGPORT= bar..." 583 * (in that case, we default the port to COM). 584 */ 585 Options = BootOptions; 586 while (Options) 587 { 588 /* Skip possible initial whitespace */ 589 Options += strspn(Options, " \t"); 590 591 /* Check whether a new commutator starts and it is the DEBUGPORT one */ 592 if (*Options != '/' || _strnicmp(++Options, "DEBUGPORT=", 10) != 0) 593 { 594 /* Search for another whitespace */ 595 Options = strpbrk(Options, " \t"); 596 continue; 597 } 598 else 599 { 600 /* We found the DEBUGPORT commutator. Move to the port name. */ 601 Options += 10; 602 break; 603 } 604 } 605 606 if (Options) 607 { 608 /* 609 * We have found the DEBUGPORT commutator. Parse the port name. 610 * Format: /DEBUGPORT=COM1 or /DEBUGPORT=FILE:\Device\HarddiskX\PartitionY\debug.log or /DEBUGPORT=FOO 611 * If we only have /DEBUGPORT= (i.e. without any port name), defaults it to "COM". 612 */ 613 strcpy(KdTransportDllName, "KD"); 614 if (_strnicmp(Options, "COM", 3) == 0 && '0' <= Options[3] && Options[3] <= '9') 615 { 616 strncat(KdTransportDllName, Options, 3); 617 } 618 else 619 { 620 size_t i = strcspn(Options, " \t:"); /* Skip valid separators: whitespace or colon */ 621 if (i == 0) 622 strcat(KdTransportDllName, "COM"); 623 else 624 strncat(KdTransportDllName, Options, i); 625 } 626 strcat(KdTransportDllName, ".DLL"); 627 _strupr(KdTransportDllName); 628 629 /* 630 * Load the transport DLL. Override the base DLL name of the 631 * loaded transport DLL to the default "KDCOM.DLL" name. 632 */ 633 LoadModule(LoaderBlock, DirPath, KdTransportDllName, "KDCOM.DLL", LoaderSystemCode, &KdComDTE, 60); 634 } 635 } 636 637 /* Load all referenced DLLs for Kernel, HAL and Kernel Debugger Transport DLL */ 638 Success = WinLdrScanImportDescriptorTable(&LoaderBlock->LoadOrderListHead, DirPath, *KernelDTE); 639 Success &= WinLdrScanImportDescriptorTable(&LoaderBlock->LoadOrderListHead, DirPath, HalDTE); 640 if (KdComDTE) 641 { 642 Success &= WinLdrScanImportDescriptorTable(&LoaderBlock->LoadOrderListHead, DirPath, KdComDTE); 643 } 644 645 return Success; 646 } 647 648 VOID 649 LoadAndBootWindows(IN OperatingSystemItem* OperatingSystem, 650 IN USHORT OperatingSystemVersion) 651 { 652 ULONG_PTR SectionId; 653 PCSTR SectionName = OperatingSystem->SystemPartition; 654 CHAR SettingsValue[80]; 655 BOOLEAN HasSection; 656 CHAR BootPath[MAX_PATH]; 657 CHAR FileName[MAX_PATH]; 658 CHAR BootOptions[256]; 659 PCHAR File; 660 BOOLEAN Success; 661 PLOADER_PARAMETER_BLOCK LoaderBlock; 662 663 /* Get OS setting value */ 664 SettingsValue[0] = ANSI_NULL; 665 IniOpenSection("Operating Systems", &SectionId); 666 IniReadSettingByName(SectionId, SectionName, SettingsValue, sizeof(SettingsValue)); 667 668 /* Open the operating system section specified in the .ini file */ 669 HasSection = IniOpenSection(SectionName, &SectionId); 670 671 UiDrawBackdrop(); 672 UiDrawProgressBarCenter(1, 100, "Loading NT..."); 673 674 /* Read the system path is set in the .ini file */ 675 if (!HasSection || 676 !IniReadSettingByName(SectionId, "SystemPath", BootPath, sizeof(BootPath))) 677 { 678 strcpy(BootPath, SectionName); 679 } 680 681 /* 682 * Check whether BootPath is a full path 683 * and if not, create a full boot path. 684 * 685 * See FsOpenFile for the technique used. 686 */ 687 if (strrchr(BootPath, ')') == NULL) 688 { 689 /* Temporarily save the boot path */ 690 strcpy(FileName, BootPath); 691 692 /* This is not a full path. Use the current (i.e. boot) device. */ 693 MachDiskGetBootPath(BootPath, sizeof(BootPath)); 694 695 /* Append a path separator if needed */ 696 if (FileName[0] != '\\' && FileName[0] != '/') 697 strcat(BootPath, "\\"); 698 699 /* Append the remaining path */ 700 strcat(BootPath, FileName); 701 } 702 703 /* Append a backslash if needed */ 704 if ((BootPath[0] == 0) || BootPath[strlen(BootPath) - 1] != '\\') 705 strcat(BootPath, "\\"); 706 707 /* Read booting options */ 708 if (!HasSection || !IniReadSettingByName(SectionId, "Options", BootOptions, sizeof(BootOptions))) 709 { 710 /* Get options after the title */ 711 PCSTR p = SettingsValue; 712 while (*p == ' ' || *p == '"') 713 p++; 714 while (*p != '\0' && *p != '"') 715 p++; 716 strcpy(BootOptions, p); 717 TRACE("BootOptions: '%s'\n", BootOptions); 718 } 719 720 /* Append boot-time options */ 721 AppendBootTimeOptions(BootOptions); 722 723 /* Check if a ramdisk file was given */ 724 File = strstr(BootOptions, "/RDPATH="); 725 if (File) 726 { 727 /* Copy the file name and everything else after it */ 728 strcpy(FileName, File + 8); 729 730 /* Null-terminate */ 731 *strstr(FileName, " ") = ANSI_NULL; 732 733 /* Load the ramdisk */ 734 if (!RamDiskLoadVirtualFile(FileName)) 735 { 736 UiMessageBox("Failed to load RAM disk file %s", FileName); 737 return; 738 } 739 } 740 741 /* Let user know we started loading */ 742 //UiDrawStatusText("Loading..."); 743 744 TRACE("BootPath: '%s'\n", BootPath); 745 746 /* Allocate and minimalist-initialize LPB */ 747 AllocateAndInitLPB(&LoaderBlock); 748 749 /* Load the system hive */ 750 UiDrawBackdrop(); 751 UiDrawProgressBarCenter(15, 100, "Loading system hive..."); 752 Success = WinLdrInitSystemHive(LoaderBlock, BootPath); 753 TRACE("SYSTEM hive %s\n", (Success ? "loaded" : "not loaded")); 754 /* Bail out if failure */ 755 if (!Success) 756 return; 757 758 /* Load NLS data, OEM font, and prepare boot drivers list */ 759 Success = WinLdrScanSystemHive(LoaderBlock, BootPath); 760 TRACE("SYSTEM hive %s\n", (Success ? "scanned" : "not scanned")); 761 /* Bail out if failure */ 762 if (!Success) 763 return; 764 765 /* Finish loading */ 766 LoadAndBootWindowsCommon(OperatingSystemVersion, 767 LoaderBlock, 768 BootOptions, 769 BootPath, 770 FALSE); 771 } 772 773 VOID 774 LoadAndBootWindowsCommon( 775 USHORT OperatingSystemVersion, 776 PLOADER_PARAMETER_BLOCK LoaderBlock, 777 LPCSTR BootOptions, 778 LPCSTR BootPath, 779 BOOLEAN Setup) 780 { 781 PLOADER_PARAMETER_BLOCK LoaderBlockVA; 782 BOOLEAN Success; 783 PLDR_DATA_TABLE_ENTRY KernelDTE; 784 KERNEL_ENTRY_POINT KiSystemStartup; 785 LPCSTR SystemRoot; 786 TRACE("LoadAndBootWindowsCommon()\n"); 787 788 #ifdef _M_IX86 789 /* Setup redirection support */ 790 WinLdrSetupEms((PCHAR)BootOptions); 791 #endif 792 793 /* Convert BootPath to SystemRoot */ 794 SystemRoot = strstr(BootPath, "\\"); 795 796 /* Detect hardware */ 797 LoaderBlock->ConfigurationRoot = MachHwDetect(); 798 799 if (OperatingSystemVersion == 0) 800 OperatingSystemVersion = WinLdrDetectVersion(); 801 802 /* Load the operating system core: the Kernel, the HAL and the Kernel Debugger Transport DLL */ 803 Success = LoadWindowsCore(OperatingSystemVersion, 804 LoaderBlock, 805 BootOptions, 806 BootPath, 807 &KernelDTE); 808 if (!Success) 809 { 810 UiMessageBox("Error loading NTOS core."); 811 return; 812 } 813 814 /* Load boot drivers */ 815 UiDrawBackdrop(); 816 UiDrawProgressBarCenter(100, 100, "Loading boot drivers..."); 817 Success = WinLdrLoadBootDrivers(LoaderBlock, BootPath); 818 TRACE("Boot drivers loading %s\n", Success ? "successful" : "failed"); 819 820 /* Initialize Phase 1 - no drivers loading anymore */ 821 WinLdrInitializePhase1(LoaderBlock, 822 BootOptions, 823 SystemRoot, 824 BootPath, 825 OperatingSystemVersion); 826 827 /* Save entry-point pointer and Loader block VAs */ 828 KiSystemStartup = (KERNEL_ENTRY_POINT)KernelDTE->EntryPoint; 829 LoaderBlockVA = PaToVa(LoaderBlock); 830 831 /* "Stop all motors", change videomode */ 832 MachPrepareForReactOS(Setup); 833 834 /* Cleanup ini file */ 835 IniCleanup(); 836 837 /* Debugging... */ 838 //DumpMemoryAllocMap(); 839 840 /* Do the machine specific initialization */ 841 WinLdrSetupMachineDependent(LoaderBlock); 842 843 /* Map pages and create memory descriptors */ 844 WinLdrSetupMemoryLayout(LoaderBlock); 845 846 /* Set processor context */ 847 WinLdrSetProcessorContext(); 848 849 /* Save final value of LoaderPagesSpanned */ 850 LoaderBlock->Extension->LoaderPagesSpanned = LoaderPagesSpanned; 851 852 TRACE("Hello from paged mode, KiSystemStartup %p, LoaderBlockVA %p!\n", 853 KiSystemStartup, LoaderBlockVA); 854 855 // Zero KI_USER_SHARED_DATA page 856 memset((PVOID)KI_USER_SHARED_DATA, 0, MM_PAGE_SIZE); 857 858 WinLdrpDumpMemoryDescriptors(LoaderBlockVA); 859 WinLdrpDumpBootDriver(LoaderBlockVA); 860 #ifndef _M_AMD64 861 WinLdrpDumpArcDisks(LoaderBlockVA); 862 #endif 863 864 /* Pass control */ 865 (*KiSystemStartup)(LoaderBlockVA); 866 } 867 868 VOID 869 WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock) 870 { 871 PLIST_ENTRY NextMd; 872 PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor; 873 874 NextMd = LoaderBlock->MemoryDescriptorListHead.Flink; 875 876 while (NextMd != &LoaderBlock->MemoryDescriptorListHead) 877 { 878 MemoryDescriptor = CONTAINING_RECORD(NextMd, MEMORY_ALLOCATION_DESCRIPTOR, ListEntry); 879 880 TRACE("BP %08X PC %04X MT %d\n", MemoryDescriptor->BasePage, 881 MemoryDescriptor->PageCount, MemoryDescriptor->MemoryType); 882 883 NextMd = MemoryDescriptor->ListEntry.Flink; 884 } 885 } 886 887 VOID 888 WinLdrpDumpBootDriver(PLOADER_PARAMETER_BLOCK LoaderBlock) 889 { 890 PLIST_ENTRY NextBd; 891 PBOOT_DRIVER_LIST_ENTRY BootDriver; 892 893 NextBd = LoaderBlock->BootDriverListHead.Flink; 894 895 while (NextBd != &LoaderBlock->BootDriverListHead) 896 { 897 BootDriver = CONTAINING_RECORD(NextBd, BOOT_DRIVER_LIST_ENTRY, Link); 898 899 TRACE("BootDriver %wZ DTE %08X RegPath: %wZ\n", &BootDriver->FilePath, 900 BootDriver->LdrEntry, &BootDriver->RegistryPath); 901 902 NextBd = BootDriver->Link.Flink; 903 } 904 } 905 906 VOID 907 WinLdrpDumpArcDisks(PLOADER_PARAMETER_BLOCK LoaderBlock) 908 { 909 PLIST_ENTRY NextBd; 910 PARC_DISK_SIGNATURE ArcDisk; 911 912 NextBd = LoaderBlock->ArcDiskInformation->DiskSignatureListHead.Flink; 913 914 while (NextBd != &LoaderBlock->ArcDiskInformation->DiskSignatureListHead) 915 { 916 ArcDisk = CONTAINING_RECORD(NextBd, ARC_DISK_SIGNATURE, ListEntry); 917 918 TRACE("ArcDisk %s checksum: 0x%X, signature: 0x%X\n", 919 ArcDisk->ArcName, ArcDisk->CheckSum, ArcDisk->Signature); 920 921 NextBd = ArcDisk->ListEntry.Flink; 922 } 923 } 924