mirror of
https://github.com/reactos/reactos.git
synced 2024-07-02 02:34:53 +00:00
[BOOTMGFW]
- Implement most of the physical memory allocator. The heap manager now gets its page allocation fulfilled. svn path=/trunk/; revision=69067
This commit is contained in:
parent
c8df1bac22
commit
e21146906a
|
@ -61,8 +61,15 @@ EarlyPrint(_In_ PWCHAR Format, ...);
|
|||
#define BL_MM_ADD_DESCRIPTOR_NEVER_TRUNCATE_FLAG 0x20
|
||||
#define BL_MM_ADD_DESCRIPTOR_UPDATE_LIST_POINTER_FLAG 0x2000
|
||||
|
||||
#define BL_MM_DESCRIPTOR_REQUIRES_FIXED_FLAG 0x40000
|
||||
#define BL_MM_DESCRIPTOR_REQUIRES_COALESCING_FLAG 0x2000000
|
||||
#define BL_MM_DESCRIPTOR_REQUIRES_UPDATING_FLAG 0x4000000
|
||||
#define BL_MM_DESCRIPTOR_NEVER_USE_FIRMWARE_FLAG 0x8000000
|
||||
#define BL_MM_DESCRIPTOR_SPECIAL_PAGES_FLAG 0x20000000
|
||||
#define BL_MM_DESCRIPTOR_CAME_FROM_FIRMWARE_FLAG 0x80000000
|
||||
|
||||
#define BL_MM_REQUEST_DEFAULT_TYPE 1
|
||||
#define BL_MM_REQUEST_TOP_DOWN_TYPE 2
|
||||
|
||||
#define BL_MM_REMOVE_VIRTUAL_REGION_FLAG 0x80000000
|
||||
|
||||
|
@ -474,6 +481,15 @@ BlpMmInitialize (
|
|||
_In_ PBL_LIBRARY_PARAMETERS LibraryParameters
|
||||
);
|
||||
|
||||
/* FIRMWARE ROUTINES *********************************************************/
|
||||
|
||||
NTSTATUS
|
||||
EfiAllocatePages (
|
||||
_In_ ULONG Type,
|
||||
_In_ ULONG Pages,
|
||||
_Inout_ EFI_PHYSICAL_ADDRESS* Memory
|
||||
);
|
||||
|
||||
/* UTILITY ROUTINES **********************************************************/
|
||||
|
||||
EFI_STATUS
|
||||
|
@ -553,6 +569,11 @@ MmMdInitByteGranularDescriptor (
|
|||
_In_ ULONGLONG PageCount
|
||||
);
|
||||
|
||||
VOID
|
||||
MmMdFreeGlobalDescriptors (
|
||||
VOID
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
MmMdAddDescriptorToList (
|
||||
_In_ PBL_MEMORY_DESCRIPTOR_LIST MdList,
|
||||
|
@ -560,6 +581,25 @@ MmMdAddDescriptorToList (
|
|||
_In_ ULONG Flags
|
||||
);
|
||||
|
||||
VOID
|
||||
MmMdRemoveDescriptorFromList (
|
||||
_In_ PBL_MEMORY_DESCRIPTOR_LIST MdList,
|
||||
_In_ PBL_MEMORY_DESCRIPTOR Entry
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
MmMdFindSatisfyingRegion (
|
||||
_In_ PBL_MEMORY_DESCRIPTOR Descriptor,
|
||||
_Out_ PBL_MEMORY_DESCRIPTOR NewDescriptor,
|
||||
_In_ ULONGLONG Pages,
|
||||
_In_ PBL_ADDRESS_RANGE BaseRange,
|
||||
_In_ PBL_ADDRESS_RANGE VirtualRange,
|
||||
_In_ BOOLEAN TopDown,
|
||||
_In_ BL_MEMORY_TYPE MemoryType,
|
||||
_In_ ULONG Flags,
|
||||
_In_ ULONG Alignment
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
MmMdRemoveRegionFromMdlEx (
|
||||
__in PBL_MEMORY_DESCRIPTOR_LIST MdList,
|
||||
|
@ -569,6 +609,11 @@ MmMdRemoveRegionFromMdlEx (
|
|||
__in PBL_MEMORY_DESCRIPTOR_LIST NewMdList
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
MmMdFreeDescriptor (
|
||||
_In_ PBL_MEMORY_DESCRIPTOR MemoryDescriptor
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
MmPapAllocatePagesInRange (
|
||||
_Inout_ PULONG PhysicalAddress,
|
||||
|
|
|
@ -646,6 +646,151 @@ Quickie:
|
|||
return Status;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
MmMdFindSatisfyingRegion (
|
||||
_In_ PBL_MEMORY_DESCRIPTOR Descriptor,
|
||||
_Out_ PBL_MEMORY_DESCRIPTOR NewDescriptor,
|
||||
_In_ ULONGLONG Pages,
|
||||
_In_ PBL_ADDRESS_RANGE BaseRange,
|
||||
_In_ PBL_ADDRESS_RANGE VirtualRange,
|
||||
_In_ BOOLEAN TopDown,
|
||||
_In_ BL_MEMORY_TYPE MemoryType,
|
||||
_In_ ULONG Flags,
|
||||
_In_ ULONG Alignment
|
||||
)
|
||||
{
|
||||
ULONGLONG BaseMin, BaseMax;
|
||||
ULONGLONG VirtualPage, BasePage;
|
||||
|
||||
/* Extract the minimum and maximum range */
|
||||
BaseMin = BaseRange->Minimum;
|
||||
BaseMax = BaseRange->Maximum;
|
||||
|
||||
/* Don't go below where the descriptor starts */
|
||||
if (BaseMin < Descriptor->BasePage)
|
||||
{
|
||||
BaseMin = Descriptor->BasePage;
|
||||
}
|
||||
|
||||
/* Don't go beyond where the descriptor ends */
|
||||
if (BaseMax > (Descriptor->BasePage + Descriptor->PageCount - 1))
|
||||
{
|
||||
BaseMax = (Descriptor->BasePage + Descriptor->PageCount - 1);
|
||||
}
|
||||
|
||||
/* Check for start overflow */
|
||||
if (BaseMin > BaseMax)
|
||||
{
|
||||
EarlyPrint(L"Descriptor overflow\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Align the base as required */
|
||||
if (Alignment != 1)
|
||||
{
|
||||
BaseMin = ALIGN_UP_BY(BaseMin, Alignment);
|
||||
}
|
||||
|
||||
/* Check for range overflow */
|
||||
if (((BaseMin + Pages - 1) < BaseMin) || ((BaseMin + Pages - 1) > BaseMax))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Check if this was a top-down request */
|
||||
if (TopDown)
|
||||
{
|
||||
/* Then get the highest page possible */
|
||||
BasePage = BaseMax - Pages + 1;
|
||||
if (Alignment != 1)
|
||||
{
|
||||
/* Align it as needed */
|
||||
BasePage = ALIGN_DOWN_BY(BasePage, Alignment);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, get the lowest page possible */
|
||||
BasePage = BaseMin;
|
||||
}
|
||||
|
||||
/* If a virtual address range was passed in, this must be a virtual descriptor */
|
||||
if (((VirtualRange->Minimum) || (VirtualRange->Maximum)) &&
|
||||
!(Descriptor->VirtualPage))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Any mapped page already? */
|
||||
if (Descriptor->VirtualPage)
|
||||
{
|
||||
EarlyPrint(L"Virtual memory not yet supported\n");
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to worry about */
|
||||
VirtualPage = 0;
|
||||
}
|
||||
|
||||
/* Bail out if the memory type attributes don't match */
|
||||
if ((((Flags & 0xFF) & (Descriptor->Flags & 0xFF)) != (Flags & 0xFF)) ||
|
||||
(((Flags & 0xFF00) & (Descriptor->Flags & 0xFF00)) != (Flags & 0xFF00)))
|
||||
{
|
||||
EarlyPrint(L"Incorrect memory attributes\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Bail out if the allocation flags don't match */
|
||||
if (((Flags ^ Descriptor->Flags) & 0x190000))
|
||||
{
|
||||
EarlyPrint(L"Incorrect memory allocation flags\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Bail out if the type doesn't match */
|
||||
if (Descriptor->Type != MemoryType)
|
||||
{
|
||||
//EarlyPrint(L"Incorrect descriptor type\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* We have a matching region, fill out the descriptor for it */
|
||||
NewDescriptor->BasePage = BasePage;
|
||||
NewDescriptor->PageCount = Pages;
|
||||
NewDescriptor->Type = Descriptor->Type;
|
||||
NewDescriptor->VirtualPage = VirtualPage;
|
||||
NewDescriptor->Flags = Descriptor->Flags;
|
||||
//EarlyPrint(L"Found a matching descriptor: %08I64X with %08I64X pages\n", BasePage, Pages);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID
|
||||
MmMdFreeGlobalDescriptors (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
ULONG Index = 0;
|
||||
|
||||
/* Make sure we're not int middle of a call using a descriptor */
|
||||
if (MmDescriptorCallTreeCount != 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Loop every current global descriptor */
|
||||
while (Index < MmGlobalMemoryDescriptorsUsed)
|
||||
{
|
||||
EarlyPrint(L"Global descriptors not yet supported\n");
|
||||
|
||||
/* Keep going */
|
||||
Index++;
|
||||
}
|
||||
|
||||
/* All global descriptors freed */
|
||||
MmGlobalMemoryDescriptorsUsed = 0;
|
||||
}
|
||||
|
||||
VOID
|
||||
MmMdInitialize (
|
||||
_In_ ULONG Phase,
|
||||
|
|
|
@ -10,6 +10,18 @@
|
|||
|
||||
#include "bl.h"
|
||||
|
||||
|
||||
typedef struct _BL_PA_REQUEST
|
||||
{
|
||||
BL_ADDRESS_RANGE BaseRange;
|
||||
BL_ADDRESS_RANGE VirtualRange;
|
||||
ULONG Type;
|
||||
ULONGLONG Pages;
|
||||
ULONG MemoryType;
|
||||
ULONG Alignment;
|
||||
ULONG Flags;
|
||||
} BL_PA_REQUEST, *PBL_PA_REQUEST;
|
||||
|
||||
/* DATA VARIABLES ************************************************************/
|
||||
|
||||
ULONGLONG PapMaximumPhysicalPage, PapMinimumPhysicalPage;
|
||||
|
@ -42,6 +54,341 @@ BlpMmInitializeConstraints (
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
MmPapAllocateRegionFromMdl (
|
||||
_In_ PBL_MEMORY_DESCRIPTOR_LIST NewList,
|
||||
_Out_opt_ PBL_MEMORY_DESCRIPTOR Descriptor,
|
||||
_In_ PBL_MEMORY_DESCRIPTOR_LIST CurrentList,
|
||||
_In_ PBL_PA_REQUEST Request,
|
||||
_In_ BL_MEMORY_TYPE Type
|
||||
)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
BL_MEMORY_DESCRIPTOR LocalDescriptor = {{0}};
|
||||
PBL_MEMORY_DESCRIPTOR FoundDescriptor, TempDescriptor;
|
||||
PLIST_ENTRY ListHead, NextEntry;
|
||||
BOOLEAN TopDown, GotFwPages;
|
||||
EFI_PHYSICAL_ADDRESS EfiAddress;
|
||||
ULONGLONG LocalEndPage, FoundEndPage, LocalVirtualEndPage;
|
||||
|
||||
/* Check if any parameters were not passed in correctly */
|
||||
if ( !(CurrentList) || !(Request) || (!(NewList) && !(Descriptor)))
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Set failure by default */
|
||||
Status = STATUS_NO_MEMORY;
|
||||
|
||||
/* Take the head and next entry in the list, as appropriate */
|
||||
ListHead = CurrentList->First;
|
||||
if (Request->Type & BL_MM_REQUEST_TOP_DOWN_TYPE)
|
||||
{
|
||||
NextEntry = ListHead->Flink;
|
||||
TopDown = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
NextEntry = ListHead->Blink;
|
||||
TopDown = TRUE;
|
||||
}
|
||||
|
||||
/* Loop through the list */
|
||||
GotFwPages = FALSE;
|
||||
while (NextEntry != ListHead)
|
||||
{
|
||||
/* Grab a descriptor */
|
||||
FoundDescriptor = CONTAINING_RECORD(NextEntry,
|
||||
BL_MEMORY_DESCRIPTOR,
|
||||
ListEntry);
|
||||
|
||||
/* See if it matches the request */
|
||||
if (MmMdFindSatisfyingRegion(FoundDescriptor,
|
||||
&LocalDescriptor,
|
||||
Request->Pages,
|
||||
&Request->BaseRange,
|
||||
&Request->VirtualRange,
|
||||
TopDown,
|
||||
Request->MemoryType,
|
||||
Request->Flags,
|
||||
Request->Alignment))
|
||||
{
|
||||
/* It does, get out */
|
||||
break;
|
||||
}
|
||||
|
||||
/* It doesn't, move to the next appropriate entry */
|
||||
if (TopDown)
|
||||
{
|
||||
NextEntry = NextEntry->Blink;
|
||||
}
|
||||
else
|
||||
{
|
||||
NextEntry = NextEntry->Flink;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if we exhausted the list */
|
||||
if (NextEntry == ListHead)
|
||||
{
|
||||
EarlyPrint(L"No matching memory found\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Copy all the flags that are not request flag */
|
||||
LocalDescriptor.Flags = (Request->Flags & 0xFFFF0000) |
|
||||
(LocalDescriptor.Flags & 0x0000FFFF);
|
||||
|
||||
/* Are we using the physical memory list, and are we OK with using firmware? */
|
||||
if ((CurrentList == &MmMdlUnmappedUnallocated) &&
|
||||
!((Request->Flags & BL_MM_DESCRIPTOR_NEVER_USE_FIRMWARE_FLAG) ||
|
||||
(LocalDescriptor.Flags & BL_MM_DESCRIPTOR_NEVER_USE_FIRMWARE_FLAG)))
|
||||
{
|
||||
/* Allocate the requested address from EFI */
|
||||
EfiAddress = LocalDescriptor.BasePage << PAGE_SHIFT;
|
||||
Status = EfiAllocatePages(AllocateAddress,
|
||||
(ULONG)LocalDescriptor.PageCount,
|
||||
&EfiAddress);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
EarlyPrint(L"EFI memory allocation failure\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Remember we got memory from EFI */
|
||||
GotFwPages = TRUE;
|
||||
}
|
||||
|
||||
/* Remove the descriptor from the original list it was on */
|
||||
MmMdRemoveDescriptorFromList(CurrentList, FoundDescriptor);
|
||||
|
||||
/* Are we allocating from the virtual memory list? */
|
||||
if (CurrentList == &MmMdlMappedUnallocated)
|
||||
{
|
||||
EarlyPrint(L"Virtual memory not yet supported\n");
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* Does the memory we received not exactly fall onto the beginning of its descriptor? */
|
||||
if (LocalDescriptor.BasePage != FoundDescriptor->BasePage)
|
||||
{
|
||||
EarlyPrint(L"Local Page: %08I64X Found Page: %08I64X\n", LocalDescriptor.BasePage, FoundDescriptor->BasePage);
|
||||
TempDescriptor = MmMdInitByteGranularDescriptor(FoundDescriptor->Flags,
|
||||
FoundDescriptor->Type,
|
||||
FoundDescriptor->BasePage,
|
||||
FoundDescriptor->VirtualPage,
|
||||
LocalDescriptor.BasePage -
|
||||
FoundDescriptor->BasePage);
|
||||
Status = MmMdAddDescriptorToList(CurrentList, TempDescriptor, 0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
/* Does the memory we received not exactly fall onto the end of its descriptor? */
|
||||
LocalEndPage = LocalDescriptor.PageCount + LocalDescriptor.BasePage;
|
||||
FoundEndPage = FoundDescriptor->PageCount + FoundDescriptor->BasePage;
|
||||
LocalVirtualEndPage = LocalDescriptor.VirtualPage ?
|
||||
LocalDescriptor.VirtualPage + LocalDescriptor.PageCount : 0;
|
||||
if (LocalEndPage != FoundEndPage)
|
||||
{
|
||||
EarlyPrint(L"Local Page: %08I64X Found Page: %08I64X\n", LocalEndPage, FoundEndPage);
|
||||
TempDescriptor = MmMdInitByteGranularDescriptor(FoundDescriptor->Flags,
|
||||
FoundDescriptor->Type,
|
||||
LocalEndPage,
|
||||
LocalVirtualEndPage,
|
||||
FoundEndPage - LocalEndPage);
|
||||
Status = MmMdAddDescriptorToList(CurrentList, TempDescriptor, 0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
/* We got the memory we needed */
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
/* Are we supposed to insert it into a new list? */
|
||||
if (NewList)
|
||||
{
|
||||
/* Copy the allocated region descriptor into the one we found */
|
||||
FoundDescriptor->BaseAddress = LocalDescriptor.BaseAddress;
|
||||
FoundDescriptor->VirtualPage = LocalDescriptor.VirtualPage;
|
||||
FoundDescriptor->PageCount = LocalDescriptor.PageCount;
|
||||
FoundDescriptor->Type = Type;
|
||||
FoundDescriptor->Flags = LocalDescriptor.Flags;
|
||||
|
||||
/* Remember if it came from EFI */
|
||||
if (GotFwPages)
|
||||
{
|
||||
FoundDescriptor->Flags |= BL_MM_DESCRIPTOR_CAME_FROM_FIRMWARE_FLAG;
|
||||
}
|
||||
|
||||
/* Add the descriptor to the requested list */
|
||||
Status = MmMdAddDescriptorToList(NewList, FoundDescriptor, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Free the descriptor, nobody wants to know about it anymore */
|
||||
MmMdFreeDescriptor(FoundDescriptor);
|
||||
}
|
||||
|
||||
/* Return the allocation region back */
|
||||
RtlCopyMemory(Descriptor, &LocalDescriptor, sizeof(LocalDescriptor));
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
MmPaAllocatePages (
|
||||
_In_ PBL_MEMORY_DESCRIPTOR_LIST NewList,
|
||||
_In_ PBL_MEMORY_DESCRIPTOR Descriptor,
|
||||
_In_ PBL_MEMORY_DESCRIPTOR_LIST CurrentList,
|
||||
_In_ PBL_PA_REQUEST Request,
|
||||
_In_ BL_MEMORY_TYPE MemoryType
|
||||
)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Heap and page directory/table pages have a special flag */
|
||||
if ((MemoryType >= BlLoaderHeap) && (MemoryType <= BlLoaderReferencePage))
|
||||
{
|
||||
Request->Flags |= BL_MM_DESCRIPTOR_SPECIAL_PAGES_FLAG;
|
||||
}
|
||||
|
||||
/* Try to find a free region of RAM matching this range and request */
|
||||
Request->MemoryType = BlConventionalMemory;
|
||||
Status = MmPapAllocateRegionFromMdl(NewList,
|
||||
Descriptor,
|
||||
CurrentList,
|
||||
Request,
|
||||
MemoryType);
|
||||
if (Status == STATUS_NOT_FOUND)
|
||||
{
|
||||
/* Need to re-synchronize the memory map and check other lists */
|
||||
EarlyPrint(L"No RAM found -- backup plan not yet implemented\n");
|
||||
}
|
||||
|
||||
/* Did we get the region we wanted? */
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* All good, return back */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Nope, we have to hunt for it elsewhere */
|
||||
EarlyPrint(L"TODO\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
MmPapAllocatePhysicalPagesInRange (
|
||||
_Inout_ PPHYSICAL_ADDRESS BaseAddress,
|
||||
_In_ BL_MEMORY_TYPE MemoryType,
|
||||
_In_ ULONGLONG Pages,
|
||||
_In_ ULONG Attributes,
|
||||
_In_ ULONG Alignment,
|
||||
_In_ PBL_MEMORY_DESCRIPTOR_LIST NewList,
|
||||
_In_opt_ PBL_ADDRESS_RANGE Range,
|
||||
_In_ ULONG RangeType
|
||||
)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
BL_PA_REQUEST Request;
|
||||
BL_MEMORY_DESCRIPTOR Descriptor;
|
||||
|
||||
/* Increase nesting depth */
|
||||
++MmDescriptorCallTreeCount;
|
||||
|
||||
/* Bail out if no address was specified */
|
||||
if (!BaseAddress)
|
||||
{
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
goto Quickie;
|
||||
}
|
||||
|
||||
/* Bail out if no page count was passed in, or a bad list was specified */
|
||||
if (!(Pages) ||
|
||||
((NewList != &MmMdlUnmappedAllocated) &&
|
||||
(NewList != &MmMdlPersistentMemory)))
|
||||
{
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
goto Quickie;
|
||||
}
|
||||
|
||||
/* Bail out if the passed in range is invalid */
|
||||
if ((Range) && (Range->Minimum >= Range->Maximum))
|
||||
{
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
goto Quickie;
|
||||
}
|
||||
|
||||
/* Adjust alignment as needed */
|
||||
if (!Alignment)
|
||||
{
|
||||
Alignment = 1;
|
||||
}
|
||||
|
||||
/* Clear the virtual range */
|
||||
Request.VirtualRange.Minimum = 0;
|
||||
Request.VirtualRange.Maximum = 0;
|
||||
|
||||
/* Check if a fixed allocation was requested*/
|
||||
if (Attributes & BL_MM_DESCRIPTOR_REQUIRES_FIXED_FLAG)
|
||||
{
|
||||
/* Force the only available range to be the passed in address */
|
||||
Request.BaseRange.Minimum = BaseAddress->QuadPart >> PAGE_SHIFT;
|
||||
Request.BaseRange.Maximum = Request.BaseRange.Minimum + Pages - 1;
|
||||
}
|
||||
else if (Range)
|
||||
{
|
||||
/* Otherwise, a manual range was specified, use it */
|
||||
Request.BaseRange.Minimum = Range->Minimum >> PAGE_SHIFT;
|
||||
Request.BaseRange.Maximum = Request.BaseRange.Minimum +
|
||||
(Range->Maximum >> PAGE_SHIFT) - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, use any possible range of pages */
|
||||
Request.BaseRange.Minimum = PapMinimumPhysicalPage;
|
||||
Request.BaseRange.Maximum = MAXULONG >> PAGE_SHIFT;
|
||||
}
|
||||
|
||||
/* Check if no type was specified, or if it was invalid */
|
||||
if (!(RangeType) ||
|
||||
(RangeType & ~(BL_MM_REQUEST_TOP_DOWN_TYPE | BL_MM_REQUEST_DEFAULT_TYPE)))
|
||||
{
|
||||
/* Use default type */
|
||||
Request.Type = BL_MM_REQUEST_DEFAULT_TYPE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Use the requested type */
|
||||
Request.Type = RangeType;
|
||||
}
|
||||
|
||||
/* Capture the other request parameters */
|
||||
Request.Alignment = Alignment;
|
||||
Request.Pages = Pages;
|
||||
Request.Flags = Attributes;
|
||||
Status = MmPaAllocatePages(NewList,
|
||||
&Descriptor,
|
||||
&MmMdlUnmappedUnallocated,
|
||||
&Request,
|
||||
MemoryType);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* We got a descriptor back, return its address */
|
||||
BaseAddress->QuadPart = Descriptor.BasePage << PAGE_SHIFT;
|
||||
}
|
||||
|
||||
Quickie:
|
||||
/* Restore the nesting depth */
|
||||
MmMdFreeGlobalDescriptors();
|
||||
--MmDescriptorCallTreeCount;
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
MmPapAllocatePagesInRange (
|
||||
_Inout_ PULONG PhysicalAddress,
|
||||
|
@ -53,7 +400,56 @@ MmPapAllocatePagesInRange (
|
|||
_In_ ULONG Type
|
||||
)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
NTSTATUS Status;
|
||||
PHYSICAL_ADDRESS BaseAddress;
|
||||
|
||||
/* Increment nesting depth */
|
||||
++MmDescriptorCallTreeCount;
|
||||
|
||||
/* Check for missing parameters or invalid range */
|
||||
if (!(PhysicalAddress) ||
|
||||
!(Pages) ||
|
||||
((Range) && (Range->Minimum >= Range->Maximum)))
|
||||
{
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
/* What translation mode are we using? */
|
||||
if (MmTranslationType != BlNone)
|
||||
{
|
||||
/* We don't support virtual memory yet */
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
goto Exit;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Check if this is a fixed allocation */
|
||||
BaseAddress.QuadPart = (Attributes & BL_MM_DESCRIPTOR_REQUIRES_FIXED_FLAG) ?
|
||||
*PhysicalAddress : 0;
|
||||
|
||||
/* Allocate the pages */
|
||||
Status = MmPapAllocatePhysicalPagesInRange(&BaseAddress,
|
||||
MemoryType,
|
||||
Pages,
|
||||
Attributes,
|
||||
Alignment,
|
||||
(&MmMdlMappedAllocated !=
|
||||
&MmMdlPersistentMemory) ?
|
||||
&MmMdlUnmappedAllocated :
|
||||
&MmMdlMappedAllocated,
|
||||
Range,
|
||||
Type);
|
||||
|
||||
/* Return the allocated address */
|
||||
*PhysicalAddress = BaseAddress.LowPart;
|
||||
}
|
||||
|
||||
Exit:
|
||||
/* Restore the nesting depth */
|
||||
MmMdFreeGlobalDescriptors();
|
||||
--MmDescriptorCallTreeCount;
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
|
|
Loading…
Reference in a new issue