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