-/*\r
- * FreeLoader\r
- *\r
- * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>\r
- * Copyright (C) 2006 Aleksey Bragin <aleksey@reactos.org>\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
- */\r
-\r
-#include <freeldr.h>\r
-\r
-#include <ndk/ldrtypes.h>\r
-#include <debug.h>\r
-\r
-//FIXME: Do a better way to retrieve Arc disk information\r
-extern ULONG reactos_disk_count;\r
-extern ARC_DISK_SIGNATURE reactos_arc_disk_info[];\r
-extern char reactos_arc_strings[32][256];\r
-extern char reactos_arc_hardware_data[HW_MAX_ARC_HEAP_SIZE];\r
-\r
-BOOLEAN\r
-WinLdrCheckForLoadedDll(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,\r
- IN PCH DllName,\r
- OUT PLDR_DATA_TABLE_ENTRY *LoadedEntry);\r
-\r
-// debug stuff\r
-VOID DumpMemoryAllocMap(VOID);\r
-VOID WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock);\r
-VOID WinLdrpDumpBootDriver(PLOADER_PARAMETER_BLOCK LoaderBlock);\r
-VOID WinLdrpDumpArcDisks(PLOADER_PARAMETER_BLOCK LoaderBlock);\r
-\r
-\r
-// Init "phase 0"\r
-VOID\r
-AllocateAndInitLPB(PLOADER_PARAMETER_BLOCK *OutLoaderBlock)\r
-{\r
- PLOADER_PARAMETER_BLOCK LoaderBlock;\r
-\r
- /* Allocate and zero-init the LPB */\r
- LoaderBlock = MmHeapAlloc(sizeof(LOADER_PARAMETER_BLOCK));\r
- RtlZeroMemory(LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));\r
-\r
- /* Init three critical lists, used right away */\r
- InitializeListHead(&LoaderBlock->LoadOrderListHead);\r
- InitializeListHead(&LoaderBlock->MemoryDescriptorListHead);\r
- InitializeListHead(&LoaderBlock->BootDriverListHead);\r
-\r
- /* Alloc space for NLS (it will be converted to VA in WinLdrLoadNLS) */\r
- LoaderBlock->NlsData = MmHeapAlloc(sizeof(NLS_DATA_BLOCK));\r
- if (LoaderBlock->NlsData == NULL)\r
- {\r
- UiMessageBox("Failed to allocate memory for NLS table data!");\r
- return;\r
- }\r
- RtlZeroMemory(LoaderBlock->NlsData, sizeof(NLS_DATA_BLOCK));\r
-\r
- *OutLoaderBlock = LoaderBlock;\r
-}\r
-\r
-// Init "phase 1"\r
-VOID\r
-WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock,\r
- PCHAR Options,\r
- PCHAR SystemPath,\r
- WORD VersionToBoot)\r
-{\r
- /* Examples of correct options and paths */\r
- //CHAR Options[] = "/DEBUGPORT=COM1 /BAUDRATE=115200";\r
- //CHAR Options[] = "/NODEBUG";\r
- //CHAR SystemRoot[] = "\\WINNT\\";\r
- //CHAR ArcBoot[] = "multi(0)disk(0)rdisk(0)partition(1)";\r
-\r
- CHAR HalPath[] = "\\";\r
- CHAR SystemRoot[256];\r
- CHAR ArcBoot[256];\r
- ULONG i, PathSeparator;\r
- PLOADER_PARAMETER_EXTENSION Extension;\r
-\r
- LoaderBlock->u.I386.CommonDataArea = NULL; // Force No ABIOS support\r
-\r
- /* Construct SystemRoot and ArcBoot from SystemPath */\r
- PathSeparator = strstr(SystemPath, "\\") - SystemPath;\r
- strncpy(ArcBoot, SystemPath, PathSeparator);\r
- ArcBoot[PathSeparator] = 0;\r
- strcpy(SystemRoot, &SystemPath[PathSeparator]);\r
- strcat(SystemRoot, "\\");\r
-\r
- DbgPrint((DPRINT_WINDOWS, "ArcBoot: %s\n", ArcBoot));\r
- DbgPrint((DPRINT_WINDOWS, "SystemRoot: %s\n", SystemRoot));\r
- DbgPrint((DPRINT_WINDOWS, "Options: %s\n", Options));\r
-\r
- /* Fill Arc BootDevice */\r
- LoaderBlock->ArcBootDeviceName = MmHeapAlloc(strlen(ArcBoot)+1);\r
- strcpy(LoaderBlock->ArcBootDeviceName, ArcBoot);\r
- LoaderBlock->ArcBootDeviceName = PaToVa(LoaderBlock->ArcBootDeviceName);\r
-\r
- /* Fill Arc HalDevice, it matches ArcBoot path */\r
- LoaderBlock->ArcHalDeviceName = MmHeapAlloc(strlen(ArcBoot)+1);\r
- strcpy(LoaderBlock->ArcHalDeviceName, ArcBoot);\r
- LoaderBlock->ArcHalDeviceName = PaToVa(LoaderBlock->ArcHalDeviceName);\r
-\r
- /* Fill SystemRoot */\r
- LoaderBlock->NtBootPathName = MmHeapAlloc(strlen(SystemRoot)+1);\r
- strcpy(LoaderBlock->NtBootPathName, SystemRoot);\r
- LoaderBlock->NtBootPathName = PaToVa(LoaderBlock->NtBootPathName);\r
-\r
- /* Fill NtHalPathName */\r
- LoaderBlock->NtHalPathName = MmHeapAlloc(strlen(HalPath)+1);\r
- strcpy(LoaderBlock->NtHalPathName, HalPath);\r
- LoaderBlock->NtHalPathName = PaToVa(LoaderBlock->NtHalPathName);\r
-\r
- /* Fill load options */\r
- LoaderBlock->LoadOptions = MmHeapAlloc(strlen(Options)+1);\r
- strcpy(LoaderBlock->LoadOptions, Options);\r
- LoaderBlock->LoadOptions = PaToVa(LoaderBlock->LoadOptions);\r
-\r
- /* Arc devices */\r
- LoaderBlock->ArcDiskInformation = (PARC_DISK_INFORMATION)MmHeapAlloc(sizeof(ARC_DISK_INFORMATION));\r
- InitializeListHead(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead);\r
-\r
- /* Convert ARC disk information from freeldr to a correct format */\r
- for (i = 0; i < reactos_disk_count; i++)\r
- {\r
- PARC_DISK_SIGNATURE ArcDiskInfo;\r
-\r
- /* Get the ARC structure */\r
- ArcDiskInfo = (PARC_DISK_SIGNATURE)MmHeapAlloc(sizeof(ARC_DISK_SIGNATURE));\r
- RtlZeroMemory(ArcDiskInfo, sizeof(ARC_DISK_SIGNATURE));\r
-\r
- /* Copy the data over */\r
- ArcDiskInfo->Signature = reactos_arc_disk_info[i].Signature;\r
- ArcDiskInfo->CheckSum = reactos_arc_disk_info[i].CheckSum;\r
-\r
- /* Copy the ARC Name */\r
- ArcDiskInfo->ArcName = (PCHAR)MmHeapAlloc(sizeof(CHAR)*256);\r
- strcpy(ArcDiskInfo->ArcName, reactos_arc_disk_info[i].ArcName);\r
- ArcDiskInfo->ArcName = (PCHAR)PaToVa(ArcDiskInfo->ArcName);\r
-\r
- /* Mark partition table as valid */\r
- ArcDiskInfo->ValidPartitionTable = TRUE; \r
-\r
- /* Insert into the list */\r
- InsertTailList(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead,\r
- &ArcDiskInfo->ListEntry);\r
- }\r
-\r
- /* Convert all list's to Virtual address */\r
-\r
- /* Convert the ArcDisks list to virtual address */\r
- List_PaToVa(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead);\r
- LoaderBlock->ArcDiskInformation = PaToVa(LoaderBlock->ArcDiskInformation);\r
-\r
- /* Convert configuration entries to VA */\r
- ConvertConfigToVA(LoaderBlock->ConfigurationRoot);\r
- LoaderBlock->ConfigurationRoot = PaToVa(LoaderBlock->ConfigurationRoot);\r
-\r
- /* Convert all DTE into virtual addresses */\r
- List_PaToVa(&LoaderBlock->LoadOrderListHead);\r
-\r
- /* this one will be converted right before switching to\r
- virtual paging mode */\r
- //List_PaToVa(&LoaderBlock->MemoryDescriptorListHead);\r
-\r
- /* Convert list of boot drivers */\r
- List_PaToVa(&LoaderBlock->BootDriverListHead);\r
-\r
- /* Initialize Extension now */\r
- Extension = MmHeapAlloc(sizeof(LOADER_PARAMETER_EXTENSION));\r
- if (Extension == NULL)\r
- {\r
- UiMessageBox("Failed to allocate LPB Extension!");\r
- return;\r
- }\r
- RtlZeroMemory(Extension, sizeof(LOADER_PARAMETER_EXTENSION));\r
-\r
- /* Save size and version information */\r
- Extension->Size = sizeof(LOADER_PARAMETER_EXTENSION);\r
- Extension->MajorVersion = (VersionToBoot & 0xFF00) >> 8;\r
- Extension->MinorVersion = VersionToBoot & 0xFF;\r
-\r
-\r
- LoaderBlock->Extension = PaToVa(Extension);\r
-}\r
-\r
-// Last step before going virtual\r
-void WinLdrSetupForNt(PLOADER_PARAMETER_BLOCK LoaderBlock,\r
- PVOID *GdtIdt,\r
- ULONG *PcrBasePage,\r
- ULONG *TssBasePage)\r
-{\r
- ULONG TssSize;\r
- ULONG TssPages;\r
- ULONG_PTR Pcr = 0;\r
- ULONG_PTR Tss = 0;\r
- ULONG BlockSize, NumPages;\r
-\r
- LoaderBlock->u.I386.CommonDataArea = NULL;//CommonDataArea;\r
- //LoaderBlock->u.I386.MachineType = MachineType; //FIXME: MachineType?\r
-\r
- /* Allocate 2 pages for PCR */\r
- Pcr = (ULONG_PTR)MmAllocateMemoryWithType(2 * MM_PAGE_SIZE, LoaderStartupPcrPage);\r
- *PcrBasePage = Pcr >> MM_PAGE_SHIFT;\r
-\r
- if (Pcr == 0)\r
- {\r
- UiMessageBox("Can't allocate PCR\n");\r
- return;\r
- }\r
-\r
- /* Allocate TSS */\r
- TssSize = (sizeof(KTSS) + MM_PAGE_SIZE) & ~(MM_PAGE_SIZE - 1);\r
- TssPages = TssSize / MM_PAGE_SIZE;\r
-\r
- Tss = (ULONG_PTR)MmAllocateMemoryWithType(TssSize, LoaderMemoryData);\r
-\r
- *TssBasePage = Tss >> MM_PAGE_SHIFT;\r
-\r
- /* Allocate space for new GDT + IDT */\r
- BlockSize = NUM_GDT*sizeof(KGDTENTRY) + NUM_IDT*sizeof(KIDTENTRY);//FIXME: Use GDT/IDT limits here?\r
- NumPages = (BlockSize + MM_PAGE_SIZE - 1) >> MM_PAGE_SHIFT;\r
- *GdtIdt = (PKGDTENTRY)MmAllocateMemoryWithType(NumPages * MM_PAGE_SIZE, LoaderMemoryData);\r
-\r
- if (*GdtIdt == NULL)\r
- {\r
- UiMessageBox("Can't allocate pages for GDT+IDT!\n");\r
- return;\r
- }\r
-\r
- /* Zero newly prepared GDT+IDT */\r
- RtlZeroMemory(*GdtIdt, NumPages << MM_PAGE_SHIFT);\r
-}\r
-\r
-BOOLEAN\r
-WinLdrLoadDeviceDriver(PLOADER_PARAMETER_BLOCK LoaderBlock,\r
- LPSTR BootPath,\r
- PUNICODE_STRING FilePath,\r
- ULONG Flags,\r
- PLDR_DATA_TABLE_ENTRY *DriverDTE)\r
-{\r
- CHAR FullPath[1024];\r
- CHAR DriverPath[1024];\r
- CHAR DllName[1024];\r
- PCHAR DriverNamePos;\r
- BOOLEAN Status;\r
- PVOID DriverBase;\r
-\r
- // Separate the path to file name and directory path\r
- sprintf(DriverPath, "%wZ", FilePath);\r
- DriverNamePos = strrchr(DriverPath, '\\');\r
- if (DriverNamePos != NULL)\r
- {\r
- // Copy the name\r
- strcpy(DllName, DriverNamePos+1);\r
-\r
- // Cut out the name from the path\r
- *(DriverNamePos+1) = 0;\r
- }\r
-\r
- DbgPrint((DPRINT_WINDOWS, "DriverPath: %s, DllName: %s, LPB %p\n", DriverPath, DllName, LoaderBlock));\r
-\r
-\r
- // Check if driver is already loaded\r
- Status = WinLdrCheckForLoadedDll(LoaderBlock, DllName, DriverDTE);\r
- if (Status)\r
- {\r
- // We've got the pointer to its DTE, just return success\r
- return TRUE;\r
- }\r
-\r
- // It's not loaded, we have to load it\r
- sprintf(FullPath,"%s%wZ", BootPath, FilePath);\r
- Status = WinLdrLoadImage(FullPath, LoaderBootDriver, &DriverBase);\r
- if (!Status)\r
- return FALSE;\r
-\r
- // Allocate a DTE for it\r
- Status = WinLdrAllocateDataTableEntry(LoaderBlock, DllName, DllName, DriverBase, DriverDTE);\r
- if (!Status)\r
- {\r
- DbgPrint((DPRINT_WINDOWS, "WinLdrAllocateDataTableEntry() failed\n"));\r
- return FALSE;\r
- }\r
-\r
- // Modify any flags, if needed\r
- (*DriverDTE)->Flags |= Flags;\r
-\r
- // Look for any dependencies it may have, and load them too\r
- sprintf(FullPath,"%s%s", BootPath, DriverPath);\r
- Status = WinLdrScanImportDescriptorTable(LoaderBlock, FullPath, *DriverDTE);\r
- if (!Status)\r
- {\r
- DbgPrint((DPRINT_WINDOWS, "WinLdrScanImportDescriptorTable() failed for %s\n",\r
- FullPath));\r
- return FALSE;\r
- }\r
-\r
- return TRUE;\r
-}\r
-\r
-BOOLEAN\r
-WinLdrLoadBootDrivers(PLOADER_PARAMETER_BLOCK LoaderBlock,\r
- LPSTR BootPath)\r
-{\r
- PLIST_ENTRY NextBd;\r
- PBOOT_DRIVER_LIST_ENTRY BootDriver;\r
- BOOLEAN Status;\r
-\r
- // Walk through the boot drivers list\r
- NextBd = LoaderBlock->BootDriverListHead.Flink;\r
-\r
- while (NextBd != &LoaderBlock->BootDriverListHead)\r
- {\r
- BootDriver = CONTAINING_RECORD(NextBd, BOOT_DRIVER_LIST_ENTRY, ListEntry);\r
-\r
- DbgPrint((DPRINT_WINDOWS, "BootDriver %wZ DTE %08X RegPath: %wZ\n", &BootDriver->FilePath,\r
- BootDriver->DataTableEntry, &BootDriver->RegistryPath));\r
-\r
- // Paths are relative (FIXME: Are they always relative?)\r
-\r
- // Load it\r
- Status = WinLdrLoadDeviceDriver(LoaderBlock, BootPath, &BootDriver->FilePath,\r
- 0, &BootDriver->DataTableEntry);\r
-\r
- // If loading failed - cry loudly\r
- //FIXME: Maybe remove it from the list and try to continue?\r
- if (!Status)\r
- {\r
- UiMessageBox("Can't load boot driver!");\r
- return FALSE;\r
- }\r
-\r
- // Convert the RegistryPath and DTE addresses to VA since we are not going to use it anymore\r
- BootDriver->RegistryPath.Buffer = PaToVa(BootDriver->RegistryPath.Buffer);\r
- BootDriver->DataTableEntry = PaToVa(BootDriver->DataTableEntry);\r
-\r
- NextBd = BootDriver->ListEntry.Flink;\r
- }\r
-\r
- return TRUE;\r
-}\r
-\r
-VOID\r
-LoadAndBootWindows(PCSTR OperatingSystemName, WORD OperatingSystemVersion)\r
-{\r
- CHAR MsgBuffer[256];\r
- CHAR SystemPath[512], SearchPath[512];\r
- CHAR FileName[512];\r
- CHAR BootPath[512];\r
- CHAR BootOptions[256];\r
- PVOID NtosBase = NULL, HalBase = NULL, KdComBase = NULL;\r
- BOOLEAN Status;\r
- ULONG SectionId;\r
- ULONG BootDevice;\r
- PLOADER_PARAMETER_BLOCK LoaderBlock, LoaderBlockVA;\r
- KERNEL_ENTRY_POINT KiSystemStartup;\r
- PLDR_DATA_TABLE_ENTRY KernelDTE, HalDTE, KdComDTE = NULL;\r
- // Mm-related things\r
- PVOID GdtIdt;\r
- ULONG PcrBasePage=0;\r
- ULONG TssBasePage=0;\r
-\r
- //sprintf(MsgBuffer,"Booting Microsoft(R) Windows(R) OS version '%04x' is not implemented yet", OperatingSystemVersion);\r
- //UiMessageBox(MsgBuffer);\r
-\r
- // Open the operating system section\r
- // specified in the .ini file\r
- if (!IniOpenSection(OperatingSystemName, &SectionId))\r
- {\r
- sprintf(MsgBuffer,"Operating System section '%s' not found in freeldr.ini", OperatingSystemName);\r
- UiMessageBox(MsgBuffer);\r
- return;\r
- }\r
-\r
- UiDrawBackdrop();\r
- UiDrawStatusText("Detecting Hardware...");\r
- UiDrawProgressBarCenter(1, 100, "Loading Windows...");\r
-\r
- /* Make sure the system path is set in the .ini file */\r
- if (!IniReadSettingByName(SectionId, "SystemPath", SystemPath, sizeof(SystemPath)))\r
- {\r
- UiMessageBox("System path not specified for selected operating system.");\r
- return;\r
- }\r
-\r
- /* Read booting options */\r
- if (!IniReadSettingByName(SectionId, "Options", BootOptions, sizeof(BootOptions)))\r
- {\r
- /* Nothing read, make the string empty */\r
- strcpy(BootOptions, "");\r
- }\r
-\r
- /* Normalize system path */\r
- if (!MachDiskNormalizeSystemPath(SystemPath, sizeof(SystemPath)))\r
- {\r
- UiMessageBox("Invalid system path");\r
- return;\r
- }\r
-\r
- /* Let user know we started loading */\r
- UiDrawStatusText("Loading...");\r
-\r
- /* Try to open system drive */\r
- BootDevice = 0xffffffff;\r
- if (!FsOpenSystemVolume(SystemPath, BootPath, &BootDevice))\r
- {\r
- UiMessageBox("Failed to open boot drive.");\r
- return;\r
- }\r
-\r
- /* append a backslash */\r
- if ((strlen(BootPath)==0) ||\r
- BootPath[strlen(BootPath)] != '\\')\r
- strcat(BootPath, "\\");\r
-\r
- DbgPrint((DPRINT_WINDOWS,"SystemRoot: '%s'\n", BootPath));\r
-\r
- /* Allocate and minimalistic-initialize LPB */\r
- AllocateAndInitLPB(&LoaderBlock);\r
-\r
- /* Detect hardware */\r
- MachHwDetect();\r
- LoaderBlock->ConfigurationRoot = MmHeapAlloc(16 * 1024);\r
- RtlCopyMemory(LoaderBlock->ConfigurationRoot,\r
- (PVOID)reactos_arc_hardware_data, 16 * 1024);\r
-\r
- /* Load kernel */\r
- strcpy(FileName, BootPath);\r
- strcat(FileName, "SYSTEM32\\NTOSKRNL.EXE");\r
- Status = WinLdrLoadImage(FileName, LoaderSystemCode, &NtosBase);\r
- DbgPrint((DPRINT_WINDOWS, "Ntos loaded with status %d at %p\n", Status, NtosBase));\r
-\r
- /* Load HAL */\r
- strcpy(FileName, BootPath);\r
- strcat(FileName, "SYSTEM32\\HAL.DLL");\r
- Status = WinLdrLoadImage(FileName, LoaderHalCode, &HalBase);\r
- DbgPrint((DPRINT_WINDOWS, "HAL loaded with status %d at %p\n", Status, HalBase));\r
-\r
- /* Load kernel-debugger support dll */\r
- if (OperatingSystemVersion > _WIN32_WINNT_WIN2K)\r
- {\r
- strcpy(FileName, BootPath);\r
- strcat(FileName, "SYSTEM32\\KDCOM.DLL");\r
- Status = WinLdrLoadImage(FileName, LoaderBootDriver, &KdComBase);\r
- DbgPrint((DPRINT_WINDOWS, "KdCom loaded with status %d at %p\n", Status, KdComBase));\r
- }\r
-\r
- /* Allocate data table entries for above-loaded modules */\r
- WinLdrAllocateDataTableEntry(LoaderBlock, "ntoskrnl.exe",\r
- "WINNT\\SYSTEM32\\NTOSKRNL.EXE", NtosBase, &KernelDTE);\r
- WinLdrAllocateDataTableEntry(LoaderBlock, "hal.dll",\r
- "WINNT\\SYSTEM32\\HAL.DLL", HalBase, &HalDTE);\r
- if (OperatingSystemVersion > _WIN32_WINNT_WIN2K)\r
- {\r
- WinLdrAllocateDataTableEntry(LoaderBlock, "kdcom.dll",\r
- "WINNT\\SYSTEM32\\KDCOM.DLL", KdComBase, &KdComDTE);\r
- }\r
-\r
- /* Load all referenced DLLs for kernel, HAL and kdcom.dll */\r
- strcpy(SearchPath, BootPath);\r
- strcat(SearchPath, "SYSTEM32\\");\r
- WinLdrScanImportDescriptorTable(LoaderBlock, SearchPath, KernelDTE);\r
- WinLdrScanImportDescriptorTable(LoaderBlock, SearchPath, HalDTE);\r
- if (KdComDTE)\r
- WinLdrScanImportDescriptorTable(LoaderBlock, SearchPath, KdComDTE);\r
-\r
- /* Load Hive, and then NLS data, OEM font, and prepare boot drivers list */\r
- Status = WinLdrLoadAndScanSystemHive(LoaderBlock, BootPath);\r
- DbgPrint((DPRINT_WINDOWS, "SYSTEM hive loaded and scanned with status %d\n", Status));\r
-\r
- /* Load boot drivers */\r
- Status = WinLdrLoadBootDrivers(LoaderBlock, BootPath);\r
- DbgPrint((DPRINT_WINDOWS, "Boot drivers loaded with status %d\n", Status));\r
-\r
- /* Initialize Phase 1 - no drivers loading anymore */\r
- WinLdrInitializePhase1(LoaderBlock, BootOptions, SystemPath, OperatingSystemVersion);\r
-\r
- /* Alloc PCR, TSS, do magic things with the GDT/IDT */\r
- WinLdrSetupForNt(LoaderBlock, &GdtIdt, &PcrBasePage, &TssBasePage);\r
-\r
- /* Save entry-point pointer and Loader block VAs */\r
- KiSystemStartup = (KERNEL_ENTRY_POINT)KernelDTE->EntryPoint;\r
- LoaderBlockVA = PaToVa(LoaderBlock);\r
-\r
- /* "Stop all motors", change videomode */\r
- DiskStopFloppyMotor();\r
- MachVideoPrepareForReactOS(FALSE);\r
-\r
- /* Debugging... */\r
- //DumpMemoryAllocMap();\r
-\r
- /* Turn on paging mode of CPU*/\r
- WinLdrTurnOnPaging(LoaderBlock, PcrBasePage, TssBasePage, GdtIdt);\r
-\r
- DbgPrint((DPRINT_WINDOWS, "Hello from paged mode, KiSystemStartup %p, LoaderBlockVA %p!\n",\r
- KiSystemStartup, LoaderBlockVA));\r
-\r
- WinLdrpDumpMemoryDescriptors(LoaderBlockVA);\r
- WinLdrpDumpBootDriver(LoaderBlockVA);\r
- WinLdrpDumpArcDisks(LoaderBlockVA);\r
-\r
- //FIXME: If I substitute this debugging checkpoint, GCC will "optimize away" the code below\r
- //while (1) {};\r
- /*asm(".intel_syntax noprefix\n");\r
- asm("test1:\n");\r
- asm("jmp test1\n");\r
- asm(".att_syntax\n");*/\r
-\r
- /* Pass control */\r
- (*KiSystemStartup)(LoaderBlockVA);\r
-\r
- return;\r
-}\r
-\r
-VOID\r
-WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock)\r
-{\r
- PLIST_ENTRY NextMd;\r
- PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor;\r
-\r
- NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;\r
-\r
- while (NextMd != &LoaderBlock->MemoryDescriptorListHead)\r
- {\r
- MemoryDescriptor = CONTAINING_RECORD(NextMd, MEMORY_ALLOCATION_DESCRIPTOR, ListEntry);\r
-\r
- DbgPrint((DPRINT_WINDOWS, "BP %08X PC %04X MT %d\n", MemoryDescriptor->BasePage,\r
- MemoryDescriptor->PageCount, MemoryDescriptor->MemoryType));\r
-\r
- NextMd = MemoryDescriptor->ListEntry.Flink;\r
- }\r
-}\r
-\r
-VOID\r
-WinLdrpDumpBootDriver(PLOADER_PARAMETER_BLOCK LoaderBlock)\r
-{\r
- PLIST_ENTRY NextBd;\r
- PBOOT_DRIVER_LIST_ENTRY BootDriver;\r
-\r
- NextBd = LoaderBlock->BootDriverListHead.Flink;\r
-\r
- while (NextBd != &LoaderBlock->BootDriverListHead)\r
- {\r
- BootDriver = CONTAINING_RECORD(NextBd, BOOT_DRIVER_LIST_ENTRY, ListEntry);\r
-\r
- DbgPrint((DPRINT_WINDOWS, "BootDriver %wZ DTE %08X RegPath: %wZ\n", &BootDriver->FilePath,\r
- BootDriver->DataTableEntry, &BootDriver->RegistryPath));\r
-\r
- NextBd = BootDriver->ListEntry.Flink;\r
- }\r
-}\r
-\r
-VOID\r
-WinLdrpDumpArcDisks(PLOADER_PARAMETER_BLOCK LoaderBlock)\r
-{\r
- PLIST_ENTRY NextBd;\r
- PARC_DISK_SIGNATURE ArcDisk;\r
-\r
- NextBd = LoaderBlock->ArcDiskInformation->DiskSignatureListHead.Flink;\r
-\r
- while (NextBd != &LoaderBlock->ArcDiskInformation->DiskSignatureListHead)\r
- {\r
- ArcDisk = CONTAINING_RECORD(NextBd, ARC_DISK_SIGNATURE, ListEntry);\r
-\r
- DbgPrint((DPRINT_WINDOWS, "ArcDisk %s checksum: 0x%X, signature: 0x%X\n",\r
- ArcDisk->ArcName, ArcDisk->CheckSum, ArcDisk->Signature));\r
-\r
- NextBd = ArcDisk->ListEntry.Flink;\r
- }\r
-}\r
-\r
+/*
+ * FreeLoader
+ *
+ * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
+ * Copyright (C) 2006 Aleksey Bragin <aleksey@reactos.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <freeldr.h>
+
+#include <ndk/ldrtypes.h>
+#include <debug.h>
+
+// TODO: Move to .h
+void WinLdrSetupForNt(PLOADER_PARAMETER_BLOCK LoaderBlock,
+ PVOID *GdtIdt,
+ ULONG *PcrBasePage,
+ ULONG *TssBasePage);
+
+//FIXME: Do a better way to retrieve Arc disk information
+extern ULONG reactos_disk_count;
+extern ARC_DISK_SIGNATURE reactos_arc_disk_info[];
+extern char reactos_arc_strings[32][256];
+
+extern BOOLEAN UseRealHeap;
+extern ULONG LoaderPagesSpanned;
+
+BOOLEAN
+WinLdrCheckForLoadedDll(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
+ IN PCH DllName,
+ OUT PLDR_DATA_TABLE_ENTRY *LoadedEntry);
+
+// debug stuff
+VOID DumpMemoryAllocMap(VOID);
+VOID WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock);
+VOID WinLdrpDumpBootDriver(PLOADER_PARAMETER_BLOCK LoaderBlock);
+VOID WinLdrpDumpArcDisks(PLOADER_PARAMETER_BLOCK LoaderBlock);
+
+
+// Init "phase 0"
+VOID
+AllocateAndInitLPB(PLOADER_PARAMETER_BLOCK *OutLoaderBlock)
+{
+ PLOADER_PARAMETER_BLOCK LoaderBlock;
+
+ /* Allocate and zero-init the LPB */
+ LoaderBlock = MmHeapAlloc(sizeof(LOADER_PARAMETER_BLOCK));
+ RtlZeroMemory(LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));
+
+ /* Init three critical lists, used right away */
+ InitializeListHead(&LoaderBlock->LoadOrderListHead);
+ InitializeListHead(&LoaderBlock->MemoryDescriptorListHead);
+ InitializeListHead(&LoaderBlock->BootDriverListHead);
+
+ /* Alloc space for NLS (it will be converted to VA in WinLdrLoadNLS) */
+ LoaderBlock->NlsData = MmHeapAlloc(sizeof(NLS_DATA_BLOCK));
+ if (LoaderBlock->NlsData == NULL)
+ {
+ UiMessageBox("Failed to allocate memory for NLS table data!");
+ return;
+ }
+ RtlZeroMemory(LoaderBlock->NlsData, sizeof(NLS_DATA_BLOCK));
+
+ *OutLoaderBlock = LoaderBlock;
+}
+
+// Init "phase 1"
+VOID
+WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock,
+ PCHAR Options,
+ PCHAR SystemRoot,
+ PCHAR BootPath,
+ USHORT VersionToBoot)
+{
+ /* Examples of correct options and paths */
+ //CHAR Options[] = "/DEBUGPORT=COM1 /BAUDRATE=115200";
+ //CHAR Options[] = "/NODEBUG";
+ //CHAR SystemRoot[] = "\\WINNT\\";
+ //CHAR ArcBoot[] = "multi(0)disk(0)rdisk(0)partition(1)";
+
+ CHAR HalPath[] = "\\";
+ CHAR ArcBoot[256];
+ CHAR MiscFiles[256];
+ ULONG i, PathSeparator;
+ PLOADER_PARAMETER_EXTENSION Extension;
+
+ /* Construct SystemRoot and ArcBoot from SystemPath */
+ PathSeparator = strstr(BootPath, "\\") - BootPath;
+ strncpy(ArcBoot, BootPath, PathSeparator);
+ ArcBoot[PathSeparator] = 0;
+
+ DPRINTM(DPRINT_WINDOWS, "ArcBoot: %s\n", ArcBoot);
+ DPRINTM(DPRINT_WINDOWS, "SystemRoot: %s\n", SystemRoot);
+ DPRINTM(DPRINT_WINDOWS, "Options: %s\n", Options);
+
+ /* Fill Arc BootDevice */
+ LoaderBlock->ArcBootDeviceName = MmHeapAlloc(strlen(ArcBoot)+1);
+ strcpy(LoaderBlock->ArcBootDeviceName, ArcBoot);
+ LoaderBlock->ArcBootDeviceName = PaToVa(LoaderBlock->ArcBootDeviceName);
+
+ /* Fill Arc HalDevice, it matches ArcBoot path */
+ LoaderBlock->ArcHalDeviceName = MmHeapAlloc(strlen(ArcBoot)+1);
+ strcpy(LoaderBlock->ArcHalDeviceName, ArcBoot);
+ LoaderBlock->ArcHalDeviceName = PaToVa(LoaderBlock->ArcHalDeviceName);
+
+ /* Fill SystemRoot */
+ LoaderBlock->NtBootPathName = MmHeapAlloc(strlen(SystemRoot)+1);
+ strcpy(LoaderBlock->NtBootPathName, SystemRoot);
+ LoaderBlock->NtBootPathName = PaToVa(LoaderBlock->NtBootPathName);
+
+ /* Fill NtHalPathName */
+ LoaderBlock->NtHalPathName = MmHeapAlloc(strlen(HalPath)+1);
+ strcpy(LoaderBlock->NtHalPathName, HalPath);
+ LoaderBlock->NtHalPathName = PaToVa(LoaderBlock->NtHalPathName);
+
+ /* Fill load options */
+ LoaderBlock->LoadOptions = MmHeapAlloc(strlen(Options)+1);
+ strcpy(LoaderBlock->LoadOptions, Options);
+ LoaderBlock->LoadOptions = PaToVa(LoaderBlock->LoadOptions);
+
+ /* Arc devices */
+ LoaderBlock->ArcDiskInformation = (PARC_DISK_INFORMATION)MmHeapAlloc(sizeof(ARC_DISK_INFORMATION));
+ InitializeListHead(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead);
+
+ /* Convert ARC disk information from freeldr to a correct format */
+ for (i = 0; i < reactos_disk_count; i++)
+ {
+ PARC_DISK_SIGNATURE ArcDiskInfo;
+
+ /* Get the ARC structure */
+ ArcDiskInfo = (PARC_DISK_SIGNATURE)MmHeapAlloc(sizeof(ARC_DISK_SIGNATURE));
+ RtlZeroMemory(ArcDiskInfo, sizeof(ARC_DISK_SIGNATURE));
+
+ /* Copy the data over */
+ ArcDiskInfo->Signature = reactos_arc_disk_info[i].Signature;
+ ArcDiskInfo->CheckSum = reactos_arc_disk_info[i].CheckSum;
+
+ /* Copy the ARC Name */
+ ArcDiskInfo->ArcName = (PCHAR)MmHeapAlloc(sizeof(CHAR)*256);
+ strcpy(ArcDiskInfo->ArcName, reactos_arc_disk_info[i].ArcName);
+ ArcDiskInfo->ArcName = (PCHAR)PaToVa(ArcDiskInfo->ArcName);
+
+ /* Mark partition table as valid */
+ ArcDiskInfo->ValidPartitionTable = TRUE;
+
+ /* Insert into the list */
+ InsertTailList(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead,
+ &ArcDiskInfo->ListEntry);
+ }
+
+ /* Convert all list's to Virtual address */
+
+ /* Convert the ArcDisks list to virtual address */
+ List_PaToVa(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead);
+ LoaderBlock->ArcDiskInformation = PaToVa(LoaderBlock->ArcDiskInformation);
+
+ /* Convert configuration entries to VA */
+ ConvertConfigToVA(LoaderBlock->ConfigurationRoot);
+ LoaderBlock->ConfigurationRoot = PaToVa(LoaderBlock->ConfigurationRoot);
+
+ /* Convert all DTE into virtual addresses */
+ List_PaToVa(&LoaderBlock->LoadOrderListHead);
+
+ /* this one will be converted right before switching to
+ virtual paging mode */
+ //List_PaToVa(&LoaderBlock->MemoryDescriptorListHead);
+
+ /* Convert list of boot drivers */
+ List_PaToVa(&LoaderBlock->BootDriverListHead);
+
+ /* Initialize Extension now */
+ Extension = MmHeapAlloc(sizeof(LOADER_PARAMETER_EXTENSION));
+ if (Extension == NULL)
+ {
+ UiMessageBox("Failed to allocate LPB Extension!");
+ return;
+ }
+ RtlZeroMemory(Extension, sizeof(LOADER_PARAMETER_EXTENSION));
+
+ /* Fill LPB extension */
+ Extension->Size = sizeof(LOADER_PARAMETER_EXTENSION);
+ Extension->MajorVersion = (VersionToBoot & 0xFF00) >> 8;
+ Extension->MinorVersion = VersionToBoot & 0xFF;
+ Extension->Profile.Status = 2;
+
+ /* Load drivers database */
+ strcpy(MiscFiles, BootPath);
+ strcat(MiscFiles, "AppPatch\\drvmain.sdb");
+ Extension->DrvDBImage = PaToVa(WinLdrLoadModule(MiscFiles,
+ &Extension->DrvDBSize, LoaderRegistryData));
+
+ /* Convert extension and setup block pointers */
+ LoaderBlock->Extension = PaToVa(Extension);
+
+ if (LoaderBlock->SetupLdrBlock)
+ LoaderBlock->SetupLdrBlock = PaToVa(LoaderBlock->SetupLdrBlock);
+}
+
+BOOLEAN
+WinLdrLoadDeviceDriver(PLOADER_PARAMETER_BLOCK LoaderBlock,
+ LPSTR BootPath,
+ PUNICODE_STRING FilePath,
+ ULONG Flags,
+ PLDR_DATA_TABLE_ENTRY *DriverDTE)
+{
+ CHAR FullPath[1024];
+ CHAR DriverPath[1024];
+ CHAR DllName[1024];
+ PCHAR DriverNamePos;
+ BOOLEAN Status;
+ PVOID DriverBase;
+
+ // Separate the path to file name and directory path
+ sprintf(DriverPath, "%S", FilePath->Buffer);
+ DriverNamePos = strrchr(DriverPath, '\\');
+ if (DriverNamePos != NULL)
+ {
+ // Copy the name
+ strcpy(DllName, DriverNamePos+1);
+
+ // Cut out the name from the path
+ *(DriverNamePos+1) = 0;
+ }
+ else
+ {
+ // There is no directory in the path
+ strcpy(DllName, DriverPath);
+ DriverPath[0] = 0;
+ }
+
+ DPRINTM(DPRINT_WINDOWS, "DriverPath: %s, DllName: %s, LPB %p\n", DriverPath, DllName, LoaderBlock);
+
+
+ // Check if driver is already loaded
+ Status = WinLdrCheckForLoadedDll(LoaderBlock, DllName, DriverDTE);
+ if (Status)
+ {
+ // We've got the pointer to its DTE, just return success
+ return TRUE;
+ }
+
+ // It's not loaded, we have to load it
+ sprintf(FullPath,"%s%S", BootPath, FilePath->Buffer);
+ Status = WinLdrLoadImage(FullPath, LoaderBootDriver, &DriverBase);
+ if (!Status)
+ return FALSE;
+
+ // Allocate a DTE for it
+ Status = WinLdrAllocateDataTableEntry(LoaderBlock, DllName, DllName, DriverBase, DriverDTE);
+ if (!Status)
+ {
+ DPRINTM(DPRINT_WINDOWS, "WinLdrAllocateDataTableEntry() failed\n");
+ return FALSE;
+ }
+
+ // Modify any flags, if needed
+ (*DriverDTE)->Flags |= Flags;
+
+ // Look for any dependencies it may have, and load them too
+ sprintf(FullPath,"%s%s", BootPath, DriverPath);
+ Status = WinLdrScanImportDescriptorTable(LoaderBlock, FullPath, *DriverDTE);
+ if (!Status)
+ {
+ DPRINTM(DPRINT_WINDOWS, "WinLdrScanImportDescriptorTable() failed for %s\n",
+ FullPath);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+BOOLEAN
+WinLdrLoadBootDrivers(PLOADER_PARAMETER_BLOCK LoaderBlock,
+ LPSTR BootPath)
+{
+ PLIST_ENTRY NextBd;
+ PBOOT_DRIVER_LIST_ENTRY BootDriver;
+ BOOLEAN Status;
+
+ // Walk through the boot drivers list
+ NextBd = LoaderBlock->BootDriverListHead.Flink;
+
+ while (NextBd != &LoaderBlock->BootDriverListHead)
+ {
+ BootDriver = CONTAINING_RECORD(NextBd, BOOT_DRIVER_LIST_ENTRY, Link);
+
+ DPRINTM(DPRINT_WINDOWS, "BootDriver %wZ DTE %08X RegPath: %wZ\n", &BootDriver->FilePath,
+ BootDriver->LdrEntry, &BootDriver->RegistryPath);
+
+ // Paths are relative (FIXME: Are they always relative?)
+
+ // Load it
+ Status = WinLdrLoadDeviceDriver(LoaderBlock, BootPath, &BootDriver->FilePath,
+ 0, &BootDriver->LdrEntry);
+
+ // If loading failed - cry loudly
+ //FIXME: Maybe remove it from the list and try to continue?
+ if (!Status)
+ {
+ UiMessageBox("Can't load boot driver!");
+ return FALSE;
+ }
+
+ // Convert the RegistryPath and DTE addresses to VA since we are not going to use it anymore
+ BootDriver->RegistryPath.Buffer = PaToVa(BootDriver->RegistryPath.Buffer);
+ BootDriver->LdrEntry = PaToVa(BootDriver->LdrEntry);
+
+ NextBd = BootDriver->Link.Flink;
+ }
+
+ return TRUE;
+}
+
+PVOID WinLdrLoadModule(PCSTR ModuleName, ULONG *Size,
+ TYPE_OF_MEMORY MemoryType)
+{
+ ULONG FileId;
+ PVOID PhysicalBase;
+ FILEINFORMATION FileInfo;
+ ULONG FileSize;
+ ULONG Status;
+ ULONG BytesRead;
+
+ //CHAR ProgressString[256];
+
+ /* Inform user we are loading files */
+ //sprintf(ProgressString, "Loading %s...", FileName);
+ //UiDrawProgressBarCenter(1, 100, ProgressString);
+
+ DPRINTM(DPRINT_WINDOWS, "Loading module %s\n", ModuleName);
+ *Size = 0;
+
+ /* Open the image file */
+ Status = ArcOpen((PCHAR)ModuleName, OpenReadOnly, &FileId);
+ if (Status != ESUCCESS)
+ {
+ /* In case of errors, we just return, without complaining to the user */
+ return NULL;
+ }
+
+ /* Get this file's size */
+ Status = ArcGetFileInformation(FileId, &FileInfo);
+ if (Status != ESUCCESS)
+ {
+ ArcClose(FileId);
+ return NULL;
+ }
+ FileSize = FileInfo.EndingAddress.LowPart;
+ *Size = FileSize;
+
+ /* Allocate memory */
+ PhysicalBase = MmAllocateMemoryWithType(FileSize, MemoryType);
+ if (PhysicalBase == NULL)
+ {
+ ArcClose(FileId);
+ return NULL;
+ }
+
+ /* Load whole file */
+ Status = ArcRead(FileId, PhysicalBase, FileSize, &BytesRead);
+ ArcClose(FileId);
+ if (Status != ESUCCESS)
+ {
+ return NULL;
+ }
+
+ DPRINTM(DPRINT_WINDOWS, "Loaded %s at 0x%x with size 0x%x\n", ModuleName, PhysicalBase, FileSize);
+
+ return PhysicalBase;
+}
+
+
+VOID
+LoadAndBootWindows(PCSTR OperatingSystemName, USHORT OperatingSystemVersion)
+{
+ CHAR MsgBuffer[256];
+ CHAR FullPath[MAX_PATH], SystemRoot[MAX_PATH], BootPath[MAX_PATH];
+ CHAR FileName[MAX_PATH];
+ CHAR BootOptions[256];
+ PCHAR File;
+ PCHAR PathSeparator;
+ PVOID NtosBase = NULL, HalBase = NULL, KdComBase = NULL;
+ BOOLEAN Status;
+ ULONG SectionId;
+ PLOADER_PARAMETER_BLOCK LoaderBlock, LoaderBlockVA;
+ KERNEL_ENTRY_POINT KiSystemStartup;
+ PLDR_DATA_TABLE_ENTRY KernelDTE, HalDTE, KdComDTE = NULL;
+ // Mm-related things
+ PVOID GdtIdt;
+ ULONG PcrBasePage=0;
+ ULONG TssBasePage=0;
+
+ //sprintf(MsgBuffer,"Booting Microsoft(R) Windows(R) OS version '%04x' is not implemented yet", OperatingSystemVersion);
+ //UiMessageBox(MsgBuffer);
+
+ // Open the operating system section
+ // specified in the .ini file
+ if (!IniOpenSection(OperatingSystemName, &SectionId))
+ {
+ sprintf(MsgBuffer,"Operating System section '%s' not found in freeldr.ini", OperatingSystemName);
+ UiMessageBox(MsgBuffer);
+ return;
+ }
+
+ UiDrawBackdrop();
+ UiDrawStatusText("Detecting Hardware...");
+ UiDrawProgressBarCenter(1, 100, "Loading Windows...");
+
+ /* Make sure the system path is set in the .ini file */
+ if (!IniReadSettingByName(SectionId, "SystemPath", FullPath, sizeof(FullPath)))
+ {
+ UiMessageBox("System path not specified for selected operating system.");
+ return;
+ }
+
+ /* Special case for LiveCD */
+ if (!_strnicmp(FullPath, "LiveCD", strlen("LiveCD")))
+ {
+ strcpy(BootPath, FullPath + strlen("LiveCD"));
+ MachDiskGetBootPath(FullPath, sizeof(FullPath));
+ strcat(FullPath, BootPath);
+ }
+
+ /* Convert FullPath to SystemRoot */
+ PathSeparator = strstr(FullPath, "\\");
+ strcpy(SystemRoot, PathSeparator);
+ strcat(SystemRoot, "\\");
+
+ /* Read booting options */
+ if (!IniReadSettingByName(SectionId, "Options", BootOptions, sizeof(BootOptions)))
+ {
+ /* Nothing read, make the string empty */
+ strcpy(BootOptions, "");
+ }
+
+ //
+ // Check if a ramdisk file was given
+ //
+ File = strstr(BootOptions, "/RDPATH=");
+ if (File)
+ {
+ //
+ // Copy the file name and everything else after it
+ //
+ strcpy(FileName, File + 8);
+
+ //
+ // Null-terminate
+ //
+ *strstr(FileName, " ") = ANSI_NULL;
+
+ //
+ // Load the ramdisk
+ //
+ RamDiskLoadVirtualFile(FileName);
+ }
+
+ /* Let user know we started loading */
+ UiDrawStatusText("Loading...");
+
+ /* append a backslash */
+ strcpy(BootPath, FullPath);
+ if ((strlen(BootPath)==0) ||
+ BootPath[strlen(BootPath)] != '\\')
+ strcat(BootPath, "\\");
+
+ DPRINTM(DPRINT_WINDOWS,"BootPath: '%s'\n", BootPath);
+
+ /* Allocate and minimalistic-initialize LPB */
+ AllocateAndInitLPB(&LoaderBlock);
+
+ /* Detect hardware */
+ UseRealHeap = TRUE;
+ LoaderBlock->ConfigurationRoot = MachHwDetect();
+
+ /* Load kernel */
+ strcpy(FileName, BootPath);
+ strcat(FileName, "SYSTEM32\\NTOSKRNL.EXE");
+ Status = WinLdrLoadImage(FileName, LoaderSystemCode, &NtosBase);
+ DPRINTM(DPRINT_WINDOWS, "Ntos loaded with status %d at %p\n", Status, NtosBase);
+
+ /* Load HAL */
+ strcpy(FileName, BootPath);
+ strcat(FileName, "SYSTEM32\\HAL.DLL");
+ Status = WinLdrLoadImage(FileName, LoaderHalCode, &HalBase);
+ DPRINTM(DPRINT_WINDOWS, "HAL loaded with status %d at %p\n", Status, HalBase);
+
+ /* Load kernel-debugger support dll */
+ if (OperatingSystemVersion > _WIN32_WINNT_WIN2K)
+ {
+ strcpy(FileName, BootPath);
+ strcat(FileName, "SYSTEM32\\KDCOM.DLL");
+ Status = WinLdrLoadImage(FileName, LoaderBootDriver, &KdComBase);
+ DPRINTM(DPRINT_WINDOWS, "KdCom loaded with status %d at %p\n", Status, KdComBase);
+ }
+
+ /* Allocate data table entries for above-loaded modules */
+ WinLdrAllocateDataTableEntry(LoaderBlock, "ntoskrnl.exe",
+ "WINDOWS\\SYSTEM32\\NTOSKRNL.EXE", NtosBase, &KernelDTE);
+ WinLdrAllocateDataTableEntry(LoaderBlock, "hal.dll",
+ "WINDOWS\\SYSTEM32\\HAL.DLL", HalBase, &HalDTE);
+ if (OperatingSystemVersion > _WIN32_WINNT_WIN2K)
+ {
+ WinLdrAllocateDataTableEntry(LoaderBlock, "kdcom.dll",
+ "WINDOWS\\SYSTEM32\\KDCOM.DLL", KdComBase, &KdComDTE);
+ }
+
+ /* Load all referenced DLLs for kernel, HAL and kdcom.dll */
+ strcpy(FileName, BootPath);
+ strcat(FileName, "SYSTEM32\\");
+ WinLdrScanImportDescriptorTable(LoaderBlock, FileName, KernelDTE);
+ WinLdrScanImportDescriptorTable(LoaderBlock, FileName, HalDTE);
+ if (KdComDTE)
+ WinLdrScanImportDescriptorTable(LoaderBlock, FileName, KdComDTE);
+
+ /* Load Hive, and then NLS data, OEM font, and prepare boot drivers list */
+ Status = WinLdrLoadAndScanSystemHive(LoaderBlock, BootPath);
+ DPRINTM(DPRINT_WINDOWS, "SYSTEM hive loaded and scanned with status %d\n", Status);
+
+ /* Load boot drivers */
+ Status = WinLdrLoadBootDrivers(LoaderBlock, BootPath);
+ DPRINTM(DPRINT_WINDOWS, "Boot drivers loaded with status %d\n", Status);
+
+ /* Alloc PCR, TSS, do magic things with the GDT/IDT */
+ WinLdrSetupForNt(LoaderBlock, &GdtIdt, &PcrBasePage, &TssBasePage);
+
+ /* Initialize Phase 1 - no drivers loading anymore */
+ WinLdrInitializePhase1(LoaderBlock, BootOptions, SystemRoot, BootPath, OperatingSystemVersion);
+
+ /* Save entry-point pointer and Loader block VAs */
+ KiSystemStartup = (KERNEL_ENTRY_POINT)KernelDTE->EntryPoint;
+ LoaderBlockVA = PaToVa(LoaderBlock);
+
+ /* "Stop all motors", change videomode */
+ if (OperatingSystemVersion < _WIN32_WINNT_WIN2K)
+ MachPrepareForReactOS(TRUE);
+ else
+ MachPrepareForReactOS(FALSE);
+
+ /* Debugging... */
+ //DumpMemoryAllocMap();
+
+ /* Turn on paging mode of CPU*/
+ WinLdrTurnOnPaging(LoaderBlock, PcrBasePage, TssBasePage, GdtIdt);
+
+ /* Save final value of LoaderPagesSpanned */
+ LoaderBlock->Extension->LoaderPagesSpanned = LoaderPagesSpanned;
+
+ DPRINTM(DPRINT_WINDOWS, "Hello from paged mode, KiSystemStartup %p, LoaderBlockVA %p!\n",
+ KiSystemStartup, LoaderBlockVA);
+
+ WinLdrpDumpMemoryDescriptors(LoaderBlockVA);
+ WinLdrpDumpBootDriver(LoaderBlockVA);
+ WinLdrpDumpArcDisks(LoaderBlockVA);
+
+ //FIXME: If I substitute this debugging checkpoint, GCC will "optimize away" the code below
+ //while (1) {};
+ /*asm(".intel_syntax noprefix\n");
+ asm("test1:\n");
+ asm("jmp test1\n");
+ asm(".att_syntax\n");*/
+
+ /* Pass control */
+ (*KiSystemStartup)(LoaderBlockVA);
+
+ return;
+}
+
+VOID
+WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+ PLIST_ENTRY NextMd;
+ PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor;
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead)
+ {
+ MemoryDescriptor = CONTAINING_RECORD(NextMd, MEMORY_ALLOCATION_DESCRIPTOR, ListEntry);
+
+ DPRINTM(DPRINT_WINDOWS, "BP %08X PC %04X MT %d\n", MemoryDescriptor->BasePage,
+ MemoryDescriptor->PageCount, MemoryDescriptor->MemoryType);
+
+ NextMd = MemoryDescriptor->ListEntry.Flink;
+ }
+}
+
+VOID
+WinLdrpDumpBootDriver(PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+ PLIST_ENTRY NextBd;
+ PBOOT_DRIVER_LIST_ENTRY BootDriver;
+
+ NextBd = LoaderBlock->BootDriverListHead.Flink;
+
+ while (NextBd != &LoaderBlock->BootDriverListHead)
+ {
+ BootDriver = CONTAINING_RECORD(NextBd, BOOT_DRIVER_LIST_ENTRY, Link);
+
+ DPRINTM(DPRINT_WINDOWS, "BootDriver %wZ DTE %08X RegPath: %wZ\n", &BootDriver->FilePath,
+ BootDriver->LdrEntry, &BootDriver->RegistryPath);
+
+ NextBd = BootDriver->Link.Flink;
+ }
+}
+
+VOID
+WinLdrpDumpArcDisks(PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+ PLIST_ENTRY NextBd;
+ PARC_DISK_SIGNATURE ArcDisk;
+
+ NextBd = LoaderBlock->ArcDiskInformation->DiskSignatureListHead.Flink;
+
+ while (NextBd != &LoaderBlock->ArcDiskInformation->DiskSignatureListHead)
+ {
+ ArcDisk = CONTAINING_RECORD(NextBd, ARC_DISK_SIGNATURE, ListEntry);
+
+ DPRINTM(DPRINT_WINDOWS, "ArcDisk %s checksum: 0x%X, signature: 0x%X\n",
+ ArcDisk->ArcName, ArcDisk->CheckSum, ArcDisk->Signature);
+
+ NextBd = ArcDisk->ListEntry.Flink;
+ }
+}
+
+