#undef KIP0PCRADDRESS\r
#define KIP0PCRADDRESS 0xffdff000\r
\r
+//\r
+// This is the zone which is used by the OS loader\r
+//\r
+#define LOADER_HIGH_ZONE ((16*1024*1024) >> MM_PAGE_SHIFT) //16Mb page\r
+\r
#define HYPER_SPACE_ENTRY 0x300\r
\r
+//TODO: Check if this is correct\r
+PCHAR MemTypeDesc[] = {\r
+ "ExceptionBlock ",\r
+ "SystemBlock ",\r
+ "Free ",\r
+ "Bad ",\r
+ "LoadedProgram ",\r
+ "FirmwareTemporary ",\r
+ "FirmwarePermanent ",\r
+ "OsloaderHeap ",\r
+ "OsloaderStack ",\r
+ "SystemCode ",\r
+ "HalCode ",\r
+ "BootDriver ",\r
+ "ConsoleInDriver ",\r
+ "ConsoleOutDriver ",\r
+ "StartupDpcStack ",\r
+ "StartupKernelStack",\r
+ "StartupPanicStack ",\r
+ "StartupPcrPage ",\r
+ "StartupPdrPage ",\r
+ "RegistryData ",\r
+ "MemoryData ",\r
+ "NlsData ",\r
+ "SpecialMemory ",\r
+ "BBTMemory ",\r
+ "Maximum "\r
+ };\r
+\r
+VOID\r
+WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock);\r
+\r
+\r
+VOID\r
+MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,\r
+ UINT64 BasePage,\r
+ UINT64 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[1024];\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
+ TotalSize = (1+1+NumPageTables*2)*MM_PAGE_SIZE;\r
+ Buffer = MmAllocateMemory(TotalSize);\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
+ // 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
+MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,\r
+ UINT64 BasePage,\r
+ UINT64 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
+ // Base page and page count are always set\r
+ //\r
+ Mad[MadCount].BasePage = BasePage;\r
+ Mad[MadCount].PageCount = PageCount;\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
+ Mad[MadCount].MemoryType = LoaderFirmwareTemporary;\r
+\r
+ WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);\r
+ MadCount++;\r
+\r
+ Status = MempSetupPaging(BasePage, PageCount);\r
+ if (!Status)\r
+ {\r
+ DbgPrint((DPRINT_WINDOWS, "Error during WinLdrpSetupPaging\n"));\r
+ return;\r
+ }\r
+ return;\r
+ }\r
+ \r
+ if (BasePage == 0xFFF && PageCount == 1)\r
+ {\r
+ Mad[MadCount].MemoryType = LoaderSpecialMemory;\r
+\r
+ WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);\r
+ MadCount++;\r
+\r
+ //\r
+ // Map it\r
+ //\r
+ Status = MempSetupPaging(BasePage, PageCount);\r
+ if (!Status)\r
+ {\r
+ DbgPrint((DPRINT_WINDOWS, "Error during MempSetupPaging\n"));\r
+ return;\r
+ }\r
+ }\r
+ else if (BasePage == 0 && PageCount == 1)\r
+ {\r
+ Mad[MadCount].MemoryType = LoaderFirmwarePermanent;\r
+\r
+ WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);\r
+ MadCount++;\r
+\r
+ //\r
+ // Map it\r
+ //\r
+ Status = MempSetupPaging(BasePage, PageCount);\r
+ if (!Status)\r
+ {\r
+ DbgPrint((DPRINT_WINDOWS, "Error during MempSetupPaging\n"));\r
+ return;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ //\r
+ // Now choose memory type as usual. FIXME!!!\r
+ //\r
+ if (Type == 0)\r
+ {\r
+ Mad[MadCount].MemoryType = LoaderFree;\r
+ }\r
+ else if (Type != 0 && Type != 1)\r
+ {\r
+ Mad[MadCount].MemoryType = LoaderFirmwarePermanent;\r
+ }\r
+ else if (Type == 1)\r
+ {\r
+ Mad[MadCount].MemoryType = LoaderSystemCode;\r
+ }\r
+ else\r
+ {\r
+ Mad[MadCount].MemoryType = LoaderFirmwarePermanent;\r
+ }\r
+\r
+ //\r
+ // Add descriptor\r
+ //\r
+ WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);\r
+ MadCount++;\r
+\r
+ //\r
+ // Map it\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
- return FALSE;\r
+ ULONG i, PagesCount;\r
+ ULONG LastPageIndex, LastPageType;\r
+ PPAGE_LOOKUP_TABLE_ITEM MemoryMap;\r
+ ULONG NoEntries;\r
+ PKTSS Tss;\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
+ // 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
+ DbgPrint((DPRINT_WINDOWS, "Got memory map with %d entries\n"));\r
+\r
+ // Construct a good memory map from what we've got\r
+ PagesCount = 1;\r
+ LastPageIndex = 0;\r
+ LastPageType = MemoryMap[0].PageAllocated;\r
+ for(i=1;i<NoEntries;i++)\r
+ {\r
+ if (MemoryMap[i].PageAllocated == LastPageType)\r
+ {\r
+ PagesCount++;\r
+ }\r
+ else\r
+ {\r
+ // Add the 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
+ 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
+ // 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
+ {\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
+\r
+\r
+ // Enable paging\r
+ //BS->ExitBootServices(ImageHandle,MapKey);\r
+\r
+ // Disable Interrupts\r
+ Ke386DisableInterrupts();\r
+\r
+ // Re-initalize EFLAGS\r
+ Ke386EraseFlags();\r
+\r
+ // Set the PDBR\r
+ Ke386SetPageTableDirectory((ULONG_PTR)PDE);\r
+\r
+ // Enable paging by modifying CR0\r
+ Ke386SetCr0(Ke386GetCr0() | 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; // 60 dwords\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
+ //\r
+ // Fill IDT with Traps\r
+ //\r
+#if 0\r
+ pIdt[0].Offset = (i386DivideByZero | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[0].ExtendedOffset = 0x8; // Selector\r
+ pIdt[0].Access = 0x8F00;\r
+ pIdt[0].Selector = (i386DivideByZero | KSEG0_BASE) >> 16; // Extended Offset\r
+\r
+ pIdt[1].Offset = (i386DebugException | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[1].ExtendedOffset = 0x8; // Selector\r
+ pIdt[1].Access = 0x8F00;\r
+ pIdt[1].Selector = (i386DebugException | KSEG0_BASE) >> 16; // Extended Offset\r
+\r
+ pIdt[2].Offset = (i386NMIException | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[2].ExtendedOffset = 0x8; // Selector\r
+ pIdt[2].Access = 0x8F00;\r
+ pIdt[2].Selector = (i386NMIException | KSEG0_BASE) >> 16; // Extended Offset\r
+\r
+ pIdt[3].Offset = (i386Breakpoint | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[3].ExtendedOffset = 0x8; // Selector\r
+ pIdt[3].Access = 0x8F00;\r
+ pIdt[3].Selector = (i386Breakpoint | KSEG0_BASE) >> 16; // Extended Offset\r
+\r
+ pIdt[4].Offset = (i386Overflow | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[4].ExtendedOffset = 0x8; // Selector\r
+ pIdt[4].Access = 0x8F00;\r
+ pIdt[4].Selector = (i386Overflow | KSEG0_BASE) >> 16; // Extended Offset\r
+\r
+ pIdt[5].Selector = (i386BoundException | KSEG0_BASE) >> 16; // Extended Offset\r
+ pIdt[5].Offset = (i386BoundException | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[5].ExtendedOffset = 0x8; // Selector\r
+ pIdt[5].Access = 0x8F00;\r
+\r
+ pIdt[6].Selector = (i386InvalidOpcode | KSEG0_BASE) >> 16; // Extended Offset\r
+ pIdt[6].Offset = (i386InvalidOpcode | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[6].ExtendedOffset = 0x8; // Selector\r
+ pIdt[6].Access = 0x8F00;\r
+\r
+ pIdt[7].Selector = (i386FPUNotAvailable | KSEG0_BASE) >> 16; // Extended Offset\r
+ pIdt[7].Offset = (i386FPUNotAvailable | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[7].ExtendedOffset = 0x8; // Selector\r
+ pIdt[7].Access = 0x8F00;\r
+\r
+ pIdt[8].Selector = (i386DoubleFault | KSEG0_BASE) >> 16; // Extended Offset\r
+ pIdt[8].Offset = (i386DoubleFault | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[8].ExtendedOffset = 0x8; // Selector\r
+ pIdt[8].Access = 0x8F00;\r
+\r
+ pIdt[9].Selector = (i386CoprocessorSegment | KSEG0_BASE) >> 16; // Extended Offset\r
+ pIdt[9].Offset = (i386CoprocessorSegment | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[9].ExtendedOffset = 0x8; // Selector\r
+ pIdt[9].Access = 0x8F00;\r
+\r
+ pIdt[10].Selector = (i386InvalidTSS | KSEG0_BASE) >> 16; // Extended Offset\r
+ pIdt[10].Offset = (i386InvalidTSS | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[10].ExtendedOffset = 0x8; // Selector\r
+ pIdt[10].Access = 0x8F00;\r
+\r
+ pIdt[11].Selector = (i386SegmentNotPresent | KSEG0_BASE) >> 16; // Extended Offset\r
+ pIdt[11].Offset = (i386SegmentNotPresent | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[11].ExtendedOffset = 0x8; // Selector\r
+ pIdt[11].Access = 0x8F00;\r
+\r
+ pIdt[12].Selector = (i386StackException | KSEG0_BASE) >> 16; // Extended Offset\r
+ pIdt[12].Offset = (i386StackException | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[12].ExtendedOffset = 0x8; // Selector\r
+ pIdt[12].Access = 0x8F00;\r
+\r
+ pIdt[13].Selector = (i386GeneralProtectionFault | KSEG0_BASE) >> 16; // Extended Offset\r
+ pIdt[13].Offset = (i386GeneralProtectionFault | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[13].ExtendedOffset = 0x8; // Selector\r
+ pIdt[13].Access = 0x8F00;\r
+\r
+ pIdt[14].Selector = (i386PageFault | KSEG0_BASE) >> 16; // Extended Offset\r
+ pIdt[14].Offset = (i386PageFault | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[14].ExtendedOffset = 0x8; // Selector\r
+ pIdt[14].Access = 0x8F00;\r
+\r
+ pIdt[15].Selector = 0; // Extended Offset\r
+ pIdt[15].Offset = 0;\r
+ pIdt[15].ExtendedOffset = 0; // Selector\r
+ pIdt[15].Access = 0;\r
+\r
+ pIdt[16].Selector = (i386CoprocessorError | KSEG0_BASE) >> 16; // Extended Offset\r
+ pIdt[16].Offset = (i386CoprocessorError | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[16].ExtendedOffset = 0x8; // Selector\r
+ pIdt[16].Access = 0x8F00;\r
+\r
+ pIdt[17].Selector = (i386AlignmentCheck | KSEG0_BASE) >> 16; // Extended Offset\r
+ pIdt[17].Offset = (i386AlignmentCheck | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[17].ExtendedOffset = 0x8; // Selector\r
+ pIdt[17].Access = 0x8F00;\r
+#endif\r
+\r
+ /*for (i=0; i<16; i++)\r
+ {\r
+ //pIdt[i].Offset = ((ULONG_PTR)i386GeneralProtectionFault | KSEG0_BASE) & 0xFFFF;\r
+ //pIdt[i].ExtendedOffset = 0x8; // Selector\r
+ //pIdt[i].Access = 0x8F00;\r
+ //pIdt[i].Selector = ((ULONG_PTR)i386GeneralProtectionFault | KSEG0_BASE) >> 16; // Extended Offset\r
+\r
+ pIdt[i].Offset = ((ULONG_PTR)i386GeneralProtectionFault | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[i].ExtendedOffset = ((ULONG_PTR)i386GeneralProtectionFault | KSEG0_BASE) >> 16; // Extended Offset\r
+ pIdt[i].Access = 0x8F00;\r
+ pIdt[i].Selector = 0x8;\r
+ }*/\r
+\r
+ // Copy the old IDT\r
+ RtlCopyMemory(pIdt, (PVOID)OldIdt.Base, OldIdt.Limit);\r
+\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