Reviewed-by: Nate DeSimone <nathaniel.l.desim...@intel.com> > -----Original Message----- > From: Luo, Heng <heng....@intel.com> > Sent: Sunday, January 31, 2021 5:37 PM > To: devel@edk2.groups.io > Cc: Chaganty, Rangasai V <rangasai.v.chaga...@intel.com>; Desimone, > Nathaniel L <nathaniel.l.desim...@intel.com> > Subject: [PATCH 29/40] TigerlakeSiliconPkg/IpBlock: Add Spi component > > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171 > > Adds the following files: > * IpBlock/Spi/IncludePrivate > * IpBlock/Spi/Library > * IpBlock/Spi/LibraryPrivate > * IpBlock/Spi/Smm > > Cc: Sai Chaganty <rangasai.v.chaga...@intel.com> > Cc: Nate DeSimone <nathaniel.l.desim...@intel.com> > Signed-off-by: Heng Luo <heng....@intel.com> > --- > > Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Library/SpiAcces > sPrivateLib.h | 40 > ++++++++++++++++++++++++++++++++ > > Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Library/SpiCom > monLib.h | 364 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++ > > Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Register/SpiRegs > .h | 136 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++ > > Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Library/PeiDxeSmmSpiAccessLib > /PeiDxeSmmSpiAccessLib.inf | 33 > ++++++++++++++++++++++++++ > > Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Library/PeiDxeSmmSpiAccessLib > /SpiAccessLib.c | 477 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > +++++++++++++++++++++++ > > Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/BaseSpiCommon > Lib/BaseSpiCommonLib.inf | 31 > +++++++++++++++++++++++++ > > Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/BaseSpiCommon > Lib/SpiCommon.c | 1115 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > > Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/PeiDxeSmmSpiAc > cessPrivateLib/PeiDxeSmmSpiAccessPrivateLib.inf | 40 > ++++++++++++++++++++++++++++++++ > > Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/PeiDxeSmmSpiAc > cessPrivateLib/SpiAccessPrivateLib.c | 133 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++ > Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Smm/Spi.c > | 296 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Smm/SpiSmm.inf > | 47 +++++++++++++++++++++++++++++++++++++ > 11 files changed, 2712 insertions(+) > > diff --git > a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Library/SpiAcc > essPrivateLib.h > b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Library/SpiAcc > essPrivateLib.h > new file mode 100644 > index 0000000000..6da88a9047 > --- /dev/null > +++ > b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Library/SpiAcc > essPrivateLib.h > @@ -0,0 +1,40 @@ > +/** @file > > + SPI library header for abstraction of SPI HW registers accesses > > + > > + Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> > > + SPDX-License-Identifier: BSD-2-Clause-Patent > > +**/ > > + > > +#ifndef _SPI_ACCESS_PRIVATE_LIB_H_ > > +#define _SPI_ACCESS_PRIVATE_LIB_H_ > > + > > +/** > > + Disable EISS (Enable InSMM.STS) > > +**/ > > +VOID > > +SpiDisableEiss ( > > + VOID > > + ); > > + > > +/** > > + 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 > > + ); > > + > > +/** > > + Clears BIOS Write Protect Disable bit > > +**/ > > +VOID > > +SpiClearBiosWriteProtectDisable ( > > + VOID > > + ); > > + > > +#endif // _SPI_ACCESS_PRIVATE_LIB_H_ > > diff --git > a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Library/SpiCo > mmonLib.h > b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Library/SpiCo > mmonLib.h > new file mode 100644 > index 0000000000..3290f77122 > --- /dev/null > +++ > b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Library/SpiCo > mmonLib.h > @@ -0,0 +1,364 @@ > +/** @file > > + Header file for the PCH SPI Common Driver. > > + > > + Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> > > + SPDX-License-Identifier: BSD-2-Clause-Patent > > +**/ > > +#ifndef _SPI_COMMON_LIB_H_ > > +#define _SPI_COMMON_LIB_H_ > > + > > +#include <Protocol/Spi.h> > > + > > +// > > +// Maximum time allowed while waiting the SPI cycle to complete > > +// Wait Time = 6 seconds = 6000000 microseconds > > +// Wait Period = 10 microseconds > > +// > > +#define SPI_WAIT_TIME 6000000 ///< Wait Time = 6 seconds = 6000000 > microseconds > > +#define SPI_WAIT_PERIOD 10 ///< Wait Period = 10 microseconds > > + > > +/// > > +/// Flash cycle Type > > +/// > > +typedef enum { > > + FlashCycleRead, > > + FlashCycleWrite, > > + FlashCycleErase, > > + FlashCycleReadSfdp, > > + FlashCycleReadJedecId, > > + FlashCycleWriteStatus, > > + FlashCycleReadStatus, > > + FlashCycleMax > > +} FLASH_CYCLE_TYPE; > > + > > +/// > > +/// Flash Component Number > > +/// > > +typedef enum { > > + FlashComponent0, > > + FlashComponent1, > > + FlashComponentMax > > +} FLASH_COMPONENT_NUM; > > + > > +/// > > +/// Private data structure definitions for the driver > > +/// > > +#define PCH_SPI_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('P', 'S', 'P', > 'I') > > + > > +typedef struct { > > + UINT32 Signature; > > + EFI_HANDLE Handle; > > + PCH_SPI_PROTOCOL SpiProtocol; > > + UINT16 PchAcpiBase; > > + UINT64 PchSpiBase; > > + UINT8 ReadPermission; > > + UINT8 WritePermission; > > + UINT32 SfdpVscc0Value; > > + UINT32 SfdpVscc1Value; > > + UINT16 PchStrapBaseAddr; > > + UINT16 PchStrapSize; > > + UINT16 CpuStrapBaseAddr; > > + UINT16 CpuStrapSize; > > + UINT8 NumberOfComponents; > > + UINT32 Component1StartAddr; > > + UINT32 TotalFlashSize; > > +} SPI_INSTANCE; > > + > > +#define SPI_INSTANCE_FROM_SPIPROTOCOL(a) CR (a, SPI_INSTANCE, > SpiProtocol, PCH_SPI_PRIVATE_DATA_SIGNATURE) > > + > > +// > > +// Function prototypes used by the SPI protocol. > > +// > > + > > +/** > > + Initialize an SPI protocol instance. > > + > > + @param[in] SpiInstance Pointer to SpiInstance to initialize > > + > > + @retval EFI_SUCCESS The protocol instance was properly > initialized > > + @exception EFI_UNSUPPORTED The PCH is not supported by this > module > > +**/ > > +EFI_STATUS > > +SpiProtocolConstructor ( > > + IN SPI_INSTANCE *SpiInstance > > + ); > > + > > +/** > > + This function is a hook for Spi to disable BIOS Write Protect > > + > > + @retval EFI_SUCCESS The protocol instance was properly > initialized > > + @retval EFI_ACCESS_DENIED The BIOS Region can only be updated in > SMM phase > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DisableBiosWriteProtect ( > > + VOID > > + ); > > + > > +/** > > + This function is a hook for Spi to enable BIOS Write Protect > > + > > + > > +**/ > > +VOID > > +EFIAPI > > +EnableBiosWriteProtect ( > > + VOID > > + ); > > + > > +/** > > + Acquire pch spi mmio address. > > + > > + @param[in] SpiInstance Pointer to SpiInstance to initialize > > + > > + @retval PchSpiBar0 return SPI MMIO address > > +**/ > > +UINTN > > +AcquireSpiBar0 ( > > + IN SPI_INSTANCE *SpiInstance > > + ); > > + > > +/** > > + Release pch spi mmio address. > > + > > + @param[in] SpiInstance Pointer to SpiInstance to initialize > > + > > + @retval None > > +**/ > > +VOID > > +ReleaseSpiBar0 ( > > + IN SPI_INSTANCE *SpiInstance > > + ); > > + > > +/** > > + Check if it's granted to do flash write. > > + > > + @retval TRUE It's secure to do flash write. > > + @retval FALSE It's not secure to do flash write. > > +**/ > > +BOOLEAN > > +IsSpiFlashWriteGranted ( > > + VOID > > + ); > > + > > +/** > > + Read data from the flash part. > > + > > + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. > > + @param[in] FlashRegionType The Flash Region type for flash cycle which > is listed in the Descriptor. > > + @param[in] Address The Flash Linear Address must fall within a > region for which BIOS has access permissions. > > + @param[in] ByteCount Number of bytes in the data portion of the > SPI cycle. > > + @param[out] Buffer The Pointer to caller-allocated buffer > containing the dada received. > > + It is the caller's responsibility to make > sure Buffer is large > enough for the total number of bytes read. > > + > > + @retval EFI_SUCCESS Command succeed. > > + @retval EFI_INVALID_PARAMETER The parameters specified are not > valid. > > + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. > > +**/ > > +EFI_STATUS > > +EFIAPI > > +SpiProtocolFlashRead ( > > + IN PCH_SPI_PROTOCOL *This, > > + IN FLASH_REGION_TYPE FlashRegionType, > > + IN UINT32 Address, > > + IN UINT32 ByteCount, > > + OUT UINT8 *Buffer > > + ); > > + > > +/** > > + Write data to the flash part. > > + > > + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. > > + @param[in] FlashRegionType The Flash Region type for flash cycle which > is listed in the Descriptor. > > + @param[in] Address The Flash Linear Address must fall within a > region for which BIOS has access permissions. > > + @param[in] ByteCount Number of bytes in the data portion of the > SPI cycle. > > + @param[in] Buffer Pointer to caller-allocated buffer > containing the > data sent during the SPI cycle. > > + > > + @retval EFI_SUCCESS Command succeed. > > + @retval EFI_INVALID_PARAMETER The parameters specified are not > valid. > > + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. > > +**/ > > +EFI_STATUS > > +EFIAPI > > +SpiProtocolFlashWrite ( > > + IN PCH_SPI_PROTOCOL *This, > > + IN FLASH_REGION_TYPE FlashRegionType, > > + IN UINT32 Address, > > + IN UINT32 ByteCount, > > + IN UINT8 *Buffer > > + ); > > + > > +/** > > + Erase some area on the flash part. > > + > > + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. > > + @param[in] FlashRegionType The Flash Region type for flash cycle which > is listed in the Descriptor. > > + @param[in] Address The Flash Linear Address must fall within a > region for which BIOS has access permissions. > > + @param[in] ByteCount Number of bytes in the data portion of the > SPI cycle. > > + > > + @retval EFI_SUCCESS Command succeed. > > + @retval EFI_INVALID_PARAMETER The parameters specified are not > valid. > > + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. > > +**/ > > +EFI_STATUS > > +EFIAPI > > +SpiProtocolFlashErase ( > > + IN PCH_SPI_PROTOCOL *This, > > + IN FLASH_REGION_TYPE FlashRegionType, > > + IN UINT32 Address, > > + IN UINT32 ByteCount > > + ); > > + > > +/** > > + Read SFDP data from the flash part. > > + > > + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. > > + @param[in] ComponentNumber The Componen Number for chip select > > + @param[in] Address The starting byte address for SFDP data > read. > > + @param[in] ByteCount Number of bytes in SFDP data portion of the > SPI cycle > > + @param[out] SfdpData The Pointer to caller-allocated buffer > containing the SFDP data received > > + It is the caller's responsibility to make > sure Buffer is large > enough for the total number of bytes read > > + > > + @retval EFI_SUCCESS Command succeed. > > + @retval EFI_INVALID_PARAMETER The parameters specified are not > valid. > > + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. > > +**/ > > +EFI_STATUS > > +EFIAPI > > +SpiProtocolFlashReadSfdp ( > > + IN PCH_SPI_PROTOCOL *This, > > + IN UINT8 ComponentNumber, > > + IN UINT32 Address, > > + IN UINT32 ByteCount, > > + OUT UINT8 *SfdpData > > + ); > > + > > +/** > > + Read Jedec Id from the flash part. > > + > > + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. > > + @param[in] ComponentNumber The Componen Number for chip select > > + @param[in] ByteCount Number of bytes in JedecId data portion of > the SPI cycle, the data size is 3 typically > > + @param[out] JedecId The Pointer to caller-allocated buffer > containing JEDEC ID received > > + It is the caller's responsibility to make > sure Buffer is large > enough for the total number of bytes read. > > + > > + @retval EFI_SUCCESS Command succeed. > > + @retval EFI_INVALID_PARAMETER The parameters specified are not > valid. > > + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. > > +**/ > > +EFI_STATUS > > +EFIAPI > > +SpiProtocolFlashReadJedecId ( > > + IN PCH_SPI_PROTOCOL *This, > > + IN UINT8 ComponentNumber, > > + IN UINT32 ByteCount, > > + OUT UINT8 *JedecId > > + ); > > + > > +/** > > + Write the status register in the flash part. > > + > > + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. > > + @param[in] ByteCount Number of bytes in Status data portion of > the > SPI cycle, the data size is 1 typically > > + @param[in] StatusValue The Pointer to caller-allocated buffer > containing the value of Status register writing > > + > > + @retval EFI_SUCCESS Command succeed. > > + @retval EFI_INVALID_PARAMETER The parameters specified are not > valid. > > + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. > > +**/ > > +EFI_STATUS > > +EFIAPI > > +SpiProtocolFlashWriteStatus ( > > + IN PCH_SPI_PROTOCOL *This, > > + IN UINT32 ByteCount, > > + IN UINT8 *StatusValue > > + ); > > + > > +/** > > + Read status register in the flash part. > > + > > + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. > > + @param[in] ByteCount Number of bytes in Status data portion of > the > SPI cycle, the data size is 1 typically > > + @param[out] StatusValue The Pointer to caller-allocated buffer > containing the value of Status register received. > > + > > + @retval EFI_SUCCESS Command succeed. > > + @retval EFI_INVALID_PARAMETER The parameters specified are not > valid. > > + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. > > +**/ > > +EFI_STATUS > > +EFIAPI > > +SpiProtocolFlashReadStatus ( > > + IN PCH_SPI_PROTOCOL *This, > > + IN UINT32 ByteCount, > > + OUT UINT8 *StatusValue > > + ); > > + > > +/** > > + Get the SPI region base and size, based on the enum type > > + > > + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. > > + @param[in] FlashRegionType The Flash Region type for for the base > address which is listed in the Descriptor. > > + @param[out] BaseAddress The Flash Linear Address for the Region 'n' > Base > > + @param[out] RegionSize The size for the Region 'n' > > + > > + @retval EFI_SUCCESS Read success > > + @retval EFI_INVALID_PARAMETER Invalid region type given > > + @retval EFI_DEVICE_ERROR The region is not used > > +**/ > > +EFI_STATUS > > +EFIAPI > > +SpiProtocolGetRegionAddress ( > > + IN PCH_SPI_PROTOCOL *This, > > + IN FLASH_REGION_TYPE FlashRegionType, > > + OUT UINT32 *BaseAddress, > > + OUT UINT32 *RegionSize > > + ); > > + > > +/** > > + Read PCH Soft Strap Values > > + > > + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. > > + @param[in] SoftStrapAddr PCH Soft Strap address offset from FPSBA. > > + @param[in] ByteCount Number of bytes in SoftStrap data portion > of > the SPI cycle > > + @param[out] SoftStrapValue The Pointer to caller-allocated buffer > containing PCH Soft Strap Value. > > + If the value of ByteCount is 0, the data > type of > SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap > Length > > + It is the caller's responsibility to make > sure Buffer is large > enough for the total number of bytes read. > > + > > + @retval EFI_SUCCESS Command succeed. > > + @retval EFI_INVALID_PARAMETER The parameters specified are not > valid. > > + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. > > +**/ > > +EFI_STATUS > > +EFIAPI > > +SpiProtocolReadPchSoftStrap ( > > + IN PCH_SPI_PROTOCOL *This, > > + IN UINT32 SoftStrapAddr, > > + IN UINT32 ByteCount, > > + OUT VOID *SoftStrapValue > > + ); > > + > > +/** > > + Read CPU Soft Strap Values > > + > > + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. > > + @param[in] SoftStrapAddr CPU Soft Strap address offset from > FCPUSBA. > > + @param[in] ByteCount Number of bytes in SoftStrap data portion > of > the SPI cycle. > > + @param[out] SoftStrapValue The Pointer to caller-allocated buffer > containing CPU Soft Strap Value. > > + If the value of ByteCount is 0, the data > type of > SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap > Length > > + It is the caller's responsibility to make > sure Buffer is large > enough for the total number of bytes read. > > + > > + @retval EFI_SUCCESS Command succeed. > > + @retval EFI_INVALID_PARAMETER The parameters specified are not > valid. > > + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. > > +**/ > > +EFI_STATUS > > +EFIAPI > > +SpiProtocolReadCpuSoftStrap ( > > + IN PCH_SPI_PROTOCOL *This, > > + IN UINT32 SoftStrapAddr, > > + IN UINT32 ByteCount, > > + OUT VOID *SoftStrapValue > > + ); > > + > > +#endif > > diff --git > a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Register/SpiRe > gs.h > b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Register/SpiR > egs.h > new file mode 100644 > index 0000000000..8e2029500c > --- /dev/null > +++ > b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Register/SpiR > egs.h > @@ -0,0 +1,136 @@ > +/** @file > > + Register names for PCH SPI device. > > + > > + Conventions: > > + > > + - Register definition format: > > + > Prefix_[GenerationName]_[ComponentName]_SubsystemName_RegisterS > pace_RegisterName > > + - Prefix: > > + Definitions beginning with "R_" are registers > > + Definitions beginning with "B_" are bits within registers > > + Definitions beginning with "V_" are meaningful values within the bits > > + Definitions beginning with "S_" are register size > > + Definitions beginning with "N_" are the bit position > > + - [GenerationName]: > > + Three letter acronym of the generation is used (e.g. SKL,KBL,CNL etc.). > > + Register name without GenerationName applies to all generations. > > + - [ComponentName]: > > + This field indicates the component name that the register belongs to > (e.g. > PCH, SA etc.) > > + Register name without ComponentName applies to all components. > > + Register that is specific to -LP denoted by "_PCH_LP_" in component > name. > > + - SubsystemName: > > + This field indicates the subsystem name of the component that the > register belongs to > > + (e.g. PCIE, USB, SATA, GPIO, PMC etc.). > > + - RegisterSpace: > > + MEM - MMIO space register of subsystem. > > + IO - IO space register of subsystem. > > + PCR - Private configuration register of subsystem. > > + CFG - PCI configuration space register of subsystem. > > + - RegisterName: > > + Full register name. > > + > > + Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> > > + SPDX-License-Identifier: BSD-2-Clause-Patent > > +**/ > > +#ifndef _SPI_REGS_H_ > > +#define _SPI_REGS_H_ > > + > > +// > > +// SPI Registers > > +// > > +#define R_SPI_CFG_BAR0 0x10 > > +#define B_SPI_CFG_BAR0_MASK 0x0FFF > > + > > +#define R_SPI_CFG_BDE 0xD8 > > + > > +#define R_SPI_CFG_BC 0xDC > > +#define S_SPI_CFG_BC 4 > > +#define N_SPI_CFG_BC_ASE_BWP 11 > > +#define B_SPI_CFG_BC_ASE_BWP BIT11 > > +#define N_SPI_CFG_BC_ASYNC_SS 10 > > +#define B_SPI_CFG_BC_ASYNC_SS BIT10 > > +#define N_SPI_CFG_BC_SYNC_SS 8 > > +#define B_SPI_CFG_BC_SYNC_SS BIT8 > > +#define B_SPI_CFG_BC_BILD BIT7 > > +#define B_SPI_CFG_BC_BBS BIT6 ///< Boot BIOS > strap > > +#define N_SPI_CFG_BC_BBS 6 > > +#define V_SPI_CFG_BC_BBS_SPI 0 ///< Boot BIOS > strapped > to SPI > > +#define B_SPI_CFG_BC_EISS BIT5 ///< Enable > InSMM.STS > > +#define B_SPI_CFG_BC_TSS BIT4 > > +#define B_SPI_CFG_BC_SRC (BIT3 | BIT2) > > +#define N_SPI_CFG_BC_SRC 2 > > +#define V_SPI_CFG_BC_SRC_PREF_DIS_CACHE_DIS 0x01 ///< No > prefetching and no caching > > +#define B_SPI_CFG_BC_LE BIT1 ///< Lock Enable > > +#define N_SPI_CFG_BC_BLE 1 > > +#define B_SPI_CFG_BC_WPD BIT0 ///< Write > Protect Disable > > + > > +// > > +// BIOS Flash Program Registers (based on SPI_BAR0) > > +// > > +#define R_SPI_MEM_HSFSC 0x04 > ///< Hardware > Sequencing Flash Status and Control Register(32bits) > > +#define B_SPI_MEM_HSFSC_FDBC_MASK 0x3F000000 > ///< > Flash Data Byte Count ( <= 64), Count = (Value in this field) + 1. > > +#define N_SPI_MEM_HSFSC_FDBC 24 > > +#define B_SPI_MEM_HSFSC_CYCLE_MASK 0x001E0000 > ///< > Flash Cycle. > > +#define N_SPI_MEM_HSFSC_CYCLE 17 > > +#define V_SPI_MEM_HSFSC_CYCLE_READ 0 > ///< Flash > Cycle Read > > +#define V_SPI_MEM_HSFSC_CYCLE_WRITE 2 > ///< Flash > Cycle Write > > +#define V_SPI_MEM_HSFSC_CYCLE_4K_ERASE 3 > ///< Flash > Cycle 4K Block Erase > > +#define V_SPI_MEM_HSFSC_CYCLE_64K_ERASE 4 > ///< > Flash Cycle 64K Sector Erase > > +#define V_SPI_MEM_HSFSC_CYCLE_READ_SFDP 5 > ///< > Flash Cycle Read SFDP > > +#define V_SPI_MEM_HSFSC_CYCLE_READ_JEDEC_ID 6 > ///< > Flash Cycle Read JEDEC ID > > +#define V_SPI_MEM_HSFSC_CYCLE_WRITE_STATUS 7 > ///< > Flash Cycle Write Status > > +#define V_SPI_MEM_HSFSC_CYCLE_READ_STATUS 8 > ///< > Flash Cycle Read Status > > +#define B_SPI_MEM_HSFSC_CYCLE_FGO BIT16 > ///< Flash > Cycle Go. > > +#define B_SPI_MEM_HSFSC_FLOCKDN BIT15 > ///< Flash > Configuration Lock-Down > > +#define B_SPI_MEM_HSFSC_FDV BIT14 > ///< Flash > Descriptor Valid, once valid software can use hareware sequencing regs > > +#define B_SPI_MEM_HSFSC_FDOPSS BIT13 > ///< Flash > Descriptor Override Pin-Strap Status > > +#define B_SPI_MEM_HSFSC_WRSDIS BIT11 > ///< Write > Status Disable > > +#define B_SPI_MEM_HSFSC_SAF_MODE_ACTIVE BIT7 > ///< > Indicates flash is attached either directly to the PCH via the SPI bus or > EC/BMC > > +#define B_SPI_MEM_HSFSC_SCIP BIT5 > ///< SPI cycle in > progress > > +#define B_SPI_MEM_HSFSC_SAF_DLE BIT4 > ///< SAF Data > length error > > +#define B_SPI_MEM_HSFSC_SAF_ERROR BIT3 > ///< SAF > Error > > +#define B_SPI_MEM_HSFSC_AEL BIT2 > ///< Access Error > Log > > +#define B_SPI_MEM_HSFSC_FCERR BIT1 > ///< Flash > Cycle Error > > +#define B_SPI_MEM_HSFSC_FDONE BIT0 > ///< Flash > Cycle Done > > +#define R_SPI_MEM_FADDR 0x08 > ///< SPI Flash > Address > > +#define B_SPI_MEM_FADDR_MASK 0x07FFFFFF > ///< SPI > Flash Address Mask (0~26bit) > > +#define R_SPI_MEM_DLOCK 0x0C > ///< Discrete Lock > Bits > > +#define B_SPI_MEM_DLOCK_PR0LOCKDN BIT8 > ///< > PR0LOCKDN > > +#define R_SPI_MEM_FDATA00 0x10 > ///< SPI Data 00 > (32 bits) > > +#define R_SPI_MEM_FRAP 0x50 > ///< Flash Region > Access Permissions Register > > +#define B_SPI_MEM_FRAP_BRWA_MASK 0x0000FF00 > ///< > BIOS Region Write Access MASK, Region0~7 - 0: Flash Descriptor; 1: BIOS; 2: > ME; 3: GbE; 4: PlatformData > > +#define N_SPI_MEM_FRAP_BRWA 8 > ///< BIOS > Region Write Access bit position > > +#define B_SPI_MEM_FRAP_BRRA_MASK 0x000000FF > ///< > BIOS Region Read Access MASK, Region0~7 - 0: Flash Descriptor; 1: BIOS; 2: > ME; 3: GbE; 4: PlatformData > > +#define B_SPI_MEM_FRAP_BMRAG_MASK 0x00FF0000 > ///< > BIOS Master Read Access Grant > > +#define B_SPI_MEM_FRAP_BMWAG_MASK 0xFF000000 > ///< > BIOS Master Write Access Grant > > +#define R_SPI_MEM_FREG0_FLASHD 0x54 > ///< Flash > Region 0(Flash Descriptor)(32bits) > > +#define R_SPI_MEM_FREG3_GBE 0x60 > ///< Flash > Region 3(GbE)(32bits) > > +#define S_SPI_MEM_FREGX 4 > ///< Size of Flash > Region register > > +#define B_SPI_MEM_FREGX_LIMIT_MASK 0x7FFF0000 > ///< > Flash Region Limit [30:16] represents [26:12], [11:0] are assumed to be FFFh > > +#define N_SPI_MEM_FREGX_LIMIT 16 > ///< Region limit > bit position > > +#define N_SPI_MEM_FREGX_LIMIT_REPR 12 > ///< Region > limit bit represents position > > +#define B_SPI_MEM_FREGX_BASE_MASK 0x00007FFF > ///< > Flash Region Base, [14:0] represents [26:12] > > +#define N_SPI_MEM_FREGX_BASE 0 > ///< Region base > bit position > > +#define N_SPI_MEM_FREGX_BASE_REPR 12 > ///< Region > base bit represents position > > +#define R_SPI_MEM_PR0 0x84 > ///< Protected > Region 0 Register > > +#define S_SPI_MEM_PRX 4 > ///< Protected Region > X Register size > > +#define B_SPI_MEM_PRX_WPE BIT31 > ///< Write > Protection Enable > > +#define B_SPI_MEM_PRX_PRL_MASK 0x7FFF0000 > ///< > Protected Range Limit Mask, [30:16] here represents upper limit of address > [26:12] > > +#define N_SPI_MEM_PRX_PRL 16 > ///< Protected > Range Limit bit position > > +#define B_SPI_MEM_PRX_RPE BIT15 > ///< Read > Protection Enable > > +#define B_SPI_MEM_PRX_PRB_MASK 0x00007FFF > ///< > Protected Range Base Mask, [14:0] here represents base limit of address > [26:12] > > +#define N_SPI_MEM_PRX_PRB 0 > ///< Protected > Range Base bit position > > +#define R_SPI_MEM_FDOC 0xB4 > ///< Flash > Descriptor Observability Control Register(32 bits) > > +#define B_SPI_MEM_FDOC_FDSS_MASK (BIT14 | BIT13 | BIT12) > ///< Flash Descritor Section Select > > +#define V_SPI_MEM_FDOC_FDSS_FSDM 0x0000 > ///< Flash > Signature and Descriptor Map > > +#define V_SPI_MEM_FDOC_FDSS_COMP 0x1000 > ///< > Component > > +#define V_SPI_MEM_FDOC_FDSS_MSTR 0x3000 > ///< > Master > > +#define B_SPI_MEM_FDOC_FDSI_MASK 0x0FFC > ///< Flash > Descriptor Section Index > > +#define R_SPI_MEM_FDOD 0xB8 > ///< Flash > Descriptor Observability Data Register(32 bits) > > +#define R_SPI_MEM_SFDP0_VSCC0 0xC4 > ///< Vendor > Specific Component Capabilities Register(32 bits) > > +#define B_SPI_MEM_SFDPX_VSCCX_CPPTV BIT31 > ///< > Component Property Parameter Table Valid > > +#define B_SPI_MEM_SFDP0_VSCC0_VCL BIT30 > ///< > Vendor Component Lock > > +#define B_SPI_MEM_SFDPX_VSCCX_EO_64K BIT29 > ///< 64k > Erase valid (EO_64k_valid) > > +#define R_SPI_MEM_SFDP1_VSCC1 0xC8 > ///< Vendor > Specific Component Capabilities Register(32 bits) > > + > > +#endif > > diff --git > a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Library/PeiDxeSmmSpiAccess > Lib/PeiDxeSmmSpiAccessLib.inf > b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Library/PeiDxeSmmSpiAccess > Lib/PeiDxeSmmSpiAccessLib.inf > new file mode 100644 > index 0000000000..bba0b1fef3 > --- /dev/null > +++ > b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Library/PeiDxeSmmSpiAccess > Lib/PeiDxeSmmSpiAccessLib.inf > @@ -0,0 +1,33 @@ > +## @file > > +# Component description file for PCH SPI access library > > +# > > +# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> > > +# SPDX-License-Identifier: BSD-2-Clause-Patent > > +# > > +## > > + > > + > > +[Defines] > > +INF_VERSION = 0x00010017 > > +BASE_NAME = PeiDxeSmmSpiAccessLib > > +FILE_GUID = A6D4C05A-F6CB-46D5-4BA1-8C47B139DCA6 > > +VERSION_STRING = 1.0 > > +MODULE_TYPE = BASE > > +LIBRARY_CLASS = SpiAccessLib > > + > > + > > +[LibraryClasses] > > +BaseLib > > +IoLib > > +DebugLib > > +PciSegmentLib > > +PchPciBdfLib > > +PchPcrLib > > + > > +[Packages] > > +MdePkg/MdePkg.dec > > +TigerlakeSiliconPkg/SiPkg.dec > > + > > + > > +[Sources] > > +SpiAccessLib.c > > diff --git > a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Library/PeiDxeSmmSpiAccess > Lib/SpiAccessLib.c > b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Library/PeiDxeSmmSpiAccess > Lib/SpiAccessLib.c > new file mode 100644 > index 0000000000..c91b9aaf4d > --- /dev/null > +++ > b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Library/PeiDxeSmmSpiAccess > Lib/SpiAccessLib.c > @@ -0,0 +1,477 @@ > +/** @file > > + SPI library for abstraction of SPI HW registers accesses > > + > > + Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> > > + SPDX-License-Identifier: BSD-2-Clause-Patent > > +**/ > > + > > +#include <Base.h> > > +#include <Uefi/UefiBaseType.h> > > +#include <IndustryStandard/Pci22.h> > > +#include <Library/BaseLib.h> > > +#include <Library/IoLib.h> > > +#include <Library/DebugLib.h> > > +#include <Library/PciSegmentLib.h> > > +#include <Library/SpiAccessLib.h> > > +#include <Library/PchPciBdfLib.h> > > +#include <Library/PchPcrLib.h> > > +#include <Register/SpiRegs.h> > > +#include <Register/FlashRegs.h> > > +#include <Register/PchRegs.h> > > +#include <Register/PchPcrRegs.h> > > +#include <Register/PchDmiRegs.h> > > + > > +/** > > + Checks if PCH SPI Controler is present and available > > + > > + @retval TRUE PCH SPI controller is avaialable > > + @retval FALSE PCH SPI controller is not available > > +**/ > > +BOOLEAN > > +SpiIsControllerAvailable ( > > + VOID > > + ) > > +{ > > + // > > + // Checks for SPI controller > > + // > > + return (PciSegmentRead16 (SpiPciCfgBase () + PCI_VENDOR_ID_OFFSET) > != 0xFFFF); > > +} > > + > > +/** > > + Returns PCH SPI BAR0 value > > + > > + @retval UINT32 PCH SPI BAR0 value > > +**/ > > +UINT32 > > +SpiGetBar0 ( > > + VOID > > + ) > > +{ > > + UINT32 SpiBar0; > > + > > + ASSERT (SpiIsControllerAvailable ()); > > + SpiBar0 = PciSegmentRead32 (SpiPciCfgBase () + R_SPI_CFG_BAR0) & > ~B_SPI_CFG_BAR0_MASK; > > + ASSERT (SpiBar0 != 0); > > + > > + return SpiBar0; > > +} > > + > > +/** > > + Reads given descriptor section and returns value > > + > > + @param[in] UINT16 Descriptor section > > + @param[in] UINT16 Offset > > + > > + @retval UINT32 Read value from a section under given offset > > +**/ > > +STATIC > > +UINT32 > > +SpiReadDescriptor ( > > + IN UINT16 DescriptorSection, > > + IN UINT16 Offset > > + ) > > +{ > > + UINT32 SpiBar0; > > + SpiBar0 = SpiGetBar0 (); > > + > > + MmioWrite32 (SpiBar0 + R_SPI_MEM_FDOC, (DescriptorSection | Offset)); > > + return MmioRead32 (SpiBar0 + R_SPI_MEM_FDOD); > > +} > > + > > +/** > > + Returns descriptor signature > > + > > + @retval UINT32 Descriptor signature > > +**/ > > +UINT32 > > +SpiGetDescriptorSignature ( > > + VOID > > + ) > > +{ > > + // > > + // Read Descriptor offset 0x10 - To get Descriptor Signature > > + // Signature section 0x0000 + offset 0x0 which points to Descriptor offset > 0x10 > > + // > > + return SpiReadDescriptor (V_SPI_MEM_FDOC_FDSS_FSDM, 0x0); > > +} > > + > > +/** > > + Returns supported features and R/W frequencies of Flash Component > > + > > + @retval UINT32 Flash Component features descriptor > > +**/ > > +UINT32 > > +SpiGetFlashComponentDescription ( > > + VOID > > + ) > > +{ > > + // > > + // Read Descriptor offset 0x30 - To get supported features and R/W > frequencies > > + // Component section 0x1000 + offset 0x0 which points to Descriptor > offset 0x30 > > + // > > + return SpiReadDescriptor (V_SPI_MEM_FDOC_FDSS_COMP, 0x0); > > +} > > + > > +/** > > + Returns number of Flash Components > > + > > + @retval UINT32 Flash components number > > +**/ > > +UINT32 > > +SpiGetFlashComponentsNumber ( > > + VOID > > + ) > > +{ > > + // > > + // Read Descriptor offset 0x14 - To get number of components > > + // Signature section 0x0000 + offset 0x4 which points to Descriptor offset > 0x14 > > + // > > + return ((SpiReadDescriptor (V_SPI_MEM_FDOC_FDSS_FSDM, > R_FLASH_FDBAR_FLASH_MAP0) & B_FLASH_FDBAR_NC) >> > N_FLASH_FDBAR_NC); > > +} > > + > > +/** > > + Returns total Flash size with regards to number of flash components > > + > > + @retval UINT32 Total Flash Memory size > > +**/ > > +UINT32 > > +SpiGetTotalFlashSize ( > > + VOID > > + ) > > +{ > > + UINT32 Data32; > > + UINT32 ComponentsNumber; > > + UINT32 TotalFlashSize; > > + > > + Data32 = SpiGetFlashComponentDescription (); > > + ComponentsNumber = SpiGetFlashComponentsNumber (); > > + > > + TotalFlashSize = (V_FLASH_FLCOMP_COMP_512KB << ((UINT8) (Data32 & > B_FLASH_FLCOMP_COMP0_MASK))); > > + if (ComponentsNumber == 1) { > > + TotalFlashSize += (V_FLASH_FLCOMP_COMP_512KB << ((UINT8) ((Data32 > & B_FLASH_FLCOMP_COMP1_MASK) >> 4))); > > + } > > + > > + return TotalFlashSize; > > +} > > + > > +/** > > + Checks BIOS lock bits for proper value and checks if write protection is > enabled > > + Expected vales are: LE bit set, EISS bit set and WPD bit cleared > > + > > + @retval TRUE All protection bits are set correctly > > + @retval FALSE Not all protection bits had exepcted values > > +**/ > > +BOOLEAN > > +SpiIsWriteProtectionEnabled ( > > + VOID > > + ) > > +{ > > + UINT32 BiosControl; > > + BiosControl = PciSegmentRead32 (SpiPciCfgBase () + R_SPI_CFG_BC); > > + > > + DEBUG ((DEBUG_INFO, "SPI BIOS CONTROL LE: %x\n", (BiosControl & > B_SPI_CFG_BC_LE) != 0 )); > > + DEBUG ((DEBUG_INFO, "SPI BIOS CONTROL WPD: %x\n", (BiosControl & > B_SPI_CFG_BC_WPD) != 0 )); > > + DEBUG ((DEBUG_INFO, "SPI BIOS CONTROL EISS: %x\n", (BiosControl & > B_SPI_CFG_BC_EISS) != 0 )); > > + > > + return (((BiosControl & B_SPI_CFG_BC_LE) != 0) && > > + ((BiosControl & B_SPI_CFG_BC_WPD) == 0) && > > + ((BiosControl & B_SPI_CFG_BC_EISS) != 0)); > > +} > > + > > +/** > > + Returns status of BIOS Interface Lockdown > > + > > + @retval TRUE BIOS Interface Lockdown is enabled > > + @retval FALSE BIOS Interface Lockdown is disabled > > +**/ > > +BOOLEAN > > +SpiIsBiosInterfaceLockdownEnabled ( > > + VOID > > + ) > > +{ > > + return !!(PciSegmentRead32 (SpiPciCfgBase () + R_SPI_CFG_BC) & > B_SPI_CFG_BC_BILD); > > +} > > + > > +/** > > + Returns Flash Descriptor Override Pin Strap status > > + > > + @retval TRUE Flash Descriptor override is enabled > > + @retval FALSE Flash Descriptor override is disabled > > +**/ > > +BOOLEAN > > +SpiIsFlashDescriptorOverrideEnabled ( > > + VOID > > + ) > > +{ > > + UINT32 SpiBar0; > > + SpiBar0 = SpiGetBar0 (); > > + > > + return !!(MmioRead16 (SpiBar0 + R_SPI_MEM_HSFSC) & > B_SPI_MEM_HSFSC_FDOPSS); > > +} > > + > > +/** > > + Returns Flash Configuration Lock Down bit status > > + > > + @retval TRUE Flash Configuration Lock Down bit is set > > + @retval FALSE Flash Configuration Lock Down bit is not set > > +**/ > > +BOOLEAN > > +SpiIsFlashConfigurationLockDownEnabled ( > > + VOID > > + ) > > +{ > > + UINT32 SpiBar0; > > + SpiBar0 = SpiGetBar0 (); > > + > > + return !!(MmioRead16 (SpiBar0 + R_SPI_MEM_HSFSC) & > B_SPI_MEM_HSFSC_FLOCKDN); > > +} > > + > > +/** > > + Returns Top Swap functionality enable state > > + > > + @retval TRUE Top Swap is enabled > > + @retval FALSE Top Swap is disabled > > +**/ > > +BOOLEAN > > +SpiIsTopSwapEnabled ( > > + VOID > > + ) > > +{ > > + return !!(PciSegmentRead32 (SpiPciCfgBase () + R_SPI_CFG_BC) & > B_SPI_CFG_BC_TSS); > > +} > > + > > +/** > > + Return Component Property Parameter Table for a given component > number > > + > > + @param[in] ComponentNumber SPI Component number > > + @param[out] CppTable Component Poperty Parameter Table value > > + > > + @retval TRUE Vendor Specific Component Capabilities Register value was > read > > + @reval FALSE Vendor Specific Component Capabilities Register value was > not present > > +**/ > > +BOOLEAN > > +SpiGetComponentPropertyParameterTable ( > > + IN UINT8 ComponentNumber, > > + OUT UINT32 *CppTable > > + ) > > +{ > > + UINT32 SpiBar0; > > + UINT32 Data32; > > + SpiBar0 = SpiGetBar0 (); > > + > > + // > > + // More than 2 components not supported > > + // > > + switch (ComponentNumber) { > > + case 0: > > + *CppTable = MmioRead32 (SpiBar0 + R_SPI_MEM_SFDP0_VSCC0); > > + return TRUE; > > + case 1: > > + Data32 = SpiReadDescriptor (V_SPI_MEM_FDOC_FDSS_FSDM, > R_FLASH_FDBAR_FLASH_MAP0); > > + *CppTable = MmioRead32 (SpiBar0 + R_SPI_MEM_SFDP1_VSCC1); > > + return !!(Data32 & BIT8); > > + default: > > + return FALSE; > > + } > > +} > > + > > +/** > > + Returns valid bit status in given Component Property Parameter Table > > + > > + @param[in] CppTable Component Poperty Parameter Table value > > + > > + @retval TRUE Valid bit is set > > + @reval FALSE Valid bit is not set > > +**/ > > +BOOLEAN > > +SpiIsCppValidBitSet ( > > + IN UINT32 CppTable > > + ) > > +{ > > + return !!(CppTable & B_SPI_MEM_SFDPX_VSCCX_CPPTV); > > +} > > + > > +/** > > + Checks if Flash Descriptor is valid > > + > > + @retval TRUE Flash Descriptor is valid > > + @retval FALSE Flash Descriptor is invalid > > +**/ > > +BOOLEAN > > +SpiIsFlashDescriptorValid ( > > + VOID > > + ) > > +{ > > + UINT32 SpiBar0; > > + SpiBar0 = SpiGetBar0 (); > > + > > + return !!(MmioRead32 (SpiBar0 + R_SPI_MEM_HSFSC) & > B_SPI_MEM_HSFSC_FDV); > > +} > > + > > +/** > > + Reads and returns value from Flash Region Access Permissions Register > (FRAP) > > + > > + @retval UINT32 Flash Region Access Permissions Register value > > +**/ > > +STATIC > > +UINT32 > > +SpiGetFlashRegionAccessPermissions ( > > + VOID > > + ) > > +{ > > + return MmioRead32 (SpiGetBar0 () + R_SPI_MEM_FRAP); > > +} > > + > > +/** > > + Returns masked BIOS Master Read Access > > + > > + @retval UINT32 Already masked BIOS Master Read Access > > +**/ > > +UINT32 > > +SpiGetMasterReadAccess ( > > + VOID > > + ) > > +{ > > + UINT32 Data32; > > + Data32 = SpiGetFlashRegionAccessPermissions () & > B_SPI_MEM_FRAP_BMRAG_MASK; > > + DEBUG ((DEBUG_INFO, "BMRAG 0x%x\n", Data32)); > > + > > + return Data32; > > +} > > + > > +/** > > + Returns masked BIOS Master Write Access > > + > > + @retval UINT32 Already masked BIOS Master Write Access > > +**/ > > +UINT32 > > +SpiGetMasterWriteAccess ( > > + VOID > > + ) > > +{ > > + UINT32 Data32; > > + Data32 = SpiGetFlashRegionAccessPermissions () & > B_SPI_MEM_FRAP_BMWAG_MASK; > > + DEBUG ((DEBUG_INFO, "BMWAG 0x%x\n", Data32)); > > + > > + return Data32; > > +} > > + > > +/** > > + Returns GbE Region Access rights > > + > > + @retval UINT32 GbE Region access rights > > +**/ > > +UINT32 > > +SpiGetGbeRegionAccess ( > > + VOID > > + ) > > +{ > > + UINT32 Data32; > > + > > + Data32 = SpiReadDescriptor (V_SPI_MEM_FDOC_FDSS_MSTR, 0x8); > > + DEBUG ((DEBUG_INFO, "GbE Region Access 0x%x\n", Data32)); > > + > > + return Data32; > > +} > > + > > +/** > > + Returns CSME region access rights > > + > > + @retval UINT32 CSME Region Access rights > > +**/ > > +UINT32 > > +SpiGetCsmeRegionAccess ( > > + VOID > > + ) > > +{ > > + UINT32 Data32; > > + > > + Data32 = SpiReadDescriptor (V_SPI_MEM_FDOC_FDSS_MSTR, 0x4); > > + DEBUG ((DEBUG_INFO, "CSME Region Access 0x%x\n", Data32)); > > + > > + return Data32; > > +} > > + > > +/** > > + Returns EC region access right > > + > > + @retval UINT32 EC Region access rights > > +**/ > > +UINT32 > > +SpiGetEcRegionAccess ( > > + VOID > > + ) > > +{ > > + UINT32 Data32; > > + > > + Data32 = SpiReadDescriptor (V_SPI_MEM_FDOC_FDSS_MSTR, 0x10); > > + DEBUG ((DEBUG_INFO, "EC Region Access 0x%x\n", Data32)); > > + > > + return Data32; > > +} > > + > > +/** > > + Checks if Slave Attached Flash (SAF) mode is active > > + > > + @retval TRUE SAF mode is active > > + @retval FALSE SAF mode is not active > > +**/ > > +BOOLEAN > > +SpiIsSafModeActive ( > > + VOID > > + ) > > +{ > > + UINT32 SpiBar0; > > + SpiBar0 = SpiGetBar0 (); > > + > > + return !!(MmioRead32 (SpiBar0 + R_SPI_MEM_HSFSC) & > B_SPI_MEM_HSFSC_SAF_MODE_ACTIVE); > > +} > > + > > +/** > > + Checks validity of GbE region > > + > > + @retval TRUE GbE region is valid > > + @retval FALSE GbE regios in invalid > > +**/ > > +BOOLEAN > > +SpiIsGbeRegionValid ( > > + VOID > > + ) > > +{ > > + UINT32 SpiBar0; > > + SpiBar0 = SpiGetBar0 (); > > + > > + if (MmioRead32 (SpiBar0 + R_SPI_MEM_FREG3_GBE) != > B_SPI_MEM_FREGX_BASE_MASK) { > > + return TRUE; > > + } > > + return FALSE; > > +} > > + > > +/** > > + Returns TRUE if BIOS Boot Strap is set to SPI > > + > > + @retval TRUE BIOS Boot strap is set to SPI > > + @retval FALSE BIOS Boot strap is set to LPC/eSPI > > +**/ > > +BOOLEAN > > +SpiIsBiosBootFromSpi ( > > + VOID > > + ) > > +{ > > + return !!(((PciSegmentRead8 (SpiPciCfgBase () + R_SPI_CFG_BC) & > B_SPI_CFG_BC_BBS) >> N_SPI_CFG_BC_BBS) == V_SPI_CFG_BC_BBS_SPI); > > +} > > + > > +/** > > + Check SPI write status disable is set > > + > > + @retval TRUE Write status disable is set > > + @retval FALSE Write status disable is not set > > +**/ > > +BOOLEAN > > +SpiIsWriteStatusDisable ( > > + VOID > > + ) > > +{ > > + return !!(MmioRead32 (SpiGetBar0 () + R_SPI_MEM_HSFSC) & > B_SPI_MEM_HSFSC_WRSDIS); > > +} > > diff --git > a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/BaseSpiComm > onLib/BaseSpiCommonLib.inf > b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/BaseSpiComm > onLib/BaseSpiCommonLib.inf > new file mode 100644 > index 0000000000..a1a5467745 > --- /dev/null > +++ > b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/BaseSpiComm > onLib/BaseSpiCommonLib.inf > @@ -0,0 +1,31 @@ > +## @file > > +# Component description file for the PchSpiCommonLib > > +# > > +# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> > > +# SPDX-License-Identifier: BSD-2-Clause-Patent > > +# > > +## > > + > > +[Defines] > > + INF_VERSION = 0x00010005 > > + BASE_NAME = BaseSpiCommonLib > > + FILE_GUID = A37CB67E-7D85-45B3-B07E-BF65BDB603E8 > > + MODULE_TYPE = BASE > > + VERSION_STRING = 1.0 > > + LIBRARY_CLASS = SpiCommonLib > > + > > +[Sources] > > + SpiCommon.c > > + > > +[Packages] > > + MdePkg/MdePkg.dec > > + TigerlakeSiliconPkg/SiPkg.dec > > + > > +[LibraryClasses] > > + IoLib > > + DebugLib > > + PmcLib > > + PchPciBdfLib > > + SpiAccessLib > > + > > +[Pcd] > > diff --git > a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/BaseSpiComm > onLib/SpiCommon.c > b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/BaseSpiComm > onLib/SpiCommon.c > new file mode 100644 > index 0000000000..954b349e7c > --- /dev/null > +++ > b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/BaseSpiComm > onLib/SpiCommon.c > @@ -0,0 +1,1115 @@ > +/** @file > > + PCH SPI Common Driver implements the SPI Host Controller Compatibility > Interface. > > + > > + Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> > > + SPDX-License-Identifier: BSD-2-Clause-Patent > > +**/ > > +#include <Uefi/UefiBaseType.h> > > +#include <Library/BaseLib.h> > > +#include <Library/IoLib.h> > > +#include <Library/DebugLib.h> > > +#include <Library/BaseMemoryLib.h> > > +#include <IndustryStandard/Pci30.h> > > +#include <Library/PmcLib.h> > > +#include <Library/PciSegmentLib.h> > > +#include <Protocol/Spi.h> > > +#include <Library/SpiCommonLib.h> > > +#include <Register/PchRegs.h> > > +#include <Register/SpiRegs.h> > > +#include <Register/FlashRegs.h> > > +#include <Register/PmcRegs.h> > > +#include <Library/PchPciBdfLib.h> > > +#include <Library/SpiAccessLib.h> > > + > > +/** > > + Initialize an SPI protocol instance. > > + > > + @param[in] SpiInstance Pointer to SpiInstance to initialize > > + > > + @retval EFI_SUCCESS The protocol instance was properly > initialized > > + @exception EFI_UNSUPPORTED The PCH is not supported by this > module > > +**/ > > +EFI_STATUS > > +SpiProtocolConstructor ( > > + IN SPI_INSTANCE *SpiInstance > > + ) > > +{ > > + UINTN PchSpiBar0; > > + UINT32 Data32; > > + UINT16 Mdtba; > > + EFI_STATUS Status; > > + > > + // > > + // Initialize the SPI protocol instance > > + // > > + SpiInstance->Signature = PCH_SPI_PRIVATE_DATA_SIGNATURE; > > + SpiInstance->Handle = NULL; > > + SpiInstance->SpiProtocol.Revision = PCH_SPI_SERVICES_REVISION; > > + SpiInstance->SpiProtocol.FlashRead = SpiProtocolFlashRead; > > + SpiInstance->SpiProtocol.FlashWrite = SpiProtocolFlashWrite; > > + SpiInstance->SpiProtocol.FlashErase = SpiProtocolFlashErase; > > + SpiInstance->SpiProtocol.FlashReadSfdp = SpiProtocolFlashReadSfdp; > > + SpiInstance->SpiProtocol.FlashReadJedecId = > SpiProtocolFlashReadJedecId; > > + SpiInstance->SpiProtocol.FlashWriteStatus = SpiProtocolFlashWriteStatus; > > + SpiInstance->SpiProtocol.FlashReadStatus = SpiProtocolFlashReadStatus; > > + SpiInstance->SpiProtocol.GetRegionAddress = > SpiProtocolGetRegionAddress; > > + SpiInstance->SpiProtocol.ReadPchSoftStrap = > SpiProtocolReadPchSoftStrap; > > + SpiInstance->SpiProtocol.ReadCpuSoftStrap = > SpiProtocolReadCpuSoftStrap; > > + > > + SpiInstance->PchSpiBase = SpiPciCfgBase (); > > + > > + SpiInstance->PchAcpiBase = PmcGetAcpiBase (); > > + ASSERT (SpiInstance->PchAcpiBase != 0); > > + > > + PchSpiBar0 = PciSegmentRead32 (SpiInstance->PchSpiBase + > R_SPI_CFG_BAR0) & ~(B_SPI_CFG_BAR0_MASK); > > + if (PchSpiBar0 == 0) { > > + DEBUG ((DEBUG_ERROR, "ERROR : PchSpiBar0 is invalid!\n")); > > + ASSERT (FALSE); > > + } > > + > > + if ((MmioRead32 (PchSpiBar0 + R_SPI_MEM_HSFSC) & > B_SPI_MEM_HSFSC_FDV) == 0) { > > + DEBUG ((DEBUG_ERROR, "ERROR : SPI Flash Signature invalid, cannot use > the Hardware Sequencing registers!\n")); > > + ASSERT (FALSE); > > + } > > + > > + // > > + // Get Region 0 - 7 read Permission bits, region 8 and above are not > permitted. > > + // > > + SpiInstance->ReadPermission = MmioRead8 (PchSpiBar0 + > R_SPI_MEM_FRAP) & B_SPI_MEM_FRAP_BRRA_MASK; > > + DEBUG ((DEBUG_INFO, "Flash Region read Permission : %0x\n", > SpiInstance->ReadPermission)); > > + // > > + // Get Region 0 - 7 write Permission bits, region 8 and above are not > permitted. > > + // > > + SpiInstance->WritePermission = (UINT8) ((MmioRead16 (PchSpiBar0 + > R_SPI_MEM_FRAP) & > > + B_SPI_MEM_FRAP_BRWA_MASK) >> > N_SPI_MEM_FRAP_BRWA); > > + DEBUG ((DEBUG_INFO, "Flash Region write Permission : %0x\n", > SpiInstance->WritePermission)); > > + > > + SpiInstance->SfdpVscc0Value = MmioRead32 (PchSpiBar0 + > R_SPI_MEM_SFDP0_VSCC0); > > + DEBUG ((DEBUG_INFO, "Component 0 SFDP VSCC value : %0x\n", > SpiInstance->SfdpVscc0Value)); > > + SpiInstance->SfdpVscc1Value = MmioRead32 (PchSpiBar0 + > R_SPI_MEM_SFDP1_VSCC1); > > + DEBUG ((DEBUG_INFO, "Component 1 SFDP VSCC value : %0x\n", > SpiInstance->SfdpVscc1Value)); > > + > > + // > > + // Select to Flash Map 0 Register to get the number of flash Component > > + // > > + MmioAndThenOr32 ( > > + PchSpiBar0 + R_SPI_MEM_FDOC, > > + (UINT32) (~(B_SPI_MEM_FDOC_FDSS_MASK | > B_SPI_MEM_FDOC_FDSI_MASK)), > > + (UINT32) (V_SPI_MEM_FDOC_FDSS_FSDM | > R_FLASH_FDBAR_FLASH_MAP0) > > + ); > > + > > + // > > + // Copy Zero based Number Of Components > > + // > > + SpiInstance->NumberOfComponents = (UINT8) ((MmioRead16 > (PchSpiBar0 + R_SPI_MEM_FDOD) & B_FLASH_FDBAR_NC) >> > N_FLASH_FDBAR_NC); > > + DEBUG ((DEBUG_INFO, "Component Number : %0x\n", SpiInstance- > >NumberOfComponents + 1)); > > + > > + MmioAndThenOr32 ( > > + PchSpiBar0 + R_SPI_MEM_FDOC, > > + (UINT32) (~(B_SPI_MEM_FDOC_FDSS_MASK | > B_SPI_MEM_FDOC_FDSI_MASK)), > > + (UINT32) (V_SPI_MEM_FDOC_FDSS_COMP | R_FLASH_FCBA_FLCOMP) > > + ); > > + > > + // > > + // Copy Component 0 Density > > + // > > + Data32 = MmioRead32 (PchSpiBar0 + R_SPI_MEM_FDOD); > > + if (SpiInstance->NumberOfComponents > 0) { > > + SpiInstance->Component1StartAddr = V_FLASH_FLCOMP_COMP_512KB > << > > + (Data32 & B_FLASH_FLCOMP_COMP0_MASK); > > + DEBUG ((DEBUG_INFO, "Component 1 StartAddr : %0x\n", SpiInstance- > >Component1StartAddr)); > > + SpiInstance->TotalFlashSize = SpiInstance->Component1StartAddr + > > + (V_FLASH_FLCOMP_COMP_512KB << > > + ((Data32 & B_FLASH_FLCOMP_COMP1_MASK) >> > > + N_FLASH_FLCOMP_COMP1)); > > + } else { > > + SpiInstance->TotalFlashSize = V_FLASH_FLCOMP_COMP_512KB << > > + (Data32 & B_FLASH_FLCOMP_COMP0_MASK); > > + } > > + DEBUG ((DEBUG_INFO, "Total Flash Size : %0x\n", SpiInstance- > >TotalFlashSize)); > > + > > + // > > + // Select FLASH_MAP1 to get Flash PCH Strap Base Address > > + // > > + MmioAndThenOr32 ( > > + (PchSpiBar0 + R_SPI_MEM_FDOC), > > + (UINT32) (~(B_SPI_MEM_FDOC_FDSS_MASK | > B_SPI_MEM_FDOC_FDSI_MASK)), > > + (UINT32) (V_SPI_MEM_FDOC_FDSS_FSDM | > R_FLASH_FDBAR_FLASH_MAP1) > > + ); > > + // > > + // Align FPSBA with address bits for the PCH Strap portion of flash > descriptor > > + // > > + Data32 = MmioRead32 (PchSpiBar0 + R_SPI_MEM_FDOD); > > + SpiInstance->PchStrapBaseAddr = (UINT16) (((Data32 & > B_FLASH_FDBAR_FPSBA) > > + >> N_FLASH_FDBAR_FPSBA) > > + << N_FLASH_FDBAR_FPSBA_REPR); > > + DEBUG ((DEBUG_INFO, "PchStrapBaseAddr : %0x\n", SpiInstance- > >PchStrapBaseAddr)); > > + ASSERT (SpiInstance->PchStrapBaseAddr != 0); > > + // > > + // PCH Strap Length, [31:24] represents number of Dwords > > + // > > + SpiInstance->PchStrapSize = (UINT16) (((Data32 & > B_FLASH_FDBAR_PCHSL) > > + >> N_FLASH_FDBAR_PCHSL) > > + * sizeof (UINT32)); > > + DEBUG ((DEBUG_INFO, "PchStrapSize : %0x\n", SpiInstance- > >PchStrapSize)); > > + > > + // > > + // Select FLASH_MAP2 to get Flash CPU Strap Base Address > > + // > > + MmioAndThenOr32 ( > > + (PchSpiBar0 + R_SPI_MEM_FDOC), > > + (UINT32) (~(B_SPI_MEM_FDOC_FDSS_MASK | > B_SPI_MEM_FDOC_FDSI_MASK)), > > + (UINT32) (V_SPI_MEM_FDOC_FDSS_FSDM | > R_FLASH_FDBAR_FLASH_MAP2) > > + ); > > + // > > + // Align FPSBA with address bits for the CPU Strap portion of flash > descriptor > > + // > > + Data32 = MmioRead32 (PchSpiBar0 + R_SPI_MEM_FDOD); > > + // > > + // CPU Strap Length, [23:16] represents number of Dwords > > + // > > + SpiInstance->CpuStrapSize = (UINT16) (((Data32 & > B_FLASH_FDBAR_CPUSL) > > + >> N_FLASH_FDBAR_CPUSL) > > + * sizeof (UINT32)); > > + > > + // > > + // CPU Strap Address [11:2] represent offset from MDTBA > > + // > > + SpiInstance->CpuStrapBaseAddr = (UINT16) ((Data32 & > B_FLASH_FDBAR_FCPUSBA) >> N_FLASH_FDBAR_FCPUSBA); > > + ASSERT (SpiInstance->CpuStrapBaseAddr != 0); > > + > > + if (SpiInstance->CpuStrapBaseAddr != 0x300) { > > + Status = SpiProtocolFlashRead (&(SpiInstance->SpiProtocol), > FlashRegionAll, R_FLASH_UMAP1, sizeof (Data32), (UINT8 *) (&Data32)); > > + ASSERT_EFI_ERROR (Status); > > + Mdtba = (UINT16)(((Data32 & B_FLASH_UMAP1_MDTBA) >> > N_FLASH_UMAP1_MDTBA) << N_FLASH_UMAP1_MDTBA_REPR); > > + DEBUG ((DEBUG_INFO, "Mdtba : %0x\n", Mdtba)); > > + // Add MDTBA offset for final address of CPU Straps > > + SpiInstance->CpuStrapBaseAddr += Mdtba; > > + } > > + > > + DEBUG ((DEBUG_INFO, "CpuStrapBaseAddr : %0x\n", SpiInstance- > >CpuStrapBaseAddr)); > > + DEBUG ((DEBUG_INFO, "CpuStrapSize : %0x\n", SpiInstance- > >CpuStrapSize)); > > + > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + Delay for at least the request number of microseconds for Runtime usage. > > + > > + @param[in] ABase Acpi base address > > + @param[in] Microseconds Number of microseconds to delay. > > + > > +**/ > > +VOID > > +EFIAPI > > +PchPmTimerStallRuntimeSafe ( > > + IN UINT16 ABase, > > + IN UINTN Microseconds > > + ) > > +{ > > + UINTN Ticks; > > + UINTN Counts; > > + UINTN CurrentTick; > > + UINTN OriginalTick; > > + UINTN RemainingTick; > > + > > + if (Microseconds == 0) { > > + return; > > + } > > + > > + OriginalTick = IoRead32 ((UINTN) (ABase + R_ACPI_IO_PM1_TMR)) & > B_ACPI_IO_PM1_TMR_VAL; > > + CurrentTick = OriginalTick; > > + > > + // > > + // The timer frequency is 3.579545 MHz, so 1 ms corresponds 3.58 clocks > > + // > > + Ticks = Microseconds * 358 / 100 + OriginalTick + 1; > > + > > + // > > + // The loops needed by timer overflow > > + // > > + Counts = Ticks / V_ACPI_IO_PM1_TMR_MAX_VAL; > > + > > + // > > + // Remaining clocks within one loop > > + // > > + RemainingTick = Ticks % V_ACPI_IO_PM1_TMR_MAX_VAL; > > + > > + // > > + // not intend to use TMROF_STS bit of register PM1_STS, because this > adds extra > > + // one I/O operation, and maybe generate SMI > > + // > > + while ((Counts != 0) || (RemainingTick > CurrentTick)) { > > + CurrentTick = IoRead32 ((UINTN) (ABase + R_ACPI_IO_PM1_TMR)) & > B_ACPI_IO_PM1_TMR_VAL; > > + // > > + // Check if timer overflow > > + // > > + if ((CurrentTick < OriginalTick)) { > > + if (Counts != 0) { > > + Counts--; > > + } else { > > + // > > + // If timer overflow and Counts equ to 0, that means we already > stalled > more than > > + // RemainingTick, break the loop here > > + // > > + break; > > + } > > + } > > + > > + OriginalTick = CurrentTick; > > + } > > +} > > + > > +/** > > + Wait execution cycle to complete on the SPI interface. > > + > > + @param[in] This The SPI protocol instance > > + @param[in] PchSpiBar0 Spi MMIO base address > > + @param[in] ErrorCheck TRUE if the SpiCycle needs to do the error > check > > + > > + @retval TRUE SPI cycle completed on the interface. > > + @retval FALSE Time out while waiting the SPI cycle to > complete. > > + It's not safe to program the next command > on the SPI > interface. > > +**/ > > +STATIC > > +BOOLEAN > > +WaitForSpiCycleComplete ( > > + IN PCH_SPI_PROTOCOL *This, > > + IN UINTN PchSpiBar0, > > + IN BOOLEAN ErrorCheck > > + ) > > +{ > > + UINT64 WaitTicks; > > + UINT64 WaitCount; > > + UINT32 Data32; > > + SPI_INSTANCE *SpiInstance; > > + > > + SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This); > > + > > + // > > + // Convert the wait period allowed into to tick count > > + // > > + WaitCount = SPI_WAIT_TIME / SPI_WAIT_PERIOD; > > + // > > + // Wait for the SPI cycle to complete. > > + // > > + for (WaitTicks = 0; WaitTicks < WaitCount; WaitTicks++) { > > + Data32 = MmioRead32 (PchSpiBar0 + R_SPI_MEM_HSFSC); > > + if ((Data32 & B_SPI_MEM_HSFSC_SCIP) == 0) { > > + MmioWrite32 (PchSpiBar0 + R_SPI_MEM_HSFSC, > B_SPI_MEM_HSFSC_FCERR | B_SPI_MEM_HSFSC_FDONE); > > + if (((Data32 & B_SPI_MEM_HSFSC_FCERR) != 0) && (ErrorCheck == > TRUE)) { > > + return FALSE; > > + } else { > > + return TRUE; > > + } > > + } > > + PchPmTimerStallRuntimeSafe (SpiInstance->PchAcpiBase, > SPI_WAIT_PERIOD); > > + } > > + return FALSE; > > +} > > + > > +/** > > + This function sends the programmed SPI command to the slave device. > > + > > + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. > > + @param[in] SpiRegionType The SPI Region type for flash cycle which > is > listed in the Descriptor > > + @param[in] FlashCycleType The Flash SPI cycle type list in HSFC > (Hardware Sequencing Flash Control Register) register > > + @param[in] Address The Flash Linear Address must fall within a > region for which BIOS has access permissions. > > + @param[in] ByteCount Number of bytes in the data portion of the > SPI cycle. > > + @param[in,out] Buffer Pointer to caller-allocated buffer > containing > the dada received or sent during the SPI cycle. > > + > > + @retval EFI_SUCCESS SPI command completes successfully. > > + @retval EFI_DEVICE_ERROR Device error, the command aborts > abnormally. > > + @retval EFI_ACCESS_DENIED Some unrecognized or blocked command > encountered in hardware sequencing mode > > + @retval EFI_INVALID_PARAMETER The parameters specified are not > valid. > > +**/ > > +STATIC > > +EFI_STATUS > > +SendSpiCmd ( > > + IN PCH_SPI_PROTOCOL *This, > > + IN FLASH_REGION_TYPE FlashRegionType, > > + IN FLASH_CYCLE_TYPE FlashCycleType, > > + IN UINT32 Address, > > + IN UINT32 ByteCount, > > + IN OUT UINT8 *Buffer > > + ) > > +{ > > + EFI_STATUS Status; > > + UINT32 Index; > > + SPI_INSTANCE *SpiInstance; > > + UINT64 SpiBaseAddress; > > + UINTN PchSpiBar0; > > + UINT32 HardwareSpiAddr; > > + UINT32 FlashRegionSize; > > + UINT32 SpiDataCount; > > + UINT32 FlashCycle; > > + UINT8 BiosCtlSave; > > + UINT32 SmiEnSave; > > + UINT16 ABase; > > + UINT32 HsfstsCtl; > > + > > + // > > + // For flash write, there is a requirement that all CPU threads are in SMM > > + // before the flash protection is disabled. > > + // > > + if ((FlashCycleType == FlashCycleWrite) || (FlashCycleType == > FlashCycleErase)) { > > + if (!IsSpiFlashWriteGranted ()) { > > + return EFI_ACCESS_DENIED; > > + } > > + } > > + > > + Status = EFI_SUCCESS; > > + SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This); > > + SpiBaseAddress = SpiInstance->PchSpiBase; > > + PchSpiBar0 = AcquireSpiBar0 (SpiInstance); > > + ABase = SpiInstance->PchAcpiBase; > > + > > + // > > + // Disable SMIs to make sure normal mode flash access is not interrupted > by an SMI > > + // whose SMI handler accesses flash (e.g. for error logging) > > + // > > + // *** NOTE: if the SMI_LOCK bit is set (i.e., PMC PCI Offset A0h [4]='1'), > > + // clearing B_GBL_SMI_EN will not have effect. In this situation, some > other > > + // synchronization methods must be applied here or in the consumer of > the > > + // SendSpiCmd. An example method is disabling the specific SMI sources > > + // whose SMI handlers access flash before flash cycle and re-enabling the > SMI > > + // sources after the flash cycle . > > + // > > + SmiEnSave = IoRead32 ((UINTN) (ABase + R_ACPI_IO_SMI_EN)); > > + IoWrite32 ((UINTN) (ABase + R_ACPI_IO_SMI_EN), SmiEnSave & (UINT32) > (~B_ACPI_IO_SMI_EN_GBL_SMI)); > > + BiosCtlSave = PciSegmentRead8 (SpiBaseAddress + R_SPI_CFG_BC) & > B_SPI_CFG_BC_SRC; > > + > > + // > > + // If it's write cycle, disable Prefetching, Caching and disable BIOS Write > Protect > > + // > > + if ((FlashCycleType == FlashCycleWrite) || > > + (FlashCycleType == FlashCycleErase)) { > > + Status = DisableBiosWriteProtect (); > > + if (EFI_ERROR (Status)) { > > + goto SendSpiCmdEnd; > > + } > > + PciSegmentAndThenOr8 ( > > + SpiBaseAddress + R_SPI_CFG_BC, > > + (UINT8) (~B_SPI_CFG_BC_SRC), > > + (UINT8) (V_SPI_CFG_BC_SRC_PREF_DIS_CACHE_DIS << > N_SPI_CFG_BC_SRC) > > + ); > > + } > > + // > > + // Make sure it's safe to program the command. > > + // > > + if (!WaitForSpiCycleComplete (This, PchSpiBar0, FALSE)) { > > + Status = EFI_DEVICE_ERROR; > > + goto SendSpiCmdEnd; > > + } > > + > > + // > > + // Check if Write Status isn't disabled in HW Sequencing > > + // > > + if (FlashCycleType == FlashCycleWriteStatus) { > > + HsfstsCtl = MmioRead32 (PchSpiBar0 + R_SPI_MEM_HSFSC); > > + if ((HsfstsCtl & B_SPI_MEM_HSFSC_WRSDIS) != 0) { > > + Status = EFI_ACCESS_DENIED; > > + goto SendSpiCmdEnd; > > + } > > + } > > + > > + Status = SpiProtocolGetRegionAddress (This, FlashRegionType, > &HardwareSpiAddr, &FlashRegionSize); > > + if (EFI_ERROR (Status)) { > > + goto SendSpiCmdEnd; > > + } > > + HardwareSpiAddr += Address; > > + if ((Address + ByteCount) > FlashRegionSize) { > > + Status = EFI_INVALID_PARAMETER; > > + goto SendSpiCmdEnd; > > + } > > + > > + // > > + // Check for PCH SPI hardware sequencing required commands > > + // > > + FlashCycle = 0; > > + switch (FlashCycleType) { > > + case FlashCycleRead: > > + FlashCycle = (UINT32) (V_SPI_MEM_HSFSC_CYCLE_READ << > N_SPI_MEM_HSFSC_CYCLE); > > + break; > > + case FlashCycleWrite: > > + FlashCycle = (UINT32) (V_SPI_MEM_HSFSC_CYCLE_WRITE << > N_SPI_MEM_HSFSC_CYCLE); > > + break; > > + case FlashCycleErase: > > + if (((ByteCount % SIZE_4KB) != 0) || > > + ((HardwareSpiAddr % SIZE_4KB) != 0)) { > > + ASSERT (FALSE); > > + Status = EFI_INVALID_PARAMETER; > > + goto SendSpiCmdEnd; > > + } > > + break; > > + case FlashCycleReadSfdp: > > + FlashCycle = (UINT32) (V_SPI_MEM_HSFSC_CYCLE_READ_SFDP << > N_SPI_MEM_HSFSC_CYCLE); > > + break; > > + case FlashCycleReadJedecId: > > + FlashCycle = (UINT32) (V_SPI_MEM_HSFSC_CYCLE_READ_JEDEC_ID << > N_SPI_MEM_HSFSC_CYCLE); > > + break; > > + case FlashCycleWriteStatus: > > + FlashCycle = (UINT32) (V_SPI_MEM_HSFSC_CYCLE_WRITE_STATUS << > N_SPI_MEM_HSFSC_CYCLE); > > + break; > > + case FlashCycleReadStatus: > > + FlashCycle = (UINT32) (V_SPI_MEM_HSFSC_CYCLE_READ_STATUS << > N_SPI_MEM_HSFSC_CYCLE); > > + break; > > + default: > > + // > > + // Unrecognized Operation > > + // > > + ASSERT (FALSE); > > + Status = EFI_INVALID_PARAMETER; > > + goto SendSpiCmdEnd; > > + break; > > + } > > + > > + do { > > + SpiDataCount = ByteCount; > > + if ((FlashCycleType == FlashCycleRead) || > > + (FlashCycleType == FlashCycleWrite) || > > + (FlashCycleType == FlashCycleReadSfdp)) { > > + // > > + // Trim at 256 byte boundary per operation, > > + // - PCH SPI controller requires trimming at 4KB boundary > > + // - Some SPI chips require trimming at 256 byte boundary for write > operation > > + // - Trimming has limited performance impact as we can read / write > atmost 64 byte > > + // per operation > > + // > > + if (HardwareSpiAddr + ByteCount > ((HardwareSpiAddr + BIT8) &~(BIT8 - > 1))) { > > + SpiDataCount = (((UINT32) (HardwareSpiAddr) + BIT8) &~(BIT8 - 1)) - > (UINT32) (HardwareSpiAddr); > > + } > > + // > > + // Calculate the number of bytes to shift in/out during the SPI data > cycle. > > + // Valid settings for the number of bytes duing each data portion of > the > > + // PCH SPI cycles are: 0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 24, 32, 40, 48, > 56, 64 > > + // > > + if (SpiDataCount >= 64) { > > + SpiDataCount = 64; > > + } else if ((SpiDataCount &~0x07) != 0) { > > + SpiDataCount = SpiDataCount &~0x07; > > + } > > + } > > + if (FlashCycleType == FlashCycleErase) { > > + if (((ByteCount / SIZE_64KB) != 0) && > > + ((ByteCount % SIZE_64KB) == 0) && > > + ((HardwareSpiAddr % SIZE_64KB) == 0)) { > > + if ((SpiInstance->NumberOfComponents == 0) || > > + (HardwareSpiAddr < SpiInstance->Component1StartAddr)) { > > + // > > + // Check whether Component0 support 64k Erase > > + // > > + if ((SpiInstance->SfdpVscc0Value & > B_SPI_MEM_SFDPX_VSCCX_EO_64K) != 0) { > > + SpiDataCount = SIZE_64KB; > > + } else { > > + SpiDataCount = SIZE_4KB; > > + } > > + } else { > > + // > > + // Check whether Component1 support 64k Erase > > + // > > + if ((SpiInstance->SfdpVscc1Value & > B_SPI_MEM_SFDPX_VSCCX_EO_64K) != 0) { > > + SpiDataCount = SIZE_64KB; > > + } else { > > + SpiDataCount = SIZE_4KB; > > + } > > + } > > + } else { > > + SpiDataCount = SIZE_4KB; > > + } > > + if (SpiDataCount == SIZE_4KB) { > > + FlashCycle = (UINT32) (V_SPI_MEM_HSFSC_CYCLE_4K_ERASE << > N_SPI_MEM_HSFSC_CYCLE); > > + } else { > > + FlashCycle = (UINT32) (V_SPI_MEM_HSFSC_CYCLE_64K_ERASE << > N_SPI_MEM_HSFSC_CYCLE); > > + } > > + } > > + // > > + // If it's write cycle, load data into the SPI data buffer. > > + // > > + if ((FlashCycleType == FlashCycleWrite) || (FlashCycleType == > FlashCycleWriteStatus)) { > > + if ((SpiDataCount & 0x07) != 0) { > > + // > > + // Use Byte write if Data Count is 0, 1, 2, 3, 4, 5, 6, 7 > > + // > > + for (Index = 0; Index < SpiDataCount; Index++) { > > + MmioWrite8 (PchSpiBar0 + R_SPI_MEM_FDATA00 + Index, > Buffer[Index]); > > + } > > + } else { > > + // > > + // Use Dword write if Data Count is 8, 16, 24, 32, 40, 48, 56, 64 > > + // > > + for (Index = 0; Index < SpiDataCount; Index += sizeof (UINT32)) { > > + MmioWrite32 (PchSpiBar0 + R_SPI_MEM_FDATA00 + Index, *(UINT32 > *) (Buffer + Index)); > > + } > > + } > > + } > > + > > + // > > + // Set the Flash Address > > + // > > + MmioWrite32 ( > > + (PchSpiBar0 + R_SPI_MEM_FADDR), > > + (UINT32) (HardwareSpiAddr & B_SPI_MEM_FADDR_MASK) > > + ); > > + > > + // > > + // Set Data count, Flash cycle, and Set Go bit to start a cycle > > + // > > + MmioAndThenOr32 ( > > + PchSpiBar0 + R_SPI_MEM_HSFSC, > > + (UINT32) (~(B_SPI_MEM_HSFSC_FDBC_MASK | > B_SPI_MEM_HSFSC_CYCLE_MASK)), > > + (UINT32) ((((SpiDataCount - 1) << N_SPI_MEM_HSFSC_FDBC) & > B_SPI_MEM_HSFSC_FDBC_MASK) | FlashCycle | > B_SPI_MEM_HSFSC_CYCLE_FGO) > > + ); > > + // > > + // end of command execution > > + // > > + // Wait the SPI cycle to complete. > > + // > > + if (!WaitForSpiCycleComplete (This, PchSpiBar0, TRUE)) { > > + ASSERT (FALSE); > > + Status = EFI_DEVICE_ERROR; > > + goto SendSpiCmdEnd; > > + } > > + // > > + // If it's read cycle, load data into the call's buffer. > > + // > > + if ((FlashCycleType == FlashCycleRead) || > > + (FlashCycleType == FlashCycleReadSfdp) || > > + (FlashCycleType == FlashCycleReadJedecId) || > > + (FlashCycleType == FlashCycleReadStatus)) { > > + if ((SpiDataCount & 0x07) != 0) { > > + // > > + // Use Byte read if Data Count is 0, 1, 2, 3, 4, 5, 6, 7 > > + // > > + for (Index = 0; Index < SpiDataCount; Index++) { > > + Buffer[Index] = MmioRead8 (PchSpiBar0 + R_SPI_MEM_FDATA00 + > Index); > > + } > > + } else { > > + // > > + // Use Dword read if Data Count is 8, 16, 24, 32, 40, 48, 56, 64 > > + // > > + for (Index = 0; Index < SpiDataCount; Index += sizeof (UINT32)) { > > + *(UINT32 *) (Buffer + Index) = MmioRead32 (PchSpiBar0 + > R_SPI_MEM_FDATA00 + Index); > > + } > > + } > > + } > > + > > + HardwareSpiAddr += SpiDataCount; > > + Buffer += SpiDataCount; > > + ByteCount -= SpiDataCount; > > + } while (ByteCount > 0); > > + > > +SendSpiCmdEnd: > > + // > > + // Restore the settings for SPI Prefetching and Caching and enable BIOS > Write Protect > > + // > > + if ((FlashCycleType == FlashCycleWrite) || > > + (FlashCycleType == FlashCycleErase)) { > > + EnableBiosWriteProtect (); > > + PciSegmentAndThenOr8 ( > > + SpiBaseAddress + R_SPI_CFG_BC, > > + (UINT8) ~B_SPI_CFG_BC_SRC, > > + BiosCtlSave > > + ); > > + } > > + // > > + // Restore SMIs. > > + // > > + IoWrite32 ((UINTN) (ABase + R_ACPI_IO_SMI_EN), SmiEnSave); > > + > > + ReleaseSpiBar0 (SpiInstance); > > + > > + return Status; > > +} > > + > > +/** > > + Read data from the flash part. > > + > > + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. > > + @param[in] FlashRegionType The Flash Region type for flash cycle which > is listed in the Descriptor. > > + @param[in] Address The Flash Linear Address must fall within a > region for which BIOS has access permissions. > > + @param[in] ByteCount Number of bytes in the data portion of the > SPI cycle. > > + @param[out] Buffer The Pointer to caller-allocated buffer > containing the dada received. > > + It is the caller's responsibility to make > sure Buffer is large > enough for the total number of bytes read. > > + > > + @retval EFI_SUCCESS Command succeed. > > + @retval EFI_INVALID_PARAMETER The parameters specified are not > valid. > > + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. > > +**/ > > +EFI_STATUS > > +EFIAPI > > +SpiProtocolFlashRead ( > > + IN PCH_SPI_PROTOCOL *This, > > + IN FLASH_REGION_TYPE FlashRegionType, > > + IN UINT32 Address, > > + IN UINT32 ByteCount, > > + OUT UINT8 *Buffer > > + ) > > +{ > > + EFI_STATUS Status; > > + > > + // > > + // Sends the command to the SPI interface to execute. > > + // > > + Status = SendSpiCmd ( > > + This, > > + FlashRegionType, > > + FlashCycleRead, > > + Address, > > + ByteCount, > > + Buffer > > + ); > > + return Status; > > +} > > + > > +/** > > + Write data to the flash part. > > + > > + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. > > + @param[in] FlashRegionType The Flash Region type for flash cycle which > is listed in the Descriptor. > > + @param[in] Address The Flash Linear Address must fall within a > region for which BIOS has access permissions. > > + @param[in] ByteCount Number of bytes in the data portion of the > SPI cycle. > > + @param[in] Buffer Pointer to caller-allocated buffer > containing the > data sent during the SPI cycle. > > + > > + @retval EFI_SUCCESS Command succeed. > > + @retval EFI_INVALID_PARAMETER The parameters specified are not > valid. > > + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. > > +**/ > > +EFI_STATUS > > +EFIAPI > > +SpiProtocolFlashWrite ( > > + IN PCH_SPI_PROTOCOL *This, > > + IN FLASH_REGION_TYPE FlashRegionType, > > + IN UINT32 Address, > > + IN UINT32 ByteCount, > > + IN UINT8 *Buffer > > + ) > > +{ > > + EFI_STATUS Status; > > + > > + // > > + // Sends the command to the SPI interface to execute. > > + // > > + Status = SendSpiCmd ( > > + This, > > + FlashRegionType, > > + FlashCycleWrite, > > + Address, > > + ByteCount, > > + Buffer > > + ); > > + return Status; > > +} > > + > > +/** > > + Erase some area on the flash part. > > + > > + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. > > + @param[in] FlashRegionType The Flash Region type for flash cycle which > is listed in the Descriptor. > > + @param[in] Address The Flash Linear Address must fall within a > region for which BIOS has access permissions. > > + @param[in] ByteCount Number of bytes in the data portion of the > SPI cycle. > > + > > + @retval EFI_SUCCESS Command succeed. > > + @retval EFI_INVALID_PARAMETER The parameters specified are not > valid. > > + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. > > +**/ > > +EFI_STATUS > > +EFIAPI > > +SpiProtocolFlashErase ( > > + IN PCH_SPI_PROTOCOL *This, > > + IN FLASH_REGION_TYPE FlashRegionType, > > + IN UINT32 Address, > > + IN UINT32 ByteCount > > + ) > > +{ > > + EFI_STATUS Status; > > + > > + // > > + // Sends the command to the SPI interface to execute. > > + // > > + Status = SendSpiCmd ( > > + This, > > + FlashRegionType, > > + FlashCycleErase, > > + Address, > > + ByteCount, > > + NULL > > + ); > > + return Status; > > +} > > + > > +/** > > + Read SFDP data from the flash part. > > + > > + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. > > + @param[in] ComponentNumber The Componen Number for chip select > > + @param[in] Address The starting byte address for SFDP data > read. > > + @param[in] ByteCount Number of bytes in SFDP data portion of the > SPI cycle > > + @param[out] SfdpData The Pointer to caller-allocated buffer > containing the SFDP data received > > + It is the caller's responsibility to make > sure Buffer is large > enough for the total number of bytes read > > + > > + @retval EFI_SUCCESS Command succeed. > > + @retval EFI_INVALID_PARAMETER The parameters specified are not > valid. > > + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. > > + @retval EFI_UNSUPPORTED Unsupported operation with SAF Mode > enabled > > +**/ > > +EFI_STATUS > > +EFIAPI > > +SpiProtocolFlashReadSfdp ( > > + IN PCH_SPI_PROTOCOL *This, > > + IN UINT8 ComponentNumber, > > + IN UINT32 Address, > > + IN UINT32 ByteCount, > > + OUT UINT8 *SfdpData > > + ) > > +{ > > + SPI_INSTANCE *SpiInstance; > > + EFI_STATUS Status; > > + UINT32 FlashAddress; > > + > > + if (SpiIsSafModeActive ()) { > > + DEBUG ((DEBUG_ERROR, "Unallowed call to %a while SAF Mode is > active.\n", __FUNCTION__)); > > + return EFI_UNSUPPORTED; > > + } > > + > > + SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This); > > + Status = EFI_SUCCESS; > > + > > + if (ComponentNumber > SpiInstance->NumberOfComponents) { > > + ASSERT (FALSE); > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + FlashAddress = 0; > > + if (ComponentNumber == FlashComponent1) { > > + FlashAddress = SpiInstance->Component1StartAddr; > > + } > > + FlashAddress += Address; > > + // > > + // Sends the command to the SPI interface to execute. > > + // > > + Status = SendSpiCmd ( > > + This, > > + FlashRegionAll, > > + FlashCycleReadSfdp, > > + FlashAddress, > > + ByteCount, > > + SfdpData > > + ); > > + return Status; > > +} > > + > > +/** > > + Read Jedec Id from the flash part. > > + > > + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. > > + @param[in] ComponentNumber The Componen Number for chip select > > + @param[in] ByteCount Number of bytes in JedecId data portion of > the SPI cycle, the data size is 3 typically > > + @param[out] JedecId The Pointer to caller-allocated buffer > containing JEDEC ID received > > + It is the caller's responsibility to make > sure Buffer is large > enough for the total number of bytes read. > > + > > + @retval EFI_SUCCESS Command succeed. > > + @retval EFI_INVALID_PARAMETER The parameters specified are not > valid. > > + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. > > + @retval EFI_UNSUPPORTED Unsupported operation with SAF Mode > enabled > > +**/ > > +EFI_STATUS > > +EFIAPI > > +SpiProtocolFlashReadJedecId ( > > + IN PCH_SPI_PROTOCOL *This, > > + IN UINT8 ComponentNumber, > > + IN UINT32 ByteCount, > > + OUT UINT8 *JedecId > > + ) > > +{ > > + SPI_INSTANCE *SpiInstance; > > + EFI_STATUS Status; > > + UINT32 Address; > > + > > + if (SpiIsSafModeActive ()) { > > + DEBUG ((DEBUG_ERROR, "Unallowed call to %a while SAF Mode is > active.\n", __FUNCTION__)); > > + return EFI_UNSUPPORTED; > > + } > > + > > + SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This); > > + Status = EFI_SUCCESS; > > + > > + if (ComponentNumber > SpiInstance->NumberOfComponents) { > > + ASSERT (FALSE); > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + Address = 0; > > + if (ComponentNumber == FlashComponent1) { > > + Address = SpiInstance->Component1StartAddr; > > + } > > + > > + // > > + // Sends the command to the SPI interface to execute. > > + // > > + Status = SendSpiCmd ( > > + This, > > + FlashRegionAll, > > + FlashCycleReadJedecId, > > + Address, > > + ByteCount, > > + JedecId > > + ); > > + return Status; > > +} > > + > > +/** > > + Write the status register in the flash part. > > + > > + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. > > + @param[in] ByteCount Number of bytes in Status data portion of > the > SPI cycle, the data size is 1 typically > > + @param[in] StatusValue The Pointer to caller-allocated buffer > containing the value of Status register writing > > + > > + @retval EFI_SUCCESS Command succeed. > > + @retval EFI_INVALID_PARAMETER The parameters specified are not > valid. > > + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. > > + @retval EFI_UNSUPPORTED Unsupported operation with SAF Mode > enabled > > +**/ > > +EFI_STATUS > > +EFIAPI > > +SpiProtocolFlashWriteStatus ( > > + IN PCH_SPI_PROTOCOL *This, > > + IN UINT32 ByteCount, > > + IN UINT8 *StatusValue > > + ) > > +{ > > + EFI_STATUS Status; > > + > > + if (SpiIsSafModeActive ()) { > > + DEBUG ((DEBUG_ERROR, "Unallowed call to %a while SAF Mode is > active.\n", __FUNCTION__)); > > + return EFI_UNSUPPORTED; > > + } > > + > > + // > > + // Sends the command to the SPI interface to execute. > > + // > > + Status = SendSpiCmd ( > > + This, > > + FlashRegionAll, > > + FlashCycleWriteStatus, > > + 0, > > + ByteCount, > > + StatusValue > > + ); > > + return Status; > > +} > > + > > +/** > > + Read status register in the flash part. > > + > > + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. > > + @param[in] ByteCount Number of bytes in Status data portion of > the > SPI cycle, the data size is 1 typically > > + @param[out] StatusValue The Pointer to caller-allocated buffer > containing the value of Status register received. > > + > > + @retval EFI_SUCCESS Command succeed. > > + @retval EFI_INVALID_PARAMETER The parameters specified are not > valid. > > + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. > > + @retval EFI_UNSUPPORTED Unsupported operation with SAF Mode > enabled > > +**/ > > +EFI_STATUS > > +EFIAPI > > +SpiProtocolFlashReadStatus ( > > + IN PCH_SPI_PROTOCOL *This, > > + IN UINT32 ByteCount, > > + OUT UINT8 *StatusValue > > + ) > > +{ > > + EFI_STATUS Status; > > + > > + if (SpiIsSafModeActive ()) { > > + DEBUG ((DEBUG_ERROR, "Unallowed call to %a while SAF Mode is > active.\n", __FUNCTION__)); > > + return EFI_UNSUPPORTED; > > + } > > + > > + // > > + // Sends the command to the SPI interface to execute. > > + // > > + Status = SendSpiCmd ( > > + This, > > + FlashRegionAll, > > + FlashCycleReadStatus, > > + 0, > > + ByteCount, > > + StatusValue > > + ); > > + return Status; > > +} > > + > > +/** > > + Get the SPI region base and size, based on the enum type > > + > > + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. > > + @param[in] FlashRegionType The Flash Region type for for the base > address which is listed in the Descriptor. > > + @param[out] BaseAddress The Flash Linear Address for the Region 'n' > Base > > + @param[out] RegionSize The size for the Region 'n' > > + > > + @retval EFI_SUCCESS Read success > > + @retval EFI_INVALID_PARAMETER Invalid region type given > > + @retval EFI_DEVICE_ERROR The region is not used > > +**/ > > +EFI_STATUS > > +EFIAPI > > +SpiProtocolGetRegionAddress ( > > + IN PCH_SPI_PROTOCOL *This, > > + IN FLASH_REGION_TYPE FlashRegionType, > > + OUT UINT32 *BaseAddress, > > + OUT UINT32 *RegionSize > > + ) > > +{ > > + SPI_INSTANCE *SpiInstance; > > + UINTN PchSpiBar0; > > + UINT32 ReadValue; > > + > > + SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This); > > + > > + if (FlashRegionType >= FlashRegionMax) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + if (FlashRegionType == FlashRegionAll) { > > + *BaseAddress = 0; > > + *RegionSize = SpiInstance->TotalFlashSize; > > + return EFI_SUCCESS; > > + } > > + > > + PchSpiBar0 = AcquireSpiBar0 (SpiInstance); > > + ReadValue = MmioRead32 (PchSpiBar0 + (R_SPI_MEM_FREG0_FLASHD + > (S_SPI_MEM_FREGX * ((UINT32) FlashRegionType)))); > > + ReleaseSpiBar0 (SpiInstance); > > + > > + // > > + // If the region is not used, the Region Base is 7FFFh and Region Limit is > 0000h > > + // > > + if (ReadValue == B_SPI_MEM_FREGX_BASE_MASK) { > > + return EFI_DEVICE_ERROR; > > + } > > + *BaseAddress = ((ReadValue & B_SPI_MEM_FREGX_BASE_MASK) >> > N_SPI_MEM_FREGX_BASE) << > > + N_SPI_MEM_FREGX_BASE_REPR; > > + // > > + // Region limit address Bits[11:0] are assumed to be FFFh > > + // > > + *RegionSize = ((((ReadValue & B_SPI_MEM_FREGX_LIMIT_MASK) >> > N_SPI_MEM_FREGX_LIMIT) + 1) << > > + N_SPI_MEM_FREGX_LIMIT_REPR) - *BaseAddress; > > + > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + Read PCH Soft Strap Values > > + > > + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. > > + @param[in] SoftStrapAddr PCH Soft Strap address offset from FPSBA. > > + @param[in] ByteCount Number of bytes in SoftStrap data portion > of > the SPI cycle > > + @param[out] SoftStrapValue The Pointer to caller-allocated buffer > containing PCH Soft Strap Value. > > + If the value of ByteCount is 0, the data > type of > SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap > Length > > + It is the caller's responsibility to make > sure Buffer is large > enough for the total number of bytes read. > > + > > + @retval EFI_SUCCESS Command succeed. > > + @retval EFI_INVALID_PARAMETER The parameters specified are not > valid. > > + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. > > +**/ > > +EFI_STATUS > > +EFIAPI > > +SpiProtocolReadPchSoftStrap ( > > + IN PCH_SPI_PROTOCOL *This, > > + IN UINT32 SoftStrapAddr, > > + IN UINT32 ByteCount, > > + OUT VOID *SoftStrapValue > > + ) > > +{ > > + SPI_INSTANCE *SpiInstance; > > + UINT32 StrapFlashAddr; > > + EFI_STATUS Status; > > + > > + SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This); > > + > > + if (ByteCount == 0) { > > + *(UINT16 *) SoftStrapValue = SpiInstance->PchStrapSize; > > + return EFI_SUCCESS; > > + } > > + > > + if ((SoftStrapAddr + ByteCount) > (UINT32) SpiInstance->PchStrapSize) { > > + ASSERT (FALSE); > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + // > > + // PCH Strap Flash Address = FPSBA + RamAddr > > + // > > + StrapFlashAddr = SpiInstance->PchStrapBaseAddr + SoftStrapAddr; > > + > > + // > > + // Read PCH Soft straps from using execute command > > + // > > + Status = SendSpiCmd ( > > + This, > > + FlashRegionDescriptor, > > + FlashCycleRead, > > + StrapFlashAddr, > > + ByteCount, > > + SoftStrapValue > > + ); > > + return Status; > > +} > > + > > +/** > > + Read CPU Soft Strap Values > > + > > + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. > > + @param[in] SoftStrapAddr CPU Soft Strap address offset from > FCPUSBA. > > + @param[in] ByteCount Number of bytes in SoftStrap data portion > of > the SPI cycle. > > + @param[out] SoftStrapValue The Pointer to caller-allocated buffer > containing CPU Soft Strap Value. > > + If the value of ByteCount is 0, the data > type of > SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap > Length > > + It is the caller's responsibility to make > sure Buffer is large > enough for the total number of bytes read. > > + > > + @retval EFI_SUCCESS Command succeed. > > + @retval EFI_INVALID_PARAMETER The parameters specified are not > valid. > > + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. > > +**/ > > +EFI_STATUS > > +EFIAPI > > +SpiProtocolReadCpuSoftStrap ( > > + IN PCH_SPI_PROTOCOL *This, > > + IN UINT32 SoftStrapAddr, > > + IN UINT32 ByteCount, > > + OUT VOID *SoftStrapValue > > + ) > > +{ > > + SPI_INSTANCE *SpiInstance; > > + UINT32 StrapFlashAddr; > > + EFI_STATUS Status; > > + > > + SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This); > > + > > + if (ByteCount == 0) { > > + *(UINT16 *) SoftStrapValue = SpiInstance->CpuStrapSize; > > + return EFI_SUCCESS; > > + } > > + > > + if ((SoftStrapAddr + ByteCount) > (UINT32) SpiInstance->CpuStrapSize) { > > + ASSERT (FALSE); > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + // > > + // CPU Strap Flash Address = FCPUSBA + RamAddr > > + // > > + StrapFlashAddr = SpiInstance->CpuStrapBaseAddr + SoftStrapAddr; > > + > > + // > > + // Read Cpu Soft straps from using execute command > > + // > > + Status = SendSpiCmd ( > > + This, > > + FlashRegionDescriptor, > > + FlashCycleRead, > > + StrapFlashAddr, > > + ByteCount, > > + SoftStrapValue > > + ); > > + return Status; > > +} > > diff --git > a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/PeiDxeSmmSpi > AccessPrivateLib/PeiDxeSmmSpiAccessPrivateLib.inf > b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/PeiDxeSmmSpi > AccessPrivateLib/PeiDxeSmmSpiAccessPrivateLib.inf > new file mode 100644 > index 0000000000..4e059494d8 > --- /dev/null > +++ > b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/PeiDxeSmmSpi > AccessPrivateLib/PeiDxeSmmSpiAccessPrivateLib.inf > @@ -0,0 +1,40 @@ > +## @file > > +# Component description file for PCH SPI access private library > > +# > > +# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> > > +# SPDX-License-Identifier: BSD-2-Clause-Patent > > +# > > +## > > + > > + > > +[Defines] > > +INF_VERSION = 0x00010017 > > +BASE_NAME = PeiDxeSmmSpiAccessPrivateLib > > +FILE_GUID = 2CD382D7-9928-C32A-601D-69797C618A6D > > +VERSION_STRING = 1.0 > > +MODULE_TYPE = BASE > > +LIBRARY_CLASS = SpiAccessPrivateLib > > + > > + > > +[LibraryClasses] > > +BaseLib > > +IoLib > > +DebugLib > > +PciSegmentLib > > +SpiAccessLib > > +PcdLib > > +S3BootScriptLib > > +PchPciBdfLib > > + > > + > > +[Packages] > > +MdePkg/MdePkg.dec > > +TigerlakeSiliconPkg/SiPkg.dec > > + > > + > > +[Sources] > > +SpiAccessPrivateLib.c > > + > > + > > +[Pcd] > > +gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress > > diff --git > a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/PeiDxeSmmSpi > AccessPrivateLib/SpiAccessPrivateLib.c > b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/PeiDxeSmmSpi > AccessPrivateLib/SpiAccessPrivateLib.c > new file mode 100644 > index 0000000000..de1f3d3f86 > --- /dev/null > +++ > b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/PeiDxeSmmSpi > AccessPrivateLib/SpiAccessPrivateLib.c > @@ -0,0 +1,133 @@ > +/** @file > > + SPI library for abstraction of SPI HW registers accesses > > + > > + Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> > > + SPDX-License-Identifier: BSD-2-Clause-Patent > > +**/ > > + > > +#include <Base.h> > > +#include <Uefi/UefiBaseType.h> > > +#include <Library/SpiAccessLib.h> > > +#include <Library/PciSegmentLib.h> > > +#include <Library/DebugLib.h> > > +#include <Library/S3BootScriptLib.h> > > +#include <Register/SpiRegs.h> > > +#include <Register/PchRegs.h> > > +#include <Register/PchPcrRegs.h> > > +#include <Library/PchPciBdfLib.h> > > + > > +/** > > + 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); > > +} > > diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Smm/Spi.c > b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Smm/Spi.c > new file mode 100644 > index 0000000000..419eddaff3 > --- /dev/null > +++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Smm/Spi.c > @@ -0,0 +1,296 @@ > +/** @file > > + PCH SPI SMM Driver implements the SPI Host Controller Compatibility > Interface. > > + > > + Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> > > + SPDX-License-Identifier: BSD-2-Clause-Patent > > +**/ > > + > > +#include <Library/IoLib.h> > > +#include <Library/DebugLib.h> > > +#include <Library/UefiDriverEntryPoint.h> > > +#include <Library/UefiBootServicesTableLib.h> > > +#include <Library/BaseLib.h> > > +#include <Library/BaseMemoryLib.h> > > +#include <Library/SmmServicesTableLib.h> > > +#include <Library/PciSegmentLib.h> > > +#include <Protocol/Spi.h> > > +#include <Protocol/SmmCpu.h> > > +#include <Library/SpiCommonLib.h> > > +#include <PchReservedResources.h> > > +#include <Library/SmmPchPrivateLib.h> > > +#include <Library/PchPciBdfLib.h> > > +#include <IndustryStandard/Pci30.h> > > +#include <Register/PchRegs.h> > > +#include <Register/SpiRegs.h> > > + > > +// > > +// Global variables > > +// > > +GLOBAL_REMOVE_IF_UNREFERENCED SPI_INSTANCE *mSpiInstance; > > +GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_CPU_PROTOCOL > *mSmmCpuProtocol; > > +// > > +// mPchSpiResvMmioAddr keeps the reserved MMIO range assiged to SPI. > > +// In SMM it always set back the reserved MMIO address to SPI BAR0 to > ensure the MMIO range > > +// won't overlap with SMRAM range, and trusted. > > +// > > +GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mSpiResvMmioAddr; > > + > > +/** > > + <b>SPI Runtime SMM Module Entry Point</b>\n > > + - <b>Introduction</b>\n > > + The SPI SMM module provide a standard way for other modules to use > the PCH SPI Interface in SMM. > > + > > + - @pre > > + - EFI_SMM_BASE2_PROTOCOL > > + - Documented in System Management Mode Core Interface > Specification . > > + > > + - @result > > + The SPI SMM driver produces @link _PCH_SPI_PROTOCOL > PCH_SPI_PROTOCOL @endlink with GUID > > + gPchSmmSpiProtocolGuid which is different from SPI RUNTIME driver. > > + > > + - <b>Integration Check List</b>\n > > + - This driver supports Descriptor Mode only. > > + - This driver supports Hardware Sequence only. > > + - When using SMM SPI Protocol to perform flash access in an SMI handler, > > + and the SMI occurrence is asynchronous to normal mode code > execution, > > + proper synchronization mechanism must be applied, e.g. disable SMI > before > > + the normal mode SendSpiCmd() starts and re-enable SMI after > > + the normal mode SendSpiCmd() completes. > > + @note The implementation of SendSpiCmd() uses GBL_SMI_EN in > > + SMI_EN register (ABase + 30h) to disable and enable SMIs. But this may > > + not be effective as platform may well set the SMI_LOCK bit (i.e., PMC > PCI Offset A0h [4]). > > + So the synchronization at caller level is likely needed. > > + > > + @param[in] ImageHandle Image handle of this driver. > > + @param[in] SystemTable Global system service table. > > + > > + @retval EFI_SUCCESS Initialization complete. > > + @exception EFI_UNSUPPORTED The chipset is unsupported by this > driver. > > + @retval EFI_OUT_OF_RESOURCES Do not have enough resources to > initialize the driver. > > + @retval EFI_DEVICE_ERROR Device error, driver exits abnormally. > > +**/ > > +EFI_STATUS > > +EFIAPI > > +InstallPchSpi ( > > + IN EFI_HANDLE ImageHandle, > > + IN EFI_SYSTEM_TABLE *SystemTable > > + ) > > +{ > > + EFI_STATUS Status; > > + > > + // > > + // Init PCH spi reserved MMIO address. > > + // > > + mSpiResvMmioAddr = PCH_SPI_BASE_ADDRESS; > > + > > + /// > > + /// Allocate pool for SPI protocol instance > > + /// > > + Status = gSmst->SmmAllocatePool ( > > + EfiRuntimeServicesData, /// MemoryType don't care > > + sizeof (SPI_INSTANCE), > > + (VOID **) &mSpiInstance > > + ); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + > > + if (mSpiInstance == NULL) { > > + return EFI_OUT_OF_RESOURCES; > > + } > > + > > + ZeroMem ((VOID *) mSpiInstance, sizeof (SPI_INSTANCE)); > > + /// > > + /// Initialize the SPI protocol instance > > + /// > > + Status = SpiProtocolConstructor (mSpiInstance); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + /// > > + /// Install the SMM PCH_SPI_PROTOCOL interface > > + /// > > + Status = gSmst->SmmInstallProtocolInterface ( > > + &(mSpiInstance->Handle), > > + &gPchSmmSpiProtocolGuid, > > + EFI_NATIVE_INTERFACE, > > + &(mSpiInstance->SpiProtocol) > > + ); > > + if (EFI_ERROR (Status)) { > > + gSmst->SmmFreePool (mSpiInstance); > > + return EFI_DEVICE_ERROR; > > + } > > + > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + Acquire PCH spi mmio address. > > + If it is ever different from the preallocated address, reassign it back. > > + In SMM, it always override the BAR0 and returns the reserved MMIO > range for SPI. > > + > > + @param[in] SpiInstance Pointer to SpiInstance to initialize > > + > > + @retval PchSpiBar0 return SPI MMIO address > > +**/ > > +UINTN > > +AcquireSpiBar0 ( > > + IN SPI_INSTANCE *SpiInstance > > + ) > > +{ > > + UINT32 SpiBar0; > > + // > > + // Save original SPI physical MMIO address > > + // > > + SpiBar0 = PciSegmentRead32 (SpiInstance->PchSpiBase + > R_SPI_CFG_BAR0) & ~(B_SPI_CFG_BAR0_MASK); > > + > > + if (SpiBar0 != mSpiResvMmioAddr) { > > + // > > + // Temporary disable MSE, and override with SPI reserved MMIO > address, then enable MSE. > > + // > > + PciSegmentAnd8 (SpiInstance->PchSpiBase + PCI_COMMAND_OFFSET, > (UINT8) ~EFI_PCI_COMMAND_MEMORY_SPACE); > > + PciSegmentWrite32 (SpiInstance->PchSpiBase + R_SPI_CFG_BAR0, > mSpiResvMmioAddr); > > + PciSegmentOr8 (SpiInstance->PchSpiBase + PCI_COMMAND_OFFSET, > EFI_PCI_COMMAND_MEMORY_SPACE); > > + } > > + // > > + // SPIBAR0 will be different before and after PCI enum so need to get it > from SPI BAR0 reg. > > + // > > + return mSpiResvMmioAddr; > > +} > > + > > +/** > > + Release pch spi mmio address. Do nothing. > > + > > + @param[in] SpiInstance Pointer to SpiInstance to initialize > > + > > + @retval None > > +**/ > > +VOID > > +ReleaseSpiBar0 ( > > + IN SPI_INSTANCE *SpiInstance > > + ) > > +{ > > +} > > + > > +/** > > + This function is a hook for Spi to disable BIOS Write Protect > > + > > + @retval EFI_SUCCESS The protocol instance was properly > initialized > > + @retval EFI_ACCESS_DENIED The BIOS Region can only be updated in > SMM phase > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DisableBiosWriteProtect ( > > + VOID > > + ) > > +{ > > + UINT64 SpiBaseAddress; > > + > > + SpiBaseAddress = SpiPciCfgBase (); > > + // Write clear BC_SYNC_SS prior to change WPD from 0 to 1. > > + // > > + PciSegmentOr8 ( > > + SpiBaseAddress + R_SPI_CFG_BC + 1, > > + (B_SPI_CFG_BC_SYNC_SS >> 8) > > + ); > > + /// > > + /// Set BIOSWE bit (SPI PCI Offset DCh [0]) = 1b > > + /// Enable the access to the BIOS space for both read and write cycles > > + /// > > + PciSegmentOr8 ( > > + SpiBaseAddress + R_SPI_CFG_BC, > > + B_SPI_CFG_BC_WPD > > + ); > > + > > + /// > > + /// PCH BIOS Spec Section 3.7 BIOS Region SMM Protection Enabling > > + /// If the following steps are implemented: > > + /// - Set the EISS bit (SPI PCI Offset DCh [5]) = 1b > > + /// - Follow the 1st recommendation in section 3.6 > > + /// the BIOS Region can only be updated by following the steps bellow: > > + /// - Once all threads enter SMM > > + /// - Read memory location FED30880h OR with 00000001h, place the > result in EAX, > > + /// and write data to lower 32 bits of MSR 1FEh (sample code available) > > + /// - Set BIOSWE bit (SPI PCI Offset DCh [0]) = 1b > > + /// - Modify BIOS Region > > + /// - Clear BIOSWE bit (SPI PCI Offset DCh [0]) = 0b > > + /// > > + if ((PciSegmentRead8 (SpiBaseAddress + R_SPI_CFG_BC) & > B_SPI_CFG_BC_EISS) != 0) { > > + PchSetInSmmSts (); > > + } > > + > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + This function is a hook for Spi to enable BIOS Write Protect > > +**/ > > +VOID > > +EFIAPI > > +EnableBiosWriteProtect ( > > + VOID > > + ) > > +{ > > + UINT64 SpiBaseAddress; > > + > > + SpiBaseAddress = SpiPciCfgBase (); > > + /// > > + /// Clear BIOSWE bit (SPI PCI Offset DCh [0]) = 0b > > + /// Disable the access to the BIOS space for write cycles > > + /// > > + PciSegmentAnd8 ( > > + SpiBaseAddress + R_SPI_CFG_BC, > > + (UINT8) (~B_SPI_CFG_BC_WPD) > > + ); > > + > > + /// > > + /// Check if EISS bit is set > > + /// > > + if (((PciSegmentRead8 (SpiBaseAddress + R_SPI_CFG_BC)) & > B_SPI_CFG_BC_EISS) == B_SPI_CFG_BC_EISS) { > > + PchClearInSmmSts (); > > + } > > +} > > + > > +/** > > + Check if it's granted to do flash write. > > + > > + @retval TRUE It's secure to do flash write. > > + @retval FALSE It's not secure to do flash write. > > +**/ > > +BOOLEAN > > +IsSpiFlashWriteGranted ( > > + VOID > > + ) > > +{ > > + EFI_STATUS Status; > > + UINT32 CpuIndex; > > + UINT64 ProcessorId; > > + > > + if (mSmmCpuProtocol == NULL) { > > + Status = gSmst->SmmLocateProtocol (&gEfiSmmCpuProtocolGuid, NULL, > (VOID **)&mSmmCpuProtocol); > > + ASSERT_EFI_ERROR (Status); > > + if (mSmmCpuProtocol == NULL) { > > + return TRUE; > > + } > > + } > > + > > + for (CpuIndex = 0; CpuIndex < gSmst->NumberOfCpus; CpuIndex++) { > > + Status = mSmmCpuProtocol->ReadSaveState ( > > + mSmmCpuProtocol, > > + sizeof (ProcessorId), > > + EFI_SMM_SAVE_STATE_REGISTER_PROCESSOR_ID, > > + CpuIndex, > > + &ProcessorId > > + ); > > + // > > + // If the processor is in SMM at the time the SMI occurred, > > + // it will return success. Otherwise, EFI_NOT_FOUND is returned. > > + // > > + if (EFI_ERROR (Status)) { > > + return FALSE; > > + } > > + } > > + > > + return TRUE; > > +} > > diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Smm/SpiSmm.inf > b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Smm/SpiSmm.inf > new file mode 100644 > index 0000000000..033134cea1 > --- /dev/null > +++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Smm/SpiSmm.inf > @@ -0,0 +1,47 @@ > +## @file > > +# Component description file for the SPI SMM driver. > > +# > > +# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> > > +# SPDX-License-Identifier: BSD-2-Clause-Patent > > +# > > +## > > + > > + > > +[Defines] > > +INF_VERSION = 0x00010017 > > +BASE_NAME = SpiSmm > > +FILE_GUID = 27F4917B-A707-4aad-9676-26DF168CBF0D > > +VERSION_STRING = 1.0 > > +MODULE_TYPE = DXE_SMM_DRIVER > > +PI_SPECIFICATION_VERSION = 1.10 > > +ENTRY_POINT = InstallPchSpi > > + > > + > > +[LibraryClasses] > > +DebugLib > > +IoLib > > +UefiDriverEntryPoint > > +UefiBootServicesTableLib > > +BaseLib > > +SmmServicesTableLib > > +SpiCommonLib > > +SmmPchPrivateLib > > +PchPciBdfLib > > + > > +[Packages] > > +MdePkg/MdePkg.dec > > +TigerlakeSiliconPkg/SiPkg.dec > > + > > + > > +[Sources] > > +Spi.c > > + > > + > > +[Protocols] > > +gPchSmmSpiProtocolGuid ## PRODUCES > > +gEfiSmmCpuProtocolGuid ## CONSUMES > > + > > + > > +[Depex] > > +gEfiSmmBase2ProtocolGuid AND # This is for SmmServicesTableLib > > +gEfiSmmCpuProtocolGuid # This is for CpuSmmDisableBiosWriteProtect() > > -- > 2.24.0.windows.2
-=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#71165): https://edk2.groups.io/g/devel/message/71165 Mute This Topic: https://groups.io/mt/80274143/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-