From: hanliyang <wojiaohanliy...@163.com> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4807
In the case of launch a SEV-ES VM with just OVMF_CODE.fd, the validation process in PlatformValidateNvVarStore will trigger MMIO NPF, and the #VC handler will detect that mmio access is invalid because the mmio address range of FlashNvVarStore is mapped as encrypted. In the case of launch a SEV VM with both OVMF_CODE.fd and OVMF_VARS.fd, PlatformValidateNvVarStore will fail to validate FlashNvVarStore because the mapping of FlashNvVarStore address range is encrypted in the guest but the corresponding data in system physical memory was not encrypted by guest key. We should map FlashNvVarStore address range as unencrypted for the above cases. Fixes: 4f173db8b45b ("OvmfPkg/PlatformInitLib: Add functions for EmuVariableNvStore") Signed-off-by: hanliyang <wojiaohanliy...@163.com> --- OvmfPkg/PlatformPei/AmdSev.c | 105 ++++++++++++++++++++++++++++ OvmfPkg/PlatformPei/Platform.c | 6 ++ OvmfPkg/PlatformPei/Platform.h | 6 ++ OvmfPkg/PlatformPei/PlatformPei.inf | 1 + 4 files changed, 118 insertions(+) diff --git a/OvmfPkg/PlatformPei/AmdSev.c b/OvmfPkg/PlatformPei/AmdSev.c index 8562787035..89f4c02b6a 100644 --- a/OvmfPkg/PlatformPei/AmdSev.c +++ b/OvmfPkg/PlatformPei/AmdSev.c @@ -575,3 +575,108 @@ SevInitializeRam ( ); } } + +/** + Prepared for FlashNvVarStore access. + + **/ +VOID +SevFlashNvVarStoreUpdateMapping ( + IN UINTN NvVarStoreBase, + IN UINTN NvVarStoreSize + ) +{ + volatile UINT8 *Ptr; + + RETURN_STATUS DecEncStatus; + UINT8 Offset; + + DEBUG ((DEBUG_INFO, "%a\n", __func__)); + + if (!MemEncryptSevIsEnabled ()) { + return; + } + + // + // In the case of launch a SEV-ES VM with just OVMF_CODE.fd, the + // validation process in PlatformValidateNvVarStore will trigger MMIO + // NPF, and the #VC handler will detect that mmio access is invalid + // because the mmio address range of FlashNvVarStore is mapped as + // encrypted. So, first we should update the mapping of address range + // of FlashNvVarStore as decrypted. + // + DEBUG ( + ( + DEBUG_INFO, + "%a: mapping FlashNvVarStore address range unencrypted [0x%p - 0x%p]\n", + __func__, + (UINT8 *)NvVarStoreBase, + (UINT8 *)NvVarStoreBase + NvVarStoreSize - 1 + ) + ); + + DecEncStatus = MemEncryptSevClearMmioPageEncMask ( + 0, + NvVarStoreBase, + EFI_SIZE_TO_PAGES (NvVarStoreSize) + ); + if (RETURN_ERROR (DecEncStatus)) { + DEBUG ( + ( + DEBUG_ERROR, + "%a: failed to map FlashNvStorage address range unencrypted\n", + __func__ + ) + ); + ASSERT_RETURN_ERROR (DecEncStatus); + } + + // + // Here, the first 16 bytes of FlashNvVarStore will be all zeros in + // the following cases: + // a. Launch VM with just OVMF_CODE.fd + // b. Launch VM with OVMF_CODE.fd and OVMF_VARS.fd + // In these cases, the access of FlashNvVarStore will be as expected. + // + // But if launch VM with just OVMF.fd, the first 16 bytes of + // FlashNvVarStore will be scrambled data because the data of + // FlashNvVarStore are encrypted by SEV API. In this case, we need + // mapping FlashNvVarStore address range as encrypted again, otherwise + // the validation of FlashNvVarStore will fail and trigger + // ASSERT (FALSE). + // + for (Offset = 0; Offset < 16; Offset++) { + Ptr = (UINT8 *)NvVarStoreBase + Offset; + if (*Ptr) { + break; + } + } + + if (Offset == 16) { + return; + } + + DEBUG ( + ( + DEBUG_INFO, + "%a: mapping FlashNvStorage address range encrypted\n", + __func__ + ) + ); + + DecEncStatus = MemEncryptSevSetPageEncMask ( + 0, + NvVarStoreBase, + EFI_SIZE_TO_PAGES (NvVarStoreSize) + ); + if (RETURN_ERROR (DecEncStatus)) { + DEBUG ( + ( + DEBUG_ERROR, + "%a: failed to map FlashNvStorage address range encrypted\n", + __func__ + ) + ); + ASSERT_RETURN_ERROR (DecEncStatus); + } +} diff --git a/OvmfPkg/PlatformPei/Platform.c b/OvmfPkg/PlatformPei/Platform.c index 0114529778..bcb18dacac 100644 --- a/OvmfPkg/PlatformPei/Platform.c +++ b/OvmfPkg/PlatformPei/Platform.c @@ -224,6 +224,12 @@ ReserveEmuVariableNvStore ( PcdStatus = PcdSet64S (PcdEmuVariableNvStoreReserved, VariableStore); if (FeaturePcdGet (PcdSecureBootSupported)) { + // update mapping of FlashNvVarStore address range + SevFlashNvVarStoreUpdateMapping ( + PcdGet32 (PcdOvmfFlashNvStorageVariableBase), + 2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize) + ); + // restore emulated VarStore from pristine ROM copy PlatformInitEmuVariableNvStore ((VOID *)(UINTN)VariableStore); } diff --git a/OvmfPkg/PlatformPei/Platform.h b/OvmfPkg/PlatformPei/Platform.h index 0a59547cfc..b8ad8df1dc 100644 --- a/OvmfPkg/PlatformPei/Platform.h +++ b/OvmfPkg/PlatformPei/Platform.h @@ -111,4 +111,10 @@ SevInitializeRam ( VOID ); +VOID +SevFlashNvVarStoreUpdateMapping ( + IN UINTN NvVarStoreBase, + IN UINTN NvVarStoreSize + ); + #endif // _PLATFORM_PEI_H_INCLUDED_ diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/PlatformPei.inf index 0bb1a46291..a3dd3db72d 100644 --- a/OvmfPkg/PlatformPei/PlatformPei.inf +++ b/OvmfPkg/PlatformPei/PlatformPei.inf @@ -139,6 +139,7 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaSize gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecretsBase gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecretsSize + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageVariableBase [FeaturePcd] gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire -- 2.25.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#119929): https://edk2.groups.io/g/devel/message/119929 Mute This Topic: https://groups.io/mt/107212944/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-