[BOOTLIB]: Implement MmPaReserveSelfMapPages, MmPaReleaseSelfMapPages

[BOOTLIB]: Stub MmDefMoveVirtualAddressRange, MmDefZeroVirtualAddressRange, MmDefRelocateSelfMap, MmDefpDestroySelfMap, MmDefpUnmapVirtualAddress, MmDefpRemapVirtualAddress, MmDefpMapPhysicalAddress, MmDefpTranslateVirtualAddress, 
[BOOTLIB]: Implement MmDefpFlushTlbEntry, MmDefpFlushTlb
[BOOTLIB]: Implement MmPaReleaseSelfMapPages, MmPaReserveSelfMapPages.
[BOOTLIB]: Implement Archx86IsCpuidSupported, BlArchIsCpuIdFunctionSupported, BlArchCpuId, BlArchGetPerformanceCounter.
[BOOTLIB]: Implement MmArchInitialize.
[BOOTLIB]: Implement most of MmDefInitializeTranslation. Almost ready to turn on paging.

svn path=/trunk/; revision=73729
This commit is contained in:
Alex Ionescu 2017-02-06 19:07:17 +00:00
parent 5267b02c28
commit 8cee5635e7
5 changed files with 665 additions and 28 deletions

View file

@ -223,6 +223,7 @@ typedef enum _BL_MEMORY_DESCRIPTOR_TYPE
{
BlMdPhysical,
BlMdVirtual,
BlMdTracker
} BL_MEMORY_DESCRIPTOR_TYPE;
typedef enum _BL_TRANSLATION_TYPE
@ -2115,6 +2116,17 @@ MmPapAllocatePhysicalPagesInRange (
);
NTSTATUS
MmPaReleaseSelfMapPages (
_In_ PHYSICAL_ADDRESS Address
);
NTSTATUS
MmPaReserveSelfMapPages (
_Inout_ PPHYSICAL_ADDRESS PhysicalAddress,
_In_ ULONG Alignment,
_In_ ULONG PageCount
);
NTSTATUS
BlMmFreePhysicalPages (
_In_ PHYSICAL_ADDRESS Address
);

View file

@ -680,7 +680,6 @@ MmMdRemoveRegionFromMdlEx (
FoundPageCount = Descriptor->PageCount;
FoundEndPage = FoundBasePage + FoundPageCount;
EndPage = PageCount + BasePage;
//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));
@ -694,19 +693,21 @@ MmMdRemoveRegionFromMdlEx (
/* Check if the found region starts after the region or ends before the region */
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\r\n");
/* This descriptor doesn't cover any part of the range -- nothing to do */
NOTHING;
}
else
{
/* This descriptor covers the head of the allocation */
//EarlyPrint(L"Descriptor covers the head of the region\r\n");
/* This descriptor covers the head of the allocation @TODO: FIXME */
EfiPrintf(L"FIXME: Descriptor covers the head of the region\r\n");
EfiStall(1000000);
}
}
else
{
/* This descriptor contains the entire allocation */
//EarlyPrint(L"Descriptor contains the entire region\r\n");
/* This descriptor contains the entire allocation @TODO: FIXME */
EfiPrintf(L"FIXME: Descriptor contains the entire region\r\n");
EfiStall(1000000);
}
/* Keep going */
@ -747,7 +748,6 @@ MmMdRemoveRegionFromMdlEx (
if (!Descriptor->PageCount)
{
/* Remove it */
//EarlyPrint(L"Entire descriptor consumed\r\n");
MmMdRemoveDescriptorFromList(MdList, Descriptor);
MmMdFreeDescriptor(Descriptor);

View file

@ -17,7 +17,12 @@ ULONG_PTR MmArchKsegBias;
ULONG MmArchLargePageSize;
BL_ADDRESS_RANGE MmArchKsegAddressRange;
ULONG_PTR MmArchTopOfApplicationAddressSpace;
ULONG_PTR Mmx86SelfMapBase;
PHYSICAL_ADDRESS Mmx86SelfMapBase;
ULONG MmDeferredMappingCount;
PVOID MmPdpt;
PVOID MmArchReferencePage;
PVOID MmPteBase;
ULONG MmArchReferencePageSize;
typedef VOID
(*PBL_MM_FLUSH_TLB) (
@ -29,10 +34,79 @@ typedef VOID
VOID
);
typedef NTSTATUS
(*PBL_MM_MOVE_VIRTUAL_ADDRESS_RANGE) (
_In_ PVOID DestinationAddress,
_In_ PVOID SourceAddress,
_In_ ULONGLONG Size
);
typedef NTSTATUS
(*PBL_MM_ZERO_VIRTUAL_ADDRESS_RANGE) (
_In_ PVOID DestinationAddress,
_In_ ULONGLONG Size
);
typedef VOID
(*PBL_MM_DESTROY_SELF_MAP) (
VOID
);
typedef VOID
(*PBL_MM_FLUSH_TLB_ENTRY) (
_In_ PVOID VirtualAddress
);
typedef VOID
(*PBL_MM_FLUSH_TLB) (
VOID
);
typedef NTSTATUS
(*PBL_MM_UNMAP_VIRTUAL_ADDRESS) (
_In_ PVOID VirtualAddress,
_In_ ULONG Size
);
typedef NTSTATUS
(*PBL_MM_REMAP_VIRTUAL_ADDRESS) (
_In_ PPHYSICAL_ADDRESS PhysicalAddress,
_Out_ PVOID VirtualAddress,
_In_ ULONG Size,
_In_ ULONG CacheAttributes
);
typedef NTSTATUS
(*PBL_MM_MAP_PHYSICAL_ADDRESS) (
_In_ PPHYSICAL_ADDRESS PhysicalAddress,
_Out_ PVOID VirtualAddress,
_In_ ULONG Size,
_In_ ULONG CacheAttributes
);
typedef BOOLEAN
(*PBL_MM_TRANSLATE_VIRTUAL_ADDRESS) (
_In_ PVOID VirtualAddress,
_Out_ PPHYSICAL_ADDRESS PhysicalAddress,
_Out_opt_ PULONG CacheAttributes
);
PBL_MM_TRANSLATE_VIRTUAL_ADDRESS Mmx86TranslateVirtualAddress;
PBL_MM_MAP_PHYSICAL_ADDRESS Mmx86MapPhysicalAddress;
PBL_MM_REMAP_VIRTUAL_ADDRESS Mmx86RemapVirtualAddress;
PBL_MM_UNMAP_VIRTUAL_ADDRESS Mmx86UnmapVirtualAddress;
PBL_MM_FLUSH_TLB Mmx86FlushTlb;
PBL_MM_FLUSH_TLB_ENTRY Mmx86FlushTlbEntry;
PBL_MM_DESTROY_SELF_MAP Mmx86DestroySelfMap;
PBL_MM_RELOCATE_SELF_MAP BlMmRelocateSelfMap;
PBL_MM_FLUSH_TLB BlMmFlushTlb;
PBL_MM_MOVE_VIRTUAL_ADDRESS_RANGE BlMmMoveVirtualAddressRange;
PBL_MM_ZERO_VIRTUAL_ADDRESS_RANGE BlMmZeroVirtualAddressRange;
ULONG MmDeferredMappingCount;
PBL_MM_FLUSH_TLB Mmx86FlushTlb;
#define PTE_BASE (PVOID)0xC0000000
/* FUNCTIONS *****************************************************************/
@ -45,6 +119,38 @@ MmArchNullFunction (
return;
}
VOID
MmDefRelocateSelfMap (
VOID
)
{
if (MmPteBase != PTE_BASE)
{
EfiPrintf(L"Supposed to relocate CR3\r\n");
}
}
NTSTATUS
MmDefMoveVirtualAddressRange (
_In_ PVOID DestinationAddress,
_In_ PVOID SourceAddress,
_In_ ULONGLONG Size
)
{
EfiPrintf(L"Supposed to move shit\r\n");
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
MmDefZeroVirtualAddressRange (
_In_ PVOID DestinationAddress,
_In_ ULONGLONG Size
)
{
EfiPrintf(L"Supposed to zero shit\r\n");
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
Mmx86pMapMemoryRegions (
_In_ ULONG Phase,
@ -78,17 +184,6 @@ Mmx86pMapMemoryRegions (
return STATUS_NOT_IMPLEMENTED;
}
BOOLEAN
Mmx86TranslateVirtualAddress (
_In_ PVOID VirtualAddress,
_Out_opt_ PPHYSICAL_ADDRESS PhysicalAddress,
_Out_opt_ PULONG CachingFlags
)
{
EfiPrintf(L"paging TODO\r\n");
return FALSE;
}
BOOLEAN
MmArchTranslateVirtualAddress (
_In_ PVOID VirtualAddress,
@ -131,6 +226,293 @@ MmArchTranslateVirtualAddress (
return Descriptor != NULL;
}
BOOLEAN
Archx86IsCpuidSupported (
VOID
)
{
ULONG CallerFlags, Flags;
/* Read the original flags, and add the CPUID bit */
CallerFlags = __getcallerseflags() ^ 0x200000;
__writeeflags(CallerFlags);
/* Read our flags now */
Flags = __readeflags();
/* Check if the bit stuck */
return (((CallerFlags ^ Flags) >> 21) & 1) ^ 1;
}
BOOLEAN
BlArchIsCpuIdFunctionSupported (
_In_ ULONG Function
)
{
BOOLEAN Supported;
INT CpuInfo[4];
/* Check if the CPU supports this instruction */
Supported = Archx86IsCpuidSupported();
if (!Supported)
{
return FALSE;
}
/* Check if it's the extended function */
if (Function >= 0x80000000)
{
/* Check if extended functions are supported */
__cpuid(CpuInfo, 0x80000000);
if ((CpuInfo[0] & 0xFFFFFF00) != 0x80000000)
{
/* Nope */
return FALSE;
}
}
else
{
/* It's a regular function, get the maximum one supported */
__cpuid(CpuInfo, 0);
}
/* Check if our function is within bounds */
if (Function <= CpuInfo[0])
{
return TRUE;
}
/* Nope */
return FALSE;
}
VOID
BlArchCpuId (
_In_ ULONG Function,
_In_ ULONG SubFunction,
_Out_ INT* Result
)
{
/* Use the intrinsic */
__cpuidex(Result, Function, SubFunction);
}
ULONGLONG
BlArchGetPerformanceCounter (
VOID
)
{
INT CpuInfo[4];
/* Serialize with CPUID, if it exists */
if (Archx86IsCpuidSupported())
{
BlArchCpuId(0, 0, CpuInfo);
}
/* Read the TSC */
return __rdtsc();
}
VOID
MmDefpDestroySelfMap (
VOID
)
{
EfiPrintf(L"No destroy\r\n");
}
VOID
MmDefpFlushTlbEntry (
_In_ PVOID VirtualAddress
)
{
/* Flush the TLB */
__invlpg(VirtualAddress);
}
VOID
MmDefpFlushTlb (
VOID
)
{
/* Flush the TLB */
__writecr3(__readcr3());
}
NTSTATUS
MmDefpUnmapVirtualAddress (
_In_ PVOID VirtualAddress,
_In_ ULONG Size
)
{
EfiPrintf(L"No unmap\r\n");
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
MmDefpRemapVirtualAddress (
_In_ PPHYSICAL_ADDRESS PhysicalAddress,
_Out_ PVOID VirtualAddress,
_In_ ULONG Size,
_In_ ULONG CacheAttributes
)
{
EfiPrintf(L"No remap\r\n");
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
MmDefpMapPhysicalAddress (
_In_ PPHYSICAL_ADDRESS PhysicalAddress,
_Out_ PVOID VirtualAddress,
_In_ ULONG Size,
_In_ ULONG CacheAttributes
)
{
EfiPrintf(L"No map\r\n");
return STATUS_NOT_IMPLEMENTED;
}
BOOLEAN
MmDefpTranslateVirtualAddress (
_In_ PVOID VirtualAddress,
_Out_ PPHYSICAL_ADDRESS PhysicalAddress,
_Out_opt_ PULONG CacheAttributes
)
{
EfiPrintf(L"No translate\r\n");
return FALSE;
}
NTSTATUS
MmDefInitializeTranslation (
_In_ PBL_MEMORY_DATA MemoryData,
_In_ BL_TRANSLATION_TYPE TranslationType
)
{
NTSTATUS Status;
PHYSICAL_ADDRESS PhysicalAddress;
/* Set the global function pointers for memory translation */
Mmx86TranslateVirtualAddress = MmDefpTranslateVirtualAddress;
Mmx86MapPhysicalAddress = MmDefpMapPhysicalAddress;
Mmx86UnmapVirtualAddress = MmDefpUnmapVirtualAddress;
Mmx86RemapVirtualAddress = MmDefpRemapVirtualAddress;
Mmx86FlushTlb = MmDefpFlushTlb;
Mmx86FlushTlbEntry = MmDefpFlushTlbEntry;
Mmx86DestroySelfMap = MmDefpDestroySelfMap;
/* Check what mode we're currently in */
if (TranslationType == BlVirtual)
{
EfiPrintf(L"Virtual->Virtual not yet supported\r\n");
return STATUS_NOT_IMPLEMENTED;
}
else if (TranslationType != BlNone)
{
/* Not even Windows supports PAE->Virtual downgrade */
return STATUS_NOT_IMPLEMENTED;
}
/* The None->Virtual case */
MmPdpt = NULL;
Mmx86SelfMapBase.QuadPart = 0;
MmArchReferencePage = NULL;
/* Truncate all memory above 4GB so that we don't use it @TODO: FIXME */
EfiPrintf(L"Warning: not truncating > 4GB memory. Don't boot with more than 4GB of RAM!\r\n");
//Status = MmPaTruncateMemory(0x100000);
Status = STATUS_SUCCESS;
if (!NT_SUCCESS(Status))
{
goto Quickie;
}
/* Allocate a page directory */
Status = MmPapAllocatePhysicalPagesInRange(&PhysicalAddress,
BlLoaderPageDirectory,
1,
0,
0,
&MmMdlUnmappedAllocated,
0,
0);
if (!NT_SUCCESS(Status))
{
goto Quickie;
}
/* Zero out the page directory */
MmPdpt = (PVOID)PhysicalAddress.LowPart;
RtlZeroMemory(MmPdpt, PAGE_SIZE);
/* Set the page size */
MmArchReferencePageSize = PAGE_SIZE;
/* Allocate the self-map page */
Status = MmPapAllocatePhysicalPagesInRange(&PhysicalAddress,
BlLoaderReferencePage,
1,
0,
0,
&MmMdlUnmappedAllocated,
0,
0);
if (!NT_SUCCESS(Status))
{
goto Quickie;
}
/* Set the reference page */
MmArchReferencePage = (PVOID)PhysicalAddress.LowPart;
/* Zero it out */
RtlZeroMemory(MmArchReferencePage, MmArchReferencePageSize);
/* Allocate 4MB worth of self-map pages */
Status = MmPaReserveSelfMapPages(&Mmx86SelfMapBase,
(4 * 1024 * 1024) >> PAGE_SHIFT,
(4 * 1024 * 1024) >> PAGE_SHIFT);
if (!NT_SUCCESS(Status))
{
goto Quickie;
}
/* Zero them out */
RtlZeroMemory((PVOID)Mmx86SelfMapBase.LowPart, 4 * 1024 * 1024);
EfiPrintf(L"PDPT at 0x%p Reference Page at 0x%p Self-map at 0x%p\r\n",
MmPdpt, MmArchReferencePage, Mmx86SelfMapBase.LowPart);
Status = STATUS_NOT_IMPLEMENTED;
//MmPteBase = Mmx86SelfMapBase.LowPart & 0xFFC00000;
Quickie:
/* Free reference page if we allocated it */
if (MmArchReferencePage)
{
PhysicalAddress.QuadPart = (ULONG_PTR)MmArchReferencePage;
BlMmFreePhysicalPages(PhysicalAddress);
}
/* Free page directory if we allocated it */
if (MmPdpt)
{
PhysicalAddress.QuadPart = (ULONG_PTR)MmPdpt;
BlMmFreePhysicalPages(PhysicalAddress);
}
/* Free the self map if we allocated it */
if (Mmx86SelfMapBase.QuadPart)
{
MmPaReleaseSelfMapPages(Mmx86SelfMapBase);
}
/* All done */
return Status;
}
NTSTATUS
MmArchInitialize (
_In_ ULONG Phase,
@ -140,6 +522,8 @@ MmArchInitialize (
)
{
NTSTATUS Status;
ULONGLONG IncreaseUserVa, PerfCounter, CpuRandom;
INT CpuInfo[4];
/* For phase 2, just map deferred regions */
if (Phase != 1)
@ -160,7 +544,7 @@ MmArchInitialize (
MmArchKsegAddressRange.Minimum = 0;
MmArchKsegAddressRange.Maximum = (ULONGLONG)~0;
MmArchTopOfApplicationAddressSpace = 0;
Mmx86SelfMapBase = 0;
Mmx86SelfMapBase.QuadPart = 0;
/* Set stub functions */
BlMmRelocateSelfMap = MmArchNullFunction;
@ -172,7 +556,70 @@ MmArchInitialize (
case BlVirtual:
Status = STATUS_NOT_IMPLEMENTED;
/* Set the large page size to 1024 pages (4MB) */
MmArchLargePageSize = (4 * 1024 * 1024) / PAGE_SIZE;
/* Check if /USERVA option was used */
Status = BlGetBootOptionInteger(BlpApplicationEntry.BcdData,
BcdOSLoaderInteger_IncreaseUserVa,
&IncreaseUserVa);
if (NT_SUCCESS(Status) && (IncreaseUserVa))
{
/* Yes -- load the kernel at 0xE0000000 instead */
MmArchKsegBase = 0xE0000000;
}
else
{
/* Nope, load at the standard 2GB split */
MmArchKsegBase = 0x80000000;
}
/* Check if CPUID 01h is supported */
CpuRandom = 0;
if (BlArchIsCpuIdFunctionSupported(1))
{
/* Call it */
BlArchCpuId(1, 0, CpuInfo);
/* Check if RDRAND is supported */
if (CpuInfo[2] & 0x40000000)
{
EfiPrintf(L"Your CPU can do RDRAND! Good for you!\r\n");
CpuRandom = 0;
}
}
/* Read the TSC */
PerfCounter = BlArchGetPerformanceCounter();
PerfCounter >>= 4;
_rotl16(PerfCounter, 5);
/* Set the address range */
MmArchKsegAddressRange.Minimum = 0;
MmArchKsegAddressRange.Maximum = (ULONGLONG)~0;
/* Set the KASLR bias */
MmArchKsegBias = ((PerfCounter ^ CpuRandom) & 0xFFF) << 12;
MmArchKsegBias = 0;
MmArchKsegBase += MmArchKsegBias;
/* Set the kernel range */
MmArchKsegAddressRange.Minimum = MmArchKsegBase;
MmArchKsegAddressRange.Maximum = (ULONGLONG)~0;
/* Set the boot application top maximum */
MmArchTopOfApplicationAddressSpace = 0x70000000;
/* Initialize virtual address space translation */
Status = MmDefInitializeTranslation(MemoryData, TranslationType);
if (NT_SUCCESS(Status))
{
/* Set stub functions */
BlMmRelocateSelfMap = MmDefRelocateSelfMap;
BlMmFlushTlb = Mmx86FlushTlb;
BlMmMoveVirtualAddressRange = MmDefMoveVirtualAddressRange;
BlMmZeroVirtualAddressRange = MmDefZeroVirtualAddressRange;
}
break;
case BlPae:

View file

@ -13,7 +13,9 @@
/* DATA VARIABLES ************************************************************/
BL_TRANSLATION_TYPE MmTranslationType, MmOriginalTranslationType;
/* This is a bug in Windows, but is required for MmTrInitialize to load */
BL_TRANSLATION_TYPE MmTranslationType = BlMax;
BL_TRANSLATION_TYPE MmOriginalTranslationType;
ULONG MmDescriptorCallTreeCount;
/* FUNCTIONS *****************************************************************/
@ -23,15 +25,70 @@ MmTrInitialize (
VOID
)
{
PBL_MEMORY_DESCRIPTOR Descriptor;
NTSTATUS Status;
PLIST_ENTRY NextEntry;
/* Nothing to track if we're using physical memory */
if (MmTranslationType == BlNone)
{
return STATUS_SUCCESS;
}
/* TODO */
EfiPrintf(L"Required for protected mode\r\n");
return STATUS_NOT_IMPLEMENTED;
/* Initialize all the virtual lists */
MmMdInitializeListHead(&MmMdlMappingTrackers);
MmMdlMappingTrackers.Type = BlMdTracker;
MmMdInitializeListHead(&MmMdlFreeVirtual);
MmMdlFreeVirtual.Type = BlMdVirtual;
/* Initialize a 4GB free descriptor */
Descriptor = MmMdInitByteGranularDescriptor(0,
BlConventionalMemory,
0,
0,
((ULONGLONG)4 * 1024 * 1024 * 1024) >>
PAGE_SHIFT);
if (!Descriptor)
{
Status = STATUS_NO_MEMORY;
goto Quickie;
}
/* Add this 4GB region to the free virtual address space list */
Status = MmMdAddDescriptorToList(&MmMdlFreeVirtual,
Descriptor,
BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG);
if (!NT_SUCCESS(Status))
{
RtlZeroMemory(Descriptor, sizeof(*Descriptor));
goto Quickie;
}
/* Remove any reserved regions of virtual address space */
NextEntry = MmMdlReservedAllocated.First->Flink;
while (NextEntry != MmMdlReservedAllocated.First)
{
/* Grab the descriptor and see if it's mapped */
Descriptor = CONTAINING_RECORD(NextEntry, BL_MEMORY_DESCRIPTOR, ListEntry);
if (Descriptor->VirtualPage)
{
EfiPrintf(L"Need to handle reserved allocation: %llx %llx\r\n",
Descriptor->VirtualPage, Descriptor->PageCount);
EfiStall(100000);
Status = STATUS_NOT_IMPLEMENTED;
goto Quickie;
}
/* Next entry */
NextEntry = NextEntry->Flink;
}
/* Set success if we made it */
Status = STATUS_SUCCESS;
Quickie:
/* Return back to caller */
return Status;
}
NTSTATUS

View file

@ -628,7 +628,7 @@ MmPapFreePhysicalPages (
DontFree = FALSE;
HasPageData = FALSE;
/* Only page-aligned addresses a re accepted */
/* Only page-aligned addresses are accepted */
if (Address.QuadPart & (PAGE_SIZE - 1))
{
EfiPrintf(L"free mem fail 1\r\n");
@ -1096,3 +1096,124 @@ Quickie:
MmMdFreeList(&FirmwareMdList);
return Status;
}
NTSTATUS
MmPaReleaseSelfMapPages (
_In_ PHYSICAL_ADDRESS Address
)
{
PBL_MEMORY_DESCRIPTOR Descriptor;
ULONGLONG BasePage;
NTSTATUS Status;
/* Only page-aligned addresses are accepted */
if (Address.QuadPart & (PAGE_SIZE - 1))
{
EfiPrintf(L"free mem fail 1\r\n");
return STATUS_INVALID_PARAMETER;
}
/* Get the base page, and find a descriptor that matches */
BasePage = Address.QuadPart >> PAGE_SHIFT;
Descriptor = MmMdFindDescriptor(BL_MM_INCLUDE_UNMAPPED_UNALLOCATED,
BL_MM_REMOVE_PHYSICAL_REGION_FLAG,
BasePage);
if (!(Descriptor) || (Descriptor->BasePage != BasePage))
{
return STATUS_INVALID_PARAMETER;
}
/* Free the physical pages */
Status = MmFwFreePages(BasePage, Descriptor->PageCount);
if (!NT_SUCCESS(Status))
{
return Status;
}
/* Remove the firmware flags */
Descriptor->Flags &= ~(BlMemoryNonFirmware |
BlMemoryFirmware |
BlMemoryPersistent);
/* Set it as free memory */
Descriptor->Type = BlConventionalMemory;
/* Create a new descriptor that's free memory, covering the old range */
Descriptor = MmMdInitByteGranularDescriptor(0,
BlConventionalMemory,
BasePage,
0,
Descriptor->PageCount);
if (!Descriptor)
{
return STATUS_NO_MEMORY;
}
/* Insert it into the virtual free list */
return MmMdAddDescriptorToList(&MmMdlFreeVirtual,
Descriptor,
BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG |
BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG);
}
NTSTATUS
MmPaReserveSelfMapPages (
_Inout_ PPHYSICAL_ADDRESS PhysicalAddress,
_In_ ULONG Alignment,
_In_ ULONG PageCount
)
{
NTSTATUS Status;
BL_PA_REQUEST Request;
BL_MEMORY_DESCRIPTOR Descriptor;
/* Increment descriptor usage count */
++MmDescriptorCallTreeCount;
/* Bail if we don't have an address */
if (!PhysicalAddress)
{
Status = STATUS_INVALID_PARAMETER;
goto Quickie;
}
/* Make a request for the required number of self-map pages */
Request.BaseRange.Minimum = PapMinimumPhysicalPage;
Request.BaseRange.Maximum = 0xFFFFFFFF >> PAGE_SHIFT;
Request.VirtualRange.Minimum = 0;
Request.VirtualRange.Maximum = 0;
Request.Pages = PageCount;
Request.Alignment = Alignment;
Request.Type = BL_MM_REQUEST_DEFAULT_TYPE;
Request.Flags = 0;;
Status = MmPaAllocatePages(&MmMdlUnmappedUnallocated,
&Descriptor,
&MmMdlUnmappedUnallocated,
&Request,
BlLoaderSelfMap);
if (!NT_SUCCESS(Status))
{
goto Quickie;
}
/* Remove this region from free virtual memory */
Status = MmMdRemoveRegionFromMdlEx(&MmMdlFreeVirtual,
BL_MM_REMOVE_VIRTUAL_REGION_FLAG,
Descriptor.BasePage,
Descriptor.PageCount,
0);
if (!NT_SUCCESS(Status))
{
goto Quickie;
}
/* Return the physical address */
PhysicalAddress->QuadPart = Descriptor.BasePage << PAGE_SHIFT;
Quickie:
/* Free global descriptors and reduce the count by one */
MmMdFreeGlobalDescriptors();
--MmDescriptorCallTreeCount;
return Status;
}