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>
9 #include <ndk/ldrtypes.h>
14 DBG_DEFAULT_CHANNEL(WINDOWS
);
16 // FIXME: Find a better way to retrieve ARC disk information
17 extern ULONG reactos_disk_count
;
18 extern ARC_DISK_SIGNATURE_EX reactos_arc_disk_info
[];
20 extern ULONG LoaderPagesSpanned
;
21 extern BOOLEAN AcpiPresent
;
23 extern HEADLESS_LOADER_BLOCK LoaderRedirectionInformation
;
24 extern BOOLEAN WinLdrTerminalConnected
;
25 extern void WinLdrSetupEms(IN PCHAR BootOptions
);
27 PLOADER_SYSTEM_BLOCK WinLdrSystemBlock
;
30 VOID
DumpMemoryAllocMap(VOID
);
34 AllocateAndInitLPB(PLOADER_PARAMETER_BLOCK
*OutLoaderBlock
)
36 PLOADER_PARAMETER_BLOCK LoaderBlock
;
38 /* Allocate and zero-init the LPB */
39 WinLdrSystemBlock
= MmAllocateMemoryWithType(sizeof(LOADER_SYSTEM_BLOCK
),
41 if (WinLdrSystemBlock
== NULL
)
43 UiMessageBox("Failed to allocate memory for system block!");
47 RtlZeroMemory(WinLdrSystemBlock
, sizeof(LOADER_SYSTEM_BLOCK
));
49 LoaderBlock
= &WinLdrSystemBlock
->LoaderBlock
;
50 LoaderBlock
->NlsData
= &WinLdrSystemBlock
->NlsDataBlock
;
52 /* Init three critical lists, used right away */
53 InitializeListHead(&LoaderBlock
->LoadOrderListHead
);
54 InitializeListHead(&LoaderBlock
->MemoryDescriptorListHead
);
55 InitializeListHead(&LoaderBlock
->BootDriverListHead
);
57 *OutLoaderBlock
= LoaderBlock
;
62 WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock
,
68 /* Examples of correct options and paths */
69 //CHAR Options[] = "/DEBUGPORT=COM1 /BAUDRATE=115200";
70 //CHAR Options[] = "/NODEBUG";
71 //CHAR SystemRoot[] = "\\WINNT\\";
72 //CHAR ArcBoot[] = "multi(0)disk(0)rdisk(0)partition(1)";
74 PSTR LoadOptions
, NewLoadOptions
;
75 CHAR HalPath
[] = "\\";
76 CHAR ArcBoot
[MAX_PATH
+1];
77 CHAR MiscFiles
[MAX_PATH
+1];
79 ULONG_PTR PathSeparator
;
80 PLOADER_PARAMETER_EXTENSION Extension
;
82 /* Construct SystemRoot and ArcBoot from SystemPath */
83 PathSeparator
= strstr(BootPath
, "\\") - BootPath
;
84 RtlStringCbCopyNA(ArcBoot
, sizeof(ArcBoot
), BootPath
, PathSeparator
);
86 TRACE("ArcBoot: '%s'\n", ArcBoot
);
87 TRACE("SystemRoot: '%s'\n", SystemRoot
);
88 TRACE("Options: '%s'\n", Options
);
90 /* Fill ARC BootDevice */
91 LoaderBlock
->ArcBootDeviceName
= WinLdrSystemBlock
->ArcBootDeviceName
;
92 RtlStringCbCopyA(LoaderBlock
->ArcBootDeviceName
, sizeof(WinLdrSystemBlock
->ArcBootDeviceName
), ArcBoot
);
93 LoaderBlock
->ArcBootDeviceName
= PaToVa(LoaderBlock
->ArcBootDeviceName
);
97 // SetupBlock->ArcSetupDeviceName must be the path to the setup **SOURCE**,
98 // and not the setup boot path. Indeed they may differ!!
100 /* If we have a setup block, adjust also its ARC path */
101 if (LoaderBlock
->SetupLdrBlock
)
103 PSETUP_LOADER_BLOCK SetupBlock
= LoaderBlock
->SetupLdrBlock
;
105 /* Matches ArcBoot path */
106 SetupBlock
->ArcSetupDeviceName
= WinLdrSystemBlock
->ArcBootDeviceName
;
107 SetupBlock
->ArcSetupDeviceName
= PaToVa(SetupBlock
->ArcSetupDeviceName
);
109 /* Note: LoaderBlock->SetupLdrBlock is PaToVa'ed at the end of this function */
112 /* Fill ARC HalDevice, it matches ArcBoot path */
113 LoaderBlock
->ArcHalDeviceName
= WinLdrSystemBlock
->ArcBootDeviceName
;
114 LoaderBlock
->ArcHalDeviceName
= PaToVa(LoaderBlock
->ArcHalDeviceName
);
116 /* Fill SystemRoot */
117 LoaderBlock
->NtBootPathName
= WinLdrSystemBlock
->NtBootPathName
;
118 RtlStringCbCopyA(LoaderBlock
->NtBootPathName
, sizeof(WinLdrSystemBlock
->NtBootPathName
), SystemRoot
);
119 LoaderBlock
->NtBootPathName
= PaToVa(LoaderBlock
->NtBootPathName
);
121 /* Fill NtHalPathName */
122 LoaderBlock
->NtHalPathName
= WinLdrSystemBlock
->NtHalPathName
;
123 RtlStringCbCopyA(LoaderBlock
->NtHalPathName
, sizeof(WinLdrSystemBlock
->NtHalPathName
), HalPath
);
124 LoaderBlock
->NtHalPathName
= PaToVa(LoaderBlock
->NtHalPathName
);
126 /* Fill LoadOptions and strip the '/' switch symbol in front of each option */
127 NewLoadOptions
= LoadOptions
= LoaderBlock
->LoadOptions
= WinLdrSystemBlock
->LoadOptions
;
128 RtlStringCbCopyA(LoaderBlock
->LoadOptions
, sizeof(WinLdrSystemBlock
->LoadOptions
), Options
);
132 while (*LoadOptions
== '/')
135 *NewLoadOptions
++ = *LoadOptions
;
136 } while (*LoadOptions
++);
138 LoaderBlock
->LoadOptions
= PaToVa(LoaderBlock
->LoadOptions
);
141 LoaderBlock
->ArcDiskInformation
= &WinLdrSystemBlock
->ArcDiskInformation
;
142 InitializeListHead(&LoaderBlock
->ArcDiskInformation
->DiskSignatureListHead
);
144 /* Convert ARC disk information from freeldr to a correct format */
145 for (i
= 0; i
< reactos_disk_count
; i
++)
147 PARC_DISK_SIGNATURE_EX ArcDiskSig
;
149 /* Allocate the ARC structure */
150 ArcDiskSig
= FrLdrHeapAlloc(sizeof(ARC_DISK_SIGNATURE_EX
), 'giSD');
152 /* Copy the data over */
153 RtlCopyMemory(ArcDiskSig
, &reactos_arc_disk_info
[i
], sizeof(ARC_DISK_SIGNATURE_EX
));
155 /* Set the ARC Name pointer */
156 ArcDiskSig
->DiskSignature
.ArcName
= PaToVa(ArcDiskSig
->ArcName
);
158 /* Insert into the list */
159 InsertTailList(&LoaderBlock
->ArcDiskInformation
->DiskSignatureListHead
,
160 &ArcDiskSig
->DiskSignature
.ListEntry
);
163 /* Convert all list's to Virtual address */
165 /* Convert the ArcDisks list to virtual address */
166 List_PaToVa(&LoaderBlock
->ArcDiskInformation
->DiskSignatureListHead
);
167 LoaderBlock
->ArcDiskInformation
= PaToVa(LoaderBlock
->ArcDiskInformation
);
169 /* Convert configuration entries to VA */
170 ConvertConfigToVA(LoaderBlock
->ConfigurationRoot
);
171 LoaderBlock
->ConfigurationRoot
= PaToVa(LoaderBlock
->ConfigurationRoot
);
173 /* Convert all DTE into virtual addresses */
174 List_PaToVa(&LoaderBlock
->LoadOrderListHead
);
176 /* This one will be converted right before switching to virtual paging mode */
177 //List_PaToVa(&LoaderBlock->MemoryDescriptorListHead);
179 /* Convert list of boot drivers */
180 List_PaToVa(&LoaderBlock
->BootDriverListHead
);
182 /* Initialize Extension now */
183 Extension
= &WinLdrSystemBlock
->Extension
;
184 Extension
->Size
= sizeof(LOADER_PARAMETER_EXTENSION
);
185 Extension
->MajorVersion
= (VersionToBoot
& 0xFF00) >> 8;
186 Extension
->MinorVersion
= VersionToBoot
& 0xFF;
187 Extension
->Profile
.Status
= 2;
189 /* Check if FreeLdr detected a ACPI table */
192 /* Set the pointer to something for compatibility */
193 Extension
->AcpiTable
= (PVOID
)1;
194 // FIXME: Extension->AcpiTableSize;
198 /* Set headless block pointer */
199 if (WinLdrTerminalConnected
)
201 Extension
->HeadlessLoaderBlock
= &WinLdrSystemBlock
->HeadlessLoaderBlock
;
202 RtlCopyMemory(Extension
->HeadlessLoaderBlock
,
203 &LoaderRedirectionInformation
,
204 sizeof(HEADLESS_LOADER_BLOCK
));
205 Extension
->HeadlessLoaderBlock
= PaToVa(Extension
->HeadlessLoaderBlock
);
208 /* Load drivers database */
209 RtlStringCbCopyA(MiscFiles
, sizeof(MiscFiles
), BootPath
);
210 RtlStringCbCatA(MiscFiles
, sizeof(MiscFiles
), "AppPatch\\drvmain.sdb");
211 Extension
->DrvDBImage
= PaToVa(WinLdrLoadModule(MiscFiles
,
212 &Extension
->DrvDBSize
,
213 LoaderRegistryData
));
215 /* Convert extension and setup block pointers */
216 LoaderBlock
->Extension
= PaToVa(Extension
);
218 if (LoaderBlock
->SetupLdrBlock
)
219 LoaderBlock
->SetupLdrBlock
= PaToVa(LoaderBlock
->SetupLdrBlock
);
221 TRACE("WinLdrInitializePhase1() completed\n");
225 WinLdrLoadDeviceDriver(PLIST_ENTRY LoadOrderListHead
,
227 PUNICODE_STRING FilePath
,
229 PLDR_DATA_TABLE_ENTRY
*DriverDTE
)
232 CHAR DriverPath
[1024];
236 PVOID DriverBase
= NULL
;
238 // Separate the path to file name and directory path
239 RtlStringCbPrintfA(DriverPath
, sizeof(DriverPath
), "%wZ", FilePath
);
240 DriverNamePos
= strrchr(DriverPath
, '\\');
241 if (DriverNamePos
!= NULL
)
244 RtlStringCbCopyA(DllName
, sizeof(DllName
), DriverNamePos
+1);
246 // Cut out the name from the path
247 *(DriverNamePos
+1) = ANSI_NULL
;
251 // There is no directory in the path
252 RtlStringCbCopyA(DllName
, sizeof(DllName
), DriverPath
);
253 *DriverPath
= ANSI_NULL
;
256 TRACE("DriverPath: '%s', DllName: '%s', LPB\n", DriverPath
, DllName
);
258 // Check if driver is already loaded
259 Success
= WinLdrCheckForLoadedDll(LoadOrderListHead
, DllName
, DriverDTE
);
262 // We've got the pointer to its DTE, just return success
266 // It's not loaded, we have to load it
267 RtlStringCbPrintfA(FullPath
, sizeof(FullPath
), "%s%wZ", BootPath
, FilePath
);
268 Success
= WinLdrLoadImage(FullPath
, LoaderBootDriver
, &DriverBase
);
272 // Allocate a DTE for it
273 Success
= WinLdrAllocateDataTableEntry(LoadOrderListHead
, DllName
, DllName
, DriverBase
, DriverDTE
);
276 ERR("WinLdrAllocateDataTableEntry() failed\n");
280 // Modify any flags, if needed
281 (*DriverDTE
)->Flags
|= Flags
;
283 // Look for any dependencies it may have, and load them too
284 RtlStringCbPrintfA(FullPath
, sizeof(FullPath
), "%s%s", BootPath
, DriverPath
);
285 Success
= WinLdrScanImportDescriptorTable(LoadOrderListHead
, FullPath
, *DriverDTE
);
288 ERR("WinLdrScanImportDescriptorTable() failed for %s\n", FullPath
);
296 WinLdrLoadBootDrivers(PLOADER_PARAMETER_BLOCK LoaderBlock
,
300 PBOOT_DRIVER_LIST_ENTRY BootDriver
;
304 // Walk through the boot drivers list
305 NextBd
= LoaderBlock
->BootDriverListHead
.Flink
;
307 while (NextBd
!= &LoaderBlock
->BootDriverListHead
)
309 BootDriver
= CONTAINING_RECORD(NextBd
, BOOT_DRIVER_LIST_ENTRY
, Link
);
311 TRACE("BootDriver %wZ DTE %08X RegPath: %wZ\n", &BootDriver
->FilePath
,
312 BootDriver
->LdrEntry
, &BootDriver
->RegistryPath
);
314 // Paths are relative (FIXME: Are they always relative?)
317 Success
= WinLdrLoadDeviceDriver(&LoaderBlock
->LoadOrderListHead
,
319 &BootDriver
->FilePath
,
321 &BootDriver
->LdrEntry
);
325 // Convert the RegistryPath and DTE addresses to VA since we are not going to use it anymore
326 BootDriver
->RegistryPath
.Buffer
= PaToVa(BootDriver
->RegistryPath
.Buffer
);
327 BootDriver
->FilePath
.Buffer
= PaToVa(BootDriver
->FilePath
.Buffer
);
328 BootDriver
->LdrEntry
= PaToVa(BootDriver
->LdrEntry
);
332 // Loading failed - cry loudly
333 ERR("Can't load boot driver '%wZ'!\n", &BootDriver
->FilePath
);
334 UiMessageBox("Can't load boot driver '%wZ'!", &BootDriver
->FilePath
);
337 // Remove it from the list and try to continue
338 RemoveEntryList(NextBd
);
341 NextBd
= BootDriver
->Link
.Flink
;
348 WinLdrLoadModule(PCSTR ModuleName
,
350 TYPE_OF_MEMORY MemoryType
)
354 FILEINFORMATION FileInfo
;
359 //CHAR ProgressString[256];
361 /* Inform user we are loading files */
363 //RtlStringCbPrintfA(ProgressString, sizeof(ProgressString), "Loading %s...", FileName);
364 //UiDrawProgressBarCenter(1, 100, ProgressString);
366 TRACE("Loading module %s\n", ModuleName
);
369 /* Open the image file */
370 Status
= ArcOpen((PCHAR
)ModuleName
, OpenReadOnly
, &FileId
);
371 if (Status
!= ESUCCESS
)
373 /* In case of errors, we just return, without complaining to the user */
374 WARN("Error while opening '%s', Status: %u\n", ModuleName
, Status
);
378 /* Get this file's size */
379 Status
= ArcGetFileInformation(FileId
, &FileInfo
);
380 if (Status
!= ESUCCESS
)
385 FileSize
= FileInfo
.EndingAddress
.LowPart
;
388 /* Allocate memory */
389 PhysicalBase
= MmAllocateMemoryWithType(FileSize
, MemoryType
);
390 if (PhysicalBase
== NULL
)
396 /* Load whole file */
397 Status
= ArcRead(FileId
, PhysicalBase
, FileSize
, &BytesRead
);
399 if (Status
!= ESUCCESS
)
401 WARN("Error while reading '%s', Status: %u\n", ModuleName
, Status
);
405 TRACE("Loaded %s at 0x%x with size 0x%x\n", ModuleName
, PhysicalBase
, FileSize
);
411 WinLdrDetectVersion(VOID
)
418 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Terminal Server",
420 if (rc
!= ERROR_SUCCESS
)
422 // Key doesn't exist; assume NT 4.0
423 return _WIN32_WINNT_NT4
;
426 // We may here want to read the value of ProductVersion
427 return _WIN32_WINNT_WS03
;
433 IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock
,
436 IN PCCH ImportName
, // BaseDllName
437 IN TYPE_OF_MEMORY MemoryType
,
438 OUT PLDR_DATA_TABLE_ENTRY
*Dte
,
442 CHAR FullFileName
[MAX_PATH
];
443 CHAR ProgressString
[256];
444 PVOID BaseAddress
= NULL
;
447 RtlStringCbPrintfA(ProgressString
, sizeof(ProgressString
), "Loading %s...", File
);
448 UiDrawProgressBarCenter(Percentage
, 100, ProgressString
);
450 RtlStringCbCopyA(FullFileName
, sizeof(FullFileName
), Path
);
451 RtlStringCbCatA(FullFileName
, sizeof(FullFileName
), File
);
453 Success
= WinLdrLoadImage(FullFileName
, MemoryType
, &BaseAddress
);
456 TRACE("Loading %s failed\n", File
);
459 TRACE("%s loaded successfully at %p\n", File
, BaseAddress
);
462 * Cheat about the base DLL name if we are loading
463 * the Kernel Debugger Transport DLL, to make the
466 Success
= WinLdrAllocateDataTableEntry(&LoaderBlock
->LoadOrderListHead
,
477 LoadWindowsCore(IN USHORT OperatingSystemVersion
,
478 IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock
,
479 IN PCSTR BootOptions
,
481 IN OUT PLDR_DATA_TABLE_ENTRY
* KernelDTE
)
485 CHAR DirPath
[MAX_PATH
];
486 CHAR KernelFileName
[MAX_PATH
];
487 CHAR HalFileName
[MAX_PATH
];
488 CHAR KdTransportDllName
[MAX_PATH
];
489 PLDR_DATA_TABLE_ENTRY HalDTE
, KdComDTE
= NULL
;
491 if (!KernelDTE
) return FALSE
;
493 /* Initialize SystemRoot\System32 path */
494 RtlStringCbCopyA(DirPath
, sizeof(DirPath
), BootPath
);
495 RtlStringCbCatA(DirPath
, sizeof(DirPath
), "system32\\");
498 // TODO: Parse also the separate INI values "Kernel=" and "Hal="
501 /* Default KERNEL and HAL file names */
502 RtlStringCbCopyA(KernelFileName
, sizeof(KernelFileName
), "ntoskrnl.exe");
503 RtlStringCbCopyA(HalFileName
, sizeof(HalFileName
) , "hal.dll");
505 /* Find any /KERNEL= or /HAL= switch in the boot options */
506 Options
= BootOptions
;
509 /* Skip possible initial whitespace */
510 Options
+= strspn(Options
, " \t");
512 /* Check whether a new option starts and it is either KERNEL or HAL */
513 if (*Options
!= '/' || (++Options
,
514 !(_strnicmp(Options
, "KERNEL=", 7) == 0 ||
515 _strnicmp(Options
, "HAL=", 4) == 0)) )
517 /* Search for another whitespace */
518 Options
= strpbrk(Options
, " \t");
523 size_t i
= strcspn(Options
, " \t"); /* Skip whitespace */
526 /* Use the default values */
530 /* We have found either KERNEL or HAL options */
531 if (_strnicmp(Options
, "KERNEL=", 7) == 0)
533 Options
+= 7; i
-= 7;
534 RtlStringCbCopyNA(KernelFileName
, sizeof(KernelFileName
), Options
, i
);
535 _strupr(KernelFileName
);
537 else if (_strnicmp(Options
, "HAL=", 4) == 0)
539 Options
+= 4; i
-= 4;
540 RtlStringCbCopyNA(HalFileName
, sizeof(HalFileName
), Options
, i
);
541 _strupr(HalFileName
);
546 TRACE("Kernel file = '%s' ; HAL file = '%s'\n", KernelFileName
, HalFileName
);
548 /* Load the Kernel */
549 LoadModule(LoaderBlock
, DirPath
, KernelFileName
, "ntoskrnl.exe", LoaderSystemCode
, KernelDTE
, 30);
552 LoadModule(LoaderBlock
, DirPath
, HalFileName
, "hal.dll", LoaderHalCode
, &HalDTE
, 45);
554 /* Load the Kernel Debugger Transport DLL */
555 if (OperatingSystemVersion
> _WIN32_WINNT_WIN2K
)
558 * According to http://www.nynaeve.net/?p=173 :
559 * "[...] Another enhancement that could be done Microsoft-side would be
560 * a better interface for replacing KD transport modules. Right now, due
561 * to the fact that ntoskrnl is static linked to KDCOM.DLL, the OS loader
562 * has a hardcoded hack that interprets the KD type in the OS loader options,
563 * loads one of the (hardcoded filenames) "kdcom.dll", "kd1394.dll", or
564 * "kdusb2.dll" modules, and inserts them into the loaded module list under
565 * the name "kdcom.dll". [...]"
569 * This loop replaces a dumb call to strstr(..., "DEBUGPORT=").
570 * Indeed I want it to be case-insensitive to allow "debugport="
571 * or "DeBuGpOrT=" or... , and I don't want it to match malformed
572 * command-line options, such as:
574 * "...foo DEBUGPORT=xxx bar..."
575 * "...foo/DEBUGPORT=xxx bar..."
576 * "...foo/DEBUGPORT=bar..."
578 * i.e. the "DEBUGPORT=" switch must start with a slash and be separated
579 * from the rest by whitespace, unless it begins the command-line, e.g.:
581 * "/DEBUGPORT=COM1 foo...bar..."
582 * "...foo /DEBUGPORT=USB bar..."
584 * "...foo /DEBUGPORT= bar..."
585 * (in that case, we default the port to COM).
587 Options
= BootOptions
;
590 /* Skip possible initial whitespace */
591 Options
+= strspn(Options
, " \t");
593 /* Check whether a new option starts and it is the DEBUGPORT one */
594 if (*Options
!= '/' || _strnicmp(++Options
, "DEBUGPORT=", 10) != 0)
596 /* Search for another whitespace */
597 Options
= strpbrk(Options
, " \t");
602 /* We found the DEBUGPORT option. Move to the port name. */
611 * We have found the DEBUGPORT option. Parse the port name.
612 * Format: /DEBUGPORT=COM1 or /DEBUGPORT=FILE:\Device\HarddiskX\PartitionY\debug.log or /DEBUGPORT=FOO
613 * If we only have /DEBUGPORT= (i.e. without any port name), defaults it to "COM".
615 RtlStringCbCopyA(KdTransportDllName
, sizeof(KdTransportDllName
), "KD");
616 if (_strnicmp(Options
, "COM", 3) == 0 && '0' <= Options
[3] && Options
[3] <= '9')
618 RtlStringCbCatNA(KdTransportDllName
, sizeof(KdTransportDllName
), Options
, 3);
622 size_t i
= strcspn(Options
, " \t:"); /* Skip valid separators: whitespace or colon */
624 RtlStringCbCatA(KdTransportDllName
, sizeof(KdTransportDllName
), "COM");
626 RtlStringCbCatNA(KdTransportDllName
, sizeof(KdTransportDllName
), Options
, i
);
628 RtlStringCbCatA(KdTransportDllName
, sizeof(KdTransportDllName
), ".DLL");
629 _strupr(KdTransportDllName
);
632 * Load the transport DLL. Override the base DLL name of the
633 * loaded transport DLL to the default "KDCOM.DLL" name.
635 LoadModule(LoaderBlock
, DirPath
, KdTransportDllName
, "kdcom.dll", LoaderSystemCode
, &KdComDTE
, 60);
639 /* Load all referenced DLLs for Kernel, HAL and Kernel Debugger Transport DLL */
640 Success
= WinLdrScanImportDescriptorTable(&LoaderBlock
->LoadOrderListHead
, DirPath
, *KernelDTE
);
641 Success
&= WinLdrScanImportDescriptorTable(&LoaderBlock
->LoadOrderListHead
, DirPath
, HalDTE
);
644 Success
&= WinLdrScanImportDescriptorTable(&LoaderBlock
->LoadOrderListHead
, DirPath
, KdComDTE
);
659 USHORT OperatingSystemVersion
;
660 PLOADER_PARAMETER_BLOCK LoaderBlock
;
661 CHAR BootPath
[MAX_PATH
];
662 CHAR FileName
[MAX_PATH
];
663 CHAR BootOptions
[256];
665 ArgValue
= GetArgumentValue(Argc
, Argv
, "BootType");
668 ERR("No 'BootType' value, aborting!\n");
672 if (_stricmp(ArgValue
, "Windows") == 0 ||
673 _stricmp(ArgValue
, "Windows2003") == 0)
675 OperatingSystemVersion
= _WIN32_WINNT_WS03
;
677 else if (_stricmp(ArgValue
, "WindowsNT40") == 0)
679 OperatingSystemVersion
= _WIN32_WINNT_NT4
;
683 ERR("Unknown 'BootType' value '%s', aborting!\n", ArgValue
);
688 UiDrawProgressBarCenter(1, 100, "Loading NT...");
690 /* Retrieve the system path */
691 *BootPath
= ANSI_NULL
;
692 ArgValue
= GetArgumentValue(Argc
, Argv
, "SystemPath");
694 RtlStringCbCopyA(BootPath
, sizeof(BootPath
), ArgValue
);
697 * Check whether BootPath is a full path
698 * and if not, create a full boot path.
700 * See FsOpenFile for the technique used.
702 if (strrchr(BootPath
, ')') == NULL
)
704 /* Temporarily save the boot path */
705 RtlStringCbCopyA(FileName
, sizeof(FileName
), BootPath
);
707 /* This is not a full path. Use the current (i.e. boot) device. */
708 MachDiskGetBootPath(BootPath
, sizeof(BootPath
));
710 /* Append a path separator if needed */
711 if (*FileName
!= '\\' && *FileName
!= '/')
712 RtlStringCbCatA(BootPath
, sizeof(BootPath
), "\\");
714 /* Append the remaining path */
715 RtlStringCbCatA(BootPath
, sizeof(BootPath
), FileName
);
718 /* Append a backslash if needed */
719 if (!*BootPath
|| BootPath
[strlen(BootPath
) - 1] != '\\')
720 RtlStringCbCatA(BootPath
, sizeof(BootPath
), "\\");
722 TRACE("BootPath: '%s'\n", BootPath
);
724 /* Retrieve the boot options */
725 *BootOptions
= ANSI_NULL
;
726 ArgValue
= GetArgumentValue(Argc
, Argv
, "Options");
728 RtlStringCbCopyA(BootOptions
, sizeof(BootOptions
), ArgValue
);
730 /* Append boot-time options */
731 AppendBootTimeOptions(BootOptions
);
733 TRACE("BootOptions: '%s'\n", BootOptions
);
735 /* Check if a ramdisk file was given */
736 File
= strstr(BootOptions
, "/RDPATH=");
739 /* Copy the file name and everything else after it */
740 RtlStringCbCopyA(FileName
, sizeof(FileName
), File
+ 8);
743 *strstr(FileName
, " ") = ANSI_NULL
;
745 /* Load the ramdisk */
746 if (!RamDiskLoadVirtualFile(FileName
))
748 UiMessageBox("Failed to load RAM disk file %s", FileName
);
753 /* Let user know we started loading */
754 //UiDrawStatusText("Loading...");
756 /* Allocate and minimalist-initialize LPB */
757 AllocateAndInitLPB(&LoaderBlock
);
759 /* Load the system hive */
761 UiDrawProgressBarCenter(15, 100, "Loading system hive...");
762 Success
= WinLdrInitSystemHive(LoaderBlock
, BootPath
, FALSE
);
763 TRACE("SYSTEM hive %s\n", (Success
? "loaded" : "not loaded"));
764 /* Bail out if failure */
768 /* Load NLS data, OEM font, and prepare boot drivers list */
769 Success
= WinLdrScanSystemHive(LoaderBlock
, BootPath
);
770 TRACE("SYSTEM hive %s\n", (Success
? "scanned" : "not scanned"));
771 /* Bail out if failure */
776 return LoadAndBootWindowsCommon(OperatingSystemVersion
,
784 LoadAndBootWindowsCommon(
785 USHORT OperatingSystemVersion
,
786 PLOADER_PARAMETER_BLOCK LoaderBlock
,
791 PLOADER_PARAMETER_BLOCK LoaderBlockVA
;
793 PLDR_DATA_TABLE_ENTRY KernelDTE
;
794 KERNEL_ENTRY_POINT KiSystemStartup
;
797 TRACE("LoadAndBootWindowsCommon()\n");
800 /* Setup redirection support */
801 WinLdrSetupEms((PCHAR
)BootOptions
);
804 /* Convert BootPath to SystemRoot */
805 SystemRoot
= strstr(BootPath
, "\\");
807 /* Detect hardware */
809 UiDrawProgressBarCenter(20, 100, "Detecting hardware...");
810 LoaderBlock
->ConfigurationRoot
= MachHwDetect();
812 if (OperatingSystemVersion
== 0)
813 OperatingSystemVersion
= WinLdrDetectVersion();
815 /* Load the operating system core: the Kernel, the HAL and the Kernel Debugger Transport DLL */
816 Success
= LoadWindowsCore(OperatingSystemVersion
,
823 UiMessageBox("Error loading NTOS core.");
827 /* Load boot drivers */
829 UiDrawProgressBarCenter(100, 100, "Loading boot drivers...");
830 Success
= WinLdrLoadBootDrivers(LoaderBlock
, BootPath
);
831 TRACE("Boot drivers loading %s\n", Success
? "successful" : "failed");
833 /* Cleanup ini file */
836 /* Initialize Phase 1 - no drivers loading anymore */
837 WinLdrInitializePhase1(LoaderBlock
,
841 OperatingSystemVersion
);
843 /* Save entry-point pointer and Loader block VAs */
844 KiSystemStartup
= (KERNEL_ENTRY_POINT
)KernelDTE
->EntryPoint
;
845 LoaderBlockVA
= PaToVa(LoaderBlock
);
847 /* "Stop all motors", change videomode */
848 MachPrepareForReactOS();
851 //DumpMemoryAllocMap();
853 /* Do the machine specific initialization */
854 WinLdrSetupMachineDependent(LoaderBlock
);
856 /* Map pages and create memory descriptors */
857 WinLdrSetupMemoryLayout(LoaderBlock
);
859 /* Set processor context */
860 WinLdrSetProcessorContext();
862 /* Save final value of LoaderPagesSpanned */
863 LoaderBlock
->Extension
->LoaderPagesSpanned
= LoaderPagesSpanned
;
865 TRACE("Hello from paged mode, KiSystemStartup %p, LoaderBlockVA %p!\n",
866 KiSystemStartup
, LoaderBlockVA
);
868 // Zero KI_USER_SHARED_DATA page
869 memset((PVOID
)KI_USER_SHARED_DATA
, 0, MM_PAGE_SIZE
);
871 WinLdrpDumpMemoryDescriptors(LoaderBlockVA
);
872 WinLdrpDumpBootDriver(LoaderBlockVA
);
874 WinLdrpDumpArcDisks(LoaderBlockVA
);
878 (*KiSystemStartup
)(LoaderBlockVA
);
883 WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock
)
886 PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor
;
888 NextMd
= LoaderBlock
->MemoryDescriptorListHead
.Flink
;
890 while (NextMd
!= &LoaderBlock
->MemoryDescriptorListHead
)
892 MemoryDescriptor
= CONTAINING_RECORD(NextMd
, MEMORY_ALLOCATION_DESCRIPTOR
, ListEntry
);
894 TRACE("BP %08X PC %04X MT %d\n", MemoryDescriptor
->BasePage
,
895 MemoryDescriptor
->PageCount
, MemoryDescriptor
->MemoryType
);
897 NextMd
= MemoryDescriptor
->ListEntry
.Flink
;
902 WinLdrpDumpBootDriver(PLOADER_PARAMETER_BLOCK LoaderBlock
)
905 PBOOT_DRIVER_LIST_ENTRY BootDriver
;
907 NextBd
= LoaderBlock
->BootDriverListHead
.Flink
;
909 while (NextBd
!= &LoaderBlock
->BootDriverListHead
)
911 BootDriver
= CONTAINING_RECORD(NextBd
, BOOT_DRIVER_LIST_ENTRY
, Link
);
913 TRACE("BootDriver %wZ DTE %08X RegPath: %wZ\n", &BootDriver
->FilePath
,
914 BootDriver
->LdrEntry
, &BootDriver
->RegistryPath
);
916 NextBd
= BootDriver
->Link
.Flink
;
921 WinLdrpDumpArcDisks(PLOADER_PARAMETER_BLOCK LoaderBlock
)
924 PARC_DISK_SIGNATURE ArcDisk
;
926 NextBd
= LoaderBlock
->ArcDiskInformation
->DiskSignatureListHead
.Flink
;
928 while (NextBd
!= &LoaderBlock
->ArcDiskInformation
->DiskSignatureListHead
)
930 ArcDisk
= CONTAINING_RECORD(NextBd
, ARC_DISK_SIGNATURE
, ListEntry
);
932 TRACE("ArcDisk %s checksum: 0x%X, signature: 0x%X\n",
933 ArcDisk
->ArcName
, ArcDisk
->CheckSum
, ArcDisk
->Signature
);
935 NextBd
= ArcDisk
->ListEntry
.Flink
;