From: Benjamin Doron <benjamin.do...@9elements.com> Former Intel platforms controlled SMRAM protection using a dedicated register.
SlimBootloader-supported platforms have converged on the SMRR, but for coreboot to support prior platforms too, lock-down is advised. Requires testing. TODO: It is more correct to install a handler in SMM to set SPI to write-protected again, though it's at least assumed secure at present: as the SMI will not be acknowledged, platform will re-enter SMM. Cc: Guo Dong <guo.d...@intel.com> Cc: Ray Ni <ray...@intel.com> Cc: Sean Rhodes <sean@starlabs.systems> Cc: James Lu <james...@intel.com> Cc: Gua Guo <gua....@intel.com> Signed-off-by: Benjamin Doron <benjamin.do...@9elements.com> --- UefiPayloadPkg/BlSupportSmm/BlSupportSmm.c | 29 ++++++ UefiPayloadPkg/BlSupportSmm/BlSupportSmm.inf | 1 + UefiPayloadPkg/Include/Guid/SmmRegisterInfoGuid.h | 1 + UefiPayloadPkg/SmmAccessDxe/SmmAccessDxe.c | 103 +++++++++++++++++++- UefiPayloadPkg/SmmAccessDxe/SmmAccessDxe.h | 1 + UefiPayloadPkg/SmmAccessDxe/SmmAccessDxe.inf | 2 + 6 files changed, 136 insertions(+), 1 deletion(-) diff --git a/UefiPayloadPkg/BlSupportSmm/BlSupportSmm.c b/UefiPayloadPkg/BlSupportSmm/BlSupportSmm.c index 0d16aec8ef70..48e7ff9ad044 100644 --- a/UefiPayloadPkg/BlSupportSmm/BlSupportSmm.c +++ b/UefiPayloadPkg/BlSupportSmm/BlSupportSmm.c @@ -6,6 +6,8 @@ writting 0xB2 port with given value from SMM communication area. The paylaod SMM handler got chance to restore regs in S3 path. + Global TODO: Install SMI handler to handle SPI write-protect. + Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> SPDX-License-Identifier: BSD-2-Clause-Patent @@ -13,9 +15,14 @@ #include <BlSupportSmm.h> +#define B_SA_SMRAMC_D_LCK_MASK (0x10) +#define B_SA_SMRAMC_D_CLS_MASK (0x20) +#define B_SA_SMRAMC_D_OPEN_MASK (0x40) + PLD_S3_COMMUNICATION mPldS3Hob; EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *mSmramHob = NULL; PLD_SMM_REGISTERS *mSmmRegisterHob = NULL; +UINT32 mSmramcAddress = 0xFFFFFFFF; UINT64 mSmmFeatureControl = 0; /** @@ -185,6 +192,20 @@ SmmFeatureLockOnS3 ( mSmmFeatureControl = AsmReadMsr64 (MSR_SMM_FEATURE_CONTROL); } +/** + Set SMRAMC, if supported, on S3 path. + +**/ +VOID +SetSmramcOnS3 ( + VOID + ) +{ + if (mSmramcAddress != 0xFFFFFFFF) { + PciOr8 (mSmramcAddress, B_SA_SMRAMC_D_LCK_MASK); + } +} + /** Function to program SMRR base and mask. @@ -299,6 +320,7 @@ BlSwSmiHandler ( ) { SetSmrrOnS3 (); + SetSmramcOnS3 (); SmmFeatureLockOnS3 (); LockSmiGlobalEn (); @@ -353,6 +375,7 @@ BlSupportSmm ( EFI_HANDLE SwHandle; EFI_HOB_GUID_TYPE *GuidHob; VOID *SmmHob; + PLD_GENERIC_REGISTER *SmramcReg; VOID *Registration; // @@ -399,6 +422,12 @@ BlSupportSmm ( } CopyMem (mSmmRegisterHob, SmmHob, GET_GUID_HOB_DATA_SIZE (GuidHob)); + + SmramcReg = GetRegisterById (REGISTER_ID_SMRAMC); + if (SmramcReg != NULL) { + DEBUG ((DEBUG_INFO, "SMRAMC reg found.\n")); + mSmramcAddress = SmramcReg->Address.Address; + } } else { return EFI_NOT_FOUND; } diff --git a/UefiPayloadPkg/BlSupportSmm/BlSupportSmm.inf b/UefiPayloadPkg/BlSupportSmm/BlSupportSmm.inf index 75d4777971fc..a92a971f7c49 100644 --- a/UefiPayloadPkg/BlSupportSmm/BlSupportSmm.inf +++ b/UefiPayloadPkg/BlSupportSmm/BlSupportSmm.inf @@ -33,6 +33,7 @@ MemoryAllocationLib BaseLib IoLib + PciLib HobLib [Guids] diff --git a/UefiPayloadPkg/Include/Guid/SmmRegisterInfoGuid.h b/UefiPayloadPkg/Include/Guid/SmmRegisterInfoGuid.h index 665eaa7e7729..feeb984b9f9b 100644 --- a/UefiPayloadPkg/Include/Guid/SmmRegisterInfoGuid.h +++ b/UefiPayloadPkg/Include/Guid/SmmRegisterInfoGuid.h @@ -27,6 +27,7 @@ typedef EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE PLD_GENERIC_ADDRESS; #define REGISTER_ID_SMI_EOS 3 #define REGISTER_ID_SMI_APM_EN 4 #define REGISTER_ID_SMI_APM_STS 5 +#define REGISTER_ID_SMRAMC 6 #pragma pack(1) typedef struct { diff --git a/UefiPayloadPkg/SmmAccessDxe/SmmAccessDxe.c b/UefiPayloadPkg/SmmAccessDxe/SmmAccessDxe.c index acb07192f714..919a47bdde7e 100644 --- a/UefiPayloadPkg/SmmAccessDxe/SmmAccessDxe.c +++ b/UefiPayloadPkg/SmmAccessDxe/SmmAccessDxe.c @@ -7,8 +7,14 @@ **/ #include "SmmAccessDxe.h" +#include <Library/PciLib.h> + +#define B_SA_SMRAMC_D_LCK_MASK (0x10) +#define B_SA_SMRAMC_D_CLS_MASK (0x20) +#define B_SA_SMRAMC_D_OPEN_MASK (0x40) SMM_ACCESS_PRIVATE_DATA mSmmAccess; +UINT32 mSmramcAddress = 0xFFFFFFFF; /** Update region state from SMRAM description @@ -53,6 +59,8 @@ Open ( IN EFI_SMM_ACCESS2_PROTOCOL *This ) { + UINT8 SmramControl; + if ((mSmmAccess.SmmRegionState & EFI_SMRAM_LOCKED) != 0) { // // Cannot open a "locked" region @@ -61,13 +69,33 @@ Open ( return EFI_DEVICE_ERROR; } + // + // Chipset code + // + if (mSmramcAddress != 0xFFFFFFFF) { + SmramControl = PciRead8 (mSmramcAddress); + + // Cannot open locked region + if ((SmramControl & B_SA_SMRAMC_D_LCK_MASK) != 0) { + mSmmAccess.SmmRegionState |= EFI_SMRAM_LOCKED; + SyncRegionState2SmramDesc (TRUE, EFI_SMRAM_LOCKED); + + DEBUG ((DEBUG_WARN, "Cannot open a locked SMRAM region\n")); + return EFI_DEVICE_ERROR; + } + + SmramControl |= B_SA_SMRAMC_D_OPEN_MASK; + SmramControl &= ~(B_SA_SMRAMC_D_CLS_MASK); + PciWrite8 (mSmramcAddress, SmramControl); + } + mSmmAccess.SmmRegionState &= ~(EFI_SMRAM_CLOSED | EFI_ALLOCATED); SyncRegionState2SmramDesc (FALSE, (UINT64)(UINTN)(~(EFI_SMRAM_CLOSED | EFI_ALLOCATED))); mSmmAccess.SmmRegionState |= EFI_SMRAM_OPEN; SyncRegionState2SmramDesc (TRUE, EFI_SMRAM_OPEN); + mSmmAccess.SmmAccess.OpenState = TRUE; - return EFI_SUCCESS; } @@ -91,6 +119,8 @@ Close ( IN EFI_SMM_ACCESS2_PROTOCOL *This ) { + UINT8 SmramControl; + if ((mSmmAccess.SmmRegionState & EFI_SMRAM_LOCKED) != 0) { // // Cannot close a "locked" region @@ -103,6 +133,25 @@ Close ( return EFI_DEVICE_ERROR; } + // + // Chipset code + // + if (mSmramcAddress != 0xFFFFFFFF) { + SmramControl = PciRead8 (mSmramcAddress); + + // Cannot open locked region + if ((SmramControl & B_SA_SMRAMC_D_LCK_MASK) != 0) { + mSmmAccess.SmmRegionState |= EFI_SMRAM_LOCKED; + SyncRegionState2SmramDesc (TRUE, EFI_SMRAM_LOCKED); + + DEBUG ((DEBUG_WARN, "Cannot close a locked SMRAM region\n")); + return EFI_DEVICE_ERROR; + } + + SmramControl &= ~(B_SA_SMRAMC_D_OPEN_MASK); + PciWrite8 (mSmramcAddress, SmramControl); + } + mSmmAccess.SmmRegionState &= ~EFI_SMRAM_OPEN; SyncRegionState2SmramDesc (FALSE, (UINT64)(UINTN)(~EFI_SMRAM_OPEN)); @@ -142,6 +191,14 @@ Lock ( mSmmAccess.SmmRegionState |= EFI_SMRAM_LOCKED; SyncRegionState2SmramDesc (TRUE, EFI_SMRAM_LOCKED); mSmmAccess.SmmAccess.LockState = TRUE; + + // + // Chipset code + // + if (mSmramcAddress != 0xFFFFFFFF) { + PciOr8 (mSmramcAddress, B_SA_SMRAMC_D_LCK_MASK); + } + return EFI_SUCCESS; } @@ -184,6 +241,33 @@ GetCapabilities ( return Status; } +/** + Get specified SMI register based on given register ID + + @param[in] SmmRegister SMI related register array from bootloader + @param[in] Id The register ID to get. + + @retval NULL The register is not found + @return smi register + +**/ +PLD_GENERIC_REGISTER * +GetRegisterById ( + PLD_SMM_REGISTERS *SmmRegisters, + UINT64 Id + ) +{ + UINT32 Index; + + for (Index = 0; Index < SmmRegisters->Count; Index++) { + if (SmmRegisters->Registers[Index].Id == Id) { + return &SmmRegisters->Registers[Index]; + } + } + + return NULL; +} + /** This function installs EFI_SMM_ACCESS_PROTOCOL. @@ -206,6 +290,8 @@ SmmAccessEntryPoint ( UINT32 SmmRegionNum; EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *SmramHob; UINT32 Index; + PLD_SMM_REGISTERS *SmmRegisters; + PLD_GENERIC_REGISTER *SmramcReg; // // Get SMRAM info HOB @@ -239,6 +325,21 @@ SmmAccessEntryPoint ( mSmmAccess.SmramDesc[Index].RegionState |= EFI_SMRAM_CLOSED | EFI_CACHEABLE; } + // + // Some platforms require to open/close SMRAMC register + // Supports PCH, not ICH (QEMU) + // + GuidHob = GetFirstGuidHob (&gSmmRegisterInfoGuid); + if (GuidHob != NULL) { + SmmRegisters = GET_GUID_HOB_DATA (GuidHob); + + SmramcReg = GetRegisterById (SmmRegisters, REGISTER_ID_SMRAMC); + if (SmramcReg != NULL) { + DEBUG ((DEBUG_INFO, "SMRAMC reg found.\n")); + mSmramcAddress = SmramcReg->Address.Address; + } + } + mSmmAccess.Signature = SMM_ACCESS_PRIVATE_DATA_SIGNATURE; mSmmAccess.NumberRegions = SmmRegionNum; mSmmAccess.SmmAccess.Open = Open; diff --git a/UefiPayloadPkg/SmmAccessDxe/SmmAccessDxe.h b/UefiPayloadPkg/SmmAccessDxe/SmmAccessDxe.h index 51a3cac8c51b..73c50a2f861e 100644 --- a/UefiPayloadPkg/SmmAccessDxe/SmmAccessDxe.h +++ b/UefiPayloadPkg/SmmAccessDxe/SmmAccessDxe.h @@ -18,6 +18,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include <Library/MemoryAllocationLib.h> #include <Library/BaseMemoryLib.h> #include <Guid/SmramMemoryReserve.h> +#include <Guid/SmmRegisterInfoGuid.h> #define SMM_ACCESS_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('S', 'M', 'M', 'A') diff --git a/UefiPayloadPkg/SmmAccessDxe/SmmAccessDxe.inf b/UefiPayloadPkg/SmmAccessDxe/SmmAccessDxe.inf index aac5ee8f28dc..bff15bc0989a 100644 --- a/UefiPayloadPkg/SmmAccessDxe/SmmAccessDxe.inf +++ b/UefiPayloadPkg/SmmAccessDxe/SmmAccessDxe.inf @@ -40,9 +40,11 @@ BaseMemoryLib MemoryAllocationLib HobLib + PciLib [Guids] gEfiSmmSmramMemoryGuid + gSmmRegisterInfoGuid [Protocols] gEfiSmmAccess2ProtocolGuid ## PRODUCES -- 2.43.0