ReactOS 0.4.16-dev-588-gf07ea94
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 KI_USER_SHARED_DATA */
251 {
252 ERR("Could not map KI_USER_SHARED_DATA\n");
253 return FALSE;
254 }
255
256 /* Map the APIC page */
258
259 /* Map the page tables for 4 MB HAL address space. */
263 MempGetOrCreatePageDir(PdeBase, VAtoPDI(MM_HAL_VA_START + 2 * 1024 * 1024));
264
265 return TRUE;
266}
267
268static
269VOID
270Amd64SetupGdt(PVOID GdtBase, ULONG64 TssBase)
271{
273 KDESCRIPTOR GdtDesc;
274 TRACE("Amd64SetupGdt(GdtBase = %p, TssBase = %p)\n", GdtBase, TssBase);
275
276 /* Setup KGDT64_NULL */
277 Entry = KiGetGdtEntry(GdtBase, KGDT64_NULL);
278 *(PULONG64)Entry = 0x0000000000000000ULL;
279
280 /* Setup KGDT64_R0_CODE */
282 *(PULONG64)Entry = 0x00209b0000000000ULL;
283
284 /* Setup KGDT64_R0_DATA */
286 *(PULONG64)Entry = 0x00cf93000000ffffULL;
287
288 /* Setup KGDT64_R3_CMCODE */
290 *(PULONG64)Entry = 0x00cffb000000ffffULL;
291
292 /* Setup KGDT64_R3_DATA */
294 *(PULONG64)Entry = 0x00cff3000000ffffULL;
295
296 /* Setup KGDT64_R3_CODE */
298 *(PULONG64)Entry = 0x0020fb0000000000ULL;
299
300 /* Setup KGDT64_R3_CMTEB */
302 *(PULONG64)Entry = 0xff40f3fd50003c00ULL;
303
304 /* Setup TSS entry */
306 KiInitGdtEntry(Entry, TssBase, sizeof(KTSS), I386_TSS, 0);
307
308 /* Setup GDT descriptor */
309 GdtDesc.Base = GdtBase;
310 GdtDesc.Limit = NUM_GDT * sizeof(KGDTENTRY) - 1;
311
312 /* Set the new Gdt */
313 __lgdt(&GdtDesc.Limit);
314 TRACE("Leave Amd64SetupGdt()\n");
315}
316
317static
318VOID
320{
321 KDESCRIPTOR IdtDesc, OldIdt;
322 //ULONG Size;
323 TRACE("Amd64SetupIdt(IdtBase = %p)\n", IdtBase);
324
325 /* Get old IDT */
326 __sidt(&OldIdt.Limit);
327
328 /* Copy the old IDT */
329 //Size = min(OldIdt.Limit + 1, NUM_IDT * sizeof(KIDTENTRY));
330 //RtlCopyMemory(IdtBase, (PVOID)OldIdt.Base, Size);
331
332 /* Setup the new IDT descriptor */
333 IdtDesc.Base = IdtBase;
334 IdtDesc.Limit = NUM_IDT * sizeof(KIDTENTRY) - 1;
335
336 /* Set the new IDT */
337 __lidt(&IdtDesc.Limit);
338 TRACE("Leave Amd64SetupIdt()\n");
339}
340
341VOID
343 _In_ USHORT OperatingSystemVersion)
344{
345 TRACE("WinLdrSetProcessorContext\n");
346
347 /* Disable Interrupts */
348 _disable();
349
350 /* Re-initialize EFLAGS */
351 __writeeflags(0);
352
353 /* Set the new PML4 */
355
356 /* Get kernel mode address of gdt / idt */
358
359 /* Create gdt entries and load gdtr */
360 Amd64SetupGdt(GdtIdt, KSEG0_BASE | (TssBasePage << MM_PAGE_SHIFT));
361
362 /* Copy old Idt and set idtr */
364
365 /* LDT is unused */
366// __lldt(0);
367
368 /* Load TSR */
369 __ltr(KGDT64_SYS_TSS);
370
371 TRACE("leave WinLdrSetProcessorContext\n");
372}
373
375{
376 PVOID SharedUserDataAddress = NULL;
377 ULONG_PTR Tss = 0;
378 ULONG BlockSize, NumPages;
379
380 LoaderBlock->u.I386.CommonDataArea = (PVOID)DbgPrint; // HACK
381 LoaderBlock->u.I386.MachineType = MACHINE_TYPE_ISA;
382
383 /* Allocate 1 page for SharedUserData */
384 SharedUserDataAddress = MmAllocateMemoryWithType(MM_PAGE_SIZE, LoaderStartupPcrPage);
385 SharedUserDataPfn = (ULONG_PTR)SharedUserDataAddress >> MM_PAGE_SHIFT;
386 if (SharedUserDataAddress == NULL)
387 {
388 UiMessageBox("Can't allocate SharedUserData page.");
389 return;
390 }
391 RtlZeroMemory(SharedUserDataAddress, MM_PAGE_SIZE);
392
393 /* Allocate TSS */
394 BlockSize = (sizeof(KTSS) + MM_PAGE_SIZE) & ~(MM_PAGE_SIZE - 1);
396 TssBasePage = Tss >> MM_PAGE_SHIFT;
397
398 /* Allocate space for new GDT + IDT */
399 BlockSize = NUM_GDT * sizeof(KGDTENTRY) + NUM_IDT * sizeof(KIDTENTRY);
400 NumPages = (BlockSize + MM_PAGE_SIZE - 1) >> MM_PAGE_SHIFT;
401 GdtIdt = (PKGDTENTRY)MmAllocateMemoryWithType(NumPages * MM_PAGE_SIZE, LoaderMemoryData);
402 if (GdtIdt == NULL)
403 {
404 UiMessageBox("Can't allocate pages for GDT+IDT!");
405 return;
406 }
407
408 /* Zero newly prepared GDT+IDT */
409 RtlZeroMemory(GdtIdt, NumPages << MM_PAGE_SHIFT);
410
411 // Before we start mapping pages, create a block of memory, which will contain
412 // PDE and PTEs
414 {
415 // FIXME: bugcheck
416 }
417
418 /* Map KI_USER_SHARED_DATA, Apic and HAL space */
420}
421
422
423VOID
425{
426}
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:33
#define VAtoPXI(va)
Definition: amd64.h:30
#define PtrToPfn(p)
Definition: amd64.h:27
#define VAtoPPI(va)
Definition: amd64.h:31
#define VAtoPDI(va)
Definition: amd64.h:32
PVOID GdtIdt
Definition: winldr.c:26
VOID WinLdrSetProcessorContext(_In_ USHORT OperatingSystemVersion)
Definition: winldr.c:342
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
PFN_NUMBER SharedUserDataPfn
Definition: winldr.c:27
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
VOID MempUnmapPage(PFN_NUMBER Page)
Definition: winldr.c:205
static VOID Amd64SetupGdt(PVOID GdtBase, ULONG64 TssBase)
Definition: winldr.c:270
static PFN_NUMBER MempMapRangeOfPages(ULONG64 VirtualAddress, ULONG64 PhysicalAddress, PFN_NUMBER cPages)
Definition: winldr.c:152
static VOID Amd64SetupIdt(PVOID IdtBase)
Definition: winldr.c:319
VOID MempDump(VOID)
Definition: winldr.c:424
BOOLEAN MempIsPageMapped(PVOID VirtualAddress)
Definition: winldr.c:123
void WinLdrSetupMachineDependent(PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: winldr.c:374
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:1683
__INTRIN_INLINE void __lidt(void *Source)
Definition: intrin_x86.h:2041
__INTRIN_INLINE void __writecr3(unsigned int Data)
Definition: intrin_x86.h:1808
__INTRIN_INLINE void __sidt(void *Destination)
Definition: intrin_x86.h:2046
unsigned __int64 * PULONG64
Definition: imports.h:198
unsigned __int64 ULONG64
Definition: imports.h:198
#define KIDTENTRY
Definition: ketypes.h:573
#define APIC_BASE
Definition: ketypes.h:345
#define KTSS
Definition: ketypes.h:1015
#define KGDT64_SYS_TSS
Definition: ketypes.h:127
#define KGDT64_R3_CODE
Definition: ketypes.h:126
#define KSEG0_BASE
Definition: ketypes.h:360
#define KGDT64_NULL
Definition: ketypes.h:121
#define MM_HAL_VA_START
Definition: ketypes.h:343
#define I386_TSS
Definition: ketypes.h:110
#define KGDT64_R0_CODE
Definition: ketypes.h:122
#define KGDT64_R3_DATA
Definition: ketypes.h:125
#define KGDT64_R3_CMCODE
Definition: ketypes.h:124
#define PKGDTENTRY
Definition: ketypes.h:532
#define KGDT64_R3_CMTEB
Definition: ketypes.h:128
#define KGDTENTRY
Definition: ketypes.h:531
#define KGDT64_R0_DATA
Definition: ketypes.h:123
#define MACHINE_TYPE_ISA
Definition: ketypes.h:102
#define _In_
Definition: no_sal2.h:158
#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:1313
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:580
USHORT Limit
Definition: ketypes.h:579
Definition: ketypes.h:844
I386_LOADER_BLOCK I386
Definition: arc.h:562
union _LOADER_PARAMETER_BLOCK::@3376 u
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