[BOOTLIB]: Implement MmMdTruncateDescriptors

[BOOTLIB]: Implement MmPaTruncateMemory and call it during paging initialization to remove > 4GB memory.c
[BOOTLIB]: Implement BlpMmInitializeConstraints if those BCD options are used.

svn path=/trunk/; revision=74542
This commit is contained in:
Alex Ionescu 2017-05-14 00:39:30 +00:00
parent 920b985227
commit d4534e81e1
4 changed files with 165 additions and 10 deletions

View file

@ -2088,6 +2088,13 @@ MmMdAddDescriptorToList (
_In_ ULONG Flags
);
NTSTATUS
MmMdTruncateDescriptors (
_In_ PBL_MEMORY_DESCRIPTOR_LIST MdList,
_In_ PBL_MEMORY_DESCRIPTOR_LIST NewList,
_In_ ULONGLONG BasePage
);
VOID
MmMdRemoveDescriptorFromList (
_In_ PBL_MEMORY_DESCRIPTOR_LIST MdList,
@ -2123,6 +2130,11 @@ MmMdFreeDescriptor (
/* PAGE ALLOCATOR ROUTINES ***************************************************/
NTSTATUS
MmPaTruncateMemory (
_In_ ULONGLONG BasePage
);
NTSTATUS
BlMmAllocatePhysicalPages(
_Inout_ PPHYSICAL_ADDRESS Address,

View file

@ -408,6 +408,82 @@ MmMdInitByteGranularDescriptor (
return MemoryDescriptor;
}
NTSTATUS
MmMdTruncateDescriptors (
_In_ PBL_MEMORY_DESCRIPTOR_LIST MdList,
_In_ PBL_MEMORY_DESCRIPTOR_LIST NewList,
_In_ ULONGLONG BasePage
)
{
PLIST_ENTRY ListHead, NextEntry;
PBL_MEMORY_DESCRIPTOR Descriptor, NewDescriptor;
ULONGLONG FoundEndPage;
/* Search the descriptor list */
ListHead = MdList->First;
NextEntry = ListHead->Flink;
while (NextEntry != ListHead)
{
/* Get the current descriptor */
Descriptor = CONTAINING_RECORD(NextEntry,
BL_MEMORY_DESCRIPTOR,
ListEntry);
/* Go to the next entry in case we have to remove */
NextEntry = NextEntry->Flink;
/* Don't touch anything else but free RAM */
if (((Descriptor->Type >> BL_MEMORY_CLASS_SHIFT) == BlSystemClass) &&
(Descriptor->Type != BlConventionalMemory))
{
continue;
}
/* Check if this page is within the descriptor's region */
FoundEndPage = Descriptor->BasePage + Descriptor->PageCount;
if (BasePage > Descriptor->BasePage)
{
/* Check if it doesn't go beyond the descriptor */
if (BasePage < FoundEndPage)
{
/* Create a new descriptor to describe this region */
EfiPrintf(L"Truncating descriptor type %lx base: %llx end: %llx\r\n",
Descriptor->Type, Descriptor->BasePage, FoundEndPage);
NewDescriptor = MmMdInitByteGranularDescriptor(Descriptor->Flags,
Descriptor->Type,
BasePage,
0,
FoundEndPage - BasePage);
if (!NewDescriptor)
{
return STATUS_NO_MEMORY;
}
/* Cut off this descriptor to make it shorter */
Descriptor->PageCount = BasePage - Descriptor->BasePage;
/* Add the region to the new list */
MmMdAddDescriptorToList(NewList,
NewDescriptor,
BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG);
}
}
else
{
/* This whole descriptor covers the truncated area */
EfiPrintf(L"Truncating descriptor type %lx base: %llx end: %llx\r\n",
Descriptor->Type, Descriptor->BasePage, FoundEndPage);
MmMdRemoveDescriptorFromList(MdList, Descriptor);
MmMdAddDescriptorToList(NewList,
Descriptor,
BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG);
}
}
/* All good if we got here */
return STATUS_SUCCESS;
}
BOOLEAN
MmMdpTruncateDescriptor (
_In_ PBL_MEMORY_DESCRIPTOR_LIST MdList,

View file

@ -939,10 +939,8 @@ MmDefInitializeTranslation (
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;
/* Truncate all memory above 4GB so that we don't use it */
Status = MmPaTruncateMemory(0x100000);
if (!NT_SUCCESS(Status))
{
goto Quickie;

View file

@ -47,13 +47,72 @@ BL_MEMORY_DESCRIPTOR_LIST MmMdlMappingTrackers;
/* FUNCTIONS *****************************************************************/
NTSTATUS
MmPaTruncateMemory (
_In_ ULONGLONG BasePage
)
{
NTSTATUS Status;
/* Increase nesting depth */
++MmDescriptorCallTreeCount;
/* Set the maximum page to the truncated request */
if (BasePage < PapMaximumPhysicalPage)
{
PapMaximumPhysicalPage = BasePage;
}
/* Truncate mapped and allocated memory */
Status = MmMdTruncateDescriptors(&MmMdlMappedAllocated,
&MmMdlTruncatedMemory,
BasePage);
if (NT_SUCCESS(Status))
{
/* Truncate unmapped and allocated memory */
Status = MmMdTruncateDescriptors(&MmMdlUnmappedAllocated,
&MmMdlTruncatedMemory,
BasePage);
if (NT_SUCCESS(Status))
{
/* Truncate mapped and unallocated memory */
Status = MmMdTruncateDescriptors(&MmMdlMappedUnallocated,
&MmMdlTruncatedMemory,
BasePage);
if (NT_SUCCESS(Status))
{
/* Truncate unmapped and unallocated memory */
Status = MmMdTruncateDescriptors(&MmMdlUnmappedUnallocated,
&MmMdlTruncatedMemory,
BasePage);
if (NT_SUCCESS(Status))
{
/* Truncate reserved memory */
Status = MmMdTruncateDescriptors(&MmMdlReservedAllocated,
&MmMdlTruncatedMemory,
BasePage);
}
}
}
}
/* Restore the nesting depth */
MmMdFreeGlobalDescriptors();
--MmDescriptorCallTreeCount;
return Status;
}
NTSTATUS
BlpMmInitializeConstraints (
VOID
)
{
NTSTATUS Status;
NTSTATUS Status, ReturnStatus;
ULONGLONG LowestAddressValid, HighestAddressValid;
ULONGLONG LowestPage, HighestPage;
/* Assume success */
ReturnStatus = STATUS_SUCCESS;
/* Check for LOWMEM */
Status = BlGetBootOptionInteger(BlpApplicationEntry.BcdData,
@ -61,8 +120,15 @@ BlpMmInitializeConstraints (
&LowestAddressValid);
if (NT_SUCCESS(Status))
{
EfiPrintf(L"/LOWMEM not supported\r\n");
return STATUS_NOT_IMPLEMENTED;
/* Align the address */
LowestAddressValid = (ULONG_PTR)PAGE_ALIGN(LowestAddressValid);
LowestPage = LowestAddressValid >> PAGE_SHIFT;
/* Make sure it's below 4GB */
if (LowestPage <= 0x100000)
{
PapMinimumPhysicalPage = LowestPage;
}
}
/* Check for MAXMEM */
@ -71,12 +137,15 @@ BlpMmInitializeConstraints (
&HighestAddressValid);
if (NT_SUCCESS(Status))
{
EfiPrintf(L"/MAXMEM not supported\r\n");
return STATUS_NOT_IMPLEMENTED;
/* Get the page */
HighestPage = HighestAddressValid >> PAGE_SHIFT;
/* Truncate memory above this page */
ReturnStatus = MmPaTruncateMemory(HighestPage);
}
/* Return back to the caller */
return STATUS_SUCCESS;
return ReturnStatus;
}
NTSTATUS