[BOOTMGR]: Fix bug in test.
[reactos.git] / reactos / boot / environ / lib / mm / descriptor.c
index ea9415d..c2522bc 100644 (file)
@@ -15,7 +15,7 @@
 BL_MEMORY_DESCRIPTOR MmStaticMemoryDescriptors[512];
 ULONG MmGlobalMemoryDescriptorCount;
 PBL_MEMORY_DESCRIPTOR MmGlobalMemoryDescriptors;
-BOOLEAN MmGlobalMemoryDescriptorsUsed;
+ULONG MmGlobalMemoryDescriptorsUsed;
 PBL_MEMORY_DESCRIPTOR MmDynamicMemoryDescriptors;
 ULONG MmDynamicMemoryDescriptorCount;
 
@@ -44,19 +44,19 @@ MmMdpHasPrecedence (
     BL_MEMORY_CLASS Class1, Class2;
     ULONG i, j;
 
-    /* Descriptor is free RAM -- it preceeds */
+    /* Descriptor is free RAM -- it precedes */
     if (Type1 == BlConventionalMemory)
     {
         return TRUE;
     }
 
-    /* It isn't free RAM, but the comparator is -- it suceeds it */
+    /* It isn't free RAM, but the comparator is -- it succeeds it */
     if (Type2 == BlConventionalMemory)
     {
         return FALSE;
     }
 
-    /* Descriptor is not system, application, or loader class -- it preceeds */
+    /* Descriptor is not system, application, or loader class -- it precedes */
     Class1 = Type1 >> BL_MEMORY_CLASS_SHIFT;
     if ((Class1 != BlSystemClass) &&
         (Class1 != BlApplicationClass) &&
@@ -65,7 +65,7 @@ MmMdpHasPrecedence (
         return TRUE;
     }
 
-    /* It isn't one of those classes, but the comparator it -- it suceeds it */
+    /* It isn't one of those classes, but the comparator it -- it succeeds it */
     Class2 = Type2 >> BL_MEMORY_CLASS_SHIFT;
     if ((Class2 != BlSystemClass) &&
         (Class2 != BlApplicationClass) &&
@@ -124,23 +124,23 @@ MmMdpHasPrecedence (
             }
         }
 
-        /* The comparator isn't system, so it preceeds it */
+        /* The comparator isn't system, so it precedes it */
         return TRUE;
     }
 
-    /* Descriptor is not system class, but comparator is -- it suceeds it */
+    /* Descriptor is not system class, but comparator is -- it succeeds it */
     if (Class2 == BlSystemClass)
     {
         return FALSE;
     }
 
-    /* Descriptor is loader class -- it preceeds */
+    /* Descriptor is loader class -- it precedes */
     if (Class1 == BlLoaderClass)
     {
         return TRUE;
     }
 
-    /* It isn't loader class  -- if the other guy is, suceed it */
+    /* It isn't loader class  -- if the other guy is, succeed it */
     return Class2 != BlLoaderClass;
 }
 
@@ -149,7 +149,7 @@ MmMdpSwitchToDynamicDescriptors (
     _In_ ULONG Count
     )
 {
-    EarlyPrint(L"NOT SUPPORTED!!!\n");
+    EfiPrintf(L"dynamic switch NOT SUPPORTED!!!\r\n");
     while (1);
 }
 
@@ -173,7 +173,7 @@ MmMdFreeDescriptor (
     else
     {
         /* It's a dynamic descriptor, so free it */
-        EarlyPrint(L"Dynamic descriptors not yet supported\n");
+        EfiPrintf(L"Dynamic descriptors not yet supported\r\n");
         Status = STATUS_NOT_IMPLEMENTED;
     }
 
@@ -197,6 +197,139 @@ MmMdpSaveCurrentListPointer (
     }
 }
 
+ULONG
+MmMdCountList (
+    _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
+    )
+{
+    PLIST_ENTRY First, NextEntry;
+    ULONG Count;
+    
+    /* Iterate the list */
+    for (Count = 0, First = MdList->First, NextEntry = First->Flink;
+         NextEntry != First;
+         NextEntry = NextEntry->Flink, Count++);
+
+    /* Return the count */
+    return Count;
+}
+
+VOID
+MmMdInitializeList (
+    _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList, 
+    _In_ ULONG Type,
+    _In_ PLIST_ENTRY ListHead
+    )
+{
+    /* Check if a list was specified */
+    if (ListHead)
+    {
+        /* Use it */
+        MdList->First = ListHead;
+    }
+    else
+    {
+        /* Otherwise, use the internal, built-in list */
+        InitializeListHead(&MdList->ListHead);
+        MdList->First = &MdList->ListHead;
+    }
+
+    /* Set the type */
+    MdList->Type = Type;
+
+    /* Initialize current iterator to nothing */
+    MdList->This = NULL;
+}
+
+NTSTATUS
+MmMdCopyList (
+    _In_ PBL_MEMORY_DESCRIPTOR_LIST DestinationList, 
+    _In_ PBL_MEMORY_DESCRIPTOR_LIST SourceList,
+    _In_opt_ PBL_MEMORY_DESCRIPTOR ListDescriptor,
+    _Out_ PULONG ActualCount, 
+    _In_ ULONG Count,
+    _In_ ULONG Flags
+    )
+{
+    NTSTATUS Status;
+    PULONG Used;
+    PLIST_ENTRY First, NextEntry;
+    PBL_MEMORY_DESCRIPTOR Descriptor;
+
+    /* Both parameters must be present */
+    if (!(DestinationList) || !(SourceList))
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Assume success */
+    Status = STATUS_SUCCESS;
+
+    /* Check if a descriptor is being used to store the list */
+    if (ListDescriptor)
+    {
+        /* See how big it is */
+        Flags |= BL_MM_ADD_DESCRIPTOR_NEVER_COALESCE_FLAG;
+        Used = ActualCount;
+    }
+    else
+    {
+        /* We are using our internal descriptors instead */
+        Used = &MmGlobalMemoryDescriptorsUsed;
+        ++MmDescriptorCallTreeCount;
+
+        /* Use as many as are available */
+        Count = MmGlobalMemoryDescriptorCount;
+        ListDescriptor = MmGlobalMemoryDescriptors;
+    }
+    
+    /* Never truncate descriptors during a list copy */
+    Flags |= BL_MM_ADD_DESCRIPTOR_NEVER_TRUNCATE_FLAG;
+
+    /* Iterate through the list */
+    First = SourceList->First;
+    NextEntry = First->Flink;
+    while ((NextEntry != First) && (NT_SUCCESS(Status)))
+    {
+        /* Make sure there's still space */
+        if (Count <= *Used)
+        {
+            Status = STATUS_NO_MEMORY;
+            break;
+        }
+
+        /* Get the current descriptor */
+        Descriptor = CONTAINING_RECORD(NextEntry,
+                                       BL_MEMORY_DESCRIPTOR,
+                                       ListEntry);
+
+        /* Copy it into one of the descriptors we have */
+        RtlCopyMemory(&ListDescriptor[*Used],
+                      Descriptor,
+                      sizeof(*Descriptor));
+
+        /* Add it to the list we have */
+        Status = MmMdAddDescriptorToList(DestinationList,
+                                         &ListDescriptor[*Used],
+                                         Flags);
+        ++*Used;
+
+        /* Move to the next entry */
+        NextEntry = NextEntry->Flink;
+    }
+
+    /* Check if the global descriptors were used */
+    if (ListDescriptor == MmGlobalMemoryDescriptors)
+    {
+        /* Unwind our usage */
+        MmMdFreeGlobalDescriptors();
+        --MmDescriptorCallTreeCount;
+    }
+
+    /* Return back to caller */
+    return Status;
+}
+
 VOID
 MmMdRemoveDescriptorFromList (
     _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList,
@@ -206,7 +339,7 @@ MmMdRemoveDescriptorFromList (
     /* Remove the entry */
     RemoveEntryList(&Entry->ListEntry);
 
-    /*  Check if this was the current link */
+    /* Check if this was the current link */
     if (MdList->This == &Entry->ListEntry)
     {
         /* Remove the current link and set the next one */
@@ -250,7 +383,7 @@ MmMdInitByteGranularDescriptor (
     /* If we're out of descriptors, bail out */
     if (MmGlobalMemoryDescriptorsUsed >= MmGlobalMemoryDescriptorCount)
     {
-        EarlyPrint(L"Out of descriptors!\n");
+        EfiPrintf(L"Out of descriptors!\r\n");
         return NULL;
     }
 
@@ -295,13 +428,13 @@ MmMdpTruncateDescriptor (
     /* Check for backward overlap */
     if ((PreviousEntry != MdList->First) && (MemoryDescriptor->BasePage < PreviousEndPage))
     {
-        EarlyPrint(L"Overlap detected -- this is unexpected on x86/x64 platforms\n");
+        EfiPrintf(L"Overlap detected -- this is unexpected on x86/x64 platforms\r\n");
     }
 
     /* Check for forward overlap */
     if ((NextEntry != MdList->First) && (NextDescriptor->BasePage < EndPage))
     {
-        EarlyPrint(L"Overlap detected -- this is unexpected on x86/x64 platforms\n");
+        EfiPrintf(L"Overlap detected -- this is unexpected on x86/x64 platforms\r\n");
     }
 
     /* Nothing to do */
@@ -343,7 +476,7 @@ MmMdpCoalesceDescriptor (
           ((MemoryDescriptor->VirtualPage) && (PreviousDescriptor->VirtualPage) &&
            (PreviousMappedEndPage == MemoryDescriptor->VirtualPage))))
     {
-        EarlyPrint(L"Previous descriptor coalescible!\n");
+        EfiPrintf(L"Previous descriptor coalescable!\r\n");
     }
 
     /* CHeck if the current entry touches the next entry, and is compatible */
@@ -355,7 +488,7 @@ MmMdpCoalesceDescriptor (
             ((MemoryDescriptor->VirtualPage) && (PreviousDescriptor->VirtualPage) &&
                 (MappedEndPage == NextDescriptor->VirtualPage))))
     {
-        EarlyPrint(L"Next descriptor coalescible!\n");
+        EfiPrintf(L"Next descriptor coalescable!\r\n");
     }
 
     /* Nothing to do */
@@ -547,7 +680,7 @@ MmMdRemoveRegionFromMdlEx (
         FoundPageCount = Descriptor->PageCount;
         FoundEndPage = FoundBasePage + FoundPageCount;
         EndPage = PageCount + BasePage;
-        //EarlyPrint(L"Looking for Region 0x%08I64X-0x%08I64X in 0x%08I64X-0x%08I64X\n", BasePage, EndPage, FoundBasePage, FoundEndPage);
+        //EarlyPrint(L"Looking for Region 0x%08I64X-0x%08I64X in 0x%08I64X-0x%08I64X\r\n", BasePage, EndPage, FoundBasePage, FoundEndPage);
 
         /* Make a copy of the original descriptor */
         RtlCopyMemory(&NewDescriptor, NextEntry, sizeof(NewDescriptor));
@@ -562,18 +695,18 @@ MmMdRemoveRegionFromMdlEx (
                 if ((FoundBasePage >= BasePage) || (EndPage >= FoundEndPage))
                 {
                     /* This descriptor doesn't cover any part of the range */
-                    //EarlyPrint(L"No part of this descriptor contains the region\n");
+                    //EarlyPrint(L"No part of this descriptor contains the region\r\n");
                 }
                 else
                 {
                     /* This descriptor covers the head of the allocation */
-                    //EarlyPrint(L"Descriptor covers the head of the region\n");
+                    //EarlyPrint(L"Descriptor covers the head of the region\r\n");
                 }
             }
             else
             {
                 /* This descriptor contains the entire allocation */
-                //EarlyPrint(L"Descriptor contains the entire region\n");
+                //EarlyPrint(L"Descriptor contains the entire region\r\n");
             }
 
             /* Keep going */
@@ -614,14 +747,14 @@ MmMdRemoveRegionFromMdlEx (
             if (!Descriptor->PageCount)
             {
                 /* Remove it */
-                //EarlyPrint(L"Entire descriptor consumed\n");
+                //EarlyPrint(L"Entire descriptor consumed\r\n");
                 MmMdRemoveDescriptorFromList(MdList, Descriptor);
                 MmMdFreeDescriptor(Descriptor);
 
                 /* Check if we're supposed to insert it into a new list */
                 if (HaveNewList)
                 {
-                    EarlyPrint(L"Not yet implemented\n");
+                    EfiPrintf(L"Not yet implemented\r\n");
                     Status = STATUS_NOT_IMPLEMENTED;
                     goto Quickie;
                 }
@@ -646,6 +779,204 @@ Quickie:
     return Status;
 }
 
+PBL_MEMORY_DESCRIPTOR
+MmMdFindDescriptorFromMdl (
+    _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList, 
+    _In_ ULONG Flags, 
+    _In_ ULONGLONG Page
+    )
+{
+    BOOLEAN IsVirtual;
+    PLIST_ENTRY NextEntry, ListHead;
+    PBL_MEMORY_DESCRIPTOR Current;
+    ULONGLONG BasePage;
+
+    /* Assume physical */
+    IsVirtual = FALSE;
+
+    /* Check if the caller wants physical memory */
+    if (!(Flags & BL_MM_REMOVE_VIRTUAL_REGION_FLAG))
+    {
+        /* Check if this is a virtual memory list */
+        if (MdList->Type == BlMdVirtual)
+        {
+            /* We won't find anything */
+            return NULL;
+        }
+    }
+    else if (MdList->Type == BlMdPhysical)
+    {
+        /* Otherwise, caller wants virtual, but this is a physical list */
+        IsVirtual = TRUE;
+        NextEntry = MdList->First->Flink;
+    }
+    
+    /* Check if this is a physical search */
+    if (!IsVirtual)
+    {
+        /* Check if we can use the current pointer */
+        NextEntry = MdList->This;
+        if (!NextEntry)
+        {
+            /* We can't -- start at the beginning */
+            NextEntry = MdList->First->Flink;
+        }
+        else
+        {
+            /* If the page is below the current pointer, restart */
+            Current = CONTAINING_RECORD(NextEntry, BL_MEMORY_DESCRIPTOR, ListEntry);
+            if (Page < Current->BasePage)
+            {
+                NextEntry = MdList->First->Flink;
+            }
+        }
+    }
+
+    /* Loop the list of descriptors */
+    ListHead = MdList->First;
+    while (NextEntry != ListHead)
+    {
+        /* Get the current one */
+        Current = CONTAINING_RECORD(NextEntry, BL_MEMORY_DESCRIPTOR, ListEntry);
+
+        /* Check if we are looking for virtual memory */
+        if (IsVirtual)
+        {
+            /* Use the base address */
+            BasePage = Current->VirtualPage;
+        }
+        else
+        {
+            /* Use the page */
+            BasePage = Current->BasePage;
+        }
+
+        /* If this is a virtual descriptor, make sure it has a base address */
+        if ((!(IsVirtual) || (BasePage)) &&
+            (BasePage <= Page) &&
+            (Page < (BasePage + Current->PageCount)))
+        {
+            /* The descriptor fits the page being requested */
+            return Current;
+        }
+
+        /* Try the next one */
+        NextEntry = NextEntry->Flink;
+    }
+
+    /* Nothing found if we're here */
+    return NULL;
+}
+
+PBL_MEMORY_DESCRIPTOR
+MmMdFindDescriptor (
+    _In_ ULONG WhichList, 
+    _In_ ULONG Flags,
+    _In_ ULONGLONG Page
+    )
+{
+    PBL_MEMORY_DESCRIPTOR FoundDescriptor;
+
+    /* Check if the caller is looking for mapped, allocated memory */
+    if (WhichList & BL_MM_INCLUDE_MAPPED_ALLOCATED)
+    {
+        /* Find a descriptor in that list */
+        FoundDescriptor = MmMdFindDescriptorFromMdl(&MmMdlMappedAllocated, Flags, Page);
+        if (FoundDescriptor)
+        {
+            /* Got it */
+            return FoundDescriptor;
+        }
+    }
+
+    /* Check if the caller is looking for mapped, unallocated memory */
+    if (WhichList & BL_MM_INCLUDE_MAPPED_UNALLOCATED)
+    {
+        /* Find a descriptor in that list */
+        FoundDescriptor = MmMdFindDescriptorFromMdl(&MmMdlMappedUnallocated, Flags, Page);
+        if (FoundDescriptor)
+        {
+            /* Got it */
+            return FoundDescriptor;
+        }
+    }
+
+    /* Check if the caller is looking for unmapped, allocated memory */
+    if (WhichList & BL_MM_INCLUDE_UNMAPPED_ALLOCATED)
+    {
+        /* Find a descriptor in that list */
+        FoundDescriptor = MmMdFindDescriptorFromMdl(&MmMdlUnmappedAllocated, Flags, Page);
+        if (FoundDescriptor)
+        {
+            /* Got it */
+            return FoundDescriptor;
+        }
+    }
+
+    /* Check if the caller is looking for unmapped, unallocated memory */
+    if (WhichList & BL_MM_INCLUDE_UNMAPPED_UNALLOCATED)
+    {
+        /* Find a descriptor in that list */
+        FoundDescriptor = MmMdFindDescriptorFromMdl(&MmMdlUnmappedUnallocated, Flags, Page);
+        if (FoundDescriptor)
+        {
+            /* Got it */
+            return FoundDescriptor;
+        }
+    }
+
+    /* Check if the caller is looking for reserved, allocated memory */
+    if (WhichList & BL_MM_INCLUDE_RESERVED_ALLOCATED)
+    {
+        /* Find a descriptor in that list */
+        FoundDescriptor = MmMdFindDescriptorFromMdl(&MmMdlReservedAllocated, Flags, Page);
+        if (FoundDescriptor)
+        {
+            /* Got it */
+            return FoundDescriptor;
+        }
+    }
+
+    /* Check if the caller is looking for bad memory */
+    if (WhichList & BL_MM_INCLUDE_BAD_MEMORY)
+    {
+        /* Find a descriptor in that list */
+        FoundDescriptor = MmMdFindDescriptorFromMdl(&MmMdlBadMemory, Flags, Page);
+        if (FoundDescriptor)
+        {
+            /* Got it */
+            return FoundDescriptor;
+        }
+    }
+
+    /* Check if the caller is looking for truncated memory */
+    if (WhichList & BL_MM_INCLUDE_TRUNCATED_MEMORY)
+    {
+        /* Find a descriptor in that list */
+        FoundDescriptor = MmMdFindDescriptorFromMdl(&MmMdlTruncatedMemory, Flags, Page);
+        if (FoundDescriptor)
+        {
+            /* Got it */
+            return FoundDescriptor;
+        }
+    }
+
+    /* Check if the caller is looking for persistent memory */
+    if (WhichList & BL_MM_INCLUDE_PERSISTENT_MEMORY)
+    {
+        /* Find a descriptor in that list */
+        FoundDescriptor = MmMdFindDescriptorFromMdl(&MmMdlPersistentMemory, Flags, Page);
+        if (FoundDescriptor)
+        {
+            /* Got it */
+            return FoundDescriptor;
+        }
+    }
+
+    /* Nothing if we got here */
+    return NULL;
+}
+
 BOOLEAN
 MmMdFindSatisfyingRegion (
     _In_ PBL_MEMORY_DESCRIPTOR Descriptor,
@@ -681,7 +1012,7 @@ MmMdFindSatisfyingRegion (
     /* Check for start overflow */
     if (BaseMin > BaseMax)
     {
-        EarlyPrint(L"Descriptor overflow\n");
+        EfiPrintf(L"Descriptor overflow\r\n");
         return FALSE;
     }
 
@@ -724,7 +1055,7 @@ MmMdFindSatisfyingRegion (
     /* Any mapped page already? */
     if (Descriptor->VirtualPage)
     {
-        EarlyPrint(L"Virtual memory not yet supported\n");
+        EfiPrintf(L"Virtual memory not yet supported\r\n");
         return FALSE;
     }
     else
@@ -737,21 +1068,21 @@ MmMdFindSatisfyingRegion (
     if ((((Flags & 0xFF) & (Descriptor->Flags & 0xFF)) != (Flags & 0xFF)) ||
         (((Flags & 0xFF00) & (Descriptor->Flags & 0xFF00)) != (Flags & 0xFF00)))
     {
-        EarlyPrint(L"Incorrect memory attributes\n");
+        EfiPrintf(L"Incorrect memory attributes\r\n");
         return FALSE;
     }
 
     /* Bail out if the allocation flags don't match */
-    if (((Flags ^ Descriptor->Flags) & 0x190000))
+    if (((Flags ^ Descriptor->Flags) & (BlMemoryRuntime | BlMemoryReserved | BlMemoryUnknown)))
     {
-        EarlyPrint(L"Incorrect memory allocation flags\n");
+        //EfiPrintf(L"Incorrect memory allocation flags\r\n");
         return FALSE;
     }
 
     /* Bail out if the type doesn't match */
     if (Descriptor->Type != MemoryType)
     {
-        //EarlyPrint(L"Incorrect descriptor type\n");
+        //EfiPrintf(L"Incorrect descriptor type: %lx %lx\r\n", Descriptor->Type, MemoryType);
         return FALSE;
     }
 
@@ -761,7 +1092,7 @@ MmMdFindSatisfyingRegion (
     NewDescriptor->Type = Descriptor->Type;
     NewDescriptor->VirtualPage = VirtualPage;
     NewDescriptor->Flags = Descriptor->Flags;
-    //EarlyPrint(L"Found a matching descriptor: %08I64X with %08I64X pages\n", BasePage, Pages);
+    //EfiPrintf(L"Found a matching descriptor: %08I64X with %08I64X pages\r\n", BasePage, Pages);
     return TRUE;
 }
 
@@ -775,14 +1106,12 @@ MmMdFreeGlobalDescriptors (
     PLIST_ENTRY OldFlink, OldBlink;
 
     /* Make sure we're not int middle of a call using a descriptor */
-    EarlyPrint(L"Call depth is %d\n", MmDescriptorCallTreeCount);
     if (MmDescriptorCallTreeCount != 1)
     {
         return;
     }
 
     /* Loop every current global descriptor */
-    EarlyPrint(L"MmGlobalMemoryDescriptorsUsed: %d\n", MmGlobalMemoryDescriptorsUsed);
     while (Index < MmGlobalMemoryDescriptorsUsed)
     {
         /* Does it have any valid pageS? */
@@ -797,8 +1126,8 @@ MmMdFreeGlobalDescriptors (
             }
 
             /* Save the links */
-            OldFlink = OldDescriptor->ListEntry.Blink;
-            OldBlink = OldDescriptor->ListEntry.Flink;
+            OldBlink = OldDescriptor->ListEntry.Blink;
+            OldFlink = OldDescriptor->ListEntry.Flink;
 
             /* Make the copy */
             *Descriptor = *OldDescriptor;
@@ -840,6 +1169,6 @@ MmMdInitialize (
         MmGlobalMemoryDescriptorCount = RTL_NUMBER_OF(MmStaticMemoryDescriptors);
         MmGlobalMemoryDescriptors = MmStaticMemoryDescriptors;
         RtlZeroMemory(MmStaticMemoryDescriptors, sizeof(MmStaticMemoryDescriptors));
-        MmGlobalMemoryDescriptorsUsed = FALSE;
+        MmGlobalMemoryDescriptorsUsed = 0;
     }
 }