#include "bl.h"
#include "bcd.h"
+#define PTE_BASE 0xC0000000
+
+//
+// Specific PDE/PTE macros to be used inside the boot library environment
+//
+#define MiAddressToPte(x) ((PMMPTE)(((((ULONG)(x)) >> 12) << 2) + (ULONG_PTR)MmPteBase))
+#define MiAddressToPde(x) ((PMMPDE)(((((ULONG)(x)) >> 22) << 2) + (ULONG_PTR)MmPdeBase))
+#define MiAddressToPteOffset(x) ((((ULONG)(x)) << 10) >> 22)
+#define MiAddressToPdeOffset(x) (((ULONG)(x)) / (1024 * PAGE_SIZE))
+
/* DATA VARIABLES ************************************************************/
ULONG_PTR MmArchKsegBase;
ULONG_PTR MmArchTopOfApplicationAddressSpace;
PHYSICAL_ADDRESS Mmx86SelfMapBase;
ULONG MmDeferredMappingCount;
-PVOID MmPdpt;
-PVOID MmArchReferencePage;
+PMMPTE MmPdpt;
+PULONG MmArchReferencePage;
PVOID MmPteBase;
+PVOID MmPdeBase;
ULONG MmArchReferencePageSize;
typedef VOID
typedef NTSTATUS
(*PBL_MM_MAP_PHYSICAL_ADDRESS) (
- _In_ PPHYSICAL_ADDRESS PhysicalAddress,
+ _In_ PHYSICAL_ADDRESS PhysicalAddress,
_Out_ PVOID VirtualAddress,
_In_ ULONG Size,
_In_ ULONG CacheAttributes
PBL_MM_FLUSH_TLB Mmx86FlushTlb;
-#define PTE_BASE (PVOID)0xC0000000
-
/* FUNCTIONS *****************************************************************/
+BOOLEAN
+BlMmIsTranslationEnabled (
+ VOID
+ )
+{
+ /* Return if paging is on */
+ return ((CurrentExecutionContext) &&
+ (CurrentExecutionContext->Mode & BL_CONTEXT_PAGING_ON));
+}
+
VOID
MmArchNullFunction (
VOID
VOID
)
{
- if (MmPteBase != PTE_BASE)
+ if (MmPteBase != (PVOID)PTE_BASE)
{
EfiPrintf(L"Supposed to relocate CR3\r\n");
}
return STATUS_NOT_IMPLEMENTED;
}
-NTSTATUS
-Mmx86pMapMemoryRegions (
- _In_ ULONG Phase,
- _In_ PBL_MEMORY_DATA MemoryData
- )
-{
- BOOLEAN DoDeferred;
-
- /* In phase 1 we don't initialize deferred mappings*/
- if (Phase == 1)
- {
- DoDeferred = 0;
- }
- else
- {
- /* Don't do anything if there's nothing to initialize */
- if (!MmDeferredMappingCount)
- {
- return STATUS_SUCCESS;
- }
-
- DoDeferred = 1;
- }
-
- if (DoDeferred)
- {
- EfiPrintf(L"Deferred todo\r\n");
- }
-
- EfiPrintf(L"Phase 1 TODO\r\n");
- return STATUS_NOT_IMPLEMENTED;
-}
-
BOOLEAN
MmArchTranslateVirtualAddress (
_In_ PVOID VirtualAddress,
return Descriptor != NULL;
}
-BOOLEAN
-Archx86IsCpuidSupported (
- VOID
- )
-{
- ULONG CallerFlags, Flags;
-
- /* Read the original flags, and add the CPUID bit */
- CallerFlags = __getcallerseflags() ^ 0x200000;
- __writeeflags(CallerFlags);
-
- /* Read our flags now */
- Flags = __readeflags();
-
- /* Check if the bit stuck */
- return (((CallerFlags ^ Flags) >> 21) & 1) ^ 1;
-}
-
-BOOLEAN
-BlArchIsCpuIdFunctionSupported (
- _In_ ULONG Function
- )
-{
- BOOLEAN Supported;
- INT CpuInfo[4];
-
- /* Check if the CPU supports this instruction */
- Supported = Archx86IsCpuidSupported();
- if (!Supported)
- {
- return FALSE;
- }
-
- /* Check if it's the extended function */
- if (Function >= 0x80000000)
- {
- /* Check if extended functions are supported */
- __cpuid(CpuInfo, 0x80000000);
- if ((CpuInfo[0] & 0xFFFFFF00) != 0x80000000)
- {
- /* Nope */
- return FALSE;
- }
- }
- else
- {
- /* It's a regular function, get the maximum one supported */
- __cpuid(CpuInfo, 0);
- }
-
- /* Check if our function is within bounds */
- if (Function <= CpuInfo[0])
- {
- return TRUE;
- }
-
- /* Nope */
- return FALSE;
-}
-
-VOID
-BlArchCpuId (
- _In_ ULONG Function,
- _In_ ULONG SubFunction,
- _Out_ INT* Result
- )
-{
- /* Use the intrinsic */
- __cpuidex(Result, Function, SubFunction);
-}
-
-ULONGLONG
-BlArchGetPerformanceCounter (
- VOID
- )
-{
- INT CpuInfo[4];
-
- /* Serialize with CPUID, if it exists */
- if (Archx86IsCpuidSupported())
- {
- BlArchCpuId(0, 0, CpuInfo);
- }
-
- /* Read the TSC */
- return __rdtsc();
-}
-
VOID
MmDefpDestroySelfMap (
VOID
NTSTATUS
MmDefpMapPhysicalAddress (
- _In_ PPHYSICAL_ADDRESS PhysicalAddress,
- _Out_ PVOID VirtualAddress,
+ _In_ PHYSICAL_ADDRESS PhysicalAddress,
+ _In_ PVOID VirtualAddress,
_In_ ULONG Size,
_In_ ULONG CacheAttributes
)
{
- EfiPrintf(L"No map\r\n");
- return STATUS_NOT_IMPLEMENTED;
+ BOOLEAN Enabled;
+ ULONG i, PageCount, PdeOffset;
+ ULONGLONG CurrentAddress;
+ PMMPDE Pde;
+ PMMPTE Pte;
+ PMMPTE PageTable;
+ PHYSICAL_ADDRESS PageTableAddress;
+ NTSTATUS Status;
+
+ /* Check if paging is on yet */
+ Enabled = BlMmIsTranslationEnabled();
+
+ /* Get the physical address aligned */
+ CurrentAddress = (PhysicalAddress.QuadPart >> PAGE_SHIFT) << PAGE_SHIFT;
+
+ /* Get the number of pages and loop through each one */
+ PageCount = Size >> PAGE_SHIFT;
+ for (i = 0; i < PageCount; i++)
+ {
+ /* Check if translation already exists for this page */
+ if (Mmx86TranslateVirtualAddress(VirtualAddress, NULL, NULL))
+ {
+ /* Ignore it and move to the next one */
+ VirtualAddress = (PVOID)((ULONG_PTR)VirtualAddress + PAGE_SIZE);
+ CurrentAddress += PAGE_SIZE;
+ continue;
+ }
+
+ /* Get the PDE offset */
+ PdeOffset = MiAddressToPdeOffset(VirtualAddress);
+
+ /* Check if paging is actually turned on */
+ if (Enabled)
+ {
+ /* Get the PDE entry using the self-map */
+ Pde = MiAddressToPde(VirtualAddress);
+ }
+ else
+ {
+ /* Get it using our physical mappings */
+ Pde = &MmPdpt[PdeOffset];
+ PageTable = (PMMPDE)(Pde->u.Hard.PageFrameNumber << PAGE_SHIFT);
+ }
+
+ /* Check if we don't yet have a PDE */
+ if (!Pde->u.Hard.Valid)
+ {
+ /* Allocate a page table */
+ Status = MmPapAllocatePhysicalPagesInRange(&PageTableAddress,
+ BlLoaderPageDirectory,
+ 1,
+ 0,
+ 0,
+ &MmMdlUnmappedAllocated,
+ 0,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ return STATUS_NO_MEMORY;
+ }
+
+ /* This is our page table */
+ PageTable = (PVOID)(ULONG_PTR)PageTableAddress.QuadPart;
+
+ /* Build the PDE for it */
+ Pde->u.Hard.PageFrameNumber = PageTableAddress.QuadPart >> PAGE_SHIFT;
+ Pde->u.Hard.Write = 1;
+ Pde->u.Hard.CacheDisable = 1;
+ Pde->u.Hard.WriteThrough = 1;
+ Pde->u.Hard.Valid = 1;
+
+ /* Check if paging is enabled */
+ if (Enabled)
+ {
+ /* Then actually, get the page table's virtual address */
+ PageTable = (PVOID)PAGE_ROUND_DOWN(MiAddressToPte(VirtualAddress));
+
+ /* Flush the TLB */
+ Mmx86FlushTlb();
+ }
+
+ /* Zero out the page table */
+ RtlZeroMemory(PageTable, PAGE_SIZE);
+
+ /* Reset caching attributes now */
+ Pde->u.Hard.CacheDisable = 0;
+ Pde->u.Hard.WriteThrough = 0;
+
+ /* Check for paging again */
+ if (Enabled)
+ {
+ /* Flush the TLB entry for the page table only */
+ Mmx86FlushTlbEntry(PageTable);
+ }
+ }
+
+ /* Add a reference to this page table */
+ MmArchReferencePage[PdeOffset]++;
+
+ /* Check if a physical address was given */
+ if (PhysicalAddress.QuadPart != -1)
+ {
+ /* Check if paging is turned on */
+ if (Enabled)
+ {
+ /* Get the PTE using the self-map */
+ Pte = MiAddressToPte(VirtualAddress);
+ }
+ else
+ {
+ /* Get the PTE using physical addressing */
+ Pte = &PageTable[MiAddressToPteOffset(VirtualAddress)];
+ }
+
+ /* Build a valid PTE for it */
+ Pte->u.Hard.PageFrameNumber = CurrentAddress >> PAGE_SHIFT;
+ Pte->u.Hard.Write = 1;
+ Pte->u.Hard.Valid = 1;
+
+ /* Check if this is uncached */
+ if (CacheAttributes == BlMemoryUncached)
+ {
+ /* Set the flags */
+ Pte->u.Hard.CacheDisable = 1;
+ Pte->u.Hard.WriteThrough = 1;
+ }
+ else if (CacheAttributes == BlMemoryWriteThrough)
+ {
+ /* It's write-through, set the flag */
+ Pte->u.Hard.WriteThrough = 1;
+ }
+ }
+
+ /* Move to the next physical/virtual address */
+ VirtualAddress = (PVOID)((ULONG_PTR)VirtualAddress + PAGE_SIZE);
+ CurrentAddress += PAGE_SIZE;
+ }
+
+ /* All done! */
+ return STATUS_SUCCESS;
}
BOOLEAN
_Out_opt_ PULONG CacheAttributes
)
{
- EfiPrintf(L"No translate\r\n");
- return FALSE;
+ PMMPDE Pde;
+ PMMPTE Pte;
+ PMMPTE PageTable;
+ BOOLEAN Enabled;
+
+ /* Is there no page directory yet? */
+ if (!MmPdpt)
+ {
+ return FALSE;
+ }
+
+ /* Is paging enabled? */
+ Enabled = BlMmIsTranslationEnabled();
+
+ /* Check if paging is actually turned on */
+ if (Enabled)
+ {
+ /* Get the PDE entry using the self-map */
+ Pde = MiAddressToPde(VirtualAddress);
+ }
+ else
+ {
+ /* Get it using our physical mappings */
+ Pde = &MmPdpt[MiAddressToPdeOffset(VirtualAddress)];
+ }
+
+ /* Is the PDE valid? */
+ if (!Pde->u.Hard.Valid)
+ {
+ return FALSE;
+ }
+
+ /* Check if paging is turned on */
+ if (Enabled)
+ {
+ /* Get the PTE using the self-map */
+ Pte = MiAddressToPte(VirtualAddress);
+ }
+ else
+ {
+ /* Get the PTE using physical addressing */
+ PageTable = (PMMPTE)(Pde->u.Hard.PageFrameNumber << PAGE_SHIFT);
+ Pte = &PageTable[MiAddressToPteOffset(VirtualAddress)];
+ }
+
+ /* Is the PTE valid? */
+ if (!Pte->u.Hard.Valid)
+ {
+ return FALSE;
+ }
+
+ /* Does caller want the physical address? */
+ if (PhysicalAddress)
+ {
+ /* Return it */
+ PhysicalAddress->QuadPart = (Pte->u.Hard.PageFrameNumber << PAGE_SHIFT) +
+ BYTE_OFFSET(VirtualAddress);
+ }
+
+ /* Does caller want cache attributes? */
+ if (CacheAttributes)
+ {
+ /* Not yet -- lie and say it's cached */
+ EfiPrintf(L"Cache checking not yet enabled\r\n");
+ *CacheAttributes = BlMemoryWriteBack;
+ }
+
+ /* It exists! */
+ return TRUE;
+}
+
+NTSTATUS
+MmSelectMappingAddress (
+ _Out_ PVOID* MappingAddress,
+ _In_ ULONGLONG Size,
+ _In_ ULONG AllocationAttributes,
+ _In_ ULONG Flags,
+ _In_ PHYSICAL_ADDRESS PhysicalAddress
+ )
+{
+ /* Are we in physical mode? */
+ if (MmTranslationType == BlNone)
+ {
+ /* Just return the physical address as the mapping address */
+ *MappingAddress = (PVOID)PhysicalAddress.LowPart;
+ return STATUS_SUCCESS;
+ }
+
+ /* We don't support virtual memory yet @TODO */
+ EfiPrintf(L"not yet implemented in %S\r\n", __FUNCTION__);
+ EfiStall(1000000);
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+MmMapPhysicalAddress (
+ _Inout_ PPHYSICAL_ADDRESS PhysicalAddressPtr,
+ _Inout_ PVOID* VirtualAddressPtr,
+ _Inout_ PULONGLONG SizePtr,
+ _In_ ULONG CacheAttributes
+ )
+{
+ ULONGLONG Size, TotalSize;
+ ULONGLONG PhysicalAddress;
+ PVOID VirtualAddress;
+ PHYSICAL_ADDRESS TranslatedAddress;
+ ULONG_PTR CurrentAddress, VirtualAddressEnd;
+ NTSTATUS Status;
+
+ /* Fail if any parameters are missing */
+ if (!(PhysicalAddressPtr) || !(VirtualAddressPtr) || !(SizePtr))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ /* Fail if the size is over 32-bits */
+ Size = *SizePtr;
+ if (Size > 0xFFFFFFFF)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ /* Nothing to do if we're in physical mode */
+ if (MmTranslationType == BlNone)
+ {
+ return STATUS_SUCCESS;
+ }
+
+ /* Can't use virtual memory in real mode */
+ if (CurrentExecutionContext->Mode == BlRealMode)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ /* Capture the current virtual and physical addresses */
+ VirtualAddress = *VirtualAddressPtr;
+ PhysicalAddress = PhysicalAddressPtr->QuadPart;
+
+ /* Check if a physical address was requested */
+ if (PhysicalAddress != 0xFFFFFFFF)
+ {
+ /* Round down the base addresses */
+ PhysicalAddress = PAGE_ROUND_DOWN(PhysicalAddress);
+ VirtualAddress = (PVOID)PAGE_ROUND_DOWN(VirtualAddress);
+
+ /* Round up the size */
+ TotalSize = ROUND_TO_PAGES(PhysicalAddressPtr->QuadPart -
+ PhysicalAddress +
+ Size);
+
+ /* Loop every virtual page */
+ CurrentAddress = (ULONG_PTR)VirtualAddress;
+ VirtualAddressEnd = CurrentAddress + TotalSize - 1;
+ while (CurrentAddress < VirtualAddressEnd)
+ {
+ /* Get the physical page of this virtual page */
+ if (MmArchTranslateVirtualAddress((PVOID)CurrentAddress,
+ &TranslatedAddress,
+ &CacheAttributes))
+ {
+ /* Make sure the physical page of the virtual page, matches our page */
+ if (TranslatedAddress.QuadPart !=
+ (PhysicalAddress +
+ (CurrentAddress - (ULONG_PTR)VirtualAddress)))
+ {
+ /* There is an existing virtual mapping for a different address */
+ EfiPrintf(L"Existing mapping exists: %lx vs %lx\r\n",
+ TranslatedAddress.QuadPart,
+ PhysicalAddress + (CurrentAddress - (ULONG_PTR)VirtualAddress));
+ return STATUS_INVALID_PARAMETER;
+ }
+ }
+
+ /* Try the next one */
+ CurrentAddress += PAGE_SIZE;
+ }
+ }
+
+ /* Aactually do the mapping */
+ TranslatedAddress.QuadPart = PhysicalAddress;
+ Status = Mmx86MapPhysicalAddress(TranslatedAddress,
+ VirtualAddress,
+ Size,
+ CacheAttributes);
+ if (!NT_SUCCESS(Status))
+ {
+ EfiPrintf(L"Failed to map!: %lx\r\n", Status);
+ return Status;
+ }
+
+ /* Return aligned/fixed up output parameters */
+ PhysicalAddressPtr->QuadPart = PhysicalAddress;
+ *VirtualAddressPtr = VirtualAddress;
+ *SizePtr = Size;
+
+ /* Flush the TLB if paging is enabled */
+ if (BlMmIsTranslationEnabled())
+ {
+ Mmx86FlushTlb();
+ }
+
+ /* All good! */
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+Mmx86MapInitStructure (
+ _In_ PVOID VirtualAddress,
+ _In_ ULONGLONG Size,
+ _In_ PHYSICAL_ADDRESS PhysicalAddress
+ )
+{
+ NTSTATUS Status;
+
+ /* Make a virtual mapping for this physical address */
+ Status = MmMapPhysicalAddress(&PhysicalAddress, &VirtualAddress, &Size, 0);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ /* Nothing else to do if we're not in paging mode */
+ if (MmTranslationType == BlNone)
+ {
+ return STATUS_SUCCESS;
+ }
+
+ /* Otherwise, remove this region from the list of free virtual ranges */
+ Status = MmMdRemoveRegionFromMdlEx(&MmMdlFreeVirtual,
+ BL_MM_REMOVE_VIRTUAL_REGION_FLAG,
+ (ULONG_PTR)VirtualAddress >> PAGE_SHIFT,
+ Size >> PAGE_SHIFT,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Unmap the address if that failed */
+ MmUnmapVirtualAddress(&VirtualAddress, &Size);
+ }
+
+ /* Return back to caller */
+ return Status;
+}
+
+NTSTATUS
+Mmx86pMapMemoryRegions (
+ _In_ ULONG Phase,
+ _In_ PBL_MEMORY_DATA MemoryData
+ )
+{
+ BOOLEAN DoDeferred;
+ ULONG DescriptorCount;
+ PBL_MEMORY_DESCRIPTOR Descriptor;
+ ULONG FinalOffset;
+ PHYSICAL_ADDRESS PhysicalAddress;
+ ULONGLONG Size;
+ NTSTATUS Status;
+ PVOID VirtualAddress;
+ BL_MEMORY_DESCRIPTOR_LIST FirmwareMdl;
+ PLIST_ENTRY Head, NextEntry;
+
+ /* Check which phase this is */
+ if (Phase == 1)
+ {
+ /* In phase 1 we don't initialize deferred mappings */
+ DoDeferred = FALSE;
+ }
+ else
+ {
+ /* Don't do anything if there's nothing to initialize */
+ if (!MmDeferredMappingCount)
+ {
+ return STATUS_SUCCESS;
+ }
+
+ /* We'll do deferred descriptors in phase 2 */
+ DoDeferred = TRUE;
+ }
+
+ /*
+ * Because BL supports cross x86-x64 application launches and a LIST_ENTRY
+ * is of variable size, care must be taken here to ensure that we see a
+ * consistent view of descriptors. BL uses some offset magic to figure out
+ * where the data actually starts, since everything is ULONGLONG past the
+ * LIST_ENTRY itself
+ */
+ FinalOffset = MemoryData->MdListOffset + MemoryData->DescriptorOffset;
+ Descriptor = (PBL_MEMORY_DESCRIPTOR)((ULONG_PTR)MemoryData + FinalOffset -
+ FIELD_OFFSET(BL_MEMORY_DESCRIPTOR, BasePage));
+
+ /* Scan all of them */
+ DescriptorCount = MemoryData->DescriptorCount;
+ while (DescriptorCount != 0)
+ {
+ /* Ignore application data */
+ if (Descriptor->Type != BlApplicationData)
+ {
+ /* If this is a ramdisk, do it in phase 2 */
+ if ((Descriptor->Type == BlLoaderRamDisk) == DoDeferred)
+ {
+ /* Get the current physical address and size */
+ PhysicalAddress.QuadPart = Descriptor->BasePage << PAGE_SHIFT;
+ Size = Descriptor->PageCount << PAGE_SHIFT;
+
+ /* Check if it was already mapped */
+ if (Descriptor->VirtualPage)
+ {
+ /* Use the existing address */
+ VirtualAddress = (PVOID)(ULONG_PTR)(Descriptor->VirtualPage << PAGE_SHIFT);
+ }
+ else
+ {
+ /* Use the physical address */
+ VirtualAddress = (PVOID)(ULONG_PTR)PhysicalAddress.QuadPart;
+ }
+
+ /* Crete the mapping */
+ Status = Mmx86MapInitStructure(VirtualAddress,
+ Size,
+ PhysicalAddress);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
+
+ /* Check if we're in phase 1 and deferring RAM disk */
+ if ((Phase == 1) && (Descriptor->Type == BlLoaderRamDisk))
+ {
+ MmDeferredMappingCount++;
+ }
+ }
+
+ /* Move on to the next descriptor */
+ DescriptorCount--;
+ Descriptor = (PBL_MEMORY_DESCRIPTOR)((ULONG_PTR)Descriptor + MemoryData->DescriptorSize);
+ }
+
+ /* In phase 1, also do UEFI mappings */
+ if (Phase != 2)
+ {
+ /* Get the memory map */
+ MmMdInitializeListHead(&FirmwareMdl);
+ Status = MmFwGetMemoryMap(&FirmwareMdl, BL_MM_FLAG_REQUEST_COALESCING);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ /* Iterate over it */
+ Head = FirmwareMdl.First;
+ NextEntry = Head->Flink;
+ while (NextEntry != Head)
+ {
+ /* Check if this is a UEFI-related descriptor, unless it's the self-map page */
+ Descriptor = CONTAINING_RECORD(NextEntry, BL_MEMORY_DESCRIPTOR, ListEntry);
+ if (((Descriptor->Type == BlEfiBootMemory) ||
+ (Descriptor->Type == BlEfiRuntimeMemory) ||
+ (Descriptor->Type == BlLoaderMemory)) &&
+ ((Descriptor->BasePage << PAGE_SHIFT) != Mmx86SelfMapBase.QuadPart))
+ {
+ /* Identity-map it */
+ PhysicalAddress.QuadPart = Descriptor->BasePage << PAGE_SHIFT;
+ Status = Mmx86MapInitStructure((PVOID)((ULONG_PTR)Descriptor->BasePage << PAGE_SHIFT),
+ Descriptor->PageCount << PAGE_SHIFT,
+ PhysicalAddress);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
+
+ /* Move to the next descriptor */
+ NextEntry = NextEntry->Flink;
+ }
+
+ /* Reset */
+ NextEntry = Head->Flink;
+ while (NextEntry != Head)
+ {
+ /* Get the descriptor */
+ Descriptor = CONTAINING_RECORD(NextEntry, BL_MEMORY_DESCRIPTOR, ListEntry);
+
+ /* Skip to the next entry before we free */
+ NextEntry = NextEntry->Flink;
+
+ /* Remove and free it */
+ MmMdRemoveDescriptorFromList(&FirmwareMdl, Descriptor);
+ MmMdFreeDescriptor(Descriptor);
+ }
+ }
+
+ /* All library mappings identity mapped now */
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+Mmx86InitializeMemoryMap (
+ _In_ ULONG Phase,
+ _In_ PBL_MEMORY_DATA MemoryData
+ )
+{
+ ULONG ImageSize;
+ PVOID ImageBase;
+ KDESCRIPTOR Gdt, Idt;
+ NTSTATUS Status;
+ PHYSICAL_ADDRESS PhysicalAddress;
+
+ /* If this is phase 2, map the memory regions */
+ if (Phase != 1)
+ {
+ return Mmx86pMapMemoryRegions(Phase, MemoryData);
+ }
+
+ /* Get the application image base/size */
+ Status = BlGetApplicationBaseAndSize(&ImageBase, &ImageSize);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ /* Map the image back at the same place */
+ PhysicalAddress.QuadPart = (ULONG_PTR)ImageBase;
+ Status = Mmx86MapInitStructure(ImageBase, ImageSize, PhysicalAddress);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ /* Map the first 4MB of memory */
+ PhysicalAddress.QuadPart = 0;
+ Status = Mmx86MapInitStructure(NULL, 4 * 1024 * 1024, PhysicalAddress);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ /* Map the GDT */
+ _sgdt(&Gdt.Limit);
+ PhysicalAddress.QuadPart = Gdt.Base;
+ Status = Mmx86MapInitStructure((PVOID)Gdt.Base, Gdt.Limit + 1, PhysicalAddress);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ /* Map the IDT */
+ __sidt(&Idt.Limit);
+ PhysicalAddress.QuadPart = Idt.Base;
+ Status = Mmx86MapInitStructure((PVOID)Idt.Base, Idt.Limit + 1, PhysicalAddress);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ /* Map the reference page */
+ PhysicalAddress.QuadPart = (ULONG_PTR)MmArchReferencePage;
+ Status = Mmx86MapInitStructure(MmArchReferencePage,
+ MmArchReferencePageSize,
+ PhysicalAddress);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ /* More to do */
+ return Mmx86pMapMemoryRegions(Phase, MemoryData);
}
NTSTATUS
{
NTSTATUS Status;
PHYSICAL_ADDRESS PhysicalAddress;
+ ULONG PdeIndex;
/* Set the global function pointers for memory translation */
Mmx86TranslateVirtualAddress = MmDefpTranslateVirtualAddress;
/* Zero them out */
RtlZeroMemory((PVOID)Mmx86SelfMapBase.LowPart, 4 * 1024 * 1024);
-
EfiPrintf(L"PDPT at 0x%p Reference Page at 0x%p Self-map at 0x%p\r\n",
MmPdpt, MmArchReferencePage, Mmx86SelfMapBase.LowPart);
- Status = STATUS_NOT_IMPLEMENTED;
- //MmPteBase = Mmx86SelfMapBase.LowPart & 0xFFC00000;
+ /* Align PTE base to 4MB region */
+ MmPteBase = (PVOID)(Mmx86SelfMapBase.LowPart & ~0x3FFFFF);
+
+ /* The PDE is the PTE of the PTE base */
+ MmPdeBase = MiAddressToPte(MmPteBase);
+ PdeIndex = MiAddressToPdeOffset(MmPdeBase);
+ MmPdpt[PdeIndex].u.Hard.Valid = 1;
+ MmPdpt[PdeIndex].u.Hard.Write = 1;
+ MmPdpt[PdeIndex].u.Hard.PageFrameNumber = (ULONG_PTR)MmPdpt >> PAGE_SHIFT;
+ MmArchReferencePage[PdeIndex]++;
+
+ /* Remove PTE_BASE from free virtual memory */
+ Status = MmMdRemoveRegionFromMdlEx(&MmMdlFreeVirtual,
+ BL_MM_REMOVE_VIRTUAL_REGION_FLAG,
+ PTE_BASE >> PAGE_SHIFT,
+ (4 * 1024 * 1024) >> PAGE_SHIFT,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ goto Quickie;
+ }
+
+ /* Remove HAL_HEAP from free virtual memory */
+ Status = MmMdRemoveRegionFromMdlEx(&MmMdlFreeVirtual,
+ BL_MM_REMOVE_VIRTUAL_REGION_FLAG,
+ MM_HAL_VA_START >> PAGE_SHIFT,
+ (4 * 1024 * 1024) >> PAGE_SHIFT,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ goto Quickie;
+ }
+
+ /* Initialize the virtual->physical memory mappings */
+ Status = Mmx86InitializeMemoryMap(1, MemoryData);
+ if (!NT_SUCCESS(Status))
+ {
+ goto Quickie;
+ }
+
+ EfiPrintf(L"Ready to turn on motherfucking paging, brah!\r\n");
+ Status = STATUS_NOT_IMPLEMENTED;
Quickie:
/* Free reference page if we allocated it */
case BlPae:
+ /* We don't support PAE */
Status = STATUS_NOT_SUPPORTED;
break;
default:
+
+ /* Invalid architecture type*/
Status = STATUS_INVALID_PARAMETER;
break;
}
+ /* Back to caller */
return Status;
-
}