/** @file This is the Common driver that initializes the Intel System Agent. Copyright (c) 2019 Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "SaInit.h" #include #include #include // // Declare I/O Ports used to perform PCI Confguration Cycles // #define PCI_CONFIGURATION_ADDRESS_PORT 0xCF8 #define PCI_CONFIGURATION_DATA_PORT 0xCFC /** Convert a PCI Library address to PCI CF8 formatted address. Declare macro to convert PCI Library address to PCI CF8 formatted address. Bit fields of PCI Library and CF8 formatted address is as follows: PCI Library formatted address CF8 Formatted Address ============================= ====================== Bits 00..11 Register Bits 00..07 Register Bits 12..14 Function Bits 08..10 Function Bits 15..19 Device Bits 11..15 Device Bits 20..27 Bus Bits 16..23 Bus Bits 28..31 Reserved(MBZ) Bits 24..30 Reserved(MBZ) Bits 31..31 Must be 1 @param A The address to convert. @retval The coverted address. **/ #define PCI_TO_CF8_ADDRESS(A) \ ((UINT32) ((((A) >> 4) & 0x00ffff00) | ((A) & 0xfc) | 0x80000000)) /// /// Global Variables /// GLOBAL_REMOVE_IF_UNREFERENCED SA_CONFIG_HOB *mSaConfigHob; BOOLEAN mSkipPamLock = FALSE; /* Intel(R) Core Processor Skylake BWG version 0.4.0 18.6 System Agent Configuration Locking For reliable operation and security, System BIOS must set the following bits: 1. For all modern Intel processors, Intel strongly recommends that BIOS should set the D_LCK bit. Set B0:D0:F0.R088h [4] = 1b to lock down SMRAM space. BaseAddr values for mSaSecurityRegisters that uses PciExpressBaseAddress will be initialized at Runtime inside function SaPcieInitPolicy(). */ GLOBAL_REMOVE_IF_UNREFERENCED BOOT_SCRIPT_REGISTER_SETTING mSaSecurityRegisters[] = { {0, R_SA_SMRAMC, 0xFFFFFFFF, BIT4} }; /** SystemAgent Initialization Common Function. @retval EFI_SUCCESS - Always. **/ VOID SaInitEntryPoint ( VOID ) { /// /// Get SaConfigHob HOB /// mSaConfigHob = NULL; mSaConfigHob = (SA_CONFIG_HOB *) GetFirstGuidHob (&gSaConfigHobGuid); if (mSaConfigHob != NULL) { mSkipPamLock = mSaConfigHob->SkipPamLock; } return; } /** Common function locks the PAM register as part of the SA Security requirements. @retval EFI_SUCCESS - Always. **/ VOID SaPamLock ( VOID ) { UINT64 BaseAddress; UINT32 Data32Or; if (mSkipPamLock == FALSE) { // // Lock PAM by PAM Lock Bit // BaseAddress = PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, 0, 0, 0, 0); Data32Or = BIT0; DEBUG ((DEBUG_INFO, "PAM_LOCK!!\n")); PciSegmentOr32 (BaseAddress + R_SA_PAM0, Data32Or); } } /** This function does SA security lock **/ VOID SaSecurityLock ( VOID ) { UINT8 Index; UINT32 RegOffset; UINT32 Data32Or; UINT32 Data32; UINT8 Data8; /// /// 17.2 System Agent Security Lock configuration /// DEBUG ((DEBUG_INFO, "DXE SaSecurityLock\n")); for (Index = 0; Index < (sizeof (mSaSecurityRegisters) / sizeof (BOOT_SCRIPT_REGISTER_SETTING)); Index++) { RegOffset = mSaSecurityRegisters[Index].Offset; Data32Or = mSaSecurityRegisters[Index].OrMask; if (RegOffset == R_SA_SMRAMC) { /// /// SMRAMC LOCK must use CF8/CFC access /// PciCf8Or8 (PCI_CF8_LIB_ADDRESS (SA_MC_BUS, SA_MC_DEV, SA_MC_FUN, R_SA_SMRAMC), (UINT8) Data32Or); Data8 = PciCf8Read8 (PCI_CF8_LIB_ADDRESS (SA_MC_BUS, SA_MC_DEV, SA_MC_FUN, R_SA_SMRAMC)); Data32 = PCI_TO_CF8_ADDRESS (PCI_CF8_LIB_ADDRESS (SA_MC_BUS, SA_MC_DEV, SA_MC_FUN, R_SA_SMRAMC)); S3BootScriptSaveIoWrite ( S3BootScriptWidthUint32, (UINTN) (PCI_CONFIGURATION_ADDRESS_PORT), 1, &Data32 ); S3BootScriptSaveIoWrite ( S3BootScriptWidthUint8, (UINTN) (PCI_CONFIGURATION_DATA_PORT), 1, &Data8 ); } } } /** This function performs SA Security locking in EndOfDxe callback @retval EFI_SUCCESS - Security lock has done @retval EFI_UNSUPPORTED - Security lock not done successfully **/ EFI_STATUS SaSecurityInit ( VOID ) { UINT8 Index; for (Index = 0; Index < (sizeof (mSaSecurityRegisters) / sizeof (BOOT_SCRIPT_REGISTER_SETTING)); Index++) { if (mSaSecurityRegisters[Index].BaseAddr != PcdGet64 (PcdMchBaseAddress)) { mSaSecurityRegisters[Index].BaseAddr = PcdGet64 (PcdPciExpressBaseAddress); } } SaSecurityLock (); return EFI_SUCCESS; }