c3917709b3237c9a44755b19602c421ea0df7a38
[reactos.git] / boot / freeldr / freeldr / ntldr / arch / i386 / winldr.c
1 /*
2 * PROJECT: EFI Windows Loader
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: boot/freeldr/freeldr/arch/i386/winldr.c
5 * PURPOSE: Memory related routines
6 * PROGRAMMERS: Aleksey Bragin (aleksey@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 // This is needed because headers define wrong one for ReactOS
19 #undef KIP0PCRADDRESS
20 #define KIP0PCRADDRESS 0xffdff000
21
22 #define SELFMAP_ENTRY 0x300
23
24 // This is needed only for SetProcessorContext routine
25 #pragma pack(2)
26 typedef struct
27 {
28 USHORT Limit;
29 ULONG Base;
30 } GDTIDT;
31 #pragma pack(4)
32
33 /* GLOBALS ***************************************************************/
34
35 PHARDWARE_PTE PDE;
36 PHARDWARE_PTE HalPageTable;
37
38 PUCHAR PhysicalPageTablesBuffer;
39 PUCHAR KernelPageTablesBuffer;
40 ULONG PhysicalPageTables;
41 ULONG KernelPageTables;
42
43 ULONG PcrBasePage;
44 ULONG TssBasePage;
45 PVOID GdtIdt;
46
47 /* FUNCTIONS **************************************************************/
48
49 static
50 BOOLEAN
51 MempAllocatePageTables(VOID)
52 {
53 ULONG NumPageTables, TotalSize;
54 PUCHAR Buffer;
55 // It's better to allocate PDE + PTEs contiguous
56
57 // Max number of entries = MaxPageNum >> 10
58 // FIXME: This is a number to describe ALL physical memory
59 // and windows doesn't expect ALL memory mapped...
60 NumPageTables = TotalPagesInLookupTable >> 10;
61
62 TRACE("NumPageTables = %d\n", NumPageTables);
63
64 // Allocate memory block for all these things:
65 // PDE, HAL mapping page table, physical mapping, kernel mapping
66 TotalSize = (1 + 1 + NumPageTables * 2) * MM_PAGE_SIZE;
67
68 // PDE+HAL+KernelPTEs == MemoryData
69 Buffer = MmAllocateMemoryWithType(TotalSize, LoaderMemoryData);
70
71 // Physical PTEs = FirmwareTemporary
72 PhysicalPageTablesBuffer = (PUCHAR)Buffer + TotalSize - NumPageTables*MM_PAGE_SIZE;
73 MmSetMemoryType(PhysicalPageTablesBuffer,
74 NumPageTables*MM_PAGE_SIZE,
75 LoaderFirmwareTemporary);
76
77 // This check is now redundant
78 if (Buffer + (TotalSize - NumPageTables*MM_PAGE_SIZE) !=
79 PhysicalPageTablesBuffer)
80 {
81 TRACE("There was a problem allocating two adjacent blocks of memory!");
82 }
83
84 if (Buffer == NULL || PhysicalPageTablesBuffer == NULL)
85 {
86 UiMessageBox("Impossible to allocate memory block for page tables!");
87 return FALSE;
88 }
89
90 // Zero all this memory block
91 RtlZeroMemory(Buffer, TotalSize);
92
93 // Set up pointers correctly now
94 PDE = (PHARDWARE_PTE)Buffer;
95
96 // Map the page directory at 0xC0000000 (maps itself)
97 PDE[SELFMAP_ENTRY].PageFrameNumber = (ULONG)PDE >> MM_PAGE_SHIFT;
98 PDE[SELFMAP_ENTRY].Valid = 1;
99 PDE[SELFMAP_ENTRY].Write = 1;
100
101 // The last PDE slot is allocated for HAL's memory mapping (Virtual Addresses 0xFFC00000 - 0xFFFFFFFF)
102 HalPageTable = (PHARDWARE_PTE)&Buffer[MM_PAGE_SIZE*1];
103
104 // Map it
105 PDE[1023].PageFrameNumber = (ULONG)HalPageTable >> MM_PAGE_SHIFT;
106 PDE[1023].Valid = 1;
107 PDE[1023].Write = 1;
108
109 // Store pointer to the table for easier access
110 KernelPageTablesBuffer = &Buffer[MM_PAGE_SIZE*2];
111
112 // Zero counters of page tables used
113 PhysicalPageTables = 0;
114 KernelPageTables = 0;
115
116 return TRUE;
117 }
118
119 static
120 VOID
121 MempAllocatePTE(ULONG Entry, PHARDWARE_PTE *PhysicalPT, PHARDWARE_PTE *KernelPT)
122 {
123 //Print(L"Creating PDE Entry %X\n", Entry);
124
125 // Identity mapping
126 *PhysicalPT = (PHARDWARE_PTE)&PhysicalPageTablesBuffer[PhysicalPageTables*MM_PAGE_SIZE];
127 PhysicalPageTables++;
128
129 PDE[Entry].PageFrameNumber = (ULONG)*PhysicalPT >> MM_PAGE_SHIFT;
130 PDE[Entry].Valid = 1;
131 PDE[Entry].Write = 1;
132
133 if (Entry+(KSEG0_BASE >> 22) > 1023)
134 {
135 TRACE("WARNING! Entry: %X > 1023\n", Entry+(KSEG0_BASE >> 22));
136 }
137
138 // Kernel-mode mapping
139 *KernelPT = (PHARDWARE_PTE)&KernelPageTablesBuffer[KernelPageTables*MM_PAGE_SIZE];
140 KernelPageTables++;
141
142 PDE[Entry+(KSEG0_BASE >> 22)].PageFrameNumber = ((ULONG)*KernelPT >> MM_PAGE_SHIFT);
143 PDE[Entry+(KSEG0_BASE >> 22)].Valid = 1;
144 PDE[Entry+(KSEG0_BASE >> 22)].Write = 1;
145 }
146
147 BOOLEAN
148 MempSetupPaging(IN PFN_NUMBER StartPage,
149 IN PFN_COUNT NumberOfPages,
150 IN BOOLEAN KernelMapping)
151 {
152 PHARDWARE_PTE PhysicalPT;
153 PHARDWARE_PTE KernelPT;
154 PFN_COUNT Entry, Page;
155
156 TRACE("MempSetupPaging: SP 0x%X, Number: 0x%X, Kernel: %s\n",
157 StartPage, NumberOfPages, KernelMapping ? "yes" : "no");
158
159 // HACK
160 if (StartPage+NumberOfPages >= 0x80000)
161 {
162 //
163 // We can't map this as it requires more than 1 PDE
164 // and in fact it's not possible at all ;)
165 //
166 //Print(L"skipping...\n");
167 return TRUE;
168 }
169
170 //
171 // Now actually set up the page tables for identity mapping
172 //
173 for (Page = StartPage; Page < StartPage + NumberOfPages; Page++)
174 {
175 Entry = Page >> 10;
176
177 if (((PULONG)PDE)[Entry] == 0)
178 {
179 MempAllocatePTE(Entry, &PhysicalPT, &KernelPT);
180 }
181 else
182 {
183 PhysicalPT = (PHARDWARE_PTE)(PDE[Entry].PageFrameNumber << MM_PAGE_SHIFT);
184 KernelPT = (PHARDWARE_PTE)(PDE[Entry+(KSEG0_BASE >> 22)].PageFrameNumber << MM_PAGE_SHIFT);
185 }
186
187 PhysicalPT[Page & 0x3ff].PageFrameNumber = Page;
188 PhysicalPT[Page & 0x3ff].Valid = (Page != 0);
189 PhysicalPT[Page & 0x3ff].Write = (Page != 0);
190
191 if (KernelMapping)
192 {
193 if (KernelPT[Page & 0x3ff].Valid) WARN("xxx already mapped \n");
194 KernelPT[Page & 0x3ff].PageFrameNumber = Page;
195 KernelPT[Page & 0x3ff].Valid = (Page != 0);
196 KernelPT[Page & 0x3ff].Write = (Page != 0);
197 }
198 }
199
200 return TRUE;
201 }
202
203 VOID
204 MempUnmapPage(PFN_NUMBER Page)
205 {
206 PHARDWARE_PTE KernelPT;
207 PFN_NUMBER Entry = (Page >> 10) + (KSEG0_BASE >> 22);
208
209 /* Don't unmap page directory or HAL entries */
210 if (Entry == SELFMAP_ENTRY || Entry == 1023)
211 return;
212
213 if (PDE[Entry].Valid)
214 {
215 KernelPT = (PHARDWARE_PTE)(PDE[Entry].PageFrameNumber << MM_PAGE_SHIFT);
216
217 if (KernelPT)
218 {
219 KernelPT[Page & 0x3ff].PageFrameNumber = 0;
220 KernelPT[Page & 0x3ff].Valid = 0;
221 KernelPT[Page & 0x3ff].Write = 0;
222 }
223 }
224 }
225
226 static
227 VOID
228 WinLdrpMapApic(VOID)
229 {
230 BOOLEAN LocalAPIC;
231 LARGE_INTEGER MsrValue;
232 ULONG APICAddress, CpuInfo[4];
233
234 /* Check if we have a local APIC */
235 __cpuid((int*)CpuInfo, 1);
236 LocalAPIC = (((CpuInfo[3] >> 9) & 1) != 0);
237
238 /* If there is no APIC, just return */
239 if (!LocalAPIC)
240 return;
241
242 /* Read the APIC Address */
243 MsrValue.QuadPart = __readmsr(0x1B);
244 APICAddress = (MsrValue.LowPart & 0xFFFFF000);
245
246 TRACE("Local APIC detected at address 0x%x\n",
247 APICAddress);
248
249 /* Map it */
250 HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].PageFrameNumber
251 = APICAddress >> MM_PAGE_SHIFT;
252 HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].Valid = 1;
253 HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].Write = 1;
254 HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].WriteThrough = 1;
255 HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].CacheDisable = 1;
256 }
257
258 static
259 BOOLEAN
260 WinLdrMapSpecialPages(void)
261 {
262
263 //VideoDisplayString(L"Hello from VGA, going into the kernel\n");
264 TRACE("HalPageTable: 0x%X\n", HalPageTable);
265
266 // Page Tables have been setup, make special handling for PCR and TSS
267 // (which is done in BlSetupFotNt in usual ntldr)
268 HalPageTable[(KI_USER_SHARED_DATA - 0xFFC00000) >> MM_PAGE_SHIFT].PageFrameNumber = PcrBasePage+1;
269 HalPageTable[(KI_USER_SHARED_DATA - 0xFFC00000) >> MM_PAGE_SHIFT].Valid = 1;
270 HalPageTable[(KI_USER_SHARED_DATA - 0xFFC00000) >> MM_PAGE_SHIFT].Write = 1;
271
272 HalPageTable[(KIP0PCRADDRESS - 0xFFC00000) >> MM_PAGE_SHIFT].PageFrameNumber = PcrBasePage;
273 HalPageTable[(KIP0PCRADDRESS - 0xFFC00000) >> MM_PAGE_SHIFT].Valid = 1;
274 HalPageTable[(KIP0PCRADDRESS - 0xFFC00000) >> MM_PAGE_SHIFT].Write = 1;
275
276 // Map APIC
277 WinLdrpMapApic();
278
279 // Map VGA memory
280 //VideoMemoryBase = MmMapIoSpace(0xb8000, 4000, MmNonCached);
281 //TRACE("VideoMemoryBase: 0x%X\n", VideoMemoryBase);
282
283 return TRUE;
284 }
285
286 #define ExtendedBIOSDataArea ((PULONG)0x740)
287 #define ExtendedBIOSDataSize ((PULONG)0x744)
288 #define RomFontPointers ((PULONG)0x700)
289
290 static
291 void WinLdrSetupSpecialDataPointers(VOID)
292 {
293 /* Get the address of the BIOS ROM fonts. Win 2003 videoprt reads these
294 values from address 0x700 .. 0x718 and store them in the registry
295 in HKLM\System\CurrentControlSet\Control\Wow\RomFontPointers */
296 MachVideoGetFontsFromFirmware(RomFontPointers);
297
298 /* Store address of the extended BIOS data area in 0x740 */
299 MachGetExtendedBIOSData(ExtendedBIOSDataArea, ExtendedBIOSDataSize);
300
301 if (*ExtendedBIOSDataArea == 0 && *ExtendedBIOSDataSize == 0)
302 {
303 WARN("Couldn't get address of extended BIOS data area\n");
304 }
305 else
306 {
307 TRACE("*ExtendedBIOSDataArea = 0x%lx\n", *ExtendedBIOSDataArea);
308 }
309 }
310
311 void WinLdrSetupMachineDependent(PLOADER_PARAMETER_BLOCK LoaderBlock)
312 {
313 ULONG TssSize;
314 //ULONG TssPages;
315 ULONG_PTR Pcr = 0;
316 ULONG_PTR Tss = 0;
317 ULONG BlockSize, NumPages;
318
319 LoaderBlock->u.I386.CommonDataArea = NULL; // Force No ABIOS support
320 LoaderBlock->u.I386.MachineType = MACHINE_TYPE_ISA;
321
322 /* Allocate 2 pages for PCR */
323 Pcr = (ULONG_PTR)MmAllocateMemoryWithType(2 * MM_PAGE_SIZE, LoaderStartupPcrPage);
324 PcrBasePage = Pcr >> MM_PAGE_SHIFT;
325
326 if (Pcr == 0)
327 {
328 UiMessageBox("Can't allocate PCR.");
329 return;
330 }
331
332 /* Allocate TSS */
333 TssSize = (sizeof(KTSS) + MM_PAGE_SIZE) & ~(MM_PAGE_SIZE - 1);
334 //TssPages = TssSize / MM_PAGE_SIZE;
335
336 Tss = (ULONG_PTR)MmAllocateMemoryWithType(TssSize, LoaderMemoryData);
337
338 TssBasePage = Tss >> MM_PAGE_SHIFT;
339
340 /* Allocate space for new GDT + IDT */
341 BlockSize = NUM_GDT*sizeof(KGDTENTRY) + NUM_IDT*sizeof(KIDTENTRY);//FIXME: Use GDT/IDT limits here?
342 NumPages = (BlockSize + MM_PAGE_SIZE - 1) >> MM_PAGE_SHIFT;
343 GdtIdt = (PKGDTENTRY)MmAllocateMemoryWithType(NumPages * MM_PAGE_SIZE, LoaderMemoryData);
344
345 if (GdtIdt == NULL)
346 {
347 UiMessageBox("Can't allocate pages for GDT+IDT!");
348 return;
349 }
350
351 /* Zero newly prepared GDT+IDT */
352 RtlZeroMemory(GdtIdt, NumPages << MM_PAGE_SHIFT);
353
354 // Before we start mapping pages, create a block of memory, which will contain
355 // PDE and PTEs
356 if (MempAllocatePageTables() == FALSE)
357 {
358 BugCheck("MempAllocatePageTables failed!\n");
359 }
360
361 /* Map stuff like PCR, KI_USER_SHARED_DATA and Apic */
362 WinLdrMapSpecialPages();
363
364 /* Set some special fields */
365 WinLdrSetupSpecialDataPointers();
366 }
367
368
369 VOID
370 WinLdrSetProcessorContext(void)
371 {
372 GDTIDT GdtDesc, IdtDesc, OldIdt;
373 PKGDTENTRY pGdt;
374 PKIDTENTRY pIdt;
375 USHORT Ldt = 0;
376 ULONG Pcr;
377 ULONG Tss;
378 //ULONG i;
379
380 Pcr = KIP0PCRADDRESS;
381 Tss = KSEG0_BASE | (TssBasePage << MM_PAGE_SHIFT);
382
383 TRACE("GDtIdt %p, Pcr %p, Tss 0x%08X\n",
384 GdtIdt, Pcr, Tss);
385
386 // Enable paging
387 //BS->ExitBootServices(ImageHandle,MapKey);
388
389 // Disable Interrupts
390 _disable();
391
392 // Re-initialize EFLAGS
393 __writeeflags(0);
394
395 // Set the PDBR
396 __writecr3((ULONG_PTR)PDE);
397
398 // Enable paging by modifying CR0
399 __writecr0(__readcr0() | CR0_PG);
400
401 // Kernel expects the PCR to be zero-filled on startup
402 // FIXME: Why zero it here when we can zero it right after allocation?
403 RtlZeroMemory((PVOID)Pcr, MM_PAGE_SIZE); //FIXME: Why zero only 1 page when we allocate 2?
404
405 // Get old values of GDT and IDT
406 Ke386GetGlobalDescriptorTable(&GdtDesc);
407 __sidt(&IdtDesc);
408
409 // Save old IDT
410 OldIdt.Base = IdtDesc.Base;
411 OldIdt.Limit = IdtDesc.Limit;
412
413 // Prepare new IDT+GDT
414 GdtDesc.Base = KSEG0_BASE | (ULONG_PTR)GdtIdt;
415 GdtDesc.Limit = NUM_GDT * sizeof(KGDTENTRY) - 1;
416 IdtDesc.Base = (ULONG)((PUCHAR)GdtDesc.Base + GdtDesc.Limit + 1);
417 IdtDesc.Limit = NUM_IDT * sizeof(KIDTENTRY) - 1;
418
419 // ========================
420 // Fill all descriptors now
421 // ========================
422
423 pGdt = (PKGDTENTRY)GdtDesc.Base;
424 pIdt = (PKIDTENTRY)IdtDesc.Base;
425
426 //
427 // Code selector (0x8)
428 // Flat 4Gb
429 //
430 pGdt[1].LimitLow = 0xFFFF;
431 pGdt[1].BaseLow = 0;
432 pGdt[1].HighWord.Bytes.BaseMid = 0;
433 pGdt[1].HighWord.Bytes.Flags1 = 0x9A;
434 pGdt[1].HighWord.Bytes.Flags2 = 0xCF;
435 pGdt[1].HighWord.Bytes.BaseHi = 0;
436
437 //
438 // Data selector (0x10)
439 // Flat 4Gb
440 //
441 pGdt[2].LimitLow = 0xFFFF;
442 pGdt[2].BaseLow = 0;
443 pGdt[2].HighWord.Bytes.BaseMid = 0;
444 pGdt[2].HighWord.Bytes.Flags1 = 0x92;
445 pGdt[2].HighWord.Bytes.Flags2 = 0xCF;
446 pGdt[2].HighWord.Bytes.BaseHi = 0;
447
448 //
449 // Selector (0x18)
450 // Flat 2Gb
451 //
452 pGdt[3].LimitLow = 0xFFFF;
453 pGdt[3].BaseLow = 0;
454 pGdt[3].HighWord.Bytes.BaseMid = 0;
455 pGdt[3].HighWord.Bytes.Flags1 = 0xFA;
456 pGdt[3].HighWord.Bytes.Flags2 = 0xCF;
457 pGdt[3].HighWord.Bytes.BaseHi = 0;
458
459 //
460 // Selector (0x20)
461 // Flat 2Gb
462 //
463 pGdt[4].LimitLow = 0xFFFF;
464 pGdt[4].BaseLow = 0;
465 pGdt[4].HighWord.Bytes.BaseMid = 0;
466 pGdt[4].HighWord.Bytes.Flags1 = 0xF2;
467 pGdt[4].HighWord.Bytes.Flags2 = 0xCF;
468 pGdt[4].HighWord.Bytes.BaseHi = 0;
469
470 //
471 // TSS Selector (0x28)
472 //
473 pGdt[5].LimitLow = 0x78-1; //FIXME: Check this
474 pGdt[5].BaseLow = (USHORT)(Tss & 0xffff);
475 pGdt[5].HighWord.Bytes.BaseMid = (UCHAR)((Tss >> 16) & 0xff);
476 pGdt[5].HighWord.Bytes.Flags1 = 0x89;
477 pGdt[5].HighWord.Bytes.Flags2 = 0x00;
478 pGdt[5].HighWord.Bytes.BaseHi = (UCHAR)((Tss >> 24) & 0xff);
479
480 //
481 // PCR Selector (0x30)
482 //
483 pGdt[6].LimitLow = 0x01;
484 pGdt[6].BaseLow = (USHORT)(Pcr & 0xffff);
485 pGdt[6].HighWord.Bytes.BaseMid = (UCHAR)((Pcr >> 16) & 0xff);
486 pGdt[6].HighWord.Bytes.Flags1 = 0x92;
487 pGdt[6].HighWord.Bytes.Flags2 = 0xC0;
488 pGdt[6].HighWord.Bytes.BaseHi = (UCHAR)((Pcr >> 24) & 0xff);
489
490 //
491 // Selector (0x38)
492 //
493 pGdt[7].LimitLow = 0xFFFF;
494 pGdt[7].BaseLow = 0;
495 pGdt[7].HighWord.Bytes.BaseMid = 0;
496 pGdt[7].HighWord.Bytes.Flags1 = 0xF3;
497 pGdt[7].HighWord.Bytes.Flags2 = 0x40;
498 pGdt[7].HighWord.Bytes.BaseHi = 0;
499
500 //
501 // Some BIOS stuff (0x40)
502 //
503 pGdt[8].LimitLow = 0xFFFF;
504 pGdt[8].BaseLow = 0x400;
505 pGdt[8].HighWord.Bytes.BaseMid = 0;
506 pGdt[8].HighWord.Bytes.Flags1 = 0xF2;
507 pGdt[8].HighWord.Bytes.Flags2 = 0x0;
508 pGdt[8].HighWord.Bytes.BaseHi = 0;
509
510 //
511 // Selector (0x48)
512 //
513 pGdt[9].LimitLow = 0;
514 pGdt[9].BaseLow = 0;
515 pGdt[9].HighWord.Bytes.BaseMid = 0;
516 pGdt[9].HighWord.Bytes.Flags1 = 0;
517 pGdt[9].HighWord.Bytes.Flags2 = 0;
518 pGdt[9].HighWord.Bytes.BaseHi = 0;
519
520 //
521 // Selector (0x50)
522 //
523 pGdt[10].LimitLow = 0xFFFF; //FIXME: Not correct!
524 pGdt[10].BaseLow = 0;
525 pGdt[10].HighWord.Bytes.BaseMid = 0x2;
526 pGdt[10].HighWord.Bytes.Flags1 = 0x89;
527 pGdt[10].HighWord.Bytes.Flags2 = 0;
528 pGdt[10].HighWord.Bytes.BaseHi = 0;
529
530 //
531 // Selector (0x58)
532 //
533 pGdt[11].LimitLow = 0xFFFF;
534 pGdt[11].BaseLow = 0;
535 pGdt[11].HighWord.Bytes.BaseMid = 0x2;
536 pGdt[11].HighWord.Bytes.Flags1 = 0x9A;
537 pGdt[11].HighWord.Bytes.Flags2 = 0;
538 pGdt[11].HighWord.Bytes.BaseHi = 0;
539
540 //
541 // Selector (0x60)
542 //
543 pGdt[12].LimitLow = 0xFFFF;
544 pGdt[12].BaseLow = 0; //FIXME: Maybe not correct, but noone cares
545 pGdt[12].HighWord.Bytes.BaseMid = 0x2;
546 pGdt[12].HighWord.Bytes.Flags1 = 0x92;
547 pGdt[12].HighWord.Bytes.Flags2 = 0;
548 pGdt[12].HighWord.Bytes.BaseHi = 0;
549
550 //
551 // Video buffer Selector (0x68)
552 //
553 pGdt[13].LimitLow = 0x3FFF;
554 pGdt[13].BaseLow = 0x8000;
555 pGdt[13].HighWord.Bytes.BaseMid = 0x0B;
556 pGdt[13].HighWord.Bytes.Flags1 = 0x92;
557 pGdt[13].HighWord.Bytes.Flags2 = 0;
558 pGdt[13].HighWord.Bytes.BaseHi = 0;
559
560 //
561 // Points to GDT (0x70)
562 //
563 pGdt[14].LimitLow = NUM_GDT*sizeof(KGDTENTRY) - 1;
564 pGdt[14].BaseLow = 0x7000;
565 pGdt[14].HighWord.Bytes.BaseMid = 0xFF;
566 pGdt[14].HighWord.Bytes.Flags1 = 0x92;
567 pGdt[14].HighWord.Bytes.Flags2 = 0;
568 pGdt[14].HighWord.Bytes.BaseHi = 0xFF;
569
570 //
571 // Some unused descriptors should go here
572 //
573
574 // Copy the old IDT
575 RtlCopyMemory(pIdt, (PVOID)OldIdt.Base, OldIdt.Limit + 1);
576
577 // Mask interrupts
578 //asm("cli\n"); // they are already masked before enabling paged mode
579
580 // Load GDT+IDT
581 Ke386SetGlobalDescriptorTable(&GdtDesc);
582 __lidt(&IdtDesc);
583
584 // Jump to proper CS and clear prefetch queue
585 #if defined(__GNUC__)
586 asm("ljmp $0x08, $1f\n"
587 "1:\n");
588 #elif defined(_MSC_VER)
589 /* We can't express the above in MASM so we use this far return instead */
590 __asm
591 {
592 push 8
593 push offset resume
594 retf
595 resume:
596 };
597 #else
598 #error
599 #endif
600
601 // Set SS selector
602 Ke386SetSs(0x10); // DataSelector=0x10
603
604 // Set DS and ES selectors
605 Ke386SetDs(0x10);
606 Ke386SetEs(0x10); // this is vital for rep stosd
607
608 // LDT = not used ever, thus set to 0
609 Ke386SetLocalDescriptorTable(Ldt);
610
611 // Load TSR
612 Ke386SetTr(KGDT_TSS);
613
614 // Clear GS
615 Ke386SetGs(0);
616
617 // Set FS to PCR
618 Ke386SetFs(0x30);
619
620 // Real end of the function, just for information
621 /* do not uncomment!
622 pop edi;
623 pop esi;
624 pop ebx;
625 mov esp, ebp;
626 pop ebp;
627 ret
628 */
629 }
630
631 #if DBG
632 VOID
633 MempDump(VOID)
634 {
635 PULONG PDE_Addr=(PULONG)PDE;//0xC0300000;
636 int i, j;
637
638 TRACE("\nPDE\n");
639
640 for (i=0; i<128; i++)
641 {
642 TRACE("0x%04X | ", i*8);
643
644 for (j=0; j<8; j++)
645 {
646 TRACE("0x%08X ", PDE_Addr[i*8+j]);
647 }
648
649 TRACE("\n");
650 }
651 }
652 #endif