ReactOS  0.4.14-dev-98-gb0d4763
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>
16 DBG_DEFAULT_CHANNEL(WINDOWS);
17 
18 //extern ULONG LoaderPagesSpanned;
19 
20 /* GLOBALS ***************************************************************/
21 
23 //PHARDWARE_PTE HalPageTable;
24 
28 
29 /* FUNCTIONS **************************************************************/
30 
31 static
32 BOOLEAN
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 
64 static
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 
90 static
91 BOOLEAN
93 {
94  PHARDWARE_PTE PpeBase, PdeBase, PteBase;
95  ULONG Index;
96 
98  PdeBase = MempGetOrCreatePageDir(PpeBase, VAtoPPI(VirtualAddress));
99  PteBase = MempGetOrCreatePageDir(PdeBase, VAtoPDI(VirtualAddress));
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 
121 BOOLEAN
123 {
124  PHARDWARE_PTE PpeBase, PdeBase, PteBase;
125  ULONG Index;
126 
128  if (!PxeBase[Index].Valid)
129  return FALSE;
130 
131  PpeBase = (PVOID)((ULONG64)(PxeBase[Index].PageFrameNumber) * PAGE_SIZE);
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 
149 static
152 {
153  PFN_NUMBER i;
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 
169 BOOLEAN
172  IN BOOLEAN KernelMapping)
173 {
174  TRACE(">>> MempSetupPaging(0x%lx, %ld, %p)\n",
176 
177  /* Identity mapping */
181  {
182  ERR("Failed to map pages %ld, %ld\n",
184  return FALSE;
185  }
186 
187  /* Kernel mapping */
188  if (KernelMapping)
189  {
193  {
194  ERR("Failed to map pages %ld, %ld\n",
196  return FALSE;
197  }
198  }
199 
200  return TRUE;
201 }
202 
203 VOID
205 {
206  // TRACE(">>> MempUnmapPage\n");
207 }
208 
209 static
210 VOID
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 
242 static
243 BOOLEAN
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 */
263  WinLdrpMapApic();
264 
265  /* Map the page tables for 4 MB HAL address space. */
267  PdeBase = MempGetOrCreatePageDir(PpeBase, VAtoPPI(MM_HAL_VA_START));
269  MempGetOrCreatePageDir(PdeBase, VAtoPDI(MM_HAL_VA_START + 2 * 1024 * 1024));
270 
271  return TRUE;
272 }
273 
274 static
275 VOID
276 Amd64SetupGdt(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 */
287  Entry = KiGetGdtEntry(GdtBase, KGDT64_R0_CODE);
288  *(PULONG64)Entry = 0x00209b0000000000ULL;
289 
290  /* Setup KGDT64_R0_DATA */
291  Entry = KiGetGdtEntry(GdtBase, KGDT64_R0_DATA);
292  *(PULONG64)Entry = 0x00cf93000000ffffULL;
293 
294  /* Setup KGDT64_R3_CMCODE */
296  *(PULONG64)Entry = 0x00cffb000000ffffULL;
297 
298  /* Setup KGDT64_R3_DATA */
299  Entry = KiGetGdtEntry(GdtBase, KGDT64_R3_DATA);
300  *(PULONG64)Entry = 0x00cff3000000ffffULL;
301 
302  /* Setup KGDT64_R3_CODE */
303  Entry = KiGetGdtEntry(GdtBase, KGDT64_R3_CODE);
304  *(PULONG64)Entry = 0x0020fb0000000000ULL;
305 
306  /* Setup KGDT64_R3_CMTEB */
307  Entry = KiGetGdtEntry(GdtBase, KGDT64_R3_CMTEB);
308  *(PULONG64)Entry = 0xff40f3fd50003c00ULL;
309 
310  /* Setup TSS entry */
311  Entry = KiGetGdtEntry(GdtBase, KGDT64_SYS_TSS);
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 
323 static
324 VOID
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 
347 VOID
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 */
389  Pcr = (ULONG_PTR)MmAllocateMemoryWithType(2 * MM_PAGE_SIZE, LoaderStartupPcrPage);
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
418  if (MempAllocatePageTables() == FALSE)
419  {
420  // FIXME: bugcheck
421  }
422 
423  /* Map stuff like PCR, KI_USER_SHARED_DATA and Apic */
425 }
426 
427 
428 VOID
430 {
431 }
ULONG64 Valid
Definition: mmtypes.h:66
static VOID Amd64SetupIdt(PVOID IdtBase)
Definition: winldr.c:325
#define KGDT64_R3_CODE
Definition: ketypes.h:76
VOID MempDump(VOID)
Definition: winldr.c:429
#define IN
Definition: typedefs.h:38
#define MM_HAL_VA_START
Definition: ketypes.h:256
BOOLEAN MempIsPageMapped(PVOID VirtualAddress)
Definition: winldr.c:122
#define TRUE
Definition: types.h:120
static PHARDWARE_PTE MempGetOrCreatePageDir(PHARDWARE_PTE PdeBase, ULONG Index)
Definition: winldr.c:66
#define PKGDTENTRY
Definition: ketypes.h:438
#define KTSS
Definition: ketypes.h:920
struct _Entry Entry
Definition: kefuncs.h:640
#define DbgPrint
Definition: loader.c:25
#define KIP0PCRADDRESS
Definition: winldr.c:20
static VOID Amd64SetupGdt(PVOID GdtBase, ULONG64 TssBase)
Definition: winldr.c:276
VOID WinLdrSetProcessorContext(void)
Definition: winldr.c:348
#define WARN(fmt,...)
Definition: debug.h:111
PHARDWARE_PTE PxeBase
Definition: winldr.c:22
VOID MempUnmapPage(PFN_NUMBER Page)
Definition: winldr.c:204
VOID FORCEINLINE KiInitGdtEntry(PKGDTENTRY64 Entry, ULONG64 Base, ULONG Size, UCHAR Type, UCHAR Dpl)
Definition: intrin_i.h:48
#define KGDT64_R3_CMTEB
Definition: ketypes.h:78
__INTRIN_INLINE void __lidt(void *Source)
Definition: intrin_x86.h:1915
BOOLEAN MempSetupPaging(IN PFN_NUMBER StartPage, IN PFN_NUMBER NumberOfPages, IN BOOLEAN KernelMapping)
Definition: winldr.c:170
ULONG_PTR PcrBasePage
Definition: winldr.c:26
union _LOADER_PARAMETER_BLOCK::@3256 u
#define KGDTENTRY
Definition: ketypes.h:437
PVOID Base
Definition: ketypes.h:486
#define APIC_BASE
Definition: mboot.c:45
USHORT Limit
Definition: ketypes.h:485
static BOOLEAN WinLdrMapSpecialPages(VOID)
Definition: winldr.c:244
uint32_t ULONG_PTR
Definition: typedefs.h:63
int WINAPI StartPage(_In_ HDC)
ULONG NumberOfPages
Definition: heap.h:214
__INTRIN_INLINE void __writecr3(unsigned int Data)
Definition: intrin_x86.h:1675
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
ULONG PFN_NUMBER
Definition: ke.h:8
#define KSEG0_BASE
Definition: ketypes.h:273
static PFN_NUMBER MempMapRangeOfPages(ULONG64 VirtualAddress, ULONG64 PhysicalAddress, PFN_NUMBER cPages)
Definition: winldr.c:151
DBG_DEFAULT_CHANNEL(WINDOWS)
__INTRIN_INLINE void __sidt(void *Destination)
Definition: intrin_x86.h:1920
#define KGDT64_R3_DATA
Definition: ketypes.h:75
VOID UiMessageBox(PCSTR Format,...)
Definition: ui.c:320
I386_LOADER_BLOCK I386
Definition: arc.h:515
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
void WinLdrSetupMachineDependent(PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: winldr.c:379
PPC_QUAL unsigned long long __readmsr()
Definition: intrin_ppc.h:741
#define VAtoPDI(va)
Definition: amd64.h:36
Definition: ketypes.h:789
ULONG_PTR TssBasePage
Definition: winldr.c:27
void * PVOID
Definition: retypes.h:9
ULONG MachineType
Definition: arc.h:407
#define TRACE(s)
Definition: solgame.cpp:4
#define VAtoPTI(va)
Definition: amd64.h:37
#define MACHINE_TYPE_ISA
Definition: ketypes.h:52
static const UCHAR Index[8]
Definition: usbohci.c:18
#define KGDT64_NULL
Definition: ketypes.h:71
#define KGDT64_R0_CODE
Definition: ketypes.h:72
#define NUM_IDT
Definition: winldr.h:17
unsigned __int64 ULONG64
Definition: imports.h:198
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS PhysicalAddress
Definition: iotypes.h:1061
ULONG64 PageFrameNumber
Definition: mmtypes.h:78
#define KGDT64_SYS_TSS
Definition: ketypes.h:77
PVOID MmAllocateMemoryWithType(SIZE_T MemorySize, TYPE_OF_MEMORY MemoryType)
Definition: mm.c:31
__INTRIN_INLINE void __writeeflags(uintptr_t Value)
Definition: intrin_x86.h:1550
#define KI_USER_SHARED_DATA
ULONG LowPart
Definition: typedefs.h:104
#define PAGE_SIZE
Definition: env_spec_w32.h:49
_In_ ULONG _In_ BOOLEAN _Must_inspect_result_ PVOID * VirtualAddress
Definition: ndis.h:3791
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
PVOID CommonDataArea
Definition: arc.h:406
#define ERR(fmt,...)
Definition: debug.h:109
#define PtrToPfn(p)
Definition: amd64.h:31
#define PXE_BASE
static BOOLEAN MempMapSinglePage(ULONG64 VirtualAddress, ULONG64 PhysicalAddress)
Definition: winldr.c:92
PPC_QUAL void __cpuid(int CPUInfo[], const int InfoType)
Definition: intrin_ppc.h:682
#define KIDTENTRY
Definition: ketypes.h:479
#define NUM_GDT
Definition: winldr.h:16
static VOID WinLdrpMapApic(VOID)
Definition: winldr.c:211
#define min(a, b)
Definition: monoChain.cc:55
#define I386_TSS
Definition: ketypes.h:60
ULONG64 Write
Definition: mmtypes.h:67
#define VAtoPXI(va)
Definition: amd64.h:34
void __cdecl _disable(void)
Definition: intrin_arm.h:365
unsigned int ULONG
Definition: retypes.h:1
#define KGDT64_R0_DATA
Definition: ketypes.h:73
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define ULONG_PTR
Definition: config.h:101
unsigned __int64 * PULONG64
Definition: imports.h:198
static const WCHAR SubDir[]
Definition: install.c:48
#define KGDT64_R3_CMCODE
Definition: ketypes.h:74
PVOID GdtIdt
Definition: winldr.c:25
#define VAtoPPI(va)
Definition: amd64.h:35
base of all file and directory entries
Definition: entries.h:82
static BOOLEAN MempAllocatePageTables(VOID)
Definition: winldr.c:33
FORCEINLINE PKGDTENTRY KiGetGdtEntry(IN PVOID pGdt, IN USHORT Selector)
Definition: winldr.c:69
LONGLONG QuadPart
Definition: typedefs.h:112