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;
+ }
+
+ /* Check if the entire allocation is being free*/
+ if (PageCount == Descriptor->PageCount)
+ {
+ /* Remove the descriptor from the allocated list */
+ MmMdRemoveDescriptorFromList(&MmMdlUnmappedAllocated, Descriptor);
+
+ /* Mark the entire descriptor as free */
+ Descriptor->Type = BlConventionalMemory;
+ }
+ else
+ {
+ /* Init a descriptor for what we're actually freeing */
+ Descriptor = MmMdInitByteGranularDescriptor(Descriptor->Flags,
+ BlConventionalMemory,
+ Page,
+ 0,
+ PageCount);
+ if (!Descriptor)
+ {
+ return STATUS_NO_MEMORY;
+ }
+
+ /* Remove the region from the existing descriptor */
+ Status = MmMdRemoveRegionFromMdlEx(&MmMdlUnmappedAllocated,
+ BL_MM_REMOVE_PHYSICAL_REGION_FLAG,
+ Page,
+ PageCount,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
+
+ /* Add the new descriptor into in the list (or the old, repurposed one) */
+ Descriptor->Flags &= ~BlMemoryCoalesced;
+ return MmMdAddDescriptorToList(&MmMdlUnmappedUnallocated, Descriptor, Flags);
+}
+
NTSTATUS
BlMmFreePhysicalPages (
_In_ PHYSICAL_ADDRESS Address
)
{
/* Call the physical allocator */
- EfiPrintf(L"Leaking memory: %p!\r\n", Address.QuadPart);
- return STATUS_SUCCESS;
- //return MmPapFreePhysicalPages(4, 0, Address);
+ return MmPapFreePhysicalPages(BL_MM_INCLUDE_UNMAPPED_ALLOCATED, 0, Address);
}
NTSTATUS
_In_ ULONG WhichList
)
{
- EfiPrintf(L"Leaking memory: %p!\r\n", Address);
- return STATUS_SUCCESS;
+ 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
/* Free the previous entries, if any */
MmMdFreeList(&FirmwareMdList);
- /* Get the firmware map */
- Status = MmFwGetMemoryMap(&FirmwareMdList, 2);
+ /* Get the firmware map, coalesced */
+ Status = MmFwGetMemoryMap(&FirmwareMdList,
+ BL_MM_FLAG_REQUEST_COALESCING);
if (!NT_SUCCESS(Status))
{
goto Quickie;
/* Free the previous entries, if any */
MmMdFreeList(&FirmwareMdList);
- /* Get the firmware map */
+ /* Get the firmware map, uncoalesced */
Status = MmFwGetMemoryMap(&FirmwareMdList, 0);
if (!NT_SUCCESS(Status))
{