/* Does the memory we received not exactly fall onto the beginning of its descriptor? */
if (LocalDescriptor.BasePage != FoundDescriptor->BasePage)
{
- EfiPrintf(L"Local Page: %08I64X Found Page: %08I64X\r\n", LocalDescriptor.BasePage, FoundDescriptor->BasePage);
TempDescriptor = MmMdInitByteGranularDescriptor(FoundDescriptor->Flags,
FoundDescriptor->Type,
FoundDescriptor->BasePage,
LocalDescriptor.VirtualPage + LocalDescriptor.PageCount : 0;
if (LocalEndPage != FoundEndPage)
{
- EfiPrintf(L"Local Page: %08I64X Found Page: %08I64X\r\n", LocalEndPage, FoundEndPage);
TempDescriptor = MmMdInitByteGranularDescriptor(FoundDescriptor->Flags,
FoundDescriptor->Type,
LocalEndPage,
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!\r\n");
- return STATUS_SUCCESS;
- //return MmPapFreePhysicalPages(4, 0, Address);
+ 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, coalesced */
+ Status = MmFwGetMemoryMap(&FirmwareMdList,
+ BL_MM_FLAG_REQUEST_COALESCING);
+ 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, uncoalesced */
+ 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;
}