[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
This commit is contained in:
Alex Ionescu 2017-02-05 21:50:14 +00:00
parent b5f0b7d584
commit 16fa7d18c5
5 changed files with 160 additions and 9 deletions

View 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);
}

View 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,

View 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);
}

View file

@ -857,7 +857,7 @@ MmMdFindDescriptorFromMdl (
(Page < (BasePage + Current->PageCount)))
{
/* The descriptor fits the page being requested */
break;
return Current;
}
/* Try the next one */

View 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;