From efc3d6a41742dd710f7df861e56f29bbc2beac6e Mon Sep 17 00:00:00 2001 From: Oliver Smith-Denny Date: Thu, 29 Jan 2026 10:12:40 -0800 Subject: [PATCH] OvmfPkg: PlatformPei: Add PEI Memory Bin Support This commit enables PEI memory bins in OVMF IA32X64 and OVMF X64. OVMF supports many different boot flows. The variable PEIM is only dispatched when SMM_REQUIRE is TRUE. The early variable store is not set up otherwise. The PlatformPei PEIM requires the variable PPI be available before creating the gEfiMemoryTypeInformationGuid HOB, in order to use the BDS advertised bin sizes. If SMM_REQUIRE is FALSE, it just produces the HOB. PEI Core requires that the gEfiMemoryTypeInformationGuid HOB be produced pre-mem PEI in order to set up the memory bins at the start of post-mem PEI. PlatformPei is also the PEIM that installs permanent memory. As such, a depex on the variable PPI cannot be used, to support the different flows. So, this commit splits the PlatformPei initialization flow into two phases. The first phase completes until memory bin initialization. If that returns success (either because SMM_REQUIRE is FALSE or because the variable PPI was already installed), phase 2 init is completed immediately and no callback is created. If that fails, a callback is created for the variable read PPI and phase 2 initialization is completed after that. Signed-off-by: Oliver Smith-Denny --- OvmfPkg/OvmfPkgIa32X64.dsc | 1 + OvmfPkg/OvmfPkgX64.dsc | 1 + OvmfPkg/PlatformPei/MemTypeInfo.c | 31 +++++++++-- OvmfPkg/PlatformPei/Platform.c | 86 +++++++++++++++++++------------ OvmfPkg/PlatformPei/Platform.h | 8 ++- 5 files changed, 89 insertions(+), 38 deletions(-) diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc index 0e11c5fba9..aacf6b6f9b 100644 --- a/OvmfPkg/OvmfPkgIa32X64.dsc +++ b/OvmfPkg/OvmfPkgIa32X64.dsc @@ -497,6 +497,7 @@ gUefiOvmfPkgTokenSpaceGuid.PcdSecureBootSupported|TRUE gEfiMdeModulePkgTokenSpaceGuid.PcdRequireSelfSignedPk|FALSE !endif + gEfiMdeModulePkgTokenSpaceGuid.PcdPeiMemoryBinsEnable|TRUE [PcdsFixedAtBuild] gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize|1 diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc index 2780fe4439..d4b3cff7fd 100644 --- a/OvmfPkg/OvmfPkgX64.dsc +++ b/OvmfPkg/OvmfPkgX64.dsc @@ -577,6 +577,7 @@ gUefiOvmfPkgTokenSpaceGuid.PcdSecureBootSupported|TRUE gEfiMdeModulePkgTokenSpaceGuid.PcdRequireSelfSignedPk|FALSE !endif + gEfiMdeModulePkgTokenSpaceGuid.PcdPeiMemoryBinsEnable|TRUE [PcdsFixedAtBuild] gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize|1 diff --git a/OvmfPkg/PlatformPei/MemTypeInfo.c b/OvmfPkg/PlatformPei/MemTypeInfo.c index dfb1bc37a9..e0e681e7c1 100644 --- a/OvmfPkg/PlatformPei/MemTypeInfo.c +++ b/OvmfPkg/PlatformPei/MemTypeInfo.c @@ -183,10 +183,15 @@ OnReadOnlyVariable2Available ( IN VOID *Ppi ) { + EFI_HOB_GUID_TYPE *GuidHob; + DEBUG ((DEBUG_VERBOSE, "%a\n", __func__)); RefreshMemTypeInfo (Ppi); BuildMemTypeInfoHob (); + GuidHob = GetFirstGuidHob (&gUefiOvmfPkgPlatformInfoGuid); + CompleteInitialization ((EFI_HOB_PLATFORM_INFO *)GET_GUID_HOB_DATA (GuidHob), (CONST EFI_PEI_SERVICES **)PeiServices); + return EFI_SUCCESS; } @@ -201,12 +206,13 @@ STATIC CONST EFI_PEI_NOTIFY_DESCRIPTOR mReadOnlyVariable2Notify = { OnReadOnlyVariable2Available // Notify }; -VOID +EFI_STATUS MemTypeInfoInitialization ( IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob ) { - EFI_STATUS Status; + EFI_STATUS Status; + EFI_PEI_READ_ONLY_VARIABLE2_PPI *ReadOnlyVariable2; if (!PlatformInfoHob->SmmSmramRequire) { // @@ -214,7 +220,23 @@ MemTypeInfoInitialization ( // the default memory type information HOB right away. // BuildMemTypeInfoHob (); - return; + return EFI_SUCCESS; + } + + Status = PeiServicesLocatePpi ( + &gEfiPeiReadOnlyVariable2PpiGuid, + 0, + NULL, + (VOID **)&ReadOnlyVariable2 + ); + + if (!EFI_ERROR (Status)) { + // + // EFI_PEI_READ_ONLY_VARIABLE2_PPI is already available; use it now. + // + RefreshMemTypeInfo (ReadOnlyVariable2); + BuildMemTypeInfoHob (); + return EFI_SUCCESS; } Status = PeiServicesNotifyPpi (&mReadOnlyVariable2Notify); @@ -228,4 +250,7 @@ MemTypeInfoInitialization ( ASSERT (FALSE); CpuDeadLoop (); } + + // Return that we're not ready yet so that the dispatcher can dispatch the variable PEIM first + return EFI_NOT_READY; } diff --git a/OvmfPkg/PlatformPei/Platform.c b/OvmfPkg/PlatformPei/Platform.c index 1768a24037..c2085cdd40 100644 --- a/OvmfPkg/PlatformPei/Platform.c +++ b/OvmfPkg/PlatformPei/Platform.c @@ -294,6 +294,50 @@ BuildPlatformInfoHob ( return (EFI_HOB_PLATFORM_INFO *)GET_GUID_HOB_DATA (GuidHob); } +VOID +CompleteInitialization ( + IN EFI_HOB_PLATFORM_INFO *PlatformInfoHob, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + PublishPeiMemory (PlatformInfoHob); + + PlatformQemuUc32BaseInitialization (PlatformInfoHob); + + InitializeRamRegions (PlatformInfoHob); + + if (PlatformInfoHob->BootMode != BOOT_ON_S3_RESUME) { + PeiFvInitialization (PlatformInfoHob); + MemMapInitialization (PlatformInfoHob); + NoexecDxeInitialization (PlatformInfoHob); + } + + InstallClearCacheCallback (); + AmdSevInitialize (PlatformInfoHob); + if (PlatformInfoHob->HostBridgeDevId == 0xffff) { + MiscInitializationForMicrovm (PlatformInfoHob); + } else { + MiscInitialization (PlatformInfoHob); + PlatformIdInitialization (PeiServices); + } + + IntelTdxInitialize (); + InstallFeatureControlCallback (PlatformInfoHob); + if (PlatformInfoHob->SmmSmramRequire) { + RelocateSmBase (); + } + + // + // Performed after CoCo (SEV/TDX) initialization to allow the memory + // used to be validated before being used. + // + if (PlatformInfoHob->BootMode != BOOT_ON_S3_RESUME) { + if (!PlatformInfoHob->SmmSmramRequire) { + ReserveEmuVariableNvStore (); + } + } +} + /** Perform Platform PEI initialization. @@ -357,43 +401,17 @@ InitializePlatform ( Q35SmramAtDefaultSmbaseInitialization (PlatformInfoHob); } - PublishPeiMemory (PlatformInfoHob); - - PlatformQemuUc32BaseInitialization (PlatformInfoHob); - - InitializeRamRegions (PlatformInfoHob); - if (PlatformInfoHob->BootMode != BOOT_ON_S3_RESUME) { - PeiFvInitialization (PlatformInfoHob); - MemTypeInfoInitialization (PlatformInfoHob); - MemMapInitialization (PlatformInfoHob); - NoexecDxeInitialization (PlatformInfoHob); - } - - InstallClearCacheCallback (); - AmdSevInitialize (PlatformInfoHob); - if (PlatformInfoHob->HostBridgeDevId == 0xffff) { - MiscInitializationForMicrovm (PlatformInfoHob); - } else { - MiscInitialization (PlatformInfoHob); - PlatformIdInitialization (PeiServices); - } - - IntelTdxInitialize (); - InstallFeatureControlCallback (PlatformInfoHob); - if (PlatformInfoHob->SmmSmramRequire) { - RelocateSmBase (); - } - - // - // Performed after CoCo (SEV/TDX) initialization to allow the memory - // used to be validated before being used. - // - if (PlatformInfoHob->BootMode != BOOT_ON_S3_RESUME) { - if (!PlatformInfoHob->SmmSmramRequire) { - ReserveEmuVariableNvStore (); + Status = MemTypeInfoInitialization (PlatformInfoHob); + if (EFI_ERROR (Status)) { + // Failing here is okay, it just means that the variable read PPI wasn't found, so + // we need to return EFI_SUCCESS here and let the dispatcher dispatch the variable PEIM first + // and then we'll get called back to finish initialization. + return EFI_SUCCESS; } } + CompleteInitialization (PlatformInfoHob, PeiServices); + return EFI_SUCCESS; } diff --git a/OvmfPkg/PlatformPei/Platform.h b/OvmfPkg/PlatformPei/Platform.h index 5ad285ffca..b2967ea933 100644 --- a/OvmfPkg/PlatformPei/Platform.h +++ b/OvmfPkg/PlatformPei/Platform.h @@ -62,7 +62,7 @@ PeiFvInitialization ( IN EFI_HOB_PLATFORM_INFO *PlatformInfoHob ); -VOID +EFI_STATUS MemTypeInfoInitialization ( IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob ); @@ -109,3 +109,9 @@ VOID SevInitializeRam ( VOID ); + +VOID +CompleteInitialization ( + IN EFI_HOB_PLATFORM_INFO *PlatformInfoHob, + IN CONST EFI_PEI_SERVICES **PeiServices + );