-/*
- * 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>
-
-//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];
-
-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 SystemPath,
- WORD 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 SystemRoot[256];
- CHAR ArcBoot[256];
- ULONG i, PathSeparator;
- PLOADER_PARAMETER_EXTENSION Extension;
-
- LoaderBlock->u.I386.CommonDataArea = NULL; // Force No ABIOS support
-
- /* Construct SystemRoot and ArcBoot from SystemPath */
- PathSeparator = strstr(SystemPath, "\\") - SystemPath;
- strncpy(ArcBoot, SystemPath, PathSeparator);
- ArcBoot[PathSeparator] = 0;
- strcpy(SystemRoot, &SystemPath[PathSeparator]);
- strcat(SystemRoot, "\\");
-
- DbgPrint((DPRINT_WINDOWS, "ArcBoot: %s\n", ArcBoot));
- DbgPrint((DPRINT_WINDOWS, "SystemRoot: %s\n", SystemRoot));
- DbgPrint((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));
-
- /* Save size and version information */
- Extension->Size = sizeof(LOADER_PARAMETER_EXTENSION);
- Extension->MajorVersion = (VersionToBoot & 0xFF00) >> 8;
- Extension->MinorVersion = VersionToBoot & 0xFF;
-
-
- LoaderBlock->Extension = PaToVa(Extension);
-}
-
-// Last step before going virtual
-void WinLdrSetupForNt(PLOADER_PARAMETER_BLOCK LoaderBlock,
- PVOID *GdtIdt,
- ULONG *PcrBasePage,
- ULONG *TssBasePage)
-{
- ULONG TssSize;
- ULONG TssPages;
- ULONG_PTR Pcr = 0;
- ULONG_PTR Tss = 0;
- ULONG BlockSize, NumPages;
-
- LoaderBlock->u.I386.CommonDataArea = NULL;//CommonDataArea;
- //LoaderBlock->u.I386.MachineType = MachineType; //FIXME: MachineType?
-
- /* Allocate 2 pages for PCR */
- Pcr = (ULONG_PTR)MmAllocateMemoryWithType(2 * MM_PAGE_SIZE, LoaderStartupPcrPage);
- *PcrBasePage = Pcr >> MM_PAGE_SHIFT;
-
- if (Pcr == 0)
- {
- UiMessageBox("Can't allocate PCR\n");
- return;
- }
-
- /* Allocate TSS */
- TssSize = (sizeof(KTSS) + MM_PAGE_SIZE) & ~(MM_PAGE_SIZE - 1);
- TssPages = TssSize / MM_PAGE_SIZE;
-
- Tss = (ULONG_PTR)MmAllocateMemoryWithType(TssSize, LoaderMemoryData);
-
- *TssBasePage = Tss >> MM_PAGE_SHIFT;
-
- /* Allocate space for new GDT + IDT */
- BlockSize = NUM_GDT*sizeof(KGDTENTRY) + NUM_IDT*sizeof(KIDTENTRY);//FIXME: Use GDT/IDT limits here?
- NumPages = (BlockSize + MM_PAGE_SIZE - 1) >> MM_PAGE_SHIFT;
- *GdtIdt = (PKGDTENTRY)MmAllocateMemoryWithType(NumPages * MM_PAGE_SIZE, LoaderMemoryData);
-
- if (*GdtIdt == NULL)
- {
- UiMessageBox("Can't allocate pages for GDT+IDT!\n");
- return;
- }
-
- /* Zero newly prepared GDT+IDT */
- RtlZeroMemory(*GdtIdt, NumPages << MM_PAGE_SHIFT);
-}
-
-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, "%wZ", FilePath);
- DriverNamePos = strrchr(DriverPath, '\\');
- if (DriverNamePos != NULL)
- {
- // Copy the name
- strcpy(DllName, DriverNamePos+1);
-
- // Cut out the name from the path
- *(DriverNamePos+1) = 0;
- }
-
- DbgPrint((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%wZ", BootPath, FilePath);
- Status = WinLdrLoadImage(FullPath, LoaderBootDriver, &DriverBase);
- if (!Status)
- return FALSE;
-
- // Allocate a DTE for it
- Status = WinLdrAllocateDataTableEntry(LoaderBlock, DllName, DllName, DriverBase, DriverDTE);
- if (!Status)
- {
- DbgPrint((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)
- {
- DbgPrint((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, ListEntry);
-
- DbgPrint((DPRINT_WINDOWS, "BootDriver %wZ DTE %08X RegPath: %wZ\n", &BootDriver->FilePath,
- BootDriver->DataTableEntry, &BootDriver->RegistryPath));
-
- // Paths are relative (FIXME: Are they always relative?)
-
- // Load it
- Status = WinLdrLoadDeviceDriver(LoaderBlock, BootPath, &BootDriver->FilePath,
- 0, &BootDriver->DataTableEntry);
-
- // 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->DataTableEntry = PaToVa(BootDriver->DataTableEntry);
-
- NextBd = BootDriver->ListEntry.Flink;
- }
-
- return TRUE;
-}
-
-VOID
-LoadAndBootWindows(PCSTR OperatingSystemName, WORD OperatingSystemVersion)
-{
- CHAR MsgBuffer[256];
- CHAR SystemPath[512], SearchPath[512];
- CHAR FileName[512];
- CHAR BootPath[512];
- CHAR BootOptions[256];
- PVOID NtosBase = NULL, HalBase = NULL, KdComBase = NULL;
- BOOLEAN Status;
- ULONG SectionId;
- ULONG BootDevice;
- 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", SystemPath, sizeof(SystemPath)))
- {
- UiMessageBox("System path not specified for selected operating system.");
- return;
- }
-
- /* Read booting options */
- if (!IniReadSettingByName(SectionId, "Options", BootOptions, sizeof(BootOptions)))
- {
- /* Nothing read, make the string empty */
- strcpy(BootOptions, "");
- }
-
- /* Normalize system path */
- if (!MachDiskNormalizeSystemPath(SystemPath, sizeof(SystemPath)))
- {
- UiMessageBox("Invalid system path");
- return;
- }
-
- /* Let user know we started loading */
- UiDrawStatusText("Loading...");
-
- /* Try to open system drive */
- BootDevice = 0xffffffff;
- if (!FsOpenSystemVolume(SystemPath, BootPath, &BootDevice))
- {
- UiMessageBox("Failed to open boot drive.");
- return;
- }
-
- /* append a backslash */
- if ((strlen(BootPath)==0) ||
- BootPath[strlen(BootPath)] != '\\')
- strcat(BootPath, "\\");
-
- DbgPrint((DPRINT_WINDOWS,"SystemRoot: '%s'\n", BootPath));
-
- /* Allocate and minimalistic-initialize LPB */
- AllocateAndInitLPB(&LoaderBlock);
-
- /* Detect hardware */
-#if WHEN_MERGE_COMPLETE
- MachHwDetect(&LoaderBlock->ConfigurationRoot);
-#else
- MachHwDetect();
-#endif
-
- /* Load kernel */
- strcpy(FileName, BootPath);
- strcat(FileName, "SYSTEM32\\NTOSKRNL.EXE");
- Status = WinLdrLoadImage(FileName, LoaderSystemCode, &NtosBase);
- DbgPrint((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);
- DbgPrint((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);
- DbgPrint((DPRINT_WINDOWS, "KdCom loaded with status %d at %p\n", Status, KdComBase));
- }
-
- /* Allocate data table entries for above-loaded modules */
- WinLdrAllocateDataTableEntry(LoaderBlock, "ntoskrnl.exe",
- "WINNT\\SYSTEM32\\NTOSKRNL.EXE", NtosBase, &KernelDTE);
- WinLdrAllocateDataTableEntry(LoaderBlock, "hal.dll",
- "WINNT\\SYSTEM32\\HAL.DLL", HalBase, &HalDTE);
- if (OperatingSystemVersion > _WIN32_WINNT_WIN2K)
- {
- WinLdrAllocateDataTableEntry(LoaderBlock, "kdcom.dll",
- "WINNT\\SYSTEM32\\KDCOM.DLL", KdComBase, &KdComDTE);
- }
-
- /* Load all referenced DLLs for kernel, HAL and kdcom.dll */
- strcpy(SearchPath, BootPath);
- strcat(SearchPath, "SYSTEM32\\");
- WinLdrScanImportDescriptorTable(LoaderBlock, SearchPath, KernelDTE);
- WinLdrScanImportDescriptorTable(LoaderBlock, SearchPath, HalDTE);
- if (KdComDTE)
- WinLdrScanImportDescriptorTable(LoaderBlock, SearchPath, KdComDTE);
-
- /* Load Hive, and then NLS data, OEM font, and prepare boot drivers list */
- Status = WinLdrLoadAndScanSystemHive(LoaderBlock, BootPath);
- DbgPrint((DPRINT_WINDOWS, "SYSTEM hive loaded and scanned with status %d\n", Status));
-
- /* Load boot drivers */
- Status = WinLdrLoadBootDrivers(LoaderBlock, BootPath);
- DbgPrint((DPRINT_WINDOWS, "Boot drivers loaded with status %d\n", Status));
-
- /* Initialize Phase 1 - no drivers loading anymore */
- WinLdrInitializePhase1(LoaderBlock, BootOptions, SystemPath, OperatingSystemVersion);
-
- /* Alloc PCR, TSS, do magic things with the GDT/IDT */
- WinLdrSetupForNt(LoaderBlock, &GdtIdt, &PcrBasePage, &TssBasePage);
-
- /* Save entry-point pointer and Loader block VAs */
- KiSystemStartup = (KERNEL_ENTRY_POINT)KernelDTE->EntryPoint;
- LoaderBlockVA = PaToVa(LoaderBlock);
-
- /* "Stop all motors", change videomode */
- DiskStopFloppyMotor();
- MachVideoPrepareForReactOS(FALSE);
-
- /* Debugging... */
- //DumpMemoryAllocMap();
-
- /* Turn on paging mode of CPU*/
- WinLdrTurnOnPaging(LoaderBlock, PcrBasePage, TssBasePage, GdtIdt);
-
- DbgPrint((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);
-
- DbgPrint((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, ListEntry);
-
- DbgPrint((DPRINT_WINDOWS, "BootDriver %wZ DTE %08X RegPath: %wZ\n", &BootDriver->FilePath,
- BootDriver->DataTableEntry, &BootDriver->RegistryPath));
-
- NextBd = BootDriver->ListEntry.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);
-
- DbgPrint((DPRINT_WINDOWS, "ArcDisk %s checksum: 0x%X, signature: 0x%X\n",
- ArcDisk->ArcName, ArcDisk->CheckSum, ArcDisk->Signature));
-
- NextBd = ArcDisk->ListEntry.Flink;
- }
-}
-
+/*\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
-/*
- * PROJECT: EFI Windows Loader
- * LICENSE: GPL - See COPYING in the top level directory
- * FILE: freeldr/winldr/wlmemory.c
- * PURPOSE: Memory related routines
- * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
- */
-
-/* INCLUDES ***************************************************************/
-
-#include <freeldr.h>
-
-#include <ndk/asm.h>
-#include <debug.h>
-
-extern ULONG TotalNLSSize;
-
-// This is needed because headers define wrong one for ReactOS
-#undef KIP0PCRADDRESS
-#define KIP0PCRADDRESS 0xffdff000
-
-#define HYPER_SPACE_ENTRY 0x300
-
-PCHAR MemTypeDesc[] = {
- "ExceptionBlock ", // ?
- "SystemBlock ", // ?
- "Free ",
- "Bad ", // used
- "LoadedProgram ", // == Free
- "FirmwareTemporary ", // == Free
- "FirmwarePermanent ", // == Bad
- "OsloaderHeap ", // used
- "OsloaderStack ", // == Free
- "SystemCode ",
- "HalCode ",
- "BootDriver ", // not used
- "ConsoleInDriver ", // ?
- "ConsoleOutDriver ", // ?
- "StartupDpcStack ", // ?
- "StartupKernelStack", // ?
- "StartupPanicStack ", // ?
- "StartupPcrPage ", // ?
- "StartupPdrPage ", // ?
- "RegistryData ", // used
- "MemoryData ", // not used
- "NlsData ", // used
- "SpecialMemory ", // == Bad
- "BBTMemory " // == Bad
- };
-
-VOID
-WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock);
-
-
-VOID
-MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
- ULONG BasePage,
- ULONG PageCount,
- ULONG Type);
-VOID
-WinLdrInsertDescriptor(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
- IN PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor);
-
-VOID
-WinLdrRemoveDescriptor(IN PMEMORY_ALLOCATION_DESCRIPTOR Descriptor);
-
-VOID
-WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss);
-
-// This is needed only for SetProcessorContext routine
-#pragma pack(2)
- typedef struct
- {
- USHORT Limit;
- ULONG Base;
- } GDTIDT;
-#pragma pack(4)
-
-// this is needed for new IDT filling
-#if 0
-extern ULONG_PTR i386DivideByZero;
-extern ULONG_PTR i386DebugException;
-extern ULONG_PTR i386NMIException;
-extern ULONG_PTR i386Breakpoint;
-extern ULONG_PTR i386Overflow;
-extern ULONG_PTR i386BoundException;
-extern ULONG_PTR i386InvalidOpcode;
-extern ULONG_PTR i386FPUNotAvailable;
-extern ULONG_PTR i386DoubleFault;
-extern ULONG_PTR i386CoprocessorSegment;
-extern ULONG_PTR i386InvalidTSS;
-extern ULONG_PTR i386SegmentNotPresent;
-extern ULONG_PTR i386StackException;
-extern ULONG_PTR i386GeneralProtectionFault;
-extern ULONG_PTR i386PageFault; // exc 14
-extern ULONG_PTR i386CoprocessorError; // exc 16
-extern ULONG_PTR i386AlignmentCheck; // exc 17
-#endif
-
-/* GLOBALS ***************************************************************/
-
-PHARDWARE_PTE PDE;
-PHARDWARE_PTE HalPT;
-
-PUCHAR PhysicalPageTablesBuffer;
-PUCHAR KernelPageTablesBuffer;
-ULONG PhysicalPageTables;
-ULONG KernelPageTables;
-
-MEMORY_ALLOCATION_DESCRIPTOR Mad[1024];
-ULONG MadCount = 0;
-
-
-/* FUNCTIONS **************************************************************/
-
-BOOLEAN
-MempAllocatePageTables()
-{
- ULONG NumPageTables, TotalSize;
- PUCHAR Buffer;
- // It's better to allocate PDE + PTEs contigiuos
-
- // Max number of entries = MaxPageNum >> 10
- // FIXME: This is a number to describe ALL physical memory
- // and windows doesn't expect ALL memory mapped...
- NumPageTables = (GetSystemMemorySize() >> MM_PAGE_SHIFT) >> 10;
-
- DbgPrint((DPRINT_WINDOWS, "NumPageTables = %d\n", NumPageTables));
-
- // Allocate memory block for all these things:
- // PDE, HAL mapping page table, physical mapping, kernel mapping
- // FIXME: PDE+HAL+KernelPTEs == FirmwarePermanent, Physical PTEs = FirmwareTemporary
- TotalSize = (1+1+NumPageTables*2)*MM_PAGE_SIZE;
- Buffer = MmAllocateMemoryWithType(TotalSize, LoaderFirmwarePermanent);
-
- if (Buffer == NULL)
- {
- UiMessageBox("Impossible to allocate memory block for page tables!");
- return FALSE;
- }
-
- // Zero all this memory block
- RtlZeroMemory(Buffer, TotalSize);
-
- // Set up pointers correctly now
- PDE = (PHARDWARE_PTE)Buffer;
-
- // Map the page directory at 0xC0000000 (maps itself)
- PDE[HYPER_SPACE_ENTRY].PageFrameNumber = (ULONG)PDE >> MM_PAGE_SHIFT;
- PDE[HYPER_SPACE_ENTRY].Valid = 1;
- PDE[HYPER_SPACE_ENTRY].Write = 1;
-
- // The last PDE slot is allocated for HAL's memory mapping (Virtual Addresses 0xFFC00000 - 0xFFFFFFFF)
- HalPT = (PHARDWARE_PTE)&Buffer[MM_PAGE_SIZE*1];
-
- // Map it
- PDE[1023].PageFrameNumber = (ULONG)HalPT >> MM_PAGE_SHIFT;
- PDE[1023].Valid = 1;
- PDE[1023].Write = 1;
-
- // Store pointers to the tables for easier access
- PhysicalPageTablesBuffer = &Buffer[MM_PAGE_SIZE*2];
- KernelPageTablesBuffer = PhysicalPageTablesBuffer + NumPageTables*MM_PAGE_SIZE;
-
- // Mark physical PTE's buffer as FirmwareTemporary
- //MmSetMemoryType(KernelPageTablesBuffer, NumPageTables*MM_PAGE_SIZE, LoaderFirmwareTemporary);
-
- // Zero counters of page tables used
- PhysicalPageTables = 0;
- KernelPageTables = 0;
-
- return TRUE;
-}
-
-VOID
-MempAllocatePTE(ULONG Entry, PHARDWARE_PTE *PhysicalPT, PHARDWARE_PTE *KernelPT)
-{
- //Print(L"Creating PDE Entry %X\n", Entry);
-
- // Identity mapping
- *PhysicalPT = (PHARDWARE_PTE)&PhysicalPageTablesBuffer[PhysicalPageTables*MM_PAGE_SIZE];
- PhysicalPageTables++;
-
- PDE[Entry].PageFrameNumber = (ULONG)*PhysicalPT >> MM_PAGE_SHIFT;
- PDE[Entry].Valid = 1;
- PDE[Entry].Write = 1;
-
- if (Entry+(KSEG0_BASE >> 22) > 1023)
- {
- DbgPrint((DPRINT_WINDOWS, "WARNING! Entry: %X > 1023\n", Entry+(KSEG0_BASE >> 22)));
- }
-
- // Kernel-mode mapping
- *KernelPT = (PHARDWARE_PTE)&KernelPageTablesBuffer[KernelPageTables*MM_PAGE_SIZE];
- KernelPageTables++;
-
- PDE[Entry+(KSEG0_BASE >> 22)].PageFrameNumber = ((ULONG)*KernelPT >> MM_PAGE_SHIFT);
- PDE[Entry+(KSEG0_BASE >> 22)].Valid = 1;
- PDE[Entry+(KSEG0_BASE >> 22)].Write = 1;
-}
-
-BOOLEAN
-MempSetupPaging(IN ULONG StartPage,
- IN ULONG NumberOfPages)
-{
- PHARDWARE_PTE PhysicalPT;
- PHARDWARE_PTE KernelPT;
- ULONG Entry, Page;
-
- //Print(L"MempSetupPaging: SP 0x%X, Number: 0x%X\n", StartPage, NumberOfPages);
-
- // HACK
- if (StartPage+NumberOfPages >= 0x80000)
- {
- //
- // We can't map this as it requires more than 1 PDE
- // and in fact it's not possible at all ;)
- //
- //Print(L"skipping...\n");
- return TRUE;
- }
-
- //
- // Now actually set up the page tables for identity mapping
- //
- for (Page=StartPage; Page < StartPage+NumberOfPages; Page++)
- {
- Entry = Page >> 10;
-
- if (((PULONG)PDE)[Entry] == 0)
- {
- MempAllocatePTE(Entry, &PhysicalPT, &KernelPT);
- }
- else
- {
- PhysicalPT = (PHARDWARE_PTE)(PDE[Entry].PageFrameNumber << MM_PAGE_SHIFT);
- KernelPT = (PHARDWARE_PTE)(PDE[Entry+(KSEG0_BASE >> 22)].PageFrameNumber << MM_PAGE_SHIFT);
- }
-
- if (Page == 0)
- {
- PhysicalPT[Page & 0x3ff].PageFrameNumber = Page;
- PhysicalPT[Page & 0x3ff].Valid = 0;
- PhysicalPT[Page & 0x3ff].Write = 0;
-
- KernelPT[Page & 0x3ff].PageFrameNumber = Page;
- KernelPT[Page & 0x3ff].Valid = 0;
- KernelPT[Page & 0x3ff].Write = 0;
- }
- else
- {
- PhysicalPT[Page & 0x3ff].PageFrameNumber = Page;
- PhysicalPT[Page & 0x3ff].Valid = 1;
- PhysicalPT[Page & 0x3ff].Write = 1;
-
- KernelPT[Page & 0x3ff].PageFrameNumber = Page;
- KernelPT[Page & 0x3ff].Valid = 1;
- KernelPT[Page & 0x3ff].Write = 1;
- }
- }
-
- return TRUE;
-}
-
-VOID
-MempDisablePages()
-{
- int i;
-
- //
- // We need to delete kernel mapping from memory areas which are
- // marked as Special or Permanent memory (thus non-accessible)
- //
-
- for (i=0; i<MadCount; i++)
- {
- ULONG StartPage, EndPage, Page;
-
- StartPage = Mad[i].BasePage;
- EndPage = Mad[i].BasePage + Mad[i].PageCount;
-
- if (Mad[i].MemoryType == LoaderFirmwarePermanent ||
- Mad[i].MemoryType == LoaderSpecialMemory ||
- Mad[i].MemoryType == LoaderFree ||
- (Mad[i].MemoryType == LoaderFirmwareTemporary && EndPage <= LOADER_HIGH_ZONE) ||
- Mad[i].MemoryType == LoaderOsloaderStack ||
- Mad[i].MemoryType == LoaderLoadedProgram)
- {
-
- //
- // But, the first megabyte of memory always stays!
- // And, to tell the truth, we don't care about what's higher
- // than LOADER_HIGH_ZONE
- if (Mad[i].MemoryType == LoaderFirmwarePermanent ||
- Mad[i].MemoryType == LoaderSpecialMemory)
- {
- if (StartPage < 0x100)
- StartPage = 0x100;
-
- if (EndPage > LOADER_HIGH_ZONE)
- EndPage = LOADER_HIGH_ZONE;
- }
-
- for (Page = StartPage; Page < EndPage; Page++)
- {
- PHARDWARE_PTE KernelPT;
- ULONG Entry = (Page >> 10) + (KSEG0_BASE >> 22);
-
- if (PDE[Entry].Valid)
- {
- KernelPT = (PHARDWARE_PTE)(PDE[Entry].PageFrameNumber << MM_PAGE_SHIFT);
-
- if (KernelPT)
- {
- KernelPT[Page & 0x3ff].PageFrameNumber = 0;
- KernelPT[Page & 0x3ff].Valid = 0;
- KernelPT[Page & 0x3ff].Write = 0;
- }
- }
- }
- }
- }
-}
-
-
-VOID
-MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
- ULONG BasePage,
- ULONG PageCount,
- ULONG Type)
-{
- BOOLEAN Status;
-
- //
- // Check for some weird stuff at the top
- //
- if (BasePage + PageCount > 0xF0000)
- {
- //
- // Just skip this, without even adding to MAD list
- //
- return;
- }
-
- //
- // Set Base page, page count and type
- //
- Mad[MadCount].BasePage = BasePage;
- Mad[MadCount].PageCount = PageCount;
- Mad[MadCount].MemoryType = Type;
-
- //
- // Check if it's more than the allowed for OS loader
- // if yes - don't map the pages, just add as FirmwareTemporary
- //
- if (BasePage + PageCount > LOADER_HIGH_ZONE)
- {
- if (Mad[MadCount].MemoryType != LoaderSpecialMemory ||
- Mad[MadCount].MemoryType != LoaderFirmwarePermanent)
- {
- Mad[MadCount].MemoryType = LoaderFirmwareTemporary;
- }
-
- WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
- MadCount++;
-
- return;
- }
-
- //
- // Add descriptor
- //
- WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
- MadCount++;
-
- //
- // Map it (don't map low 1Mb because it was already contigiously
- // mapped in WinLdrTurnOnPaging)
- //
- if (BasePage >= 0x100)
- {
- Status = MempSetupPaging(BasePage, PageCount);
- if (!Status)
- {
- DbgPrint((DPRINT_WINDOWS, "Error during MempSetupPaging\n"));
- return;
- }
- }
-}
-
-BOOLEAN
-WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
- ULONG PcrBasePage,
- ULONG TssBasePage,
- PVOID GdtIdt)
-{
- ULONG i, PagesCount, MemoryMapSizeInPages;
- ULONG LastPageIndex, LastPageType, MemoryMapStartPage;
- PPAGE_LOOKUP_TABLE_ITEM MemoryMap;
- ULONG NoEntries;
- PKTSS Tss;
- BOOLEAN Status;
-
- //
- // Creating a suitable memory map for the Windows can be tricky, so let's
- // give a few advices:
- // 1) One must not map the whole available memory pages to PDE!
- // Map only what's needed - 16Mb, 24Mb, 32Mb max I think,
- // thus occupying 4, 6 or 8 PDE entries for identical mapping,
- // the same quantity for KSEG0_BASE mapping, one more entry for
- // hyperspace and one more entry for HAL physical pages mapping.
- // 2) Memory descriptors must map *the whole* physical memory
- // showing any memory above 16/24/32 as FirmwareTemporary
- //
- // 3) Overall memory blocks count must not exceed 30
- //
-
- //
- // During MmInitMachineDependent, the kernel zeroes PDE at the following address
- // 0xC0300000 - 0xC03007FC
- //
- // Then it finds the best place for non-paged pool:
- // StartPde C0300F70, EndPde C0300FF8, NumberOfPages C13, NextPhysPage 3AD
- //
-
- // Before we start mapping pages, create a block of memory, which will contain
- // PDE and PTEs
- if (MempAllocatePageTables() == FALSE)
- return FALSE;
-
- // Setup an entry for each descriptor
- MemoryMap = MmGetMemoryMap(&NoEntries);
- if (MemoryMap == NULL)
- {
- UiMessageBox("Can not retrieve the current memory map");
- return FALSE;
- }
-
- // Calculate parameters of the memory map
- MemoryMapStartPage = (ULONG_PTR)MemoryMap >> MM_PAGE_SHIFT;
- MemoryMapSizeInPages = NoEntries * sizeof(PAGE_LOOKUP_TABLE_ITEM);
-
- DbgPrint((DPRINT_WINDOWS, "Got memory map with %d entries\n", NoEntries));
-
- // Always contigiously map low 1Mb of memory
- Status = MempSetupPaging(0, 0x100);
- if (!Status)
- {
- DbgPrint((DPRINT_WINDOWS, "Error during MempSetupPaging of low 1Mb\n"));
- return FALSE;
- }
-
- // Construct a good memory map from what we've got,
- // but mark entries which the memory allocation bitmap takes
- // as free entries (this is done in order to have the ability
- // to place mem alloc bitmap outside lower 16Mb zone)
- PagesCount = 1;
- LastPageIndex = 0;
- LastPageType = MemoryMap[0].PageAllocated;
- for(i=1;i<NoEntries;i++)
- {
- // Check if its memory map itself
- if (i >= MemoryMapStartPage &&
- i < (MemoryMapStartPage+MemoryMapSizeInPages))
- {
- // Exclude it if current page belongs to the memory map
- MemoryMap[i].PageAllocated = LoaderFree;
- }
-
- // Process entry
- if (MemoryMap[i].PageAllocated == LastPageType &&
- (i != NoEntries-1) )
- {
- PagesCount++;
- }
- else
- {
- // Add the resulting region
- MempAddMemoryBlock(LoaderBlock, LastPageIndex, PagesCount, LastPageType);
-
- // Reset our counter vars
- LastPageIndex = i;
- LastPageType = MemoryMap[i].PageAllocated;
- PagesCount = 1;
- }
- }
-
- // TEMP, DEBUG!
- // adding special reserved memory zones for vmware workstation
-#if 0
- {
- Mad[MadCount].BasePage = 0xfec00;
- Mad[MadCount].PageCount = 0x10;
- Mad[MadCount].MemoryType = LoaderSpecialMemory;
- WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
- MadCount++;
-
- Mad[MadCount].BasePage = 0xfee00;
- Mad[MadCount].PageCount = 0x1;
- Mad[MadCount].MemoryType = LoaderSpecialMemory;
- WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
- MadCount++;
-
- Mad[MadCount].BasePage = 0xfffe0;
- Mad[MadCount].PageCount = 0x20;
- Mad[MadCount].MemoryType = LoaderSpecialMemory;
- WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
- MadCount++;
- }
-#endif
-
- DbgPrint((DPRINT_WINDOWS, "MadCount: %d\n", MadCount));
-
- WinLdrpDumpMemoryDescriptors(LoaderBlock); //FIXME: Delete!
-
- // Map our loader image, so we can continue running
- /*Status = MempSetupPaging(OsLoaderBase >> MM_PAGE_SHIFT, OsLoaderSize >> MM_PAGE_SHIFT);
- if (!Status)
- {
- UiMessageBox("Error during MempSetupPaging");
- return;
- }*/
-
- //VideoDisplayString(L"Hello from VGA, going into the kernel\n");
- DbgPrint((DPRINT_WINDOWS, "HalPT: 0x%X\n", HalPT));
-
- // Page Tables have been setup, make special handling for PCR and TSS
- // (which is done in BlSetupFotNt in usual ntldr)
- HalPT[(KI_USER_SHARED_DATA - 0xFFC00000) >> MM_PAGE_SHIFT].PageFrameNumber = PcrBasePage+1;
- HalPT[(KI_USER_SHARED_DATA - 0xFFC00000) >> MM_PAGE_SHIFT].Valid = 1;
- HalPT[(KI_USER_SHARED_DATA - 0xFFC00000) >> MM_PAGE_SHIFT].Write = 1;
-
- HalPT[(KIP0PCRADDRESS - 0xFFC00000) >> MM_PAGE_SHIFT].PageFrameNumber = PcrBasePage;
- HalPT[(KIP0PCRADDRESS - 0xFFC00000) >> MM_PAGE_SHIFT].Valid = 1;
- HalPT[(KIP0PCRADDRESS - 0xFFC00000) >> MM_PAGE_SHIFT].Write = 1;
-
- // Map VGA memory
- //VideoMemoryBase = MmMapIoSpace(0xb8000, 4000, MmNonCached);
- //DbgPrint((DPRINT_WINDOWS, "VideoMemoryBase: 0x%X\n", VideoMemoryBase));
-
- Tss = (PKTSS)(KSEG0_BASE | (TssBasePage << MM_PAGE_SHIFT));
-
- // Unmap what is not needed from kernel page table
- MempDisablePages();
-
- // Fill the memory descriptor list and
- //PrepareMemoryDescriptorList();
- DbgPrint((DPRINT_WINDOWS, "Memory Descriptor List prepared, printing PDE\n"));
- List_PaToVa(&LoaderBlock->MemoryDescriptorListHead);
-
-#ifdef DBG
- {
- ULONG *PDE_Addr=(ULONG *)PDE;//0xC0300000;
- int j;
-
- DbgPrint((DPRINT_WINDOWS, "\nPDE\n"));
-
- for (i=0; i<128; i++)
- {
- DbgPrint((DPRINT_WINDOWS, "0x%04X | ", i*8));
-
- for (j=0; j<8; j++)
- {
- DbgPrint((DPRINT_WINDOWS, "0x%08X ", PDE_Addr[i*8+j]));
- }
-
- DbgPrint((DPRINT_WINDOWS, "\n"));
- }
- }
-#endif
-
-
- // Enable paging
- //BS->ExitBootServices(ImageHandle,MapKey);
-
- // Disable Interrupts
- _disable();
-
- // Re-initalize EFLAGS
- Ke386EraseFlags();
-
- // Set the PDBR
- __writecr3((ULONG_PTR)PDE);
-
- // Enable paging by modifying CR0
- __writecr0(__readcr0() | CR0_PG);
-
- // Set processor context
- WinLdrSetProcessorContext(GdtIdt, KIP0PCRADDRESS, KSEG0_BASE | (TssBasePage << MM_PAGE_SHIFT));
-
- // Zero KI_USER_SHARED_DATA page
- memset((PVOID)KI_USER_SHARED_DATA, 0, MM_PAGE_SIZE);
-
- return TRUE;
-}
-
-// Two special things this func does: it sorts descriptors,
-// and it merges free ones
-VOID
-WinLdrInsertDescriptor(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
- IN PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor)
-{
- PLIST_ENTRY ListHead = &LoaderBlock->MemoryDescriptorListHead;
- PLIST_ENTRY PreviousEntry, NextEntry;
- PMEMORY_ALLOCATION_DESCRIPTOR PreviousDescriptor = NULL, NextDescriptor = NULL;
-
- DbgPrint((DPRINT_WINDOWS, "BP=0x%X PC=0x%X %s\n", NewDescriptor->BasePage,
- NewDescriptor->PageCount, MemTypeDesc[NewDescriptor->MemoryType]));
-
- /* Find a place where to insert the new descriptor to */
- PreviousEntry = ListHead;
- NextEntry = ListHead->Flink;
- while (NextEntry != ListHead)
- {
- NextDescriptor = CONTAINING_RECORD(NextEntry,
- MEMORY_ALLOCATION_DESCRIPTOR,
- ListEntry);
- if (NewDescriptor->BasePage < NextDescriptor->BasePage)
- break;
-
- PreviousEntry = NextEntry;
- PreviousDescriptor = NextDescriptor;
- NextEntry = NextEntry->Flink;
- }
-
- /* Don't forget about merging free areas */
- if (NewDescriptor->MemoryType != LoaderFree)
- {
- /* Just insert, nothing to merge */
- InsertHeadList(PreviousEntry, &NewDescriptor->ListEntry);
- }
- else
- {
- /* Previous block also free? */
- if ((PreviousEntry != ListHead) && (PreviousDescriptor->MemoryType == LoaderFree) &&
- ((PreviousDescriptor->BasePage + PreviousDescriptor->PageCount) ==
- NewDescriptor->BasePage))
- {
- /* Just enlarge previous descriptor's PageCount */
- PreviousDescriptor->PageCount += NewDescriptor->PageCount;
- NewDescriptor = PreviousDescriptor;
- }
- else
- {
- /* Nope, just insert */
- InsertHeadList(PreviousEntry, &NewDescriptor->ListEntry);
- }
-
- /* Next block is free ?*/
- if ((NextEntry != ListHead) &&
- (NextDescriptor->MemoryType == LoaderFree) &&
- ((NewDescriptor->BasePage + NewDescriptor->PageCount) == NextDescriptor->BasePage))
- {
- /* Enlarge next descriptor's PageCount */
- NewDescriptor->PageCount += NextDescriptor->PageCount;
- RemoveEntryList(&NextDescriptor->ListEntry);
- }
- }
-
- return;
-}
-
-VOID
-WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss)
-{
- GDTIDT GdtDesc, IdtDesc, OldIdt;
- PKGDTENTRY pGdt;
- PKIDTENTRY pIdt;
- ULONG Ldt = 0;
- //ULONG i;
-
- DbgPrint((DPRINT_WINDOWS, "GDtIdt %p, Pcr %p, Tss 0x%08X\n",
- GdtIdt, Pcr, Tss));
-
- // Kernel expects the PCR to be zero-filled on startup
- // FIXME: Why zero it here when we can zero it right after allocation?
- RtlZeroMemory((PVOID)Pcr, MM_PAGE_SIZE); //FIXME: Why zero only 1 page when we allocate 2?
-
- // Get old values of GDT and IDT
- Ke386GetGlobalDescriptorTable(GdtDesc);
- Ke386GetInterruptDescriptorTable(IdtDesc);
-
- // Save old IDT
- OldIdt.Base = IdtDesc.Base;
- OldIdt.Limit = IdtDesc.Limit;
-
- // Prepare new IDT+GDT
- GdtDesc.Base = KSEG0_BASE | (ULONG_PTR)GdtIdt;
- GdtDesc.Limit = NUM_GDT * sizeof(KGDTENTRY) - 1;
- IdtDesc.Base = (ULONG)((PUCHAR)GdtDesc.Base + GdtDesc.Limit + 1);
- IdtDesc.Limit = NUM_IDT * sizeof(KIDTENTRY) - 1;
-
- // ========================
- // Fill all descriptors now
- // ========================
-
- pGdt = (PKGDTENTRY)GdtDesc.Base;
- pIdt = (PKIDTENTRY)IdtDesc.Base;
-
- //
- // Code selector (0x8)
- // Flat 4Gb
- //
- pGdt[1].LimitLow = 0xFFFF;
- pGdt[1].BaseLow = 0;
- pGdt[1].HighWord.Bytes.BaseMid = 0;
- pGdt[1].HighWord.Bytes.Flags1 = 0x9A;
- pGdt[1].HighWord.Bytes.Flags2 = 0xCF;
- pGdt[1].HighWord.Bytes.BaseHi = 0;
-
- //
- // Data selector (0x10)
- // Flat 4Gb
- //
- pGdt[2].LimitLow = 0xFFFF;
- pGdt[2].BaseLow = 0;
- pGdt[2].HighWord.Bytes.BaseMid = 0;
- pGdt[2].HighWord.Bytes.Flags1 = 0x92;
- pGdt[2].HighWord.Bytes.Flags2 = 0xCF;
- pGdt[2].HighWord.Bytes.BaseHi = 0;
-
- //
- // Selector (0x18)
- // Flat 2Gb
- //
- pGdt[3].LimitLow = 0xFFFF;
- pGdt[3].BaseLow = 0;
- pGdt[3].HighWord.Bytes.BaseMid = 0;
- pGdt[3].HighWord.Bytes.Flags1 = 0xFA;
- pGdt[3].HighWord.Bytes.Flags2 = 0xCF;
- pGdt[3].HighWord.Bytes.BaseHi = 0;
-
- //
- // Selector (0x20)
- // Flat 2Gb
- //
- pGdt[4].LimitLow = 0xFFFF;
- pGdt[4].BaseLow = 0;
- pGdt[4].HighWord.Bytes.BaseMid = 0;
- pGdt[4].HighWord.Bytes.Flags1 = 0xF2;
- pGdt[4].HighWord.Bytes.Flags2 = 0xCF;
- pGdt[4].HighWord.Bytes.BaseHi = 0;
-
- //
- // TSS Selector (0x28)
- //
- pGdt[5].LimitLow = 0x78-1; //FIXME: Check this
- pGdt[5].BaseLow = (USHORT)(Tss & 0xffff);
- pGdt[5].HighWord.Bytes.BaseMid = (UCHAR)((Tss >> 16) & 0xff);
- pGdt[5].HighWord.Bytes.Flags1 = 0x89;
- pGdt[5].HighWord.Bytes.Flags2 = 0x00;
- pGdt[5].HighWord.Bytes.BaseHi = (UCHAR)((Tss >> 24) & 0xff);
-
- //
- // PCR Selector (0x30)
- //
- pGdt[6].LimitLow = 0x01;
- pGdt[6].BaseLow = (USHORT)(Pcr & 0xffff);
- pGdt[6].HighWord.Bytes.BaseMid = (UCHAR)((Pcr >> 16) & 0xff);
- pGdt[6].HighWord.Bytes.Flags1 = 0x92;
- pGdt[6].HighWord.Bytes.Flags2 = 0xC0;
- pGdt[6].HighWord.Bytes.BaseHi = (UCHAR)((Pcr >> 24) & 0xff);
-
- //
- // Selector (0x38)
- //
- pGdt[7].LimitLow = 0xFFFF;
- pGdt[7].BaseLow = 0;
- pGdt[7].HighWord.Bytes.BaseMid = 0;
- pGdt[7].HighWord.Bytes.Flags1 = 0xF3;
- pGdt[7].HighWord.Bytes.Flags2 = 0x40;
- pGdt[7].HighWord.Bytes.BaseHi = 0;
-
- //
- // Some BIOS fuck (0x40)
- //
- pGdt[8].LimitLow = 0xFFFF;
- pGdt[8].BaseLow = 0x400;
- pGdt[8].HighWord.Bytes.BaseMid = 0;
- pGdt[8].HighWord.Bytes.Flags1 = 0xF2;
- pGdt[8].HighWord.Bytes.Flags2 = 0x0;
- pGdt[8].HighWord.Bytes.BaseHi = 0;
-
- //
- // Selector (0x48)
- //
- pGdt[9].LimitLow = 0;
- pGdt[9].BaseLow = 0;
- pGdt[9].HighWord.Bytes.BaseMid = 0;
- pGdt[9].HighWord.Bytes.Flags1 = 0;
- pGdt[9].HighWord.Bytes.Flags2 = 0;
- pGdt[9].HighWord.Bytes.BaseHi = 0;
-
- //
- // Selector (0x50)
- //
- pGdt[10].LimitLow = 0xFFFF; //FIXME: Not correct!
- pGdt[10].BaseLow = 0;
- pGdt[10].HighWord.Bytes.BaseMid = 0x2;
- pGdt[10].HighWord.Bytes.Flags1 = 0x89;
- pGdt[10].HighWord.Bytes.Flags2 = 0;
- pGdt[10].HighWord.Bytes.BaseHi = 0;
-
- //
- // Selector (0x58)
- //
- pGdt[11].LimitLow = 0xFFFF;
- pGdt[11].BaseLow = 0;
- pGdt[11].HighWord.Bytes.BaseMid = 0x2;
- pGdt[11].HighWord.Bytes.Flags1 = 0x9A;
- pGdt[11].HighWord.Bytes.Flags2 = 0;
- pGdt[11].HighWord.Bytes.BaseHi = 0;
-
- //
- // Selector (0x60)
- //
- pGdt[12].LimitLow = 0xFFFF;
- pGdt[12].BaseLow = 0; //FIXME: Maybe not correct, but noone cares
- pGdt[12].HighWord.Bytes.BaseMid = 0x2;
- pGdt[12].HighWord.Bytes.Flags1 = 0x92;
- pGdt[12].HighWord.Bytes.Flags2 = 0;
- pGdt[12].HighWord.Bytes.BaseHi = 0;
-
- //
- // Video buffer Selector (0x68)
- //
- pGdt[13].LimitLow = 0x3FFF;
- pGdt[13].BaseLow = 0x8000; //FIXME: I guess not correct for UGA
- pGdt[13].HighWord.Bytes.BaseMid = 0x0B;
- pGdt[13].HighWord.Bytes.Flags1 = 0x92;
- pGdt[13].HighWord.Bytes.Flags2 = 0;
- pGdt[13].HighWord.Bytes.BaseHi = 0;
-
- //
- // Points to GDT (0x70)
- //
- pGdt[14].LimitLow = NUM_GDT*sizeof(KGDTENTRY) - 1;
- pGdt[14].BaseLow = 0x7000;
- pGdt[14].HighWord.Bytes.BaseMid = 0xFF;
- pGdt[14].HighWord.Bytes.Flags1 = 0x92;
- pGdt[14].HighWord.Bytes.Flags2 = 0;
- pGdt[14].HighWord.Bytes.BaseHi = 0xFF;
-
- //
- // Some unused descriptors should go here
- // ...
-
- // Copy the old IDT
- RtlCopyMemory(pIdt, (PVOID)OldIdt.Base, OldIdt.Limit);
-
- // Mask interrupts
- //asm("cli\n"); // they are already masked before enabling paged mode
-
- // Load GDT+IDT
- Ke386SetGlobalDescriptorTable(GdtDesc);
- Ke386SetInterruptDescriptorTable(IdtDesc);
-
- // Jump to proper CS and clear prefetch queue
- asm("ljmp $0x08, $mb1\n"
- "mb1:\n");
-
- // Set SS selector
- asm(".intel_syntax noprefix\n");
- asm("mov ax, 0x10\n"); // DataSelector=0x10
- asm("mov ss, ax\n");
- asm(".att_syntax\n");
-
- // Set DS and ES selectors
- Ke386SetDs(0x10);
- Ke386SetEs(0x10); // this is vital for rep stosd
-
- // LDT = not used ever, thus set to 0
- Ke386SetLocalDescriptorTable(Ldt);
-
- // Load TSR
- Ke386SetTr(0x28);
-
- // Clear GS
- asm(".intel_syntax noprefix\n");
- asm("push 0\n");
- asm("pop gs\n");
- asm(".att_syntax\n");
-
- // Set FS to PCR
- Ke386SetFs(0x30);
-
- // Real end of the function, just for information
- /* do not uncomment!
- pop edi;
- pop esi;
- pop ebx;
- mov esp, ebp;
- pop ebp;
- ret
- */
-}
+/*\r
+ * PROJECT: EFI Windows Loader\r
+ * LICENSE: GPL - See COPYING in the top level directory\r
+ * FILE: freeldr/winldr/wlmemory.c\r
+ * PURPOSE: Memory related routines\r
+ * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)\r
+ */\r
+\r
+/* INCLUDES ***************************************************************/\r
+\r
+#include <freeldr.h>\r
+\r
+#include <ndk/asm.h>\r
+#include <debug.h>\r
+\r
+extern ULONG TotalNLSSize;\r
+\r
+// This is needed because headers define wrong one for ReactOS\r
+#undef KIP0PCRADDRESS\r
+#define KIP0PCRADDRESS 0xffdff000\r
+\r
+#define HYPER_SPACE_ENTRY 0x300\r
+\r
+PCHAR MemTypeDesc[] = {\r
+ "ExceptionBlock ", // ?\r
+ "SystemBlock ", // ?\r
+ "Free ",\r
+ "Bad ", // used\r
+ "LoadedProgram ", // == Free\r
+ "FirmwareTemporary ", // == Free\r
+ "FirmwarePermanent ", // == Bad\r
+ "OsloaderHeap ", // used\r
+ "OsloaderStack ", // == Free\r
+ "SystemCode ",\r
+ "HalCode ",\r
+ "BootDriver ", // not used\r
+ "ConsoleInDriver ", // ?\r
+ "ConsoleOutDriver ", // ?\r
+ "StartupDpcStack ", // ?\r
+ "StartupKernelStack", // ?\r
+ "StartupPanicStack ", // ?\r
+ "StartupPcrPage ", // ?\r
+ "StartupPdrPage ", // ?\r
+ "RegistryData ", // used\r
+ "MemoryData ", // not used\r
+ "NlsData ", // used\r
+ "SpecialMemory ", // == Bad\r
+ "BBTMemory " // == Bad\r
+ };\r
+\r
+VOID\r
+WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock);\r
+\r
+\r
+VOID\r
+MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,\r
+ ULONG BasePage,\r
+ ULONG PageCount,\r
+ ULONG Type);\r
+VOID\r
+WinLdrInsertDescriptor(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,\r
+ IN PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor);\r
+\r
+VOID\r
+WinLdrRemoveDescriptor(IN PMEMORY_ALLOCATION_DESCRIPTOR Descriptor);\r
+\r
+VOID\r
+WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss);\r
+\r
+// This is needed only for SetProcessorContext routine\r
+#pragma pack(2)\r
+ typedef struct\r
+ {\r
+ USHORT Limit;\r
+ ULONG Base;\r
+ } GDTIDT;\r
+#pragma pack(4)\r
+\r
+// this is needed for new IDT filling\r
+#if 0\r
+extern ULONG_PTR i386DivideByZero;\r
+extern ULONG_PTR i386DebugException;\r
+extern ULONG_PTR i386NMIException;\r
+extern ULONG_PTR i386Breakpoint;\r
+extern ULONG_PTR i386Overflow;\r
+extern ULONG_PTR i386BoundException;\r
+extern ULONG_PTR i386InvalidOpcode;\r
+extern ULONG_PTR i386FPUNotAvailable;\r
+extern ULONG_PTR i386DoubleFault;\r
+extern ULONG_PTR i386CoprocessorSegment;\r
+extern ULONG_PTR i386InvalidTSS;\r
+extern ULONG_PTR i386SegmentNotPresent;\r
+extern ULONG_PTR i386StackException;\r
+extern ULONG_PTR i386GeneralProtectionFault;\r
+extern ULONG_PTR i386PageFault; // exc 14\r
+extern ULONG_PTR i386CoprocessorError; // exc 16\r
+extern ULONG_PTR i386AlignmentCheck; // exc 17\r
+#endif\r
+\r
+/* GLOBALS ***************************************************************/\r
+\r
+PHARDWARE_PTE PDE;\r
+PHARDWARE_PTE HalPT;\r
+\r
+PUCHAR PhysicalPageTablesBuffer;\r
+PUCHAR KernelPageTablesBuffer;\r
+ULONG PhysicalPageTables;\r
+ULONG KernelPageTables;\r
+\r
+MEMORY_ALLOCATION_DESCRIPTOR *Mad;\r
+ULONG MadCount = 0;\r
+\r
+\r
+/* FUNCTIONS **************************************************************/\r
+\r
+BOOLEAN\r
+MempAllocatePageTables()\r
+{\r
+ ULONG NumPageTables, TotalSize;\r
+ PUCHAR Buffer;\r
+ // It's better to allocate PDE + PTEs contigiuos\r
+\r
+ // Max number of entries = MaxPageNum >> 10\r
+ // FIXME: This is a number to describe ALL physical memory\r
+ // and windows doesn't expect ALL memory mapped...\r
+ NumPageTables = (GetSystemMemorySize() >> MM_PAGE_SHIFT) >> 10;\r
+\r
+ DbgPrint((DPRINT_WINDOWS, "NumPageTables = %d\n", NumPageTables));\r
+\r
+ // Allocate memory block for all these things:\r
+ // PDE, HAL mapping page table, physical mapping, kernel mapping\r
+ // FIXME: PDE+HAL+KernelPTEs == FirmwarePermanent, Physical PTEs = FirmwareTemporary\r
+ TotalSize = (1+1+NumPageTables*2)*MM_PAGE_SIZE;\r
+ Buffer = MmAllocateMemoryWithType(TotalSize, LoaderFirmwarePermanent);\r
+\r
+ if (Buffer == NULL)\r
+ {\r
+ UiMessageBox("Impossible to allocate memory block for page tables!");\r
+ return FALSE;\r
+ }\r
+\r
+ // Zero all this memory block\r
+ RtlZeroMemory(Buffer, TotalSize);\r
+\r
+ // Set up pointers correctly now\r
+ PDE = (PHARDWARE_PTE)Buffer;\r
+\r
+ // Map the page directory at 0xC0000000 (maps itself)\r
+ PDE[HYPER_SPACE_ENTRY].PageFrameNumber = (ULONG)PDE >> MM_PAGE_SHIFT;\r
+ PDE[HYPER_SPACE_ENTRY].Valid = 1;\r
+ PDE[HYPER_SPACE_ENTRY].Write = 1;\r
+\r
+ // The last PDE slot is allocated for HAL's memory mapping (Virtual Addresses 0xFFC00000 - 0xFFFFFFFF)\r
+ HalPT = (PHARDWARE_PTE)&Buffer[MM_PAGE_SIZE*1];\r
+\r
+ // Map it\r
+ PDE[1023].PageFrameNumber = (ULONG)HalPT >> MM_PAGE_SHIFT;\r
+ PDE[1023].Valid = 1;\r
+ PDE[1023].Write = 1;\r
+\r
+ // Store pointers to the tables for easier access\r
+ PhysicalPageTablesBuffer = &Buffer[MM_PAGE_SIZE*2];\r
+ KernelPageTablesBuffer = PhysicalPageTablesBuffer + NumPageTables*MM_PAGE_SIZE;\r
+\r
+ // Mark physical PTE's buffer as FirmwareTemporary\r
+ //MmSetMemoryType(KernelPageTablesBuffer, NumPageTables*MM_PAGE_SIZE, LoaderFirmwareTemporary);\r
+\r
+ // Zero counters of page tables used\r
+ PhysicalPageTables = 0;\r
+ KernelPageTables = 0;\r
+\r
+ return TRUE;\r
+}\r
+\r
+VOID\r
+MempAllocatePTE(ULONG Entry, PHARDWARE_PTE *PhysicalPT, PHARDWARE_PTE *KernelPT)\r
+{\r
+ //Print(L"Creating PDE Entry %X\n", Entry);\r
+\r
+ // Identity mapping\r
+ *PhysicalPT = (PHARDWARE_PTE)&PhysicalPageTablesBuffer[PhysicalPageTables*MM_PAGE_SIZE];\r
+ PhysicalPageTables++;\r
+\r
+ PDE[Entry].PageFrameNumber = (ULONG)*PhysicalPT >> MM_PAGE_SHIFT;\r
+ PDE[Entry].Valid = 1;\r
+ PDE[Entry].Write = 1;\r
+\r
+ if (Entry+(KSEG0_BASE >> 22) > 1023)\r
+ {\r
+ DbgPrint((DPRINT_WINDOWS, "WARNING! Entry: %X > 1023\n", Entry+(KSEG0_BASE >> 22)));\r
+ }\r
+\r
+ // Kernel-mode mapping\r
+ *KernelPT = (PHARDWARE_PTE)&KernelPageTablesBuffer[KernelPageTables*MM_PAGE_SIZE];\r
+ KernelPageTables++;\r
+\r
+ PDE[Entry+(KSEG0_BASE >> 22)].PageFrameNumber = ((ULONG)*KernelPT >> MM_PAGE_SHIFT);\r
+ PDE[Entry+(KSEG0_BASE >> 22)].Valid = 1;\r
+ PDE[Entry+(KSEG0_BASE >> 22)].Write = 1;\r
+}\r
+\r
+BOOLEAN\r
+MempSetupPaging(IN ULONG StartPage,\r
+ IN ULONG NumberOfPages)\r
+{\r
+ PHARDWARE_PTE PhysicalPT;\r
+ PHARDWARE_PTE KernelPT;\r
+ ULONG Entry, Page;\r
+\r
+ //Print(L"MempSetupPaging: SP 0x%X, Number: 0x%X\n", StartPage, NumberOfPages);\r
+ \r
+ // HACK\r
+ if (StartPage+NumberOfPages >= 0x80000)\r
+ {\r
+ //\r
+ // We can't map this as it requires more than 1 PDE\r
+ // and in fact it's not possible at all ;)\r
+ //\r
+ //Print(L"skipping...\n");\r
+ return TRUE;\r
+ }\r
+\r
+ //\r
+ // Now actually set up the page tables for identity mapping\r
+ //\r
+ for (Page=StartPage; Page < StartPage+NumberOfPages; Page++)\r
+ {\r
+ Entry = Page >> 10;\r
+\r
+ if (((PULONG)PDE)[Entry] == 0)\r
+ {\r
+ MempAllocatePTE(Entry, &PhysicalPT, &KernelPT);\r
+ }\r
+ else\r
+ {\r
+ PhysicalPT = (PHARDWARE_PTE)(PDE[Entry].PageFrameNumber << MM_PAGE_SHIFT);\r
+ KernelPT = (PHARDWARE_PTE)(PDE[Entry+(KSEG0_BASE >> 22)].PageFrameNumber << MM_PAGE_SHIFT);\r
+ }\r
+\r
+ if (Page == 0)\r
+ {\r
+ PhysicalPT[Page & 0x3ff].PageFrameNumber = Page;\r
+ PhysicalPT[Page & 0x3ff].Valid = 0;\r
+ PhysicalPT[Page & 0x3ff].Write = 0;\r
+\r
+ KernelPT[Page & 0x3ff].PageFrameNumber = Page;\r
+ KernelPT[Page & 0x3ff].Valid = 0;\r
+ KernelPT[Page & 0x3ff].Write = 0;\r
+ }\r
+ else\r
+ {\r
+ PhysicalPT[Page & 0x3ff].PageFrameNumber = Page;\r
+ PhysicalPT[Page & 0x3ff].Valid = 1;\r
+ PhysicalPT[Page & 0x3ff].Write = 1;\r
+\r
+ KernelPT[Page & 0x3ff].PageFrameNumber = Page;\r
+ KernelPT[Page & 0x3ff].Valid = 1;\r
+ KernelPT[Page & 0x3ff].Write = 1;\r
+ }\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+VOID\r
+MempDisablePages()\r
+{\r
+ int i;\r
+\r
+ //\r
+ // We need to delete kernel mapping from memory areas which are\r
+ // marked as Special or Permanent memory (thus non-accessible)\r
+ //\r
+\r
+ for (i=0; i<MadCount; i++)\r
+ {\r
+ ULONG StartPage, EndPage, Page;\r
+\r
+ StartPage = Mad[i].BasePage;\r
+ EndPage = Mad[i].BasePage + Mad[i].PageCount;\r
+\r
+ if (Mad[i].MemoryType == LoaderFirmwarePermanent ||\r
+ Mad[i].MemoryType == LoaderSpecialMemory ||\r
+ Mad[i].MemoryType == LoaderFree ||\r
+ (Mad[i].MemoryType == LoaderFirmwareTemporary && EndPage <= LOADER_HIGH_ZONE) ||\r
+ Mad[i].MemoryType == LoaderOsloaderStack ||\r
+ Mad[i].MemoryType == LoaderLoadedProgram)\r
+ {\r
+\r
+ //\r
+ // But, the first megabyte of memory always stays!\r
+ // And, to tell the truth, we don't care about what's higher\r
+ // than LOADER_HIGH_ZONE\r
+ if (Mad[i].MemoryType == LoaderFirmwarePermanent ||\r
+ Mad[i].MemoryType == LoaderSpecialMemory)\r
+ {\r
+ if (StartPage < 0x100)\r
+ StartPage = 0x100;\r
+\r
+ if (EndPage > LOADER_HIGH_ZONE)\r
+ EndPage = LOADER_HIGH_ZONE;\r
+ }\r
+\r
+ for (Page = StartPage; Page < EndPage; Page++)\r
+ {\r
+ PHARDWARE_PTE KernelPT;\r
+ ULONG Entry = (Page >> 10) + (KSEG0_BASE >> 22);\r
+\r
+ if (PDE[Entry].Valid)\r
+ {\r
+ KernelPT = (PHARDWARE_PTE)(PDE[Entry].PageFrameNumber << MM_PAGE_SHIFT);\r
+\r
+ if (KernelPT)\r
+ {\r
+ KernelPT[Page & 0x3ff].PageFrameNumber = 0;\r
+ KernelPT[Page & 0x3ff].Valid = 0;\r
+ KernelPT[Page & 0x3ff].Write = 0;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+\r
+VOID\r
+MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,\r
+ ULONG BasePage,\r
+ ULONG PageCount,\r
+ ULONG Type)\r
+{\r
+ BOOLEAN Status;\r
+\r
+ //\r
+ // Check for some weird stuff at the top\r
+ //\r
+ if (BasePage + PageCount > 0xF0000)\r
+ {\r
+ //\r
+ // Just skip this, without even adding to MAD list\r
+ //\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Set Base page, page count and type\r
+ //\r
+ Mad[MadCount].BasePage = BasePage;\r
+ Mad[MadCount].PageCount = PageCount;\r
+ Mad[MadCount].MemoryType = Type;\r
+\r
+ //\r
+ // Check if it's more than the allowed for OS loader\r
+ // if yes - don't map the pages, just add as FirmwareTemporary\r
+ //\r
+ if (BasePage + PageCount > LOADER_HIGH_ZONE)\r
+ {\r
+ if (Mad[MadCount].MemoryType != LoaderSpecialMemory ||\r
+ Mad[MadCount].MemoryType != LoaderFirmwarePermanent)\r
+ {\r
+ Mad[MadCount].MemoryType = LoaderFirmwareTemporary;\r
+ }\r
+\r
+ WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);\r
+ MadCount++;\r
+\r
+ return;\r
+ }\r
+ \r
+ //\r
+ // Add descriptor\r
+ //\r
+ WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);\r
+ MadCount++;\r
+\r
+ //\r
+ // Map it (don't map low 1Mb because it was already contigiously\r
+ // mapped in WinLdrTurnOnPaging)\r
+ //\r
+ if (BasePage >= 0x100)\r
+ {\r
+ Status = MempSetupPaging(BasePage, PageCount);\r
+ if (!Status)\r
+ {\r
+ DbgPrint((DPRINT_WINDOWS, "Error during MempSetupPaging\n"));\r
+ return;\r
+ }\r
+ }\r
+}\r
+\r
+BOOLEAN\r
+WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,\r
+ ULONG PcrBasePage,\r
+ ULONG TssBasePage,\r
+ PVOID GdtIdt)\r
+{\r
+ ULONG i, PagesCount, MemoryMapSizeInPages;\r
+ ULONG LastPageIndex, LastPageType, MemoryMapStartPage;\r
+ PPAGE_LOOKUP_TABLE_ITEM MemoryMap;\r
+ ULONG NoEntries;\r
+ PKTSS Tss;\r
+ BOOLEAN Status;\r
+\r
+ //\r
+ // Creating a suitable memory map for the Windows can be tricky, so let's\r
+ // give a few advices:\r
+ // 1) One must not map the whole available memory pages to PDE!\r
+ // Map only what's needed - 16Mb, 24Mb, 32Mb max I think,\r
+ // thus occupying 4, 6 or 8 PDE entries for identical mapping,\r
+ // the same quantity for KSEG0_BASE mapping, one more entry for\r
+ // hyperspace and one more entry for HAL physical pages mapping.\r
+ // 2) Memory descriptors must map *the whole* physical memory\r
+ // showing any memory above 16/24/32 as FirmwareTemporary\r
+ //\r
+ // 3) Overall memory blocks count must not exceed 30\r
+ //\r
+\r
+ //\r
+ // During MmInitMachineDependent, the kernel zeroes PDE at the following address\r
+ // 0xC0300000 - 0xC03007FC\r
+ //\r
+ // Then it finds the best place for non-paged pool:\r
+ // StartPde C0300F70, EndPde C0300FF8, NumberOfPages C13, NextPhysPage 3AD\r
+ //\r
+\r
+ // Before we start mapping pages, create a block of memory, which will contain\r
+ // PDE and PTEs\r
+ if (MempAllocatePageTables() == FALSE)\r
+ return FALSE;\r
+\r
+ // Allocate memory for memory allocation descriptors\r
+ Mad = MmHeapAlloc(sizeof(MEMORY_ALLOCATION_DESCRIPTOR) * 1024);\r
+\r
+ // Setup an entry for each descriptor\r
+ MemoryMap = MmGetMemoryMap(&NoEntries);\r
+ if (MemoryMap == NULL)\r
+ {\r
+ UiMessageBox("Can not retrieve the current memory map");\r
+ return FALSE;\r
+ }\r
+\r
+ // Calculate parameters of the memory map\r
+ MemoryMapStartPage = (ULONG_PTR)MemoryMap >> MM_PAGE_SHIFT;\r
+ MemoryMapSizeInPages = NoEntries * sizeof(PAGE_LOOKUP_TABLE_ITEM);\r
+\r
+ DbgPrint((DPRINT_WINDOWS, "Got memory map with %d entries\n", NoEntries));\r
+\r
+ // Always contigiously map low 1Mb of memory\r
+ Status = MempSetupPaging(0, 0x100);\r
+ if (!Status)\r
+ {\r
+ DbgPrint((DPRINT_WINDOWS, "Error during MempSetupPaging of low 1Mb\n"));\r
+ return FALSE;\r
+ }\r
+\r
+ // Construct a good memory map from what we've got,\r
+ // but mark entries which the memory allocation bitmap takes\r
+ // as free entries (this is done in order to have the ability\r
+ // to place mem alloc bitmap outside lower 16Mb zone)\r
+ PagesCount = 1;\r
+ LastPageIndex = 0;\r
+ LastPageType = MemoryMap[0].PageAllocated;\r
+ for(i=1;i<NoEntries;i++)\r
+ {\r
+ // Check if its memory map itself\r
+ if (i >= MemoryMapStartPage &&\r
+ i < (MemoryMapStartPage+MemoryMapSizeInPages))\r
+ {\r
+ // Exclude it if current page belongs to the memory map\r
+ MemoryMap[i].PageAllocated = LoaderFree;\r
+ }\r
+\r
+ // Process entry\r
+ if (MemoryMap[i].PageAllocated == LastPageType &&\r
+ (i != NoEntries-1) )\r
+ {\r
+ PagesCount++;\r
+ }\r
+ else\r
+ {\r
+ // Add the resulting region\r
+ MempAddMemoryBlock(LoaderBlock, LastPageIndex, PagesCount, LastPageType);\r
+\r
+ // Reset our counter vars\r
+ LastPageIndex = i;\r
+ LastPageType = MemoryMap[i].PageAllocated;\r
+ PagesCount = 1;\r
+ }\r
+ }\r
+\r
+ // TEMP, DEBUG!\r
+ // adding special reserved memory zones for vmware workstation\r
+#if 0\r
+ {\r
+ Mad[MadCount].BasePage = 0xfec00;\r
+ Mad[MadCount].PageCount = 0x10;\r
+ Mad[MadCount].MemoryType = LoaderSpecialMemory;\r
+ WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);\r
+ MadCount++;\r
+\r
+ Mad[MadCount].BasePage = 0xfee00;\r
+ Mad[MadCount].PageCount = 0x1;\r
+ Mad[MadCount].MemoryType = LoaderSpecialMemory;\r
+ WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);\r
+ MadCount++;\r
+\r
+ Mad[MadCount].BasePage = 0xfffe0;\r
+ Mad[MadCount].PageCount = 0x20;\r
+ Mad[MadCount].MemoryType = LoaderSpecialMemory;\r
+ WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);\r
+ MadCount++;\r
+ }\r
+#endif\r
+\r
+ DbgPrint((DPRINT_WINDOWS, "MadCount: %d\n", MadCount));\r
+\r
+ WinLdrpDumpMemoryDescriptors(LoaderBlock); //FIXME: Delete!\r
+\r
+ // Map our loader image, so we can continue running\r
+ /*Status = MempSetupPaging(OsLoaderBase >> MM_PAGE_SHIFT, OsLoaderSize >> MM_PAGE_SHIFT);\r
+ if (!Status)\r
+ {\r
+ UiMessageBox("Error during MempSetupPaging");\r
+ return;\r
+ }*/\r
+\r
+ //VideoDisplayString(L"Hello from VGA, going into the kernel\n");\r
+ DbgPrint((DPRINT_WINDOWS, "HalPT: 0x%X\n", HalPT));\r
+\r
+ // Page Tables have been setup, make special handling for PCR and TSS\r
+ // (which is done in BlSetupFotNt in usual ntldr)\r
+ HalPT[(KI_USER_SHARED_DATA - 0xFFC00000) >> MM_PAGE_SHIFT].PageFrameNumber = PcrBasePage+1;\r
+ HalPT[(KI_USER_SHARED_DATA - 0xFFC00000) >> MM_PAGE_SHIFT].Valid = 1;\r
+ HalPT[(KI_USER_SHARED_DATA - 0xFFC00000) >> MM_PAGE_SHIFT].Write = 1;\r
+\r
+ HalPT[(KIP0PCRADDRESS - 0xFFC00000) >> MM_PAGE_SHIFT].PageFrameNumber = PcrBasePage;\r
+ HalPT[(KIP0PCRADDRESS - 0xFFC00000) >> MM_PAGE_SHIFT].Valid = 1;\r
+ HalPT[(KIP0PCRADDRESS - 0xFFC00000) >> MM_PAGE_SHIFT].Write = 1;\r
+\r
+ // Map VGA memory\r
+ //VideoMemoryBase = MmMapIoSpace(0xb8000, 4000, MmNonCached);\r
+ //DbgPrint((DPRINT_WINDOWS, "VideoMemoryBase: 0x%X\n", VideoMemoryBase));\r
+\r
+ Tss = (PKTSS)(KSEG0_BASE | (TssBasePage << MM_PAGE_SHIFT));\r
+\r
+ // Unmap what is not needed from kernel page table\r
+ MempDisablePages();\r
+\r
+ // Fill the memory descriptor list and \r
+ //PrepareMemoryDescriptorList();\r
+ DbgPrint((DPRINT_WINDOWS, "Memory Descriptor List prepared, printing PDE\n"));\r
+ List_PaToVa(&LoaderBlock->MemoryDescriptorListHead);\r
+\r
+#ifdef DBG\r
+ {\r
+ ULONG *PDE_Addr=(ULONG *)PDE;//0xC0300000;\r
+ int j;\r
+\r
+ DbgPrint((DPRINT_WINDOWS, "\nPDE\n"));\r
+\r
+ for (i=0; i<128; i++)\r
+ {\r
+ DbgPrint((DPRINT_WINDOWS, "0x%04X | ", i*8));\r
+\r
+ for (j=0; j<8; j++)\r
+ {\r
+ DbgPrint((DPRINT_WINDOWS, "0x%08X ", PDE_Addr[i*8+j]));\r
+ }\r
+\r
+ DbgPrint((DPRINT_WINDOWS, "\n"));\r
+ }\r
+ }\r
+#endif\r
+\r
+\r
+ // Enable paging\r
+ //BS->ExitBootServices(ImageHandle,MapKey);\r
+\r
+ // Disable Interrupts\r
+ _disable();\r
+\r
+ // Re-initalize EFLAGS\r
+ Ke386EraseFlags();\r
+\r
+ // Set the PDBR\r
+ __writecr3((ULONG_PTR)PDE);\r
+\r
+ // Enable paging by modifying CR0\r
+ __writecr0(__readcr0() | CR0_PG);\r
+\r
+ // Set processor context\r
+ WinLdrSetProcessorContext(GdtIdt, KIP0PCRADDRESS, KSEG0_BASE | (TssBasePage << MM_PAGE_SHIFT));\r
+\r
+ // Zero KI_USER_SHARED_DATA page\r
+ memset((PVOID)KI_USER_SHARED_DATA, 0, MM_PAGE_SIZE);\r
+\r
+ return TRUE;\r
+}\r
+\r
+// Two special things this func does: it sorts descriptors,\r
+// and it merges free ones\r
+VOID\r
+WinLdrInsertDescriptor(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,\r
+ IN PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor)\r
+{\r
+ PLIST_ENTRY ListHead = &LoaderBlock->MemoryDescriptorListHead;\r
+ PLIST_ENTRY PreviousEntry, NextEntry;\r
+ PMEMORY_ALLOCATION_DESCRIPTOR PreviousDescriptor = NULL, NextDescriptor = NULL;\r
+\r
+ DbgPrint((DPRINT_WINDOWS, "BP=0x%X PC=0x%X %s\n", NewDescriptor->BasePage,\r
+ NewDescriptor->PageCount, MemTypeDesc[NewDescriptor->MemoryType]));\r
+\r
+ /* Find a place where to insert the new descriptor to */\r
+ PreviousEntry = ListHead;\r
+ NextEntry = ListHead->Flink;\r
+ while (NextEntry != ListHead)\r
+ {\r
+ NextDescriptor = CONTAINING_RECORD(NextEntry,\r
+ MEMORY_ALLOCATION_DESCRIPTOR,\r
+ ListEntry);\r
+ if (NewDescriptor->BasePage < NextDescriptor->BasePage)\r
+ break;\r
+\r
+ PreviousEntry = NextEntry;\r
+ PreviousDescriptor = NextDescriptor;\r
+ NextEntry = NextEntry->Flink;\r
+ }\r
+\r
+ /* Don't forget about merging free areas */\r
+ if (NewDescriptor->MemoryType != LoaderFree)\r
+ {\r
+ /* Just insert, nothing to merge */\r
+ InsertHeadList(PreviousEntry, &NewDescriptor->ListEntry);\r
+ }\r
+ else\r
+ {\r
+ /* Previous block also free? */\r
+ if ((PreviousEntry != ListHead) && (PreviousDescriptor->MemoryType == LoaderFree) &&\r
+ ((PreviousDescriptor->BasePage + PreviousDescriptor->PageCount) ==\r
+ NewDescriptor->BasePage))\r
+ {\r
+ /* Just enlarge previous descriptor's PageCount */\r
+ PreviousDescriptor->PageCount += NewDescriptor->PageCount;\r
+ NewDescriptor = PreviousDescriptor;\r
+ }\r
+ else\r
+ {\r
+ /* Nope, just insert */\r
+ InsertHeadList(PreviousEntry, &NewDescriptor->ListEntry);\r
+ }\r
+\r
+ /* Next block is free ?*/\r
+ if ((NextEntry != ListHead) &&\r
+ (NextDescriptor->MemoryType == LoaderFree) &&\r
+ ((NewDescriptor->BasePage + NewDescriptor->PageCount) == NextDescriptor->BasePage))\r
+ {\r
+ /* Enlarge next descriptor's PageCount */\r
+ NewDescriptor->PageCount += NextDescriptor->PageCount;\r
+ RemoveEntryList(&NextDescriptor->ListEntry);\r
+ }\r
+ }\r
+\r
+ return;\r
+}\r
+\r
+VOID\r
+WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss)\r
+{\r
+ GDTIDT GdtDesc, IdtDesc, OldIdt;\r
+ PKGDTENTRY pGdt;\r
+ PKIDTENTRY pIdt;\r
+ ULONG Ldt = 0;\r
+ //ULONG i;\r
+\r
+ DbgPrint((DPRINT_WINDOWS, "GDtIdt %p, Pcr %p, Tss 0x%08X\n",\r
+ GdtIdt, Pcr, Tss));\r
+\r
+ // Kernel expects the PCR to be zero-filled on startup\r
+ // FIXME: Why zero it here when we can zero it right after allocation?\r
+ RtlZeroMemory((PVOID)Pcr, MM_PAGE_SIZE); //FIXME: Why zero only 1 page when we allocate 2?\r
+\r
+ // Get old values of GDT and IDT\r
+ Ke386GetGlobalDescriptorTable(GdtDesc);\r
+ Ke386GetInterruptDescriptorTable(IdtDesc);\r
+\r
+ // Save old IDT\r
+ OldIdt.Base = IdtDesc.Base;\r
+ OldIdt.Limit = IdtDesc.Limit;\r
+\r
+ // Prepare new IDT+GDT\r
+ GdtDesc.Base = KSEG0_BASE | (ULONG_PTR)GdtIdt;\r
+ GdtDesc.Limit = NUM_GDT * sizeof(KGDTENTRY) - 1;\r
+ IdtDesc.Base = (ULONG)((PUCHAR)GdtDesc.Base + GdtDesc.Limit + 1);\r
+ IdtDesc.Limit = NUM_IDT * sizeof(KIDTENTRY) - 1;\r
+\r
+ // ========================\r
+ // Fill all descriptors now\r
+ // ========================\r
+\r
+ pGdt = (PKGDTENTRY)GdtDesc.Base;\r
+ pIdt = (PKIDTENTRY)IdtDesc.Base;\r
+\r
+ //\r
+ // Code selector (0x8)\r
+ // Flat 4Gb\r
+ //\r
+ pGdt[1].LimitLow = 0xFFFF;\r
+ pGdt[1].BaseLow = 0;\r
+ pGdt[1].HighWord.Bytes.BaseMid = 0;\r
+ pGdt[1].HighWord.Bytes.Flags1 = 0x9A;\r
+ pGdt[1].HighWord.Bytes.Flags2 = 0xCF;\r
+ pGdt[1].HighWord.Bytes.BaseHi = 0;\r
+\r
+ //\r
+ // Data selector (0x10)\r
+ // Flat 4Gb\r
+ //\r
+ pGdt[2].LimitLow = 0xFFFF;\r
+ pGdt[2].BaseLow = 0;\r
+ pGdt[2].HighWord.Bytes.BaseMid = 0;\r
+ pGdt[2].HighWord.Bytes.Flags1 = 0x92;\r
+ pGdt[2].HighWord.Bytes.Flags2 = 0xCF;\r
+ pGdt[2].HighWord.Bytes.BaseHi = 0;\r
+\r
+ //\r
+ // Selector (0x18)\r
+ // Flat 2Gb\r
+ //\r
+ pGdt[3].LimitLow = 0xFFFF;\r
+ pGdt[3].BaseLow = 0;\r
+ pGdt[3].HighWord.Bytes.BaseMid = 0;\r
+ pGdt[3].HighWord.Bytes.Flags1 = 0xFA;\r
+ pGdt[3].HighWord.Bytes.Flags2 = 0xCF;\r
+ pGdt[3].HighWord.Bytes.BaseHi = 0;\r
+\r
+ //\r
+ // Selector (0x20)\r
+ // Flat 2Gb\r
+ //\r
+ pGdt[4].LimitLow = 0xFFFF;\r
+ pGdt[4].BaseLow = 0;\r
+ pGdt[4].HighWord.Bytes.BaseMid = 0;\r
+ pGdt[4].HighWord.Bytes.Flags1 = 0xF2;\r
+ pGdt[4].HighWord.Bytes.Flags2 = 0xCF;\r
+ pGdt[4].HighWord.Bytes.BaseHi = 0;\r
+\r
+ //\r
+ // TSS Selector (0x28)\r
+ //\r
+ pGdt[5].LimitLow = 0x78-1; //FIXME: Check this\r
+ pGdt[5].BaseLow = (USHORT)(Tss & 0xffff);\r
+ pGdt[5].HighWord.Bytes.BaseMid = (UCHAR)((Tss >> 16) & 0xff);\r
+ pGdt[5].HighWord.Bytes.Flags1 = 0x89;\r
+ pGdt[5].HighWord.Bytes.Flags2 = 0x00;\r
+ pGdt[5].HighWord.Bytes.BaseHi = (UCHAR)((Tss >> 24) & 0xff);\r
+\r
+ //\r
+ // PCR Selector (0x30)\r
+ //\r
+ pGdt[6].LimitLow = 0x01;\r
+ pGdt[6].BaseLow = (USHORT)(Pcr & 0xffff);\r
+ pGdt[6].HighWord.Bytes.BaseMid = (UCHAR)((Pcr >> 16) & 0xff);\r
+ pGdt[6].HighWord.Bytes.Flags1 = 0x92;\r
+ pGdt[6].HighWord.Bytes.Flags2 = 0xC0;\r
+ pGdt[6].HighWord.Bytes.BaseHi = (UCHAR)((Pcr >> 24) & 0xff);\r
+\r
+ //\r
+ // Selector (0x38)\r
+ //\r
+ pGdt[7].LimitLow = 0xFFFF;\r
+ pGdt[7].BaseLow = 0;\r
+ pGdt[7].HighWord.Bytes.BaseMid = 0;\r
+ pGdt[7].HighWord.Bytes.Flags1 = 0xF3;\r
+ pGdt[7].HighWord.Bytes.Flags2 = 0x40;\r
+ pGdt[7].HighWord.Bytes.BaseHi = 0;\r
+\r
+ //\r
+ // Some BIOS fuck (0x40)\r
+ //\r
+ pGdt[8].LimitLow = 0xFFFF;\r
+ pGdt[8].BaseLow = 0x400;\r
+ pGdt[8].HighWord.Bytes.BaseMid = 0;\r
+ pGdt[8].HighWord.Bytes.Flags1 = 0xF2;\r
+ pGdt[8].HighWord.Bytes.Flags2 = 0x0;\r
+ pGdt[8].HighWord.Bytes.BaseHi = 0;\r
+\r
+ //\r
+ // Selector (0x48)\r
+ //\r
+ pGdt[9].LimitLow = 0;\r
+ pGdt[9].BaseLow = 0;\r
+ pGdt[9].HighWord.Bytes.BaseMid = 0;\r
+ pGdt[9].HighWord.Bytes.Flags1 = 0;\r
+ pGdt[9].HighWord.Bytes.Flags2 = 0;\r
+ pGdt[9].HighWord.Bytes.BaseHi = 0;\r
+\r
+ //\r
+ // Selector (0x50)\r
+ //\r
+ pGdt[10].LimitLow = 0xFFFF; //FIXME: Not correct!\r
+ pGdt[10].BaseLow = 0;\r
+ pGdt[10].HighWord.Bytes.BaseMid = 0x2;\r
+ pGdt[10].HighWord.Bytes.Flags1 = 0x89;\r
+ pGdt[10].HighWord.Bytes.Flags2 = 0;\r
+ pGdt[10].HighWord.Bytes.BaseHi = 0;\r
+\r
+ //\r
+ // Selector (0x58)\r
+ //\r
+ pGdt[11].LimitLow = 0xFFFF;\r
+ pGdt[11].BaseLow = 0;\r
+ pGdt[11].HighWord.Bytes.BaseMid = 0x2;\r
+ pGdt[11].HighWord.Bytes.Flags1 = 0x9A;\r
+ pGdt[11].HighWord.Bytes.Flags2 = 0;\r
+ pGdt[11].HighWord.Bytes.BaseHi = 0;\r
+\r
+ //\r
+ // Selector (0x60)\r
+ //\r
+ pGdt[12].LimitLow = 0xFFFF;\r
+ pGdt[12].BaseLow = 0; //FIXME: Maybe not correct, but noone cares\r
+ pGdt[12].HighWord.Bytes.BaseMid = 0x2;\r
+ pGdt[12].HighWord.Bytes.Flags1 = 0x92;\r
+ pGdt[12].HighWord.Bytes.Flags2 = 0;\r
+ pGdt[12].HighWord.Bytes.BaseHi = 0;\r
+\r
+ //\r
+ // Video buffer Selector (0x68)\r
+ //\r
+ pGdt[13].LimitLow = 0x3FFF;\r
+ pGdt[13].BaseLow = 0x8000; //FIXME: I guess not correct for UGA\r
+ pGdt[13].HighWord.Bytes.BaseMid = 0x0B;\r
+ pGdt[13].HighWord.Bytes.Flags1 = 0x92;\r
+ pGdt[13].HighWord.Bytes.Flags2 = 0;\r
+ pGdt[13].HighWord.Bytes.BaseHi = 0;\r
+\r
+ //\r
+ // Points to GDT (0x70)\r
+ //\r
+ pGdt[14].LimitLow = NUM_GDT*sizeof(KGDTENTRY) - 1;\r
+ pGdt[14].BaseLow = 0x7000;\r
+ pGdt[14].HighWord.Bytes.BaseMid = 0xFF;\r
+ pGdt[14].HighWord.Bytes.Flags1 = 0x92;\r
+ pGdt[14].HighWord.Bytes.Flags2 = 0;\r
+ pGdt[14].HighWord.Bytes.BaseHi = 0xFF;\r
+\r
+ //\r
+ // Some unused descriptors should go here\r
+ // ...\r
+\r
+ // Copy the old IDT\r
+ RtlCopyMemory(pIdt, (PVOID)OldIdt.Base, OldIdt.Limit);\r
+\r
+ // Mask interrupts\r
+ //asm("cli\n"); // they are already masked before enabling paged mode\r
+\r
+ // Load GDT+IDT\r
+ Ke386SetGlobalDescriptorTable(GdtDesc);\r
+ Ke386SetInterruptDescriptorTable(IdtDesc);\r
+\r
+ // Jump to proper CS and clear prefetch queue\r
+ asm("ljmp $0x08, $mb1\n"\r
+ "mb1:\n");\r
+\r
+ // Set SS selector\r
+ asm(".intel_syntax noprefix\n");\r
+ asm("mov ax, 0x10\n"); // DataSelector=0x10\r
+ asm("mov ss, ax\n");\r
+ asm(".att_syntax\n");\r
+\r
+ // Set DS and ES selectors\r
+ Ke386SetDs(0x10);\r
+ Ke386SetEs(0x10); // this is vital for rep stosd\r
+\r
+ // LDT = not used ever, thus set to 0\r
+ Ke386SetLocalDescriptorTable(Ldt);\r
+\r
+ // Load TSR\r
+ Ke386SetTr(0x28);\r
+\r
+ // Clear GS\r
+ asm(".intel_syntax noprefix\n");\r
+ asm("push 0\n");\r
+ asm("pop gs\n");\r
+ asm(".att_syntax\n");\r
+\r
+ // Set FS to PCR\r
+ Ke386SetFs(0x30);\r
+\r
+ // Real end of the function, just for information\r
+ /* do not uncomment!\r
+ pop edi;\r
+ pop esi;\r
+ pop ebx;\r
+ mov esp, ebp;\r
+ pop ebp;\r
+ ret\r
+ */\r
+}\r