[BOOTLIB]: Implement BlMmIsTranslationEnabled and MmMapPhysicalAddress. MmDefpMapPhys...
[reactos.git] / reactos / boot / environ / lib / mm / i386 / mmx86.c
1 /*
2 * COPYRIGHT: See COPYING.ARM in the top level directory
3 * PROJECT: ReactOS UEFI Boot Library
4 * FILE: boot/environ/lib/mm/i386/mmx86.c
5 * PURPOSE: Boot Library Memory Manager x86-Specific Code
6 * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include "bl.h"
12 #include "bcd.h"
13 #include "../../../../../ntoskrnl/include/internal/i386/mm.h"
14
15 /* DATA VARIABLES ************************************************************/
16
17 ULONG_PTR MmArchKsegBase;
18 ULONG_PTR MmArchKsegBias;
19 ULONG MmArchLargePageSize;
20 BL_ADDRESS_RANGE MmArchKsegAddressRange;
21 ULONG_PTR MmArchTopOfApplicationAddressSpace;
22 PHYSICAL_ADDRESS Mmx86SelfMapBase;
23 ULONG MmDeferredMappingCount;
24 PMMPTE MmPdpt;
25 PULONG MmArchReferencePage;
26 PVOID MmPteBase;
27 PVOID MmPdeBase;
28 ULONG MmArchReferencePageSize;
29
30 typedef VOID
31 (*PBL_MM_FLUSH_TLB) (
32 VOID
33 );
34
35 typedef VOID
36 (*PBL_MM_RELOCATE_SELF_MAP) (
37 VOID
38 );
39
40 typedef NTSTATUS
41 (*PBL_MM_MOVE_VIRTUAL_ADDRESS_RANGE) (
42 _In_ PVOID DestinationAddress,
43 _In_ PVOID SourceAddress,
44 _In_ ULONGLONG Size
45 );
46
47 typedef NTSTATUS
48 (*PBL_MM_ZERO_VIRTUAL_ADDRESS_RANGE) (
49 _In_ PVOID DestinationAddress,
50 _In_ ULONGLONG Size
51 );
52
53 typedef VOID
54 (*PBL_MM_DESTROY_SELF_MAP) (
55 VOID
56 );
57
58 typedef VOID
59 (*PBL_MM_FLUSH_TLB_ENTRY) (
60 _In_ PVOID VirtualAddress
61 );
62
63 typedef VOID
64 (*PBL_MM_FLUSH_TLB) (
65 VOID
66 );
67
68 typedef NTSTATUS
69 (*PBL_MM_UNMAP_VIRTUAL_ADDRESS) (
70 _In_ PVOID VirtualAddress,
71 _In_ ULONG Size
72 );
73
74 typedef NTSTATUS
75 (*PBL_MM_REMAP_VIRTUAL_ADDRESS) (
76 _In_ PPHYSICAL_ADDRESS PhysicalAddress,
77 _Out_ PVOID VirtualAddress,
78 _In_ ULONG Size,
79 _In_ ULONG CacheAttributes
80 );
81
82 typedef NTSTATUS
83 (*PBL_MM_MAP_PHYSICAL_ADDRESS) (
84 _In_ PPHYSICAL_ADDRESS PhysicalAddress,
85 _Out_ PVOID VirtualAddress,
86 _In_ ULONG Size,
87 _In_ ULONG CacheAttributes
88 );
89
90 typedef BOOLEAN
91 (*PBL_MM_TRANSLATE_VIRTUAL_ADDRESS) (
92 _In_ PVOID VirtualAddress,
93 _Out_ PPHYSICAL_ADDRESS PhysicalAddress,
94 _Out_opt_ PULONG CacheAttributes
95 );
96
97 PBL_MM_TRANSLATE_VIRTUAL_ADDRESS Mmx86TranslateVirtualAddress;
98 PBL_MM_MAP_PHYSICAL_ADDRESS Mmx86MapPhysicalAddress;
99 PBL_MM_REMAP_VIRTUAL_ADDRESS Mmx86RemapVirtualAddress;
100 PBL_MM_UNMAP_VIRTUAL_ADDRESS Mmx86UnmapVirtualAddress;
101 PBL_MM_FLUSH_TLB Mmx86FlushTlb;
102 PBL_MM_FLUSH_TLB_ENTRY Mmx86FlushTlbEntry;
103 PBL_MM_DESTROY_SELF_MAP Mmx86DestroySelfMap;
104
105 PBL_MM_RELOCATE_SELF_MAP BlMmRelocateSelfMap;
106 PBL_MM_FLUSH_TLB BlMmFlushTlb;
107 PBL_MM_MOVE_VIRTUAL_ADDRESS_RANGE BlMmMoveVirtualAddressRange;
108 PBL_MM_ZERO_VIRTUAL_ADDRESS_RANGE BlMmZeroVirtualAddressRange;
109
110 PBL_MM_FLUSH_TLB Mmx86FlushTlb;
111
112 /* FUNCTIONS *****************************************************************/
113
114 VOID
115 MmArchNullFunction (
116 VOID
117 )
118 {
119 /* Nothing to do */
120 return;
121 }
122
123 VOID
124 MmDefRelocateSelfMap (
125 VOID
126 )
127 {
128 if (MmPteBase != (PVOID)PTE_BASE)
129 {
130 EfiPrintf(L"Supposed to relocate CR3\r\n");
131 }
132 }
133
134 NTSTATUS
135 MmDefMoveVirtualAddressRange (
136 _In_ PVOID DestinationAddress,
137 _In_ PVOID SourceAddress,
138 _In_ ULONGLONG Size
139 )
140 {
141 EfiPrintf(L"Supposed to move shit\r\n");
142 return STATUS_NOT_IMPLEMENTED;
143 }
144
145 NTSTATUS
146 MmDefZeroVirtualAddressRange (
147 _In_ PVOID DestinationAddress,
148 _In_ ULONGLONG Size
149 )
150 {
151 EfiPrintf(L"Supposed to zero shit\r\n");
152 return STATUS_NOT_IMPLEMENTED;
153 }
154
155 NTSTATUS
156 Mmx86pMapMemoryRegions (
157 _In_ ULONG Phase,
158 _In_ PBL_MEMORY_DATA MemoryData
159 )
160 {
161 BOOLEAN DoDeferred;
162
163 /* In phase 1 we don't initialize deferred mappings*/
164 if (Phase == 1)
165 {
166 DoDeferred = 0;
167 }
168 else
169 {
170 /* Don't do anything if there's nothing to initialize */
171 if (!MmDeferredMappingCount)
172 {
173 return STATUS_SUCCESS;
174 }
175
176 DoDeferred = 1;
177 }
178
179 if (DoDeferred)
180 {
181 EfiPrintf(L"Deferred todo\r\n");
182 }
183
184 EfiPrintf(L"Phase 1 TODO\r\n");
185 return STATUS_NOT_IMPLEMENTED;
186 }
187
188 BOOLEAN
189 MmArchTranslateVirtualAddress (
190 _In_ PVOID VirtualAddress,
191 _Out_opt_ PPHYSICAL_ADDRESS PhysicalAddress,
192 _Out_opt_ PULONG CachingFlags
193 )
194 {
195 PBL_MEMORY_DESCRIPTOR Descriptor;
196
197 /* Check if paging is on */
198 if ((CurrentExecutionContext) &&
199 (CurrentExecutionContext->ContextFlags & BL_CONTEXT_PAGING_ON))
200 {
201 /* Yes -- we have to translate this from virtual */
202 return Mmx86TranslateVirtualAddress(VirtualAddress,
203 PhysicalAddress,
204 CachingFlags);
205 }
206
207 /* Look in all descriptors except truncated and firmware ones */
208 Descriptor = MmMdFindDescriptor(BL_MM_INCLUDE_NO_FIRMWARE_MEMORY &
209 ~BL_MM_INCLUDE_TRUNCATED_MEMORY,
210 BL_MM_REMOVE_PHYSICAL_REGION_FLAG,
211 (ULONG_PTR)VirtualAddress >> PAGE_SHIFT);
212
213 /* Return the virtual address as the physical address */
214 if (PhysicalAddress)
215 {
216 PhysicalAddress->HighPart = 0;
217 PhysicalAddress->LowPart = (ULONG_PTR)VirtualAddress;
218 }
219
220 /* There's no caching on physical memory */
221 if (CachingFlags)
222 {
223 *CachingFlags = 0;
224 }
225
226 /* Success is if we found a descriptor */
227 return Descriptor != NULL;
228 }
229
230 VOID
231 MmDefpDestroySelfMap (
232 VOID
233 )
234 {
235 EfiPrintf(L"No destroy\r\n");
236 }
237
238 VOID
239 MmDefpFlushTlbEntry (
240 _In_ PVOID VirtualAddress
241 )
242 {
243 /* Flush the TLB */
244 __invlpg(VirtualAddress);
245 }
246
247 VOID
248 MmDefpFlushTlb (
249 VOID
250 )
251 {
252 /* Flush the TLB */
253 __writecr3(__readcr3());
254 }
255
256 NTSTATUS
257 MmDefpUnmapVirtualAddress (
258 _In_ PVOID VirtualAddress,
259 _In_ ULONG Size
260 )
261 {
262 EfiPrintf(L"No unmap\r\n");
263 return STATUS_NOT_IMPLEMENTED;
264 }
265
266 NTSTATUS
267 MmDefpRemapVirtualAddress (
268 _In_ PPHYSICAL_ADDRESS PhysicalAddress,
269 _Out_ PVOID VirtualAddress,
270 _In_ ULONG Size,
271 _In_ ULONG CacheAttributes
272 )
273 {
274 EfiPrintf(L"No remap\r\n");
275 return STATUS_NOT_IMPLEMENTED;
276 }
277
278 NTSTATUS
279 MmDefpMapPhysicalAddress (
280 _In_ PPHYSICAL_ADDRESS PhysicalAddress,
281 _Out_ PVOID VirtualAddress,
282 _In_ ULONG Size,
283 _In_ ULONG CacheAttributes
284 )
285 {
286 EfiPrintf(L"No map\r\n");
287 return STATUS_NOT_IMPLEMENTED;
288 }
289
290 BOOLEAN
291 MmDefpTranslateVirtualAddress (
292 _In_ PVOID VirtualAddress,
293 _Out_ PPHYSICAL_ADDRESS PhysicalAddress,
294 _Out_opt_ PULONG CacheAttributes
295 )
296 {
297 EfiPrintf(L"No translate\r\n");
298 return FALSE;
299 }
300
301 NTSTATUS
302 MmSelectMappingAddress (
303 _Out_ PVOID* MappingAddress,
304 _In_ ULONGLONG Size,
305 _In_ ULONG AllocationAttributes,
306 _In_ ULONG Flags,
307 _In_ PHYSICAL_ADDRESS PhysicalAddress
308 )
309 {
310 /* Are we in physical mode? */
311 if (MmTranslationType == BlNone)
312 {
313 /* Just return the physical address as the mapping address */
314 *MappingAddress = (PVOID)PhysicalAddress.LowPart;
315 return STATUS_SUCCESS;
316 }
317
318 /* We don't support virtual memory yet @TODO */
319 #ifdef _MSC_VER // Fuck gcc.
320 EfiPrintf(L"not yet implemented in " __FUNCTION__ "\r\n");
321 EfiStall(1000000);
322 #endif
323 return STATUS_NOT_IMPLEMENTED;
324 }
325
326 BOOLEAN
327 BlMmIsTranslationEnabled (
328 VOID
329 )
330 {
331 /* Return if paging is on */
332 return ((CurrentExecutionContext) &&
333 (CurrentExecutionContext->Mode & BL_CONTEXT_PAGING_ON));
334 }
335
336 NTSTATUS
337 MmMapPhysicalAddress (
338 _Inout_ PPHYSICAL_ADDRESS PhysicalAddressPtr,
339 _Inout_ PVOID* VirtualAddressPtr,
340 _Inout_ PULONGLONG SizePtr,
341 _In_ ULONG CacheAttributes
342 )
343 {
344 ULONGLONG Size, TotalSize;
345 ULONGLONG PhysicalAddress;
346 PVOID VirtualAddress;
347 PHYSICAL_ADDRESS TranslatedAddress;
348 ULONG_PTR CurrentAddress, VirtualAddressEnd;
349 NTSTATUS Status;
350
351 /* Fail if any parameters are missing */
352 if (!(PhysicalAddressPtr) || !(VirtualAddressPtr) || !(SizePtr))
353 {
354 return STATUS_INVALID_PARAMETER;
355 }
356
357 /* Fail if the size is over 32-bits */
358 Size = *SizePtr;
359 if (Size > 0xFFFFFFFF)
360 {
361 return STATUS_INVALID_PARAMETER;
362 }
363
364 /* Nothing to do if we're in physical mode */
365 if (MmTranslationType == BlNone)
366 {
367 return STATUS_SUCCESS;
368 }
369
370 /* Can't use virtual memory in real mode */
371 if (CurrentExecutionContext->Mode == BlRealMode)
372 {
373 return STATUS_UNSUCCESSFUL;
374 }
375
376 /* Capture the current virtual and physical addresses */
377 VirtualAddress = *VirtualAddressPtr;
378 PhysicalAddress = PhysicalAddressPtr->QuadPart;
379
380 /* Check if a physical address was requested */
381 if (PhysicalAddress != 0xFFFFFFFF)
382 {
383 /* Round down the base addresses */
384 PhysicalAddress = PAGE_ROUND_DOWN(PhysicalAddress);
385 VirtualAddress = (PVOID)PAGE_ROUND_DOWN(VirtualAddress);
386
387 /* Round up the size */
388 TotalSize = ROUND_TO_PAGES(PhysicalAddressPtr->QuadPart -
389 PhysicalAddress +
390 Size);
391
392 /* Loop every virtual page */
393 CurrentAddress = (ULONG_PTR)VirtualAddress;
394 VirtualAddressEnd = CurrentAddress + TotalSize - 1;
395 while (CurrentAddress < VirtualAddressEnd)
396 {
397 /* Get the physical page of this virtual page */
398 if (MmArchTranslateVirtualAddress((PVOID)CurrentAddress,
399 &TranslatedAddress,
400 &CacheAttributes))
401 {
402 /* Make sure the physical page of the virtual page, matches our page */
403 if (TranslatedAddress.QuadPart !=
404 (PhysicalAddress +
405 (CurrentAddress - (ULONG_PTR)VirtualAddress)))
406 {
407 /* There is an existing virtual mapping for a different address */
408 EfiPrintf(L"Existing mapping exists: %lx vs %lx\r\n",
409 TranslatedAddress.QuadPart,
410 PhysicalAddress + (CurrentAddress - (ULONG_PTR)VirtualAddress));
411 return STATUS_INVALID_PARAMETER;
412 }
413 }
414
415 /* Try the next one */
416 CurrentAddress += PAGE_SIZE;
417 }
418 }
419
420 /* Aactually do the mapping */
421 TranslatedAddress.QuadPart = PhysicalAddress;
422 Status = Mmx86MapPhysicalAddress(&TranslatedAddress,
423 VirtualAddress,
424 Size,
425 CacheAttributes);
426 if (!NT_SUCCESS(Status))
427 {
428 EfiPrintf(L"Failed to map!: %lx\r\n", Status);
429 return Status;
430 }
431
432 /* Return aligned/fixed up output parameters */
433 PhysicalAddressPtr->QuadPart = PhysicalAddress;
434 *VirtualAddressPtr = VirtualAddress;
435 *SizePtr = Size;
436
437 /* Flush the TLB if paging is enabled */
438 if (BlMmIsTranslationEnabled())
439 {
440 Mmx86FlushTlb();
441 }
442
443 /* All good! */
444 return STATUS_SUCCESS;
445 }
446
447 NTSTATUS
448 Mmx86MapInitStructure (
449 _In_ PVOID VirtualAddress,
450 _In_ ULONGLONG Size,
451 _In_ PHYSICAL_ADDRESS PhysicalAddress
452 )
453 {
454 NTSTATUS Status;
455
456 /* Make a virtual mapping for this physical address */
457 Status = MmMapPhysicalAddress(&PhysicalAddress, &VirtualAddress, &Size, 0);
458 if (!NT_SUCCESS(Status))
459 {
460 return Status;
461 }
462
463 /* Nothing else to do if we're not in paging mode */
464 if (MmTranslationType == BlNone)
465 {
466 return STATUS_SUCCESS;
467 }
468
469 /* Otherwise, remove this region from the list of free virtual ranges */
470 Status = MmMdRemoveRegionFromMdlEx(&MmMdlFreeVirtual,
471 BL_MM_REMOVE_VIRTUAL_REGION_FLAG,
472 (ULONG_PTR)VirtualAddress >> PAGE_SHIFT,
473 Size >> PAGE_SHIFT,
474 0);
475 if (!NT_SUCCESS(Status))
476 {
477 /* Unmap the address if that failed */
478 MmUnmapVirtualAddress(&VirtualAddress, &Size);
479 }
480
481 /* Return back to caller */
482 return Status;
483 }
484
485 NTSTATUS
486 Mmx86InitializeMemoryMap (
487 _In_ ULONG Phase,
488 _In_ PBL_MEMORY_DATA MemoryData
489 )
490 {
491 ULONG ImageSize;
492 PVOID ImageBase;
493 KDESCRIPTOR Gdt, Idt;
494 NTSTATUS Status;
495 PHYSICAL_ADDRESS PhysicalAddress;
496
497 /* If this is phase 2, map the memory regions */
498 if (Phase != 1)
499 {
500 return Mmx86pMapMemoryRegions(Phase, MemoryData);
501 }
502
503 /* Get the application image base/size */
504 Status = BlGetApplicationBaseAndSize(&ImageBase, &ImageSize);
505 if (!NT_SUCCESS(Status))
506 {
507 return Status;
508 }
509
510 /* Map the image back at the same place */
511 PhysicalAddress.QuadPart = (ULONG_PTR)ImageBase;
512 Status = Mmx86MapInitStructure(ImageBase, ImageSize, PhysicalAddress);
513 if (!NT_SUCCESS(Status))
514 {
515 return Status;
516 }
517
518 /* Map the first 4MB of memory */
519 PhysicalAddress.QuadPart = 0;
520 Status = Mmx86MapInitStructure(NULL, 4 * 1024 * 1024, PhysicalAddress);
521 if (!NT_SUCCESS(Status))
522 {
523 return Status;
524 }
525
526 /* Map the GDT */
527 _sgdt(&Gdt.Limit);
528 PhysicalAddress.QuadPart = Gdt.Base;
529 Status = Mmx86MapInitStructure((PVOID)Gdt.Base, Gdt.Limit + 1, PhysicalAddress);
530 if (!NT_SUCCESS(Status))
531 {
532 return Status;
533 }
534
535 /* Map the IDT */
536 __sidt(&Idt.Limit);
537 PhysicalAddress.QuadPart = Idt.Base;
538 Status = Mmx86MapInitStructure((PVOID)Idt.Base, Idt.Limit + 1, PhysicalAddress);
539 if (!NT_SUCCESS(Status))
540 {
541 return Status;
542 }
543
544 /* Map the reference page */
545 PhysicalAddress.QuadPart = (ULONG_PTR)MmArchReferencePage;
546 Status = Mmx86MapInitStructure(MmArchReferencePage,
547 MmArchReferencePageSize,
548 PhysicalAddress);
549 if (!NT_SUCCESS(Status))
550 {
551 return Status;
552 }
553
554 /* More to do */
555 EfiPrintf(L"VM more work\r\n");
556 return STATUS_NOT_IMPLEMENTED;
557 }
558
559 NTSTATUS
560 MmDefInitializeTranslation (
561 _In_ PBL_MEMORY_DATA MemoryData,
562 _In_ BL_TRANSLATION_TYPE TranslationType
563 )
564 {
565 NTSTATUS Status;
566 PHYSICAL_ADDRESS PhysicalAddress;
567 ULONG PdeIndex;
568
569 /* Set the global function pointers for memory translation */
570 Mmx86TranslateVirtualAddress = MmDefpTranslateVirtualAddress;
571 Mmx86MapPhysicalAddress = MmDefpMapPhysicalAddress;
572 Mmx86UnmapVirtualAddress = MmDefpUnmapVirtualAddress;
573 Mmx86RemapVirtualAddress = MmDefpRemapVirtualAddress;
574 Mmx86FlushTlb = MmDefpFlushTlb;
575 Mmx86FlushTlbEntry = MmDefpFlushTlbEntry;
576 Mmx86DestroySelfMap = MmDefpDestroySelfMap;
577
578 /* Check what mode we're currently in */
579 if (TranslationType == BlVirtual)
580 {
581 EfiPrintf(L"Virtual->Virtual not yet supported\r\n");
582 return STATUS_NOT_IMPLEMENTED;
583 }
584 else if (TranslationType != BlNone)
585 {
586 /* Not even Windows supports PAE->Virtual downgrade */
587 return STATUS_NOT_IMPLEMENTED;
588 }
589
590 /* The None->Virtual case */
591 MmPdpt = NULL;
592 Mmx86SelfMapBase.QuadPart = 0;
593 MmArchReferencePage = NULL;
594
595 /* Truncate all memory above 4GB so that we don't use it @TODO: FIXME */
596 EfiPrintf(L"Warning: not truncating > 4GB memory. Don't boot with more than 4GB of RAM!\r\n");
597 //Status = MmPaTruncateMemory(0x100000);
598 Status = STATUS_SUCCESS;
599 if (!NT_SUCCESS(Status))
600 {
601 goto Quickie;
602 }
603
604 /* Allocate a page directory */
605 Status = MmPapAllocatePhysicalPagesInRange(&PhysicalAddress,
606 BlLoaderPageDirectory,
607 1,
608 0,
609 0,
610 &MmMdlUnmappedAllocated,
611 0,
612 0);
613 if (!NT_SUCCESS(Status))
614 {
615 goto Quickie;
616 }
617
618 /* Zero out the page directory */
619 MmPdpt = (PVOID)PhysicalAddress.LowPart;
620 RtlZeroMemory(MmPdpt, PAGE_SIZE);
621
622 /* Set the page size */
623 MmArchReferencePageSize = PAGE_SIZE;
624
625 /* Allocate the self-map page */
626 Status = MmPapAllocatePhysicalPagesInRange(&PhysicalAddress,
627 BlLoaderReferencePage,
628 1,
629 0,
630 0,
631 &MmMdlUnmappedAllocated,
632 0,
633 0);
634 if (!NT_SUCCESS(Status))
635 {
636 goto Quickie;
637 }
638
639 /* Set the reference page */
640 MmArchReferencePage = (PVOID)PhysicalAddress.LowPart;
641
642 /* Zero it out */
643 RtlZeroMemory(MmArchReferencePage, MmArchReferencePageSize);
644
645 /* Allocate 4MB worth of self-map pages */
646 Status = MmPaReserveSelfMapPages(&Mmx86SelfMapBase,
647 (4 * 1024 * 1024) >> PAGE_SHIFT,
648 (4 * 1024 * 1024) >> PAGE_SHIFT);
649 if (!NT_SUCCESS(Status))
650 {
651 goto Quickie;
652 }
653
654 /* Zero them out */
655 RtlZeroMemory((PVOID)Mmx86SelfMapBase.LowPart, 4 * 1024 * 1024);
656 EfiPrintf(L"PDPT at 0x%p Reference Page at 0x%p Self-map at 0x%p\r\n",
657 MmPdpt, MmArchReferencePage, Mmx86SelfMapBase.LowPart);
658
659 /* Align PTE base to 4MB region */
660 MmPteBase = (PVOID)(Mmx86SelfMapBase.LowPart & ~0x3FFFFF);
661
662 /* The PDE is the PTE of the PTE base */
663 MmPdeBase = MiAddressToPte(MmPteBase);
664 PdeIndex = MiGetPdeOffset(MmPdeBase);
665 MmPdpt[PdeIndex].u.Hard.Valid = 1;
666 MmPdpt[PdeIndex].u.Hard.Write = 1;
667 MmPdpt[PdeIndex].u.Hard.PageFrameNumber = (ULONG_PTR)MmPdpt >> PAGE_SHIFT;
668 MmArchReferencePage[PdeIndex]++;
669
670 /* Remove PTE_BASE from free virtual memory */
671 Status = MmMdRemoveRegionFromMdlEx(&MmMdlFreeVirtual,
672 BL_MM_REMOVE_VIRTUAL_REGION_FLAG,
673 PTE_BASE >> PAGE_SHIFT,
674 (4 * 1024 * 1024) >> PAGE_SHIFT,
675 0);
676 if (!NT_SUCCESS(Status))
677 {
678 goto Quickie;
679 }
680
681 /* Remove HAL_HEAP from free virtual memory */
682 Status = MmMdRemoveRegionFromMdlEx(&MmMdlFreeVirtual,
683 BL_MM_REMOVE_VIRTUAL_REGION_FLAG,
684 MM_HAL_VA_START >> PAGE_SHIFT,
685 (4 * 1024 * 1024) >> PAGE_SHIFT,
686 0);
687 if (!NT_SUCCESS(Status))
688 {
689 goto Quickie;
690 }
691
692 /* Initialize the virtual->physical memory mappings */
693 Status = Mmx86InitializeMemoryMap(1, MemoryData);
694 if (!NT_SUCCESS(Status))
695 {
696 goto Quickie;
697 }
698
699 EfiPrintf(L"Ready to turn on motherfucking paging, brah!\r\n");
700 Status = STATUS_NOT_IMPLEMENTED;
701
702 Quickie:
703 /* Free reference page if we allocated it */
704 if (MmArchReferencePage)
705 {
706 PhysicalAddress.QuadPart = (ULONG_PTR)MmArchReferencePage;
707 BlMmFreePhysicalPages(PhysicalAddress);
708 }
709
710 /* Free page directory if we allocated it */
711 if (MmPdpt)
712 {
713 PhysicalAddress.QuadPart = (ULONG_PTR)MmPdpt;
714 BlMmFreePhysicalPages(PhysicalAddress);
715 }
716
717 /* Free the self map if we allocated it */
718 if (Mmx86SelfMapBase.QuadPart)
719 {
720 MmPaReleaseSelfMapPages(Mmx86SelfMapBase);
721 }
722
723 /* All done */
724 return Status;
725 }
726
727 NTSTATUS
728 MmArchInitialize (
729 _In_ ULONG Phase,
730 _In_ PBL_MEMORY_DATA MemoryData,
731 _In_ BL_TRANSLATION_TYPE TranslationType,
732 _In_ BL_TRANSLATION_TYPE RequestedTranslationType
733 )
734 {
735 NTSTATUS Status;
736 ULONGLONG IncreaseUserVa, PerfCounter, CpuRandom;
737 INT CpuInfo[4];
738
739 /* For phase 2, just map deferred regions */
740 if (Phase != 1)
741 {
742 return Mmx86pMapMemoryRegions(2, MemoryData);
743 }
744
745 /* What translation type are we switching to? */
746 switch (RequestedTranslationType)
747 {
748 /* Physical memory */
749 case BlNone:
750
751 /* Initialize everything to default/null values */
752 MmArchLargePageSize = 1;
753 MmArchKsegBase = 0;
754 MmArchKsegBias = 0;
755 MmArchKsegAddressRange.Minimum = 0;
756 MmArchKsegAddressRange.Maximum = (ULONGLONG)~0;
757 MmArchTopOfApplicationAddressSpace = 0;
758 Mmx86SelfMapBase.QuadPart = 0;
759
760 /* Set stub functions */
761 BlMmRelocateSelfMap = MmArchNullFunction;
762 BlMmFlushTlb = MmArchNullFunction;
763
764 /* Set success */
765 Status = STATUS_SUCCESS;
766 break;
767
768 case BlVirtual:
769
770 /* Set the large page size to 1024 pages (4MB) */
771 MmArchLargePageSize = (4 * 1024 * 1024) / PAGE_SIZE;
772
773 /* Check if /USERVA option was used */
774 Status = BlGetBootOptionInteger(BlpApplicationEntry.BcdData,
775 BcdOSLoaderInteger_IncreaseUserVa,
776 &IncreaseUserVa);
777 if (NT_SUCCESS(Status) && (IncreaseUserVa))
778 {
779 /* Yes -- load the kernel at 0xE0000000 instead */
780 MmArchKsegBase = 0xE0000000;
781 }
782 else
783 {
784 /* Nope, load at the standard 2GB split */
785 MmArchKsegBase = 0x80000000;
786 }
787
788 /* Check if CPUID 01h is supported */
789 CpuRandom = 0;
790 if (BlArchIsCpuIdFunctionSupported(1))
791 {
792 /* Call it */
793 BlArchCpuId(1, 0, CpuInfo);
794
795 /* Check if RDRAND is supported */
796 if (CpuInfo[2] & 0x40000000)
797 {
798 EfiPrintf(L"Your CPU can do RDRAND! Good for you!\r\n");
799 CpuRandom = 0;
800 }
801 }
802
803 /* Read the TSC */
804 PerfCounter = BlArchGetPerformanceCounter();
805 PerfCounter >>= 4;
806 _rotl16(PerfCounter, 5);
807
808 /* Set the address range */
809 MmArchKsegAddressRange.Minimum = 0;
810 MmArchKsegAddressRange.Maximum = (ULONGLONG)~0;
811
812 /* Set the KASLR bias */
813 MmArchKsegBias = ((PerfCounter ^ CpuRandom) & 0xFFF) << 12;
814 MmArchKsegBias = 0;
815 MmArchKsegBase += MmArchKsegBias;
816
817 /* Set the kernel range */
818 MmArchKsegAddressRange.Minimum = MmArchKsegBase;
819 MmArchKsegAddressRange.Maximum = (ULONGLONG)~0;
820
821 /* Set the boot application top maximum */
822 MmArchTopOfApplicationAddressSpace = 0x70000000;
823
824 /* Initialize virtual address space translation */
825 Status = MmDefInitializeTranslation(MemoryData, TranslationType);
826 if (NT_SUCCESS(Status))
827 {
828 /* Set stub functions */
829 BlMmRelocateSelfMap = MmDefRelocateSelfMap;
830 BlMmFlushTlb = Mmx86FlushTlb;
831 BlMmMoveVirtualAddressRange = MmDefMoveVirtualAddressRange;
832 BlMmZeroVirtualAddressRange = MmDefZeroVirtualAddressRange;
833 }
834 break;
835
836 case BlPae:
837
838 Status = STATUS_NOT_SUPPORTED;
839 break;
840
841 default:
842 Status = STATUS_INVALID_PARAMETER;
843 break;
844 }
845
846 return Status;
847
848 }