Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenwinldr.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
1.7.6.1
|