From e6ea1464a846b3f012a9ca07d92924c2e1b88334 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 15 Dec 2021 17:48:58 +0100 Subject: OvmfPkg/PlatformPei: Revert "stop using cmos for memory detection" This reverts commit 41d8bb30386ceab55787fc9f5aac6434e2493e27, as it breaks Cloud Hypervisor. Reported-by: Sebastien Boeuf Signed-off-by: Ard Biesheuvel --- OvmfPkg/PlatformPei/MemDetect.c | 59 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/OvmfPkg/PlatformPei/MemDetect.c b/OvmfPkg/PlatformPei/MemDetect.c index fb38e3c39d..1bcb5a08bc 100644 --- a/OvmfPkg/PlatformPei/MemDetect.c +++ b/OvmfPkg/PlatformPei/MemDetect.c @@ -38,6 +38,7 @@ Module Name: #include #include "Platform.h" +#include "Cmos.h" UINT8 mPhysMemAddressWidth; @@ -321,11 +322,51 @@ GetSystemMemorySizeBelow4gb ( { EFI_STATUS Status; UINT64 LowerMemorySize = 0; + UINT8 Cmos0x34; + UINT8 Cmos0x35; Status = ScanOrAdd64BitE820Ram (FALSE, &LowerMemorySize, NULL); - ASSERT_EFI_ERROR (Status); - ASSERT (LowerMemorySize > 0); - return (UINT32)LowerMemorySize; + if ((Status == EFI_SUCCESS) && (LowerMemorySize > 0)) { + return (UINT32)LowerMemorySize; + } + + // + // CMOS 0x34/0x35 specifies the system memory above 16 MB. + // * CMOS(0x35) is the high byte + // * CMOS(0x34) is the low byte + // * The size is specified in 64kb chunks + // * Since this is memory above 16MB, the 16MB must be added + // into the calculation to get the total memory size. + // + + Cmos0x34 = (UINT8)CmosRead8 (0x34); + Cmos0x35 = (UINT8)CmosRead8 (0x35); + + return (UINT32)(((UINTN)((Cmos0x35 << 8) + Cmos0x34) << 16) + SIZE_16MB); +} + +STATIC +UINT64 +GetSystemMemorySizeAbove4gb ( + ) +{ + UINT32 Size; + UINTN CmosIndex; + + // + // CMOS 0x5b-0x5d specifies the system memory above 4GB MB. + // * CMOS(0x5d) is the most significant size byte + // * CMOS(0x5c) is the middle size byte + // * CMOS(0x5b) is the least significant size byte + // * The size is specified in 64kb chunks + // + + Size = 0; + for (CmosIndex = 0x5d; CmosIndex >= 0x5b; CmosIndex--) { + Size = (UINT32)(Size << 8) + (UINT32)CmosRead8 (CmosIndex); + } + + return LShiftU64 (Size, 16); } /** @@ -355,9 +396,12 @@ GetFirstNonAddress ( // If QEMU presents an E820 map, then get the highest exclusive >=4GB RAM // address from it. This can express an address >= 4GB+1TB. // + // Otherwise, get the flat size of the memory above 4GB from the CMOS (which + // can only express a size smaller than 1TB), and add it to 4GB. + // Status = ScanOrAdd64BitE820Ram (FALSE, NULL, &FirstNonAddress); if (EFI_ERROR (Status)) { - FirstNonAddress = BASE_4GB; + FirstNonAddress = BASE_4GB + GetSystemMemorySizeAbove4gb (); } // @@ -729,6 +773,7 @@ QemuInitializeRam ( ) { UINT64 LowerMemorySize; + UINT64 UpperMemorySize; MTRR_SETTINGS MtrrSettings; EFI_STATUS Status; @@ -787,6 +832,12 @@ QemuInitializeRam ( // memory size read from the CMOS. // Status = ScanOrAdd64BitE820Ram (TRUE, NULL, NULL); + if (EFI_ERROR (Status)) { + UpperMemorySize = GetSystemMemorySizeAbove4gb (); + if (UpperMemorySize != 0) { + AddMemoryBaseSizeHob (BASE_4GB, UpperMemorySize); + } + } } // -- cgit v1.2.3