[BOOTMGR]: Fix bug in test.
authorAlex Ionescu <aionescu@gmail.com>
Sun, 5 Feb 2017 21:50:14 +0000 (21:50 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Sun, 5 Feb 2017 21:50:14 +0000 (21:50 +0000)
[BOOTLIB]: Fix bug in MmMdFindDescriptorFromMdl.
[BOOTLIB]: Implement MmFwFreePages.
[BOOTLIB]: Implement most of MmPapFreePhysicalPages. The rest is coming next.
[BOOTMGR]: Add test for alloc/free.

svn path=/trunk/; revision=73716

reactos/boot/environ/app/bootmgr/bootmgr.c
reactos/boot/environ/include/bl.h
reactos/boot/environ/lib/firmware/fwutil.c
reactos/boot/environ/lib/mm/descriptor.c
reactos/boot/environ/lib/mm/pagealloc.c

index 8da61c7..8b1ef5d 100644 (file)
@@ -2902,12 +2902,6 @@ BmMain (
         NTSTATUS Status;
         PHYSICAL_ADDRESS PhysicalAddress;
         PBL_MEMORY_DESCRIPTOR Found;
-        PBL_MEMORY_DESCRIPTOR
-            MmMdFindDescriptor (
-                _In_ ULONG WhichList,
-                _In_ ULONG Flags,
-                _In_ ULONGLONG Page
-            );
 
         /* Allocate 1 physical page */
         PhysicalAddress.QuadPart = 0;
@@ -2915,8 +2909,11 @@ BmMain (
         EfiPrintf(L"Allocation status: %lx at address: %llx\r\n", Status, PhysicalAddress.QuadPart);
         EfiStall(10000);
 
-        Found = MmMdFindDescriptor(BL_MM_INCLUDE_UNMAPPED_ALLOCATED, 0, PhysicalAddress.QuadPart);
+        Found = MmMdFindDescriptor(BL_MM_INCLUDE_UNMAPPED_ALLOCATED, 0, PhysicalAddress.QuadPart >> PAGE_SHIFT);
         EfiPrintf(L"Found descriptor: %p %llx\r\n", Found, Found->BasePage);
+
+        Status = BlMmFreePhysicalPages(PhysicalAddress);
+        EfiPrintf(L"Memory free status: %lx\r\n", Status);
     }
 
 
index 6ade600..9d06f98 100644 (file)
@@ -122,6 +122,7 @@ C_ASSERT(BL_MM_INCLUDE_ONLY_FIRMWARE_MEMORY == 0x240);
 #define BL_MM_REQUEST_DEFAULT_TYPE                      1
 #define BL_MM_REQUEST_TOP_DOWN_TYPE                     2
 
+#define BL_MM_REMOVE_PHYSICAL_REGION_FLAG               0x40000000
 #define BL_MM_REMOVE_VIRTUAL_REGION_FLAG                0x80000000
 
 #define BL_LIBRARY_FLAG_NO_DISPLAY                      0x01
@@ -374,9 +375,10 @@ typedef enum _BL_MEMORY_ATTR
     BlMemoryCoalesced =         0x02000000,
     BlMemoryUpdate =            0x04000000,
     BlMemoryNonFirmware =       0x08000000,
+    BlMemoryPersistent =        0x10000000,
     BlMemorySpecial =           0x20000000,
     BlMemoryFirmware =          0x80000000,
-    BlMemoryValidTypeAttributes             = BlMemoryRuntime | BlMemoryCoalesced | BlMemoryUpdate | BlMemoryNonFirmware | BlMemorySpecial | BlMemoryFirmware,
+    BlMemoryValidTypeAttributes             = BlMemoryRuntime | BlMemoryCoalesced | BlMemoryUpdate | BlMemoryNonFirmware | BlMemoryPersistent | BlMemorySpecial | BlMemoryFirmware,
     BlMemoryValidTypeAttributeMask          = 0xFF000000,
 } BL_MEMORY_ATTR;
 
@@ -1541,6 +1543,12 @@ EfipGetRsdt (
     _Out_ PPHYSICAL_ADDRESS FoundRsdt
     );
 
+NTSTATUS
+EfiFreePages (
+    _In_ ULONG Pages,
+    _In_ EFI_PHYSICAL_ADDRESS PhysicalAddress
+    );
+
 /* PLATFORM TIMER ROUTINES ***************************************************/
 
 NTSTATUS
@@ -1711,6 +1719,12 @@ BlFwReboot (
     VOID
     );
 
+NTSTATUS
+MmFwFreePages (
+    _In_ ULONG BasePage,
+    _In_ ULONG PageCount
+    );
+
 PGUID
 BlGetApplicationIdentifier (
     VOID
@@ -1989,6 +2003,13 @@ MmMdInitializeList (
     _In_ PLIST_ENTRY ListHead
     );
 
+PBL_MEMORY_DESCRIPTOR
+MmMdFindDescriptor (
+    _In_ ULONG WhichList,
+    _In_ ULONG Flags,
+    _In_ ULONGLONG Page
+    );
+
 NTSTATUS
 MmMdCopyList (
     _In_ PBL_MEMORY_DESCRIPTOR_LIST DestinationList,
index 17010bd..b408f69 100644 (file)
@@ -24,3 +24,12 @@ BlFwReboot (
     EfiResetSystem(EfiResetCold);
 }
 
+NTSTATUS
+MmFwFreePages (
+    _In_ ULONG BasePage,
+    _In_ ULONG PageCount
+    )
+{
+    /* Free the pages */
+    return EfiFreePages(PageCount, BasePage << PAGE_SHIFT);
+}
index 808be81..c2522bc 100644 (file)
@@ -857,7 +857,7 @@ MmMdFindDescriptorFromMdl (
             (Page < (BasePage + Current->PageCount)))
         {
             /* The descriptor fits the page being requested */
-            break;
+            return Current;
         }
 
         /* Try the next one */
index d26853d..dd7cbd0 100644 (file)
@@ -616,6 +616,130 @@ MmPapFreePhysicalPages (
     _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;