[BOOTLIB]: Implement MmPaReserveSelfMapPages, MmPaReleaseSelfMapPages
authorAlex Ionescu <aionescu@gmail.com>
Mon, 6 Feb 2017 19:07:17 +0000 (19:07 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Mon, 6 Feb 2017 19:07:17 +0000 (19:07 +0000)
[BOOTLIB]: Stub MmDefMoveVirtualAddressRange, MmDefZeroVirtualAddressRange, MmDefRelocateSelfMap, MmDefpDestroySelfMap, MmDefpUnmapVirtualAddress, MmDefpRemapVirtualAddress, MmDefpMapPhysicalAddress, MmDefpTranslateVirtualAddress,
[BOOTLIB]: Implement MmDefpFlushTlbEntry, MmDefpFlushTlb
[BOOTLIB]: Implement MmPaReleaseSelfMapPages, MmPaReserveSelfMapPages.
[BOOTLIB]: Implement Archx86IsCpuidSupported, BlArchIsCpuIdFunctionSupported, BlArchCpuId, BlArchGetPerformanceCounter.
[BOOTLIB]: Implement MmArchInitialize.
[BOOTLIB]: Implement most of MmDefInitializeTranslation. Almost ready to turn on paging.

svn path=/trunk/; revision=73729

reactos/boot/environ/include/bl.h
reactos/boot/environ/lib/mm/descriptor.c
reactos/boot/environ/lib/mm/i386/mmx86.c
reactos/boot/environ/lib/mm/mm.c
reactos/boot/environ/lib/mm/pagealloc.c

index 0b046c5..7b0d365 100644 (file)
@@ -223,6 +223,7 @@ typedef enum _BL_MEMORY_DESCRIPTOR_TYPE
 {
     BlMdPhysical,
     BlMdVirtual,
+    BlMdTracker
 } BL_MEMORY_DESCRIPTOR_TYPE;
 
 typedef enum _BL_TRANSLATION_TYPE
@@ -2115,6 +2116,17 @@ MmPapAllocatePhysicalPagesInRange (
     );
 
 NTSTATUS
+MmPaReleaseSelfMapPages (
+    _In_ PHYSICAL_ADDRESS Address
+    );
+
+NTSTATUS
+MmPaReserveSelfMapPages (
+    _Inout_ PPHYSICAL_ADDRESS PhysicalAddress,
+    _In_ ULONG Alignment,
+    _In_ ULONG PageCount
+    );
+NTSTATUS
 BlMmFreePhysicalPages (
     _In_ PHYSICAL_ADDRESS Address
     );
index bfb8c37..4f95a29 100644 (file)
@@ -680,7 +680,6 @@ MmMdRemoveRegionFromMdlEx (
         FoundPageCount = Descriptor->PageCount;
         FoundEndPage = FoundBasePage + FoundPageCount;
         EndPage = PageCount + BasePage;
-        //EarlyPrint(L"Looking for Region 0x%08I64X-0x%08I64X in 0x%08I64X-0x%08I64X\r\n", BasePage, EndPage, FoundBasePage, FoundEndPage);
 
         /* Make a copy of the original descriptor */
         RtlCopyMemory(&NewDescriptor, NextEntry, sizeof(NewDescriptor));
@@ -694,19 +693,21 @@ MmMdRemoveRegionFromMdlEx (
                 /* Check if the found region starts after the region or ends before the region */
                 if ((FoundBasePage >= BasePage) || (EndPage >= FoundEndPage))
                 {
-                    /* This descriptor doesn't cover any part of the range */
-                    //EarlyPrint(L"No part of this descriptor contains the region\r\n");
+                    /* This descriptor doesn't cover any part of the range -- nothing to do */
+                    NOTHING;
                 }
                 else
                 {
-                    /* This descriptor covers the head of the allocation */
-                    //EarlyPrint(L"Descriptor covers the head of the region\r\n");
+                    /* This descriptor covers the head of the allocation @TODO: FIXME */
+                    EfiPrintf(L"FIXME: Descriptor covers the head of the region\r\n");
+                    EfiStall(1000000);
                 }
             }
             else
             {
-                /* This descriptor contains the entire allocation */
-                //EarlyPrint(L"Descriptor contains the entire region\r\n");
+                /* This descriptor contains the entire allocation @TODO: FIXME */
+                EfiPrintf(L"FIXME: Descriptor contains the entire region\r\n");
+                EfiStall(1000000);
             }
 
             /* Keep going */
@@ -747,7 +748,6 @@ MmMdRemoveRegionFromMdlEx (
             if (!Descriptor->PageCount)
             {
                 /* Remove it */
-                //EarlyPrint(L"Entire descriptor consumed\r\n");
                 MmMdRemoveDescriptorFromList(MdList, Descriptor);
                 MmMdFreeDescriptor(Descriptor);
 
index 36c5742..4125715 100644 (file)
@@ -17,7 +17,12 @@ ULONG_PTR MmArchKsegBias;
 ULONG MmArchLargePageSize;
 BL_ADDRESS_RANGE MmArchKsegAddressRange;
 ULONG_PTR MmArchTopOfApplicationAddressSpace;
-ULONG_PTR Mmx86SelfMapBase;
+PHYSICAL_ADDRESS Mmx86SelfMapBase;
+ULONG MmDeferredMappingCount;
+PVOID MmPdpt;
+PVOID MmArchReferencePage;
+PVOID MmPteBase;
+ULONG MmArchReferencePageSize;
 
 typedef VOID
 (*PBL_MM_FLUSH_TLB) (
@@ -29,10 +34,79 @@ typedef VOID
     VOID
     );
 
+typedef NTSTATUS
+(*PBL_MM_MOVE_VIRTUAL_ADDRESS_RANGE) (
+    _In_ PVOID DestinationAddress,
+    _In_ PVOID SourceAddress,
+    _In_ ULONGLONG Size
+    );
+
+typedef NTSTATUS
+(*PBL_MM_ZERO_VIRTUAL_ADDRESS_RANGE) (
+    _In_ PVOID DestinationAddress,
+    _In_ ULONGLONG Size
+    );
+
+typedef VOID
+(*PBL_MM_DESTROY_SELF_MAP) (
+    VOID
+    );
+
+typedef VOID
+(*PBL_MM_FLUSH_TLB_ENTRY) (
+    _In_ PVOID VirtualAddress
+    );
+
+typedef VOID
+(*PBL_MM_FLUSH_TLB) (
+    VOID
+    );
+
+typedef NTSTATUS
+(*PBL_MM_UNMAP_VIRTUAL_ADDRESS) (
+    _In_ PVOID VirtualAddress,
+    _In_ ULONG Size
+    );
+
+typedef NTSTATUS
+(*PBL_MM_REMAP_VIRTUAL_ADDRESS) (
+    _In_ PPHYSICAL_ADDRESS PhysicalAddress,
+    _Out_ PVOID VirtualAddress,
+    _In_ ULONG Size,
+    _In_ ULONG CacheAttributes
+    );
+
+typedef NTSTATUS
+(*PBL_MM_MAP_PHYSICAL_ADDRESS) (
+    _In_ PPHYSICAL_ADDRESS PhysicalAddress,
+    _Out_ PVOID VirtualAddress,
+    _In_ ULONG Size,
+    _In_ ULONG CacheAttributes
+    );
+
+typedef BOOLEAN
+(*PBL_MM_TRANSLATE_VIRTUAL_ADDRESS) (
+    _In_ PVOID VirtualAddress,
+    _Out_ PPHYSICAL_ADDRESS PhysicalAddress,
+    _Out_opt_ PULONG CacheAttributes
+    );
+
+PBL_MM_TRANSLATE_VIRTUAL_ADDRESS Mmx86TranslateVirtualAddress;
+PBL_MM_MAP_PHYSICAL_ADDRESS Mmx86MapPhysicalAddress;
+PBL_MM_REMAP_VIRTUAL_ADDRESS Mmx86RemapVirtualAddress;
+PBL_MM_UNMAP_VIRTUAL_ADDRESS Mmx86UnmapVirtualAddress;
+PBL_MM_FLUSH_TLB Mmx86FlushTlb;
+PBL_MM_FLUSH_TLB_ENTRY Mmx86FlushTlbEntry;
+PBL_MM_DESTROY_SELF_MAP Mmx86DestroySelfMap;
+
 PBL_MM_RELOCATE_SELF_MAP BlMmRelocateSelfMap;
 PBL_MM_FLUSH_TLB BlMmFlushTlb;
+PBL_MM_MOVE_VIRTUAL_ADDRESS_RANGE BlMmMoveVirtualAddressRange;
+PBL_MM_ZERO_VIRTUAL_ADDRESS_RANGE BlMmZeroVirtualAddressRange;
 
-ULONG MmDeferredMappingCount;
+PBL_MM_FLUSH_TLB Mmx86FlushTlb;
+
+#define PTE_BASE (PVOID)0xC0000000
 
 /* FUNCTIONS *****************************************************************/
 
@@ -45,6 +119,38 @@ MmArchNullFunction (
     return;
 }
 
+VOID
+MmDefRelocateSelfMap (
+    VOID
+    )
+{
+    if (MmPteBase != PTE_BASE)
+    {
+        EfiPrintf(L"Supposed to relocate CR3\r\n");
+    }
+}
+
+NTSTATUS
+MmDefMoveVirtualAddressRange (
+    _In_ PVOID DestinationAddress,
+    _In_ PVOID SourceAddress,
+    _In_ ULONGLONG Size
+    )
+{
+    EfiPrintf(L"Supposed to move shit\r\n");
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+MmDefZeroVirtualAddressRange (
+    _In_ PVOID DestinationAddress,
+    _In_ ULONGLONG Size
+    )
+{
+    EfiPrintf(L"Supposed to zero shit\r\n");
+    return STATUS_NOT_IMPLEMENTED;
+}
+
 NTSTATUS
 Mmx86pMapMemoryRegions (
     _In_ ULONG Phase,
@@ -78,17 +184,6 @@ Mmx86pMapMemoryRegions (
     return STATUS_NOT_IMPLEMENTED;
 }
 
-BOOLEAN
-Mmx86TranslateVirtualAddress (
-    _In_ PVOID VirtualAddress,
-    _Out_opt_ PPHYSICAL_ADDRESS PhysicalAddress,
-    _Out_opt_ PULONG CachingFlags
-    )
-{
-    EfiPrintf(L"paging  TODO\r\n");
-    return FALSE;
-}
-
 BOOLEAN
 MmArchTranslateVirtualAddress (
     _In_ PVOID VirtualAddress, 
@@ -131,6 +226,293 @@ MmArchTranslateVirtualAddress (
     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
+    )
+{
+    EfiPrintf(L"No destroy\r\n");
+}
+
+VOID
+MmDefpFlushTlbEntry (
+    _In_ PVOID VirtualAddress
+    )
+{
+    /* Flush the TLB */
+    __invlpg(VirtualAddress);
+}
+
+VOID
+MmDefpFlushTlb (
+    VOID
+    )
+{
+    /* Flush the TLB */
+    __writecr3(__readcr3());
+}
+
+NTSTATUS
+MmDefpUnmapVirtualAddress (
+    _In_ PVOID VirtualAddress,
+    _In_ ULONG Size
+    )
+{
+    EfiPrintf(L"No unmap\r\n");
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+MmDefpRemapVirtualAddress (
+    _In_ PPHYSICAL_ADDRESS PhysicalAddress,
+    _Out_ PVOID VirtualAddress,
+    _In_ ULONG Size,
+    _In_ ULONG CacheAttributes
+    )
+{
+    EfiPrintf(L"No remap\r\n");
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+MmDefpMapPhysicalAddress (
+    _In_ PPHYSICAL_ADDRESS PhysicalAddress,
+    _Out_ PVOID VirtualAddress,
+    _In_ ULONG Size,
+    _In_ ULONG CacheAttributes
+    )
+{
+    EfiPrintf(L"No map\r\n");
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+BOOLEAN
+MmDefpTranslateVirtualAddress (
+    _In_ PVOID VirtualAddress,
+    _Out_ PPHYSICAL_ADDRESS PhysicalAddress,
+    _Out_opt_ PULONG CacheAttributes
+    )
+{
+    EfiPrintf(L"No translate\r\n");
+    return FALSE;
+}
+
+NTSTATUS
+MmDefInitializeTranslation (
+    _In_ PBL_MEMORY_DATA MemoryData,
+    _In_ BL_TRANSLATION_TYPE TranslationType
+    )
+{
+    NTSTATUS Status;
+    PHYSICAL_ADDRESS PhysicalAddress;
+
+    /* Set the global function pointers for memory translation */
+    Mmx86TranslateVirtualAddress = MmDefpTranslateVirtualAddress;
+    Mmx86MapPhysicalAddress = MmDefpMapPhysicalAddress;
+    Mmx86UnmapVirtualAddress = MmDefpUnmapVirtualAddress;
+    Mmx86RemapVirtualAddress = MmDefpRemapVirtualAddress;
+    Mmx86FlushTlb = MmDefpFlushTlb;
+    Mmx86FlushTlbEntry = MmDefpFlushTlbEntry;
+    Mmx86DestroySelfMap = MmDefpDestroySelfMap;
+
+    /* Check what mode we're currently in */
+    if (TranslationType == BlVirtual)
+    {
+        EfiPrintf(L"Virtual->Virtual not yet supported\r\n");
+        return STATUS_NOT_IMPLEMENTED;
+    }
+    else if (TranslationType != BlNone)
+    {
+        /* Not even Windows supports PAE->Virtual downgrade */
+        return STATUS_NOT_IMPLEMENTED;
+    }
+
+    /* The None->Virtual case */
+    MmPdpt = NULL;
+    Mmx86SelfMapBase.QuadPart = 0;
+    MmArchReferencePage = NULL;
+
+    /* Truncate all memory above 4GB so that we don't use it @TODO: FIXME */
+    EfiPrintf(L"Warning: not truncating > 4GB memory. Don't boot with more than 4GB of RAM!\r\n");
+    //Status = MmPaTruncateMemory(0x100000);
+    Status = STATUS_SUCCESS;
+    if (!NT_SUCCESS(Status))
+    {
+        goto Quickie;
+    }
+
+    /* Allocate a page directory */
+    Status = MmPapAllocatePhysicalPagesInRange(&PhysicalAddress,
+                                               BlLoaderPageDirectory,
+                                               1,
+                                               0,
+                                               0,
+                                               &MmMdlUnmappedAllocated,
+                                               0,
+                                               0);
+    if (!NT_SUCCESS(Status))
+    {
+        goto Quickie;
+    }
+
+    /* Zero out the page directory */
+    MmPdpt = (PVOID)PhysicalAddress.LowPart;
+    RtlZeroMemory(MmPdpt, PAGE_SIZE);
+
+    /* Set the page size */
+    MmArchReferencePageSize = PAGE_SIZE;
+
+    /* Allocate the self-map page */
+    Status = MmPapAllocatePhysicalPagesInRange(&PhysicalAddress,
+                                               BlLoaderReferencePage,
+                                               1,
+                                               0,
+                                               0,
+                                               &MmMdlUnmappedAllocated,
+                                               0,
+                                               0);
+    if (!NT_SUCCESS(Status))
+    {
+        goto Quickie;
+    }
+
+    /* Set the reference page */
+    MmArchReferencePage = (PVOID)PhysicalAddress.LowPart;
+
+    /* Zero it out */
+    RtlZeroMemory(MmArchReferencePage, MmArchReferencePageSize);
+
+    /* Allocate 4MB worth of self-map pages */
+    Status = MmPaReserveSelfMapPages(&Mmx86SelfMapBase, 
+                                     (4 * 1024 * 1024) >> PAGE_SHIFT,
+                                     (4 * 1024 * 1024) >> PAGE_SHIFT);
+    if (!NT_SUCCESS(Status))
+    {
+        goto Quickie;
+    }
+
+    /* 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;
+
+Quickie:
+    /* Free reference page if we allocated it */
+    if (MmArchReferencePage)
+    {
+        PhysicalAddress.QuadPart = (ULONG_PTR)MmArchReferencePage;
+        BlMmFreePhysicalPages(PhysicalAddress);
+    }
+
+    /* Free page directory if we allocated it */
+    if (MmPdpt)
+    {
+        PhysicalAddress.QuadPart = (ULONG_PTR)MmPdpt;
+        BlMmFreePhysicalPages(PhysicalAddress);
+    }
+
+    /* Free the self map if we allocated it */
+    if (Mmx86SelfMapBase.QuadPart)
+    {
+        MmPaReleaseSelfMapPages(Mmx86SelfMapBase);
+    }
+
+    /* All done */
+    return Status;
+}
+
 NTSTATUS
 MmArchInitialize (
     _In_ ULONG Phase,
@@ -140,6 +522,8 @@ MmArchInitialize (
     )
 {
     NTSTATUS Status;
+    ULONGLONG IncreaseUserVa, PerfCounter, CpuRandom;
+    INT CpuInfo[4];
 
     /* For phase 2, just map deferred regions */
     if (Phase != 1)
@@ -160,7 +544,7 @@ MmArchInitialize (
             MmArchKsegAddressRange.Minimum = 0;
             MmArchKsegAddressRange.Maximum = (ULONGLONG)~0;
             MmArchTopOfApplicationAddressSpace = 0;
-            Mmx86SelfMapBase = 0;
+            Mmx86SelfMapBase.QuadPart = 0;
 
             /* Set stub functions */
             BlMmRelocateSelfMap = MmArchNullFunction;
@@ -172,7 +556,70 @@ MmArchInitialize (
 
         case BlVirtual:
 
-            Status = STATUS_NOT_IMPLEMENTED;
+            /* Set the large page size to 1024 pages (4MB) */
+            MmArchLargePageSize = (4 * 1024 * 1024) / PAGE_SIZE;
+
+            /* Check if /USERVA option was used */
+            Status = BlGetBootOptionInteger(BlpApplicationEntry.BcdData,
+                                            BcdOSLoaderInteger_IncreaseUserVa,
+                                            &IncreaseUserVa);
+            if (NT_SUCCESS(Status) && (IncreaseUserVa))
+            {
+                /* Yes -- load the kernel at 0xE0000000 instead */
+                MmArchKsegBase = 0xE0000000;
+            }
+            else
+            {
+                /* Nope, load at the standard 2GB split */
+                MmArchKsegBase = 0x80000000;
+            }
+
+            /* Check if CPUID 01h is supported */
+            CpuRandom = 0;
+            if (BlArchIsCpuIdFunctionSupported(1))
+            {
+                /* Call it */
+                BlArchCpuId(1, 0, CpuInfo);
+
+                /* Check if RDRAND is supported */
+                if (CpuInfo[2] & 0x40000000)
+                {
+                    EfiPrintf(L"Your CPU can do RDRAND! Good for you!\r\n");
+                    CpuRandom = 0;
+                }
+            }
+
+            /* Read the TSC */
+            PerfCounter = BlArchGetPerformanceCounter();
+            PerfCounter >>= 4;
+            _rotl16(PerfCounter, 5);
+
+            /* Set the address range */
+            MmArchKsegAddressRange.Minimum = 0;
+            MmArchKsegAddressRange.Maximum = (ULONGLONG)~0;
+
+            /* Set the KASLR bias */
+            MmArchKsegBias = ((PerfCounter ^ CpuRandom) & 0xFFF) << 12;
+            MmArchKsegBias = 0;
+            MmArchKsegBase += MmArchKsegBias;
+
+            /* Set the kernel range */
+            MmArchKsegAddressRange.Minimum = MmArchKsegBase;
+            MmArchKsegAddressRange.Maximum = (ULONGLONG)~0;
+
+            /* Set the boot application top maximum */
+            MmArchTopOfApplicationAddressSpace = 0x70000000;
+
+            /* Initialize virtual address space translation */
+            Status = MmDefInitializeTranslation(MemoryData, TranslationType);
+            if (NT_SUCCESS(Status))
+            {
+                /* Set stub functions */
+                BlMmRelocateSelfMap = MmDefRelocateSelfMap;
+                BlMmFlushTlb = Mmx86FlushTlb;
+                BlMmMoveVirtualAddressRange = MmDefMoveVirtualAddressRange;
+                BlMmZeroVirtualAddressRange = MmDefZeroVirtualAddressRange;
+            }
             break;
 
         case BlPae:
index d0dbe99..e574f4d 100644 (file)
@@ -13,7 +13,9 @@
 
 /* DATA VARIABLES ************************************************************/
 
-BL_TRANSLATION_TYPE MmTranslationType, MmOriginalTranslationType;
+/* This is a bug in Windows, but is required for MmTrInitialize to load */
+BL_TRANSLATION_TYPE MmTranslationType = BlMax;
+BL_TRANSLATION_TYPE MmOriginalTranslationType;
 ULONG MmDescriptorCallTreeCount;
 
 /* FUNCTIONS *****************************************************************/
@@ -23,15 +25,70 @@ MmTrInitialize (
     VOID
     )
 {
+    PBL_MEMORY_DESCRIPTOR Descriptor;
+    NTSTATUS Status;
+    PLIST_ENTRY NextEntry;
+
     /* Nothing to track if we're using physical memory */
     if (MmTranslationType == BlNone)
     {
         return STATUS_SUCCESS;
     }
 
-    /* TODO */
-    EfiPrintf(L"Required for protected mode\r\n");
-    return STATUS_NOT_IMPLEMENTED;
+    /* Initialize all the virtual lists */
+    MmMdInitializeListHead(&MmMdlMappingTrackers);
+    MmMdlMappingTrackers.Type = BlMdTracker;
+    MmMdInitializeListHead(&MmMdlFreeVirtual);
+    MmMdlFreeVirtual.Type = BlMdVirtual;
+
+    /* Initialize a 4GB free descriptor */
+    Descriptor = MmMdInitByteGranularDescriptor(0,
+                                                BlConventionalMemory,
+                                                0,
+                                                0,
+                                                ((ULONGLONG)4 * 1024 * 1024 * 1024) >>
+                                                PAGE_SHIFT);
+    if (!Descriptor)
+    {
+        Status = STATUS_NO_MEMORY;
+        goto Quickie;
+    }
+
+    /* Add this 4GB region to the free virtual address space list */
+    Status = MmMdAddDescriptorToList(&MmMdlFreeVirtual,
+                                     Descriptor,
+                                     BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG);
+    if (!NT_SUCCESS(Status))
+    {
+        RtlZeroMemory(Descriptor, sizeof(*Descriptor));
+        goto Quickie;
+    }
+
+    /* Remove any reserved regions of virtual address space */
+    NextEntry = MmMdlReservedAllocated.First->Flink;
+    while (NextEntry != MmMdlReservedAllocated.First)
+    {
+        /* Grab the descriptor and see if it's mapped */
+        Descriptor = CONTAINING_RECORD(NextEntry, BL_MEMORY_DESCRIPTOR, ListEntry);
+        if (Descriptor->VirtualPage)
+        {
+            EfiPrintf(L"Need to handle reserved allocation: %llx %llx\r\n",
+                      Descriptor->VirtualPage, Descriptor->PageCount);
+            EfiStall(100000);
+            Status = STATUS_NOT_IMPLEMENTED;
+            goto Quickie;
+        }
+
+        /* Next entry */
+        NextEntry = NextEntry->Flink;
+    }
+
+    /* Set success if we made it */
+    Status = STATUS_SUCCESS;
+
+Quickie:
+    /* Return back to caller */
+    return Status;
 }
 
 NTSTATUS
index 1ca2652..2bb9f02 100644 (file)
@@ -628,7 +628,7 @@ MmPapFreePhysicalPages (
     DontFree = FALSE;
     HasPageData = FALSE;
 
-    /* Only page-aligned addresses a re accepted */
+    /* Only page-aligned addresses are accepted */
     if (Address.QuadPart & (PAGE_SIZE - 1))
     {
         EfiPrintf(L"free mem fail 1\r\n");
@@ -1096,3 +1096,124 @@ Quickie:
     MmMdFreeList(&FirmwareMdList);
     return Status;
 }
+
+NTSTATUS
+MmPaReleaseSelfMapPages (
+    _In_ PHYSICAL_ADDRESS Address
+    )
+{
+    PBL_MEMORY_DESCRIPTOR Descriptor;
+    ULONGLONG BasePage;
+    NTSTATUS Status;
+
+    /* Only page-aligned addresses are accepted */
+    if (Address.QuadPart & (PAGE_SIZE - 1))
+    {
+        EfiPrintf(L"free mem fail 1\r\n");
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Get the base page, and find a descriptor that matches */
+    BasePage = Address.QuadPart >> PAGE_SHIFT;
+    Descriptor = MmMdFindDescriptor(BL_MM_INCLUDE_UNMAPPED_UNALLOCATED,
+                                    BL_MM_REMOVE_PHYSICAL_REGION_FLAG,
+                                    BasePage);
+    if (!(Descriptor) || (Descriptor->BasePage != BasePage))
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Free the physical pages */
+    Status = MmFwFreePages(BasePage, Descriptor->PageCount);
+    if (!NT_SUCCESS(Status))
+    {
+        return Status;
+    }
+
+    /* Remove the firmware flags */
+    Descriptor->Flags &= ~(BlMemoryNonFirmware |
+                           BlMemoryFirmware |
+                           BlMemoryPersistent);
+
+    /* Set it as free memory */
+    Descriptor->Type = BlConventionalMemory;
+
+    /* Create a new descriptor that's free memory, covering the old range */
+    Descriptor = MmMdInitByteGranularDescriptor(0,
+                                                BlConventionalMemory,
+                                                BasePage,
+                                                0,
+                                                Descriptor->PageCount);
+    if (!Descriptor)
+    {
+        return STATUS_NO_MEMORY;
+    }
+
+    /* Insert it into the virtual free list */
+    return MmMdAddDescriptorToList(&MmMdlFreeVirtual,
+                                   Descriptor,
+                                   BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG |
+                                   BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG);
+}
+
+NTSTATUS
+MmPaReserveSelfMapPages (
+    _Inout_ PPHYSICAL_ADDRESS PhysicalAddress,
+    _In_ ULONG Alignment, 
+    _In_ ULONG PageCount
+    )
+{
+    NTSTATUS Status;
+    BL_PA_REQUEST Request;
+    BL_MEMORY_DESCRIPTOR Descriptor;
+
+    /* Increment descriptor usage count */
+    ++MmDescriptorCallTreeCount;
+
+    /* Bail if we don't have an address */
+    if (!PhysicalAddress)
+    {
+        Status = STATUS_INVALID_PARAMETER;
+        goto Quickie;
+    }
+
+    /* Make a request for the required number of self-map pages */
+    Request.BaseRange.Minimum = PapMinimumPhysicalPage;
+    Request.BaseRange.Maximum = 0xFFFFFFFF >> PAGE_SHIFT;
+    Request.VirtualRange.Minimum = 0;
+    Request.VirtualRange.Maximum = 0;
+    Request.Pages = PageCount;
+    Request.Alignment = Alignment;
+    Request.Type = BL_MM_REQUEST_DEFAULT_TYPE;
+    Request.Flags = 0;;
+    Status = MmPaAllocatePages(&MmMdlUnmappedUnallocated,
+                               &Descriptor,
+                               &MmMdlUnmappedUnallocated,
+                               &Request,
+                               BlLoaderSelfMap);
+    if (!NT_SUCCESS(Status))
+    {
+        goto Quickie;
+    }
+
+    /* Remove this region from free virtual memory */
+    Status = MmMdRemoveRegionFromMdlEx(&MmMdlFreeVirtual,
+                                       BL_MM_REMOVE_VIRTUAL_REGION_FLAG,
+                                       Descriptor.BasePage,
+                                       Descriptor.PageCount,
+                                       0);
+    if (!NT_SUCCESS(Status))
+    {
+        goto Quickie;
+    }
+
+    /* Return the physical address */
+    PhysicalAddress->QuadPart = Descriptor.BasePage << PAGE_SHIFT;
+
+Quickie:
+    /* Free global descriptors and reduce the count by one */
+    MmMdFreeGlobalDescriptors();
+    --MmDescriptorCallTreeCount;
+    return Status;
+}
+