Author: tkreuzer Date: Mon Oct 19 13:29:10 2009 New Revision: 43598
URL: http://svn.reactos.org/svn/reactos?rev=43598&view=rev Log: [FREELDR] - Split wlmemory into portable and arch specific code - Partly implement amd64 version, doesn't work correctly yet
Added: branches/ros-amd64-bringup/reactos/boot/freeldr/freeldr/windows/wlmemory.c - copied, changed from r43566, branches/ros-amd64-bringup/reactos/boot/freeldr/freeldr/windows/i386/wlmemory.c Modified: branches/ros-amd64-bringup/reactos/boot/freeldr/freeldr/freeldr_base.rbuild branches/ros-amd64-bringup/reactos/boot/freeldr/freeldr/windows/amd64/wlmemory.c branches/ros-amd64-bringup/reactos/boot/freeldr/freeldr/windows/i386/wlmemory.c
Modified: branches/ros-amd64-bringup/reactos/boot/freeldr/freeldr/freeldr_base.rbuild URL: http://svn.reactos.org/svn/reactos/branches/ros-amd64-bringup/reactos/boot/f... ============================================================================== --- branches/ros-amd64-bringup/reactos/boot/freeldr/freeldr/freeldr_base.rbuild [iso-8859-1] (original) +++ branches/ros-amd64-bringup/reactos/boot/freeldr/freeldr/freeldr_base.rbuild [iso-8859-1] Mon Oct 19 13:29:10 2009 @@ -73,6 +73,7 @@ <file>conversion.c</file> <file>peloader.c</file> <file>winldr.c</file> + <file>wlmemory.c</file> <file>wlregistry.c</file> </directory> </if> @@ -81,6 +82,7 @@ <file>conversion.c</file> <file>peloader.c</file> <file>winldr.c</file> + <file>wlmemory.c</file> <file>wlregistry.c</file> </directory> </if>
Modified: branches/ros-amd64-bringup/reactos/boot/freeldr/freeldr/windows/amd64/wlmemory.c URL: http://svn.reactos.org/svn/reactos/branches/ros-amd64-bringup/reactos/boot/f... ============================================================================== --- branches/ros-amd64-bringup/reactos/boot/freeldr/freeldr/windows/amd64/wlmemory.c [iso-8859-1] (original) +++ branches/ros-amd64-bringup/reactos/boot/freeldr/freeldr/windows/amd64/wlmemory.c [iso-8859-1] Mon Oct 19 13:29:10 2009 @@ -1,9 +1,9 @@ /* * PROJECT: EFI Windows Loader * LICENSE: GPL - See COPYING in the top level directory - * FILE: freeldr/winldr/wlmemory.c + * FILE: freeldr/amd64/wlmemory.c * PURPOSE: Memory related routines - * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org) + * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org) */
/* INCLUDES ***************************************************************/ @@ -13,60 +13,13 @@ #include <ndk/asm.h> #include <debug.h>
-extern ULONG TotalNLSSize; -extern ULONG LoaderPagesSpanned; +//extern ULONG LoaderPagesSpanned;
// 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) @@ -79,91 +32,284 @@
/* GLOBALS ***************************************************************/
-PHARDWARE_PTE PDE; -PHARDWARE_PTE HalPageTable; - -PUCHAR PhysicalPageTablesBuffer; -PUCHAR KernelPageTablesBuffer; -ULONG PhysicalPageTables; -ULONG KernelPageTables; - -MEMORY_ALLOCATION_DESCRIPTOR *Mad; -ULONG MadCount = 0; - +//PHARDWARE_PTE PDE; +//PHARDWARE_PTE HalPageTable; + +PPAGE_DIRECTORY_AMD64 pPML4;
/* FUNCTIONS **************************************************************/
BOOLEAN MempAllocatePageTables() { + ULONG KernelPages; + PVOID UserSharedData; + + DPRINTM(DPRINT_WINDOWS,">>> MempAllocatePageTables\n"); + + /* Allocate a page for the PML4 */ + pPML4 = MmAllocateMemoryWithType(PAGE_SIZE, LoaderMemoryData); + if (!pPML4) + { + DPRINTM(DPRINT_WINDOWS,"failed to allocate PML4\n"); + return FALSE; + } + + // FIXME: Physical PTEs = FirmwareTemporary ? + + /* Zero the PML4 */ + RtlZeroMemory(pPML4, PAGE_SIZE); + + /* The page tables are located at 0xfffff68000000000 + * We create a recursive self mapping through all 4 levels at + * virtual address 0xfffff6fb7dbedf68 */ + pPML4->Pde[VAtoPXI(PXE_BASE)].Valid = 1; + pPML4->Pde[VAtoPXI(PXE_BASE)].Write = 1; + pPML4->Pde[VAtoPXI(PXE_BASE)].PageFrameNumber = PtrToPfn(pPML4); + + // FIXME: map PDE's for hals memory mapping + + DPRINTM(DPRINT_WINDOWS,">>> leave MempAllocatePageTables\n");
return TRUE; }
-VOID -MempAllocatePTE(ULONG Entry, PHARDWARE_PTE *PhysicalPT, PHARDWARE_PTE *KernelPT) -{ - +PPAGE_DIRECTORY_AMD64 +MempGetOrCreatePageDir(PPAGE_DIRECTORY_AMD64 pDir, ULONG Index) +{ + PPAGE_DIRECTORY_AMD64 pSubDir; + + if (!pDir) + return NULL; + + if (!pDir->Pde[Index].Valid) + { + pSubDir = MmAllocateMemoryWithType(PAGE_SIZE, LoaderSpecialMemory); + if (!pSubDir) + return NULL; + RtlZeroMemory(pSubDir, PAGE_SIZE); + pDir->Pde[Index].PageFrameNumber = PtrToPfn(pSubDir); + pDir->Pde[Index].Valid = 1; + pDir->Pde[Index].Write = 1; + } + else + { + pSubDir = (PPAGE_DIRECTORY_AMD64)((ULONGLONG)(pDir->Pde[Index].PageFrameNumber) * PAGE_SIZE); + } + return pSubDir; +} + +BOOLEAN +MempMapSinglePage(ULONGLONG VirtualAddress, ULONGLONG PhysicalAddress) +{ + PPAGE_DIRECTORY_AMD64 pDir3, pDir2, pDir1; + ULONG Index; + + pDir3 = MempGetOrCreatePageDir(pPML4, VAtoPXI(VirtualAddress)); + pDir2 = MempGetOrCreatePageDir(pDir3, VAtoPPI(VirtualAddress)); + pDir1 = MempGetOrCreatePageDir(pDir2, VAtoPDI(VirtualAddress)); + + if (!pDir1) + return FALSE; + + Index = VAtoPTI(VirtualAddress); + if (pDir1->Pde[Index].Valid) + { + return FALSE; + } + + pDir1->Pde[Index].Valid = 1; + pDir1->Pde[Index].Write = 1; + pDir1->Pde[Index].PageFrameNumber = PhysicalAddress / PAGE_SIZE; + + return TRUE; +} + +ULONG +MempMapRangeOfPages(ULONGLONG VirtualAddress, ULONGLONG PhysicalAddress, ULONG cPages) +{ + ULONG i; + + for (i = 0; i < cPages; i++) + { + if (!FrLdrMapSinglePage(VirtualAddress, PhysicalAddress)) + { + return i; + } + VirtualAddress += PAGE_SIZE; + PhysicalAddress += PAGE_SIZE; + } + return i; }
BOOLEAN MempSetupPaging(IN ULONG StartPage, IN ULONG NumberOfPages) { + DPRINTM(DPRINT_WINDOWS,">>> MempSetupPaging(0x%lx, %ld)\n", StartPage, NumberOfPages); + + if (MempMapRangeOfPages(StartPage * PAGE_SIZE, + StartPage * PAGE_SIZE, + NumberOfPages) != NumberOfPages) + { + DPRINTM(DPRINT_WINDOWS,"Failed to map pages\n"); + return FALSE; + }
return TRUE; }
VOID -MempDisablePages() -{ - -} - -VOID -MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, - ULONG BasePage, - ULONG PageCount, - ULONG Type) -{ - -} - -#ifdef _M_IX86 +MempUnmapPage(ULONG Page) +{ + // DPRINTM(DPRINT_WINDOWS,">>> MempUnmapPage\n"); +} + VOID WinLdrpMapApic() { - -} -#else -VOID -WinLdrpMapApic() -{ - /* Implement it for another arch */ -} -#endif + BOOLEAN LocalAPIC; + LARGE_INTEGER MsrValue; + ULONG CpuInfo[4]; + ULONG64 APICAddress; + + DPRINTM(DPRINT_WINDOWS,">>> WinLdrpMapApic\n"); + + /* Check if we have a local APIC */ + __cpuid((int*)CpuInfo, 1); + LocalAPIC = (((CpuInfo[3] >> 9) & 1) != 0); + + /* If there is no APIC, just return */ + if (!LocalAPIC) + { + DPRINTM(DPRINT_WINDOWS,"No APIC found.\n"); + return; + } + + /* Read the APIC Address */ + MsrValue.QuadPart = __readmsr(0x1B); + APICAddress = (MsrValue.LowPart & 0xFFFFF000); + + DPRINTM(DPRINT_WINDOWS, "Local APIC detected at address 0x%x\n", + APICAddress); + + /* Map it */ + MempMapSinglePage(APIC_BASE, APICAddress); +}
BOOLEAN -WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, - ULONG PcrBasePage, - ULONG TssBasePage, - PVOID GdtIdt) -{ -return 1; -} - -// 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) -{ - -} - -VOID -WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss) -{ - -} - +WinLdrMapSpecialPages(ULONG PcrBasePage) +{ + /* Map the PCR page */ + if (!MempMapSinglePage(PcrBasePage * PAGE_SIZE, KIP0PCRADDRESS)) + { + DPRINTM(DPRINT_WINDOWS, "Could not map PCR @ %lx\n", PcrBasePage); + return FALSE; + } + + /* Map KI_USER_SHARED_DATA */ + if (!MempMapSinglePage((PcrBasePage+1) * PAGE_SIZE, KI_USER_SHARED_DATA)) + { + DPRINTM(DPRINT_WINDOWS, "Could not map KI_USER_SHARED_DATA\n"); + return FALSE; + } + + /* Map the APIC page */ + WinLdrpMapApic(); + + return TRUE; +} + +VOID +WinLdrSetupGdt(PVOID GdtBase, ULONG64 TssBase) +{ + PKGDTENTRY64 Entry; + KDESCRIPTOR GdtDesc; + + /* Setup KGDT_64_R0_CODE */ + Entry = KiGetGdtEntry(GdtBase, KGDT_64_R0_CODE); + *(PULONG64)Entry = 0x00209b0000000000ULL; + + /* Setup KGDT_64_R0_SS */ + Entry = KiGetGdtEntry(GdtBase, KGDT_64_R0_SS); + *(PULONG64)Entry = 0x00cf93000000ffffULL; + + /* Setup KGDT_64_DATA */ + Entry = KiGetGdtEntry(GdtBase, KGDT_64_DATA); + *(PULONG64)Entry = 0x00cff3000000ffffULL; + + /* Setup KGDT_64_R3_CODE */ + Entry = KiGetGdtEntry(GdtBase, KGDT_64_R3_CODE); + *(PULONG64)Entry = 0x0020fb0000000000ULL; + + /* Setup KGDT_32_R3_TEB */ + Entry = KiGetGdtEntry(GdtBase, KGDT_32_R3_TEB); + *(PULONG64)Entry = 0xff40f3fd50003c00ULL; + + /* Setup TSS entry */ + Entry = KiGetGdtEntry(GdtBase, KGDT_TSS); + KiInitGdtEntry(Entry, TssBase, sizeof(KTSS), I386_TSS, 0); + + /* Setup GDT descriptor */ + GdtDesc.Base = GdtBase; + GdtDesc.Limit = NUM_GDT * sizeof(KGDTENTRY) - 1; + + /* Set the new Gdt */ + __lgdt(&GdtDesc.Limit); + DbgPrint("Gdtr.Base = %p, num = %ld\n", GdtDesc.Base, NUM_GDT); + +} + +VOID +WinLdrSetupIdt(PVOID IdtBase) +{ + KDESCRIPTOR IdtDesc, OldIdt; + + /* Get old IDT */ + __sidt(&OldIdt); + + /* Copy the old IDT */ + RtlCopyMemory(IdtBase, (PVOID)OldIdt.Base, OldIdt.Limit + 1); + + /* Setup the new IDT descriptor */ + IdtDesc.Base = IdtBase; + IdtDesc.Limit = NUM_IDT * sizeof(KIDTENTRY) - 1; + + /* Set the new IDT */ + __lidt(&IdtDesc.Limit); + DbgPrint("Idtr.Base = %p\n", IdtDesc.Base); + +} + +VOID +WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG64 Pcr, IN ULONG64 Tss) +{ + /* Disable Interrupts */ + _disable(); + + /* Re-initalize EFLAGS */ + __writeeflags(0); + + /* Set the new PML4 */ + __writecr3((ULONGLONG)pPML4); + + // Enable paging by modifying CR0 + __writecr0(__readcr0() | CR0_PG); + + // 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? + + RtlZeroMemory(GdtIdt, PAGE_SIZE); + + WinLdrSetupGdt(GdtIdt, Tss); + + WinLdrSetupIdt(GdtIdt); + +} + +VOID +MempDump() +{ +} +
Modified: branches/ros-amd64-bringup/reactos/boot/freeldr/freeldr/windows/i386/wlmemory.c URL: http://svn.reactos.org/svn/reactos/branches/ros-amd64-bringup/reactos/boot/f... ============================================================================== --- branches/ros-amd64-bringup/reactos/boot/freeldr/freeldr/windows/i386/wlmemory.c [iso-8859-1] (original) +++ branches/ros-amd64-bringup/reactos/boot/freeldr/freeldr/windows/i386/wlmemory.c [iso-8859-1] Mon Oct 19 13:29:10 2009 @@ -1,7 +1,7 @@ /* * PROJECT: EFI Windows Loader * LICENSE: GPL - See COPYING in the top level directory - * FILE: freeldr/winldr/wlmemory.c + * FILE: freeldr/winldr/i386/wlmemory.c * PURPOSE: Memory related routines * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org) */ @@ -21,52 +21,6 @@ #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) @@ -86,10 +40,6 @@ PUCHAR KernelPageTablesBuffer; ULONG PhysicalPageTables; ULONG KernelPageTables; - -MEMORY_ALLOCATION_DESCRIPTOR *Mad; -ULONG MadCount = 0; -
/* FUNCTIONS **************************************************************/
@@ -253,133 +203,24 @@ }
VOID -MempDisablePages() -{ - ULONG 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 <= LoaderPagesSpanned) || - 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 LoaderPagesSpanned - if (Mad[i].MemoryType == LoaderFirmwarePermanent || - Mad[i].MemoryType == LoaderSpecialMemory) - { - if (StartPage < 0x100) - StartPage = 0x100; - - if (EndPage > LoaderPagesSpanned) - EndPage = LoaderPagesSpanned; - } - - 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 > LoaderPagesSpanned) - { - if (Mad[MadCount].MemoryType != LoaderSpecialMemory && - Mad[MadCount].MemoryType != LoaderFirmwarePermanent && - Mad[MadCount].MemoryType != LoaderFree) - { - DPRINTM(DPRINT_WINDOWS, "Setting page %x %x to Temporary from %d\n", - BasePage, PageCount, Mad[MadCount].MemoryType); - 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) - { - DPRINTM(DPRINT_WINDOWS, "Error during MempSetupPaging\n"); - return; - } - } -} - -#ifdef _M_IX86 +MempUnmapPage(ULONG 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 WinLdrpMapApic() { @@ -410,149 +251,10 @@ HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].WriteThrough = 1; HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].CacheDisable = 1; } -#else -VOID -WinLdrpMapApic() -{ - /* Implement it for another arch */ -} -#endif
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 (?? why?) - // - - // - // 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; - - // Allocate memory for memory allocation descriptors - Mad = MmHeapAlloc(sizeof(MEMORY_ALLOCATION_DESCRIPTOR) * 1024); - - // 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); - - DPRINTM(DPRINT_WINDOWS, "Got memory map with %d entries\n", NoEntries); - - // Always contigiously map low 1Mb of memory - Status = MempSetupPaging(0, 0x100); - if (!Status) - { - DPRINTM(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 - - DPRINTM(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; - }*/ +WinLdrMapSpecialPages(ULONG PcrBasePage) +{
//VideoDisplayString(L"Hello from VGA, going into the kernel\n"); DPRINTM(DPRINT_WINDOWS, "HalPageTable: 0x%X\n", HalPageTable); @@ -574,127 +276,9 @@ //VideoMemoryBase = MmMapIoSpace(0xb8000, 4000, MmNonCached); //DPRINTM(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(); - DPRINTM(DPRINT_WINDOWS, "Memory Descriptor List prepared, printing PDE\n"); - List_PaToVa(&LoaderBlock->MemoryDescriptorListHead); - -#if DBG - { - ULONG *PDE_Addr=(ULONG *)PDE;//0xC0300000; - int j; - - DPRINTM(DPRINT_WINDOWS, "\nPDE\n"); - - for (i=0; i<128; i++) - { - DPRINTM(DPRINT_WINDOWS, "0x%04X | ", i*8); - - for (j=0; j<8; j++) - { - DPRINTM(DPRINT_WINDOWS, "0x%08X ", PDE_Addr[i*8+j]); - } - - DPRINTM(DPRINT_WINDOWS, "\n"); - } - } -#endif - - - // Enable paging - //BS->ExitBootServices(ImageHandle,MapKey); - - // Disable Interrupts - _disable(); - - // Re-initalize EFLAGS - __writeeflags(0); - - // 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; - - DPRINTM(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; -} + return TRUE; +} +
VOID WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss) @@ -707,6 +291,21 @@
DPRINTM(DPRINT_WINDOWS, "GDtIdt %p, Pcr %p, Tss 0x%08X\n", GdtIdt, Pcr, Tss); + + // Enable paging + //BS->ExitBootServices(ImageHandle,MapKey); + + // Disable Interrupts + _disable(); + + // Re-initalize EFLAGS + __writeeflags(0); + + // Set the PDBR + __writecr3((ULONG_PTR)PDE); + + // Enable paging by modifying CR0 + __writecr0(__readcr0() | CR0_PG);
// Kernel expects the PCR to be zero-filled on startup // FIXME: Why zero it here when we can zero it right after allocation? @@ -937,3 +536,25 @@ ret */ } + +VOID +MempDump() +{ + ULONG *PDE_Addr=(ULONG *)PDE;//0xC0300000; + int j; + + DPRINTM(DPRINT_WINDOWS, "\nPDE\n"); + + for (i=0; i<128; i++) + { + DPRINTM(DPRINT_WINDOWS, "0x%04X | ", i*8); + + for (j=0; j<8; j++) + { + DPRINTM(DPRINT_WINDOWS, "0x%08X ", PDE_Addr[i*8+j]); + } + + DPRINTM(DPRINT_WINDOWS, "\n"); + } +} +
Copied: branches/ros-amd64-bringup/reactos/boot/freeldr/freeldr/windows/wlmemory.c (from r43566, branches/ros-amd64-bringup/reactos/boot/freeldr/freeldr/windows/i386/wlmemory.c) URL: http://svn.reactos.org/svn/reactos/branches/ros-amd64-bringup/reactos/boot/f... ============================================================================== --- branches/ros-amd64-bringup/reactos/boot/freeldr/freeldr/windows/i386/wlmemory.c [iso-8859-1] (original) +++ branches/ros-amd64-bringup/reactos/boot/freeldr/freeldr/windows/wlmemory.c [iso-8859-1] Mon Oct 19 13:29:10 2009 @@ -13,14 +13,11 @@ #include <ndk/asm.h> #include <debug.h>
-extern ULONG TotalNLSSize; extern ULONG LoaderPagesSpanned;
// This is needed because headers define wrong one for ReactOS #undef KIP0PCRADDRESS #define KIP0PCRADDRESS 0xffdff000 - -#define HYPER_SPACE_ENTRY 0x300
PCHAR MemTypeDesc[] = { "ExceptionBlock ", // ? @@ -68,189 +65,28 @@ 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) +BOOLEAN +MempAllocatePageTables(); + +BOOLEAN +MempSetupPaging(IN ULONG StartPage, + IN ULONG NumberOfPages); + +BOOLEAN +WinLdrMapSpecialPages(ULONG PcrBasePage); + +VOID +MempUnmapPage(ULONG Page); + +VOID +MempDump();
/* GLOBALS ***************************************************************/ - -PHARDWARE_PTE PDE; -PHARDWARE_PTE HalPageTable; - -PUCHAR PhysicalPageTablesBuffer; -PUCHAR KernelPageTablesBuffer; -ULONG PhysicalPageTables; -ULONG KernelPageTables;
MEMORY_ALLOCATION_DESCRIPTOR *Mad; 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; - - DPRINTM(DPRINT_WINDOWS, "NumPageTables = %d\n", NumPageTables); - - // Allocate memory block for all these things: - // PDE, HAL mapping page table, physical mapping, kernel mapping - TotalSize = (1+1+NumPageTables*2)*MM_PAGE_SIZE; - - // PDE+HAL+KernelPTEs == MemoryData - Buffer = MmAllocateMemoryWithType(TotalSize, LoaderMemoryData); - - // Physical PTEs = FirmwareTemporary - PhysicalPageTablesBuffer = (PUCHAR)Buffer + TotalSize - NumPageTables*MM_PAGE_SIZE; - MmSetMemoryType(PhysicalPageTablesBuffer, - NumPageTables*MM_PAGE_SIZE, - LoaderFirmwareTemporary); - - // This check is now redundant - if (Buffer + (TotalSize - NumPageTables*MM_PAGE_SIZE) != - PhysicalPageTablesBuffer) - { - DPRINTM(DPRINT_WINDOWS, "There was a problem allocating two adjacent blocks of memory!"); - } - - if (Buffer == NULL || PhysicalPageTablesBuffer == 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) - HalPageTable = (PHARDWARE_PTE)&Buffer[MM_PAGE_SIZE*1]; - - // Map it - PDE[1023].PageFrameNumber = (ULONG)HalPageTable >> MM_PAGE_SHIFT; - PDE[1023].Valid = 1; - PDE[1023].Write = 1; - - // Store pointer to the table for easier access - KernelPageTablesBuffer = &Buffer[MM_PAGE_SIZE*2]; - - // 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) - { - DPRINTM(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() @@ -292,20 +128,7 @@
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; - } - } + MempUnmapPage(Page); } } } @@ -378,45 +201,6 @@ } } } - -#ifdef _M_IX86 -VOID -WinLdrpMapApic() -{ - BOOLEAN LocalAPIC; - LARGE_INTEGER MsrValue; - ULONG APICAddress, CpuInfo[4]; - - /* Check if we have a local APIC */ - __cpuid((int*)CpuInfo, 1); - LocalAPIC = (((CpuInfo[3] >> 9) & 1) != 0); - - /* If there is no APIC, just return */ - if (!LocalAPIC) - return; - - /* Read the APIC Address */ - MsrValue.QuadPart = __readmsr(0x1B); - APICAddress = (MsrValue.LowPart & 0xFFFFF000); - - DPRINTM(DPRINT_WINDOWS, "Local APIC detected at address 0x%x\n", - APICAddress); - - /* Map it */ - HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].PageFrameNumber - = APICAddress >> MM_PAGE_SHIFT; - HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].Valid = 1; - HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].Write = 1; - HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].WriteThrough = 1; - HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].CacheDisable = 1; -} -#else -VOID -WinLdrpMapApic() -{ - /* Implement it for another arch */ -} -#endif
BOOLEAN WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, @@ -554,25 +338,8 @@ return; }*/
- //VideoDisplayString(L"Hello from VGA, going into the kernel\n"); - DPRINTM(DPRINT_WINDOWS, "HalPageTable: 0x%X\n", HalPageTable); - - // Page Tables have been setup, make special handling for PCR and TSS - // (which is done in BlSetupFotNt in usual ntldr) - HalPageTable[(KI_USER_SHARED_DATA - 0xFFC00000) >> MM_PAGE_SHIFT].PageFrameNumber = PcrBasePage+1; - HalPageTable[(KI_USER_SHARED_DATA - 0xFFC00000) >> MM_PAGE_SHIFT].Valid = 1; - HalPageTable[(KI_USER_SHARED_DATA - 0xFFC00000) >> MM_PAGE_SHIFT].Write = 1; - - HalPageTable[(KIP0PCRADDRESS - 0xFFC00000) >> MM_PAGE_SHIFT].PageFrameNumber = PcrBasePage; - HalPageTable[(KIP0PCRADDRESS - 0xFFC00000) >> MM_PAGE_SHIFT].Valid = 1; - HalPageTable[(KIP0PCRADDRESS - 0xFFC00000) >> MM_PAGE_SHIFT].Write = 1; - - // Map APIC - WinLdrpMapApic(); - - // Map VGA memory - //VideoMemoryBase = MmMapIoSpace(0xb8000, 4000, MmNonCached); - //DPRINTM(DPRINT_WINDOWS, "VideoMemoryBase: 0x%X\n", VideoMemoryBase); + /* Map stuff like PCR, KI_USER_SHARED_DATA and Apic */ + WinLdrMapSpecialPages(PcrBasePage);
Tss = (PKTSS)(KSEG0_BASE | (TssBasePage << MM_PAGE_SHIFT));
@@ -585,41 +352,8 @@ List_PaToVa(&LoaderBlock->MemoryDescriptorListHead);
#if DBG - { - ULONG *PDE_Addr=(ULONG *)PDE;//0xC0300000; - int j; - - DPRINTM(DPRINT_WINDOWS, "\nPDE\n"); - - for (i=0; i<128; i++) - { - DPRINTM(DPRINT_WINDOWS, "0x%04X | ", i*8); - - for (j=0; j<8; j++) - { - DPRINTM(DPRINT_WINDOWS, "0x%08X ", PDE_Addr[i*8+j]); - } - - DPRINTM(DPRINT_WINDOWS, "\n"); - } - } + MempDump(); #endif - - - // Enable paging - //BS->ExitBootServices(ImageHandle,MapKey); - - // Disable Interrupts - _disable(); - - // Re-initalize EFLAGS - __writeeflags(0); - - // 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)); @@ -696,244 +430,3 @@ return; }
-VOID -WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss) -{ - GDTIDT GdtDesc, IdtDesc, OldIdt; - PKGDTENTRY pGdt; - PKIDTENTRY pIdt; - ULONG Ldt = 0; - //ULONG i; - - DPRINTM(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); - __sidt(&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 stuff (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; - 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 + 1); - - // Mask interrupts - //asm("cli\n"); // they are already masked before enabling paged mode - - // Load GDT+IDT - Ke386SetGlobalDescriptorTable(&GdtDesc); - __lidt(&IdtDesc); - - // Jump to proper CS and clear prefetch queue -#if defined(__GNUC__) - asm("ljmp $0x08, $1f\n" - "1:\n"); -#elif defined(_MSC_VER) - /* We can't express the above in MASM so we use this far return instead */ - DbgPrint("WinLdrSetProcessorContext: Performing untested far-return\n"); - __asm { - push 8 - push offset resume - retf - resume: - }; -#else -#error -#endif - - // Set SS selector - Ke386SetSs(0x10); // DataSelector=0x10 - - // 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(KGDT_TSS); - - // Clear GS - Ke386SetGs(0); - - // 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 - */ -}