[BOOTLIB]: Implement MmArchTranslateVirtualAddress for non-paging mode. Stub Mmx86Tra...
[reactos.git] / reactos / boot / environ / lib / mm / pagealloc.c
index 2b682a1..22b926a 100644 (file)
@@ -195,7 +195,6 @@ MmPapAllocateRegionFromMdl (
     /* 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,
@@ -216,7 +215,6 @@ MmPapAllocateRegionFromMdl (
                           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,
@@ -611,13 +609,490 @@ BlMmAllocatePhysicalPages(
                                              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;
 }