[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
_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,
/* PAGE ALLOCATOR ROUTINES ***************************************************/
+NTSTATUS
+MmPaTruncateMemory (
+ _In_ ULONGLONG BasePage
+ );
+
NTSTATUS
BlMmAllocatePhysicalPages(
_Inout_ PPHYSICAL_ADDRESS Address,
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,
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;
/* 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,
&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 */
&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