mirror of
https://github.com/reactos/reactos.git
synced 2025-08-04 17:05:45 +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
3 changed files with 587 additions and 1 deletions
|
@ -61,8 +61,15 @@ EarlyPrint(_In_ PWCHAR Format, ...);
|
||||||
#define BL_MM_ADD_DESCRIPTOR_NEVER_TRUNCATE_FLAG 0x20
|
#define BL_MM_ADD_DESCRIPTOR_NEVER_TRUNCATE_FLAG 0x20
|
||||||
#define BL_MM_ADD_DESCRIPTOR_UPDATE_LIST_POINTER_FLAG 0x2000
|
#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_COALESCING_FLAG 0x2000000
|
||||||
#define BL_MM_DESCRIPTOR_REQUIRES_UPDATING_FLAG 0x4000000
|
#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
|
#define BL_MM_REMOVE_VIRTUAL_REGION_FLAG 0x80000000
|
||||||
|
|
||||||
|
@ -474,6 +481,15 @@ BlpMmInitialize (
|
||||||
_In_ PBL_LIBRARY_PARAMETERS LibraryParameters
|
_In_ PBL_LIBRARY_PARAMETERS LibraryParameters
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/* FIRMWARE ROUTINES *********************************************************/
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
EfiAllocatePages (
|
||||||
|
_In_ ULONG Type,
|
||||||
|
_In_ ULONG Pages,
|
||||||
|
_Inout_ EFI_PHYSICAL_ADDRESS* Memory
|
||||||
|
);
|
||||||
|
|
||||||
/* UTILITY ROUTINES **********************************************************/
|
/* UTILITY ROUTINES **********************************************************/
|
||||||
|
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
|
@ -553,6 +569,11 @@ MmMdInitByteGranularDescriptor (
|
||||||
_In_ ULONGLONG PageCount
|
_In_ ULONGLONG PageCount
|
||||||
);
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
MmMdFreeGlobalDescriptors (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
MmMdAddDescriptorToList (
|
MmMdAddDescriptorToList (
|
||||||
_In_ PBL_MEMORY_DESCRIPTOR_LIST MdList,
|
_In_ PBL_MEMORY_DESCRIPTOR_LIST MdList,
|
||||||
|
@ -560,6 +581,25 @@ MmMdAddDescriptorToList (
|
||||||
_In_ ULONG Flags
|
_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
|
NTSTATUS
|
||||||
MmMdRemoveRegionFromMdlEx (
|
MmMdRemoveRegionFromMdlEx (
|
||||||
__in PBL_MEMORY_DESCRIPTOR_LIST MdList,
|
__in PBL_MEMORY_DESCRIPTOR_LIST MdList,
|
||||||
|
@ -569,6 +609,11 @@ MmMdRemoveRegionFromMdlEx (
|
||||||
__in PBL_MEMORY_DESCRIPTOR_LIST NewMdList
|
__in PBL_MEMORY_DESCRIPTOR_LIST NewMdList
|
||||||
);
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
MmMdFreeDescriptor (
|
||||||
|
_In_ PBL_MEMORY_DESCRIPTOR MemoryDescriptor
|
||||||
|
);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
MmPapAllocatePagesInRange (
|
MmPapAllocatePagesInRange (
|
||||||
_Inout_ PULONG PhysicalAddress,
|
_Inout_ PULONG PhysicalAddress,
|
||||||
|
|
|
@ -646,6 +646,151 @@ Quickie:
|
||||||
return Status;
|
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
|
VOID
|
||||||
MmMdInitialize (
|
MmMdInitialize (
|
||||||
_In_ ULONG Phase,
|
_In_ ULONG Phase,
|
||||||
|
|
|
@ -10,6 +10,18 @@
|
||||||
|
|
||||||
#include "bl.h"
|
#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 ************************************************************/
|
/* DATA VARIABLES ************************************************************/
|
||||||
|
|
||||||
ULONGLONG PapMaximumPhysicalPage, PapMinimumPhysicalPage;
|
ULONGLONG PapMaximumPhysicalPage, PapMinimumPhysicalPage;
|
||||||
|
@ -42,6 +54,341 @@ BlpMmInitializeConstraints (
|
||||||
return STATUS_SUCCESS;
|
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
|
NTSTATUS
|
||||||
MmPapAllocatePagesInRange (
|
MmPapAllocatePagesInRange (
|
||||||
_Inout_ PULONG PhysicalAddress,
|
_Inout_ PULONG PhysicalAddress,
|
||||||
|
@ -53,7 +400,56 @@ MmPapAllocatePagesInRange (
|
||||||
_In_ ULONG Type
|
_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
|
NTSTATUS
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue