From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga01.intel.com (mga01.intel.com []) by mx.groups.io with SMTP id smtpd.web10.5201.1612510915343505036 for ; Thu, 04 Feb 2021 23:41:59 -0800 Authentication-Results: mx.groups.io; dkim=missing; spf=fail (domain: intel.com, ip: , mailfrom: heng.luo@intel.com) IronPort-SDR: atzQH7hTIkSyODLzKcYG7iNYiO5pEBAege1otgVwT6/u6Y7Th+XOzRQMwvfdxqkhUlcIHDoSg+ 5KWM1sVdHniQ== X-IronPort-AV: E=McAfee;i="6000,8403,9885"; a="200397308" X-IronPort-AV: E=Sophos;i="5.81,154,1610438400"; d="scan'208";a="200397308" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Feb 2021 23:41:59 -0800 IronPort-SDR: tMVZYarRX37zcbzmc6O6QSKYruFi4Vm3RzjzkFgY9BVV6nSbS4ohRmtRUIPBvgodfWsqtjYnF/ QK4NEyrrAICA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.81,154,1610438400"; d="scan'208";a="373260676" Received: from hengluo-dev.ccr.corp.intel.com ([10.239.153.154]) by fmsmga008.fm.intel.com with ESMTP; 04 Feb 2021 23:41:56 -0800 From: "Heng Luo" To: devel@edk2.groups.io Cc: Sai Chaganty , Nate DeSimone Subject: [Patch V3 29/40] TigerlakeSiliconPkg/IpBlock: Add Spi component Date: Fri, 5 Feb 2021 15:40:34 +0800 Message-Id: <20210205074045.3916-29-heng.luo@intel.com> X-Mailer: git-send-email 2.24.0.windows.2 In-Reply-To: <20210205074045.3916-1-heng.luo@intel.com> References: <20210205074045.3916-1-heng.luo@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D3171 Adds the following files: * IpBlock/Spi/IncludePrivate * IpBlock/Spi/Library * IpBlock/Spi/LibraryPrivate * IpBlock/Spi/Smm Cc: Sai Chaganty Cc: Nate DeSimone Signed-off-by: Heng Luo --- Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Library/SpiAc= cessPrivateLib.h | 40 +++++++++++++++++++= +++++++++++++ Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Library/SpiCo= mmonLib.h | 364 +++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= ++++++++++++++++++++++++++++++++++++++++ Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Register/SpiR= egs.h | 136 +++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= ++++++++++++ Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Library/PeiDxeSmmSpiAccessLi= b/PeiDxeSmmSpiAccessLib.inf | 33 +++++++++++++++++++= +++++++ Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Library/PeiDxeSmmSpiAccessLi= b/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/PeiDxeSmmSpiA= ccessPrivateLib/PeiDxeSmmSpiAccessPrivateLib.inf | 40 +++++++++++++++++++= +++++++++++++ Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/PeiDxeSmmSpiA= ccessPrivateLib/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/L= ibrary/SpiAccessPrivateLib.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Sp= i/IncludePrivate/Library/SpiAccessPrivateLib.h new file mode 100644 index 0000000000..6da88a9047 --- /dev/null +++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Library/= SpiAccessPrivateLib.h @@ -0,0 +1,40 @@ +/** @file=0D + SPI library header for abstraction of SPI HW registers accesses=0D +=0D + Copyright (c) 2021, Intel Corporation. All rights reserved.
=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +**/=0D +=0D +#ifndef _SPI_ACCESS_PRIVATE_LIB_H_=0D +#define _SPI_ACCESS_PRIVATE_LIB_H_=0D +=0D +/**=0D + Disable EISS (Enable InSMM.STS)=0D +**/=0D +VOID=0D +SpiDisableEiss (=0D + VOID=0D + );=0D +=0D +/**=0D + Configure BiosLockEnable bit and BiosInterfaceLock bit according to poli= cy setting.=0D +=0D + @param[in] BiosLockEnable Policy for BiosLockEnable bit programming= =0D + @param[in] BiosInterfaceLock Policy for BiosInterfaceLock bit programmi= ng=0D +=0D +**/=0D +VOID=0D +SpiBiosLockEnableAndBiosInterfaceLockWithS3BootScript (=0D + IN BOOLEAN BiosLockEnable,=0D + IN BOOLEAN BiosInterfaceLock=0D + );=0D +=0D +/**=0D + Clears BIOS Write Protect Disable bit=0D +**/=0D +VOID=0D +SpiClearBiosWriteProtectDisable (=0D + VOID=0D + );=0D +=0D +#endif // _SPI_ACCESS_PRIVATE_LIB_H_=0D diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/L= ibrary/SpiCommonLib.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Inclu= dePrivate/Library/SpiCommonLib.h new file mode 100644 index 0000000000..3290f77122 --- /dev/null +++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Library/= SpiCommonLib.h @@ -0,0 +1,364 @@ +/** @file=0D + Header file for the PCH SPI Common Driver.=0D +=0D + Copyright (c) 2021, Intel Corporation. All rights reserved.
=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +**/=0D +#ifndef _SPI_COMMON_LIB_H_=0D +#define _SPI_COMMON_LIB_H_=0D +=0D +#include =0D +=0D +//=0D +// Maximum time allowed while waiting the SPI cycle to complete=0D +// Wait Time =3D 6 seconds =3D 6000000 microseconds=0D +// Wait Period =3D 10 microseconds=0D +//=0D +#define SPI_WAIT_TIME 6000000 ///< Wait Time =3D 6 seconds =3D 60000= 00 microseconds=0D +#define SPI_WAIT_PERIOD 10 ///< Wait Period =3D 10 microseconds=0D +=0D +///=0D +/// Flash cycle Type=0D +///=0D +typedef enum {=0D + FlashCycleRead,=0D + FlashCycleWrite,=0D + FlashCycleErase,=0D + FlashCycleReadSfdp,=0D + FlashCycleReadJedecId,=0D + FlashCycleWriteStatus,=0D + FlashCycleReadStatus,=0D + FlashCycleMax=0D +} FLASH_CYCLE_TYPE;=0D +=0D +///=0D +/// Flash Component Number=0D +///=0D +typedef enum {=0D + FlashComponent0,=0D + FlashComponent1,=0D + FlashComponentMax=0D +} FLASH_COMPONENT_NUM;=0D +=0D +///=0D +/// Private data structure definitions for the driver=0D +///=0D +#define PCH_SPI_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('P', 'S', 'P', 'I')= =0D +=0D +typedef struct {=0D + UINT32 Signature;=0D + EFI_HANDLE Handle;=0D + PCH_SPI_PROTOCOL SpiProtocol;=0D + UINT16 PchAcpiBase;=0D + UINT64 PchSpiBase;=0D + UINT8 ReadPermission;=0D + UINT8 WritePermission;=0D + UINT32 SfdpVscc0Value;=0D + UINT32 SfdpVscc1Value;=0D + UINT16 PchStrapBaseAddr;=0D + UINT16 PchStrapSize;=0D + UINT16 CpuStrapBaseAddr;=0D + UINT16 CpuStrapSize;=0D + UINT8 NumberOfComponents;=0D + UINT32 Component1StartAddr;=0D + UINT32 TotalFlashSize;=0D +} SPI_INSTANCE;=0D +=0D +#define SPI_INSTANCE_FROM_SPIPROTOCOL(a) CR (a, SPI_INSTANCE, SpiProtocol= , PCH_SPI_PRIVATE_DATA_SIGNATURE)=0D +=0D +//=0D +// Function prototypes used by the SPI protocol.=0D +//=0D +=0D +/**=0D + Initialize an SPI protocol instance.=0D +=0D + @param[in] SpiInstance Pointer to SpiInstance to initialize=0D +=0D + @retval EFI_SUCCESS The protocol instance was properly initi= alized=0D + @exception EFI_UNSUPPORTED The PCH is not supported by this module= =0D +**/=0D +EFI_STATUS=0D +SpiProtocolConstructor (=0D + IN SPI_INSTANCE *SpiInstance=0D + );=0D +=0D +/**=0D + This function is a hook for Spi to disable BIOS Write Protect=0D +=0D + @retval EFI_SUCCESS The protocol instance was properly initi= alized=0D + @retval EFI_ACCESS_DENIED The BIOS Region can only be updated in S= MM phase=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +DisableBiosWriteProtect (=0D + VOID=0D + );=0D +=0D +/**=0D + This function is a hook for Spi to enable BIOS Write Protect=0D +=0D +=0D +**/=0D +VOID=0D +EFIAPI=0D +EnableBiosWriteProtect (=0D + VOID=0D + );=0D +=0D +/**=0D + Acquire pch spi mmio address.=0D +=0D + @param[in] SpiInstance Pointer to SpiInstance to initialize=0D +=0D + @retval PchSpiBar0 return SPI MMIO address=0D +**/=0D +UINTN=0D +AcquireSpiBar0 (=0D + IN SPI_INSTANCE *SpiInstance=0D + );=0D +=0D +/**=0D + Release pch spi mmio address.=0D +=0D + @param[in] SpiInstance Pointer to SpiInstance to initialize=0D +=0D + @retval None=0D +**/=0D +VOID=0D +ReleaseSpiBar0 (=0D + IN SPI_INSTANCE *SpiInstance=0D + );=0D +=0D +/**=0D + Check if it's granted to do flash write.=0D +=0D + @retval TRUE It's secure to do flash write.=0D + @retval FALSE It's not secure to do flash write.=0D +**/=0D +BOOLEAN=0D +IsSpiFlashWriteGranted (=0D + VOID=0D + );=0D +=0D +/**=0D + Read data from the flash part.=0D +=0D + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance= .=0D + @param[in] FlashRegionType The Flash Region type for flash cycle wh= ich is listed in the Descriptor.=0D + @param[in] Address The Flash Linear Address must fall withi= n a region for which BIOS has access permissions.=0D + @param[in] ByteCount Number of bytes in the data portion of t= he SPI cycle.=0D + @param[out] Buffer The Pointer to caller-allocated buffer c= ontaining the dada received.=0D + It is the caller's responsibility to mak= e sure Buffer is large enough for the total number of bytes read.=0D +=0D + @retval EFI_SUCCESS Command succeed.=0D + @retval EFI_INVALID_PARAMETER The parameters specified are not valid.= =0D + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.= =0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SpiProtocolFlashRead (=0D + IN PCH_SPI_PROTOCOL *This,=0D + IN FLASH_REGION_TYPE FlashRegionType,=0D + IN UINT32 Address,=0D + IN UINT32 ByteCount,=0D + OUT UINT8 *Buffer=0D + );=0D +=0D +/**=0D + Write data to the flash part.=0D +=0D + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance= .=0D + @param[in] FlashRegionType The Flash Region type for flash cycle wh= ich is listed in the Descriptor.=0D + @param[in] Address The Flash Linear Address must fall withi= n a region for which BIOS has access permissions.=0D + @param[in] ByteCount Number of bytes in the data portion of t= he SPI cycle.=0D + @param[in] Buffer Pointer to caller-allocated buffer conta= ining the data sent during the SPI cycle.=0D +=0D + @retval EFI_SUCCESS Command succeed.=0D + @retval EFI_INVALID_PARAMETER The parameters specified are not valid.= =0D + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.= =0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SpiProtocolFlashWrite (=0D + IN PCH_SPI_PROTOCOL *This,=0D + IN FLASH_REGION_TYPE FlashRegionType,=0D + IN UINT32 Address,=0D + IN UINT32 ByteCount,=0D + IN UINT8 *Buffer=0D + );=0D +=0D +/**=0D + Erase some area on the flash part.=0D +=0D + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance= .=0D + @param[in] FlashRegionType The Flash Region type for flash cycle wh= ich is listed in the Descriptor.=0D + @param[in] Address The Flash Linear Address must fall withi= n a region for which BIOS has access permissions.=0D + @param[in] ByteCount Number of bytes in the data portion of t= he SPI cycle.=0D +=0D + @retval EFI_SUCCESS Command succeed.=0D + @retval EFI_INVALID_PARAMETER The parameters specified are not valid.= =0D + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.= =0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SpiProtocolFlashErase (=0D + IN PCH_SPI_PROTOCOL *This,=0D + IN FLASH_REGION_TYPE FlashRegionType,=0D + IN UINT32 Address,=0D + IN UINT32 ByteCount=0D + );=0D +=0D +/**=0D + Read SFDP data from the flash part.=0D +=0D + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance= .=0D + @param[in] ComponentNumber The Componen Number for chip select=0D + @param[in] Address The starting byte address for SFDP data = read.=0D + @param[in] ByteCount Number of bytes in SFDP data portion of = the SPI cycle=0D + @param[out] SfdpData The Pointer to caller-allocated buffer c= ontaining the SFDP data received=0D + It is the caller's responsibility to mak= e sure Buffer is large enough for the total number of bytes read=0D +=0D + @retval EFI_SUCCESS Command succeed.=0D + @retval EFI_INVALID_PARAMETER The parameters specified are not valid.= =0D + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.= =0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SpiProtocolFlashReadSfdp (=0D + IN PCH_SPI_PROTOCOL *This,=0D + IN UINT8 ComponentNumber,=0D + IN UINT32 Address,=0D + IN UINT32 ByteCount,=0D + OUT UINT8 *SfdpData=0D + );=0D +=0D +/**=0D + Read Jedec Id from the flash part.=0D +=0D + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance= .=0D + @param[in] ComponentNumber The Componen Number for chip select=0D + @param[in] ByteCount Number of bytes in JedecId data portion = of the SPI cycle, the data size is 3 typically=0D + @param[out] JedecId The Pointer to caller-allocated buffer c= ontaining JEDEC ID received=0D + It is the caller's responsibility to mak= e sure Buffer is large enough for the total number of bytes read.=0D +=0D + @retval EFI_SUCCESS Command succeed.=0D + @retval EFI_INVALID_PARAMETER The parameters specified are not valid.= =0D + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.= =0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SpiProtocolFlashReadJedecId (=0D + IN PCH_SPI_PROTOCOL *This,=0D + IN UINT8 ComponentNumber,=0D + IN UINT32 ByteCount,=0D + OUT UINT8 *JedecId=0D + );=0D +=0D +/**=0D + Write the status register in the flash part.=0D +=0D + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance= .=0D + @param[in] ByteCount Number of bytes in Status data portion o= f the SPI cycle, the data size is 1 typically=0D + @param[in] StatusValue The Pointer to caller-allocated buffer c= ontaining the value of Status register writing=0D +=0D + @retval EFI_SUCCESS Command succeed.=0D + @retval EFI_INVALID_PARAMETER The parameters specified are not valid.= =0D + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.= =0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SpiProtocolFlashWriteStatus (=0D + IN PCH_SPI_PROTOCOL *This,=0D + IN UINT32 ByteCount,=0D + IN UINT8 *StatusValue=0D + );=0D +=0D +/**=0D + Read status register in the flash part.=0D +=0D + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance= .=0D + @param[in] ByteCount Number of bytes in Status data portion o= f the SPI cycle, the data size is 1 typically=0D + @param[out] StatusValue The Pointer to caller-allocated buffer c= ontaining the value of Status register received.=0D +=0D + @retval EFI_SUCCESS Command succeed.=0D + @retval EFI_INVALID_PARAMETER The parameters specified are not valid.= =0D + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.= =0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SpiProtocolFlashReadStatus (=0D + IN PCH_SPI_PROTOCOL *This,=0D + IN UINT32 ByteCount,=0D + OUT UINT8 *StatusValue=0D + );=0D +=0D +/**=0D + Get the SPI region base and size, based on the enum type=0D +=0D + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance= .=0D + @param[in] FlashRegionType The Flash Region type for for the base a= ddress which is listed in the Descriptor.=0D + @param[out] BaseAddress The Flash Linear Address for the Region = 'n' Base=0D + @param[out] RegionSize The size for the Region 'n'=0D +=0D + @retval EFI_SUCCESS Read success=0D + @retval EFI_INVALID_PARAMETER Invalid region type given=0D + @retval EFI_DEVICE_ERROR The region is not used=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SpiProtocolGetRegionAddress (=0D + IN PCH_SPI_PROTOCOL *This,=0D + IN FLASH_REGION_TYPE FlashRegionType,=0D + OUT UINT32 *BaseAddress,=0D + OUT UINT32 *RegionSize=0D + );=0D +=0D +/**=0D + Read PCH Soft Strap Values=0D +=0D + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance= .=0D + @param[in] SoftStrapAddr PCH Soft Strap address offset from FPSBA= .=0D + @param[in] ByteCount Number of bytes in SoftStrap data portio= n of the SPI cycle=0D + @param[out] SoftStrapValue The Pointer to caller-allocated buffer c= ontaining PCH Soft Strap Value.=0D + If the value of ByteCount is 0, the data= type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Sof= t Strap Length=0D + It is the caller's responsibility to mak= e sure Buffer is large enough for the total number of bytes read.=0D +=0D + @retval EFI_SUCCESS Command succeed.=0D + @retval EFI_INVALID_PARAMETER The parameters specified are not valid.= =0D + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.= =0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SpiProtocolReadPchSoftStrap (=0D + IN PCH_SPI_PROTOCOL *This,=0D + IN UINT32 SoftStrapAddr,=0D + IN UINT32 ByteCount,=0D + OUT VOID *SoftStrapValue=0D + );=0D +=0D +/**=0D + Read CPU Soft Strap Values=0D +=0D + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance= .=0D + @param[in] SoftStrapAddr CPU Soft Strap address offset from FCPUS= BA.=0D + @param[in] ByteCount Number of bytes in SoftStrap data portio= n of the SPI cycle.=0D + @param[out] SoftStrapValue The Pointer to caller-allocated buffer c= ontaining CPU Soft Strap Value.=0D + If the value of ByteCount is 0, the data= type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Sof= t Strap Length=0D + It is the caller's responsibility to mak= e sure Buffer is large enough for the total number of bytes read.=0D +=0D + @retval EFI_SUCCESS Command succeed.=0D + @retval EFI_INVALID_PARAMETER The parameters specified are not valid.= =0D + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.= =0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SpiProtocolReadCpuSoftStrap (=0D + IN PCH_SPI_PROTOCOL *This,=0D + IN UINT32 SoftStrapAddr,=0D + IN UINT32 ByteCount,=0D + OUT VOID *SoftStrapValue=0D + );=0D +=0D +#endif=0D diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/R= egister/SpiRegs.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePr= ivate/Register/SpiRegs.h new file mode 100644 index 0000000000..8e2029500c --- /dev/null +++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Register= /SpiRegs.h @@ -0,0 +1,136 @@ +/** @file=0D + Register names for PCH SPI device.=0D +=0D + Conventions:=0D +=0D + - Register definition format:=0D + Prefix_[GenerationName]_[ComponentName]_SubsystemName_RegisterSpace_Re= gisterName=0D + - Prefix:=0D + Definitions beginning with "R_" are registers=0D + Definitions beginning with "B_" are bits within registers=0D + Definitions beginning with "V_" are meaningful values within the bits= =0D + Definitions beginning with "S_" are register size=0D + Definitions beginning with "N_" are the bit position=0D + - [GenerationName]:=0D + Three letter acronym of the generation is used (e.g. SKL,KBL,CNL etc.)= .=0D + Register name without GenerationName applies to all generations.=0D + - [ComponentName]:=0D + This field indicates the component name that the register belongs to (= e.g. PCH, SA etc.)=0D + Register name without ComponentName applies to all components.=0D + Register that is specific to -LP denoted by "_PCH_LP_" in component na= me.=0D + - SubsystemName:=0D + This field indicates the subsystem name of the component that the regi= ster belongs to=0D + (e.g. PCIE, USB, SATA, GPIO, PMC etc.).=0D + - RegisterSpace:=0D + MEM - MMIO space register of subsystem.=0D + IO - IO space register of subsystem.=0D + PCR - Private configuration register of subsystem.=0D + CFG - PCI configuration space register of subsystem.=0D + - RegisterName:=0D + Full register name.=0D +=0D + Copyright (c) 2021, Intel Corporation. All rights reserved.
=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +**/=0D +#ifndef _SPI_REGS_H_=0D +#define _SPI_REGS_H_=0D +=0D +//=0D +// SPI Registers=0D +//=0D +#define R_SPI_CFG_BAR0 0x10=0D +#define B_SPI_CFG_BAR0_MASK 0x0FFF=0D +=0D +#define R_SPI_CFG_BDE 0xD8=0D +=0D +#define R_SPI_CFG_BC 0xDC=0D +#define S_SPI_CFG_BC 4=0D +#define N_SPI_CFG_BC_ASE_BWP 11=0D +#define B_SPI_CFG_BC_ASE_BWP BIT11=0D +#define N_SPI_CFG_BC_ASYNC_SS 10=0D +#define B_SPI_CFG_BC_ASYNC_SS BIT10=0D +#define N_SPI_CFG_BC_SYNC_SS 8=0D +#define B_SPI_CFG_BC_SYNC_SS BIT8=0D +#define B_SPI_CFG_BC_BILD BIT7=0D +#define B_SPI_CFG_BC_BBS BIT6 ///< Boot BIOS= strap=0D +#define N_SPI_CFG_BC_BBS 6=0D +#define V_SPI_CFG_BC_BBS_SPI 0 ///< Boot BIOS= strapped to SPI=0D +#define B_SPI_CFG_BC_EISS BIT5 ///< Enable In= SMM.STS=0D +#define B_SPI_CFG_BC_TSS BIT4=0D +#define B_SPI_CFG_BC_SRC (BIT3 | BIT2)=0D +#define N_SPI_CFG_BC_SRC 2=0D +#define V_SPI_CFG_BC_SRC_PREF_DIS_CACHE_DIS 0x01 ///< No prefet= ching and no caching=0D +#define B_SPI_CFG_BC_LE BIT1 ///< Lock Enab= le=0D +#define N_SPI_CFG_BC_BLE 1=0D +#define B_SPI_CFG_BC_WPD BIT0 ///< Write Pro= tect Disable=0D +=0D +//=0D +// BIOS Flash Program Registers (based on SPI_BAR0)=0D +//=0D +#define R_SPI_MEM_HSFSC 0x04 = ///< Hardware Sequencing Flash Status and Control Register(32bits)=0D +#define B_SPI_MEM_HSFSC_FDBC_MASK 0x3F000000 = ///< Flash Data Byte Count ( <=3D 64), Count =3D (Value in this field) + 1.= =0D +#define N_SPI_MEM_HSFSC_FDBC 24=0D +#define B_SPI_MEM_HSFSC_CYCLE_MASK 0x001E0000 = ///< Flash Cycle.=0D +#define N_SPI_MEM_HSFSC_CYCLE 17=0D +#define V_SPI_MEM_HSFSC_CYCLE_READ 0 = ///< Flash Cycle Read=0D +#define V_SPI_MEM_HSFSC_CYCLE_WRITE 2 = ///< Flash Cycle Write=0D +#define V_SPI_MEM_HSFSC_CYCLE_4K_ERASE 3 = ///< Flash Cycle 4K Block Erase=0D +#define V_SPI_MEM_HSFSC_CYCLE_64K_ERASE 4 = ///< Flash Cycle 64K Sector Erase=0D +#define V_SPI_MEM_HSFSC_CYCLE_READ_SFDP 5 = ///< Flash Cycle Read SFDP=0D +#define V_SPI_MEM_HSFSC_CYCLE_READ_JEDEC_ID 6 = ///< Flash Cycle Read JEDEC ID=0D +#define V_SPI_MEM_HSFSC_CYCLE_WRITE_STATUS 7 = ///< Flash Cycle Write Status=0D +#define V_SPI_MEM_HSFSC_CYCLE_READ_STATUS 8 = ///< Flash Cycle Read Status=0D +#define B_SPI_MEM_HSFSC_CYCLE_FGO BIT16 = ///< Flash Cycle Go.=0D +#define B_SPI_MEM_HSFSC_FLOCKDN BIT15 = ///< Flash Configuration Lock-Down=0D +#define B_SPI_MEM_HSFSC_FDV BIT14 = ///< Flash Descriptor Valid, once valid software can use hareware sequencin= g regs=0D +#define B_SPI_MEM_HSFSC_FDOPSS BIT13 = ///< Flash Descriptor Override Pin-Strap Status=0D +#define B_SPI_MEM_HSFSC_WRSDIS BIT11 = ///< Write Status Disable=0D +#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=0D +#define B_SPI_MEM_HSFSC_SCIP BIT5 = ///< SPI cycle in progress=0D +#define B_SPI_MEM_HSFSC_SAF_DLE BIT4 = ///< SAF Data length error=0D +#define B_SPI_MEM_HSFSC_SAF_ERROR BIT3 = ///< SAF Error=0D +#define B_SPI_MEM_HSFSC_AEL BIT2 = ///< Access Error Log=0D +#define B_SPI_MEM_HSFSC_FCERR BIT1 = ///< Flash Cycle Error=0D +#define B_SPI_MEM_HSFSC_FDONE BIT0 = ///< Flash Cycle Done=0D +#define R_SPI_MEM_FADDR 0x08 = ///< SPI Flash Address=0D +#define B_SPI_MEM_FADDR_MASK 0x07FFFFFF = ///< SPI Flash Address Mask (0~26bit)=0D +#define R_SPI_MEM_DLOCK 0x0C = ///< Discrete Lock Bits=0D +#define B_SPI_MEM_DLOCK_PR0LOCKDN BIT8 = ///< PR0LOCKDN=0D +#define R_SPI_MEM_FDATA00 0x10 = ///< SPI Data 00 (32 bits)=0D +#define R_SPI_MEM_FRAP 0x50 = ///< Flash Region Access Permissions Register=0D +#define B_SPI_MEM_FRAP_BRWA_MASK 0x0000FF00 = ///< BIOS Region Write Access MASK, Region0~7 - 0: Flash Descriptor; 1: BIO= S; 2: ME; 3: GbE; 4: PlatformData=0D +#define N_SPI_MEM_FRAP_BRWA 8 = ///< BIOS Region Write Access bit position=0D +#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=0D +#define B_SPI_MEM_FRAP_BMRAG_MASK 0x00FF0000 = ///< BIOS Master Read Access Grant=0D +#define B_SPI_MEM_FRAP_BMWAG_MASK 0xFF000000 = ///< BIOS Master Write Access Grant=0D +#define R_SPI_MEM_FREG0_FLASHD 0x54 = ///< Flash Region 0(Flash Descriptor)(32bits)=0D +#define R_SPI_MEM_FREG3_GBE 0x60 = ///< Flash Region 3(GbE)(32bits)=0D +#define S_SPI_MEM_FREGX 4 = ///< Size of Flash Region register=0D +#define B_SPI_MEM_FREGX_LIMIT_MASK 0x7FFF0000 = ///< Flash Region Limit [30:16] represents [26:12], [11:0] are assumed to b= e FFFh=0D +#define N_SPI_MEM_FREGX_LIMIT 16 = ///< Region limit bit position=0D +#define N_SPI_MEM_FREGX_LIMIT_REPR 12 = ///< Region limit bit represents position=0D +#define B_SPI_MEM_FREGX_BASE_MASK 0x00007FFF = ///< Flash Region Base, [14:0] represents [26:12]=0D +#define N_SPI_MEM_FREGX_BASE 0 = ///< Region base bit position=0D +#define N_SPI_MEM_FREGX_BASE_REPR 12 = ///< Region base bit represents position=0D +#define R_SPI_MEM_PR0 0x84 = ///< Protected Region 0 Register=0D +#define S_SPI_MEM_PRX 4 = ///< Protected Region X Register size=0D +#define B_SPI_MEM_PRX_WPE BIT31 = ///< Write Protection Enable=0D +#define B_SPI_MEM_PRX_PRL_MASK 0x7FFF0000 = ///< Protected Range Limit Mask, [30:16] here represents upper limit of add= ress [26:12]=0D +#define N_SPI_MEM_PRX_PRL 16 = ///< Protected Range Limit bit position=0D +#define B_SPI_MEM_PRX_RPE BIT15 = ///< Read Protection Enable=0D +#define B_SPI_MEM_PRX_PRB_MASK 0x00007FFF = ///< Protected Range Base Mask, [14:0] here represents base limit of addres= s [26:12]=0D +#define N_SPI_MEM_PRX_PRB 0 = ///< Protected Range Base bit position=0D +#define R_SPI_MEM_FDOC 0xB4 = ///< Flash Descriptor Observability Control Register(32 bits)=0D +#define B_SPI_MEM_FDOC_FDSS_MASK (BIT14 | BIT13 | BIT12) = ///< Flash Descritor Section Select=0D +#define V_SPI_MEM_FDOC_FDSS_FSDM 0x0000 = ///< Flash Signature and Descriptor Map=0D +#define V_SPI_MEM_FDOC_FDSS_COMP 0x1000 = ///< Component=0D +#define V_SPI_MEM_FDOC_FDSS_MSTR 0x3000 = ///< Master=0D +#define B_SPI_MEM_FDOC_FDSI_MASK 0x0FFC = ///< Flash Descriptor Section Index=0D +#define R_SPI_MEM_FDOD 0xB8 = ///< Flash Descriptor Observability Data Register(32 bits)=0D +#define R_SPI_MEM_SFDP0_VSCC0 0xC4 = ///< Vendor Specific Component Capabilities Register(32 bits)=0D +#define B_SPI_MEM_SFDPX_VSCCX_CPPTV BIT31 = ///< Component Property Parameter Table Valid=0D +#define B_SPI_MEM_SFDP0_VSCC0_VCL BIT30 = ///< Vendor Component Lock=0D +#define B_SPI_MEM_SFDPX_VSCCX_EO_64K BIT29 = ///< 64k Erase valid (EO_64k_valid)=0D +#define R_SPI_MEM_SFDP1_VSCC1 0xC8 = ///< Vendor Specific Component Capabilities Register(32 bits)=0D +=0D +#endif=0D diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Library/PeiDxeSm= mSpiAccessLib/PeiDxeSmmSpiAccessLib.inf b/Silicon/Intel/TigerlakeSiliconPkg= /IpBlock/Spi/Library/PeiDxeSmmSpiAccessLib/PeiDxeSmmSpiAccessLib.inf new file mode 100644 index 0000000000..bba0b1fef3 --- /dev/null +++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Library/PeiDxeSmmSpiAcc= essLib/PeiDxeSmmSpiAccessLib.inf @@ -0,0 +1,33 @@ +## @file=0D +# Component description file for PCH SPI access library=0D +#=0D +# Copyright (c) 2021, Intel Corporation. All rights reserved.
=0D +# SPDX-License-Identifier: BSD-2-Clause-Patent=0D +#=0D +##=0D +=0D +=0D +[Defines]=0D +INF_VERSION =3D 0x00010017=0D +BASE_NAME =3D PeiDxeSmmSpiAccessLib=0D +FILE_GUID =3D A6D4C05A-F6CB-46D5-4BA1-8C47B139DCA6=0D +VERSION_STRING =3D 1.0=0D +MODULE_TYPE =3D BASE=0D +LIBRARY_CLASS =3D SpiAccessLib=0D +=0D +=0D +[LibraryClasses]=0D +BaseLib=0D +IoLib=0D +DebugLib=0D +PciSegmentLib=0D +PchPciBdfLib=0D +PchPcrLib=0D +=0D +[Packages]=0D +MdePkg/MdePkg.dec=0D +TigerlakeSiliconPkg/SiPkg.dec=0D +=0D +=0D +[Sources]=0D +SpiAccessLib.c=0D diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Library/PeiDxeSm= mSpiAccessLib/SpiAccessLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Sp= i/Library/PeiDxeSmmSpiAccessLib/SpiAccessLib.c new file mode 100644 index 0000000000..c91b9aaf4d --- /dev/null +++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Library/PeiDxeSmmSpiAcc= essLib/SpiAccessLib.c @@ -0,0 +1,477 @@ +/** @file=0D + SPI library for abstraction of SPI HW registers accesses=0D +=0D + Copyright (c) 2021, Intel Corporation. All rights reserved.
=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +**/=0D +=0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +=0D +/**=0D + Checks if PCH SPI Controler is present and available=0D +=0D + @retval TRUE PCH SPI controller is avaialable=0D + @retval FALSE PCH SPI controller is not available=0D +**/=0D +BOOLEAN=0D +SpiIsControllerAvailable (=0D + VOID=0D + )=0D +{=0D + //=0D + // Checks for SPI controller=0D + //=0D + return (PciSegmentRead16 (SpiPciCfgBase () + PCI_VENDOR_ID_OFFSET) !=3D = 0xFFFF);=0D +}=0D +=0D +/**=0D + Returns PCH SPI BAR0 value=0D +=0D + @retval UINT32 PCH SPI BAR0 value=0D +**/=0D +UINT32=0D +SpiGetBar0 (=0D + VOID=0D + )=0D +{=0D + UINT32 SpiBar0;=0D +=0D + ASSERT (SpiIsControllerAvailable ());=0D + SpiBar0 =3D PciSegmentRead32 (SpiPciCfgBase () + R_SPI_CFG_BAR0) & ~B_SP= I_CFG_BAR0_MASK;=0D + ASSERT (SpiBar0 !=3D 0);=0D +=0D + return SpiBar0;=0D +}=0D +=0D +/**=0D + Reads given descriptor section and returns value=0D +=0D + @param[in] UINT16 Descriptor section=0D + @param[in] UINT16 Offset=0D +=0D + @retval UINT32 Read value from a section under given offset=0D +**/=0D +STATIC=0D +UINT32=0D +SpiReadDescriptor (=0D + IN UINT16 DescriptorSection,=0D + IN UINT16 Offset=0D + )=0D +{=0D + UINT32 SpiBar0;=0D + SpiBar0 =3D SpiGetBar0 ();=0D +=0D + MmioWrite32 (SpiBar0 + R_SPI_MEM_FDOC, (DescriptorSection | Offset));=0D + return MmioRead32 (SpiBar0 + R_SPI_MEM_FDOD);=0D +}=0D +=0D +/**=0D + Returns descriptor signature=0D +=0D + @retval UINT32 Descriptor signature=0D +**/=0D +UINT32=0D +SpiGetDescriptorSignature (=0D + VOID=0D + )=0D +{=0D + //=0D + // Read Descriptor offset 0x10 - To get Descriptor Signature=0D + // Signature section 0x0000 + offset 0x0 which points to Descriptor offs= et 0x10=0D + //=0D + return SpiReadDescriptor (V_SPI_MEM_FDOC_FDSS_FSDM, 0x0);=0D +}=0D +=0D +/**=0D + Returns supported features and R/W frequencies of Flash Component=0D +=0D + @retval UINT32 Flash Component features descriptor=0D +**/=0D +UINT32=0D +SpiGetFlashComponentDescription (=0D + VOID=0D + )=0D +{=0D + //=0D + // Read Descriptor offset 0x30 - To get supported features and R/W frequ= encies=0D + // Component section 0x1000 + offset 0x0 which points to Descriptor offs= et 0x30=0D + //=0D + return SpiReadDescriptor (V_SPI_MEM_FDOC_FDSS_COMP, 0x0);=0D +}=0D +=0D +/**=0D + Returns number of Flash Components=0D +=0D + @retval UINT32 Flash components number=0D +**/=0D +UINT32=0D +SpiGetFlashComponentsNumber (=0D + VOID=0D + )=0D +{=0D + //=0D + // Read Descriptor offset 0x14 - To get number of components=0D + // Signature section 0x0000 + offset 0x4 which points to Descriptor offs= et 0x14=0D + //=0D + return ((SpiReadDescriptor (V_SPI_MEM_FDOC_FDSS_FSDM, R_FLASH_FDBAR_FLAS= H_MAP0) & B_FLASH_FDBAR_NC) >> N_FLASH_FDBAR_NC);=0D +}=0D +=0D +/**=0D + Returns total Flash size with regards to number of flash components=0D +=0D + @retval UINT32 Total Flash Memory size=0D +**/=0D +UINT32=0D +SpiGetTotalFlashSize (=0D + VOID=0D + )=0D +{=0D + UINT32 Data32;=0D + UINT32 ComponentsNumber;=0D + UINT32 TotalFlashSize;=0D +=0D + Data32 =3D SpiGetFlashComponentDescription ();=0D + ComponentsNumber =3D SpiGetFlashComponentsNumber ();=0D +=0D + TotalFlashSize =3D (V_FLASH_FLCOMP_COMP_512KB << ((UINT8) (Data32 & B_FL= ASH_FLCOMP_COMP0_MASK)));=0D + if (ComponentsNumber =3D=3D 1) {=0D + TotalFlashSize +=3D (V_FLASH_FLCOMP_COMP_512KB << ((UINT8) ((Data32 & = B_FLASH_FLCOMP_COMP1_MASK) >> 4)));=0D + }=0D +=0D + return TotalFlashSize;=0D +}=0D +=0D +/**=0D + Checks BIOS lock bits for proper value and checks if write protection is= enabled=0D + Expected vales are: LE bit set, EISS bit set and WPD bit cleared=0D +=0D + @retval TRUE All protection bits are set correctly=0D + @retval FALSE Not all protection bits had exepcted values=0D +**/=0D +BOOLEAN=0D +SpiIsWriteProtectionEnabled (=0D + VOID=0D + )=0D +{=0D + UINT32 BiosControl;=0D + BiosControl =3D PciSegmentRead32 (SpiPciCfgBase () + R_SPI_CFG_BC);=0D +=0D + DEBUG ((DEBUG_INFO, "SPI BIOS CONTROL LE: %x\n", (BiosControl & B_SPI_CF= G_BC_LE) !=3D 0 ));=0D + DEBUG ((DEBUG_INFO, "SPI BIOS CONTROL WPD: %x\n", (BiosControl & B_SPI_C= FG_BC_WPD) !=3D 0 ));=0D + DEBUG ((DEBUG_INFO, "SPI BIOS CONTROL EISS: %x\n", (BiosControl & B_SPI_= CFG_BC_EISS) !=3D 0 ));=0D +=0D + return (((BiosControl & B_SPI_CFG_BC_LE) !=3D 0) &&=0D + ((BiosControl & B_SPI_CFG_BC_WPD) =3D=3D 0) &&=0D + ((BiosControl & B_SPI_CFG_BC_EISS) !=3D 0));=0D +}=0D +=0D +/**=0D + Returns status of BIOS Interface Lockdown=0D +=0D + @retval TRUE BIOS Interface Lockdown is enabled=0D + @retval FALSE BIOS Interface Lockdown is disabled=0D +**/=0D +BOOLEAN=0D +SpiIsBiosInterfaceLockdownEnabled (=0D + VOID=0D + )=0D +{=0D + return !!(PciSegmentRead32 (SpiPciCfgBase () + R_SPI_CFG_BC) & B_SPI_CFG= _BC_BILD);=0D +}=0D +=0D +/**=0D + Returns Flash Descriptor Override Pin Strap status=0D +=0D + @retval TRUE Flash Descriptor override is enabled=0D + @retval FALSE Flash Descriptor override is disabled=0D +**/=0D +BOOLEAN=0D +SpiIsFlashDescriptorOverrideEnabled (=0D + VOID=0D + )=0D +{=0D + UINT32 SpiBar0;=0D + SpiBar0 =3D SpiGetBar0 ();=0D +=0D + return !!(MmioRead16 (SpiBar0 + R_SPI_MEM_HSFSC) & B_SPI_MEM_HSFSC_FDOPS= S);=0D +}=0D +=0D +/**=0D + Returns Flash Configuration Lock Down bit status=0D +=0D + @retval TRUE Flash Configuration Lock Down bit is set=0D + @retval FALSE Flash Configuration Lock Down bit is not set=0D +**/=0D +BOOLEAN=0D +SpiIsFlashConfigurationLockDownEnabled (=0D + VOID=0D + )=0D +{=0D + UINT32 SpiBar0;=0D + SpiBar0 =3D SpiGetBar0 ();=0D +=0D + return !!(MmioRead16 (SpiBar0 + R_SPI_MEM_HSFSC) & B_SPI_MEM_HSFSC_FLOCK= DN);=0D +}=0D +=0D +/**=0D + Returns Top Swap functionality enable state=0D +=0D + @retval TRUE Top Swap is enabled=0D + @retval FALSE Top Swap is disabled=0D +**/=0D +BOOLEAN=0D +SpiIsTopSwapEnabled (=0D + VOID=0D + )=0D +{=0D + return !!(PciSegmentRead32 (SpiPciCfgBase () + R_SPI_CFG_BC) & B_SPI_CFG= _BC_TSS);=0D +}=0D +=0D +/**=0D + Return Component Property Parameter Table for a given component number=0D +=0D + @param[in] ComponentNumber SPI Component number=0D + @param[out] CppTable Component Poperty Parameter Table value=0D +=0D + @retval TRUE Vendor Specific Component Capabilities Register value was = read=0D + @reval FALSE Vendor Specific Component Capabilities Register value was = not present=0D +**/=0D +BOOLEAN=0D +SpiGetComponentPropertyParameterTable (=0D + IN UINT8 ComponentNumber,=0D + OUT UINT32 *CppTable=0D + )=0D +{=0D + UINT32 SpiBar0;=0D + UINT32 Data32;=0D + SpiBar0 =3D SpiGetBar0 ();=0D +=0D + //=0D + // More than 2 components not supported=0D + //=0D + switch (ComponentNumber) {=0D + case 0:=0D + *CppTable =3D MmioRead32 (SpiBar0 + R_SPI_MEM_SFDP0_VSCC0);=0D + return TRUE;=0D + case 1:=0D + Data32 =3D SpiReadDescriptor (V_SPI_MEM_FDOC_FDSS_FSDM, R_FLASH_F= DBAR_FLASH_MAP0);=0D + *CppTable =3D MmioRead32 (SpiBar0 + R_SPI_MEM_SFDP1_VSCC1);=0D + return !!(Data32 & BIT8);=0D + default:=0D + return FALSE;=0D + }=0D +}=0D +=0D +/**=0D + Returns valid bit status in given Component Property Parameter Table=0D +=0D + @param[in] CppTable Component Poperty Parameter Table value=0D +=0D + @retval TRUE Valid bit is set=0D + @reval FALSE Valid bit is not set=0D +**/=0D +BOOLEAN=0D +SpiIsCppValidBitSet (=0D + IN UINT32 CppTable=0D + )=0D +{=0D + return !!(CppTable & B_SPI_MEM_SFDPX_VSCCX_CPPTV);=0D +}=0D +=0D +/**=0D + Checks if Flash Descriptor is valid=0D +=0D + @retval TRUE Flash Descriptor is valid=0D + @retval FALSE Flash Descriptor is invalid=0D +**/=0D +BOOLEAN=0D +SpiIsFlashDescriptorValid (=0D + VOID=0D + )=0D +{=0D + UINT32 SpiBar0;=0D + SpiBar0 =3D SpiGetBar0 ();=0D +=0D + return !!(MmioRead32 (SpiBar0 + R_SPI_MEM_HSFSC) & B_SPI_MEM_HSFSC_FDV);= =0D +}=0D +=0D +/**=0D + Reads and returns value from Flash Region Access Permissions Register (F= RAP)=0D +=0D + @retval UINT32 Flash Region Access Permissions Register value=0D +**/=0D +STATIC=0D +UINT32=0D +SpiGetFlashRegionAccessPermissions (=0D + VOID=0D + )=0D +{=0D + return MmioRead32 (SpiGetBar0 () + R_SPI_MEM_FRAP);=0D +}=0D +=0D +/**=0D + Returns masked BIOS Master Read Access=0D +=0D + @retval UINT32 Already masked BIOS Master Read Access=0D +**/=0D +UINT32=0D +SpiGetMasterReadAccess (=0D + VOID=0D + )=0D +{=0D + UINT32 Data32;=0D + Data32 =3D SpiGetFlashRegionAccessPermissions () & B_SPI_MEM_FRAP_BMRAG_= MASK;=0D + DEBUG ((DEBUG_INFO, "BMRAG 0x%x\n", Data32));=0D +=0D + return Data32;=0D +}=0D +=0D +/**=0D + Returns masked BIOS Master Write Access=0D +=0D + @retval UINT32 Already masked BIOS Master Write Access=0D +**/=0D +UINT32=0D +SpiGetMasterWriteAccess (=0D + VOID=0D + )=0D +{=0D + UINT32 Data32;=0D + Data32 =3D SpiGetFlashRegionAccessPermissions () & B_SPI_MEM_FRAP_BMWAG_= MASK;=0D + DEBUG ((DEBUG_INFO, "BMWAG 0x%x\n", Data32));=0D +=0D + return Data32;=0D +}=0D +=0D +/**=0D + Returns GbE Region Access rights=0D +=0D + @retval UINT32 GbE Region access rights=0D +**/=0D +UINT32=0D +SpiGetGbeRegionAccess (=0D + VOID=0D + )=0D +{=0D + UINT32 Data32;=0D +=0D + Data32 =3D SpiReadDescriptor (V_SPI_MEM_FDOC_FDSS_MSTR, 0x8);=0D + DEBUG ((DEBUG_INFO, "GbE Region Access 0x%x\n", Data32));=0D +=0D + return Data32;=0D +}=0D +=0D +/**=0D + Returns CSME region access rights=0D +=0D + @retval UINT32 CSME Region Access rights=0D +**/=0D +UINT32=0D +SpiGetCsmeRegionAccess (=0D + VOID=0D + )=0D +{=0D + UINT32 Data32;=0D +=0D + Data32 =3D SpiReadDescriptor (V_SPI_MEM_FDOC_FDSS_MSTR, 0x4);=0D + DEBUG ((DEBUG_INFO, "CSME Region Access 0x%x\n", Data32));=0D +=0D + return Data32;=0D +}=0D +=0D +/**=0D + Returns EC region access right=0D +=0D + @retval UINT32 EC Region access rights=0D +**/=0D +UINT32=0D +SpiGetEcRegionAccess (=0D + VOID=0D + )=0D +{=0D + UINT32 Data32;=0D +=0D + Data32 =3D SpiReadDescriptor (V_SPI_MEM_FDOC_FDSS_MSTR, 0x10);=0D + DEBUG ((DEBUG_INFO, "EC Region Access 0x%x\n", Data32));=0D +=0D + return Data32;=0D +}=0D +=0D +/**=0D + Checks if Slave Attached Flash (SAF) mode is active=0D +=0D + @retval TRUE SAF mode is active=0D + @retval FALSE SAF mode is not active=0D +**/=0D +BOOLEAN=0D +SpiIsSafModeActive (=0D + VOID=0D + )=0D +{=0D + UINT32 SpiBar0;=0D + SpiBar0 =3D SpiGetBar0 ();=0D +=0D + return !!(MmioRead32 (SpiBar0 + R_SPI_MEM_HSFSC) & B_SPI_MEM_HSFSC_SAF_M= ODE_ACTIVE);=0D +}=0D +=0D +/**=0D + Checks validity of GbE region=0D +=0D + @retval TRUE GbE region is valid=0D + @retval FALSE GbE regios in invalid=0D +**/=0D +BOOLEAN=0D +SpiIsGbeRegionValid (=0D + VOID=0D + )=0D +{=0D + UINT32 SpiBar0;=0D + SpiBar0 =3D SpiGetBar0 ();=0D +=0D + if (MmioRead32 (SpiBar0 + R_SPI_MEM_FREG3_GBE) !=3D B_SPI_MEM_FREGX_BASE= _MASK) {=0D + return TRUE;=0D + }=0D + return FALSE;=0D +}=0D +=0D +/**=0D + Returns TRUE if BIOS Boot Strap is set to SPI=0D +=0D + @retval TRUE BIOS Boot strap is set to SPI=0D + @retval FALSE BIOS Boot strap is set to LPC/eSPI=0D +**/=0D +BOOLEAN=0D +SpiIsBiosBootFromSpi (=0D + VOID=0D + )=0D +{=0D + return !!(((PciSegmentRead8 (SpiPciCfgBase () + R_SPI_CFG_BC) & B_SPI_CF= G_BC_BBS) >> N_SPI_CFG_BC_BBS) =3D=3D V_SPI_CFG_BC_BBS_SPI);=0D +}=0D +=0D +/**=0D + Check SPI write status disable is set=0D +=0D + @retval TRUE Write status disable is set=0D + @retval FALSE Write status disable is not set=0D +**/=0D +BOOLEAN=0D +SpiIsWriteStatusDisable (=0D + VOID=0D + )=0D +{=0D + return !!(MmioRead32 (SpiGetBar0 () + R_SPI_MEM_HSFSC) & B_SPI_MEM_HSFSC= _WRSDIS);=0D +}=0D diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/B= aseSpiCommonLib/BaseSpiCommonLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/Ip= Block/Spi/LibraryPrivate/BaseSpiCommonLib/BaseSpiCommonLib.inf new file mode 100644 index 0000000000..a1a5467745 --- /dev/null +++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/BaseSpiC= ommonLib/BaseSpiCommonLib.inf @@ -0,0 +1,31 @@ +## @file=0D +# Component description file for the PchSpiCommonLib=0D +#=0D +# Copyright (c) 2021, Intel Corporation. All rights reserved.
=0D +# SPDX-License-Identifier: BSD-2-Clause-Patent=0D +#=0D +##=0D +=0D +[Defines]=0D + INF_VERSION =3D 0x00010005=0D + BASE_NAME =3D BaseSpiCommonLib=0D + FILE_GUID =3D A37CB67E-7D85-45B3-B07E-BF65BDB603E8= =0D + MODULE_TYPE =3D BASE=0D + VERSION_STRING =3D 1.0=0D + LIBRARY_CLASS =3D SpiCommonLib=0D +=0D +[Sources]=0D + SpiCommon.c=0D +=0D +[Packages]=0D + MdePkg/MdePkg.dec=0D + TigerlakeSiliconPkg/SiPkg.dec=0D +=0D +[LibraryClasses]=0D + IoLib=0D + DebugLib=0D + PmcLib=0D + PchPciBdfLib=0D + SpiAccessLib=0D +=0D +[Pcd]=0D diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/B= aseSpiCommonLib/SpiCommon.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi= /LibraryPrivate/BaseSpiCommonLib/SpiCommon.c new file mode 100644 index 0000000000..954b349e7c --- /dev/null +++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/BaseSpiC= ommonLib/SpiCommon.c @@ -0,0 +1,1115 @@ +/** @file=0D + PCH SPI Common Driver implements the SPI Host Controller Compatibility I= nterface.=0D +=0D + Copyright (c) 2021, Intel Corporation. All rights reserved.
=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +**/=0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +=0D +/**=0D + Initialize an SPI protocol instance.=0D +=0D + @param[in] SpiInstance Pointer to SpiInstance to initialize=0D +=0D + @retval EFI_SUCCESS The protocol instance was properly initi= alized=0D + @exception EFI_UNSUPPORTED The PCH is not supported by this module= =0D +**/=0D +EFI_STATUS=0D +SpiProtocolConstructor (=0D + IN SPI_INSTANCE *SpiInstance=0D + )=0D +{=0D + UINTN PchSpiBar0;=0D + UINT32 Data32;=0D + UINT16 Mdtba;=0D + EFI_STATUS Status;=0D +=0D + //=0D + // Initialize the SPI protocol instance=0D + //=0D + SpiInstance->Signature =3D PCH_SPI_PRIVATE_DATA_SIGNA= TURE;=0D + SpiInstance->Handle =3D NULL;=0D + SpiInstance->SpiProtocol.Revision =3D PCH_SPI_SERVICES_REVISION;= =0D + SpiInstance->SpiProtocol.FlashRead =3D SpiProtocolFlashRead;=0D + SpiInstance->SpiProtocol.FlashWrite =3D SpiProtocolFlashWrite;=0D + SpiInstance->SpiProtocol.FlashErase =3D SpiProtocolFlashErase;=0D + SpiInstance->SpiProtocol.FlashReadSfdp =3D SpiProtocolFlashReadSfdp;= =0D + SpiInstance->SpiProtocol.FlashReadJedecId =3D SpiProtocolFlashReadJedecI= d;=0D + SpiInstance->SpiProtocol.FlashWriteStatus =3D SpiProtocolFlashWriteStatu= s;=0D + SpiInstance->SpiProtocol.FlashReadStatus =3D SpiProtocolFlashReadStatus= ;=0D + SpiInstance->SpiProtocol.GetRegionAddress =3D SpiProtocolGetRegionAddres= s;=0D + SpiInstance->SpiProtocol.ReadPchSoftStrap =3D SpiProtocolReadPchSoftStra= p;=0D + SpiInstance->SpiProtocol.ReadCpuSoftStrap =3D SpiProtocolReadCpuSoftStra= p;=0D +=0D + SpiInstance->PchSpiBase =3D SpiPciCfgBase ();=0D +=0D + SpiInstance->PchAcpiBase =3D PmcGetAcpiBase ();=0D + ASSERT (SpiInstance->PchAcpiBase !=3D 0);=0D +=0D + PchSpiBar0 =3D PciSegmentRead32 (SpiInstance->PchSpiBase + R_SPI_CFG_BAR= 0) & ~(B_SPI_CFG_BAR0_MASK);=0D + if (PchSpiBar0 =3D=3D 0) {=0D + DEBUG ((DEBUG_ERROR, "ERROR : PchSpiBar0 is invalid!\n"));=0D + ASSERT (FALSE);=0D + }=0D +=0D + if ((MmioRead32 (PchSpiBar0 + R_SPI_MEM_HSFSC) & B_SPI_MEM_HSFSC_FDV) = =3D=3D 0) {=0D + DEBUG ((DEBUG_ERROR, "ERROR : SPI Flash Signature invalid, cannot use = the Hardware Sequencing registers!\n"));=0D + ASSERT (FALSE);=0D + }=0D +=0D + //=0D + // Get Region 0 - 7 read Permission bits, region 8 and above are not per= mitted.=0D + //=0D + SpiInstance->ReadPermission =3D MmioRead8 (PchSpiBar0 + R_SPI_MEM_FRAP) = & B_SPI_MEM_FRAP_BRRA_MASK;=0D + DEBUG ((DEBUG_INFO, "Flash Region read Permission : %0x\n", SpiInstance-= >ReadPermission));=0D + //=0D + // Get Region 0 - 7 write Permission bits, region 8 and above are not pe= rmitted.=0D + //=0D + SpiInstance->WritePermission =3D (UINT8) ((MmioRead16 (PchSpiBar0 + R_SP= I_MEM_FRAP) &=0D + B_SPI_MEM_FRAP_BRWA_MASK) >> N_= SPI_MEM_FRAP_BRWA);=0D + DEBUG ((DEBUG_INFO, "Flash Region write Permission : %0x\n", SpiInstance= ->WritePermission));=0D +=0D + SpiInstance->SfdpVscc0Value =3D MmioRead32 (PchSpiBar0 + R_SPI_MEM_SFDP0= _VSCC0);=0D + DEBUG ((DEBUG_INFO, "Component 0 SFDP VSCC value : %0x\n", SpiInstance->= SfdpVscc0Value));=0D + SpiInstance->SfdpVscc1Value =3D MmioRead32 (PchSpiBar0 + R_SPI_MEM_SFDP1= _VSCC1);=0D + DEBUG ((DEBUG_INFO, "Component 1 SFDP VSCC value : %0x\n", SpiInstance->= SfdpVscc1Value));=0D +=0D + //=0D + // Select to Flash Map 0 Register to get the number of flash Component=0D + //=0D + MmioAndThenOr32 (=0D + PchSpiBar0 + R_SPI_MEM_FDOC,=0D + (UINT32) (~(B_SPI_MEM_FDOC_FDSS_MASK | B_SPI_MEM_FDOC_FDSI_MASK)),=0D + (UINT32) (V_SPI_MEM_FDOC_FDSS_FSDM | R_FLASH_FDBAR_FLASH_MAP0)=0D + );=0D +=0D + //=0D + // Copy Zero based Number Of Components=0D + //=0D + SpiInstance->NumberOfComponents =3D (UINT8) ((MmioRead16 (PchSpiBar0 + R= _SPI_MEM_FDOD) & B_FLASH_FDBAR_NC) >> N_FLASH_FDBAR_NC);=0D + DEBUG ((DEBUG_INFO, "Component Number : %0x\n", SpiInstance->NumberOfCom= ponents + 1));=0D +=0D + MmioAndThenOr32 (=0D + PchSpiBar0 + R_SPI_MEM_FDOC,=0D + (UINT32) (~(B_SPI_MEM_FDOC_FDSS_MASK | B_SPI_MEM_FDOC_FDSI_MASK)),=0D + (UINT32) (V_SPI_MEM_FDOC_FDSS_COMP | R_FLASH_FCBA_FLCOMP)=0D + );=0D +=0D + //=0D + // Copy Component 0 Density=0D + //=0D + Data32 =3D MmioRead32 (PchSpiBar0 + R_SPI_MEM_FDOD);=0D + if (SpiInstance->NumberOfComponents > 0) {=0D + SpiInstance->Component1StartAddr =3D V_FLASH_FLCOMP_COMP_512KB <<=0D + (Data32 & B_FLASH_FLCOMP_COMP0_MASK);=0D + DEBUG ((DEBUG_INFO, "Component 1 StartAddr : %0x\n", SpiInstance->Comp= onent1StartAddr));=0D + SpiInstance->TotalFlashSize =3D SpiInstance->Component1StartAddr +=0D + (V_FLASH_FLCOMP_COMP_512KB <<=0D + ((Data32 & B_FLASH_FLCOMP_COMP1_MASK) >>=0D + N_FLASH_FLCOMP_COMP1));=0D + } else {=0D + SpiInstance->TotalFlashSize =3D V_FLASH_FLCOMP_COMP_512KB <<=0D + (Data32 & B_FLASH_FLCOMP_COMP0_MASK);=0D + }=0D + DEBUG ((DEBUG_INFO, "Total Flash Size : %0x\n", SpiInstance->TotalFlashS= ize));=0D +=0D + //=0D + // Select FLASH_MAP1 to get Flash PCH Strap Base Address=0D + //=0D + MmioAndThenOr32 (=0D + (PchSpiBar0 + R_SPI_MEM_FDOC),=0D + (UINT32) (~(B_SPI_MEM_FDOC_FDSS_MASK | B_SPI_MEM_FDOC_FDSI_MASK)),=0D + (UINT32) (V_SPI_MEM_FDOC_FDSS_FSDM | R_FLASH_FDBAR_FLASH_MAP1)=0D + );=0D + //=0D + // Align FPSBA with address bits for the PCH Strap portion of flash desc= riptor=0D + //=0D + Data32 =3D MmioRead32 (PchSpiBar0 + R_SPI_MEM_FDOD);=0D + SpiInstance->PchStrapBaseAddr =3D (UINT16) (((Data32 & B_FLASH_FDBAR_FPS= BA)=0D + >> N_FLASH_FDBAR_FPSBA)=0D + << N_FLASH_FDBAR_FPSBA_REPR);= =0D + DEBUG ((DEBUG_INFO, "PchStrapBaseAddr : %0x\n", SpiInstance->PchStrapBas= eAddr));=0D + ASSERT (SpiInstance->PchStrapBaseAddr !=3D 0);=0D + //=0D + // PCH Strap Length, [31:24] represents number of Dwords=0D + //=0D + SpiInstance->PchStrapSize =3D (UINT16) (((Data32 & B_FLASH_FDBAR_PCHSL)= =0D + >> N_FLASH_FDBAR_PCHSL)=0D + * sizeof (UINT32));=0D + DEBUG ((DEBUG_INFO, "PchStrapSize : %0x\n", SpiInstance->PchStrapSize));= =0D +=0D + //=0D + // Select FLASH_MAP2 to get Flash CPU Strap Base Address=0D + //=0D + MmioAndThenOr32 (=0D + (PchSpiBar0 + R_SPI_MEM_FDOC),=0D + (UINT32) (~(B_SPI_MEM_FDOC_FDSS_MASK | B_SPI_MEM_FDOC_FDSI_MASK)),=0D + (UINT32) (V_SPI_MEM_FDOC_FDSS_FSDM | R_FLASH_FDBAR_FLASH_MAP2)=0D + );=0D + //=0D + // Align FPSBA with address bits for the CPU Strap portion of flash desc= riptor=0D + //=0D + Data32 =3D MmioRead32 (PchSpiBar0 + R_SPI_MEM_FDOD);=0D + //=0D + // CPU Strap Length, [23:16] represents number of Dwords=0D + //=0D + SpiInstance->CpuStrapSize =3D (UINT16) (((Data32 & B_FLASH_FDBAR_CPUSL)= =0D + >> N_FLASH_FDBAR_CPUSL)=0D + * sizeof (UINT32));=0D +=0D + //=0D + // CPU Strap Address [11:2] represent offset from MDTBA=0D + //=0D + SpiInstance->CpuStrapBaseAddr =3D (UINT16) ((Data32 & B_FLASH_FDBAR_FCPU= SBA) >> N_FLASH_FDBAR_FCPUSBA);=0D + ASSERT (SpiInstance->CpuStrapBaseAddr !=3D 0);=0D +=0D + if (SpiInstance->CpuStrapBaseAddr !=3D 0x300) {=0D + Status =3D SpiProtocolFlashRead (&(SpiInstance->SpiProtocol), FlashReg= ionAll, R_FLASH_UMAP1, sizeof (Data32), (UINT8 *) (&Data32));=0D + ASSERT_EFI_ERROR (Status);=0D + Mdtba =3D (UINT16)(((Data32 & B_FLASH_UMAP1_MDTBA) >> N_FLASH_UMAP1_MD= TBA) << N_FLASH_UMAP1_MDTBA_REPR);=0D + DEBUG ((DEBUG_INFO, "Mdtba : %0x\n", Mdtba));=0D + // Add MDTBA offset for final address of CPU Straps=0D + SpiInstance->CpuStrapBaseAddr +=3D Mdtba;=0D + }=0D +=0D + DEBUG ((DEBUG_INFO, "CpuStrapBaseAddr : %0x\n", SpiInstance->CpuStrapBas= eAddr));=0D + DEBUG ((DEBUG_INFO, "CpuStrapSize : %0x\n", SpiInstance->CpuStrapSize));= =0D +=0D + return EFI_SUCCESS;=0D +}=0D +=0D +/**=0D + Delay for at least the request number of microseconds for Runtime usage.= =0D +=0D + @param[in] ABase Acpi base address=0D + @param[in] Microseconds Number of microseconds to delay.=0D +=0D +**/=0D +VOID=0D +EFIAPI=0D +PchPmTimerStallRuntimeSafe (=0D + IN UINT16 ABase,=0D + IN UINTN Microseconds=0D + )=0D +{=0D + UINTN Ticks;=0D + UINTN Counts;=0D + UINTN CurrentTick;=0D + UINTN OriginalTick;=0D + UINTN RemainingTick;=0D +=0D + if (Microseconds =3D=3D 0) {=0D + return;=0D + }=0D +=0D + OriginalTick =3D IoRead32 ((UINTN) (ABase + R_ACPI_IO_PM1_TMR)) & B_AC= PI_IO_PM1_TMR_VAL;=0D + CurrentTick =3D OriginalTick;=0D +=0D + //=0D + // The timer frequency is 3.579545 MHz, so 1 ms corresponds 3.58 clocks= =0D + //=0D + Ticks =3D Microseconds * 358 / 100 + OriginalTick + 1;=0D +=0D + //=0D + // The loops needed by timer overflow=0D + //=0D + Counts =3D Ticks / V_ACPI_IO_PM1_TMR_MAX_VAL;=0D +=0D + //=0D + // Remaining clocks within one loop=0D + //=0D + RemainingTick =3D Ticks % V_ACPI_IO_PM1_TMR_MAX_VAL;=0D +=0D + //=0D + // not intend to use TMROF_STS bit of register PM1_STS, because this add= s extra=0D + // one I/O operation, and maybe generate SMI=0D + //=0D + while ((Counts !=3D 0) || (RemainingTick > CurrentTick)) {=0D + CurrentTick =3D IoRead32 ((UINTN) (ABase + R_ACPI_IO_PM1_TMR)) & B_ACP= I_IO_PM1_TMR_VAL;=0D + //=0D + // Check if timer overflow=0D + //=0D + if ((CurrentTick < OriginalTick)) {=0D + if (Counts !=3D 0) {=0D + Counts--;=0D + } else {=0D + //=0D + // If timer overflow and Counts equ to 0, that means we already st= alled more than=0D + // RemainingTick, break the loop here=0D + //=0D + break;=0D + }=0D + }=0D +=0D + OriginalTick =3D CurrentTick;=0D + }=0D +}=0D +=0D +/**=0D + Wait execution cycle to complete on the SPI interface.=0D +=0D + @param[in] This The SPI protocol instance=0D + @param[in] PchSpiBar0 Spi MMIO base address=0D + @param[in] ErrorCheck TRUE if the SpiCycle needs to do the err= or check=0D +=0D + @retval TRUE SPI cycle completed on the interface.=0D + @retval FALSE Time out while waiting the SPI cycle to = complete.=0D + It's not safe to program the next comman= d on the SPI interface.=0D +**/=0D +STATIC=0D +BOOLEAN=0D +WaitForSpiCycleComplete (=0D + IN PCH_SPI_PROTOCOL *This,=0D + IN UINTN PchSpiBar0,=0D + IN BOOLEAN ErrorCheck=0D + )=0D +{=0D + UINT64 WaitTicks;=0D + UINT64 WaitCount;=0D + UINT32 Data32;=0D + SPI_INSTANCE *SpiInstance;=0D +=0D + SpiInstance =3D SPI_INSTANCE_FROM_SPIPROTOCOL (This);=0D +=0D + //=0D + // Convert the wait period allowed into to tick count=0D + //=0D + WaitCount =3D SPI_WAIT_TIME / SPI_WAIT_PERIOD;=0D + //=0D + // Wait for the SPI cycle to complete.=0D + //=0D + for (WaitTicks =3D 0; WaitTicks < WaitCount; WaitTicks++) {=0D + Data32 =3D MmioRead32 (PchSpiBar0 + R_SPI_MEM_HSFSC);=0D + if ((Data32 & B_SPI_MEM_HSFSC_SCIP) =3D=3D 0) {=0D + MmioWrite32 (PchSpiBar0 + R_SPI_MEM_HSFSC, B_SPI_MEM_HSFSC_FCERR | B= _SPI_MEM_HSFSC_FDONE);=0D + if (((Data32 & B_SPI_MEM_HSFSC_FCERR) !=3D 0) && (ErrorCheck =3D=3D = TRUE)) {=0D + return FALSE;=0D + } else {=0D + return TRUE;=0D + }=0D + }=0D + PchPmTimerStallRuntimeSafe (SpiInstance->PchAcpiBase, SPI_WAIT_PERIOD)= ;=0D + }=0D + return FALSE;=0D +}=0D +=0D +/**=0D + This function sends the programmed SPI command to the slave device.=0D +=0D + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance= .=0D + @param[in] SpiRegionType The SPI Region type for flash cycle whic= h is listed in the Descriptor=0D + @param[in] FlashCycleType The Flash SPI cycle type list in HSFC (H= ardware Sequencing Flash Control Register) register=0D + @param[in] Address The Flash Linear Address must fall withi= n a region for which BIOS has access permissions.=0D + @param[in] ByteCount Number of bytes in the data portion of t= he SPI cycle.=0D + @param[in,out] Buffer Pointer to caller-allocated buffer conta= ining the dada received or sent during the SPI cycle.=0D +=0D + @retval EFI_SUCCESS SPI command completes successfully.=0D + @retval EFI_DEVICE_ERROR Device error, the command aborts abnorma= lly.=0D + @retval EFI_ACCESS_DENIED Some unrecognized or blocked command enc= ountered in hardware sequencing mode=0D + @retval EFI_INVALID_PARAMETER The parameters specified are not valid.= =0D +**/=0D +STATIC=0D +EFI_STATUS=0D +SendSpiCmd (=0D + IN PCH_SPI_PROTOCOL *This,=0D + IN FLASH_REGION_TYPE FlashRegionType,=0D + IN FLASH_CYCLE_TYPE FlashCycleType,=0D + IN UINT32 Address,=0D + IN UINT32 ByteCount,=0D + IN OUT UINT8 *Buffer=0D + )=0D +{=0D + EFI_STATUS Status;=0D + UINT32 Index;=0D + SPI_INSTANCE *SpiInstance;=0D + UINT64 SpiBaseAddress;=0D + UINTN PchSpiBar0;=0D + UINT32 HardwareSpiAddr;=0D + UINT32 FlashRegionSize;=0D + UINT32 SpiDataCount;=0D + UINT32 FlashCycle;=0D + UINT8 BiosCtlSave;=0D + UINT32 SmiEnSave;=0D + UINT16 ABase;=0D + UINT32 HsfstsCtl;=0D +=0D + //=0D + // For flash write, there is a requirement that all CPU threads are in S= MM=0D + // before the flash protection is disabled.=0D + //=0D + if ((FlashCycleType =3D=3D FlashCycleWrite) || (FlashCycleType =3D=3D Fl= ashCycleErase)) {=0D + if (!IsSpiFlashWriteGranted ()) {=0D + return EFI_ACCESS_DENIED;=0D + }=0D + }=0D +=0D + Status =3D EFI_SUCCESS;=0D + SpiInstance =3D SPI_INSTANCE_FROM_SPIPROTOCOL (This);=0D + SpiBaseAddress =3D SpiInstance->PchSpiBase;=0D + PchSpiBar0 =3D AcquireSpiBar0 (SpiInstance);=0D + ABase =3D SpiInstance->PchAcpiBase;=0D +=0D + //=0D + // Disable SMIs to make sure normal mode flash access is not interrupted= by an SMI=0D + // whose SMI handler accesses flash (e.g. for error logging)=0D + //=0D + // *** NOTE: if the SMI_LOCK bit is set (i.e., PMC PCI Offset A0h [4]=3D= '1'),=0D + // clearing B_GBL_SMI_EN will not have effect. In this situation, some o= ther=0D + // synchronization methods must be applied here or in the consumer of th= e=0D + // SendSpiCmd. An example method is disabling the specific SMI sources=0D + // whose SMI handlers access flash before flash cycle and re-enabling th= e SMI=0D + // sources after the flash cycle .=0D + //=0D + SmiEnSave =3D IoRead32 ((UINTN) (ABase + R_ACPI_IO_SMI_EN));=0D + IoWrite32 ((UINTN) (ABase + R_ACPI_IO_SMI_EN), SmiEnSave & (UINT32) (~B_= ACPI_IO_SMI_EN_GBL_SMI));=0D + BiosCtlSave =3D PciSegmentRead8 (SpiBaseAddress + R_SPI_CFG_BC) & B_SPI_= CFG_BC_SRC;=0D +=0D + //=0D + // If it's write cycle, disable Prefetching, Caching and disable BIOS Wr= ite Protect=0D + //=0D + if ((FlashCycleType =3D=3D FlashCycleWrite) ||=0D + (FlashCycleType =3D=3D FlashCycleErase)) {=0D + Status =3D DisableBiosWriteProtect ();=0D + if (EFI_ERROR (Status)) {=0D + goto SendSpiCmdEnd;=0D + }=0D + PciSegmentAndThenOr8 (=0D + SpiBaseAddress + R_SPI_CFG_BC,=0D + (UINT8) (~B_SPI_CFG_BC_SRC),=0D + (UINT8) (V_SPI_CFG_BC_SRC_PREF_DIS_CACHE_DIS << N_SPI_CFG_BC_SRC)=0D + );=0D + }=0D + //=0D + // Make sure it's safe to program the command.=0D + //=0D + if (!WaitForSpiCycleComplete (This, PchSpiBar0, FALSE)) {=0D + Status =3D EFI_DEVICE_ERROR;=0D + goto SendSpiCmdEnd;=0D + }=0D +=0D + //=0D + // Check if Write Status isn't disabled in HW Sequencing=0D + //=0D + if (FlashCycleType =3D=3D FlashCycleWriteStatus) {=0D + HsfstsCtl =3D MmioRead32 (PchSpiBar0 + R_SPI_MEM_HSFSC);=0D + if ((HsfstsCtl & B_SPI_MEM_HSFSC_WRSDIS) !=3D 0) {=0D + Status =3D EFI_ACCESS_DENIED;=0D + goto SendSpiCmdEnd;=0D + }=0D + }=0D +=0D + Status =3D SpiProtocolGetRegionAddress (This, FlashRegionType, &Hardware= SpiAddr, &FlashRegionSize);=0D + if (EFI_ERROR (Status)) {=0D + goto SendSpiCmdEnd;=0D + }=0D + HardwareSpiAddr +=3D Address;=0D + if ((Address + ByteCount) > FlashRegionSize) {=0D + Status =3D EFI_INVALID_PARAMETER;=0D + goto SendSpiCmdEnd;=0D + }=0D +=0D + //=0D + // Check for PCH SPI hardware sequencing required commands=0D + //=0D + FlashCycle =3D 0;=0D + switch (FlashCycleType) {=0D + case FlashCycleRead:=0D + FlashCycle =3D (UINT32) (V_SPI_MEM_HSFSC_CYCLE_READ << N_SPI_MEM_HSF= SC_CYCLE);=0D + break;=0D + case FlashCycleWrite:=0D + FlashCycle =3D (UINT32) (V_SPI_MEM_HSFSC_CYCLE_WRITE << N_SPI_MEM_HS= FSC_CYCLE);=0D + break;=0D + case FlashCycleErase:=0D + if (((ByteCount % SIZE_4KB) !=3D 0) ||=0D + ((HardwareSpiAddr % SIZE_4KB) !=3D 0)) {=0D + ASSERT (FALSE);=0D + Status =3D EFI_INVALID_PARAMETER;=0D + goto SendSpiCmdEnd;=0D + }=0D + break;=0D + case FlashCycleReadSfdp:=0D + FlashCycle =3D (UINT32) (V_SPI_MEM_HSFSC_CYCLE_READ_SFDP << N_SPI_ME= M_HSFSC_CYCLE);=0D + break;=0D + case FlashCycleReadJedecId:=0D + FlashCycle =3D (UINT32) (V_SPI_MEM_HSFSC_CYCLE_READ_JEDEC_ID << N_SP= I_MEM_HSFSC_CYCLE);=0D + break;=0D + case FlashCycleWriteStatus:=0D + FlashCycle =3D (UINT32) (V_SPI_MEM_HSFSC_CYCLE_WRITE_STATUS << N_SPI= _MEM_HSFSC_CYCLE);=0D + break;=0D + case FlashCycleReadStatus:=0D + FlashCycle =3D (UINT32) (V_SPI_MEM_HSFSC_CYCLE_READ_STATUS << N_SPI_= MEM_HSFSC_CYCLE);=0D + break;=0D + default:=0D + //=0D + // Unrecognized Operation=0D + //=0D + ASSERT (FALSE);=0D + Status =3D EFI_INVALID_PARAMETER;=0D + goto SendSpiCmdEnd;=0D + break;=0D + }=0D +=0D + do {=0D + SpiDataCount =3D ByteCount;=0D + if ((FlashCycleType =3D=3D FlashCycleRead) ||=0D + (FlashCycleType =3D=3D FlashCycleWrite) ||=0D + (FlashCycleType =3D=3D FlashCycleReadSfdp)) {=0D + //=0D + // Trim at 256 byte boundary per operation,=0D + // - PCH SPI controller requires trimming at 4KB boundary=0D + // - Some SPI chips require trimming at 256 byte boundary for write = operation=0D + // - Trimming has limited performance impact as we can read / write = atmost 64 byte=0D + // per operation=0D + //=0D + if (HardwareSpiAddr + ByteCount > ((HardwareSpiAddr + BIT8) &~(BIT8 = - 1))) {=0D + SpiDataCount =3D (((UINT32) (HardwareSpiAddr) + BIT8) &~(BIT8 - 1)= ) - (UINT32) (HardwareSpiAddr);=0D + }=0D + //=0D + // Calculate the number of bytes to shift in/out during the SPI data= cycle.=0D + // Valid settings for the number of bytes duing each data portion of= the=0D + // PCH SPI cycles are: 0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 24, 32, 40, 48= , 56, 64=0D + //=0D + if (SpiDataCount >=3D 64) {=0D + SpiDataCount =3D 64;=0D + } else if ((SpiDataCount &~0x07) !=3D 0) {=0D + SpiDataCount =3D SpiDataCount &~0x07;=0D + }=0D + }=0D + if (FlashCycleType =3D=3D FlashCycleErase) {=0D + if (((ByteCount / SIZE_64KB) !=3D 0) &&=0D + ((ByteCount % SIZE_64KB) =3D=3D 0) &&=0D + ((HardwareSpiAddr % SIZE_64KB) =3D=3D 0)) {=0D + if ((SpiInstance->NumberOfComponents =3D=3D 0) ||=0D + (HardwareSpiAddr < SpiInstance->Component1StartAddr)) {=0D + //=0D + // Check whether Component0 support 64k Erase=0D + //=0D + if ((SpiInstance->SfdpVscc0Value & B_SPI_MEM_SFDPX_VSCCX_EO_64K)= !=3D 0) {=0D + SpiDataCount =3D SIZE_64KB;=0D + } else {=0D + SpiDataCount =3D SIZE_4KB;=0D + }=0D + } else {=0D + //=0D + // Check whether Component1 support 64k Erase=0D + //=0D + if ((SpiInstance->SfdpVscc1Value & B_SPI_MEM_SFDPX_VSCCX_EO_64K)= !=3D 0) {=0D + SpiDataCount =3D SIZE_64KB;=0D + } else {=0D + SpiDataCount =3D SIZE_4KB;=0D + }=0D + }=0D + } else {=0D + SpiDataCount =3D SIZE_4KB;=0D + }=0D + if (SpiDataCount =3D=3D SIZE_4KB) {=0D + FlashCycle =3D (UINT32) (V_SPI_MEM_HSFSC_CYCLE_4K_ERASE << N_SPI_M= EM_HSFSC_CYCLE);=0D + } else {=0D + FlashCycle =3D (UINT32) (V_SPI_MEM_HSFSC_CYCLE_64K_ERASE << N_SPI_= MEM_HSFSC_CYCLE);=0D + }=0D + }=0D + //=0D + // If it's write cycle, load data into the SPI data buffer.=0D + //=0D + if ((FlashCycleType =3D=3D FlashCycleWrite) || (FlashCycleType =3D=3D = FlashCycleWriteStatus)) {=0D + if ((SpiDataCount & 0x07) !=3D 0) {=0D + //=0D + // Use Byte write if Data Count is 0, 1, 2, 3, 4, 5, 6, 7=0D + //=0D + for (Index =3D 0; Index < SpiDataCount; Index++) {=0D + MmioWrite8 (PchSpiBar0 + R_SPI_MEM_FDATA00 + Index, Buffer[Index= ]);=0D + }=0D + } else {=0D + //=0D + // Use Dword write if Data Count is 8, 16, 24, 32, 40, 48, 56, 64= =0D + //=0D + for (Index =3D 0; Index < SpiDataCount; Index +=3D sizeof (UINT32)= ) {=0D + MmioWrite32 (PchSpiBar0 + R_SPI_MEM_FDATA00 + Index, *(UINT32 *)= (Buffer + Index));=0D + }=0D + }=0D + }=0D +=0D + //=0D + // Set the Flash Address=0D + //=0D + MmioWrite32 (=0D + (PchSpiBar0 + R_SPI_MEM_FADDR),=0D + (UINT32) (HardwareSpiAddr & B_SPI_MEM_FADDR_MASK)=0D + );=0D +=0D + //=0D + // Set Data count, Flash cycle, and Set Go bit to start a cycle=0D + //=0D + MmioAndThenOr32 (=0D + PchSpiBar0 + R_SPI_MEM_HSFSC,=0D + (UINT32) (~(B_SPI_MEM_HSFSC_FDBC_MASK | B_SPI_MEM_HSFSC_CYCLE_MASK))= ,=0D + (UINT32) ((((SpiDataCount - 1) << N_SPI_MEM_HSFSC_FDBC) & B_SPI_MEM_= HSFSC_FDBC_MASK) | FlashCycle | B_SPI_MEM_HSFSC_CYCLE_FGO)=0D + );=0D + //=0D + // end of command execution=0D + //=0D + // Wait the SPI cycle to complete.=0D + //=0D + if (!WaitForSpiCycleComplete (This, PchSpiBar0, TRUE)) {=0D + ASSERT (FALSE);=0D + Status =3D EFI_DEVICE_ERROR;=0D + goto SendSpiCmdEnd;=0D + }=0D + //=0D + // If it's read cycle, load data into the call's buffer.=0D + //=0D + if ((FlashCycleType =3D=3D FlashCycleRead) ||=0D + (FlashCycleType =3D=3D FlashCycleReadSfdp) ||=0D + (FlashCycleType =3D=3D FlashCycleReadJedecId) ||=0D + (FlashCycleType =3D=3D FlashCycleReadStatus)) {=0D + if ((SpiDataCount & 0x07) !=3D 0) {=0D + //=0D + // Use Byte read if Data Count is 0, 1, 2, 3, 4, 5, 6, 7=0D + //=0D + for (Index =3D 0; Index < SpiDataCount; Index++) {=0D + Buffer[Index] =3D MmioRead8 (PchSpiBar0 + R_SPI_MEM_FDATA00 + In= dex);=0D + }=0D + } else {=0D + //=0D + // Use Dword read if Data Count is 8, 16, 24, 32, 40, 48, 56, 64=0D + //=0D + for (Index =3D 0; Index < SpiDataCount; Index +=3D sizeof (UINT32)= ) {=0D + *(UINT32 *) (Buffer + Index) =3D MmioRead32 (PchSpiBar0 + R_SPI_= MEM_FDATA00 + Index);=0D + }=0D + }=0D + }=0D +=0D + HardwareSpiAddr +=3D SpiDataCount;=0D + Buffer +=3D SpiDataCount;=0D + ByteCount -=3D SpiDataCount;=0D + } while (ByteCount > 0);=0D +=0D +SendSpiCmdEnd:=0D + //=0D + // Restore the settings for SPI Prefetching and Caching and enable BIOS = Write Protect=0D + //=0D + if ((FlashCycleType =3D=3D FlashCycleWrite) ||=0D + (FlashCycleType =3D=3D FlashCycleErase)) {=0D + EnableBiosWriteProtect ();=0D + PciSegmentAndThenOr8 (=0D + SpiBaseAddress + R_SPI_CFG_BC,=0D + (UINT8) ~B_SPI_CFG_BC_SRC,=0D + BiosCtlSave=0D + );=0D + }=0D + //=0D + // Restore SMIs.=0D + //=0D + IoWrite32 ((UINTN) (ABase + R_ACPI_IO_SMI_EN), SmiEnSave);=0D +=0D + ReleaseSpiBar0 (SpiInstance);=0D +=0D + return Status;=0D +}=0D +=0D +/**=0D + Read data from the flash part.=0D +=0D + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance= .=0D + @param[in] FlashRegionType The Flash Region type for flash cycle wh= ich is listed in the Descriptor.=0D + @param[in] Address The Flash Linear Address must fall withi= n a region for which BIOS has access permissions.=0D + @param[in] ByteCount Number of bytes in the data portion of t= he SPI cycle.=0D + @param[out] Buffer The Pointer to caller-allocated buffer c= ontaining the dada received.=0D + It is the caller's responsibility to mak= e sure Buffer is large enough for the total number of bytes read.=0D +=0D + @retval EFI_SUCCESS Command succeed.=0D + @retval EFI_INVALID_PARAMETER The parameters specified are not valid.= =0D + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.= =0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SpiProtocolFlashRead (=0D + IN PCH_SPI_PROTOCOL *This,=0D + IN FLASH_REGION_TYPE FlashRegionType,=0D + IN UINT32 Address,=0D + IN UINT32 ByteCount,=0D + OUT UINT8 *Buffer=0D + )=0D +{=0D + EFI_STATUS Status;=0D +=0D + //=0D + // Sends the command to the SPI interface to execute.=0D + //=0D + Status =3D SendSpiCmd (=0D + This,=0D + FlashRegionType,=0D + FlashCycleRead,=0D + Address,=0D + ByteCount,=0D + Buffer=0D + );=0D + return Status;=0D +}=0D +=0D +/**=0D + Write data to the flash part.=0D +=0D + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance= .=0D + @param[in] FlashRegionType The Flash Region type for flash cycle wh= ich is listed in the Descriptor.=0D + @param[in] Address The Flash Linear Address must fall withi= n a region for which BIOS has access permissions.=0D + @param[in] ByteCount Number of bytes in the data portion of t= he SPI cycle.=0D + @param[in] Buffer Pointer to caller-allocated buffer conta= ining the data sent during the SPI cycle.=0D +=0D + @retval EFI_SUCCESS Command succeed.=0D + @retval EFI_INVALID_PARAMETER The parameters specified are not valid.= =0D + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.= =0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SpiProtocolFlashWrite (=0D + IN PCH_SPI_PROTOCOL *This,=0D + IN FLASH_REGION_TYPE FlashRegionType,=0D + IN UINT32 Address,=0D + IN UINT32 ByteCount,=0D + IN UINT8 *Buffer=0D + )=0D +{=0D + EFI_STATUS Status;=0D +=0D + //=0D + // Sends the command to the SPI interface to execute.=0D + //=0D + Status =3D SendSpiCmd (=0D + This,=0D + FlashRegionType,=0D + FlashCycleWrite,=0D + Address,=0D + ByteCount,=0D + Buffer=0D + );=0D + return Status;=0D +}=0D +=0D +/**=0D + Erase some area on the flash part.=0D +=0D + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance= .=0D + @param[in] FlashRegionType The Flash Region type for flash cycle wh= ich is listed in the Descriptor.=0D + @param[in] Address The Flash Linear Address must fall withi= n a region for which BIOS has access permissions.=0D + @param[in] ByteCount Number of bytes in the data portion of t= he SPI cycle.=0D +=0D + @retval EFI_SUCCESS Command succeed.=0D + @retval EFI_INVALID_PARAMETER The parameters specified are not valid.= =0D + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.= =0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SpiProtocolFlashErase (=0D + IN PCH_SPI_PROTOCOL *This,=0D + IN FLASH_REGION_TYPE FlashRegionType,=0D + IN UINT32 Address,=0D + IN UINT32 ByteCount=0D + )=0D +{=0D + EFI_STATUS Status;=0D +=0D + //=0D + // Sends the command to the SPI interface to execute.=0D + //=0D + Status =3D SendSpiCmd (=0D + This,=0D + FlashRegionType,=0D + FlashCycleErase,=0D + Address,=0D + ByteCount,=0D + NULL=0D + );=0D + return Status;=0D +}=0D +=0D +/**=0D + Read SFDP data from the flash part.=0D +=0D + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance= .=0D + @param[in] ComponentNumber The Componen Number for chip select=0D + @param[in] Address The starting byte address for SFDP data = read.=0D + @param[in] ByteCount Number of bytes in SFDP data portion of = the SPI cycle=0D + @param[out] SfdpData The Pointer to caller-allocated buffer c= ontaining the SFDP data received=0D + It is the caller's responsibility to mak= e sure Buffer is large enough for the total number of bytes read=0D +=0D + @retval EFI_SUCCESS Command succeed.=0D + @retval EFI_INVALID_PARAMETER The parameters specified are not valid.= =0D + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.= =0D + @retval EFI_UNSUPPORTED Unsupported operation with SAF Mode enab= led=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SpiProtocolFlashReadSfdp (=0D + IN PCH_SPI_PROTOCOL *This,=0D + IN UINT8 ComponentNumber,=0D + IN UINT32 Address,=0D + IN UINT32 ByteCount,=0D + OUT UINT8 *SfdpData=0D + )=0D +{=0D + SPI_INSTANCE *SpiInstance;=0D + EFI_STATUS Status;=0D + UINT32 FlashAddress;=0D +=0D + if (SpiIsSafModeActive ()) {=0D + DEBUG ((DEBUG_ERROR, "Unallowed call to %a while SAF Mode is active.\n= ", __FUNCTION__));=0D + return EFI_UNSUPPORTED;=0D + }=0D +=0D + SpiInstance =3D SPI_INSTANCE_FROM_SPIPROTOCOL (This);=0D + Status =3D EFI_SUCCESS;=0D +=0D + if (ComponentNumber > SpiInstance->NumberOfComponents) {=0D + ASSERT (FALSE);=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + FlashAddress =3D 0;=0D + if (ComponentNumber =3D=3D FlashComponent1) {=0D + FlashAddress =3D SpiInstance->Component1StartAddr;=0D + }=0D + FlashAddress +=3D Address;=0D + //=0D + // Sends the command to the SPI interface to execute.=0D + //=0D + Status =3D SendSpiCmd (=0D + This,=0D + FlashRegionAll,=0D + FlashCycleReadSfdp,=0D + FlashAddress,=0D + ByteCount,=0D + SfdpData=0D + );=0D + return Status;=0D +}=0D +=0D +/**=0D + Read Jedec Id from the flash part.=0D +=0D + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance= .=0D + @param[in] ComponentNumber The Componen Number for chip select=0D + @param[in] ByteCount Number of bytes in JedecId data portion = of the SPI cycle, the data size is 3 typically=0D + @param[out] JedecId The Pointer to caller-allocated buffer c= ontaining JEDEC ID received=0D + It is the caller's responsibility to mak= e sure Buffer is large enough for the total number of bytes read.=0D +=0D + @retval EFI_SUCCESS Command succeed.=0D + @retval EFI_INVALID_PARAMETER The parameters specified are not valid.= =0D + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.= =0D + @retval EFI_UNSUPPORTED Unsupported operation with SAF Mode enab= led=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SpiProtocolFlashReadJedecId (=0D + IN PCH_SPI_PROTOCOL *This,=0D + IN UINT8 ComponentNumber,=0D + IN UINT32 ByteCount,=0D + OUT UINT8 *JedecId=0D + )=0D +{=0D + SPI_INSTANCE *SpiInstance;=0D + EFI_STATUS Status;=0D + UINT32 Address;=0D +=0D + if (SpiIsSafModeActive ()) {=0D + DEBUG ((DEBUG_ERROR, "Unallowed call to %a while SAF Mode is active.\n= ", __FUNCTION__));=0D + return EFI_UNSUPPORTED;=0D + }=0D +=0D + SpiInstance =3D SPI_INSTANCE_FROM_SPIPROTOCOL (This);=0D + Status =3D EFI_SUCCESS;=0D +=0D + if (ComponentNumber > SpiInstance->NumberOfComponents) {=0D + ASSERT (FALSE);=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + Address =3D 0;=0D + if (ComponentNumber =3D=3D FlashComponent1) {=0D + Address =3D SpiInstance->Component1StartAddr;=0D + }=0D +=0D + //=0D + // Sends the command to the SPI interface to execute.=0D + //=0D + Status =3D SendSpiCmd (=0D + This,=0D + FlashRegionAll,=0D + FlashCycleReadJedecId,=0D + Address,=0D + ByteCount,=0D + JedecId=0D + );=0D + return Status;=0D +}=0D +=0D +/**=0D + Write the status register in the flash part.=0D +=0D + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance= .=0D + @param[in] ByteCount Number of bytes in Status data portion o= f the SPI cycle, the data size is 1 typically=0D + @param[in] StatusValue The Pointer to caller-allocated buffer c= ontaining the value of Status register writing=0D +=0D + @retval EFI_SUCCESS Command succeed.=0D + @retval EFI_INVALID_PARAMETER The parameters specified are not valid.= =0D + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.= =0D + @retval EFI_UNSUPPORTED Unsupported operation with SAF Mode enab= led=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SpiProtocolFlashWriteStatus (=0D + IN PCH_SPI_PROTOCOL *This,=0D + IN UINT32 ByteCount,=0D + IN UINT8 *StatusValue=0D + )=0D +{=0D + EFI_STATUS Status;=0D +=0D + if (SpiIsSafModeActive ()) {=0D + DEBUG ((DEBUG_ERROR, "Unallowed call to %a while SAF Mode is active.\n= ", __FUNCTION__));=0D + return EFI_UNSUPPORTED;=0D + }=0D +=0D + //=0D + // Sends the command to the SPI interface to execute.=0D + //=0D + Status =3D SendSpiCmd (=0D + This,=0D + FlashRegionAll,=0D + FlashCycleWriteStatus,=0D + 0,=0D + ByteCount,=0D + StatusValue=0D + );=0D + return Status;=0D +}=0D +=0D +/**=0D + Read status register in the flash part.=0D +=0D + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance= .=0D + @param[in] ByteCount Number of bytes in Status data portion o= f the SPI cycle, the data size is 1 typically=0D + @param[out] StatusValue The Pointer to caller-allocated buffer c= ontaining the value of Status register received.=0D +=0D + @retval EFI_SUCCESS Command succeed.=0D + @retval EFI_INVALID_PARAMETER The parameters specified are not valid.= =0D + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.= =0D + @retval EFI_UNSUPPORTED Unsupported operation with SAF Mode enab= led=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SpiProtocolFlashReadStatus (=0D + IN PCH_SPI_PROTOCOL *This,=0D + IN UINT32 ByteCount,=0D + OUT UINT8 *StatusValue=0D + )=0D +{=0D + EFI_STATUS Status;=0D +=0D + if (SpiIsSafModeActive ()) {=0D + DEBUG ((DEBUG_ERROR, "Unallowed call to %a while SAF Mode is active.\n= ", __FUNCTION__));=0D + return EFI_UNSUPPORTED;=0D + }=0D +=0D + //=0D + // Sends the command to the SPI interface to execute.=0D + //=0D + Status =3D SendSpiCmd (=0D + This,=0D + FlashRegionAll,=0D + FlashCycleReadStatus,=0D + 0,=0D + ByteCount,=0D + StatusValue=0D + );=0D + return Status;=0D +}=0D +=0D +/**=0D + Get the SPI region base and size, based on the enum type=0D +=0D + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance= .=0D + @param[in] FlashRegionType The Flash Region type for for the base a= ddress which is listed in the Descriptor.=0D + @param[out] BaseAddress The Flash Linear Address for the Region = 'n' Base=0D + @param[out] RegionSize The size for the Region 'n'=0D +=0D + @retval EFI_SUCCESS Read success=0D + @retval EFI_INVALID_PARAMETER Invalid region type given=0D + @retval EFI_DEVICE_ERROR The region is not used=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SpiProtocolGetRegionAddress (=0D + IN PCH_SPI_PROTOCOL *This,=0D + IN FLASH_REGION_TYPE FlashRegionType,=0D + OUT UINT32 *BaseAddress,=0D + OUT UINT32 *RegionSize=0D + )=0D +{=0D + SPI_INSTANCE *SpiInstance;=0D + UINTN PchSpiBar0;=0D + UINT32 ReadValue;=0D +=0D + SpiInstance =3D SPI_INSTANCE_FROM_SPIPROTOCOL (This);=0D +=0D + if (FlashRegionType >=3D FlashRegionMax) {=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + if (FlashRegionType =3D=3D FlashRegionAll) {=0D + *BaseAddress =3D 0;=0D + *RegionSize =3D SpiInstance->TotalFlashSize;=0D + return EFI_SUCCESS;=0D + }=0D +=0D + PchSpiBar0 =3D AcquireSpiBar0 (SpiInstance);=0D + ReadValue =3D MmioRead32 (PchSpiBar0 + (R_SPI_MEM_FREG0_FLASHD + (S_SPI_= MEM_FREGX * ((UINT32) FlashRegionType))));=0D + ReleaseSpiBar0 (SpiInstance);=0D +=0D + //=0D + // If the region is not used, the Region Base is 7FFFh and Region Limit = is 0000h=0D + //=0D + if (ReadValue =3D=3D B_SPI_MEM_FREGX_BASE_MASK) {=0D + return EFI_DEVICE_ERROR;=0D + }=0D + *BaseAddress =3D ((ReadValue & B_SPI_MEM_FREGX_BASE_MASK) >> N_SPI_MEM_F= REGX_BASE) <<=0D + N_SPI_MEM_FREGX_BASE_REPR;=0D + //=0D + // Region limit address Bits[11:0] are assumed to be FFFh=0D + //=0D + *RegionSize =3D ((((ReadValue & B_SPI_MEM_FREGX_LIMIT_MASK) >> N_SPI_MEM= _FREGX_LIMIT) + 1) <<=0D + N_SPI_MEM_FREGX_LIMIT_REPR) - *BaseAddress;=0D +=0D + return EFI_SUCCESS;=0D +}=0D +=0D +/**=0D + Read PCH Soft Strap Values=0D +=0D + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance= .=0D + @param[in] SoftStrapAddr PCH Soft Strap address offset from FPSBA= .=0D + @param[in] ByteCount Number of bytes in SoftStrap data portio= n of the SPI cycle=0D + @param[out] SoftStrapValue The Pointer to caller-allocated buffer c= ontaining PCH Soft Strap Value.=0D + If the value of ByteCount is 0, the data= type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Sof= t Strap Length=0D + It is the caller's responsibility to mak= e sure Buffer is large enough for the total number of bytes read.=0D +=0D + @retval EFI_SUCCESS Command succeed.=0D + @retval EFI_INVALID_PARAMETER The parameters specified are not valid.= =0D + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.= =0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SpiProtocolReadPchSoftStrap (=0D + IN PCH_SPI_PROTOCOL *This,=0D + IN UINT32 SoftStrapAddr,=0D + IN UINT32 ByteCount,=0D + OUT VOID *SoftStrapValue=0D + )=0D +{=0D + SPI_INSTANCE *SpiInstance;=0D + UINT32 StrapFlashAddr;=0D + EFI_STATUS Status;=0D +=0D + SpiInstance =3D SPI_INSTANCE_FROM_SPIPROTOCOL (This);=0D +=0D + if (ByteCount =3D=3D 0) {=0D + *(UINT16 *) SoftStrapValue =3D SpiInstance->PchStrapSize;=0D + return EFI_SUCCESS;=0D + }=0D +=0D + if ((SoftStrapAddr + ByteCount) > (UINT32) SpiInstance->PchStrapSize) {= =0D + ASSERT (FALSE);=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + //=0D + // PCH Strap Flash Address =3D FPSBA + RamAddr=0D + //=0D + StrapFlashAddr =3D SpiInstance->PchStrapBaseAddr + SoftStrapAddr;=0D +=0D + //=0D + // Read PCH Soft straps from using execute command=0D + //=0D + Status =3D SendSpiCmd (=0D + This,=0D + FlashRegionDescriptor,=0D + FlashCycleRead,=0D + StrapFlashAddr,=0D + ByteCount,=0D + SoftStrapValue=0D + );=0D + return Status;=0D +}=0D +=0D +/**=0D + Read CPU Soft Strap Values=0D +=0D + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance= .=0D + @param[in] SoftStrapAddr CPU Soft Strap address offset from FCPUS= BA.=0D + @param[in] ByteCount Number of bytes in SoftStrap data portio= n of the SPI cycle.=0D + @param[out] SoftStrapValue The Pointer to caller-allocated buffer c= ontaining CPU Soft Strap Value.=0D + If the value of ByteCount is 0, the data= type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Sof= t Strap Length=0D + It is the caller's responsibility to mak= e sure Buffer is large enough for the total number of bytes read.=0D +=0D + @retval EFI_SUCCESS Command succeed.=0D + @retval EFI_INVALID_PARAMETER The parameters specified are not valid.= =0D + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.= =0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SpiProtocolReadCpuSoftStrap (=0D + IN PCH_SPI_PROTOCOL *This,=0D + IN UINT32 SoftStrapAddr,=0D + IN UINT32 ByteCount,=0D + OUT VOID *SoftStrapValue=0D + )=0D +{=0D + SPI_INSTANCE *SpiInstance;=0D + UINT32 StrapFlashAddr;=0D + EFI_STATUS Status;=0D +=0D + SpiInstance =3D SPI_INSTANCE_FROM_SPIPROTOCOL (This);=0D +=0D + if (ByteCount =3D=3D 0) {=0D + *(UINT16 *) SoftStrapValue =3D SpiInstance->CpuStrapSize;=0D + return EFI_SUCCESS;=0D + }=0D +=0D + if ((SoftStrapAddr + ByteCount) > (UINT32) SpiInstance->CpuStrapSize) {= =0D + ASSERT (FALSE);=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + //=0D + // CPU Strap Flash Address =3D FCPUSBA + RamAddr=0D + //=0D + StrapFlashAddr =3D SpiInstance->CpuStrapBaseAddr + SoftStrapAddr;=0D +=0D + //=0D + // Read Cpu Soft straps from using execute command=0D + //=0D + Status =3D SendSpiCmd (=0D + This,=0D + FlashRegionDescriptor,=0D + FlashCycleRead,=0D + StrapFlashAddr,=0D + ByteCount,=0D + SoftStrapValue=0D + );=0D + return Status;=0D +}=0D diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/P= eiDxeSmmSpiAccessPrivateLib/PeiDxeSmmSpiAccessPrivateLib.inf b/Silicon/Inte= l/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/PeiDxeSmmSpiAccessPrivateL= ib/PeiDxeSmmSpiAccessPrivateLib.inf new file mode 100644 index 0000000000..4e059494d8 --- /dev/null +++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/PeiDxeSm= mSpiAccessPrivateLib/PeiDxeSmmSpiAccessPrivateLib.inf @@ -0,0 +1,40 @@ +## @file=0D +# Component description file for PCH SPI access private library=0D +#=0D +# Copyright (c) 2021, Intel Corporation. All rights reserved.
=0D +# SPDX-License-Identifier: BSD-2-Clause-Patent=0D +#=0D +##=0D +=0D +=0D +[Defines]=0D +INF_VERSION =3D 0x00010017=0D +BASE_NAME =3D PeiDxeSmmSpiAccessPrivateLib=0D +FILE_GUID =3D 2CD382D7-9928-C32A-601D-69797C618A6D=0D +VERSION_STRING =3D 1.0=0D +MODULE_TYPE =3D BASE=0D +LIBRARY_CLASS =3D SpiAccessPrivateLib=0D +=0D +=0D +[LibraryClasses]=0D +BaseLib=0D +IoLib=0D +DebugLib=0D +PciSegmentLib=0D +SpiAccessLib=0D +PcdLib=0D +S3BootScriptLib=0D +PchPciBdfLib=0D +=0D +=0D +[Packages]=0D +MdePkg/MdePkg.dec=0D +TigerlakeSiliconPkg/SiPkg.dec=0D +=0D +=0D +[Sources]=0D +SpiAccessPrivateLib.c=0D +=0D +=0D +[Pcd]=0D +gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress=0D diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/P= eiDxeSmmSpiAccessPrivateLib/SpiAccessPrivateLib.c b/Silicon/Intel/Tigerlake= SiliconPkg/IpBlock/Spi/LibraryPrivate/PeiDxeSmmSpiAccessPrivateLib/SpiAcces= sPrivateLib.c new file mode 100644 index 0000000000..de1f3d3f86 --- /dev/null +++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/PeiDxeSm= mSpiAccessPrivateLib/SpiAccessPrivateLib.c @@ -0,0 +1,133 @@ +/** @file=0D + SPI library for abstraction of SPI HW registers accesses=0D +=0D + Copyright (c) 2021, Intel Corporation. All rights reserved.
=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +**/=0D +=0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +=0D +/**=0D + Disable EISS (Enable InSMM.STS)=0D +**/=0D +VOID=0D +SpiDisableEiss (=0D + VOID=0D + )=0D +{=0D + UINT64 SpiBaseAddress;=0D + SpiBaseAddress =3D SpiPciCfgBase ();=0D +=0D + ASSERT ((PciSegmentRead8 (SpiBaseAddress + R_SPI_CFG_BC) & B_SPI_CFG_BC_= LE) =3D=3D 0);=0D +=0D + PciSegmentAnd8 (SpiBaseAddress + R_SPI_CFG_BC, (UINT8) ~(B_SPI_CFG_BC_EI= SS));=0D +}=0D +=0D +/**=0D + Configure BiosLockEnable bit and BiosInterfaceLock bit according to poli= cy setting.=0D +=0D + @param[in] BiosLockEnable Policy for BiosLockEnable bit programming= =0D + @param[in] BiosInterfaceLock Policy for BiosInterfaceLock bit programmi= ng=0D +=0D +**/=0D +VOID=0D +SpiBiosLockEnableAndBiosInterfaceLockWithS3BootScript (=0D + IN BOOLEAN BiosLockEnable,=0D + IN BOOLEAN BiosInterfaceLock=0D + )=0D +{=0D + UINT64 SpiBaseAddress;=0D + UINT8 SpiData8;=0D +=0D + if (!BiosLockEnable && !BiosInterfaceLock) {=0D + return;=0D + }=0D +=0D + SpiBaseAddress =3D SpiPciCfgBase ();=0D +=0D + ///=0D + /// PCH BIOS Spec Flash Security Recommendation=0D + ///=0D + /// BIOS needs to enable the BIOS Lock Enable (BLE) feature of the PCH b= y setting=0D + /// SPI/eSPI/LPC PCI offset DCh[1] =3D 1b.=0D + /// When this bit is set, attempts to write the Write Protect Disable (W= PD) bit=0D + /// in PCH will cause a SMI which will allow the BIOS to verify that the= write is=0D + /// from a valid source.=0D + /// Remember that BIOS needs to set SPI/LPC/eSPI PCI Offset DC [0] =3D 0= b to enable=0D + /// BIOS region protection before exiting the SMI handler.=0D + /// Also, TCO_EN bit needs to be set (SMI_EN Register, ABASE + 30h[13] = =3D 1b) to keep=0D + /// BLE feature enabled after booting to the OS.=0D + /// Intel requires that BIOS enables the Lock Enable (LE) feature of the= PCH to=0D + /// ensure SMM protection of flash.=0D + /// RC installs a default SMI handler that clears WPD.=0D + /// There could be additional SMI handler to log such attempt if desired= .=0D + ///=0D + /// BIOS needs to enable the "Enable in SMM.STS" (EISS) feature of the P= CH by setting=0D + /// SPI PCI offset DCh[5] =3D 1b for SPI or setting eSPI PCI offset DCh[= 5] =3D 1b for eSPI.=0D + /// When this bit is set, the BIOS region is not writable until SMM sets= the InSMM.STS bit,=0D + /// to ensure BIOS can only be modified from SMM. Please refer to CPU BW= G for more details=0D + /// on InSMM.STS bit.=0D + /// Intel requires that BIOS enables the Lock Enable (LE) feature of the= PCH to ensure=0D + /// SMM protection of flash.=0D + /// SPI PCI offset DCh[1] =3D 1b for SPI or setting eSPI PCI offset DCh[= 1] =3D 1b for eSPI.=0D + /// When this bit is set, EISS is locked down.=0D + ///=0D + SpiData8 =3D 0;=0D + if (BiosLockEnable) {=0D + SpiData8 |=3D B_SPI_CFG_BC_EISS | B_SPI_CFG_BC_LE;=0D + }=0D + ///=0D + /// BIOS also needs to set the BIOS Interface Lock Down bit in multiple = locations=0D + /// (PCR[DMI] + 274Ch[0], LPC/eSPI PCI offset DCh[7] and SPI PCI offset = DCh[7]).=0D + /// (done in PchInit/Dxe/PchInit.c by PchDmiSetBiosLockDownWithS3BootScr= ipt ()) for PCR[DMI] 274Ch)=0D + /// Setting these bits will prevent writes to the Top Swap bit (under th= eir respective locations)=0D + /// and the Boot BIOS Straps. Enabling this bit will mitigate malicious = software=0D + /// attempts to replace the system BIOS option ROM with its own code.=0D + ///=0D + if (BiosInterfaceLock) {=0D + SpiData8 |=3D B_SPI_CFG_BC_BILD;=0D + }=0D +=0D + PciSegmentOr8 (SpiBaseAddress + R_SPI_CFG_BC, SpiData8);=0D + S3BootScriptSaveMemWrite (=0D + S3BootScriptWidthUint8,=0D + PcdGet64 (PcdPciExpressBaseAddress) + SpiBaseAddress + R_SPI_CFG_BC,=0D + 1,=0D + (VOID *) (UINTN) (PcdGet64 (PcdPciExpressBaseAddress) + SpiBaseAddress= + R_SPI_CFG_BC)=0D + );=0D + //=0D + // Reads back for posted write to take effect=0D + //=0D + SpiData8 =3D PciSegmentRead8 (SpiBaseAddress + R_SPI_CFG_BC);=0D + S3BootScriptSaveMemPoll (=0D + S3BootScriptWidthUint8,=0D + PcdGet64 (PcdPciExpressBaseAddress) + SpiBaseAddress + R_SPI_CFG_BC,=0D + &SpiData8,=0D + &SpiData8,=0D + 1,=0D + 1=0D + );=0D +}=0D +=0D +/**=0D + Clears BIOS Write Protect Disable bit=0D +**/=0D +VOID=0D +SpiClearBiosWriteProtectDisable (=0D + VOID=0D + )=0D +{=0D + //=0D + // Disable BIOSWE bit to protect BIOS=0D + //=0D + PciSegmentAnd8 (SpiPciCfgBase () + R_SPI_CFG_BC, (UINT8) ~B_SPI_CFG_BC_W= PD);=0D +}=0D diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Smm/Spi.c b/Sili= con/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=0D + PCH SPI SMM Driver implements the SPI Host Controller Compatibility Inte= rface.=0D +=0D + Copyright (c) 2021, Intel Corporation. All rights reserved.
=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +**/=0D +=0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +=0D +//=0D +// Global variables=0D +//=0D +GLOBAL_REMOVE_IF_UNREFERENCED SPI_INSTANCE *mSpiInstance;=0D +GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_CPU_PROTOCOL *mSmmCpuProtocol;=0D +//=0D +// mPchSpiResvMmioAddr keeps the reserved MMIO range assiged to SPI.=0D +// In SMM it always set back the reserved MMIO address to SPI BAR0 to ensu= re the MMIO range=0D +// won't overlap with SMRAM range, and trusted.=0D +//=0D +GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mSpiResvMmioAddr;=0D +=0D +/**=0D + SPI Runtime SMM Module Entry Point\n=0D + - Introduction\n=0D + The SPI SMM module provide a standard way for other modules to use the= PCH SPI Interface in SMM.=0D +=0D + - @pre=0D + - EFI_SMM_BASE2_PROTOCOL=0D + - Documented in System Management Mode Core Interface Specification = .=0D +=0D + - @result=0D + The SPI SMM driver produces @link _PCH_SPI_PROTOCOL PCH_SPI_PROTOCOL @= endlink with GUID=0D + gPchSmmSpiProtocolGuid which is different from SPI RUNTIME driver.=0D +=0D + - Integration Check List\n=0D + - This driver supports Descriptor Mode only.=0D + - This driver supports Hardware Sequence only.=0D + - When using SMM SPI Protocol to perform flash access in an SMI handle= r,=0D + and the SMI occurrence is asynchronous to normal mode code execution= ,=0D + proper synchronization mechanism must be applied, e.g. disable SMI b= efore=0D + the normal mode SendSpiCmd() starts and re-enable SMI after=0D + the normal mode SendSpiCmd() completes.=0D + @note The implementation of SendSpiCmd() uses GBL_SMI_EN in=0D + SMI_EN register (ABase + 30h) to disable and enable SMIs. But this m= ay=0D + not be effective as platform may well set the SMI_LOCK bit (i.e., PM= C PCI Offset A0h [4]).=0D + So the synchronization at caller level is likely needed.=0D +=0D + @param[in] ImageHandle Image handle of this driver.=0D + @param[in] SystemTable Global system service table.=0D +=0D + @retval EFI_SUCCESS Initialization complete.=0D + @exception EFI_UNSUPPORTED The chipset is unsupported by this drive= r.=0D + @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initiali= ze the driver.=0D + @retval EFI_DEVICE_ERROR Device error, driver exits abnormally.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +InstallPchSpi (=0D + IN EFI_HANDLE ImageHandle,=0D + IN EFI_SYSTEM_TABLE *SystemTable=0D + )=0D +{=0D + EFI_STATUS Status;=0D +=0D + //=0D + // Init PCH spi reserved MMIO address.=0D + //=0D + mSpiResvMmioAddr =3D PCH_SPI_BASE_ADDRESS;=0D +=0D + ///=0D + /// Allocate pool for SPI protocol instance=0D + ///=0D + Status =3D gSmst->SmmAllocatePool (=0D + EfiRuntimeServicesData, /// MemoryType don't care=0D + sizeof (SPI_INSTANCE),=0D + (VOID **) &mSpiInstance=0D + );=0D + if (EFI_ERROR (Status)) {=0D + return Status;=0D + }=0D +=0D + if (mSpiInstance =3D=3D NULL) {=0D + return EFI_OUT_OF_RESOURCES;=0D + }=0D +=0D + ZeroMem ((VOID *) mSpiInstance, sizeof (SPI_INSTANCE));=0D + ///=0D + /// Initialize the SPI protocol instance=0D + ///=0D + Status =3D SpiProtocolConstructor (mSpiInstance);=0D + if (EFI_ERROR (Status)) {=0D + return Status;=0D + }=0D + ///=0D + /// Install the SMM PCH_SPI_PROTOCOL interface=0D + ///=0D + Status =3D gSmst->SmmInstallProtocolInterface (=0D + &(mSpiInstance->Handle),=0D + &gPchSmmSpiProtocolGuid,=0D + EFI_NATIVE_INTERFACE,=0D + &(mSpiInstance->SpiProtocol)=0D + );=0D + if (EFI_ERROR (Status)) {=0D + gSmst->SmmFreePool (mSpiInstance);=0D + return EFI_DEVICE_ERROR;=0D + }=0D +=0D + return EFI_SUCCESS;=0D +}=0D +=0D +/**=0D + Acquire PCH spi mmio address.=0D + If it is ever different from the preallocated address, reassign it back.= =0D + In SMM, it always override the BAR0 and returns the reserved MMIO range = for SPI.=0D +=0D + @param[in] SpiInstance Pointer to SpiInstance to initialize=0D +=0D + @retval PchSpiBar0 return SPI MMIO address=0D +**/=0D +UINTN=0D +AcquireSpiBar0 (=0D + IN SPI_INSTANCE *SpiInstance=0D + )=0D +{=0D + UINT32 SpiBar0;=0D + //=0D + // Save original SPI physical MMIO address=0D + //=0D + SpiBar0 =3D PciSegmentRead32 (SpiInstance->PchSpiBase + R_SPI_CFG_BAR0) = & ~(B_SPI_CFG_BAR0_MASK);=0D +=0D + if (SpiBar0 !=3D mSpiResvMmioAddr) {=0D + //=0D + // Temporary disable MSE, and override with SPI reserved MMIO address,= then enable MSE.=0D + //=0D + PciSegmentAnd8 (SpiInstance->PchSpiBase + PCI_COMMAND_OFFSET, (UINT8) = ~EFI_PCI_COMMAND_MEMORY_SPACE);=0D + PciSegmentWrite32 (SpiInstance->PchSpiBase + R_SPI_CFG_BAR0, mSpiResvM= mioAddr);=0D + PciSegmentOr8 (SpiInstance->PchSpiBase + PCI_COMMAND_OFFSET, EFI_PCI_C= OMMAND_MEMORY_SPACE);=0D + }=0D + //=0D + // SPIBAR0 will be different before and after PCI enum so need to get it= from SPI BAR0 reg.=0D + //=0D + return mSpiResvMmioAddr;=0D +}=0D +=0D +/**=0D + Release pch spi mmio address. Do nothing.=0D +=0D + @param[in] SpiInstance Pointer to SpiInstance to initialize=0D +=0D + @retval None=0D +**/=0D +VOID=0D +ReleaseSpiBar0 (=0D + IN SPI_INSTANCE *SpiInstance=0D + )=0D +{=0D +}=0D +=0D +/**=0D + This function is a hook for Spi to disable BIOS Write Protect=0D +=0D + @retval EFI_SUCCESS The protocol instance was properly initi= alized=0D + @retval EFI_ACCESS_DENIED The BIOS Region can only be updated in S= MM phase=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +DisableBiosWriteProtect (=0D + VOID=0D + )=0D +{=0D + UINT64 SpiBaseAddress;=0D +=0D + SpiBaseAddress =3D SpiPciCfgBase ();=0D + // Write clear BC_SYNC_SS prior to change WPD from 0 to 1.=0D + //=0D + PciSegmentOr8 (=0D + SpiBaseAddress + R_SPI_CFG_BC + 1,=0D + (B_SPI_CFG_BC_SYNC_SS >> 8)=0D + );=0D + ///=0D + /// Set BIOSWE bit (SPI PCI Offset DCh [0]) =3D 1b=0D + /// Enable the access to the BIOS space for both read and write cycles=0D + ///=0D + PciSegmentOr8 (=0D + SpiBaseAddress + R_SPI_CFG_BC,=0D + B_SPI_CFG_BC_WPD=0D + );=0D +=0D + ///=0D + /// PCH BIOS Spec Section 3.7 BIOS Region SMM Protection Enabling=0D + /// If the following steps are implemented:=0D + /// - Set the EISS bit (SPI PCI Offset DCh [5]) =3D 1b=0D + /// - Follow the 1st recommendation in section 3.6=0D + /// the BIOS Region can only be updated by following the steps bellow:=0D + /// - Once all threads enter SMM=0D + /// - Read memory location FED30880h OR with 00000001h, place the resul= t in EAX,=0D + /// and write data to lower 32 bits of MSR 1FEh (sample code availabl= e)=0D + /// - Set BIOSWE bit (SPI PCI Offset DCh [0]) =3D 1b=0D + /// - Modify BIOS Region=0D + /// - Clear BIOSWE bit (SPI PCI Offset DCh [0]) =3D 0b=0D + ///=0D + if ((PciSegmentRead8 (SpiBaseAddress + R_SPI_CFG_BC) & B_SPI_CFG_BC_EISS= ) !=3D 0) {=0D + PchSetInSmmSts ();=0D + }=0D +=0D + return EFI_SUCCESS;=0D +}=0D +=0D +/**=0D + This function is a hook for Spi to enable BIOS Write Protect=0D +**/=0D +VOID=0D +EFIAPI=0D +EnableBiosWriteProtect (=0D + VOID=0D + )=0D +{=0D + UINT64 SpiBaseAddress;=0D +=0D + SpiBaseAddress =3D SpiPciCfgBase ();=0D + ///=0D + /// Clear BIOSWE bit (SPI PCI Offset DCh [0]) =3D 0b=0D + /// Disable the access to the BIOS space for write cycles=0D + ///=0D + PciSegmentAnd8 (=0D + SpiBaseAddress + R_SPI_CFG_BC,=0D + (UINT8) (~B_SPI_CFG_BC_WPD)=0D + );=0D +=0D + ///=0D + /// Check if EISS bit is set=0D + ///=0D + if (((PciSegmentRead8 (SpiBaseAddress + R_SPI_CFG_BC)) & B_SPI_CFG_BC_EI= SS) =3D=3D B_SPI_CFG_BC_EISS) {=0D + PchClearInSmmSts ();=0D + }=0D +}=0D +=0D +/**=0D + Check if it's granted to do flash write.=0D +=0D + @retval TRUE It's secure to do flash write.=0D + @retval FALSE It's not secure to do flash write.=0D +**/=0D +BOOLEAN=0D +IsSpiFlashWriteGranted (=0D + VOID=0D + )=0D +{=0D + EFI_STATUS Status;=0D + UINT32 CpuIndex;=0D + UINT64 ProcessorId;=0D +=0D + if (mSmmCpuProtocol =3D=3D NULL) {=0D + Status =3D gSmst->SmmLocateProtocol (&gEfiSmmCpuProtocolGuid, NULL, (V= OID **)&mSmmCpuProtocol);=0D + ASSERT_EFI_ERROR (Status);=0D + if (mSmmCpuProtocol =3D=3D NULL) {=0D + return TRUE;=0D + }=0D + }=0D +=0D + for (CpuIndex =3D 0; CpuIndex < gSmst->NumberOfCpus; CpuIndex++) {=0D + Status =3D mSmmCpuProtocol->ReadSaveState (=0D + mSmmCpuProtocol,=0D + sizeof (ProcessorId),=0D + EFI_SMM_SAVE_STATE_REGISTER_PROCESSOR_ID,= =0D + CpuIndex,=0D + &ProcessorId=0D + );=0D + //=0D + // If the processor is in SMM at the time the SMI occurred,=0D + // it will return success. Otherwise, EFI_NOT_FOUND is returned.=0D + //=0D + if (EFI_ERROR (Status)) {=0D + return FALSE;=0D + }=0D + }=0D +=0D + return TRUE;=0D +}=0D 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=0D +# Component description file for the SPI SMM driver.=0D +#=0D +# Copyright (c) 2021, Intel Corporation. All rights reserved.
=0D +# SPDX-License-Identifier: BSD-2-Clause-Patent=0D +#=0D +##=0D +=0D +=0D +[Defines]=0D +INF_VERSION =3D 0x00010017=0D +BASE_NAME =3D SpiSmm=0D +FILE_GUID =3D 27F4917B-A707-4aad-9676-26DF168CBF0D=0D +VERSION_STRING =3D 1.0=0D +MODULE_TYPE =3D DXE_SMM_DRIVER=0D +PI_SPECIFICATION_VERSION =3D 1.10=0D +ENTRY_POINT =3D InstallPchSpi=0D +=0D +=0D +[LibraryClasses]=0D +DebugLib=0D +IoLib=0D +UefiDriverEntryPoint=0D +UefiBootServicesTableLib=0D +BaseLib=0D +SmmServicesTableLib=0D +SpiCommonLib=0D +SmmPchPrivateLib=0D +PchPciBdfLib=0D +=0D +[Packages]=0D +MdePkg/MdePkg.dec=0D +TigerlakeSiliconPkg/SiPkg.dec=0D +=0D +=0D +[Sources]=0D +Spi.c=0D +=0D +=0D +[Protocols]=0D +gPchSmmSpiProtocolGuid ## PRODUCES=0D +gEfiSmmCpuProtocolGuid ## CONSUMES=0D +=0D +=0D +[Depex]=0D +gEfiSmmBase2ProtocolGuid AND # This is for SmmServicesTableLib=0D +gEfiSmmCpuProtocolGuid # This is for CpuSmmDisableBiosWriteProtect()=0D --=20 2.24.0.windows.2