From 16fa7d18c53ad4c0086499c5087439f97449928a Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Sun, 5 Feb 2017 21:50:14 +0000 Subject: [PATCH] [BOOTMGR]: Fix bug in test. [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 | 11 +- reactos/boot/environ/include/bl.h | 23 +++- reactos/boot/environ/lib/firmware/fwutil.c | 9 ++ reactos/boot/environ/lib/mm/descriptor.c | 2 +- reactos/boot/environ/lib/mm/pagealloc.c | 124 +++++++++++++++++++++ 5 files changed, 160 insertions(+), 9 deletions(-) diff --git a/reactos/boot/environ/app/bootmgr/bootmgr.c b/reactos/boot/environ/app/bootmgr/bootmgr.c index 8da61c7d7bb..8b1ef5d7b76 100644 --- a/reactos/boot/environ/app/bootmgr/bootmgr.c +++ b/reactos/boot/environ/app/bootmgr/bootmgr.c @@ -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); } diff --git a/reactos/boot/environ/include/bl.h b/reactos/boot/environ/include/bl.h index 6ade600762e..9d06f98dbfb 100644 --- a/reactos/boot/environ/include/bl.h +++ b/reactos/boot/environ/include/bl.h @@ -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, diff --git a/reactos/boot/environ/lib/firmware/fwutil.c b/reactos/boot/environ/lib/firmware/fwutil.c index 17010bdc402..b408f69c578 100644 --- a/reactos/boot/environ/lib/firmware/fwutil.c +++ b/reactos/boot/environ/lib/firmware/fwutil.c @@ -24,3 +24,12 @@ BlFwReboot ( EfiResetSystem(EfiResetCold); } +NTSTATUS +MmFwFreePages ( + _In_ ULONG BasePage, + _In_ ULONG PageCount + ) +{ + /* Free the pages */ + return EfiFreePages(PageCount, BasePage << PAGE_SHIFT); +} diff --git a/reactos/boot/environ/lib/mm/descriptor.c b/reactos/boot/environ/lib/mm/descriptor.c index 808be81b28f..c2522bc1687 100644 --- a/reactos/boot/environ/lib/mm/descriptor.c +++ b/reactos/boot/environ/lib/mm/descriptor.c @@ -857,7 +857,7 @@ MmMdFindDescriptorFromMdl ( (Page < (BasePage + Current->PageCount))) { /* The descriptor fits the page being requested */ - break; + return Current; } /* Try the next one */ diff --git a/reactos/boot/environ/lib/mm/pagealloc.c b/reactos/boot/environ/lib/mm/pagealloc.c index d26853dec51..dd7cbd06a2e 100644 --- a/reactos/boot/environ/lib/mm/pagealloc.c +++ b/reactos/boot/environ/lib/mm/pagealloc.c @@ -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; -- 2.17.1