ReactOS 0.4.15-dev-6703-g6528ab8
winldr.c
Go to the documentation of this file.
1/*
2 * PROJECT: EFI Windows Loader
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: boot/freeldr/freeldr/arch/amd64/winldr.c
5 * PURPOSE: Memory related routines
6 * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org)
7 */
8
9/* INCLUDES ***************************************************************/
10
11#include <freeldr.h>
12#include <ndk/asm.h>
13#include "../../winldr.h"
14
15#include <debug.h>
17
18//extern ULONG LoaderPagesSpanned;
19
20/* GLOBALS ***************************************************************/
21
23//PHARDWARE_PTE HalPageTable;
24
28
29/* FUNCTIONS **************************************************************/
30
31static
34{
35 TRACE(">>> MempAllocatePageTables\n");
36
37 /* Allocate a page for the PML4 */
39 if (!PxeBase)
40 {
41 ERR("failed to allocate PML4\n");
42 return FALSE;
43 }
44
45 // FIXME: Physical PTEs = FirmwareTemporary ?
46
47 /* Zero the PML4 */
49
50 /* The page tables are located at 0xfffff68000000000
51 * We create a recursive self mapping through all 4 levels at
52 * virtual address 0xfffff6fb7dbedf68 */
56
57 // FIXME: map PDE's for hals memory mapping
58
59 TRACE(">>> leave MempAllocatePageTables\n");
60
61 return TRUE;
62}
63
64static
67{
69
70 if (!PdeBase)
71 return NULL;
72
73 if (!PdeBase[Index].Valid)
74 {
76 if (!SubDir)
77 return NULL;
80 PdeBase[Index].Valid = 1;
81 PdeBase[Index].Write = 1;
82 }
83 else
84 {
86 }
87 return SubDir;
88}
89
90static
93{
94 PHARDWARE_PTE PpeBase, PdeBase, PteBase;
96
100
101 if (!PteBase)
102 {
103 ERR("!!!No Dir %p, %p, %p, %p\n", PxeBase, PpeBase, PdeBase, PteBase);
104 return FALSE;
105 }
106
108 if (PteBase[Index].Valid)
109 {
110 ERR("!!!Already mapped %ld\n", Index);
111 return FALSE;
112 }
113
114 PteBase[Index].Valid = 1;
115 PteBase[Index].Write = 1;
117
118 return TRUE;
119}
120
123{
124 PHARDWARE_PTE PpeBase, PdeBase, PteBase;
125 ULONG Index;
126
128 if (!PxeBase[Index].Valid)
129 return FALSE;
130
133 if (!PpeBase[Index].Valid)
134 return FALSE;
135
136 PdeBase = (PVOID)((ULONG64)(PpeBase[Index].PageFrameNumber) * PAGE_SIZE);
138 if (!PdeBase[Index].Valid)
139 return FALSE;
140
141 PteBase = (PVOID)((ULONG64)(PdeBase[Index].PageFrameNumber) * PAGE_SIZE);
143 if (!PteBase[Index].Valid)
144 return FALSE;
145
146 return TRUE;
147}
148
149static
152{
154
155 for (i = 0; i < cPages; i++)
156 {
158 {
159 ERR("Failed to map page %ld from %p to %p\n",
161 return i;
162 }
165 }
166 return i;
167}
168
171 IN PFN_NUMBER NumberOfPages,
172 IN BOOLEAN KernelMapping)
173{
174 TRACE(">>> MempSetupPaging(0x%lx, %ld, %p)\n",
175 StartPage, NumberOfPages, StartPage * PAGE_SIZE + KSEG0_BASE);
176
177 /* Identity mapping */
180 NumberOfPages) != NumberOfPages)
181 {
182 ERR("Failed to map pages %ld, %ld\n",
183 StartPage, NumberOfPages);
184 return FALSE;
185 }
186
187 /* Kernel mapping */
188 if (KernelMapping)
189 {
192 NumberOfPages) != NumberOfPages)
193 {
194 ERR("Failed to map pages %ld, %ld\n",
195 StartPage, NumberOfPages);
196 return FALSE;
197 }
198 }
199
200 return TRUE;
201}
202
203VOID
205{
206 // TRACE(">>> MempUnmapPage\n");
207}
208
209static
210VOID
212{
213 BOOLEAN LocalAPIC;
214 LARGE_INTEGER MsrValue;
215 ULONG CpuInfo[4];
216 ULONG64 APICAddress;
217
218 TRACE(">>> WinLdrpMapApic\n");
219
220 /* Check if we have a local APIC */
221 __cpuid((int*)CpuInfo, 1);
222 LocalAPIC = (((CpuInfo[3] >> 9) & 1) != 0);
223
224 /* If there is no APIC, just return */
225 if (!LocalAPIC)
226 {
227 WARN("No APIC found.\n");
228 return;
229 }
230
231 /* Read the APIC Address */
232 MsrValue.QuadPart = __readmsr(0x1B);
233 APICAddress = (MsrValue.LowPart & 0xFFFFF000);
234
235 TRACE("Local APIC detected at address 0x%x\n",
236 APICAddress);
237
238 /* Map it */
239 MempMapSinglePage(APIC_BASE, APICAddress);
240}
241
242static
245{
246 PHARDWARE_PTE PpeBase, PdeBase;
247
248 /* Map the PCR page */
250 {
251 ERR("Could not map PCR @ %lx\n", PcrBasePage);
252 return FALSE;
253 }
254
255 /* Map KI_USER_SHARED_DATA */
257 {
258 ERR("Could not map KI_USER_SHARED_DATA\n");
259 return FALSE;
260 }
261
262 /* Map the APIC page */
264
265 /* Map the page tables for 4 MB HAL address space. */
269 MempGetOrCreatePageDir(PdeBase, VAtoPDI(MM_HAL_VA_START + 2 * 1024 * 1024));
270
271 return TRUE;
272}
273
274static
275VOID
276Amd64SetupGdt(PVOID GdtBase, ULONG64 TssBase)
277{
279 KDESCRIPTOR GdtDesc;
280 TRACE("Amd64SetupGdt(GdtBase = %p, TssBase = %p)\n", GdtBase, TssBase);
281
282 /* Setup KGDT64_NULL */
283 Entry = KiGetGdtEntry(GdtBase, KGDT64_NULL);
284 *(PULONG64)Entry = 0x0000000000000000ULL;
285
286 /* Setup KGDT64_R0_CODE */
288 *(PULONG64)Entry = 0x00209b0000000000ULL;
289
290 /* Setup KGDT64_R0_DATA */
292 *(PULONG64)Entry = 0x00cf93000000ffffULL;
293
294 /* Setup KGDT64_R3_CMCODE */
296 *(PULONG64)Entry = 0x00cffb000000ffffULL;
297
298 /* Setup KGDT64_R3_DATA */
300 *(PULONG64)Entry = 0x00cff3000000ffffULL;
301
302 /* Setup KGDT64_R3_CODE */
304 *(PULONG64)Entry = 0x0020fb0000000000ULL;
305
306 /* Setup KGDT64_R3_CMTEB */
308 *(PULONG64)Entry = 0xff40f3fd50003c00ULL;
309
310 /* Setup TSS entry */
312 KiInitGdtEntry(Entry, TssBase, sizeof(KTSS), I386_TSS, 0);
313
314 /* Setup GDT descriptor */
315 GdtDesc.Base = GdtBase;
316 GdtDesc.Limit = NUM_GDT * sizeof(KGDTENTRY) - 1;
317
318 /* Set the new Gdt */
319 __lgdt(&GdtDesc.Limit);
320 TRACE("Leave Amd64SetupGdt()\n");
321}
322
323static
324VOID
326{
327 KDESCRIPTOR IdtDesc, OldIdt;
328 //ULONG Size;
329 TRACE("Amd64SetupIdt(IdtBase = %p)\n", IdtBase);
330
331 /* Get old IDT */
332 __sidt(&OldIdt.Limit);
333
334 /* Copy the old IDT */
335 //Size = min(OldIdt.Limit + 1, NUM_IDT * sizeof(KIDTENTRY));
336 //RtlCopyMemory(IdtBase, (PVOID)OldIdt.Base, Size);
337
338 /* Setup the new IDT descriptor */
339 IdtDesc.Base = IdtBase;
340 IdtDesc.Limit = NUM_IDT * sizeof(KIDTENTRY) - 1;
341
342 /* Set the new IDT */
343 __lidt(&IdtDesc.Limit);
344 TRACE("Leave Amd64SetupIdt()\n");
345}
346
347VOID
349{
350 TRACE("WinLdrSetProcessorContext\n");
351
352 /* Disable Interrupts */
353 _disable();
354
355 /* Re-initialize EFLAGS */
356 __writeeflags(0);
357
358 /* Set the new PML4 */
360
361 /* Get kernel mode address of gdt / idt */
363
364 /* Create gdt entries and load gdtr */
365 Amd64SetupGdt(GdtIdt, KSEG0_BASE | (TssBasePage << MM_PAGE_SHIFT));
366
367 /* Copy old Idt and set idtr */
369
370 /* LDT is unused */
371// __lldt(0);
372
373 /* Load TSR */
374 __ltr(KGDT64_SYS_TSS);
375
376 TRACE("leave WinLdrSetProcessorContext\n");
377}
378
380{
381 ULONG_PTR Pcr = 0;
382 ULONG_PTR Tss = 0;
383 ULONG BlockSize, NumPages;
384
385 LoaderBlock->u.I386.CommonDataArea = (PVOID)DbgPrint; // HACK
386 LoaderBlock->u.I386.MachineType = MACHINE_TYPE_ISA;
387
388 /* Allocate 2 pages for PCR */
390 PcrBasePage = Pcr >> MM_PAGE_SHIFT;
391 if (Pcr == 0)
392 {
393 UiMessageBox("Can't allocate PCR.");
394 return;
395 }
396 RtlZeroMemory((PVOID)Pcr, 2 * MM_PAGE_SIZE);
397
398 /* Allocate TSS */
399 BlockSize = (sizeof(KTSS) + MM_PAGE_SIZE) & ~(MM_PAGE_SIZE - 1);
401 TssBasePage = Tss >> MM_PAGE_SHIFT;
402
403 /* Allocate space for new GDT + IDT */
404 BlockSize = NUM_GDT * sizeof(KGDTENTRY) + NUM_IDT * sizeof(KIDTENTRY);
405 NumPages = (BlockSize + MM_PAGE_SIZE - 1) >> MM_PAGE_SHIFT;
406 GdtIdt = (PKGDTENTRY)MmAllocateMemoryWithType(NumPages * MM_PAGE_SIZE, LoaderMemoryData);
407 if (GdtIdt == NULL)
408 {
409 UiMessageBox("Can't allocate pages for GDT+IDT!");
410 return;
411 }
412
413 /* Zero newly prepared GDT+IDT */
414 RtlZeroMemory(GdtIdt, NumPages << MM_PAGE_SHIFT);
415
416 // Before we start mapping pages, create a block of memory, which will contain
417 // PDE and PTEs
419 {
420 // FIXME: bugcheck
421 }
422
423 /* Map stuff like PCR, KI_USER_SHARED_DATA and Apic */
425}
426
427
428VOID
430{
431}
unsigned char BOOLEAN
FORCEINLINE VOID KiInitGdtEntry(PKGDTENTRY64 Entry, ULONG64 Base, ULONG Size, UCHAR Type, UCHAR Dpl)
Definition: intrin_i.h:48
#define VAtoPTI(va)
Definition: amd64.h:37
#define KIP0PCRADDRESS
Definition: amd64.h:27
#define VAtoPXI(va)
Definition: amd64.h:34
#define PtrToPfn(p)
Definition: amd64.h:31
#define VAtoPPI(va)
Definition: amd64.h:35
#define VAtoPDI(va)
Definition: amd64.h:36
PVOID GdtIdt
Definition: winldr.c:25
static BOOLEAN MempMapSinglePage(ULONG64 VirtualAddress, ULONG64 PhysicalAddress)
Definition: winldr.c:92
BOOLEAN MempSetupPaging(IN PFN_NUMBER StartPage, IN PFN_NUMBER NumberOfPages, IN BOOLEAN KernelMapping)
Definition: winldr.c:170
static BOOLEAN MempAllocatePageTables(VOID)
Definition: winldr.c:33
ULONG_PTR TssBasePage
Definition: winldr.c:27
static PHARDWARE_PTE MempGetOrCreatePageDir(PHARDWARE_PTE PdeBase, ULONG Index)
Definition: winldr.c:66
PHARDWARE_PTE PxeBase
Definition: winldr.c:22
static VOID WinLdrpMapApic(VOID)
Definition: winldr.c:211
ULONG_PTR PcrBasePage
Definition: winldr.c:26
VOID MempUnmapPage(PFN_NUMBER Page)
Definition: winldr.c:204
static VOID Amd64SetupGdt(PVOID GdtBase, ULONG64 TssBase)
Definition: winldr.c:276
VOID WinLdrSetProcessorContext(void)
Definition: winldr.c:348
static PFN_NUMBER MempMapRangeOfPages(ULONG64 VirtualAddress, ULONG64 PhysicalAddress, PFN_NUMBER cPages)
Definition: winldr.c:151
static VOID Amd64SetupIdt(PVOID IdtBase)
Definition: winldr.c:325
VOID MempDump(VOID)
Definition: winldr.c:429
BOOLEAN MempIsPageMapped(PVOID VirtualAddress)
Definition: winldr.c:122
void WinLdrSetupMachineDependent(PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: winldr.c:379
FORCEINLINE PKGDTENTRY KiGetGdtEntry(IN PVOID pGdt, IN USHORT Selector)
Definition: winldr.c:69
static BOOLEAN WinLdrMapSpecialPages(void)
Definition: winldr.c:394
#define WARN(fmt,...)
Definition: debug.h:112
#define ERR(fmt,...)
Definition: debug.h:110
#define DBG_DEFAULT_CHANNEL(ch)
Definition: debug.h:103
PVOID MmAllocateMemoryWithType(SIZE_T MemorySize, TYPE_OF_MEMORY MemoryType)
Definition: mm.c:31
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static const WCHAR SubDir[]
Definition: install.c:49
#define ULONG_PTR
Definition: config.h:101
#define PAGE_SIZE
Definition: env_spec_w32.h:49
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define DbgPrint
Definition: hal.h:12
void __cdecl _disable(void)
Definition: intrin_arm.h:365
PPC_QUAL void __cpuid(int CPUInfo[], const int InfoType)
Definition: intrin_ppc.h:682
PPC_QUAL unsigned long long __readmsr()
Definition: intrin_ppc.h:741
__INTRIN_INLINE void __writeeflags(uintptr_t Value)
Definition: intrin_x86.h:1669
__INTRIN_INLINE void __lidt(void *Source)
Definition: intrin_x86.h:2018
__INTRIN_INLINE void __writecr3(unsigned int Data)
Definition: intrin_x86.h:1794
__INTRIN_INLINE void __sidt(void *Destination)
Definition: intrin_x86.h:2023
unsigned __int64 * PULONG64
Definition: imports.h:198
unsigned __int64 ULONG64
Definition: imports.h:198
#define KIDTENTRY
Definition: ketypes.h:488
#define APIC_BASE
Definition: ketypes.h:263
#define KTSS
Definition: ketypes.h:929
#define KGDT64_SYS_TSS
Definition: ketypes.h:77
#define KGDT64_R3_CODE
Definition: ketypes.h:76
#define KSEG0_BASE
Definition: ketypes.h:278
#define KGDT64_NULL
Definition: ketypes.h:71
#define MM_HAL_VA_START
Definition: ketypes.h:261
#define I386_TSS
Definition: ketypes.h:60
#define KGDT64_R0_CODE
Definition: ketypes.h:72
#define KGDT64_R3_DATA
Definition: ketypes.h:75
#define KGDT64_R3_CMCODE
Definition: ketypes.h:74
#define PKGDTENTRY
Definition: ketypes.h:447
#define KGDT64_R3_CMTEB
Definition: ketypes.h:78
#define KGDTENTRY
Definition: ketypes.h:446
#define KGDT64_R0_DATA
Definition: ketypes.h:73
#define MACHINE_TYPE_ISA
Definition: ketypes.h:52
#define NUM_IDT
Definition: winldr.h:17
#define NUM_GDT
Definition: winldr.h:16
_In_ PVOID _Out_opt_ BOOLEAN _Out_opt_ PPFN_NUMBER Page
Definition: mm.h:1306
@ LoaderMemoryData
Definition: arc.h:194
@ LoaderStartupPcrPage
Definition: arc.h:191
#define KI_USER_SHARED_DATA
#define PXE_BASE
ULONG PFN_NUMBER
Definition: ke.h:9
#define TRACE(s)
Definition: solgame.cpp:4
base of all file and directory entries
Definition: entries.h:83
ULONG64 PageFrameNumber
Definition: mmtypes.h:78
ULONG64 Write
Definition: mmtypes.h:67
ULONG64 Valid
Definition: mmtypes.h:66
ULONG MachineType
Definition: arc.h:454
PVOID CommonDataArea
Definition: arc.h:453
PVOID Base
Definition: ketypes.h:495
USHORT Limit
Definition: ketypes.h:494
Definition: ketypes.h:791
union _LOADER_PARAMETER_BLOCK::@3356 u
I386_LOADER_BLOCK I386
Definition: arc.h:562
void * PVOID
Definition: typedefs.h:50
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
VOID UiMessageBox(PCSTR Format,...)
Definition: ui.c:357
LONGLONG QuadPart
Definition: typedefs.h:114
ULONG LowPart
Definition: typedefs.h:106
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFDMATRANSACTION _In_ PFN_WDF_PROGRAM_DMA _In_ WDF_DMA_DIRECTION _In_ PMDL _In_ PVOID VirtualAddress
int WINAPI StartPage(_In_ HDC)
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS PhysicalAddress
Definition: iotypes.h:1098