diff --git a/UefiPayloadPkg/Library/CbParseLib/CbParseLib.c b/UefiPayloadPkg/Library/CbParseLib/CbParseLib.c index 9e149532a7..03b6431610 100644 --- a/UefiPayloadPkg/Library/CbParseLib/CbParseLib.c +++ b/UefiPayloadPkg/Library/CbParseLib/CbParseLib.c @@ -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); } diff --git a/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.c b/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.c index 939873d762..2ecea0ce84 100644 --- a/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.c +++ b/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.c @@ -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 ();