Enhance memory gap handling in memory map

The UEFI payload uses the memory map info to guess the top of low
memory. It expects the memory map to be continuous. However, in
certain case, the memory resource HOB produced by FSP is not
continous, and it causes issue for UEFI payload to find the correct
top of low memory. This patch enhanced SBL memory map handling to
check if there is any gap in the memory map. If so, it will try to
insert a new entry to fill the gap.

Signed-off-by: Maurice Ma <maurice.ma@intel.com>
This commit is contained in:
Maurice Ma 2021-10-22 14:36:01 -07:00
parent 4936832cde
commit 4f3c50adf7
1 changed files with 74 additions and 13 deletions

View File

@ -81,23 +81,22 @@ CompareMemoryMap (
@param MemoryMapInfo Array of MemoryMapInfo structure containing memory map entry.
@retval EFI_SUCCESS Memory ranges have been splitted successfully.
@retval EFI_NOT_FOUND Could not find proper entry to split.
@retval EFI_UNSUPPORTED Required memory range size is not page aligned.
@retval EFI_OUT_OF_RESOURCES The system memory map top entry is too small.
@retval EFI_ABORTED No memory range has been splitted.
@retval EFI_ABORTED Insufficant memory map entry number.
**/
EFI_STATUS
SplitMemroyMap (
IN OUT MEMORY_MAP_INFO *MemoryMapInfo
)
{
UINTN Idx;
UINT32 Idx;
UINT32 NewIdx;
UINTN Loop;
UINT32 Loop;
UINT8 Flag;
UINT8 Type;
UINT32 Adjust;
MEMORY_MAP_ENTRY TempMemoryMap;
LOADER_GLOBAL_DATA *LdrGlobal;
LdrGlobal = (LOADER_GLOBAL_DATA *)GetLoaderGlobalDataPointer();
@ -156,19 +155,78 @@ SplitMemroyMap (
}
}
MemoryMapInfo->Entry[NewIdx].Base = PcdGet32(PcdFlashBaseAddress);
MemoryMapInfo->Entry[NewIdx].Size = PcdGet32(PcdFlashSize);
MemoryMapInfo->Entry[NewIdx].Type = MEM_MAP_TYPE_RESERVED;
MemoryMapInfo->Entry[NewIdx].Flag = 0;
NewIdx++;
if (NewIdx <= MemoryMapInfo->Count) {
return EFI_ABORTED;
// Add a flash map entry
if (NewIdx < PcdGet32 (PcdMemoryMapEntryNumber)) {
MemoryMapInfo->Entry[NewIdx].Base = PcdGet32(PcdFlashBaseAddress);
MemoryMapInfo->Entry[NewIdx].Size = PcdGet32(PcdFlashSize);
MemoryMapInfo->Entry[NewIdx].Type = MEM_MAP_TYPE_RESERVED;
MemoryMapInfo->Entry[NewIdx].Flag = 0;
NewIdx++;
}
MemoryMapInfo->Count = NewIdx;
// Always keep one free entry
if (NewIdx >= PcdGet32 (PcdMemoryMapEntryNumber)) {
return EFI_ABORTED;
}
return EFI_SUCCESS;
}
/**
Sort memory map in order and check the gap in between.
@param MemoryMapInfo Array of MemoryMapInfo structure containing memory map entry.
@retval EFI_SUCCESS Memory ranges have been splitted successfully.
@retval EFI_UNSUPPORTED Required memory range size is not page aligned.
@retval EFI_OUT_OF_RESOURCES The system memory map top entry is too small.
@retval EFI_ABORTED No memory range has been splitted.
**/
EFI_STATUS
SortMemroyMap (
IN OUT MEMORY_MAP_INFO *MemoryMapInfo
)
{
UINT32 Idx;
UINT32 NewIdx;
MEMORY_MAP_ENTRY TempMemoryMap;
UINT64 Current;
UINT32 Tolum;
NewIdx = MemoryMapInfo->Count;
PerformQuickSort (MemoryMapInfo->Entry, NewIdx, sizeof (MEMORY_MAP_ENTRY), CompareMemoryMap, &TempMemoryMap);
// Verify if there is any gap for memory map entries below top of low memory
Current = 0;
Tolum = (UINT32)GetMemoryInfo (EnumMemInfoTolum);
for (Idx = 0; Idx < MemoryMapInfo->Count; Idx++) {
if (MemoryMapInfo->Entry[Idx].Base >= Tolum) {
break;
}
if ((Current < MemoryMapInfo->Entry[Idx].Base) && (NewIdx < PcdGet32 (PcdMemoryMapEntryNumber))) {
DEBUG ((DEBUG_INFO, "Found a gap in memory map: %08X - %08X\n", Current, (UINT32)MemoryMapInfo->Entry[Idx].Base - 1));
MemoryMapInfo->Entry[NewIdx].Base = Current;
MemoryMapInfo->Entry[NewIdx].Size = MemoryMapInfo->Entry[Idx].Base - Current;
MemoryMapInfo->Entry[NewIdx].Type = MEM_MAP_TYPE_RESERVED;
MemoryMapInfo->Entry[NewIdx].Flag = 0;
NewIdx++;
}
Current = MemoryMapInfo->Entry[Idx].Base + MemoryMapInfo->Entry[Idx].Size;
}
// Check if it has enough space to cover all memory map
if (NewIdx >= PcdGet32 (PcdMemoryMapEntryNumber)) {
return EFI_ABORTED;
}
// New entry were added, need to sort again
if (NewIdx != MemoryMapInfo->Count) {
MemoryMapInfo->Count = NewIdx;
PerformQuickSort (MemoryMapInfo->Entry, NewIdx, sizeof (MEMORY_MAP_ENTRY), CompareMemoryMap, &TempMemoryMap);
}
return EFI_SUCCESS;
}
@ -293,6 +351,9 @@ BuildBaseInfoHob (
MemoryMapInfo->Revision = 1;
TraverseMemoryResourceHob (LdrGlobal->FspHobList, MemResHobCallback, MemoryMapInfo);
Status = SplitMemroyMap (MemoryMapInfo);
if (!EFI_ERROR (Status)) {
Status = SortMemroyMap (MemoryMapInfo);
}
PrintMemoryMap (MemoryMapInfo);
if (EFI_ERROR (Status)) {
CpuHaltWithStatus ("Memory map failure !", Status);