[BOOTMGR]: Fix bug in test.
[reactos.git] / reactos / boot / environ / lib / mm / pagealloc.c
index 5b97d50..dd7cbd0 100644 (file)
@@ -9,7 +9,7 @@
 /* INCLUDES ******************************************************************/
 
 #include "bl.h"
-
+#include "bcd.h"
 
 typedef struct _BL_PA_REQUEST
 {
@@ -50,7 +50,30 @@ BlpMmInitializeConstraints (
     VOID
     )
 {
-    /* FIXME: Read BCD option 'avoidlowmemory' and 'truncatememory' */
+    NTSTATUS Status;
+    ULONGLONG LowestAddressValid, HighestAddressValid;
+
+    /* Check for LOWMEM */
+    Status = BlGetBootOptionInteger(BlpApplicationEntry.BcdData,
+                                    BcdLibraryInteger_AvoidLowPhysicalMemory,
+                                    &LowestAddressValid);
+    if (NT_SUCCESS(Status))
+    {
+        EfiPrintf(L"/LOWMEM not supported\r\n");
+        return STATUS_NOT_IMPLEMENTED;
+    }
+
+    /* Check for MAXMEM */
+    Status = BlGetBootOptionInteger(BlpApplicationEntry.BcdData,
+                                    BcdLibraryInteger_TruncatePhysicalMemory,
+                                    &HighestAddressValid);
+    if (NT_SUCCESS(Status))
+    {
+        EfiPrintf(L"/MAXMEM not supported\r\n");
+        return STATUS_NOT_IMPLEMENTED;
+    }
+
+    /* Return back to the caller */
     return STATUS_SUCCESS;
 }
 
@@ -84,13 +107,13 @@ MmPapAllocateRegionFromMdl (
     ListHead = CurrentList->First;
     if (Request->Type & BL_MM_REQUEST_TOP_DOWN_TYPE)
     {
-        NextEntry = ListHead->Flink;
-        TopDown = FALSE;
+        NextEntry = ListHead->Blink;
+        TopDown = TRUE;
     }
     else
     {
-        NextEntry = ListHead->Blink;
-        TopDown = TRUE;
+        NextEntry = ListHead->Flink;
+        TopDown = FALSE;
     }
 
     /* Loop through the list */
@@ -131,7 +154,7 @@ MmPapAllocateRegionFromMdl (
     /* Check if we exhausted the list */
     if (NextEntry == ListHead)
     {
-        EarlyPrint(L"No matching memory found\n");
+        EfiPrintf(L"No matching memory found\r\n");
         return Status;
     }
 
@@ -141,8 +164,8 @@ MmPapAllocateRegionFromMdl (
 
     /* Are we using the physical memory list, and are we OK with using firmware? */
     if ((CurrentList == &MmMdlUnmappedUnallocated) &&
-        !((Request->Flags & BL_MM_DESCRIPTOR_NEVER_USE_FIRMWARE_FLAG) ||
-          (LocalDescriptor.Flags & BL_MM_DESCRIPTOR_NEVER_USE_FIRMWARE_FLAG)))
+        !((Request->Flags & BlMemoryNonFirmware) ||
+          (LocalDescriptor.Flags & BlMemoryNonFirmware)))
     {
         /* Allocate the requested address from EFI */
         EfiAddress = LocalDescriptor.BasePage << PAGE_SHIFT;
@@ -151,7 +174,7 @@ MmPapAllocateRegionFromMdl (
                                   &EfiAddress);
         if (!NT_SUCCESS(Status))
         {
-            EarlyPrint(L"EFI memory allocation failure\n");
+            EfiPrintf(L"EFI memory allocation failure\r\n");
             return Status;
         }
 
@@ -165,14 +188,13 @@ MmPapAllocateRegionFromMdl (
     /* Are we allocating from the virtual memory list? */
     if (CurrentList == &MmMdlMappedUnallocated)
     {
-        EarlyPrint(L"Virtual memory not yet supported\n");
+        EfiPrintf(L"Virtual memory not yet supported\r\n");
         return STATUS_NOT_IMPLEMENTED;
     }
 
     /* Does the memory we received not exactly fall onto the beginning of its descriptor? */
     if (LocalDescriptor.BasePage != FoundDescriptor->BasePage)
     {
-        EarlyPrint(L"Local Page: %08I64X Found Page: %08I64X\n", LocalDescriptor.BasePage, FoundDescriptor->BasePage);
         TempDescriptor = MmMdInitByteGranularDescriptor(FoundDescriptor->Flags,
                                                         FoundDescriptor->Type,
                                                         FoundDescriptor->BasePage,
@@ -193,7 +215,6 @@ MmPapAllocateRegionFromMdl (
                           LocalDescriptor.VirtualPage + LocalDescriptor.PageCount : 0;
     if (LocalEndPage != FoundEndPage)
     {
-        EarlyPrint(L"Local Page: %08I64X Found Page: %08I64X\n", LocalEndPage, FoundEndPage);
         TempDescriptor = MmMdInitByteGranularDescriptor(FoundDescriptor->Flags,
                                                         FoundDescriptor->Type,
                                                         LocalEndPage,
@@ -222,7 +243,7 @@ MmPapAllocateRegionFromMdl (
         /* Remember if it came from EFI */
         if (GotFwPages)
         {
-            FoundDescriptor->Flags |= BL_MM_DESCRIPTOR_CAME_FROM_FIRMWARE_FLAG;
+            FoundDescriptor->Flags |= BlMemoryFirmware;
         }
 
         /* Add the descriptor to the requested list */
@@ -253,7 +274,7 @@ MmPaAllocatePages (
     /* Heap and page directory/table pages have a special flag */
     if ((MemoryType >= BlLoaderHeap) && (MemoryType <= BlLoaderReferencePage))
     {
-        Request->Flags |= BL_MM_DESCRIPTOR_SPECIAL_PAGES_FLAG;
+        Request->Flags |= BlMemorySpecial;
     }
 
     /* Try to find a free region of RAM matching this range and request */
@@ -266,7 +287,7 @@ MmPaAllocatePages (
     if (Status == STATUS_NOT_FOUND)
     {
         /* Need to re-synchronize the memory map and check other lists */
-        EarlyPrint(L"No RAM found -- backup plan not yet implemented\n");
+        EfiPrintf(L"No RAM found -- backup plan not yet implemented\r\n");
     }
 
     /* Did we get the region we wanted? */
@@ -277,7 +298,7 @@ MmPaAllocatePages (
     }
 
     /* Nope, we have to hunt for it elsewhere */
-    EarlyPrint(L"TODO\n");
+    EfiPrintf(L"TODO\r\n");
     return Status;
 }
 
@@ -334,7 +355,7 @@ MmPapAllocatePhysicalPagesInRange (
     Request.VirtualRange.Maximum = 0;
 
     /* Check if a fixed allocation was requested*/
-    if (Attributes & BL_MM_DESCRIPTOR_REQUIRES_FIXED_FLAG)
+    if (Attributes & BlMemoryFixed)
     {
         /* Force the only available range to be the passed in address */
         Request.BaseRange.Minimum = BaseAddress->QuadPart >> PAGE_SHIFT;
@@ -391,7 +412,7 @@ Quickie:
 
 NTSTATUS
 MmPapAllocatePagesInRange (
-    _Inout_ PULONG PhysicalAddress,
+    _Inout_ PVOID* PhysicalAddress,
     _In_ BL_MEMORY_TYPE MemoryType,
     _In_ ULONGLONG Pages,
     _In_ ULONG Attributes,
@@ -425,8 +446,7 @@ MmPapAllocatePagesInRange (
     else
     {
         /* Check if this is a fixed allocation */
-        BaseAddress.QuadPart = (Attributes & BL_MM_DESCRIPTOR_REQUIRES_FIXED_FLAG) ?
-                               *PhysicalAddress : 0;
+        BaseAddress.QuadPart = (Attributes & BlMemoryFixed) ? (ULONG_PTR)*PhysicalAddress : 0;
 
         /* Allocate the pages */
         Status = MmPapAllocatePhysicalPagesInRange(&BaseAddress,
@@ -442,7 +462,7 @@ MmPapAllocatePagesInRange (
                                                    Type);
 
         /* Return the allocated address */
-        *PhysicalAddress = BaseAddress.LowPart;
+        *PhysicalAddress = (PVOID)BaseAddress.LowPart;
     }
 
 Exit:
@@ -489,14 +509,14 @@ MmPaInitialize (
         PLIST_ENTRY listHead, nextEntry;
 
         /* Loop the NT firmware memory list */
-        EarlyPrint(L"NT MEMORY MAP\n\n");
+        EfiPrintf(L"NT MEMORY MAP\n\r\n");
         listHead = &MmMdlUnmappedUnallocated.ListHead;
         nextEntry = listHead->Flink;
         while (listHead != nextEntry)
         {
             Descriptor = CONTAINING_RECORD(nextEntry, BL_MEMORY_DESCRIPTOR, ListEntry);
 
-            EarlyPrint(L"Type: %08lX Flags: %08lX Base: 0x%016I64X End: 0x%016I64X\n",
+            EfiPrintf(L"Type: %08lX Flags: %08lX Base: 0x%016I64X End: 0x%016I64X\r\n",
                        Descriptor->Type,
                        Descriptor->Flags,
                        Descriptor->BasePage << PAGE_SHIFT,
@@ -569,4 +589,475 @@ MmPaInitialize (
     return Status;
 }
 
+NTSTATUS
+BlMmAllocatePhysicalPages( 
+    _In_ PPHYSICAL_ADDRESS Address,
+    _In_ BL_MEMORY_TYPE MemoryType,
+    _In_ ULONGLONG PageCount,
+    _In_ ULONG Attributes,
+    _In_ ULONG Alignment
+    )
+{
+    /* Call the physical allocator */
+    return MmPapAllocatePhysicalPagesInRange(Address,
+                                             MemoryType,
+                                             PageCount,
+                                             Attributes,
+                                             Alignment,
+                                             &MmMdlUnmappedAllocated,
+                                             NULL,
+                                             0);
+}
+
+NTSTATUS
+MmPapFreePhysicalPages (
+    _In_ ULONG WhichList,
+    _In_ ULONGLONG PageCount,
+    _In_ PHYSICAL_ADDRESS Address
+    )
+{
+    PBL_MEMORY_DESCRIPTOR Descriptor;
+    ULONGLONG Page;
+    ULONG DescriptorFlags, Flags;
+    BOOLEAN DontFree, HasPageData;
+    BL_LIBRARY_PARAMETERS LibraryParameters;
+    NTSTATUS Status;
+
+    /* Set some defaults */
+    Flags = BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG;
+    DontFree = FALSE;
+    HasPageData = FALSE;
+
+    /* Only page-aligned addresses a re accepted */
+    if (Address.QuadPart & (PAGE_SIZE - 1))
+    {
+        EfiPrintf(L"free mem fail 1\r\n");
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Try to find the descriptor containing this address */
+    Page = Address.QuadPart >> PAGE_SHIFT;
+    Descriptor = MmMdFindDescriptor(WhichList,
+                                    BL_MM_REMOVE_PHYSICAL_REGION_FLAG,
+                                    Page);
+    if (!Descriptor)
+    {
+        EfiPrintf(L"free mem fail 2\r\n");
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* If a page count was given, it must match, unless it's coalesced */
+    DescriptorFlags = Descriptor->Flags;
+    if (!(DescriptorFlags & BlMemoryCoalesced) &&
+        (PageCount) && (PageCount != Descriptor->PageCount))
+    {
+        EfiPrintf(L"free mem fail 3\r\n");
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Check if this is persistent memory in teardown status */
+    if ((PapInitializationStatus == 2) &&
+        (DescriptorFlags & BlMemoryPersistent))
+    {
+        /* Then we should keep it */
+        DontFree = TRUE;
+    }
+    else
+    {
+        /* Mark it as non-persistent, since we're freeing it */
+        Descriptor->Flags &= ~BlMemoryPersistent;
+    }
+
+    /* Check if this memory contains paging data */
+    if ((Descriptor->Type == BlLoaderPageDirectory) ||
+        (Descriptor->Type == BlLoaderReferencePage))
+    {
+        HasPageData = TRUE;
+    }
+
+    /* Check if a page count was given */
+    if (PageCount)
+    {
+        /* The pages must fit within the descriptor */
+        if ((PageCount + Page - Descriptor->BasePage) > Descriptor->PageCount)
+        {
+            EfiPrintf(L"free mem fail 4\r\n");
+            return STATUS_INVALID_PARAMETER;
+        }
+    }
+    else
+    {
+        /* No page count given, so the address must be at the beginning then */
+        if (Descriptor->BasePage != Page)
+        {
+            EfiPrintf(L"free mem fail 5\r\n");
+            return STATUS_INVALID_PARAMETER;
+        }
+
+        /* And we'll use the page count in the descriptor */
+        PageCount = Descriptor->PageCount;
+    }
+
+    /* Copy library parameters since we will read them */
+    RtlCopyMemory(&LibraryParameters,
+                  &BlpLibraryParameters,
+                  sizeof(LibraryParameters));
+
+    /* Check if this is teardown */
+    if (PapInitializationStatus == 2)
+    {
+        EfiPrintf(L"Case 2 not yet handled!\r\n");
+        return STATUS_NOT_SUPPORTED;
+    }
+    else if (!DontFree)
+    {
+        /* Caller wants memory to be freed -- should we zero it? */
+        if (!(HasPageData) &
+            (LibraryParameters.LibraryFlags &
+             BL_LIBRARY_FLAG_ZERO_HEAP_ALLOCATIONS_ON_FREE))
+        {
+            EfiPrintf(L"Freeing zero data not yet handled!\r\n");
+            return STATUS_NOT_SUPPORTED;
+        }
+    }
+
+    /* Now call into firmware to actually free the physical pages */
+    Status = MmFwFreePages(Page, PageCount);
+    if (!NT_SUCCESS(Status))
+    {
+        EfiPrintf(L"free mem fail 6\r\n");
+        return Status;
+    }
+
+    /* Remove the firmware flags */
+    Descriptor->Flags &= ~(BlMemoryNonFirmware |
+                           BlMemoryFirmware |
+                           BlMemoryPersistent);
+
+    /* If we're not actually freeing, don't coalesce with anyone nearby */
+    if (DontFree)
+    {
+        Flags |= BL_MM_ADD_DESCRIPTOR_NEVER_COALESCE_FLAG;
+    }
+
+    /* TBD */
+    EfiPrintf(L"Leaking memory: %p!\r\n", Address.QuadPart);
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+BlMmFreePhysicalPages (
+    _In_ PHYSICAL_ADDRESS Address
+    )
+{
+    /* Call the physical allocator */
+    return MmPapFreePhysicalPages(BL_MM_INCLUDE_UNMAPPED_ALLOCATED, 0, Address);
+}
+
+NTSTATUS
+MmPapFreePages (
+    _In_ PVOID Address,
+    _In_ ULONG WhichList
+    )
+{
+    PHYSICAL_ADDRESS PhysicalAddress;
+
+    /* Handle virtual memory scenario */
+    if (MmTranslationType != BlNone)
+    {
+        EfiPrintf(L"Unimplemented virtual path\r\n");
+        return STATUS_SUCCESS;
+    }
+
+    /* Physical memory should be in the unmapped allocated list */
+    if (WhichList != BL_MM_INCLUDE_PERSISTENT_MEMORY)
+    {
+        WhichList = BL_MM_INCLUDE_UNMAPPED_ALLOCATED;
+    }
+
+    /* Free it from there */
+    PhysicalAddress.QuadPart = (ULONG_PTR)Address;
+    return MmPapFreePhysicalPages(WhichList, 0, PhysicalAddress);
+}
+
+NTSTATUS
+BlMmGetMemoryMap (
+    _In_ PLIST_ENTRY MemoryMap,
+    _In_ PBL_IMAGE_PARAMETERS MemoryParameters,
+    _In_ ULONG WhichTypes,
+    _In_ ULONG Flags
+    )
+{
+    BL_MEMORY_DESCRIPTOR_LIST FirmwareMdList, FullMdList;
+    BOOLEAN DoFirmware, DoPersistent, DoTruncated, DoBad;
+    BOOLEAN DoReserved, DoUnmapUnalloc, DoUnmapAlloc;
+    BOOLEAN DoMapAlloc, DoMapUnalloc, DoFirmware2;
+    ULONG LoopCount, MdListCount, MdListSize, Used;
+    NTSTATUS Status;
+
+    /* Initialize the firmware list if we use it */
+    MmMdInitializeListHead(&FirmwareMdList);
+
+    /* Make sure we got our input parameters */
+    if (!(MemoryMap) || !(MemoryParameters))
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Either ask for firmware memory, or don't. Not neither */
+    if ((WhichTypes & ~BL_MM_INCLUDE_NO_FIRMWARE_MEMORY) &&
+        (WhichTypes & ~BL_MM_INCLUDE_ONLY_FIRMWARE_MEMORY))
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Either ask for firmware memory, or don't. Not both */
+    if ((WhichTypes & BL_MM_INCLUDE_NO_FIRMWARE_MEMORY) &&
+        (WhichTypes & BL_MM_INCLUDE_ONLY_FIRMWARE_MEMORY))
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Initialize the memory map list */
+    InitializeListHead(MemoryMap);
+
+    /* Check which types of memory to dump */
+    DoFirmware = WhichTypes & BL_MM_INCLUDE_FIRMWARE_MEMORY;
+    DoPersistent = WhichTypes & BL_MM_INCLUDE_PERSISTENT_MEMORY;
+    DoTruncated = WhichTypes & BL_MM_INCLUDE_TRUNCATED_MEMORY;
+    DoBad = WhichTypes & BL_MM_INCLUDE_BAD_MEMORY;
+    DoReserved = WhichTypes & BL_MM_INCLUDE_RESERVED_ALLOCATED;
+    DoUnmapUnalloc = WhichTypes & BL_MM_INCLUDE_UNMAPPED_UNALLOCATED;
+    DoUnmapAlloc = WhichTypes & BL_MM_INCLUDE_UNMAPPED_ALLOCATED;
+    DoMapAlloc = WhichTypes & BL_MM_INCLUDE_MAPPED_ALLOCATED;
+    DoMapUnalloc = WhichTypes & BL_MM_INCLUDE_MAPPED_UNALLOCATED;
+    DoFirmware2 = WhichTypes & BL_MM_INCLUDE_FIRMWARE_MEMORY_2;
+
+    /* Begin the attempt loop */
+    LoopCount = 0;
+    while (TRUE)
+    {
+        /* Count how many entries we will need */
+        MdListCount = 0;
+        if (DoMapAlloc) MdListCount = MmMdCountList(&MmMdlMappedAllocated);
+        if (DoMapUnalloc) MdListCount += MmMdCountList(&MmMdlMappedUnallocated);
+        if (DoUnmapAlloc) MdListCount += MmMdCountList(&MmMdlUnmappedAllocated);
+        if (DoUnmapUnalloc) MdListCount += MmMdCountList(&MmMdlUnmappedUnallocated);
+        if (DoReserved) MdListCount += MmMdCountList(&MmMdlReservedAllocated);
+        if (DoBad) MdListCount += MmMdCountList(&MmMdlBadMemory);
+        if (DoTruncated) MdListCount += MmMdCountList(&MmMdlTruncatedMemory);
+        if (DoPersistent) MdListCount += MmMdCountList(&MmMdlPersistentMemory);
+
+        /* Plus firmware entries */
+        if (DoFirmware)
+        {
+            /* Free the previous entries, if any */
+            MmMdFreeList(&FirmwareMdList);
+
+            /* Get the firmware map */
+            Status = MmFwGetMemoryMap(&FirmwareMdList, 2);
+            if (!NT_SUCCESS(Status))
+            {
+                goto Quickie;
+            }
+
+            /* We overwrite, since this type is exclusive */
+            MdListCount = MmMdCountList(&FirmwareMdList);
+        }
+
+        /* Plus firmware entries-2 */
+        if (DoFirmware2)
+        {
+            /* Free the previous entries, if any */
+            MmMdFreeList(&FirmwareMdList);
+
+            /* Get the firmware map */
+            Status = MmFwGetMemoryMap(&FirmwareMdList, 0);
+            if (!NT_SUCCESS(Status))
+            {
+                goto Quickie;
+            }
+
+            /* We overwrite, since this type is exclusive */
+            MdListCount = MmMdCountList(&FirmwareMdList);
+        }
+
+        /* If there's no descriptors, we're done */
+        if (!MdListCount)
+        {
+            Status = STATUS_SUCCESS;
+            goto Quickie;
+        }
+
+        /* Check if the buffer we have is big enough */
+        if (MemoryParameters->BufferSize >=
+            (sizeof(BL_MEMORY_DESCRIPTOR) * MdListCount))
+        {
+            break;
+        }
+
+        /* It's not, allocate it, with a slack of 4 extra descriptors */
+        MdListSize = sizeof(BL_MEMORY_DESCRIPTOR) * (MdListCount + 4);
+
+        /* Except if we weren't asked to */
+        if (!(Flags & BL_MM_ADD_DESCRIPTOR_ALLOCATE_FLAG))
+        {
+            MemoryParameters->BufferSize = MdListSize;
+            Status = STATUS_BUFFER_TOO_SMALL;
+            goto Quickie;
+        }
 
+        /* Has it been less than 4 times we've tried this? */
+        if (++LoopCount <= 4)
+        {
+            /* Free the previous attempt, if any */
+            if (MemoryParameters->BufferSize)
+            {
+                BlMmFreeHeap(MemoryParameters->Buffer);
+            }
+
+            /* Allocate a new buffer */
+            MemoryParameters->BufferSize = MdListSize;
+            MemoryParameters->Buffer = BlMmAllocateHeap(MdListSize);
+            if (MemoryParameters->Buffer)
+            {
+                /* Try again */
+                continue;
+            }
+        }
+
+        /* If we got here, we're out of memory after 4 attempts */
+        Status = STATUS_NO_MEMORY;
+        goto Quickie;
+    }
+
+    /* We should have a buffer by now... */
+    if (MemoryParameters->Buffer)
+    {
+        /* Zero it out */
+        RtlZeroMemory(MemoryParameters->Buffer,
+                      MdListCount * sizeof(BL_MEMORY_DESCRIPTOR));
+    }
+
+    /* Initialize our list of descriptors */
+    MmMdInitializeList(&FullMdList, 0, MemoryMap);
+    Used = 0;
+
+    /* Handle mapped, allocated */
+    if (DoMapAlloc)
+    {
+        Status = MmMdCopyList(&FullMdList,
+                              &MmMdlMappedAllocated,
+                              MemoryParameters->Buffer,
+                              &Used,
+                              MdListCount,
+                              Flags);
+    }
+
+    /* Handle mapped, unallocated */
+    if (DoMapUnalloc)
+    {
+        Status = MmMdCopyList(&FullMdList,
+                              &MmMdlMappedUnallocated,
+                              MemoryParameters->Buffer,
+                              &Used,
+                              MdListCount,
+                              Flags);
+    }
+
+    /* Handle unmapped, allocated */
+    if (DoUnmapAlloc)
+    {
+        Status = MmMdCopyList(&FullMdList,
+                              &MmMdlUnmappedAllocated,
+                              MemoryParameters->Buffer,
+                              &Used,
+                              MdListCount,
+                              Flags);
+    }
+
+    /* Handle unmapped, unallocated */
+    if (DoUnmapUnalloc)
+    {
+        Status = MmMdCopyList(&FullMdList,
+                              &MmMdlUnmappedUnallocated,
+                              MemoryParameters->Buffer,
+                              &Used,
+                              MdListCount,
+                              Flags);
+    }
+
+    /* Handle reserved, allocated */
+    if (DoReserved)
+    {
+        Status = MmMdCopyList(&FullMdList,
+                              &MmMdlReservedAllocated,
+                              MemoryParameters->Buffer,
+                              &Used,
+                              MdListCount,
+                              Flags);
+    }
+
+    /* Handle bad */
+    if (DoBad)
+    {
+        Status = MmMdCopyList(&FullMdList,
+                              &MmMdlBadMemory,
+                              MemoryParameters->Buffer,
+                              &Used,
+                              MdListCount,
+                              Flags);
+    }
+
+    /* Handle truncated */
+    if (DoTruncated)
+    {
+        Status = MmMdCopyList(&FullMdList,
+                              &MmMdlTruncatedMemory,
+                              MemoryParameters->Buffer,
+                              &Used,
+                              MdListCount,
+                              Flags);
+    }
+
+    /* Handle persistent */
+    if (DoPersistent)
+    {
+        Status = MmMdCopyList(&FullMdList,
+                              &MmMdlPersistentMemory,
+                              MemoryParameters->Buffer,
+                              &Used,
+                              MdListCount,
+                              Flags);
+    }
+
+    /* Handle firmware */
+    if (DoFirmware)
+    {
+        Status = MmMdCopyList(&FullMdList,
+                              &FirmwareMdList,
+                              MemoryParameters->Buffer,
+                              &Used,
+                              MdListCount,
+                              Flags);
+    }
+
+    /* Handle firmware2 */
+    if (DoFirmware2)
+    {
+        Status = MmMdCopyList(&FullMdList,
+                              &FirmwareMdList,
+                              MemoryParameters->Buffer,
+                              &Used,
+                              MdListCount,
+                              Flags);
+    }
+
+    /* Add up the final size */
+    Status = RtlULongLongToULong(Used * sizeof(BL_MEMORY_DESCRIPTOR),
+                                 &MemoryParameters->ActualSize);
+
+Quickie:
+    MmMdFreeList(&FirmwareMdList);
+    return Status;
+}