[edk2-devel] [PATCH 29/40] TigerlakeSiliconPkg/IpBlock: Add Spi component

Nate DeSimone nathaniel.l.desimone at intel.com
Thu Feb 4 03:56:27 UTC 2021


Reviewed-by: Nate DeSimone <nathaniel.l.desimone at intel.com>

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



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#71165): https://edk2.groups.io/g/devel/message/71165
Mute This Topic: https://groups.io/mt/80274143/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-






More information about the edk2-devel-archive mailing list