summaryrefslogtreecommitdiffstats
path: root/MdeModulePkg
diff options
context:
space:
mode:
Diffstat (limited to 'MdeModulePkg')
-rw-r--r--MdeModulePkg/Core/Dxe/DxeMain.h6
-rw-r--r--MdeModulePkg/Core/Dxe/Gcd/Gcd.c72
-rw-r--r--MdeModulePkg/Core/Dxe/Mem/Page.c102
-rw-r--r--MdeModulePkg/Include/Guid/MemoryTypeInformation.h14
4 files changed, 186 insertions, 8 deletions
diff --git a/MdeModulePkg/Core/Dxe/DxeMain.h b/MdeModulePkg/Core/Dxe/DxeMain.h
index 86a7be2f51..53e26703f8 100644
--- a/MdeModulePkg/Core/Dxe/DxeMain.h
+++ b/MdeModulePkg/Core/Dxe/DxeMain.h
@@ -277,6 +277,12 @@ CoreInitializePool (
VOID
);
+VOID
+CoreSetMemoryTypeInformationRange (
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 Length
+ );
+
/**
Called to initialize the memory map and add descriptors to
the current descriptor list.
diff --git a/MdeModulePkg/Core/Dxe/Gcd/Gcd.c b/MdeModulePkg/Core/Dxe/Gcd/Gcd.c
index 792cd2e0af..c450d1bf25 100644
--- a/MdeModulePkg/Core/Dxe/Gcd/Gcd.c
+++ b/MdeModulePkg/Core/Dxe/Gcd/Gcd.c
@@ -2238,6 +2238,8 @@ CoreInitializeMemoryServices (
EFI_HOB_HANDOFF_INFO_TABLE *PhitHob;
EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
EFI_HOB_RESOURCE_DESCRIPTOR *PhitResourceHob;
+ EFI_HOB_RESOURCE_DESCRIPTOR *MemoryTypeInformationResourceHob;
+ UINTN Count;
EFI_PHYSICAL_ADDRESS BaseAddress;
UINT64 Length;
UINT64 Attributes;
@@ -2289,12 +2291,47 @@ CoreInitializeMemoryServices (
//
// See if a Memory Type Information HOB is available
//
- GuidHob = GetFirstGuidHob (&gEfiMemoryTypeInformationGuid);
+ MemoryTypeInformationResourceHob = NULL;
+ GuidHob = GetFirstGuidHob (&gEfiMemoryTypeInformationGuid);
if (GuidHob != NULL) {
EfiMemoryTypeInformation = GET_GUID_HOB_DATA (GuidHob);
DataSize = GET_GUID_HOB_DATA_SIZE (GuidHob);
if ((EfiMemoryTypeInformation != NULL) && (DataSize > 0) && (DataSize <= (EfiMaxMemoryType + 1) * sizeof (EFI_MEMORY_TYPE_INFORMATION))) {
CopyMem (&gMemoryTypeInformation, EfiMemoryTypeInformation, DataSize);
+
+ //
+ // Look for Resource Descriptor HOB with a ResourceType of System Memory
+ // and an Owner GUID of gEfiMemoryTypeInformationGuid. If more than 1 is
+ // found, then set MemoryTypeInformationResourceHob to NULL.
+ //
+ Count = 0;
+ for (Hob.Raw = *HobStart; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
+ if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
+ continue;
+ }
+
+ ResourceHob = Hob.ResourceDescriptor;
+ if (!CompareGuid (&ResourceHob->Owner, &gEfiMemoryTypeInformationGuid)) {
+ continue;
+ }
+
+ Count++;
+ if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) {
+ continue;
+ }
+
+ if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) {
+ continue;
+ }
+
+ if (ResourceHob->ResourceLength >= CalculateTotalMemoryBinSizeNeeded ()) {
+ MemoryTypeInformationResourceHob = ResourceHob;
+ }
+ }
+
+ if (Count > 1) {
+ MemoryTypeInformationResourceHob = NULL;
+ }
}
}
@@ -2345,6 +2382,15 @@ CoreInitializeMemoryServices (
Found = TRUE;
//
+ // If a Memory Type Information Resource HOB was found and is the same
+ // Resource HOB that describes the PHIT HOB, then ignore the Memory Type
+ // Information Resource HOB.
+ //
+ if (MemoryTypeInformationResourceHob == PhitResourceHob) {
+ MemoryTypeInformationResourceHob = NULL;
+ }
+
+ //
// Compute range between PHIT EfiMemoryTop and the end of the Resource Descriptor HOB
//
Attributes = PhitResourceHob->ResourceAttribute;
@@ -2387,8 +2433,9 @@ CoreInitializeMemoryServices (
if (Length < MinimalMemorySizeNeeded) {
//
// Search all the resource descriptor HOBs from the highest possible addresses down for a memory
- // region that is big enough to initialize the DXE core. Always skip the PHIT Resource HOB.
- // The max address must be within the physically addressible range for the processor.
+ // region that is big enough to initialize the DXE core. Always skip the PHIT Resource HOB
+ // and the Memory Type Information Resource HOB. The max address must be within the physically
+ // addressable range for the processor.
//
HighAddress = MAX_ALLOC_ADDRESS;
for (Hob.Raw = *HobStart; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
@@ -2400,6 +2447,13 @@ CoreInitializeMemoryServices (
}
//
+ // Skip the Resource Descriptor HOB that contains Memory Type Information bins
+ //
+ if (Hob.ResourceDescriptor == MemoryTypeInformationResourceHob) {
+ continue;
+ }
+
+ //
// Skip all HOBs except Resource Descriptor HOBs
//
if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
@@ -2466,6 +2520,18 @@ CoreInitializeMemoryServices (
Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeSystemMemory, Attributes);
}
+ if (MemoryTypeInformationResourceHob != NULL) {
+ //
+ // If a Memory Type Information Resource HOB was found, then use the address
+ // range of the Memory Type Information Resource HOB as the preferred
+ // address range for the Memory Type Information bins.
+ //
+ CoreSetMemoryTypeInformationRange (
+ MemoryTypeInformationResourceHob->PhysicalStart,
+ MemoryTypeInformationResourceHob->ResourceLength
+ );
+ }
+
//
// Declare the very first memory region, so the EFI Memory Services are available.
//
diff --git a/MdeModulePkg/Core/Dxe/Mem/Page.c b/MdeModulePkg/Core/Dxe/Mem/Page.c
index 6497af5733..3205732ede 100644
--- a/MdeModulePkg/Core/Dxe/Mem/Page.c
+++ b/MdeModulePkg/Core/Dxe/Mem/Page.c
@@ -533,6 +533,108 @@ CoreLoadingFixedAddressHook (
}
/**
+ Sets the preferred memory range to use for the Memory Type Information bins.
+ This service must be called before fist call to CoreAddMemoryDescriptor().
+
+ If the location of the Memory Type Information bins has already been
+ established or the size of the range provides is smaller than all the
+ Memory Type Information bins, then the range provides is not used.
+
+ @param Start The start address of the Memory Type Information range.
+ @param Length The size, in bytes, of the Memory Type Information range.
+**/
+VOID
+CoreSetMemoryTypeInformationRange (
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 Length
+ )
+{
+ EFI_PHYSICAL_ADDRESS Top;
+ EFI_MEMORY_TYPE Type;
+ UINTN Index;
+ UINTN Size;
+
+ //
+ // Return if Memory Type Information bin locations have already been set
+ //
+ if (mMemoryTypeInformationInitialized) {
+ DEBUG ((DEBUG_ERROR, "%a: Ignored. Bins already set.\n", __func__));
+ return;
+ }
+
+ //
+ // Return if size of the Memory Type Information bins is greater than Length
+ //
+ Size = 0;
+ for (Index = 0; gMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {
+ //
+ // Make sure the memory type in the gMemoryTypeInformation[] array is valid
+ //
+ Type = (EFI_MEMORY_TYPE)(gMemoryTypeInformation[Index].Type);
+ if ((UINT32)Type > EfiMaxMemoryType) {
+ continue;
+ }
+
+ Size += EFI_PAGES_TO_SIZE (gMemoryTypeInformation[Index].NumberOfPages);
+ }
+
+ if (Size > Length) {
+ return;
+ }
+
+ //
+ // Loop through each memory type in the order specified by the
+ // gMemoryTypeInformation[] array
+ //
+ Top = Start + Length;
+ for (Index = 0; gMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {
+ //
+ // Make sure the memory type in the gMemoryTypeInformation[] array is valid
+ //
+ Type = (EFI_MEMORY_TYPE)(gMemoryTypeInformation[Index].Type);
+ if ((UINT32)Type > EfiMaxMemoryType) {
+ continue;
+ }
+
+ if (gMemoryTypeInformation[Index].NumberOfPages != 0) {
+ mMemoryTypeStatistics[Type].MaximumAddress = Top - 1;
+ Top -= EFI_PAGES_TO_SIZE (gMemoryTypeInformation[Index].NumberOfPages);
+ mMemoryTypeStatistics[Type].BaseAddress = Top;
+
+ //
+ // If the current base address is the lowest address so far, then update
+ // the default maximum address
+ //
+ if (mMemoryTypeStatistics[Type].BaseAddress < mDefaultMaximumAddress) {
+ mDefaultMaximumAddress = mMemoryTypeStatistics[Type].BaseAddress - 1;
+ }
+
+ mMemoryTypeStatistics[Type].NumberOfPages = gMemoryTypeInformation[Index].NumberOfPages;
+ gMemoryTypeInformation[Index].NumberOfPages = 0;
+ }
+ }
+
+ //
+ // If the number of pages reserved for a memory type is 0, then all
+ // allocations for that type should be in the default range.
+ //
+ for (Type = (EFI_MEMORY_TYPE)0; Type < EfiMaxMemoryType; Type++) {
+ for (Index = 0; gMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {
+ if (Type == (EFI_MEMORY_TYPE)gMemoryTypeInformation[Index].Type) {
+ mMemoryTypeStatistics[Type].InformationIndex = Index;
+ }
+ }
+
+ mMemoryTypeStatistics[Type].CurrentNumberOfPages = 0;
+ if (mMemoryTypeStatistics[Type].MaximumAddress == MAX_ALLOC_ADDRESS) {
+ mMemoryTypeStatistics[Type].MaximumAddress = mDefaultMaximumAddress;
+ }
+ }
+
+ mMemoryTypeInformationInitialized = TRUE;
+}
+
+/**
Called to initialize the memory map and add descriptors to
the current descriptor list.
The first descriptor that is added must be general usable
diff --git a/MdeModulePkg/Include/Guid/MemoryTypeInformation.h b/MdeModulePkg/Include/Guid/MemoryTypeInformation.h
index e97d88765e..65adcf478b 100644
--- a/MdeModulePkg/Include/Guid/MemoryTypeInformation.h
+++ b/MdeModulePkg/Include/Guid/MemoryTypeInformation.h
@@ -1,14 +1,18 @@
/** @file
This file defines:
- * Memory Type Information GUID for HOB and Variable.
+ * Memory Type Information GUID for Guided HOB and Variable.
* Memory Type Information Variable Name.
* Memory Type Information GUID HOB data structure.
- The memory type information HOB and variable can
- be used to store the information for each memory type in Variable or HOB.
+ The memory type information HOB and variable can be used to store information
+ for each memory type in Variable or HOB.
-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
+ The Memory Type Information GUID can also be optionally used as the Owner
+ field of a Resource Descriptor HOB to provide the preferred memory range
+ for the memory types described in the Memory Type Information GUID HOB.
+
+ Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
**/