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)
9 /* INCLUDES ******************************************************************/
14 #define PTE_BASE 0xC0000000
17 // Specific PDE/PTE macros to be used inside the boot library environment
19 #define MiAddressToPte(x) ((PMMPTE)(((((ULONG)(x)) >> 12) << 2) + (ULONG_PTR)MmPteBase))
20 #define MiAddressToPde(x) ((PMMPDE)(((((ULONG)(x)) >> 22) << 2) + (ULONG_PTR)MmPdeBase))
21 #define MiAddressToPteOffset(x) ((((ULONG)(x)) << 10) >> 22)
22 #define MiAddressToPdeOffset(x) (((ULONG)(x)) / (1024 * PAGE_SIZE))
24 /* DATA VARIABLES ************************************************************/
26 ULONG_PTR MmArchKsegBase
;
27 ULONG_PTR MmArchKsegBias
;
28 ULONG MmArchLargePageSize
;
29 BL_ADDRESS_RANGE MmArchKsegAddressRange
;
30 ULONG_PTR MmArchTopOfApplicationAddressSpace
;
31 PHYSICAL_ADDRESS Mmx86SelfMapBase
;
32 ULONG MmDeferredMappingCount
;
34 PULONG MmArchReferencePage
;
37 ULONG MmArchReferencePageSize
;
45 (*PBL_MM_RELOCATE_SELF_MAP
) (
50 (*PBL_MM_MOVE_VIRTUAL_ADDRESS_RANGE
) (
51 _In_ PVOID DestinationAddress
,
52 _In_ PVOID SourceAddress
,
57 (*PBL_MM_ZERO_VIRTUAL_ADDRESS_RANGE
) (
58 _In_ PVOID DestinationAddress
,
63 (*PBL_MM_DESTROY_SELF_MAP
) (
68 (*PBL_MM_FLUSH_TLB_ENTRY
) (
69 _In_ PVOID VirtualAddress
78 (*PBL_MM_UNMAP_VIRTUAL_ADDRESS
) (
79 _In_ PVOID VirtualAddress
,
84 (*PBL_MM_REMAP_VIRTUAL_ADDRESS
) (
85 _In_ PPHYSICAL_ADDRESS PhysicalAddress
,
86 _Out_ PVOID VirtualAddress
,
88 _In_ ULONG CacheAttributes
92 (*PBL_MM_MAP_PHYSICAL_ADDRESS
) (
93 _In_ PHYSICAL_ADDRESS PhysicalAddress
,
94 _Out_ PVOID VirtualAddress
,
96 _In_ ULONG CacheAttributes
100 (*PBL_MM_TRANSLATE_VIRTUAL_ADDRESS
) (
101 _In_ PVOID VirtualAddress
,
102 _Out_ PPHYSICAL_ADDRESS PhysicalAddress
,
103 _Out_opt_ PULONG CacheAttributes
106 PBL_MM_TRANSLATE_VIRTUAL_ADDRESS Mmx86TranslateVirtualAddress
;
107 PBL_MM_MAP_PHYSICAL_ADDRESS Mmx86MapPhysicalAddress
;
108 PBL_MM_REMAP_VIRTUAL_ADDRESS Mmx86RemapVirtualAddress
;
109 PBL_MM_UNMAP_VIRTUAL_ADDRESS Mmx86UnmapVirtualAddress
;
110 PBL_MM_FLUSH_TLB Mmx86FlushTlb
;
111 PBL_MM_FLUSH_TLB_ENTRY Mmx86FlushTlbEntry
;
112 PBL_MM_DESTROY_SELF_MAP Mmx86DestroySelfMap
;
114 PBL_MM_RELOCATE_SELF_MAP BlMmRelocateSelfMap
;
115 PBL_MM_FLUSH_TLB BlMmFlushTlb
;
116 PBL_MM_MOVE_VIRTUAL_ADDRESS_RANGE BlMmMoveVirtualAddressRange
;
117 PBL_MM_ZERO_VIRTUAL_ADDRESS_RANGE BlMmZeroVirtualAddressRange
;
119 PBL_MM_FLUSH_TLB Mmx86FlushTlb
;
121 /* FUNCTIONS *****************************************************************/
124 BlMmIsTranslationEnabled (
128 /* Return if paging is on */
129 return ((CurrentExecutionContext
) &&
130 (CurrentExecutionContext
->Mode
& BL_CONTEXT_PAGING_ON
));
143 MmDefRelocateSelfMap (
147 if (MmPteBase
!= (PVOID
)PTE_BASE
)
149 EfiPrintf(L
"Supposed to relocate CR3\r\n");
154 MmDefMoveVirtualAddressRange (
155 _In_ PVOID DestinationAddress
,
156 _In_ PVOID SourceAddress
,
160 EfiPrintf(L
"Supposed to move shit\r\n");
161 return STATUS_NOT_IMPLEMENTED
;
165 MmDefZeroVirtualAddressRange (
166 _In_ PVOID DestinationAddress
,
170 EfiPrintf(L
"Supposed to zero shit\r\n");
171 return STATUS_NOT_IMPLEMENTED
;
175 Mmx86pMapMemoryRegions (
177 _In_ PBL_MEMORY_DATA MemoryData
182 /* In phase 1 we don't initialize deferred mappings*/
189 /* Don't do anything if there's nothing to initialize */
190 if (!MmDeferredMappingCount
)
192 return STATUS_SUCCESS
;
200 EfiPrintf(L
"Deferred todo\r\n");
203 EfiPrintf(L
"Phase 1 TODO\r\n");
204 return STATUS_NOT_IMPLEMENTED
;
208 MmArchTranslateVirtualAddress (
209 _In_ PVOID VirtualAddress
,
210 _Out_opt_ PPHYSICAL_ADDRESS PhysicalAddress
,
211 _Out_opt_ PULONG CachingFlags
214 PBL_MEMORY_DESCRIPTOR Descriptor
;
216 /* Check if paging is on */
217 if ((CurrentExecutionContext
) &&
218 (CurrentExecutionContext
->ContextFlags
& BL_CONTEXT_PAGING_ON
))
220 /* Yes -- we have to translate this from virtual */
221 return Mmx86TranslateVirtualAddress(VirtualAddress
,
226 /* Look in all descriptors except truncated and firmware ones */
227 Descriptor
= MmMdFindDescriptor(BL_MM_INCLUDE_NO_FIRMWARE_MEMORY
&
228 ~BL_MM_INCLUDE_TRUNCATED_MEMORY
,
229 BL_MM_REMOVE_PHYSICAL_REGION_FLAG
,
230 (ULONG_PTR
)VirtualAddress
>> PAGE_SHIFT
);
232 /* Return the virtual address as the physical address */
235 PhysicalAddress
->HighPart
= 0;
236 PhysicalAddress
->LowPart
= (ULONG_PTR
)VirtualAddress
;
239 /* There's no caching on physical memory */
245 /* Success is if we found a descriptor */
246 return Descriptor
!= NULL
;
250 MmDefpDestroySelfMap (
254 EfiPrintf(L
"No destroy\r\n");
258 MmDefpFlushTlbEntry (
259 _In_ PVOID VirtualAddress
263 __invlpg(VirtualAddress
);
272 __writecr3(__readcr3());
276 MmDefpUnmapVirtualAddress (
277 _In_ PVOID VirtualAddress
,
281 EfiPrintf(L
"No unmap\r\n");
282 return STATUS_NOT_IMPLEMENTED
;
286 MmDefpRemapVirtualAddress (
287 _In_ PPHYSICAL_ADDRESS PhysicalAddress
,
288 _Out_ PVOID VirtualAddress
,
290 _In_ ULONG CacheAttributes
293 EfiPrintf(L
"No remap\r\n");
294 return STATUS_NOT_IMPLEMENTED
;
298 MmDefpMapPhysicalAddress (
299 _In_ PHYSICAL_ADDRESS PhysicalAddress
,
300 _In_ PVOID VirtualAddress
,
302 _In_ ULONG CacheAttributes
306 ULONG i
, PageCount
, PdeOffset
;
307 ULONGLONG CurrentAddress
;
311 PHYSICAL_ADDRESS PageTableAddress
;
314 /* Check if paging is on yet */
315 Enabled
= BlMmIsTranslationEnabled();
317 /* Get the physical address aligned */
318 CurrentAddress
= (PhysicalAddress
.QuadPart
>> PAGE_SHIFT
) << PAGE_SHIFT
;
320 /* Get the number of pages and loop through each one */
321 PageCount
= Size
>> PAGE_SHIFT
;
322 for (i
= 0; i
< PageCount
; i
++)
324 /* Check if translation already exists for this page */
325 if (Mmx86TranslateVirtualAddress(VirtualAddress
, NULL
, NULL
))
327 /* Ignore it and move to the next one */
328 VirtualAddress
= (PVOID
)((ULONG_PTR
)VirtualAddress
+ PAGE_SIZE
);
329 CurrentAddress
+= PAGE_SIZE
;
333 /* Get the PDE offset */
334 PdeOffset
= MiAddressToPdeOffset(VirtualAddress
);
336 /* Check if paging is actually turned on */
339 /* Get the PDE entry using the self-map */
340 Pde
= MiAddressToPde(VirtualAddress
);
344 /* Get it using our physical mappings */
345 Pde
= &MmPdpt
[PdeOffset
];
346 PageTable
= (PMMPDE
)(Pde
->u
.Hard
.PageFrameNumber
<< PAGE_SHIFT
);
349 /* Check if we don't yet have a PDE */
350 if (!Pde
->u
.Hard
.Valid
)
352 /* Allocate a page table */
353 Status
= MmPapAllocatePhysicalPagesInRange(&PageTableAddress
,
354 BlLoaderPageDirectory
,
358 &MmMdlUnmappedAllocated
,
361 if (!NT_SUCCESS(Status
))
363 return STATUS_NO_MEMORY
;
366 /* This is our page table */
367 PageTable
= (PVOID
)(ULONG_PTR
)PageTableAddress
.QuadPart
;
369 /* Build the PDE for it */
370 Pde
->u
.Hard
.PageFrameNumber
= PageTableAddress
.QuadPart
>> PAGE_SHIFT
;
371 Pde
->u
.Hard
.Write
= 1;
372 Pde
->u
.Hard
.CacheDisable
= 1;
373 Pde
->u
.Hard
.WriteThrough
= 1;
374 Pde
->u
.Hard
.Valid
= 1;
376 /* Check if paging is enabled */
379 /* Then actually, get the page table's virtual address */
380 PageTable
= (PVOID
)PAGE_ROUND_DOWN(MiAddressToPte(VirtualAddress
));
386 /* Zero out the page table */
387 RtlZeroMemory(PageTable
, PAGE_SIZE
);
389 /* Reset caching attributes now */
390 Pde
->u
.Hard
.CacheDisable
= 0;
391 Pde
->u
.Hard
.WriteThrough
= 0;
393 /* Check for paging again */
396 /* Flush the TLB entry for the page table only */
397 Mmx86FlushTlbEntry(PageTable
);
401 /* Add a reference to this page table */
402 MmArchReferencePage
[PdeOffset
]++;
404 /* Check if a physical address was given */
405 if (PhysicalAddress
.QuadPart
!= -1)
407 /* Check if paging is turned on */
410 /* Get the PTE using the self-map */
411 Pte
= MiAddressToPte(VirtualAddress
);
415 /* Get the PTE using physical addressing */
416 Pte
= &PageTable
[MiAddressToPteOffset(VirtualAddress
)];
419 /* Build a valid PTE for it */
420 Pte
->u
.Hard
.PageFrameNumber
= CurrentAddress
>> PAGE_SHIFT
;
421 Pte
->u
.Hard
.Write
= 1;
422 Pte
->u
.Hard
.Valid
= 1;
424 /* Check if this is uncached */
425 if (CacheAttributes
== BlMemoryUncached
)
428 Pte
->u
.Hard
.CacheDisable
= 1;
429 Pte
->u
.Hard
.WriteThrough
= 1;
431 else if (CacheAttributes
== BlMemoryWriteThrough
)
433 /* It's write-through, set the flag */
434 Pte
->u
.Hard
.WriteThrough
= 1;
438 /* Move to the next physical/virtual address */
439 VirtualAddress
= (PVOID
)((ULONG_PTR
)VirtualAddress
+ PAGE_SIZE
);
440 CurrentAddress
+= PAGE_SIZE
;
444 return STATUS_SUCCESS
;
448 MmDefpTranslateVirtualAddress (
449 _In_ PVOID VirtualAddress
,
450 _Out_ PPHYSICAL_ADDRESS PhysicalAddress
,
451 _Out_opt_ PULONG CacheAttributes
459 /* Is there no page directory yet? */
465 /* Is paging enabled? */
466 Enabled
= BlMmIsTranslationEnabled();
468 /* Check if paging is actually turned on */
471 /* Get the PDE entry using the self-map */
472 Pde
= MiAddressToPde(VirtualAddress
);
476 /* Get it using our physical mappings */
477 Pde
= &MmPdpt
[MiAddressToPdeOffset(VirtualAddress
)];
480 /* Is the PDE valid? */
481 if (!Pde
->u
.Hard
.Valid
)
486 /* Check if paging is turned on */
489 /* Get the PTE using the self-map */
490 Pte
= MiAddressToPte(VirtualAddress
);
494 /* Get the PTE using physical addressing */
495 PageTable
= (PMMPTE
)(Pde
->u
.Hard
.PageFrameNumber
<< PAGE_SHIFT
);
496 Pte
= &PageTable
[MiAddressToPteOffset(VirtualAddress
)];
499 /* Is the PTE valid? */
500 if (!Pte
->u
.Hard
.Valid
)
505 /* Does caller want the physical address? */
509 PhysicalAddress
->QuadPart
= (Pte
->u
.Hard
.PageFrameNumber
<< PAGE_SHIFT
) +
510 BYTE_OFFSET(VirtualAddress
);
513 /* Does caller want cache attributes? */
516 /* Not yet -- lie and say it's cached */
517 EfiPrintf(L
"Cache checking not yet enabled\r\n");
518 *CacheAttributes
= BlMemoryWriteBack
;
526 MmSelectMappingAddress (
527 _Out_ PVOID
* MappingAddress
,
529 _In_ ULONG AllocationAttributes
,
531 _In_ PHYSICAL_ADDRESS PhysicalAddress
534 /* Are we in physical mode? */
535 if (MmTranslationType
== BlNone
)
537 /* Just return the physical address as the mapping address */
538 *MappingAddress
= (PVOID
)PhysicalAddress
.LowPart
;
539 return STATUS_SUCCESS
;
542 /* We don't support virtual memory yet @TODO */
543 #ifdef _MSC_VER // Fuck gcc.
544 EfiPrintf(L
"not yet implemented in " __FUNCTION__
"\r\n");
547 return STATUS_NOT_IMPLEMENTED
;
551 MmMapPhysicalAddress (
552 _Inout_ PPHYSICAL_ADDRESS PhysicalAddressPtr
,
553 _Inout_ PVOID
* VirtualAddressPtr
,
554 _Inout_ PULONGLONG SizePtr
,
555 _In_ ULONG CacheAttributes
558 ULONGLONG Size
, TotalSize
;
559 ULONGLONG PhysicalAddress
;
560 PVOID VirtualAddress
;
561 PHYSICAL_ADDRESS TranslatedAddress
;
562 ULONG_PTR CurrentAddress
, VirtualAddressEnd
;
565 /* Fail if any parameters are missing */
566 if (!(PhysicalAddressPtr
) || !(VirtualAddressPtr
) || !(SizePtr
))
568 return STATUS_INVALID_PARAMETER
;
571 /* Fail if the size is over 32-bits */
573 if (Size
> 0xFFFFFFFF)
575 return STATUS_INVALID_PARAMETER
;
578 /* Nothing to do if we're in physical mode */
579 if (MmTranslationType
== BlNone
)
581 return STATUS_SUCCESS
;
584 /* Can't use virtual memory in real mode */
585 if (CurrentExecutionContext
->Mode
== BlRealMode
)
587 return STATUS_UNSUCCESSFUL
;
590 /* Capture the current virtual and physical addresses */
591 VirtualAddress
= *VirtualAddressPtr
;
592 PhysicalAddress
= PhysicalAddressPtr
->QuadPart
;
594 /* Check if a physical address was requested */
595 if (PhysicalAddress
!= 0xFFFFFFFF)
597 /* Round down the base addresses */
598 PhysicalAddress
= PAGE_ROUND_DOWN(PhysicalAddress
);
599 VirtualAddress
= (PVOID
)PAGE_ROUND_DOWN(VirtualAddress
);
601 /* Round up the size */
602 TotalSize
= ROUND_TO_PAGES(PhysicalAddressPtr
->QuadPart
-
606 /* Loop every virtual page */
607 CurrentAddress
= (ULONG_PTR
)VirtualAddress
;
608 VirtualAddressEnd
= CurrentAddress
+ TotalSize
- 1;
609 while (CurrentAddress
< VirtualAddressEnd
)
611 /* Get the physical page of this virtual page */
612 if (MmArchTranslateVirtualAddress((PVOID
)CurrentAddress
,
616 /* Make sure the physical page of the virtual page, matches our page */
617 if (TranslatedAddress
.QuadPart
!=
619 (CurrentAddress
- (ULONG_PTR
)VirtualAddress
)))
621 /* There is an existing virtual mapping for a different address */
622 EfiPrintf(L
"Existing mapping exists: %lx vs %lx\r\n",
623 TranslatedAddress
.QuadPart
,
624 PhysicalAddress
+ (CurrentAddress
- (ULONG_PTR
)VirtualAddress
));
625 return STATUS_INVALID_PARAMETER
;
629 /* Try the next one */
630 CurrentAddress
+= PAGE_SIZE
;
634 /* Aactually do the mapping */
635 TranslatedAddress
.QuadPart
= PhysicalAddress
;
636 Status
= Mmx86MapPhysicalAddress(TranslatedAddress
,
640 if (!NT_SUCCESS(Status
))
642 EfiPrintf(L
"Failed to map!: %lx\r\n", Status
);
646 /* Return aligned/fixed up output parameters */
647 PhysicalAddressPtr
->QuadPart
= PhysicalAddress
;
648 *VirtualAddressPtr
= VirtualAddress
;
651 /* Flush the TLB if paging is enabled */
652 if (BlMmIsTranslationEnabled())
658 return STATUS_SUCCESS
;
662 Mmx86MapInitStructure (
663 _In_ PVOID VirtualAddress
,
665 _In_ PHYSICAL_ADDRESS PhysicalAddress
670 /* Make a virtual mapping for this physical address */
671 Status
= MmMapPhysicalAddress(&PhysicalAddress
, &VirtualAddress
, &Size
, 0);
672 if (!NT_SUCCESS(Status
))
677 /* Nothing else to do if we're not in paging mode */
678 if (MmTranslationType
== BlNone
)
680 return STATUS_SUCCESS
;
683 /* Otherwise, remove this region from the list of free virtual ranges */
684 Status
= MmMdRemoveRegionFromMdlEx(&MmMdlFreeVirtual
,
685 BL_MM_REMOVE_VIRTUAL_REGION_FLAG
,
686 (ULONG_PTR
)VirtualAddress
>> PAGE_SHIFT
,
689 if (!NT_SUCCESS(Status
))
691 /* Unmap the address if that failed */
692 MmUnmapVirtualAddress(&VirtualAddress
, &Size
);
695 /* Return back to caller */
700 Mmx86InitializeMemoryMap (
702 _In_ PBL_MEMORY_DATA MemoryData
707 KDESCRIPTOR Gdt
, Idt
;
709 PHYSICAL_ADDRESS PhysicalAddress
;
711 /* If this is phase 2, map the memory regions */
714 return Mmx86pMapMemoryRegions(Phase
, MemoryData
);
717 /* Get the application image base/size */
718 Status
= BlGetApplicationBaseAndSize(&ImageBase
, &ImageSize
);
719 if (!NT_SUCCESS(Status
))
724 /* Map the image back at the same place */
725 PhysicalAddress
.QuadPart
= (ULONG_PTR
)ImageBase
;
726 Status
= Mmx86MapInitStructure(ImageBase
, ImageSize
, PhysicalAddress
);
727 if (!NT_SUCCESS(Status
))
732 /* Map the first 4MB of memory */
733 PhysicalAddress
.QuadPart
= 0;
734 Status
= Mmx86MapInitStructure(NULL
, 4 * 1024 * 1024, PhysicalAddress
);
735 if (!NT_SUCCESS(Status
))
742 PhysicalAddress
.QuadPart
= Gdt
.Base
;
743 Status
= Mmx86MapInitStructure((PVOID
)Gdt
.Base
, Gdt
.Limit
+ 1, PhysicalAddress
);
744 if (!NT_SUCCESS(Status
))
751 PhysicalAddress
.QuadPart
= Idt
.Base
;
752 Status
= Mmx86MapInitStructure((PVOID
)Idt
.Base
, Idt
.Limit
+ 1, PhysicalAddress
);
753 if (!NT_SUCCESS(Status
))
758 /* Map the reference page */
759 PhysicalAddress
.QuadPart
= (ULONG_PTR
)MmArchReferencePage
;
760 Status
= Mmx86MapInitStructure(MmArchReferencePage
,
761 MmArchReferencePageSize
,
763 if (!NT_SUCCESS(Status
))
769 EfiPrintf(L
"VM more work\r\n");
770 return STATUS_NOT_IMPLEMENTED
;
774 MmDefInitializeTranslation (
775 _In_ PBL_MEMORY_DATA MemoryData
,
776 _In_ BL_TRANSLATION_TYPE TranslationType
780 PHYSICAL_ADDRESS PhysicalAddress
;
783 /* Set the global function pointers for memory translation */
784 Mmx86TranslateVirtualAddress
= MmDefpTranslateVirtualAddress
;
785 Mmx86MapPhysicalAddress
= MmDefpMapPhysicalAddress
;
786 Mmx86UnmapVirtualAddress
= MmDefpUnmapVirtualAddress
;
787 Mmx86RemapVirtualAddress
= MmDefpRemapVirtualAddress
;
788 Mmx86FlushTlb
= MmDefpFlushTlb
;
789 Mmx86FlushTlbEntry
= MmDefpFlushTlbEntry
;
790 Mmx86DestroySelfMap
= MmDefpDestroySelfMap
;
792 /* Check what mode we're currently in */
793 if (TranslationType
== BlVirtual
)
795 EfiPrintf(L
"Virtual->Virtual not yet supported\r\n");
796 return STATUS_NOT_IMPLEMENTED
;
798 else if (TranslationType
!= BlNone
)
800 /* Not even Windows supports PAE->Virtual downgrade */
801 return STATUS_NOT_IMPLEMENTED
;
804 /* The None->Virtual case */
806 Mmx86SelfMapBase
.QuadPart
= 0;
807 MmArchReferencePage
= NULL
;
809 /* Truncate all memory above 4GB so that we don't use it @TODO: FIXME */
810 EfiPrintf(L
"Warning: not truncating > 4GB memory. Don't boot with more than 4GB of RAM!\r\n");
811 //Status = MmPaTruncateMemory(0x100000);
812 Status
= STATUS_SUCCESS
;
813 if (!NT_SUCCESS(Status
))
818 /* Allocate a page directory */
819 Status
= MmPapAllocatePhysicalPagesInRange(&PhysicalAddress
,
820 BlLoaderPageDirectory
,
824 &MmMdlUnmappedAllocated
,
827 if (!NT_SUCCESS(Status
))
832 /* Zero out the page directory */
833 MmPdpt
= (PVOID
)PhysicalAddress
.LowPart
;
834 RtlZeroMemory(MmPdpt
, PAGE_SIZE
);
836 /* Set the page size */
837 MmArchReferencePageSize
= PAGE_SIZE
;
839 /* Allocate the self-map page */
840 Status
= MmPapAllocatePhysicalPagesInRange(&PhysicalAddress
,
841 BlLoaderReferencePage
,
845 &MmMdlUnmappedAllocated
,
848 if (!NT_SUCCESS(Status
))
853 /* Set the reference page */
854 MmArchReferencePage
= (PVOID
)PhysicalAddress
.LowPart
;
857 RtlZeroMemory(MmArchReferencePage
, MmArchReferencePageSize
);
859 /* Allocate 4MB worth of self-map pages */
860 Status
= MmPaReserveSelfMapPages(&Mmx86SelfMapBase
,
861 (4 * 1024 * 1024) >> PAGE_SHIFT
,
862 (4 * 1024 * 1024) >> PAGE_SHIFT
);
863 if (!NT_SUCCESS(Status
))
869 RtlZeroMemory((PVOID
)Mmx86SelfMapBase
.LowPart
, 4 * 1024 * 1024);
870 EfiPrintf(L
"PDPT at 0x%p Reference Page at 0x%p Self-map at 0x%p\r\n",
871 MmPdpt
, MmArchReferencePage
, Mmx86SelfMapBase
.LowPart
);
873 /* Align PTE base to 4MB region */
874 MmPteBase
= (PVOID
)(Mmx86SelfMapBase
.LowPart
& ~0x3FFFFF);
876 /* The PDE is the PTE of the PTE base */
877 MmPdeBase
= MiAddressToPte(MmPteBase
);
878 PdeIndex
= MiAddressToPdeOffset(MmPdeBase
);
879 MmPdpt
[PdeIndex
].u
.Hard
.Valid
= 1;
880 MmPdpt
[PdeIndex
].u
.Hard
.Write
= 1;
881 MmPdpt
[PdeIndex
].u
.Hard
.PageFrameNumber
= (ULONG_PTR
)MmPdpt
>> PAGE_SHIFT
;
882 MmArchReferencePage
[PdeIndex
]++;
884 /* Remove PTE_BASE from free virtual memory */
885 Status
= MmMdRemoveRegionFromMdlEx(&MmMdlFreeVirtual
,
886 BL_MM_REMOVE_VIRTUAL_REGION_FLAG
,
887 PTE_BASE
>> PAGE_SHIFT
,
888 (4 * 1024 * 1024) >> PAGE_SHIFT
,
890 if (!NT_SUCCESS(Status
))
895 /* Remove HAL_HEAP from free virtual memory */
896 Status
= MmMdRemoveRegionFromMdlEx(&MmMdlFreeVirtual
,
897 BL_MM_REMOVE_VIRTUAL_REGION_FLAG
,
898 MM_HAL_VA_START
>> PAGE_SHIFT
,
899 (4 * 1024 * 1024) >> PAGE_SHIFT
,
901 if (!NT_SUCCESS(Status
))
906 /* Initialize the virtual->physical memory mappings */
907 Status
= Mmx86InitializeMemoryMap(1, MemoryData
);
908 if (!NT_SUCCESS(Status
))
913 EfiPrintf(L
"Ready to turn on motherfucking paging, brah!\r\n");
914 Status
= STATUS_NOT_IMPLEMENTED
;
917 /* Free reference page if we allocated it */
918 if (MmArchReferencePage
)
920 PhysicalAddress
.QuadPart
= (ULONG_PTR
)MmArchReferencePage
;
921 BlMmFreePhysicalPages(PhysicalAddress
);
924 /* Free page directory if we allocated it */
927 PhysicalAddress
.QuadPart
= (ULONG_PTR
)MmPdpt
;
928 BlMmFreePhysicalPages(PhysicalAddress
);
931 /* Free the self map if we allocated it */
932 if (Mmx86SelfMapBase
.QuadPart
)
934 MmPaReleaseSelfMapPages(Mmx86SelfMapBase
);
944 _In_ PBL_MEMORY_DATA MemoryData
,
945 _In_ BL_TRANSLATION_TYPE TranslationType
,
946 _In_ BL_TRANSLATION_TYPE RequestedTranslationType
950 ULONGLONG IncreaseUserVa
, PerfCounter
, CpuRandom
;
953 /* For phase 2, just map deferred regions */
956 return Mmx86pMapMemoryRegions(2, MemoryData
);
959 /* What translation type are we switching to? */
960 switch (RequestedTranslationType
)
962 /* Physical memory */
965 /* Initialize everything to default/null values */
966 MmArchLargePageSize
= 1;
969 MmArchKsegAddressRange
.Minimum
= 0;
970 MmArchKsegAddressRange
.Maximum
= (ULONGLONG
)~0;
971 MmArchTopOfApplicationAddressSpace
= 0;
972 Mmx86SelfMapBase
.QuadPart
= 0;
974 /* Set stub functions */
975 BlMmRelocateSelfMap
= MmArchNullFunction
;
976 BlMmFlushTlb
= MmArchNullFunction
;
979 Status
= STATUS_SUCCESS
;
984 /* Set the large page size to 1024 pages (4MB) */
985 MmArchLargePageSize
= (4 * 1024 * 1024) / PAGE_SIZE
;
987 /* Check if /USERVA option was used */
988 Status
= BlGetBootOptionInteger(BlpApplicationEntry
.BcdData
,
989 BcdOSLoaderInteger_IncreaseUserVa
,
991 if (NT_SUCCESS(Status
) && (IncreaseUserVa
))
993 /* Yes -- load the kernel at 0xE0000000 instead */
994 MmArchKsegBase
= 0xE0000000;
998 /* Nope, load at the standard 2GB split */
999 MmArchKsegBase
= 0x80000000;
1002 /* Check if CPUID 01h is supported */
1004 if (BlArchIsCpuIdFunctionSupported(1))
1007 BlArchCpuId(1, 0, CpuInfo
);
1009 /* Check if RDRAND is supported */
1010 if (CpuInfo
[2] & 0x40000000)
1012 EfiPrintf(L
"Your CPU can do RDRAND! Good for you!\r\n");
1018 PerfCounter
= BlArchGetPerformanceCounter();
1020 _rotl16(PerfCounter
, 5);
1022 /* Set the address range */
1023 MmArchKsegAddressRange
.Minimum
= 0;
1024 MmArchKsegAddressRange
.Maximum
= (ULONGLONG
)~0;
1026 /* Set the KASLR bias */
1027 MmArchKsegBias
= ((PerfCounter
^ CpuRandom
) & 0xFFF) << 12;
1029 MmArchKsegBase
+= MmArchKsegBias
;
1031 /* Set the kernel range */
1032 MmArchKsegAddressRange
.Minimum
= MmArchKsegBase
;
1033 MmArchKsegAddressRange
.Maximum
= (ULONGLONG
)~0;
1035 /* Set the boot application top maximum */
1036 MmArchTopOfApplicationAddressSpace
= 0x70000000;
1038 /* Initialize virtual address space translation */
1039 Status
= MmDefInitializeTranslation(MemoryData
, TranslationType
);
1040 if (NT_SUCCESS(Status
))
1042 /* Set stub functions */
1043 BlMmRelocateSelfMap
= MmDefRelocateSelfMap
;
1044 BlMmFlushTlb
= Mmx86FlushTlb
;
1045 BlMmMoveVirtualAddressRange
= MmDefMoveVirtualAddressRange
;
1046 BlMmZeroVirtualAddressRange
= MmDefZeroVirtualAddressRange
;
1052 Status
= STATUS_NOT_SUPPORTED
;
1056 Status
= STATUS_INVALID_PARAMETER
;