UefiPayloadPkg: UefiPayloadEntry: Don't use reserved DRAM
Recent AMD platforms reserve parts of the lower DRAM where UefiPayload is being loaded to and since UefiPayloadEntry doesn't care, it uses the reserved memory for HOB and memory allocation. The bootloader cannot prevent this, as it can only place the UEFI FV in usable DRAM, but it has no control over EfiBootService memory allocations. This issue prevents boot on those platforms without any specific error message. It's not vendor specific and can happen on every platform. Add the same logic as used on UniversalPayload and do the following: - Walk bootloader provided memory information - Skip everything that's not marked as usable DRAM - Align entries to 1MiB boundary - Don't use memory above 4GiB on x86_32 - Skip memory ranges too small - Don't use memory currently occupied by the UEFI FV itself Once a useable memory range is found pass it to HobConstructor(). TEST: Fixes boot on AMD/glinda, that reserved memory at 2000000h. Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
This commit is contained in:
parent
1d5063763b
commit
c9ff197059
|
@ -400,15 +400,6 @@ ParseMemoryInfo (
|
|||
MemoryMap.Size = cb_unpack64 (Range->size);
|
||||
MemoryMap.Type = (UINT8)Range->type;
|
||||
MemoryMap.Flag = 0;
|
||||
DEBUG ((
|
||||
DEBUG_INFO,
|
||||
"%d. %016lx - %016lx [%02x]\n",
|
||||
Index,
|
||||
MemoryMap.Base,
|
||||
MemoryMap.Base + MemoryMap.Size - 1,
|
||||
MemoryMap.Type
|
||||
));
|
||||
|
||||
MemInfoCallback (&MemoryMap, Params);
|
||||
}
|
||||
|
||||
|
|
|
@ -167,6 +167,108 @@ FindToludCallback (
|
|||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Callback function to find free and usable DRAM for HOB
|
||||
The memory region returned will have at least PcdSystemMemoryUefiRegionSize bytes
|
||||
and will be aligned to 1 MiB.
|
||||
|
||||
The caller must initialize HobMemBase to zero.
|
||||
|
||||
@param MemoryMapEntry Memory map entry info got from bootloader.
|
||||
@param Params Pointer to HobMemBase
|
||||
|
||||
@retval EFI_SUCCESS Continue walking the memory map
|
||||
@retval EFI_ALREADY_STARTED HobMemBase is not zero
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
FindFreeMemForHobCallback (
|
||||
IN MEMORY_MAP_ENTRY *MemoryMapEntry,
|
||||
IN VOID *Params
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
MEMORY_MAP_ENTRY MemoryMapEntrySplit;
|
||||
UINTN *HobMemBase = (UINTN *)Params;
|
||||
|
||||
//
|
||||
// Found new base, nothing to do
|
||||
//
|
||||
if (*HobMemBase != 0) {
|
||||
return EFI_ALREADY_STARTED;
|
||||
}
|
||||
|
||||
//
|
||||
// Skip memory types not RAM
|
||||
//
|
||||
if (MemoryMapEntry->Type != E820_RAM) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Align on 1 MiB
|
||||
//
|
||||
if (ALIGN_VALUE (MemoryMapEntry->Base, SIZE_1MB) > MemoryMapEntry->Base) {
|
||||
//
|
||||
// Skip too small
|
||||
//
|
||||
if (ALIGN_VALUE (MemoryMapEntry->Base, SIZE_1MB) >= (MemoryMapEntry->Base + MemoryMapEntry->Size)) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
MemoryMapEntry->Size -= ALIGN_VALUE (MemoryMapEntry->Base, SIZE_1MB) - MemoryMapEntry->Base;
|
||||
MemoryMapEntry->Base = ALIGN_VALUE (MemoryMapEntry->Base, SIZE_1MB);
|
||||
}
|
||||
|
||||
//
|
||||
// Skip resources above 4GiB on x86_32
|
||||
//
|
||||
if ((sizeof (UINTN) == 4) && (MemoryMapEntry->Base >= 0x100000000ULL)) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
if ((sizeof (UINTN) == 4) && ((MemoryMapEntry->Base + MemoryMapEntry->Size) > 0x100000000ULL)) {
|
||||
MemoryMapEntry->Size = 0x100000000ULL - MemoryMapEntry->Base;
|
||||
}
|
||||
|
||||
//
|
||||
// Skip too small
|
||||
//
|
||||
if (MemoryMapEntry->Size < FixedPcdGet32 (PcdSystemMemoryUefiRegionSize)) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Overlaps UefiPayload, split into smaller chunks
|
||||
//
|
||||
if ((MemoryMapEntry->Base <= PcdGet32 (PcdPayloadFdMemBase)) &&
|
||||
((MemoryMapEntry->Base + MemoryMapEntry->Size) >= PcdGet32 (PcdPayloadFdMemBase)))
|
||||
{
|
||||
MemoryMapEntrySplit.Type = E820_RAM;
|
||||
MemoryMapEntrySplit.Base = MemoryMapEntry->Base;
|
||||
MemoryMapEntrySplit.Size = PcdGet32 (PcdPayloadFdMemBase) - MemoryMapEntrySplit.Base;
|
||||
Status = FindFreeMemForHobCallback (&MemoryMapEntrySplit, Params);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
if ((MemoryMapEntry->Base + MemoryMapEntry->Size) > (PcdGet32 (PcdPayloadFdMemBase) + PcdGet32 (PcdPayloadFdMemSize))) {
|
||||
MemoryMapEntrySplit.Base = PcdGet32 (PcdPayloadFdMemBase) + PcdGet32 (PcdPayloadFdMemSize);
|
||||
MemoryMapEntrySplit.Size = (MemoryMapEntry->Base + MemoryMapEntry->Size) - MemoryMapEntrySplit.Base;
|
||||
Status = FindFreeMemForHobCallback (&MemoryMapEntrySplit, Params);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
*HobMemBase = MemoryMapEntry->Base;
|
||||
|
||||
return EFI_ALREADY_STARTED;
|
||||
}
|
||||
|
||||
/**
|
||||
Callback function to build resource descriptor HOB
|
||||
|
||||
|
@ -404,8 +506,19 @@ _ModuleEntryPoint (
|
|||
|
||||
// HOB region is used for HOB and memory allocation for this module
|
||||
MemBase = PcdGet32 (PcdPayloadFdMemBase);
|
||||
HobMemBase = ALIGN_VALUE (MemBase + PcdGet32 (PcdPayloadFdMemSize), SIZE_1MB);
|
||||
HobMemTop = HobMemBase + FixedPcdGet32 (PcdSystemMemoryUefiRegionSize);
|
||||
HobMemBase = 0;
|
||||
|
||||
//
|
||||
// Find a good place for HOB and memory allocation
|
||||
//
|
||||
ParseMemoryInfo (FindFreeMemForHobCallback, &HobMemBase);
|
||||
|
||||
ASSERT (HobMemBase != 0);
|
||||
if (HobMemBase == 0) {
|
||||
HobMemBase = ALIGN_VALUE (MemBase + PcdGet32 (PcdPayloadFdMemSize), SIZE_1MB);
|
||||
}
|
||||
|
||||
HobMemTop = HobMemBase + FixedPcdGet32 (PcdSystemMemoryUefiRegionSize);
|
||||
|
||||
HobConstructor ((VOID *)MemBase, (VOID *)HobMemTop, (VOID *)HobMemBase, (VOID *)HobMemTop);
|
||||
|
||||
|
@ -435,6 +548,8 @@ _ModuleEntryPoint (
|
|||
// The library constructors might depend on serial port, so call it after serial port hob
|
||||
ProcessLibraryConstructorList ();
|
||||
DEBUG ((DEBUG_INFO, "sizeof(UINTN) = 0x%x\n", sizeof (UINTN)));
|
||||
DEBUG ((DEBUG_INFO, "MemBase = 0x%llx\n", (UINT64)MemBase));
|
||||
DEBUG ((DEBUG_INFO, "HobMemBase = 0x%llx\n", (UINT64)HobMemBase));
|
||||
|
||||
// Build HOB based on information from Bootloader
|
||||
Status = BuildHobFromBl ();
|
||||
|
|
Loading…
Reference in New Issue