ReactOS 0.4.16-dev-109-gf4cb10f
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>
14#include "../../winldr.h"
15
16#include <debug.h>
18
19//extern ULONG LoaderPagesSpanned;
20
21/* GLOBALS ***************************************************************/
22
24//PHARDWARE_PTE HalPageTable;
25
29
30/* FUNCTIONS **************************************************************/
31
32static
35{
36 TRACE(">>> MempAllocatePageTables\n");
37
38 /* Allocate a page for the PML4 */
40 if (!PxeBase)
41 {
42 ERR("failed to allocate PML4\n");
43 return FALSE;
44 }
45
46 // FIXME: Physical PTEs = FirmwareTemporary ?
47
48 /* Zero the PML4 */
50
51 /* The page tables are located at 0xfffff68000000000
52 * We create a recursive self mapping through all 4 levels at
53 * virtual address 0xfffff6fb7dbedf68 */
57
58 // FIXME: map PDE's for hals memory mapping
59
60 TRACE(">>> leave MempAllocatePageTables\n");
61
62 return TRUE;
63}
64
65static
68{
70
71 if (!PdeBase)
72 return NULL;
73
74 if (!PdeBase[Index].Valid)
75 {
77 if (!SubDir)
78 return NULL;
81 PdeBase[Index].Valid = 1;
82 PdeBase[Index].Write = 1;
83 }
84 else
85 {
87 }
88 return SubDir;
89}
90
91static
94{
95 PHARDWARE_PTE PpeBase, PdeBase, PteBase;
97
100 PteBase = MempGetOrCreatePageDir(PdeBase, VAtoPDI(VirtualAddress));
101
102 if (!PteBase)
103 {
104 ERR("!!!No Dir %p, %p, %p, %p\n", PxeBase, PpeBase, PdeBase, PteBase);
105 return FALSE;
106 }
107
109 if (PteBase[Index].Valid)
110 {
111 ERR("!!!Already mapped %ld\n", Index);
112 return FALSE;
113 }
114
115 PteBase[Index].Valid = 1;
116 PteBase[Index].Write = 1;
118
119 return TRUE;
120}
121
124{
125 PHARDWARE_PTE PpeBase, PdeBase, PteBase;
126 ULONG Index;
127
129 if (!PxeBase[Index].Valid)
130 return FALSE;
131
134 if (!PpeBase[Index].Valid)
135 return FALSE;
136
137 PdeBase = (PVOID)((ULONG64)(PpeBase[Index].PageFrameNumber) * PAGE_SIZE);
139 if (!PdeBase[Index].Valid)
140 return FALSE;
141
142 PteBase = (PVOID)((ULONG64)(PdeBase[Index].PageFrameNumber) * PAGE_SIZE);
144 if (!PteBase[Index].Valid)
145 return FALSE;
146
147 return TRUE;
148}
149
150static
153{
155
156 for (i = 0; i < cPages; i++)
157 {
159 {
160 ERR("Failed to map page %ld from %p to %p\n",
162 return i;
163 }
166 }
167 return i;
168}
169
172 IN PFN_NUMBER NumberOfPages,
173 IN BOOLEAN KernelMapping)
174{
175 TRACE(">>> MempSetupPaging(0x%lx, %ld, %p)\n",
176 StartPage, NumberOfPages, StartPage * PAGE_SIZE + KSEG0_BASE);
177
178 /* Identity mapping */
181 NumberOfPages) != NumberOfPages)
182 {
183 ERR("Failed to map pages %ld, %ld\n",
184 StartPage, NumberOfPages);
185 return FALSE;
186 }
187
188 /* Kernel mapping */
189 if (KernelMapping)
190 {
193 NumberOfPages) != NumberOfPages)
194 {
195 ERR("Failed to map pages %ld, %ld\n",
196 StartPage, NumberOfPages);
197 return FALSE;
198 }
199 }
200
201 return TRUE;
202}
203
204VOID
206{
207 // TRACE(">>> MempUnmapPage\n");
208}
209
210static
211VOID
213{
214 BOOLEAN LocalAPIC;
215 LARGE_INTEGER MsrValue;
216 ULONG CpuInfo[4];
217 ULONG64 APICAddress;
218
219 TRACE(">>> WinLdrpMapApic\n");
220
221 /* Check if we have a local APIC */
222 __cpuid((int*)CpuInfo, 1);
223 LocalAPIC = (((CpuInfo[3] >> 9) & 1) != 0);
224
225 /* If there is no APIC, just return */
226 if (!LocalAPIC)
227 {
228 WARN("No APIC found.\n");
229 return;
230 }
231
232 /* Read the APIC Address */
233 MsrValue.QuadPart = __readmsr(0x1B);
234 APICAddress = (MsrValue.LowPart & 0xFFFFF000);
235
236 TRACE("Local APIC detected at address 0x%x\n",
237 APICAddress);
238
239 /* Map it */
240 MempMapSinglePage(APIC_BASE, APICAddress);
241}
242
243static
246{
247 PHARDWARE_PTE PpeBase, PdeBase;
248
249 /* Map the PCR page */
251 {
252 ERR("Could not map PCR @ %lx\n", PcrBasePage);
253 return FALSE;
254 }
255
256 /* Map KI_USER_SHARED_DATA */
258 {
259 ERR("Could not map KI_USER_SHARED_DATA\n");
260 return FALSE;
261 }
262
263 /* Map the APIC page */
265
266 /* Map the page tables for 4 MB HAL address space. */
270 MempGetOrCreatePageDir(PdeBase, VAtoPDI(MM_HAL_VA_START + 2 * 1024 * 1024));
271
272 return TRUE;
273}
274
275static
276VOID
277Amd64SetupGdt(PVOID GdtBase, ULONG64 TssBase)
278{
280 KDESCRIPTOR GdtDesc;
281 TRACE("Amd64SetupGdt(GdtBase = %p, TssBase = %p)\n", GdtBase, TssBase);
282
283 /* Setup KGDT64_NULL */
284 Entry = KiGetGdtEntry(GdtBase, KGDT64_NULL);
285 *(PULONG64)Entry = 0x0000000000000000ULL;
286
287 /* Setup KGDT64_R0_CODE */
289 *(PULONG64)Entry = 0x00209b0000000000ULL;
290
291 /* Setup KGDT64_R0_DATA */
293 *(PULONG64)Entry = 0x00cf93000000ffffULL;
294
295 /* Setup KGDT64_R3_CMCODE */
297 *(PULONG64)Entry = 0x00cffb000000ffffULL;
298
299 /* Setup KGDT64_R3_DATA */
301 *(PULONG64)Entry = 0x00cff3000000ffffULL;
302
303 /* Setup KGDT64_R3_CODE */
305 *(PULONG64)Entry = 0x0020fb0000000000ULL;
306
307 /* Setup KGDT64_R3_CMTEB */
309 *(PULONG64)Entry = 0xff40f3fd50003c00ULL;
310
311 /* Setup TSS entry */
313 KiInitGdtEntry(Entry, TssBase, sizeof(KTSS), I386_TSS, 0);
314
315 /* Setup GDT descriptor */
316 GdtDesc.Base = GdtBase;
317 GdtDesc.Limit = NUM_GDT * sizeof(KGDTENTRY) - 1;
318
319 /* Set the new Gdt */
320 __lgdt(&GdtDesc.Limit);
321 TRACE("Leave Amd64SetupGdt()\n");
322}
323
324static
325VOID
327{
328 KDESCRIPTOR IdtDesc, OldIdt;
329 //ULONG Size;
330 TRACE("Amd64SetupIdt(IdtBase = %p)\n", IdtBase);
331
332 /* Get old IDT */
333 __sidt(&OldIdt.Limit);
334
335 /* Copy the old IDT */
336 //Size = min(OldIdt.Limit + 1, NUM_IDT * sizeof(KIDTENTRY));
337 //RtlCopyMemory(IdtBase, (PVOID)OldIdt.Base, Size);
338
339 /* Setup the new IDT descriptor */
340 IdtDesc.Base = IdtBase;
341 IdtDesc.Limit = NUM_IDT * sizeof(KIDTENTRY) - 1;
342
343 /* Set the new IDT */
344 __lidt(&IdtDesc.Limit);
345 TRACE("Leave Amd64SetupIdt()\n");
346}
347
348VOID
350 _In_ USHORT OperatingSystemVersion)
351{
352 TRACE("WinLdrSetProcessorContext\n");
353
354 /* Disable Interrupts */
355 _disable();
356
357 /* Re-initialize EFLAGS */
358 __writeeflags(0);
359
360 /* Set the new PML4 */
362
363 /* Get kernel mode address of gdt / idt */
365
366 /* Create gdt entries and load gdtr */
367 Amd64SetupGdt(GdtIdt, KSEG0_BASE | (TssBasePage << MM_PAGE_SHIFT));
368
369 /* Copy old Idt and set idtr */
371
372 /* LDT is unused */
373// __lldt(0);
374
375 /* Load TSR */
376 __ltr(KGDT64_SYS_TSS);
377
378 TRACE("leave WinLdrSetProcessorContext\n");
379}
380
382{
383 ULONG_PTR Pcr = 0;
384 ULONG_PTR Tss = 0;
385 ULONG BlockSize, NumPages;
386
387 LoaderBlock->u.I386.CommonDataArea = (PVOID)DbgPrint; // HACK
388 LoaderBlock->u.I386.MachineType = MACHINE_TYPE_ISA;
389
390 /* Allocate 2 pages for PCR */
392 PcrBasePage = Pcr >> MM_PAGE_SHIFT;
393 if (Pcr == 0)
394 {
395 UiMessageBox("Can't allocate PCR.");
396 return;
397 }
398 RtlZeroMemory((PVOID)Pcr, 2 * MM_PAGE_SIZE);
399
400 /* Allocate TSS */
401 BlockSize = (sizeof(KTSS) + MM_PAGE_SIZE) & ~(MM_PAGE_SIZE - 1);
403 TssBasePage = Tss >> MM_PAGE_SHIFT;
404
405 /* Allocate space for new GDT + IDT */
406 BlockSize = NUM_GDT * sizeof(KGDTENTRY) + NUM_IDT * sizeof(KIDTENTRY);
407 NumPages = (BlockSize + MM_PAGE_SIZE - 1) >> MM_PAGE_SHIFT;
408 GdtIdt = (PKGDTENTRY)MmAllocateMemoryWithType(NumPages * MM_PAGE_SIZE, LoaderMemoryData);
409 if (GdtIdt == NULL)
410 {
411 UiMessageBox("Can't allocate pages for GDT+IDT!");
412 return;
413 }
414
415 /* Zero newly prepared GDT+IDT */
416 RtlZeroMemory(GdtIdt, NumPages << MM_PAGE_SHIFT);
417
418 // Before we start mapping pages, create a block of memory, which will contain
419 // PDE and PTEs
421 {
422 // FIXME: bugcheck
423 }
424
425 /* Map stuff like PCR, KI_USER_SHARED_DATA and Apic */
427}
428
429
430VOID
432{
433}
unsigned char BOOLEAN
FORCEINLINE PKGDTENTRY64 KiGetGdtEntry(PVOID pGdt, USHORT Selector)
Definition: intrin_i.h:13
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:26
VOID WinLdrSetProcessorContext(_In_ USHORT OperatingSystemVersion)
Definition: winldr.c:349
static BOOLEAN MempMapSinglePage(ULONG64 VirtualAddress, ULONG64 PhysicalAddress)
Definition: winldr.c:93
BOOLEAN MempSetupPaging(IN PFN_NUMBER StartPage, IN PFN_NUMBER NumberOfPages, IN BOOLEAN KernelMapping)
Definition: winldr.c:171
static BOOLEAN MempAllocatePageTables(VOID)
Definition: winldr.c:34
ULONG_PTR TssBasePage
Definition: winldr.c:28
static PHARDWARE_PTE MempGetOrCreatePageDir(PHARDWARE_PTE PdeBase, ULONG Index)
Definition: winldr.c:67
PHARDWARE_PTE PxeBase
Definition: winldr.c:23
static VOID WinLdrpMapApic(VOID)
Definition: winldr.c:212
ULONG_PTR PcrBasePage
Definition: winldr.c:27
VOID MempUnmapPage(PFN_NUMBER Page)
Definition: winldr.c:205
static VOID Amd64SetupGdt(PVOID GdtBase, ULONG64 TssBase)
Definition: winldr.c:277
static PFN_NUMBER MempMapRangeOfPages(ULONG64 VirtualAddress, ULONG64 PhysicalAddress, PFN_NUMBER cPages)
Definition: winldr.c:152
static VOID Amd64SetupIdt(PVOID IdtBase)
Definition: winldr.c:326
VOID MempDump(VOID)
Definition: winldr.c:431
BOOLEAN MempIsPageMapped(PVOID VirtualAddress)
Definition: winldr.c:123
void WinLdrSetupMachineDependent(PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: winldr.c:381
static BOOLEAN WinLdrMapSpecialPages(void)
Definition: winldr.c:320
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
#define DBG_DEFAULT_CHANNEL(ch)
Definition: debug.h:106
PVOID MmAllocateMemoryWithType(SIZE_T MemorySize, TYPE_OF_MEMORY MemoryType)
Definition: mm.c:31
VOID UiMessageBox(_In_ PCSTR Format,...)
Definition: ui.c:359
#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 _In_
Definition: ms_sal.h:308
#define KIDTENTRY
Definition: ketypes.h:564
#define APIC_BASE
Definition: ketypes.h:339
#define KTSS
Definition: ketypes.h:1006
#define KGDT64_SYS_TSS
Definition: ketypes.h:138
#define KGDT64_R3_CODE
Definition: ketypes.h:137
#define KSEG0_BASE
Definition: ketypes.h:354
#define KGDT64_NULL
Definition: ketypes.h:132
#define MM_HAL_VA_START
Definition: ketypes.h:337
#define I386_TSS
Definition: ketypes.h:121
#define KGDT64_R0_CODE
Definition: ketypes.h:133
#define KGDT64_R3_DATA
Definition: ketypes.h:136
#define KGDT64_R3_CMCODE
Definition: ketypes.h:135
#define PKGDTENTRY
Definition: ketypes.h:523
#define KGDT64_R3_CMTEB
Definition: ketypes.h:139
#define KGDTENTRY
Definition: ketypes.h:522
#define KGDT64_R0_DATA
Definition: ketypes.h:134
#define MACHINE_TYPE_ISA
Definition: ketypes.h:113
#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
unsigned short USHORT
Definition: pedump.c:61
@ 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:571
USHORT Limit
Definition: ketypes.h:570
Definition: ketypes.h:844
union _LOADER_PARAMETER_BLOCK::@3369 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
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