/** @file Functions and types shared by the SMM accessor PEI and DXE modules. Copyright (C) 2015, Red Hat, Inc. Copyright (c) 2024 Intel Corporation. SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include #include #include #include "SmramInternal.h" // // The value of PcdQ35TsegMbytes is saved into this variable at module startup. // UINT16 mQ35TsegMbytes; // // The value of PcdQ35SmramAtDefaultSmbase is saved into this variable at // module startup. // STATIC BOOLEAN mQ35SmramAtDefaultSmbase; /** Save PcdQ35TsegMbytes into mQ35TsegMbytes. **/ VOID InitQ35TsegMbytes ( VOID ) { mQ35TsegMbytes = PcdGet16 (PcdQ35TsegMbytes); } /** Save PcdQ35SmramAtDefaultSmbase into mQ35SmramAtDefaultSmbase. **/ VOID InitQ35SmramAtDefaultSmbase ( VOID ) { mQ35SmramAtDefaultSmbase = PcdGetBool (PcdQ35SmramAtDefaultSmbase); } /** Read the MCH_SMRAM and ESMRAMC registers, and update the LockState and OpenState fields in the PEI_SMM_ACCESS_PPI / EFI_SMM_ACCESS2_PROTOCOL object, from the D_LCK and T_EN bits. PEI_SMM_ACCESS_PPI and EFI_SMM_ACCESS2_PROTOCOL member functions can rely on the LockState and OpenState fields being up-to-date on entry, and they need to restore the same invariant on exit, if they touch the bits in question. @param[out] LockState Reflects the D_LCK bit on output; TRUE iff SMRAM is locked. @param[out] OpenState Reflects the inverse of the T_EN bit on output; TRUE iff SMRAM is open. **/ VOID GetStates ( OUT BOOLEAN *LockState, OUT BOOLEAN *OpenState ) { UINT8 SmramVal, EsmramcVal; SmramVal = PciRead8 (DRAMC_REGISTER_Q35 (MCH_SMRAM)); EsmramcVal = PciRead8 (DRAMC_REGISTER_Q35 (MCH_ESMRAMC)); *LockState = !!(SmramVal & MCH_SMRAM_D_LCK); *OpenState = !(EsmramcVal & MCH_ESMRAMC_T_EN); } // // The functions below follow the PEI_SMM_ACCESS_PPI and // EFI_SMM_ACCESS2_PROTOCOL member declarations. The PeiServices and This // pointers are removed (TSEG doesn't depend on them), and so is the // DescriptorIndex parameter (TSEG doesn't support range-wise locking). // // The LockState and OpenState members that are common to both // PEI_SMM_ACCESS_PPI and EFI_SMM_ACCESS2_PROTOCOL are taken and updated in // isolation from the rest of the (non-shared) members. // EFI_STATUS SmramAccessOpen ( OUT BOOLEAN *LockState, OUT BOOLEAN *OpenState ) { // // Open TSEG by clearing T_EN. // PciAnd8 ( DRAMC_REGISTER_Q35 (MCH_ESMRAMC), (UINT8)((~(UINT32)MCH_ESMRAMC_T_EN) & 0xff) ); GetStates (LockState, OpenState); if (!*OpenState) { return EFI_DEVICE_ERROR; } return EFI_SUCCESS; } EFI_STATUS SmramAccessClose ( OUT BOOLEAN *LockState, OUT BOOLEAN *OpenState ) { // // Close TSEG by setting T_EN. // PciOr8 (DRAMC_REGISTER_Q35 (MCH_ESMRAMC), MCH_ESMRAMC_T_EN); GetStates (LockState, OpenState); if (*OpenState) { return EFI_DEVICE_ERROR; } return EFI_SUCCESS; } EFI_STATUS SmramAccessLock ( OUT BOOLEAN *LockState, IN OUT BOOLEAN *OpenState ) { if (*OpenState) { return EFI_DEVICE_ERROR; } // // Close & lock TSEG by setting T_EN and D_LCK. // PciOr8 (DRAMC_REGISTER_Q35 (MCH_ESMRAMC), MCH_ESMRAMC_T_EN); PciOr8 (DRAMC_REGISTER_Q35 (MCH_SMRAM), MCH_SMRAM_D_LCK); // // Close & lock the SMRAM at the default SMBASE, if it exists. // if (mQ35SmramAtDefaultSmbase) { PciWrite8 ( DRAMC_REGISTER_Q35 (MCH_DEFAULT_SMBASE_CTL), MCH_DEFAULT_SMBASE_LCK ); } GetStates (LockState, OpenState); if (*OpenState || !*LockState) { return EFI_DEVICE_ERROR; } return EFI_SUCCESS; } EFI_STATUS SmramAccessGetCapabilities ( IN OUT UINTN *SmramMapSize, IN OUT EFI_SMRAM_DESCRIPTOR *SmramMap ) { UINTN BufferSize; EFI_HOB_GUID_TYPE *GuidHob; EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *DescriptorBlock; UINTN Index; // // Get Hob list // GuidHob = GetFirstGuidHob (&gEfiSmmSmramMemoryGuid); DescriptorBlock = GET_GUID_HOB_DATA (GuidHob); ASSERT (DescriptorBlock); BufferSize = DescriptorBlock->NumberOfSmmReservedRegions * sizeof (EFI_SMRAM_DESCRIPTOR); if (*SmramMapSize < BufferSize) { *SmramMapSize = BufferSize; return EFI_BUFFER_TOO_SMALL; } // // Update SmramMapSize to real return SMRAM map size // *SmramMapSize = BufferSize; // // Use the hob to publish SMRAM capabilities // for (Index = 0; Index < DescriptorBlock->NumberOfSmmReservedRegions; Index++) { SmramMap[Index].PhysicalStart = DescriptorBlock->Descriptor[Index].PhysicalStart; SmramMap[Index].CpuStart = DescriptorBlock->Descriptor[Index].CpuStart; SmramMap[Index].PhysicalSize = DescriptorBlock->Descriptor[Index].PhysicalSize; SmramMap[Index].RegionState = DescriptorBlock->Descriptor[Index].RegionState; } return EFI_SUCCESS; }