]> git.proxmox.com Git - mirror_edk2.git/commitdiff
UefiPayloadPkg: Add SpiFlashLib
authorGuo Dong <guo.dong@intel.com>
Wed, 22 Sep 2021 21:31:29 +0000 (14:31 -0700)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Mon, 25 Oct 2021 17:28:21 +0000 (17:28 +0000)
This is a common SPI Flash library used for the Intel platform that
supports SPI hardware sequence. This library provides actual SPI flash
operation via Intel PCH SPI controller.

Signed-off-by: Guo Dong <guo.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Maurice Ma <maurice.ma@intel.com>
Cc: Benjamin You <benjamin.you@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
Reviewed-by: Benjamin You <benjamin.you@intel.com>
UefiPayloadPkg/Include/Guid/SpiFlashInfoGuid.h [new file with mode: 0644]
UefiPayloadPkg/Include/Library/SpiFlashLib.h [new file with mode: 0644]
UefiPayloadPkg/Library/SpiFlashLib/PchSpi.c [new file with mode: 0644]
UefiPayloadPkg/Library/SpiFlashLib/RegsSpi.h [new file with mode: 0644]
UefiPayloadPkg/Library/SpiFlashLib/SpiCommon.h [new file with mode: 0644]
UefiPayloadPkg/Library/SpiFlashLib/SpiFlashLib.c [new file with mode: 0644]
UefiPayloadPkg/Library/SpiFlashLib/SpiFlashLib.inf [new file with mode: 0644]
UefiPayloadPkg/UefiPayloadPkg.dec

diff --git a/UefiPayloadPkg/Include/Guid/SpiFlashInfoGuid.h b/UefiPayloadPkg/Include/Guid/SpiFlashInfoGuid.h
new file mode 100644 (file)
index 0000000..6241463
--- /dev/null
@@ -0,0 +1,38 @@
+/** @file\r
+  This file defines the hob structure for the SPI flash variable info.\r
+\r
+  Copyright (c) 2017 - 2021, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#ifndef SPI_FLASH_INFO_GUID_H_\r
+#define SPI_FLASH_INFO_GUID_H_\r
+\r
+#include <IndustryStandard/Acpi.h>\r
+//\r
+// SPI Flash infor hob GUID\r
+//\r
+extern EFI_GUID gSpiFlashInfoGuid;\r
+\r
+//\r
+// Set this bit if platform need disable SMM write protection when writing flash\r
+// in SMM mode using this method:  -- AsmWriteMsr32 (0x1FE, MmioRead32 (0xFED30880) | BIT0);\r
+//\r
+#define FLAGS_SPI_DISABLE_SMM_WRITE_PROTECT     BIT0\r
+\r
+//\r
+// Reuse ACPI definition\r
+//\r
+typedef EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE PLD_GENERIC_ADDRESS;\r
+#define SPACE_ID_PCI_CONFIGURATION              EFI_ACPI_3_0_PCI_CONFIGURATION_SPACE\r
+#define REGISTER_BIT_WIDTH_DWORD                EFI_ACPI_3_0_DWORD\r
+\r
+typedef struct {\r
+  UINT8                        Revision;\r
+  UINT8                        Reserved;\r
+  UINT16                       Flags;\r
+  PLD_GENERIC_ADDRESS          SpiAddress;\r
+} SPI_FLASH_INFO;\r
+\r
+#endif\r
diff --git a/UefiPayloadPkg/Include/Library/SpiFlashLib.h b/UefiPayloadPkg/Include/Library/SpiFlashLib.h
new file mode 100644 (file)
index 0000000..59840af
--- /dev/null
@@ -0,0 +1,215 @@
+/** @file\r
+  PCH SPI Common Driver implements the SPI Host Controller Compatibility Interface.\r
+\r
+  Copyright (c) 2017 - 2021, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#ifndef SPI_FLASH_LIB_H_\r
+#define SPI_FLASH_LIB_H_\r
+\r
+/**\r
+  Flash Region Type\r
+**/\r
+typedef enum {\r
+  FlashRegionDescriptor,\r
+  FlashRegionBios,\r
+  FlashRegionMe,\r
+  FlashRegionGbE,\r
+  FlashRegionPlatformData,\r
+  FlashRegionDer,\r
+  FlashRegionAll,\r
+  FlashRegionMax\r
+} FLASH_REGION_TYPE;\r
+\r
+/**\r
+  Read SFDP data from the flash part.\r
+\r
+  @param[in] ComponentNumber      The Component Number for chip select\r
+  @param[in] ByteCount            Number of bytes in SFDP data portion of the SPI cycle, the max number is 64\r
+  @param[out] SfdpData            The Pointer to caller-allocated buffer containing the SFDP data received\r
+                                  It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.\r
+\r
+  @retval EFI_SUCCESS             Command succeed.\r
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.\r
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SpiFlashReadSfdp (\r
+  IN     UINT8              ComponentNumber,\r
+  IN     UINT32             ByteCount,\r
+  OUT    UINT8              *SfdpData\r
+  );\r
+\r
+/**\r
+  Read Jedec Id from the flash part.\r
+\r
+  @param[in] ComponentNumber      The Component Number for chip select\r
+  @param[in] ByteCount            Number of bytes in JedecId data portion of the SPI cycle, the data size is 3 typically\r
+  @param[out] JedecId             The Pointer to caller-allocated buffer containing JEDEC ID received\r
+                                  It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.\r
+\r
+  @retval EFI_SUCCESS             Command succeed.\r
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.\r
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SpiFlashReadJedecId (\r
+  IN     UINT8              ComponentNumber,\r
+  IN     UINT32             ByteCount,\r
+  OUT    UINT8              *JedecId\r
+  );\r
+\r
+/**\r
+  Write the status register in the flash part.\r
+\r
+  @param[in] ByteCount            Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically\r
+  @param[in] StatusValue          The Pointer to caller-allocated buffer containing the value of Status register writing\r
+\r
+  @retval EFI_SUCCESS             Command succeed.\r
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.\r
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SpiFlashWriteStatus (\r
+  IN     UINT32             ByteCount,\r
+  IN     UINT8              *StatusValue\r
+  );\r
+\r
+/**\r
+  Read status register in the flash part.\r
+\r
+  @param[in] ByteCount            Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically\r
+  @param[out] StatusValue         The Pointer to caller-allocated buffer containing the value of Status register received.\r
+\r
+  @retval EFI_SUCCESS             Command succeed.\r
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.\r
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SpiFlashReadStatus (\r
+  IN     UINT32             ByteCount,\r
+  OUT    UINT8              *StatusValue\r
+  );\r
+\r
+/**\r
+  Read SC Soft Strap Values\r
+\r
+  @param[in] SoftStrapAddr        SC Soft Strap address offset from FPSBA.\r
+  @param[in] ByteCount            Number of bytes in SoftStrap data portion of the SPI cycle\r
+  @param[out] SoftStrapValue      The Pointer to caller-allocated buffer containing SC Soft Strap Value.\r
+                                  It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.\r
+\r
+  @retval EFI_SUCCESS             Command succeed.\r
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.\r
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SpiReadPchSoftStrap (\r
+  IN     UINT32             SoftStrapAddr,\r
+  IN     UINT32             ByteCount,\r
+  OUT    UINT8              *SoftStrapValue\r
+  );\r
+\r
+\r
+/**\r
+  Read data from the flash part.\r
+\r
+  @param[in] FlashRegionType      The Flash Region type for flash cycle which is listed in the Descriptor.\r
+  @param[in] Address              The Flash Linear Address must fall within a region for which BIOS has access permissions.\r
+  @param[in] ByteCount            Number of bytes in the data portion of the SPI cycle.\r
+  @param[out] Buffer              The Pointer to caller-allocated buffer containing the dada received.\r
+                                  It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.\r
+\r
+  @retval EFI_SUCCESS             Command succeed.\r
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.\r
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SpiFlashRead (\r
+  IN     FLASH_REGION_TYPE  FlashRegionType,\r
+  IN     UINT32             Address,\r
+  IN     UINT32             ByteCount,\r
+  OUT    UINT8              *Buffer\r
+  );\r
+\r
+/**\r
+  Erase some area on the flash part.\r
+\r
+  @param[in] FlashRegionType      The Flash Region type for flash cycle which is listed in the Descriptor.\r
+  @param[in] Address              The Flash Linear Address must fall within a region for which BIOS has access permissions.\r
+  @param[in] ByteCount            Number of bytes in the data portion of the SPI cycle.\r
+\r
+  @retval EFI_SUCCESS             Command succeed.\r
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.\r
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SpiFlashErase (\r
+  IN     FLASH_REGION_TYPE  FlashRegionType,\r
+  IN     UINT32             Address,\r
+  IN     UINT32             ByteCount\r
+  );\r
+\r
+/**\r
+  Write data to the flash part.\r
+\r
+  @param[in] FlashRegionType      The Flash Region type for flash cycle which is listed in the Descriptor.\r
+  @param[in] Address              The Flash Linear Address must fall within a region for which BIOS has access permissions.\r
+  @param[in] ByteCount            Number of bytes in the data portion of the SPI cycle.\r
+  @param[in] Buffer               Pointer to caller-allocated buffer containing the data sent during the SPI cycle.\r
+\r
+  @retval EFI_SUCCESS             Command succeed.\r
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.\r
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SpiFlashWrite (\r
+  IN     FLASH_REGION_TYPE  FlashRegionType,\r
+  IN     UINT32             Address,\r
+  IN     UINT32             ByteCount,\r
+  IN     UINT8              *Buffer\r
+  );\r
+\r
+/**\r
+  Initialize an SPI library.\r
+\r
+  @retval EFI_SUCCESS             The protocol instance was properly initialized\r
+  @retval EFI_NOT_FOUND           The expected SPI info could not be found\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SpiConstructor (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Get the SPI region base and size, based on the enum type\r
+\r
+  @param[in] FlashRegionType      The Flash Region type for for the base address which is listed in the Descriptor.\r
+  @param[out] BaseAddress         The Flash Linear Address for the Region 'n' Base\r
+  @param[out] RegionSize          The size for the Region 'n'\r
+\r
+  @retval EFI_SUCCESS             Read success\r
+  @retval EFI_INVALID_PARAMETER   Invalid region type given\r
+  @retval EFI_DEVICE_ERROR        The region is not used\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SpiGetRegionAddress (\r
+  IN     FLASH_REGION_TYPE  FlashRegionType,\r
+  OUT    UINT32             *BaseAddress, OPTIONAL\r
+  OUT    UINT32             *RegionSize OPTIONAL\r
+  );\r
+\r
+#endif\r
+\r
diff --git a/UefiPayloadPkg/Library/SpiFlashLib/PchSpi.c b/UefiPayloadPkg/Library/SpiFlashLib/PchSpi.c
new file mode 100644 (file)
index 0000000..1dafce1
--- /dev/null
@@ -0,0 +1,173 @@
+/** @file\r
+\r
+  Copyright (c) 2017-2021, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+#include "SpiCommon.h"\r
+\r
+/**\r
+  Acquire SPI MMIO BAR.\r
+\r
+  @param[in] PchSpiBase           PCH SPI PCI Base Address\r
+\r
+  @retval                         Return SPI BAR Address\r
+\r
+**/\r
+UINT32\r
+AcquireSpiBar0 (\r
+  IN  UINTN         PchSpiBase\r
+  )\r
+{\r
+  return MmioRead32 (PchSpiBase + R_SPI_BASE) & ~(B_SPI_BAR0_MASK);\r
+}\r
+\r
+/**\r
+  Release SPI MMIO BAR. Do nothing.\r
+\r
+  @param[in] PchSpiBase           PCH SPI PCI Base Address\r
+\r
+**/\r
+VOID\r
+ReleaseSpiBar0 (\r
+  IN  UINTN         PchSpiBase\r
+  )\r
+{\r
+}\r
+\r
+\r
+\r
+/**\r
+  This function is to enable/disable BIOS Write Protect in SMM phase.\r
+\r
+  @param[in] EnableSmmSts        Flag to Enable/disable Bios write protect\r
+\r
+**/\r
+VOID\r
+CpuSmmDisableBiosWriteProtect (\r
+   IN  BOOLEAN   EnableSmmSts\r
+  )\r
+{\r
+  UINT32      Data32;\r
+\r
+  if(EnableSmmSts){\r
+    //\r
+    // Disable BIOS Write Protect in SMM phase.\r
+    //\r
+    Data32 = MmioRead32 ((UINTN) (0xFED30880)) | (UINT32) (BIT0);\r
+    AsmWriteMsr32 (0x000001FE, Data32);\r
+  } else {\r
+    //\r
+    // Enable BIOS Write Protect in SMM phase\r
+    //\r
+    Data32 = MmioRead32 ((UINTN) (0xFED30880)) & (UINT32) (~BIT0);\r
+    AsmWriteMsr32 (0x000001FE, Data32);\r
+  }\r
+\r
+  //\r
+  // Read FED30880h back to ensure the setting went through.\r
+  //\r
+  Data32 = MmioRead32 (0xFED30880);\r
+}\r
+\r
+\r
+/**\r
+  This function is a hook for Spi to disable BIOS Write Protect.\r
+\r
+  @param[in] PchSpiBase           PCH SPI PCI Base Address\r
+  @param[in] CpuSmmBwp            Need to disable CPU SMM Bios write protection or not\r
+\r
+  @retval EFI_SUCCESS             The protocol instance was properly initialized\r
+  @retval EFI_ACCESS_DENIED       The BIOS Region can only be updated in SMM phase\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DisableBiosWriteProtect (\r
+  IN  UINTN         PchSpiBase,\r
+  IN  UINT8         CpuSmmBwp\r
+  )\r
+{\r
+\r
+  //\r
+  // Write clear BC_SYNC_SS prior to change WPD from 0 to 1.\r
+  //\r
+  MmioOr8 (PchSpiBase + R_SPI_BCR + 1, (B_SPI_BCR_SYNC_SS >> 8));\r
+\r
+  //\r
+  // Enable the access to the BIOS space for both read and write cycles\r
+  //\r
+  MmioOr8 (PchSpiBase + R_SPI_BCR, B_SPI_BCR_BIOSWE);\r
+\r
+  if (CpuSmmBwp != 0) {\r
+    CpuSmmDisableBiosWriteProtect (TRUE);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This function is a hook for Spi to enable BIOS Write Protect.\r
+\r
+  @param[in] PchSpiBase           PCH SPI PCI Base Address\r
+  @param[in] CpuSmmBwp            Need to disable CPU SMM Bios write protection or not\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+EnableBiosWriteProtect (\r
+  IN  UINTN         PchSpiBase,\r
+  IN  UINT8         CpuSmmBwp\r
+  )\r
+{\r
+\r
+  //\r
+  // Disable the access to the BIOS space for write cycles\r
+  //\r
+  MmioAnd8 (PchSpiBase + R_SPI_BCR, (UINT8) (~B_SPI_BCR_BIOSWE));\r
+\r
+  if (CpuSmmBwp != 0) {\r
+    CpuSmmDisableBiosWriteProtect (FALSE);\r
+  }\r
+}\r
+\r
+/**\r
+  This function disables SPI Prefetching and caching,\r
+  and returns previous BIOS Control Register value before disabling.\r
+\r
+  @param[in] PchSpiBase           PCH SPI PCI Base Address\r
+\r
+  @retval                         Previous BIOS Control Register value\r
+\r
+**/\r
+UINT8\r
+SaveAndDisableSpiPrefetchCache (\r
+  IN  UINTN         PchSpiBase\r
+  )\r
+{\r
+  UINT8           BiosCtlSave;\r
+\r
+  BiosCtlSave = MmioRead8 (PchSpiBase + R_SPI_BCR) & B_SPI_BCR_SRC;\r
+\r
+  MmioAndThenOr32 (PchSpiBase + R_SPI_BCR, \\r
+    (UINT32) (~B_SPI_BCR_SRC), \\r
+    (UINT32) (V_SPI_BCR_SRC_PREF_DIS_CACHE_DIS <<  B_SPI_BCR_SRC));\r
+\r
+  return BiosCtlSave;\r
+}\r
+\r
+/**\r
+  This function updates BIOS Control Register with the given value.\r
+\r
+  @param[in] PchSpiBase           PCH SPI PCI Base Address\r
+  @param[in] BiosCtlValue         BIOS Control Register Value to be updated\r
+\r
+**/\r
+VOID\r
+SetSpiBiosControlRegister (\r
+  IN  UINTN         PchSpiBase,\r
+  IN  UINT8         BiosCtlValue\r
+  )\r
+{\r
+  MmioAndThenOr8 (PchSpiBase + R_SPI_BCR, (UINT8) ~B_SPI_BCR_SRC, BiosCtlValue);\r
+}\r
diff --git a/UefiPayloadPkg/Library/SpiFlashLib/RegsSpi.h b/UefiPayloadPkg/Library/SpiFlashLib/RegsSpi.h
new file mode 100644 (file)
index 0000000..5f22623
--- /dev/null
@@ -0,0 +1,129 @@
+/** @file\r
+  Register names for SPI device.\r
+\r
+  Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#ifndef REGS_SPI_H_\r
+#define REGS_SPI_H_\r
+\r
+#define R_SPI_BASE                      0x10           ///< 32-bit Memory Base Address Register\r
+#define B_SPI_BAR0_MASK                 0x0FFF\r
+#define R_SPI_BCR                       0xDC           ///< BIOS Control  Register\r
+#define B_SPI_BCR_SRC                    (BIT3 | BIT2) ///< SPI Read Configuration (SRC)\r
+#define V_SPI_BCR_SRC_PREF_DIS_CACHE_DIS 0x04          ///< Prefetch Disable, Cache Disable\r
+#define B_SPI_BCR_SYNC_SS                BIT8\r
+#define B_SPI_BCR_BIOSWE                 BIT0          ///< Write Protect Disable (WPD)\r
+\r
+///\r
+/// SPI Host Interface Registers\r
+#define R_SPI_HSFS                       0x04          ///< Hardware Sequencing Flash Status and Control Register(32bits)\r
+#define B_SPI_HSFS_FDBC_MASK             0x3F000000    ///< Flash Data Byte Count ( <= 64), Count = (Value in this field) + 1.\r
+#define N_SPI_HSFS_FDBC                  24\r
+#define B_SPI_HSFS_CYCLE_MASK            0x001E0000    ///< Flash Cycle.\r
+#define N_SPI_HSFS_CYCLE                 17\r
+#define V_SPI_HSFS_CYCLE_READ            0             ///< Flash Cycle Read\r
+#define V_SPI_HSFS_CYCLE_WRITE           2             ///< Flash Cycle Write\r
+#define V_SPI_HSFS_CYCLE_4K_ERASE        3             ///< Flash Cycle 4K Block Erase\r
+#define V_SPI_HSFS_CYCLE_64K_ERASE       4             ///< Flash Cycle 64K Sector Erase\r
+#define V_SPI_HSFS_CYCLE_READ_SFDP       5             ///< Flash Cycle Read SFDP\r
+#define V_SPI_HSFS_CYCLE_READ_JEDEC_ID   6             ///< Flash Cycle Read JEDEC ID\r
+#define V_SPI_HSFS_CYCLE_WRITE_STATUS    7             ///< Flash Cycle Write Status\r
+#define V_SPI_HSFS_CYCLE_READ_STATUS     8             ///< Flash Cycle Read Status\r
+#define B_SPI_HSFS_CYCLE_FGO             BIT16         ///< Flash Cycle Go.\r
+#define B_SPI_HSFS_FDV                   BIT14         ///< Flash Descriptor Valid\r
+#define B_SPI_HSFS_SCIP                  BIT5          ///< SPI Cycle in Progress\r
+#define B_SPI_HSFS_FCERR                 BIT1          ///< Flash Cycle Error\r
+#define B_SPI_HSFS_FDONE                 BIT0          ///< Flash Cycle Done\r
+\r
+\r
+#define R_SPI_FADDR                      0x08   ///< SPI Flash Address\r
+#define B_SPI_FADDR_MASK                 0x07FFFFFF ///< SPI Flash Address Mask (0~26bit)\r
+\r
+\r
+#define R_SPI_FDATA00                    0x10  ///< SPI Data 00 (32 bits)\r
+\r
+#define R_SPI_FRAP                       0x50  ///< SPI Flash Regions Access Permissions Register\r
+#define B_SPI_FRAP_BRWA_PLATFORM         BIT12 //< Region write access for Region4 PlatformData\r
+#define B_SPI_FRAP_BRWA_GBE              BIT11 //< Region write access for Region3 GbE\r
+#define B_SPI_FRAP_BRWA_SEC              BIT10 ///< Region Write Access for Region2 SEC\r
+#define B_SPI_FRAP_BRWA_BIOS             BIT9  ///< Region Write Access for Region1 BIOS\r
+#define B_SPI_FRAP_BRWA_FLASHD           BIT8  ///< Region Write Access for Region0 Flash Descriptor\r
+#define B_SPI_FRAP_BRRA_PLATFORM         BIT4       ///< Region read access for Region4 PlatformData\r
+#define B_SPI_FRAP_BRRA_GBE              BIT3       ///< Region read access for Region3 GbE\r
+#define B_SPI_FRAP_BRRA_SEC              BIT2       ///< Region Read Access for Region2 SEC\r
+#define B_SPI_FRAP_BRRA_BIOS             BIT1       ///< Region Read Access for Region1 BIOS\r
+#define B_SPI_FRAP_BRRA_FLASHD           BIT0       ///< Region Read Access for Region0 Flash Descriptor\r
+\r
+\r
+#define R_SPI_FREG0_FLASHD               0x54       ///< Flash Region 0 (Flash Descriptor) (32bits)\r
+#define B_SPI_FREG0_LIMIT_MASK           0x7FFF0000 ///< Size, [30:16] here represents limit[26:12]\r
+#define N_SPI_FREG0_LIMIT                4          ///< Bit 30:16 identifies address bits [26:12]\r
+#define B_SPI_FREG0_BASE_MASK            0x00007FFF ///< Base, [14:0]  here represents base [26:12]\r
+#define N_SPI_FREG0_BASE                 12         ///< Bit 14:0 identifies address bits [26:2]\r
+\r
+#define R_SPI_FREG1_BIOS                 0x58       ///< Flash Region 1 (BIOS) (32bits)\r
+#define B_SPI_FREG1_LIMIT_MASK           0x7FFF0000 ///< Size, [30:16] here represents limit[26:12]\r
+#define N_SPI_FREG1_LIMIT                4          ///< Bit 30:16 identifies address bits [26:12]\r
+#define B_SPI_FREG1_BASE_MASK            0x00007FFF ///< Base, [14:0]  here represents base [26:12]\r
+#define N_SPI_FREG1_BASE                 12         ///< Bit 14:0 identifies address bits [26:2]\r
+\r
+#define R_SPI_FREG2_SEC                  0x5C       ///< Flash Region 2 (SEC) (32bits)\r
+#define B_SPI_FREG2_LIMIT_MASK           0x7FFF0000 ///< Size, [30:16] here represents limit[26:12]\r
+#define N_SPI_FREG2_LIMIT                4          //< Bit 30:16 identifies address bits [26:12]\r
+#define B_SPI_FREG2_BASE_MASK            0x00007FFF ///< Base, [14:0]  here represents base [26:12]\r
+#define N_SPI_FREG2_BASE                 12         //< Bit 14:0 identifies address bits [26:2]\r
+\r
+#define R_SPI_FREG3_GBE                  0x60       //< Flash Region 3(GbE)(32bits)\r
+#define B_SPI_FREG3_LIMIT_MASK           0x7FFF0000 ///< Size, [30:16] here represents limit[26:12]\r
+#define N_SPI_FREG3_LIMIT                4          //< Bit 30:16 identifies address bits [26:12]\r
+#define B_SPI_FREG3_BASE_MASK            0x00007FFF ///< Base, [14:0]  here represents base [26:12]\r
+#define N_SPI_FREG3_BASE                 12         //< Bit 14:0 identifies address bits [26:2]\r
+\r
+#define R_SPI_FREG4_PLATFORM_DATA        0x64       ///< Flash Region 4 (Platform Data) (32bits)\r
+#define B_SPI_FREG4_LIMIT_MASK           0x7FFF0000 ///< Size, [30:16] here represents limit[26:12]\r
+#define N_SPI_FREG4_LIMIT                4          ///< Bit 30:16 identifies address bits [26:12]\r
+#define B_SPI_FREG4_BASE_MASK            0x00007FFF ///< Base, [14:0]  here represents base [26:12]\r
+#define N_SPI_FREG4_BASE                 12         ///< Bit 14:0 identifies address bits [26:2]\r
+\r
+\r
+#define S_SPI_FREGX                      4          ///< Size of Flash Region register\r
+#define B_SPI_FREGX_LIMIT_MASK           0x7FFF0000 ///< Flash Region Limit [30:16] represents [26:12], [11:0] are assumed to be FFFh\r
+#define N_SPI_FREGX_LIMIT                16         ///< Region limit bit position\r
+#define N_SPI_FREGX_LIMIT_REPR           12         ///< Region limit bit represents position\r
+#define B_SPI_FREGX_BASE_MASK            0x00007FFF ///< Flash Region Base, [14:0] represents [26:12]\r
+\r
+\r
+#define R_SPI_FDOC                       0xB4  ///< Flash Descriptor Observability Control Register (32 bits)\r
+#define B_SPI_FDOC_FDSS_MASK             (BIT14 | BIT13 | BIT12) ///< Flash Descriptor Section Select\r
+#define V_SPI_FDOC_FDSS_FSDM             0x0000 ///< Flash Signature and Descriptor Map\r
+#define V_SPI_FDOC_FDSS_COMP             0x1000 ///< Component\r
+#define B_SPI_FDOC_FDSI_MASK             0x0FFC ///< Flash Descriptor Section Index\r
+\r
+#define R_SPI_FDOD                       0xB8  ///< Flash Descriptor Observability Data Register (32 bits)\r
+\r
+\r
+#define R_SPI_LVSCC                      0xC4  ///<Vendor Specific Component Capabilities for Component 0 (32 bits)\r
+#define B_SPI_LVSCC_EO_64K               BIT29 ///<< 64k Erase valid (EO_64k_valid)\r
+\r
+#define R_SPI_UVSCC                      0xC8  ///< Vendor Specific Component Capabilities for Component 1 (32 bits)\r
+\r
+\r
+#define R_SPI_FDBAR_FLASH_MAP0           0x14  ///< Flash MAP 0\r
+#define N_SPI_FDBAR_NC                   8       ///<< Number Of Components\r
+#define B_SPI_FDBAR_NC                   0x00000300 ///< Number Of Components\r
+\r
+#define R_SPI_FDBAR_FLASH_MAP1           0x18  ///< Flash MAP 1\r
+#define B_SPI_FDBAR_FPSBA                0x00FF0000 ///< Flash Strap Base Address\r
+\r
+\r
+//\r
+// Flash Component Base Address (FCBA) from Flash Region 0\r
+//\r
+#define R_SPI_FCBA_FLCOMP                0x00  ///< Flash Components Register\r
+#define B_SPI_FLCOMP_COMP1_MASK          0x0F  ///< Flash Component 1 Density\r
+\r
+\r
+#endif\r
diff --git a/UefiPayloadPkg/Library/SpiFlashLib/SpiCommon.h b/UefiPayloadPkg/Library/SpiFlashLib/SpiCommon.h
new file mode 100644 (file)
index 0000000..e4f4ad9
--- /dev/null
@@ -0,0 +1,208 @@
+/** @file\r
+  Header file for the SPI flash module.\r
+\r
+  Copyright (c) 2017 - 2021, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#ifndef SPI_COMMON_LIB_H_\r
+#define SPI_COMMON_LIB_H_\r
+\r
+#include <PiDxe.h>\r
+#include <Uefi/UefiBaseType.h>\r
+#include <IndustryStandard/Pci30.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/SpiFlashLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/TimerLib.h>\r
+#include <Guid/SpiFlashInfoGuid.h>\r
+#include "RegsSpi.h"\r
+\r
+///\r
+/// Maximum time allowed while waiting the SPI cycle to complete\r
+///  Wait Time = 6 seconds = 6000000 microseconds\r
+///  Wait Period = 10 microseconds\r
+///\r
+#define WAIT_TIME   6000000     ///< Wait Time = 6 seconds = 6000000 microseconds\r
+#define WAIT_PERIOD 10          ///< Wait Period = 10 microseconds\r
+\r
+///\r
+/// Flash cycle Type\r
+///\r
+typedef enum {\r
+  FlashCycleRead,\r
+  FlashCycleWrite,\r
+  FlashCycleErase,\r
+  FlashCycleReadSfdp,\r
+  FlashCycleReadJedecId,\r
+  FlashCycleWriteStatus,\r
+  FlashCycleReadStatus,\r
+  FlashCycleMax\r
+} FLASH_CYCLE_TYPE;\r
+\r
+///\r
+/// Flash Component Number\r
+///\r
+typedef enum {\r
+  FlashComponent0,\r
+  FlashComponent1,\r
+  FlashComponentMax\r
+} FLASH_COMPONENT_NUM;\r
+\r
+///\r
+/// Private data structure definitions for the driver\r
+///\r
+#define SC_SPI_PRIVATE_DATA_SIGNATURE  SIGNATURE_32 ('P', 'S', 'P', 'I')\r
+\r
+typedef struct {\r
+  UINTN                 Signature;\r
+  EFI_HANDLE            Handle;\r
+  UINT32                AcpiTmrReg;\r
+  UINTN                 PchSpiBase;\r
+  UINT16                RegionPermission;\r
+  UINT32                SfdpVscc0Value;\r
+  UINT32                SfdpVscc1Value;\r
+  UINT32                StrapBaseAddress;\r
+  UINT8                 NumberOfComponents;\r
+  UINT16                Flags;\r
+  UINT32                Component1StartAddr;\r
+} SPI_INSTANCE;\r
+\r
+\r
+/**\r
+  Acquire SPI MMIO BAR\r
+\r
+  @param[in] PchSpiBase           PCH SPI PCI Base Address\r
+\r
+  @retval                         Return SPI BAR Address\r
+\r
+**/\r
+UINT32\r
+AcquireSpiBar0 (\r
+  IN  UINTN         PchSpiBase\r
+  );\r
+\r
+\r
+/**\r
+  Release SPI MMIO BAR. Do nothing.\r
+\r
+  @param[in] PchSpiBase           PCH SPI PCI Base Address\r
+\r
+  @retval None\r
+\r
+**/\r
+VOID\r
+ReleaseSpiBar0 (\r
+  IN  UINTN         PchSpiBase\r
+  );\r
+\r
+\r
+/**\r
+  This function is a hook for Spi to disable BIOS Write Protect\r
+\r
+  @param[in] PchSpiBase           PCH SPI PCI Base Address\r
+  @param[in] CpuSmmBwp            Need to disable CPU SMM Bios write protection or not\r
+\r
+  @retval EFI_SUCCESS             The protocol instance was properly initialized\r
+  @retval EFI_ACCESS_DENIED       The BIOS Region can only be updated in SMM phase\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DisableBiosWriteProtect (\r
+  IN  UINTN         PchSpiBase,\r
+  IN  UINT8         CpuSmmBwp\r
+  );\r
+\r
+/**\r
+  This function is a hook for Spi to enable BIOS Write Protect\r
+\r
+  @param[in] PchSpiBase           PCH SPI PCI Base Address\r
+  @param[in] CpuSmmBwp            Need to disable CPU SMM Bios write protection or not\r
+\r
+  @retval None\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+EnableBiosWriteProtect (\r
+  IN  UINTN         PchSpiBase,\r
+  IN  UINT8         CpuSmmBwp\r
+  );\r
+\r
+\r
+/**\r
+  This function disables SPI Prefetching and caching,\r
+  and returns previous BIOS Control Register value before disabling.\r
+\r
+  @param[in] PchSpiBase           PCH SPI PCI Base Address\r
+\r
+  @retval                         Previous BIOS Control Register value\r
+\r
+**/\r
+UINT8\r
+SaveAndDisableSpiPrefetchCache (\r
+  IN  UINTN         PchSpiBase\r
+  );\r
+\r
+/**\r
+  This function updates BIOS Control Register with the given value.\r
+\r
+  @param[in] PchSpiBase           PCH SPI PCI Base Address\r
+  @param[in] BiosCtlValue         BIOS Control Register Value to be updated\r
+\r
+  @retval None\r
+\r
+**/\r
+VOID\r
+SetSpiBiosControlRegister (\r
+  IN  UINTN         PchSpiBase,\r
+  IN  UINT8         BiosCtlValue\r
+  );\r
+\r
+\r
+/**\r
+  This function sends the programmed SPI command to the slave device.\r
+\r
+  @param[in] SpiRegionType        The SPI Region type for flash cycle which is listed in the Descriptor\r
+  @param[in] FlashCycleType       The Flash SPI cycle type list in HSFC (Hardware Sequencing Flash Control Register) register\r
+  @param[in] Address              The Flash Linear Address must fall within a region for which BIOS has access permissions.\r
+  @param[in] ByteCount            Number of bytes in the data portion of the SPI cycle.\r
+  @param[in,out] Buffer           Pointer to caller-allocated buffer containing the data received or sent during the SPI cycle.\r
+\r
+  @retval EFI_SUCCESS             SPI command completes successfully.\r
+  @retval EFI_DEVICE_ERROR        Device error, the command aborts abnormally.\r
+  @retval EFI_ACCESS_DENIED       Some unrecognized command encountered in hardware sequencing mode\r
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.\r
+**/\r
+EFI_STATUS\r
+SendSpiCmd (\r
+  IN     FLASH_REGION_TYPE  FlashRegionType,\r
+  IN     FLASH_CYCLE_TYPE   FlashCycleType,\r
+  IN     UINT32             Address,\r
+  IN     UINT32             ByteCount,\r
+  IN OUT UINT8              *Buffer\r
+  );\r
+\r
+/**\r
+  Wait execution cycle to complete on the SPI interface.\r
+\r
+  @param[in] PchSpiBar0           Spi MMIO base address\r
+  @param[in] ErrorCheck           TRUE if the SpiCycle needs to do the error check\r
+\r
+  @retval TRUE                    SPI cycle completed on the interface.\r
+  @retval FALSE                   Time out while waiting the SPI cycle to complete.\r
+                                  It's not safe to program the next command on the SPI interface.\r
+**/\r
+BOOLEAN\r
+WaitForSpiCycleComplete (\r
+  IN     UINT32             PchSpiBar0,\r
+  IN     BOOLEAN            ErrorCheck\r
+  );\r
+\r
+#endif\r
diff --git a/UefiPayloadPkg/Library/SpiFlashLib/SpiFlashLib.c b/UefiPayloadPkg/Library/SpiFlashLib/SpiFlashLib.c
new file mode 100644 (file)
index 0000000..71dfcef
--- /dev/null
@@ -0,0 +1,857 @@
+/** @file\r
+  Generic driver using Hardware Sequencing registers.\r
+\r
+  Copyright (c) 2017-2021, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+#include "SpiCommon.h"\r
+\r
+SPI_INSTANCE      *mSpiInstance = NULL;\r
+\r
+/**\r
+  Get SPI Instance from library global data..\r
+\r
+  @retval SpiInstance       Return SPI instance\r
+**/\r
+SPI_INSTANCE *\r
+GetSpiInstance (\r
+  VOID\r
+)\r
+{\r
+  if (mSpiInstance == NULL) {\r
+    mSpiInstance  = AllocatePool (sizeof(SPI_INSTANCE));\r
+    if (mSpiInstance == NULL) {\r
+      return NULL;\r
+    }\r
+    ZeroMem (mSpiInstance, sizeof(SPI_INSTANCE));\r
+  }\r
+\r
+  return mSpiInstance;\r
+}\r
+\r
+\r
+/**\r
+  Initialize an SPI library.\r
+\r
+  @retval EFI_SUCCESS             The protocol instance was properly initialized\r
+  @retval EFI_NOT_FOUND           The expected SPI info could not be found\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SpiConstructor (\r
+  VOID\r
+  )\r
+{\r
+  UINT32              ScSpiBar0;\r
+  UINT8               Comp0Density;\r
+  SPI_INSTANCE        *SpiInstance;\r
+  EFI_HOB_GUID_TYPE   *GuidHob;\r
+  SPI_FLASH_INFO      *SpiFlashInfo;\r
+\r
+  //\r
+  // Find SPI flash hob\r
+  //\r
+  GuidHob = GetFirstGuidHob (&gSpiFlashInfoGuid);\r
+  if (GuidHob == NULL) {\r
+    ASSERT (FALSE);\r
+    return EFI_NOT_FOUND;\r
+  }\r
+  SpiFlashInfo = (SPI_FLASH_INFO *) GET_GUID_HOB_DATA (GuidHob);\r
+\r
+  //\r
+  // Initialize the SPI instance\r
+  //\r
+  SpiInstance = GetSpiInstance ();\r
+  if (SpiInstance == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+  DEBUG ((DEBUG_INFO, "SpiInstance = %08X\n", SpiInstance));\r
+\r
+  SpiInstance->Signature  = SC_SPI_PRIVATE_DATA_SIGNATURE;\r
+  SpiInstance->Handle     = NULL;\r
+\r
+  //\r
+  // Check the SPI address\r
+  //\r
+  if ((SpiFlashInfo->SpiAddress.AddressSpaceId !=  EFI_ACPI_3_0_PCI_CONFIGURATION_SPACE) ||\r
+      (SpiFlashInfo->SpiAddress.RegisterBitWidth !=  32) ||\r
+      (SpiFlashInfo->SpiAddress.RegisterBitOffset !=  0) ||\r
+      (SpiFlashInfo->SpiAddress.AccessSize !=  EFI_ACPI_3_0_DWORD)){\r
+    DEBUG ((DEBUG_ERROR, "SPI FLASH HOB is not expected. need check the hob or enhance SPI flash driver.\n"));\r
+  }\r
+  SpiInstance->PchSpiBase = (UINT32)(UINTN)SpiFlashInfo->SpiAddress.Address;\r
+  SpiInstance->Flags      = SpiFlashInfo->Flags;\r
+  DEBUG ((DEBUG_INFO, "PchSpiBase at 0x%x\n", SpiInstance->PchSpiBase));\r
+\r
+  ScSpiBar0 = AcquireSpiBar0 (SpiInstance->PchSpiBase);\r
+  DEBUG ((DEBUG_INFO, "ScSpiBar0 at 0x%08X\n", ScSpiBar0));\r
+\r
+  if (ScSpiBar0 == 0) {\r
+    ASSERT (FALSE);\r
+  }\r
+\r
+  if ((MmioRead32 (ScSpiBar0 + R_SPI_HSFS) & B_SPI_HSFS_FDV) == 0) {\r
+    DEBUG ((DEBUG_ERROR, "SPI Flash descriptor invalid, cannot use Hardware Sequencing registers!\n"));\r
+    ASSERT (FALSE);\r
+  }\r
+\r
+  MmioOr32 (SpiInstance->PchSpiBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);\r
+  SpiInstance->RegionPermission = MmioRead16 (ScSpiBar0 + R_SPI_FRAP);\r
+  SpiInstance->SfdpVscc0Value   = MmioRead32 (ScSpiBar0 + R_SPI_LVSCC);\r
+  SpiInstance->SfdpVscc1Value   = MmioRead32 (ScSpiBar0 + R_SPI_UVSCC);\r
+\r
+  //\r
+  // Select to Flash Map 0 Register to get the number of flash Component\r
+  //\r
+  MmioAndThenOr32 (\r
+    ScSpiBar0 + R_SPI_FDOC,\r
+    (UINT32) (~(B_SPI_FDOC_FDSS_MASK | B_SPI_FDOC_FDSI_MASK)),\r
+    (UINT32) (V_SPI_FDOC_FDSS_FSDM | R_SPI_FDBAR_FLASH_MAP0)\r
+    );\r
+\r
+  //\r
+  // Copy Zero based Number Of Components\r
+  //\r
+  SpiInstance->NumberOfComponents = (UINT8) ((MmioRead16 (ScSpiBar0 + R_SPI_FDOD) & B_SPI_FDBAR_NC) >> N_SPI_FDBAR_NC);\r
+\r
+  MmioAndThenOr32 (\r
+    ScSpiBar0 + R_SPI_FDOC,\r
+    (UINT32) (~(B_SPI_FDOC_FDSS_MASK | B_SPI_FDOC_FDSI_MASK)),\r
+    (UINT32) (V_SPI_FDOC_FDSS_COMP | R_SPI_FCBA_FLCOMP)\r
+    );\r
+\r
+  //\r
+  // Copy Component 0 Density\r
+  //\r
+  Comp0Density = (UINT8) MmioRead32 (ScSpiBar0 + R_SPI_FDOD) & B_SPI_FLCOMP_COMP1_MASK;\r
+  SpiInstance->Component1StartAddr = (UINT32) (SIZE_512KB << Comp0Density);\r
+\r
+  //\r
+  // Select FLASH_MAP1 to get Flash SC Strap Base Address\r
+  //\r
+  MmioAndThenOr32 (\r
+    (ScSpiBar0 + R_SPI_FDOC),\r
+    (UINT32) (~(B_SPI_FDOC_FDSS_MASK | B_SPI_FDOC_FDSI_MASK)),\r
+    (UINT32) (V_SPI_FDOC_FDSS_FSDM | R_SPI_FDBAR_FLASH_MAP1)\r
+    );\r
+\r
+  SpiInstance->StrapBaseAddress = MmioRead32 (ScSpiBar0 + R_SPI_FDOD) & B_SPI_FDBAR_FPSBA;\r
+\r
+  //\r
+  // Align FPSBA with address bits for the SC Strap portion of flash descriptor\r
+  //\r
+  SpiInstance->StrapBaseAddress &= B_SPI_FDBAR_FPSBA;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Read data from the flash part.\r
+\r
+  @param[in] FlashRegionType      The Flash Region type for flash cycle which is listed in the Descriptor.\r
+  @param[in] Address              The Flash Linear Address must fall within a region for which BIOS has access permissions.\r
+  @param[in] ByteCount            Number of bytes in the data portion of the SPI cycle.\r
+  @param[out] Buffer              The Pointer to caller-allocated buffer containing the data received.\r
+                                  It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.\r
+\r
+  @retval EFI_SUCCESS             Command succeed.\r
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.\r
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SpiFlashRead (\r
+  IN     FLASH_REGION_TYPE  FlashRegionType,\r
+  IN     UINT32             Address,\r
+  IN     UINT32             ByteCount,\r
+  OUT    UINT8              *Buffer\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+\r
+  Status = SendSpiCmd (FlashRegionType, FlashCycleRead, Address, ByteCount, Buffer);\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Write data to the flash part.\r
+\r
+  @param[in] FlashRegionType      The Flash Region type for flash cycle which is listed in the Descriptor.\r
+  @param[in] Address              The Flash Linear Address must fall within a region for which BIOS has access permissions.\r
+  @param[in] ByteCount            Number of bytes in the data portion of the SPI cycle.\r
+  @param[in] Buffer               Pointer to caller-allocated buffer containing the data sent during the SPI cycle.\r
+\r
+  @retval EFI_SUCCESS             Command succeed.\r
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.\r
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SpiFlashWrite (\r
+  IN     FLASH_REGION_TYPE  FlashRegionType,\r
+  IN     UINT32             Address,\r
+  IN     UINT32             ByteCount,\r
+  IN     UINT8              *Buffer\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+\r
+  Status = SendSpiCmd (FlashRegionType, FlashCycleWrite, Address, ByteCount, Buffer);\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Erase some area on the flash part.\r
+\r
+  @param[in] FlashRegionType      The Flash Region type for flash cycle which is listed in the Descriptor.\r
+  @param[in] Address              The Flash Linear Address must fall within a region for which BIOS has access permissions.\r
+  @param[in] ByteCount            Number of bytes in the data portion of the SPI cycle.\r
+\r
+  @retval EFI_SUCCESS             Command succeed.\r
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.\r
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SpiFlashErase (\r
+  IN     FLASH_REGION_TYPE  FlashRegionType,\r
+  IN     UINT32             Address,\r
+  IN     UINT32             ByteCount\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+\r
+  Status = SendSpiCmd (FlashRegionType, FlashCycleErase, Address, ByteCount, NULL);\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Read SFDP data from the flash part.\r
+\r
+  @param[in] ComponentNumber      The Component Number for chip select\r
+  @param[in] ByteCount            Number of bytes in SFDP data portion of the SPI cycle, the max number is 64\r
+  @param[out] SfdpData            The Pointer to caller-allocated buffer containing the SFDP data received\r
+                                  It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.\r
+\r
+  @retval EFI_SUCCESS             Command succeed.\r
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.\r
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SpiFlashReadSfdp (\r
+  IN     UINT8              ComponentNumber,\r
+  IN     UINT32             ByteCount,\r
+  OUT    UINT8              *SfdpData\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  UINT32                    Address;\r
+  SPI_INSTANCE              *SpiInstance;\r
+\r
+  SpiInstance = GetSpiInstance ();\r
+  if (SpiInstance == NULL) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  if ((ByteCount > 64) || (ComponentNumber > SpiInstance->NumberOfComponents)) {\r
+    ASSERT (FALSE);\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Address = 0;\r
+  if (ComponentNumber == FlashComponent1) {\r
+    Address = SpiInstance->Component1StartAddr;\r
+  }\r
+\r
+  Status = SendSpiCmd (0, FlashCycleReadSfdp, Address, ByteCount, SfdpData);\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Read Jedec Id from the flash part.\r
+\r
+  @param[in] ComponentNumber      The Component Number for chip select\r
+  @param[in] ByteCount            Number of bytes in JedecId data portion of the SPI cycle, the data size is 3 typically\r
+  @param[out] JedecId             The Pointer to caller-allocated buffer containing JEDEC ID received\r
+                                  It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.\r
+\r
+  @retval EFI_SUCCESS             Command succeed.\r
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.\r
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SpiFlashReadJedecId (\r
+  IN     UINT8              ComponentNumber,\r
+  IN     UINT32             ByteCount,\r
+  OUT    UINT8              *JedecId\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  UINT32                    Address;\r
+  SPI_INSTANCE              *SpiInstance;\r
+\r
+  SpiInstance = GetSpiInstance ();\r
+  if (SpiInstance == NULL) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  if (ComponentNumber > SpiInstance->NumberOfComponents) {\r
+    ASSERT (FALSE);\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Address = 0;\r
+  if (ComponentNumber == FlashComponent1) {\r
+    Address = SpiInstance->Component1StartAddr;\r
+  }\r
+\r
+  Status = SendSpiCmd (0, FlashCycleReadJedecId, Address, ByteCount, JedecId);\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Write the status register in the flash part.\r
+\r
+  @param[in] ByteCount            Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically\r
+  @param[in] StatusValue          The Pointer to caller-allocated buffer containing the value of Status register writing\r
+\r
+  @retval EFI_SUCCESS             Command succeed.\r
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.\r
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SpiFlashWriteStatus (\r
+  IN     UINT32             ByteCount,\r
+  IN     UINT8              *StatusValue\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+\r
+  Status = SendSpiCmd (0, FlashCycleWriteStatus, 0, ByteCount, StatusValue);\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Read status register in the flash part.\r
+\r
+  @param[in] ByteCount            Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically\r
+  @param[out] StatusValue         The Pointer to caller-allocated buffer containing the value of Status register received.\r
+\r
+  @retval EFI_SUCCESS             Command succeed.\r
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.\r
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SpiFlashReadStatus (\r
+  IN     UINT32             ByteCount,\r
+  OUT    UINT8              *StatusValue\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+\r
+  Status = SendSpiCmd (0, FlashCycleReadStatus, 0, ByteCount, StatusValue);\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Read SC Soft Strap Values\r
+\r
+  @param[in] SoftStrapAddr        SC Soft Strap address offset from FPSBA.\r
+  @param[in] ByteCount            Number of bytes in SoftStrap data portion of the SPI cycle\r
+  @param[out] SoftStrapValue      The Pointer to caller-allocated buffer containing SC Soft Strap Value.\r
+                                  It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.\r
+\r
+  @retval EFI_SUCCESS             Command succeed.\r
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.\r
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SpiReadPchSoftStrap (\r
+  IN     UINT32             SoftStrapAddr,\r
+  IN     UINT32             ByteCount,\r
+  OUT    UINT8              *SoftStrapValue\r
+  )\r
+{\r
+  UINT32                    StrapFlashAddr;\r
+  EFI_STATUS                Status;\r
+  SPI_INSTANCE              *SpiInstance;\r
+\r
+  SpiInstance = GetSpiInstance ();\r
+  if (SpiInstance == NULL) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  ASSERT (SpiInstance->StrapBaseAddress != 0);\r
+  //\r
+  // SC Strap Flash Address = FPSBA + RamAddr\r
+  //\r
+  StrapFlashAddr = SpiInstance->StrapBaseAddress + SoftStrapAddr;\r
+\r
+  Status = SendSpiCmd (FlashRegionDescriptor, FlashCycleRead, StrapFlashAddr, ByteCount, SoftStrapValue);\r
+  return Status;\r
+}\r
+\r
+/**\r
+  This function sends the programmed SPI command to the slave device.\r
+\r
+  @param[in] FlashRegionType      The SPI Region type for flash cycle which is listed in the Descriptor\r
+  @param[in] FlashCycleType       The Flash SPI cycle type list in HSFC (Hardware Sequencing Flash Control Register) register\r
+  @param[in] Address              The Flash Linear Address must fall within a region for which BIOS has access permissions.\r
+  @param[in] ByteCount            Number of bytes in the data portion of the SPI cycle.\r
+  @param[in,out] Buffer           Pointer to caller-allocated buffer containing the data received or sent during the SPI cycle.\r
+\r
+  @retval EFI_SUCCESS             SPI command completes successfully.\r
+  @retval EFI_DEVICE_ERROR        Device error, the command aborts abnormally.\r
+  @retval EFI_ACCESS_DENIED       Some unrecognized command encountered in hardware sequencing mode\r
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.\r
+**/\r
+EFI_STATUS\r
+SendSpiCmd (\r
+  IN     FLASH_REGION_TYPE  FlashRegionType,\r
+  IN     FLASH_CYCLE_TYPE   FlashCycleType,\r
+  IN     UINT32             Address,\r
+  IN     UINT32             ByteCount,\r
+  IN OUT UINT8              *Buffer\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  UINT32                    Index;\r
+  UINTN                     SpiBaseAddress;\r
+  UINT32                    ScSpiBar0;\r
+  UINT32                    LimitAddress;\r
+  UINT32                    HardwareSpiAddr;\r
+  UINT16                    PermissionBit;\r
+  UINT32                    SpiDataCount;\r
+  UINT32                    FlashCycle;\r
+  UINT8                     BiosCtlSave;\r
+  SPI_INSTANCE              *SpiInstance;\r
+  UINT32                    Data32;\r
+\r
+  SpiInstance = GetSpiInstance ();\r
+  if (SpiInstance == NULL) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  Status         = EFI_SUCCESS;\r
+  SpiBaseAddress = SpiInstance->PchSpiBase;\r
+  ScSpiBar0      = AcquireSpiBar0 (SpiBaseAddress);\r
+  BiosCtlSave    = 0;\r
+  SpiInstance->RegionPermission = MmioRead16 (ScSpiBar0 + R_SPI_FRAP);\r
+\r
+  //\r
+  // If it's write cycle, disable Prefetching, Caching and disable BIOS Write Protect\r
+  //\r
+  if ((FlashCycleType == FlashCycleWrite) || (FlashCycleType == FlashCycleErase)) {\r
+    Status = DisableBiosWriteProtect (SpiBaseAddress, mSpiInstance->Flags & FLAGS_SPI_DISABLE_SMM_WRITE_PROTECT);\r
+    if (EFI_ERROR (Status)) {\r
+      goto SendSpiCmdEnd;\r
+    }\r
+    BiosCtlSave = SaveAndDisableSpiPrefetchCache (SpiBaseAddress);\r
+  }\r
+\r
+  //\r
+  // Make sure it's safe to program the command.\r
+  //\r
+  if (!WaitForSpiCycleComplete (ScSpiBar0, FALSE)) {\r
+    Status = EFI_DEVICE_ERROR;\r
+    goto SendSpiCmdEnd;\r
+  }\r
+\r
+  HardwareSpiAddr = Address;\r
+  if ((FlashCycleType == FlashCycleRead) ||\r
+      (FlashCycleType == FlashCycleWrite) ||\r
+      (FlashCycleType == FlashCycleErase)) {\r
+\r
+    switch (FlashRegionType) {\r
+    case FlashRegionDescriptor:\r
+      if (FlashCycleType == FlashCycleRead) {\r
+        PermissionBit = B_SPI_FRAP_BRRA_FLASHD;\r
+      } else {\r
+        PermissionBit = B_SPI_FRAP_BRWA_FLASHD;\r
+      }\r
+      Data32 = MmioRead32 (ScSpiBar0 + R_SPI_FREG0_FLASHD);\r
+      HardwareSpiAddr += (Data32 & B_SPI_FREG0_BASE_MASK) << N_SPI_FREG0_BASE;\r
+      LimitAddress     = (Data32 & B_SPI_FREG0_LIMIT_MASK) >> N_SPI_FREG0_LIMIT;\r
+      break;\r
+\r
+    case FlashRegionBios:\r
+      if (FlashCycleType == FlashCycleRead) {\r
+        PermissionBit = B_SPI_FRAP_BRRA_BIOS;\r
+      } else {\r
+        PermissionBit = B_SPI_FRAP_BRWA_BIOS;\r
+      }\r
+      Data32 = MmioRead32 (ScSpiBar0 + R_SPI_FREG1_BIOS);\r
+      HardwareSpiAddr += (Data32 & B_SPI_FREG1_BASE_MASK) << N_SPI_FREG1_BASE;\r
+      LimitAddress     = (Data32 & B_SPI_FREG1_LIMIT_MASK) >> N_SPI_FREG1_LIMIT;\r
+      break;\r
+\r
+    case FlashRegionMe:\r
+      if (FlashCycleType == FlashCycleRead) {\r
+        PermissionBit = B_SPI_FRAP_BRRA_SEC;\r
+      } else {\r
+        PermissionBit = B_SPI_FRAP_BRWA_SEC;\r
+      }\r
+      Data32 = MmioRead32 (ScSpiBar0 + R_SPI_FREG2_SEC);\r
+      HardwareSpiAddr += (Data32 & B_SPI_FREG2_BASE_MASK) << N_SPI_FREG2_BASE;\r
+      LimitAddress     = (Data32 & B_SPI_FREG2_LIMIT_MASK) >> N_SPI_FREG2_LIMIT;\r
+      break;\r
+\r
+    case FlashRegionGbE:\r
+      if (FlashCycleType == FlashCycleRead) {\r
+        PermissionBit = B_SPI_FRAP_BRRA_GBE;\r
+      } else {\r
+        PermissionBit = B_SPI_FRAP_BRWA_GBE;\r
+      }\r
+      Data32 = MmioRead32 (ScSpiBar0 + R_SPI_FREG3_GBE);\r
+      HardwareSpiAddr += (Data32 & B_SPI_FREG3_BASE_MASK) << N_SPI_FREG3_BASE;\r
+      LimitAddress     = (Data32 & B_SPI_FREG3_LIMIT_MASK) >> N_SPI_FREG3_LIMIT;\r
+      break;\r
+\r
+    case FlashRegionPlatformData:\r
+      if (FlashCycleType == FlashCycleRead) {\r
+        PermissionBit = B_SPI_FRAP_BRRA_PLATFORM;\r
+      } else {\r
+        PermissionBit = B_SPI_FRAP_BRWA_PLATFORM;\r
+      }\r
+      Data32 = MmioRead32 (ScSpiBar0 + R_SPI_FREG4_PLATFORM_DATA);\r
+      HardwareSpiAddr += (Data32 & B_SPI_FREG4_BASE_MASK) << N_SPI_FREG4_BASE;\r
+      LimitAddress     = (Data32 & B_SPI_FREG4_LIMIT_MASK) >> N_SPI_FREG4_LIMIT;\r
+      break;\r
+\r
+    case FlashRegionAll:\r
+      //\r
+      // FlashRegionAll indicates address is relative to flash device\r
+      // No error checking for this case\r
+      //\r
+      LimitAddress = 0;\r
+      PermissionBit = 0;\r
+      break;\r
+\r
+    default:\r
+      Status = EFI_UNSUPPORTED;\r
+      goto SendSpiCmdEnd;\r
+    }\r
+\r
+    if ((LimitAddress != 0) && (Address > LimitAddress)) {\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto SendSpiCmdEnd;\r
+    }\r
+\r
+    //\r
+    // If the operation is read, but the region attribute is not read allowed, return error.\r
+    // If the operation is write, but the region attribute is not write allowed, return error.\r
+    //\r
+    if ((PermissionBit != 0) && ((SpiInstance->RegionPermission & PermissionBit) == 0)) {\r
+      Status = EFI_ACCESS_DENIED;\r
+      goto SendSpiCmdEnd;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Check for SC SPI hardware sequencing required commands\r
+  //\r
+  FlashCycle = 0;\r
+  switch (FlashCycleType) {\r
+  case FlashCycleRead:\r
+    FlashCycle = (UINT32) (V_SPI_HSFS_CYCLE_READ << N_SPI_HSFS_CYCLE);\r
+    break;\r
+\r
+  case FlashCycleWrite:\r
+    FlashCycle = (UINT32) (V_SPI_HSFS_CYCLE_WRITE << N_SPI_HSFS_CYCLE);\r
+    break;\r
+\r
+  case FlashCycleErase:\r
+    if (((ByteCount % SIZE_4KB) != 0) || ((HardwareSpiAddr % SIZE_4KB) != 0)) {\r
+      DEBUG ((DEBUG_ERROR, "Erase and erase size must be 4KB aligned. \n"));\r
+      ASSERT (FALSE);\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto SendSpiCmdEnd;\r
+    }\r
+    break;\r
+\r
+  case FlashCycleReadSfdp:\r
+    FlashCycle = (UINT32) (V_SPI_HSFS_CYCLE_READ_SFDP << N_SPI_HSFS_CYCLE);\r
+    break;\r
+\r
+  case FlashCycleReadJedecId:\r
+    FlashCycle = (UINT32) (V_SPI_HSFS_CYCLE_READ_JEDEC_ID << N_SPI_HSFS_CYCLE);\r
+    break;\r
+\r
+  case FlashCycleWriteStatus:\r
+    FlashCycle = (UINT32) (V_SPI_HSFS_CYCLE_WRITE_STATUS << N_SPI_HSFS_CYCLE);\r
+    break;\r
+\r
+  case FlashCycleReadStatus:\r
+    FlashCycle = (UINT32) (V_SPI_HSFS_CYCLE_READ_STATUS << N_SPI_HSFS_CYCLE);\r
+    break;\r
+\r
+  default:\r
+    //\r
+    // Unrecognized Operation\r
+    //\r
+    ASSERT (FALSE);\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto SendSpiCmdEnd;\r
+    break;\r
+  }\r
+\r
+  do {\r
+    SpiDataCount = ByteCount;\r
+    if ((FlashCycleType == FlashCycleRead) || (FlashCycleType == FlashCycleWrite)) {\r
+      //\r
+      // Trim at 256 byte boundary per operation,\r
+      // - SC SPI controller requires trimming at 4KB boundary\r
+      // - Some SPI chips require trimming at 256 byte boundary for write operation\r
+      // - Trimming has limited performance impact as we can read / write at most 64 byte\r
+      //   per operation\r
+      //\r
+      if (HardwareSpiAddr + ByteCount > ((HardwareSpiAddr + BIT8) &~(BIT8 - 1))) {\r
+        SpiDataCount = (((UINT32) (HardwareSpiAddr) + BIT8) &~(BIT8 - 1)) - (UINT32) (HardwareSpiAddr);\r
+      }\r
+      //\r
+      // Calculate the number of bytes to shift in/out during the SPI data cycle.\r
+      // Valid settings for the number of bytes during each data portion of the\r
+      // SC SPI cycles are: 0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 24, 32, 40, 48, 56, 64\r
+      //\r
+      if (SpiDataCount >= 64) {\r
+        SpiDataCount = 64;\r
+      } else if ((SpiDataCount &~0x07) != 0) {\r
+        SpiDataCount = SpiDataCount &~0x07;\r
+      }\r
+    }\r
+\r
+    if (FlashCycleType == FlashCycleErase) {\r
+      if (((ByteCount / SIZE_64KB) != 0) &&\r
+          ((ByteCount % SIZE_64KB) == 0) &&\r
+          ((HardwareSpiAddr % SIZE_64KB) == 0)) {\r
+        if (HardwareSpiAddr < SpiInstance->Component1StartAddr) {\r
+          //\r
+          // Check whether Component0 support 64k Erase\r
+          //\r
+          if ((SpiInstance->SfdpVscc0Value & B_SPI_LVSCC_EO_64K) != 0) {\r
+            SpiDataCount = SIZE_64KB;\r
+          } else {\r
+            SpiDataCount = SIZE_4KB;\r
+          }\r
+        } else {\r
+          //\r
+          // Check whether Component1 support 64k Erase\r
+          //\r
+          if ((SpiInstance->SfdpVscc1Value & B_SPI_LVSCC_EO_64K) != 0) {\r
+            SpiDataCount = SIZE_64KB;\r
+          } else {\r
+            SpiDataCount = SIZE_4KB;\r
+          }\r
+        }\r
+      } else {\r
+        SpiDataCount = SIZE_4KB;\r
+      }\r
+      if (SpiDataCount == SIZE_4KB) {\r
+        FlashCycle = (UINT32) (V_SPI_HSFS_CYCLE_4K_ERASE << N_SPI_HSFS_CYCLE);\r
+      } else {\r
+        FlashCycle = (UINT32) (V_SPI_HSFS_CYCLE_64K_ERASE << N_SPI_HSFS_CYCLE);\r
+      }\r
+    }\r
+\r
+    //\r
+    // If it's write cycle, load data into the SPI data buffer.\r
+    //\r
+    if ((FlashCycleType == FlashCycleWrite) || (FlashCycleType == FlashCycleWriteStatus)) {\r
+      if ((SpiDataCount & 0x07) != 0) {\r
+        //\r
+        // Use Byte write if Data Count is 0, 1, 2, 3, 4, 5, 6, 7\r
+        //\r
+        for (Index = 0; Index < SpiDataCount; Index++) {\r
+          MmioWrite8 (ScSpiBar0 + R_SPI_FDATA00 + Index, Buffer[Index]);\r
+        }\r
+      } else {\r
+        //\r
+        // Use Dword write if Data Count is 8, 16, 24, 32, 40, 48, 56, 64\r
+        //\r
+        for (Index = 0; Index < SpiDataCount; Index += sizeof (UINT32)) {\r
+          MmioWrite32 (ScSpiBar0 + R_SPI_FDATA00 + Index, *(UINT32 *) (Buffer + Index));\r
+        }\r
+      }\r
+    }\r
+\r
+    //\r
+    // Set the Flash Address\r
+    //\r
+    MmioWrite32 (ScSpiBar0 + R_SPI_FADDR, (UINT32) (HardwareSpiAddr & B_SPI_FADDR_MASK));\r
+\r
+    //\r
+    // Set Data count, Flash cycle, and Set Go bit to start a cycle\r
+    //\r
+    MmioAndThenOr32 (\r
+      ScSpiBar0 + R_SPI_HSFS,\r
+      (UINT32) (~(B_SPI_HSFS_FDBC_MASK | B_SPI_HSFS_CYCLE_MASK)),\r
+      (UINT32) (((SpiDataCount - 1) << N_SPI_HSFS_FDBC) | FlashCycle | B_SPI_HSFS_CYCLE_FGO)\r
+      );\r
+\r
+    //\r
+    // Wait for command execution complete.\r
+    //\r
+    if (!WaitForSpiCycleComplete (ScSpiBar0, TRUE)) {\r
+      Status = EFI_DEVICE_ERROR;\r
+      goto SendSpiCmdEnd;\r
+    }\r
+\r
+    //\r
+    // If it's read cycle, load data into the caller's buffer.\r
+    //\r
+    if ((FlashCycleType == FlashCycleRead) ||\r
+        (FlashCycleType == FlashCycleReadSfdp) ||\r
+        (FlashCycleType == FlashCycleReadJedecId) ||\r
+        (FlashCycleType == FlashCycleReadStatus)) {\r
+      if ((SpiDataCount & 0x07) != 0) {\r
+        //\r
+        // Use Byte read if Data Count is 0, 1, 2, 3, 4, 5, 6, 7\r
+        //\r
+        for (Index = 0; Index < SpiDataCount; Index++) {\r
+          Buffer[Index] = MmioRead8 (ScSpiBar0 + R_SPI_FDATA00 + Index);\r
+        }\r
+      } else {\r
+        //\r
+        // Use Dword read if Data Count is 8, 16, 24, 32, 40, 48, 56, 64\r
+        //\r
+        for (Index = 0; Index < SpiDataCount; Index += sizeof (UINT32)) {\r
+          *(UINT32 *) (Buffer + Index) = MmioRead32 (ScSpiBar0 + R_SPI_FDATA00 + Index);\r
+        }\r
+      }\r
+    }\r
+\r
+    HardwareSpiAddr += SpiDataCount;\r
+    Buffer          += SpiDataCount;\r
+    ByteCount       -= SpiDataCount;\r
+  } while (ByteCount > 0);\r
+\r
+SendSpiCmdEnd:\r
+  ///\r
+  /// Restore the settings for SPI Prefetching and Caching and enable BIOS Write Protect\r
+  ///\r
+  if ((FlashCycleType == FlashCycleWrite) || (FlashCycleType == FlashCycleErase)) {\r
+    EnableBiosWriteProtect (SpiBaseAddress,  mSpiInstance->Flags & FLAGS_SPI_DISABLE_SMM_WRITE_PROTECT);\r
+    SetSpiBiosControlRegister (SpiBaseAddress, BiosCtlSave);\r
+  }\r
+\r
+  ReleaseSpiBar0 (SpiBaseAddress);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Wait execution cycle to complete on the SPI interface.\r
+\r
+  @param[in] ScSpiBar0            Spi MMIO base address\r
+  @param[in] ErrorCheck           TRUE if the SpiCycle needs to do the error check\r
+\r
+  @retval TRUE                    SPI cycle completed on the interface.\r
+  @retval FALSE                   Time out while waiting the SPI cycle to complete.\r
+                                  It's not safe to program the next command on the SPI interface.\r
+**/\r
+BOOLEAN\r
+WaitForSpiCycleComplete (\r
+  IN     UINT32             ScSpiBar0,\r
+  IN     BOOLEAN            ErrorCheck\r
+  )\r
+{\r
+  UINT64                    WaitTicks;\r
+  UINT64                    WaitCount;\r
+  UINT32                    Data32;\r
+\r
+  //\r
+  // Convert the wait period allowed into to tick count\r
+  //\r
+  WaitCount = WAIT_TIME / WAIT_PERIOD;\r
+  //\r
+  // Wait for the SPI cycle to complete.\r
+  //\r
+  for (WaitTicks = 0; WaitTicks < WaitCount; WaitTicks++) {\r
+    Data32 = MmioRead32 (ScSpiBar0 + R_SPI_HSFS);\r
+    if ((Data32 & B_SPI_HSFS_SCIP) == 0) {\r
+      MmioWrite32 (ScSpiBar0 + R_SPI_HSFS, B_SPI_HSFS_FCERR | B_SPI_HSFS_FDONE);\r
+      if (((Data32 & B_SPI_HSFS_FCERR) != 0) && ErrorCheck) {\r
+        return FALSE;\r
+      } else {\r
+        return TRUE;\r
+      }\r
+    }\r
+    MicroSecondDelay ( WAIT_PERIOD);\r
+  }\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Get the SPI region base and size, based on the enum type\r
+\r
+  @param[in] FlashRegionType      The Flash Region type for for the base address which is listed in the Descriptor.\r
+  @param[out] BaseAddress         The Flash Linear Address for the Region 'n' Base\r
+  @param[out] RegionSize          The size for the Region 'n'\r
+\r
+  @retval EFI_SUCCESS             Read success\r
+  @retval EFI_INVALID_PARAMETER   Invalid region type given\r
+  @retval EFI_DEVICE_ERROR        The region is not used\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SpiGetRegionAddress (\r
+  IN     FLASH_REGION_TYPE  FlashRegionType,\r
+  OUT    UINT32             *BaseAddress, OPTIONAL\r
+  OUT    UINT32             *RegionSize OPTIONAL\r
+  )\r
+{\r
+  UINT32                    ScSpiBar0;\r
+  UINT32                    ReadValue;\r
+  UINT32                    Base;\r
+  SPI_INSTANCE             *SpiInstance;\r
+\r
+  if (FlashRegionType >= FlashRegionMax) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  SpiInstance = GetSpiInstance();\r
+  if (SpiInstance == NULL) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  if (FlashRegionType == FlashRegionAll) {\r
+    if (BaseAddress != NULL) {\r
+      *BaseAddress  = 0;\r
+    }\r
+    if (RegionSize != NULL) {\r
+      *RegionSize  = SpiInstance->Component1StartAddr;\r
+    }\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  ScSpiBar0 = AcquireSpiBar0 (SpiInstance->PchSpiBase);\r
+  ReadValue = MmioRead32 (ScSpiBar0 + R_SPI_FREG0_FLASHD + S_SPI_FREGX * (UINT32) FlashRegionType);\r
+  ReleaseSpiBar0 (SpiInstance->PchSpiBase);\r
+\r
+  //\r
+  // If the region is not used, the Region Base is 7FFFh and Region Limit is 0000h\r
+  //\r
+  if (ReadValue == B_SPI_FREGX_BASE_MASK) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  Base = (ReadValue & B_SPI_FREG1_BASE_MASK) << N_SPI_FREG1_BASE;\r
+  if (BaseAddress != NULL) {\r
+    *BaseAddress = Base;\r
+  }\r
+\r
+  if (RegionSize != NULL) {\r
+    *RegionSize =  ((((ReadValue & B_SPI_FREGX_LIMIT_MASK) >> N_SPI_FREGX_LIMIT) + 1) <<\r
+                     N_SPI_FREGX_LIMIT_REPR) - Base;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
diff --git a/UefiPayloadPkg/Library/SpiFlashLib/SpiFlashLib.inf b/UefiPayloadPkg/Library/SpiFlashLib/SpiFlashLib.inf
new file mode 100644 (file)
index 0000000..3e02307
--- /dev/null
@@ -0,0 +1,48 @@
+## @file\r
+#  Library instance for SPI flash library using SPI hardware sequence\r
+#\r
+#  Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>\r
+#  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = SpiFlashLib\r
+  FILE_GUID                      = 6F96AFCB-DE89-4ca1-A63F-8703EE8FDE50\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = SpiFlashLib\r
+  CONSTRUCTOR                    = SpiConstructor\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64\r
+#\r
+\r
+[Sources]\r
+  RegsSpi.h\r
+  SpiCommon.h\r
+  PchSpi.c\r
+  SpiFlashLib.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  UefiPayloadPkg/UefiPayloadPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  PcdLib\r
+  IoLib\r
+  PciLib\r
+  HobLib\r
+  TimerLib\r
+  BaseLib\r
+\r
+[Guids]\r
+  gSpiFlashInfoGuid\r
+\r
+[Pcd]\r
+  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress\r
index 4c3bd0c2eb698a6cffe3f1e45716f5dac02bae2e..3ffdce550d11367cb7358e2b11976d01c0599431 100644 (file)
@@ -37,6 +37,7 @@
   gUefiSerialPortInfoGuid  = { 0x6c6872fe, 0x56a9, 0x4403, { 0xbb, 0x98, 0x95, 0x8d, 0x62, 0xde, 0x87, 0xf1 } }\r
   gLoaderMemoryMapInfoGuid = { 0xa1ff7424, 0x7a1a, 0x478e, { 0xa9, 0xe4, 0x92, 0xf3, 0x57, 0xd1, 0x28, 0x32 } }\r
 \r
+  gSpiFlashInfoGuid        = { 0x2d4aac1b, 0x91a5, 0x4cd5, { 0x9b, 0x5c, 0xb4, 0x0f, 0x5d, 0x28, 0x51, 0xa1 } }\r
   gSmmRegisterInfoGuid     = { 0xaa9bd7a7, 0xcafb, 0x4499, { 0xa4, 0xa9, 0xb, 0x34, 0x6b, 0x40, 0xa6, 0x22 } }\r
   gS3CommunicationGuid     = { 0x88e31ba1, 0x1856, 0x4b8b, { 0xbb, 0xdf, 0xf8, 0x16, 0xdd, 0x94, 0xa, 0xef } }\r
 \r