/** @file SPI library for abstraction of SPI HW registers accesses Copyright (c) 2021, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include #include #include #include #include #include #include #include #include /** Disable EISS (Enable InSMM.STS) **/ VOID SpiDisableEiss ( VOID ) { UINT64 SpiBaseAddress; SpiBaseAddress = SpiPciCfgBase (); ASSERT ((PciSegmentRead8 (SpiBaseAddress + R_SPI_CFG_BC) & B_SPI_CFG_BC_LE) == 0); PciSegmentAnd8 (SpiBaseAddress + R_SPI_CFG_BC, (UINT8) ~(B_SPI_CFG_BC_EISS)); } /** Configure BiosLockEnable bit and BiosInterfaceLock bit according to policy setting. @param[in] BiosLockEnable Policy for BiosLockEnable bit programming @param[in] BiosInterfaceLock Policy for BiosInterfaceLock bit programming **/ VOID SpiBiosLockEnableAndBiosInterfaceLockWithS3BootScript ( IN BOOLEAN BiosLockEnable, IN BOOLEAN BiosInterfaceLock ) { UINT64 SpiBaseAddress; UINT8 SpiData8; if (!BiosLockEnable && !BiosInterfaceLock) { return; } SpiBaseAddress = SpiPciCfgBase (); /// /// PCH BIOS Spec Flash Security Recommendation /// /// BIOS needs to enable the BIOS Lock Enable (BLE) feature of the PCH by setting /// SPI/eSPI/LPC PCI offset DCh[1] = 1b. /// When this bit is set, attempts to write the Write Protect Disable (WPD) bit /// in PCH will cause a SMI which will allow the BIOS to verify that the write is /// from a valid source. /// Remember that BIOS needs to set SPI/LPC/eSPI PCI Offset DC [0] = 0b to enable /// BIOS region protection before exiting the SMI handler. /// Also, TCO_EN bit needs to be set (SMI_EN Register, ABASE + 30h[13] = 1b) to keep /// BLE feature enabled after booting to the OS. /// Intel requires that BIOS enables the Lock Enable (LE) feature of the PCH to /// ensure SMM protection of flash. /// RC installs a default SMI handler that clears WPD. /// There could be additional SMI handler to log such attempt if desired. /// /// BIOS needs to enable the "Enable in SMM.STS" (EISS) feature of the PCH by setting /// SPI PCI offset DCh[5] = 1b for SPI or setting eSPI PCI offset DCh[5] = 1b for eSPI. /// When this bit is set, the BIOS region is not writable until SMM sets the InSMM.STS bit, /// to ensure BIOS can only be modified from SMM. Please refer to CPU BWG for more details /// on InSMM.STS bit. /// Intel requires that BIOS enables the Lock Enable (LE) feature of the PCH to ensure /// SMM protection of flash. /// SPI PCI offset DCh[1] = 1b for SPI or setting eSPI PCI offset DCh[1] = 1b for eSPI. /// When this bit is set, EISS is locked down. /// SpiData8 = 0; if (BiosLockEnable) { SpiData8 |= B_SPI_CFG_BC_EISS | B_SPI_CFG_BC_LE; } /// /// BIOS also needs to set the BIOS Interface Lock Down bit in multiple locations /// (PCR[DMI] + 274Ch[0], LPC/eSPI PCI offset DCh[7] and SPI PCI offset DCh[7]). /// (done in PchInit/Dxe/PchInit.c by PchDmiSetBiosLockDownWithS3BootScript ()) for PCR[DMI] 274Ch) /// Setting these bits will prevent writes to the Top Swap bit (under their respective locations) /// and the Boot BIOS Straps. Enabling this bit will mitigate malicious software /// attempts to replace the system BIOS option ROM with its own code. /// if (BiosInterfaceLock) { SpiData8 |= B_SPI_CFG_BC_BILD; } PciSegmentOr8 (SpiBaseAddress + R_SPI_CFG_BC, SpiData8); S3BootScriptSaveMemWrite ( S3BootScriptWidthUint8, PcdGet64 (PcdPciExpressBaseAddress) + SpiBaseAddress + R_SPI_CFG_BC, 1, (VOID *) (UINTN) (PcdGet64 (PcdPciExpressBaseAddress) + SpiBaseAddress + R_SPI_CFG_BC) ); // // Reads back for posted write to take effect // SpiData8 = PciSegmentRead8 (SpiBaseAddress + R_SPI_CFG_BC); S3BootScriptSaveMemPoll ( S3BootScriptWidthUint8, PcdGet64 (PcdPciExpressBaseAddress) + SpiBaseAddress + R_SPI_CFG_BC, &SpiData8, &SpiData8, 1, 1 ); } /** Clears BIOS Write Protect Disable bit **/ VOID SpiClearBiosWriteProtectDisable ( VOID ) { // // Disable BIOSWE bit to protect BIOS // PciSegmentAnd8 (SpiPciCfgBase () + R_SPI_CFG_BC, (UINT8) ~B_SPI_CFG_BC_WPD); }