ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

winldr.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         EFI Windows Loader
00003  * LICENSE:         GPL - See COPYING in the top level directory
00004  * FILE:            freeldr/amd64/wlmemory.c
00005  * PURPOSE:         Memory related routines
00006  * PROGRAMMERS:     Timo Kreuzer (timo.kreuzer@reactos.org)
00007  */
00008 
00009 /* INCLUDES ***************************************************************/
00010 
00011 #include <freeldr.h>
00012 
00013 #include <ndk/asm.h>
00014 #include <debug.h>
00015 
00016 //extern ULONG LoaderPagesSpanned;
00017 
00018 #define HYPER_SPACE_ENTRY       0x1EE
00019 
00020 DBG_DEFAULT_CHANNEL(WINDOWS);
00021 
00022 /* GLOBALS ***************************************************************/
00023 
00024 PHARDWARE_PTE PxeBase;
00025 //PHARDWARE_PTE HalPageTable;
00026 
00027 PVOID GdtIdt;
00028 ULONG_PTR PcrBasePage;
00029 ULONG_PTR TssBasePage;
00030 
00031 /* FUNCTIONS **************************************************************/
00032 
00033 BOOLEAN
00034 MempAllocatePageTables()
00035 {
00036     TRACE(">>> MempAllocatePageTables\n");
00037 
00038     /* Allocate a page for the PML4 */
00039     PxeBase = MmAllocateMemoryWithType(PAGE_SIZE, LoaderMemoryData);
00040     if (!PxeBase)
00041     {
00042         ERR("failed to allocate PML4\n");
00043         return FALSE;
00044     }
00045 
00046     // FIXME: Physical PTEs = FirmwareTemporary ?
00047 
00048     /* Zero the PML4 */
00049     RtlZeroMemory(PxeBase, PAGE_SIZE);
00050 
00051     /* The page tables are located at 0xfffff68000000000
00052      * We create a recursive self mapping through all 4 levels at
00053      * virtual address 0xfffff6fb7dbedf68 */
00054     PxeBase[VAtoPXI(PXE_BASE)].Valid = 1;
00055     PxeBase[VAtoPXI(PXE_BASE)].Write = 1;
00056     PxeBase[VAtoPXI(PXE_BASE)].PageFrameNumber = PtrToPfn(PxeBase);
00057 
00058     // FIXME: map PDE's for hals memory mapping
00059 
00060     TRACE(">>> leave MempAllocatePageTables\n");
00061 
00062     return TRUE;
00063 }
00064 
00065 PHARDWARE_PTE
00066 MempGetOrCreatePageDir(PHARDWARE_PTE PdeBase, ULONG Index)
00067 {
00068     PHARDWARE_PTE SubDir;
00069 
00070     if (!PdeBase)
00071         return NULL;
00072 
00073     if (!PdeBase[Index].Valid)
00074     {
00075         SubDir = MmAllocateMemoryWithType(PAGE_SIZE, LoaderMemoryData);
00076         if (!SubDir)
00077             return NULL;
00078         RtlZeroMemory(SubDir, PAGE_SIZE);
00079         PdeBase[Index].PageFrameNumber = PtrToPfn(SubDir);
00080         PdeBase[Index].Valid = 1;
00081         PdeBase[Index].Write = 1;
00082     }
00083     else
00084     {
00085         SubDir = (PVOID)((ULONG64)(PdeBase[Index].PageFrameNumber) * PAGE_SIZE);
00086     }
00087     return SubDir;
00088 }
00089 
00090 BOOLEAN
00091 MempMapSinglePage(ULONG64 VirtualAddress, ULONG64 PhysicalAddress)
00092 {
00093     PHARDWARE_PTE PpeBase, PdeBase, PteBase;
00094     ULONG Index;
00095 
00096     PpeBase = MempGetOrCreatePageDir(PxeBase, VAtoPXI(VirtualAddress));
00097     PdeBase = MempGetOrCreatePageDir(PpeBase, VAtoPPI(VirtualAddress));
00098     PteBase = MempGetOrCreatePageDir(PdeBase, VAtoPDI(VirtualAddress));
00099 
00100     if (!PteBase)
00101     {
00102         ERR("!!!No Dir %p, %p, %p, %p\n", PxeBase, PpeBase, PdeBase, PteBase);
00103         return FALSE;
00104     }
00105 
00106     Index = VAtoPTI(VirtualAddress);
00107     if (PteBase[Index].Valid)
00108     {
00109         ERR("!!!Already mapped %ld\n", Index);
00110         return FALSE;
00111     }
00112 
00113     PteBase[Index].Valid = 1;
00114     PteBase[Index].Write = 1;
00115     PteBase[Index].PageFrameNumber = PhysicalAddress / PAGE_SIZE;
00116 
00117     return TRUE;
00118 }
00119 
00120 BOOLEAN
00121 MempIsPageMapped(PVOID VirtualAddress)
00122 {
00123     PHARDWARE_PTE PpeBase, PdeBase, PteBase;
00124     ULONG Index;
00125 
00126     Index = VAtoPXI(VirtualAddress);
00127     if (!PxeBase[Index].Valid)
00128         return FALSE;
00129 
00130     PpeBase = (PVOID)((ULONG64)(PxeBase[Index].PageFrameNumber) * PAGE_SIZE);
00131     Index = VAtoPPI(VirtualAddress);
00132     if (!PpeBase[Index].Valid)
00133         return FALSE;
00134 
00135     PdeBase = (PVOID)((ULONG64)(PpeBase[Index].PageFrameNumber) * PAGE_SIZE);
00136     Index = VAtoPDI(VirtualAddress);
00137     if (!PdeBase[Index].Valid)
00138         return FALSE;
00139 
00140     PteBase = (PVOID)((ULONG64)(PdeBase[Index].PageFrameNumber) * PAGE_SIZE);
00141     Index = VAtoPTI(VirtualAddress);
00142     if (!PteBase[Index].Valid)
00143         return FALSE;
00144 
00145     return TRUE;
00146 }
00147 
00148 PFN_NUMBER
00149 MempMapRangeOfPages(ULONG64 VirtualAddress, ULONG64 PhysicalAddress, PFN_NUMBER cPages)
00150 {
00151     PFN_NUMBER i;
00152 
00153     for (i = 0; i < cPages; i++)
00154     {
00155         if (!MempMapSinglePage(VirtualAddress, PhysicalAddress))
00156         {
00157             ERR("Failed to map page %ld from %p to %p\n",
00158                     i, (PVOID)VirtualAddress, (PVOID)PhysicalAddress);
00159             return i;
00160         }
00161         VirtualAddress += PAGE_SIZE;
00162         PhysicalAddress += PAGE_SIZE;
00163     }
00164     return i;
00165 }
00166 
00167 BOOLEAN
00168 MempSetupPaging(IN PFN_NUMBER StartPage,
00169                 IN PFN_NUMBER NumberOfPages,
00170                 IN BOOLEAN KernelMapping)
00171 {
00172     TRACE(">>> MempSetupPaging(0x%lx, %ld, %p)\n",
00173             StartPage, NumberOfPages, StartPage * PAGE_SIZE + KSEG0_BASE);
00174 
00175     /* Identity mapping */
00176     if (MempMapRangeOfPages(StartPage * PAGE_SIZE,
00177                             StartPage * PAGE_SIZE,
00178                             NumberOfPages) != NumberOfPages)
00179     {
00180         ERR("Failed to map pages %ld, %ld\n",
00181                 StartPage, NumberOfPages);
00182         return FALSE;
00183     }
00184 
00185     /* Kernel mapping */
00186     if (MempMapRangeOfPages(StartPage * PAGE_SIZE + KSEG0_BASE,
00187                             StartPage * PAGE_SIZE,
00188                             NumberOfPages) != NumberOfPages)
00189     {
00190         ERR("Failed to map pages %ld, %ld\n",
00191                 StartPage, NumberOfPages);
00192         return FALSE;
00193     }
00194 
00195     return TRUE;
00196 }
00197 
00198 VOID
00199 MempUnmapPage(PFN_NUMBER Page)
00200 {
00201    // TRACE(">>> MempUnmapPage\n");
00202 }
00203 
00204 VOID
00205 WinLdrpMapApic()
00206 {
00207     BOOLEAN LocalAPIC;
00208     LARGE_INTEGER MsrValue;
00209     ULONG CpuInfo[4];
00210     ULONG64 APICAddress;
00211 
00212     TRACE(">>> WinLdrpMapApic\n");
00213 
00214     /* Check if we have a local APIC */
00215     __cpuid((int*)CpuInfo, 1);
00216     LocalAPIC = (((CpuInfo[3] >> 9) & 1) != 0);
00217 
00218     /* If there is no APIC, just return */
00219     if (!LocalAPIC)
00220     {
00221         WARN("No APIC found.\n");
00222         return;
00223     }
00224 
00225     /* Read the APIC Address */
00226     MsrValue.QuadPart = __readmsr(0x1B);
00227     APICAddress = (MsrValue.LowPart & 0xFFFFF000);
00228 
00229     TRACE("Local APIC detected at address 0x%x\n",
00230         APICAddress);
00231 
00232     /* Map it */
00233     MempMapSinglePage(APIC_BASE, APICAddress);
00234 }
00235 
00236 BOOLEAN
00237 WinLdrMapSpecialPages()
00238 {
00239     PHARDWARE_PTE PpeBase, PdeBase;
00240 
00241     /* Map the PCR page */
00242     if (!MempMapSinglePage(KIP0PCRADDRESS, PcrBasePage * PAGE_SIZE))
00243     {
00244         ERR("Could not map PCR @ %lx\n", PcrBasePage);
00245         return FALSE;
00246     }
00247 
00248     /* Map KI_USER_SHARED_DATA */
00249     if (!MempMapSinglePage(KI_USER_SHARED_DATA, (PcrBasePage+1) * PAGE_SIZE))
00250     {
00251         ERR("Could not map KI_USER_SHARED_DATA\n");
00252         return FALSE;
00253     }
00254 
00255     /* Map the APIC page */
00256     WinLdrpMapApic();
00257 
00258     /* Map the page tables for 4 MB HAL address space. */
00259     PpeBase = MempGetOrCreatePageDir(PxeBase, VAtoPXI(MM_HAL_VA_START));
00260     PdeBase = MempGetOrCreatePageDir(PpeBase, VAtoPPI(MM_HAL_VA_START));
00261     MempGetOrCreatePageDir(PdeBase, VAtoPDI(MM_HAL_VA_START));
00262     MempGetOrCreatePageDir(PdeBase, VAtoPDI(MM_HAL_VA_START + 2 * 1024 * 1024));
00263 
00264     return TRUE;
00265 }
00266 
00267 VOID
00268 Amd64SetupGdt(PVOID GdtBase, ULONG64 TssBase)
00269 {
00270     PKGDTENTRY64 Entry;
00271     KDESCRIPTOR GdtDesc;
00272 
00273     /* Setup KGDT64_NULL */
00274     Entry = KiGetGdtEntry(GdtBase, KGDT64_NULL);
00275     *(PULONG64)Entry = 0x0000000000000000ULL;
00276 
00277     /* Setup KGDT64_R0_CODE */
00278     Entry = KiGetGdtEntry(GdtBase, KGDT64_R0_CODE);
00279     *(PULONG64)Entry = 0x00209b0000000000ULL;
00280 
00281     /* Setup KGDT64_R0_DATA */
00282     Entry = KiGetGdtEntry(GdtBase, KGDT64_R0_DATA);
00283     *(PULONG64)Entry = 0x00cf93000000ffffULL;
00284 
00285     /* Setup KGDT64_R3_CMCODE */
00286     Entry = KiGetGdtEntry(GdtBase, KGDT64_R3_CMCODE);
00287     *(PULONG64)Entry = 0x00cffb000000ffffULL;
00288 
00289     /* Setup KGDT64_R3_DATA */
00290     Entry = KiGetGdtEntry(GdtBase, KGDT64_R3_DATA);
00291     *(PULONG64)Entry = 0x00cff3000000ffffULL;
00292 
00293     /* Setup KGDT64_R3_CODE */
00294     Entry = KiGetGdtEntry(GdtBase, KGDT64_R3_CODE);
00295     *(PULONG64)Entry = 0x0020fb0000000000ULL;
00296 
00297     /* Setup KGDT64_R3_CMTEB */
00298     Entry = KiGetGdtEntry(GdtBase, KGDT64_R3_CMTEB);
00299     *(PULONG64)Entry = 0xff40f3fd50003c00ULL;
00300 
00301     /* Setup TSS entry */
00302     Entry = KiGetGdtEntry(GdtBase, KGDT64_SYS_TSS);
00303     KiInitGdtEntry(Entry, TssBase, sizeof(KTSS), I386_TSS, 0);
00304 
00305     /* Setup GDT descriptor */
00306     GdtDesc.Base  = GdtBase;
00307     GdtDesc.Limit = NUM_GDT * sizeof(KGDTENTRY) - 1;
00308 
00309     /* Set the new Gdt */
00310     __lgdt(&GdtDesc.Limit);
00311     TRACE("Gdtr.Base = %p, num = %ld\n", GdtDesc.Base, NUM_GDT);
00312 
00313 }
00314 
00315 VOID
00316 Amd64SetupIdt(PVOID IdtBase)
00317 {
00318     KDESCRIPTOR IdtDesc, OldIdt;
00319 
00320     /* Get old IDT */
00321     __sidt(&OldIdt);
00322 
00323     /* Copy the old IDT */
00324     RtlCopyMemory(IdtBase, (PVOID)OldIdt.Base, OldIdt.Limit + 1);
00325 
00326     /* Setup the new IDT descriptor */
00327     IdtDesc.Base = IdtBase;
00328     IdtDesc.Limit = NUM_IDT * sizeof(KIDTENTRY) - 1;
00329 
00330     /* Set the new IDT */
00331     __lidt(&IdtDesc.Limit);
00332     TRACE("Idtr.Base = %p\n", IdtDesc.Base);
00333 
00334 }
00335 
00336 VOID
00337 WinLdrSetProcessorContext(void)
00338 {
00339     TRACE("WinLdrSetProcessorContext\n");
00340 
00341     /* Disable Interrupts */
00342     _disable();
00343 
00344     /* Re-initalize EFLAGS */
00345     __writeeflags(0);
00346 
00347     /* Set the new PML4 */
00348     __writecr3((ULONG64)PxeBase);
00349 
00350     /* Get kernel mode address of gdt / idt */
00351     GdtIdt = (PVOID)((ULONG64)GdtIdt + KSEG0_BASE);
00352 
00353     /* Create gdt entries and load gdtr */
00354     Amd64SetupGdt(GdtIdt, KSEG0_BASE | (TssBasePage << MM_PAGE_SHIFT));
00355 
00356     /* Copy old Idt and set idtr */
00357     Amd64SetupIdt((PVOID)((ULONG64)GdtIdt + 2048)); // HACK!
00358 
00359     /* LDT is unused */
00360 //    __lldt(0);
00361 
00362     /* Load TSR */
00363     __ltr(KGDT64_SYS_TSS);
00364 
00365     TRACE("leave WinLdrSetProcessorContext\n");
00366 }
00367 
00368 void WinLdrSetupMachineDependent(PLOADER_PARAMETER_BLOCK LoaderBlock)
00369 {
00370     ULONG_PTR Pcr = 0;
00371     ULONG_PTR Tss = 0;
00372     ULONG BlockSize, NumPages;
00373 
00374     LoaderBlock->u.I386.CommonDataArea = (PVOID)DbgPrint; // HACK
00375     LoaderBlock->u.I386.MachineType = MACHINE_TYPE_ISA;
00376 
00377     /* Allocate 2 pages for PCR */
00378     Pcr = (ULONG_PTR)MmAllocateMemoryWithType(2 * MM_PAGE_SIZE, LoaderStartupPcrPage);
00379     PcrBasePage = Pcr >> MM_PAGE_SHIFT;
00380     if (Pcr == 0)
00381     {
00382         UiMessageBox("Can't allocate PCR\n");
00383         return;
00384     }
00385     RtlZeroMemory((PVOID)Pcr, 2 * MM_PAGE_SIZE);
00386 
00387     /* Allocate TSS */
00388     BlockSize = (sizeof(KTSS) + MM_PAGE_SIZE) & ~(MM_PAGE_SIZE - 1);
00389     Tss = (ULONG_PTR)MmAllocateMemoryWithType(BlockSize, LoaderMemoryData);
00390     TssBasePage = Tss >> MM_PAGE_SHIFT;
00391 
00392     /* Allocate space for new GDT + IDT */
00393     BlockSize = NUM_GDT*sizeof(KGDTENTRY) + NUM_IDT*sizeof(KIDTENTRY);//FIXME: Use GDT/IDT limits here?
00394     NumPages = (BlockSize + MM_PAGE_SIZE - 1) >> MM_PAGE_SHIFT;
00395     GdtIdt = (PKGDTENTRY)MmAllocateMemoryWithType(NumPages * MM_PAGE_SIZE, LoaderMemoryData);
00396     if (GdtIdt == NULL)
00397     {
00398         UiMessageBox("Can't allocate pages for GDT+IDT!\n");
00399         return;
00400     }
00401 
00402     /* Zero newly prepared GDT+IDT */
00403     RtlZeroMemory(GdtIdt, NumPages << MM_PAGE_SHIFT);
00404 
00405     // Before we start mapping pages, create a block of memory, which will contain
00406     // PDE and PTEs
00407     if (MempAllocatePageTables() == FALSE)
00408     {
00409         // FIXME: bugcheck
00410     }
00411 
00412     /* Map stuff like PCR, KI_USER_SHARED_DATA and Apic */
00413     WinLdrMapSpecialPages();
00414 }
00415 
00416 
00417 VOID
00418 MempDump()
00419 {
00420 }
00421 

Generated on Sat May 26 2012 04:17:51 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.