public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [Patch][edk2-platforms/devel-MinnowBoard3 1/2] Add BPDT library.
@ 2017-03-10  8:05 zwei4
  2017-03-10  8:05 ` [Patch][edk2-platforms/devel-MinnowBoard3 2/2] Add PEI SPI library zwei4
  0 siblings, 1 reply; 2+ messages in thread
From: zwei4 @ 2017-03-10  8:05 UTC (permalink / raw)
  To: edk2-devel

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: zwei4 <david.wei@intel.com>
---
 Silicon/BroxtonSoC/BroxtonSiPkg/BroxtonSiPkg.dec   |   4 +-
 .../BroxtonSiPkg/Include/Library/BpdtLib.h         | 240 +++++++
 .../BroxtonSiPkg/Library/BpdtLib/BpdtLib.c         | 798 +++++++++++++++++++++
 .../BroxtonSiPkg/Library/BpdtLib/BpdtLib.inf       |  49 ++
 4 files changed, 1090 insertions(+), 1 deletion(-)
 create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Include/Library/BpdtLib.h
 create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/BpdtLib/BpdtLib.c
 create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/BpdtLib/BpdtLib.inf

diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/BroxtonSiPkg.dec b/Silicon/BroxtonSoC/BroxtonSiPkg/BroxtonSiPkg.dec
index 2ee4008c6..da728e888 100644
--- a/Silicon/BroxtonSoC/BroxtonSiPkg/BroxtonSiPkg.dec
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/BroxtonSiPkg.dec
@@ -238,7 +238,9 @@
   gDciConfigGuid                        = { 0x9af1e14a, 0xe6b7, 0x4b64, { 0xbb, 0x33, 0x9b, 0x1, 0x33, 0x4c, 0x24, 0xfe } }
   gP2sbConfigGuid                       = { 0x11354a0c, 0x781e, 0x44a1, { 0xa7, 0x87, 0xc0, 0x17, 0x8c, 0x8d, 0x57, 0xf } }
   gInterruptConfigGuid                  = { 0x097dccd0, 0xf570, 0x41f6, { 0x9d, 0xf0, 0x72, 0xe2, 0x5a, 0xbe, 0xd3, 0x98 } }
-
+  gEfiBpdtLibBp1DataGuid                = { 0x7a4ecf02, 0xa1cf, 0x4e42, { 0xb6, 0x33, 0xfe, 0x95, 0x54, 0xbb, 0x60, 0xf8 } }
+  gEfiBpdtLibBp2DataGuid                = { 0x75b0886e, 0xcd6a, 0x469f, { 0xae, 0x0b, 0x8c, 0xed, 0x90, 0x33, 0xd1, 0x99 } }
+  
 [Includes.common]
   Include
   Library
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Include/Library/BpdtLib.h b/Silicon/BroxtonSoC/BroxtonSiPkg/Include/Library/BpdtLib.h
new file mode 100644
index 000000000..87683ab90
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Include/Library/BpdtLib.h
@@ -0,0 +1,240 @@
+/** @file
+  Interface definitons of BPDT(Boot Partition Description Table) library.
+
+  Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __BPDT_HEADER_H__
+#define __BPDT_HEADER_H__
+
+extern EFI_GUID gEfiBpdtLibBp1DataGuid;
+extern EFI_GUID gEfiBpdtLibBp2DataGuid;
+
+#define BPDT_SIGN_GREEN       0x000055AA    //Normal Boot
+#define BPDT_SIGN_YELLOW      0x00AA55AA    //Recovery Boot
+
+typedef enum {
+  BootPart1,
+  BootPart2,
+  BootPartMax
+} BOOT_PARITION_SELECT;
+
+typedef struct {
+  VOID   *DataPtr;
+  UINT32  Size;
+} BPDT_PAYLOAD_DATA;
+
+typedef enum {
+  BpdtOemSmip,      // 0
+  BpdtCseRbe,       // 1
+  BpdtCseBup,       // 2
+  BpdtUcode,        // 3
+  BpdtIbb,          // 4
+  BpdtSbpdt,        // 5 - Secondary BPDT within a BPDT Entry
+  BpdtObb,          // 6
+  BpdtCseMain,      // 7
+  BpdtIsh,          // 8
+  BpdtCseIdlm,      // 9
+  BpdtIfpOverride,  //10
+  BpdtDebugTokens,  //11
+  BpdtUfsPhyConfig, //12
+  BpdtUfsGppLunId,  //13
+  BpdtPmc,          //14
+  BpdtIunit,        //15
+  BpdtMaxType
+} BPDT_ENTRY_TYPES;
+
+typedef struct {
+  UINT32  Signature;
+  UINT16  DscCount;
+  UINT16  BpdtVer;
+  UINT32  RedundantBlockXorSum;
+  UINT32  IfwiVer;
+  UINT64  FitToolVer;
+} BPDT_HEADER;
+
+
+typedef struct {
+  UINT16  Type;
+  UINT16  Flags;
+  UINT32  LbpOffset;  // Offset of Sub-Partition starting from base of LBP
+  UINT32  Size;       // Size of the Sub-Partition
+} BPDT_ENTRY;
+
+
+typedef struct {
+  UINT32  HeaderMarker;
+  UINT32  NumOfEntries;
+  UINT8   HeaderVersion;
+  UINT8   EntryVersion;
+  UINT8   HeaderLength;
+  UINT8   Checksum;
+  UINT32  SubPartName;
+} SUBPART_DIR_HEADER;
+
+
+typedef struct {
+  CHAR8   EntryName[12];
+  UINT32  EntryOffset:25;
+  UINT32  Huffman:1;
+  UINT32  Reserved1:6;
+  UINT32  EntrySize;
+  UINT32  Reserved2;
+} SUBPART_DIR_ENTRY;
+
+typedef enum {
+  HashIbbl = 0,
+  HashIbbm,
+  HashObb
+} BPM_HASH_SELECT;
+
+///
+/// Boot Policy Manifest (BPM) data structure
+///
+typedef struct {
+  UINT32                    ExtType;       ///< 0x00000013  (Little-Endian)
+  UINT32                    ExtLength;
+  UINT32                    NemData;
+  UINT32                    IbblHashAlgo;  ///< 0x00000002
+  UINT32                    IbblHashSize;  ///< 0x00000020
+  UINT8                     IbblHash[0x20];
+  UINT32                    IbbmHashAlgo;
+  UINT32                    IbbmHashSize;
+  UINT8                     IbbmHash[0x20];
+  UINT32                    ObbHashAlgo;
+  UINT32                    ObbHashSize;
+  UINT8                     ObbHash[0x20];
+  UINT8                     Reserved[124]; ///< Others data
+} BPM_DATA_FILE;
+
+
+/**
+  Locate and return a pointer to the selected Logical Boot Partition.
+
+  For block devices, the address will be the location in memory that the BP was copied to.
+  For memory mapped device (eg SPI), the address will be the location on the device.
+
+  @param[in]    LbpSel         Which BP to locate on the boot device
+  @param[out]   Address        The address of the selected BP on the boot device
+
+  @retval       EFI_SUCCESS    The operation completed successfully.
+  @retval       other          The selected BP could not be found.
+**/
+EFI_STATUS
+EFIAPI
+GetBootPartitionPointer (
+  IN  BOOT_PARITION_SELECT  LbpSel,
+  OUT VOID                  **LbpPointer
+  );
+
+/**
+  Parse the Boot Partition Descriptor Table of the provided Logical Boot Partition.
+  Note: "payload" is the Sub-Partition pointed to by the BDPT Entry of the given type.
+
+  @param[in]   LbpPointer      Pointer to the start of the BootPartition to be parsed
+  @param[in]   EntryType       The entry type of the subparition(payload) to look for
+  @param[out]  BpdtPayloadPtr  Address of the Struct to put the results into (MUST be allocated by caller)
+
+  @retval      EFI_SUCCESS     The operation completed successfully.
+**/
+EFI_STATUS
+EFIAPI
+GetBpdtPayloadDataRaw (
+  IN  VOID                *LbpPointer,
+  IN  BPDT_ENTRY_TYPES    EntryType,
+  OUT BPDT_PAYLOAD_DATA   *BpdtPayloadPtr
+  );
+
+/**
+  Parse the Boot Partition Descriptor Table on the selected Logical Boot Partition.
+  Takes the BP as input since some BPDT entry types can exist in both locations.
+  Note: "payload" is the Sub-Partition pointed to by the BDPT Entry of the given type.
+  
+  @param[in]   BpSel           Boot partition index
+  @param[in]   EntryType       The entry type of the subparition(payload) to look for
+  @param[out]   BpdtPayloadPtr Pointer to a Struct (in a HOB) containing the Size and Absolute address
+                               in memory(or spi) of the BPDT payload(subpart) of EntryType.
+                               If the caller shadows the Payload for performance, it should update this value
+
+  @retval  EFI_SUCCESS         The operation completed successfully.
+**/
+EFI_STATUS
+EFIAPI
+GetBpdtPayloadData (
+  IN  BOOT_PARITION_SELECT  BpSel,
+  IN  BPDT_ENTRY_TYPES      EntryType,
+  OUT BPDT_PAYLOAD_DATA     **BpdtPayloadPtr
+  );
+
+
+/**
+  Search the Subpartition pointed to by BpdtPayloadPtr for a Directory entry with "EntryName",
+  then fill in the Struct pointed to by SubPartPayloadPtr with the Addres and Size of the Dir Entry.
+  Note: "payload" is the Data pointed to by the Directory Entry with the given name.
+
+  @param[in]   BpdtPayloadPtr     Location and Size of the Payload to search
+  @param[in]   EntryName          the String name of the Directory entry to look for
+  @param[out]  SubPartPayloadPtr  Address of the Struct to put the results into (MUST be allocated by caller)
+
+  @retval      EFI_SUCCESS        The operation completed successfully.
+**/
+EFI_STATUS
+EFIAPI
+GetSubPartitionPayloadData (
+  IN  BPDT_PAYLOAD_DATA     *BpdtPayloadPtr,
+  IN  CONST CHAR8           *EntryName,
+  OUT BPDT_PAYLOAD_DATA     *SubPartPayloadPtr
+  );
+
+
+/**
+  This is a wrapper function for using VerifyHashBpm that will only
+  check the hash for the payloads used during normal boot.
+
+  If you want to check other payloads (ie during recovery flow), then the
+  calling code should locate and pass in the payload directly to VerifyHashBpm().
+
+  @param[in]   PayloadSel   Which hash in BPM to compare with.
+
+  @retval      EFI_SUCCESS  The function completed successfully and the Hash matched.
+  @retval      other        An error occured when locating and computing the Hash.
+**/
+EFI_STATUS
+EFIAPI
+LocateAndVerifyHashBpm (
+  IN BPM_HASH_SELECT   PayloadSel
+  );
+
+
+/**
+  Computes the Hash of a given data block and compares to the one in the Boot Policy Metadata.
+
+  @param[in]  PayloadSel   Which hash in BPM to compare with.
+  @param[in]  PayloadPtr   Pointer to the begining of the data to be hashed.
+  @param[in]  DataSize     Size of the data to be hashed.
+  @param[in]  BpmPtr       Pointer to the BPM structure.
+
+  @retval     EFI_SUCCESS             If the function completed successfully.
+  @retval     EFI_ABORTED             If the attempt to compute the hash fails.
+  @retval     EFI_INVALID_PARAMETER   If the hash type or size in BPM is unsupported.
+  @retval     EFI_SECURITY_VIOLATION  If the has does not match the one in BPM.
+**/
+EFI_STATUS
+EFIAPI
+VerifyHashBpm (
+  IN BPM_HASH_SELECT   PayloadSel,
+  IN BPM_DATA_FILE     *BpmPtr,
+  IN VOID              *PayloadPtr,
+  IN UINT32            DataSize
+  );
+
+#endif
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/BpdtLib/BpdtLib.c b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/BpdtLib/BpdtLib.c
new file mode 100644
index 000000000..b65e8ae83
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/BpdtLib/BpdtLib.c
@@ -0,0 +1,798 @@
+/** @file
+  This file contains the implementation of BpdtLib library.
+
+  The library exposes an abstract interface for accessing boot data
+  stored in the BPDT format on the Logical Boot Partition of the boot device.
+
+  Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi.h>
+#include <SeCAccess.h>
+#include <PiPei.h>
+#include <Ppi/BlockIoPei.h>
+#include <Ppi/Spi.h>
+#include <Guid/FirmwareFileSystem2.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Library/ScPlatformLib.h>
+#include <Library/BpdtLib.h>
+#include <Library/PeiSpiInitLib.h>
+#include <Library/BaseCryptLib.h>
+
+#define DIR_HDR_SIGNATURE     SIGNATURE_32('$', 'C', 'P', 'D')
+#define DIR_ENTRY_NAME_SIZE   12   //This is spec defined to be bytes
+#define SPLIT_ENTRY_PART_1    BIT0
+#define SPLIT_ENTRY_PART_2    BIT1
+#define SPLIT_ENTRY_FLAGS     (BIT1 | BIT0)
+#define BPDT_HOB_DATA_SIZE    (sizeof(BPDT_PAYLOAD_DATA) * BpdtMaxType)
+#define SpiMmioBoundary       0xFFFC0000
+
+/**
+  Calculate the Address in SPI of the selected Boot Partition
+
+  @param[in]     BpSel                 Which BP to locate on the SPI
+  @param[out]    BpFlashLinearAddress  The linear flash address of selected BP
+  @param[out]    LbpPointer            A pointer to the selected Boot partition on this media
+
+  @retval        EFI_SUCCESS           The operation completed successfully.
+**/
+EFI_STATUS
+EFIAPI
+InternalGetBpSpi (
+  IN  BOOT_PARITION_SELECT  BpSel,
+  OUT UINT32                *BpFlashLinearAddress,
+  OUT VOID                  **LbpPointer
+  )
+{
+  UINT32  BiosAddr;
+
+  //
+  // Compute BP FlashLinearAddress.
+  //
+  switch (BpSel) {
+    case BootPart1:
+      *BpFlashLinearAddress = 0x1000;
+      break;
+    case BootPart2:
+      if (HeciPciRead16(R_SEC_DevID_VID) != 0xFFFF) {
+        //
+        // BP2 linear address is the midpoint between BIOS base and expansion data base.
+        //
+        *BpFlashLinearAddress = (GetSpiFlashRegionBase(BIOS) + GetSpiFlashRegionBase(DeviceExpansion1)) / 2;
+      } else {
+
+        *BpFlashLinearAddress = 0x00800000>>1; 
+      }
+      break;
+    default:
+      return EFI_NOT_FOUND;
+      break;
+  }
+  DEBUG ((DEBUG_INFO, "BpFlashLinearAddress = %X\n", *BpFlashLinearAddress));
+  
+  //
+  // Calculate Boot partition physical address.
+  // FLA[26:0] <= (Flash_Region_Limit) - (FFFF_FFFCh - bios_address)
+  //
+  BiosAddr = GetSpiFlashRegionLimit(BIOS) + 0xFFC - *BpFlashLinearAddress;
+  *LbpPointer = (VOID *)((UINTN)0xFFFFFFFC - BiosAddr);
+  DEBUG ((DEBUG_INFO, "Flash address of BP%d = %X\n", BpSel+1, *LbpPointer));
+
+  return EFI_SUCCESS;
+}
+
+/**
+  SPI CMD read w/a. Because the upper 256k of address space is mapped to CSE SRAM,
+  it cannot be directly accessed via MMIO from host.
+
+  @param[in]         BpSel                 Which BP to locate on the SPI
+  @param[in out]     CombinedSpiObb        Combined OBB data.       
+  
+  @retval            EFI_SUCCESS           The operation completed successfully.
+**/
+EFI_STATUS
+EFIAPI
+InternalCheckAndJoinUpperSpi (
+  IN      BOOT_PARITION_SELECT  BpSel,
+  IN OUT  BPDT_PAYLOAD_DATA     *CombinedSpiObb
+  )
+{
+  VOID                      *UpperSpiObb;
+  VOID                      *LbpPointer;
+  UINT32                    Bp2LinearAddr;
+  UINT32                    SpiPart1Size;
+  UINT32                    SpiPart2Size;
+  EFI_STATUS                Status;
+  SC_SPI_PROTOCOL           *SpiPpi;
+  CONST EFI_PEI_SERVICES    **PeiServices;
+
+  //
+  // Check if Obb part is in upper spi address space.
+  // If the entry is from emmc this will be false, it can only be true for SPI.
+  //
+  if ((UINT32)CombinedSpiObb->DataPtr + CombinedSpiObb->Size >= SpiMmioBoundary) {
+
+    //Get Linear Addr of BpSel (on BXT this will be BP2, since it is)
+    InternalGetBpSpi (BpSel, &Bp2LinearAddr, &LbpPointer);
+
+    SpiPart1Size = SpiMmioBoundary - (UINT32)CombinedSpiObb->DataPtr;
+    SpiPart2Size = CombinedSpiObb->Size - SpiPart1Size;
+
+    UpperSpiObb = AllocatePages (EFI_SIZE_TO_PAGES (CombinedSpiObb->Size));
+
+    CopyMem (UpperSpiObb, CombinedSpiObb->DataPtr, SpiPart1Size);  //Copy MemMapped part of Spi.
+
+    //
+    // Install ScSpi Ppi.
+    //
+    InstallScSpi ();
+    PeiServices = GetPeiServicesTablePointer ();
+    Status = (*PeiServices)->LocatePpi (
+                               PeiServices,
+                               &gScSpiPpiGuid,
+                               0,
+                               NULL,
+                               (VOID **) &SpiPpi
+                               );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "Cannot Locate gScSpiPpiGuid: %r. Halting system.\n", Status));
+      CpuDeadLoop ();
+    }
+
+    //
+    // Use SPI cmd to read entry into memory.
+    //
+    Status = SpiPpi->FlashRead (
+                       SpiPpi,
+                       FlashRegionBios,
+                       Bp2LinearAddr + SpiPart1Size,
+                       SpiPart2Size,
+                       (UINT8 *)((UINTN)UpperSpiObb + SpiPart1Size)
+                       );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "Read SPI fail: %r. Halting system.\n", Status));
+      CpuDeadLoop ();
+    }
+
+    CombinedSpiObb->DataPtr = UpperSpiObb;
+  }
+  return EFI_SUCCESS;
+}
+
+
+/**
+  This function will handle locating and combining both parts of Split Obb,
+  regardless of which BootPartition that part1 or part2 is located on.
+
+  @param[in]     BpSel            Which BP to locate on the SPI
+  @param[out]    ObbPayloadPtr    Pointer to other part of Obb (hopefully on Bp1).
+                                  It does not matter if this ptr is actual memory or mmio,
+                                  since it needs to be combined anyway.
+                                  
+  @retval        EFI_SUCCESS      The operation completed successfully.
+  @retval        other            The selected BP could not be found.
+**/
+EFI_STATUS
+EFIAPI
+InternalLocateSplitObb (
+  IN   BOOT_PARITION_SELECT  BpSel,
+  OUT  BPDT_PAYLOAD_DATA     *ObbPayloadPtr
+  )
+{
+  UINT8               index;
+  VOID                *LbpPointer;
+  VOID                *LbpOffset;
+  BPDT_HEADER         *BpdtHeaderPtr;
+  BPDT_HEADER         *sBpdtHeader;
+  BPDT_ENTRY          *BpdtEntryPtr;
+  EFI_STATUS          Status;
+
+  Status = GetBootPartitionPointer (BpSel, &LbpPointer);
+  ASSERT_EFI_ERROR (Status);
+
+  BpdtHeaderPtr = (BPDT_HEADER *)LbpPointer;
+  Status = EFI_NOT_FOUND;
+  do {
+    //
+    //Reset secondary header each time to ensure proper exit.
+    //
+    sBpdtHeader = NULL;
+    BpdtEntryPtr = (BPDT_ENTRY *)((UINTN)BpdtHeaderPtr + sizeof(BPDT_HEADER));
+
+    if (BpdtHeaderPtr->Signature != BPDT_SIGN_GREEN) {
+      DEBUG ((EFI_D_INFO, "Signature of BPDT Header is invalid - Stop Parsing BP%d.\n", BpSel));
+      break;
+    }
+    for (index=0; index < BpdtHeaderPtr->DscCount; index++, BpdtEntryPtr++) {
+      if (BpdtEntryPtr->LbpOffset == 0) {
+        DEBUG ((EFI_D_INFO, "Skipping Stub-entry for Bpdt type: 0x%x \n", BpdtEntryPtr->Type));
+        continue;
+      }
+      LbpOffset = (VOID *)((UINTN)LbpPointer + BpdtEntryPtr->LbpOffset);
+
+      if (BpdtEntryPtr->Type == BpdtSbpdt) {
+        sBpdtHeader = (BPDT_HEADER *)LbpOffset;
+        continue;
+      }
+      if (BpdtEntryPtr->Type == BpdtObb) {
+        ObbPayloadPtr->DataPtr = LbpOffset;
+        ObbPayloadPtr->Size    = BpdtEntryPtr->Size;
+        Status = EFI_SUCCESS;
+        break;
+      }
+    }
+    if (sBpdtHeader != NULL) {
+      BpdtHeaderPtr = sBpdtHeader;
+    }
+  } while (sBpdtHeader != NULL);
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "Unable to locate part of Split Obb: %r. Halting system.\n", Status));
+    CpuDeadLoop ();
+  }
+  return Status;
+}
+
+
+/**
+  Locate and return a pointer to the selected Logical Boot Partition.
+
+  For block devices, the address will be the location in memory that the BP was copied to.
+  For memory mapped device (eg SPI), the address will be the location on the device.
+
+  @param[in]     LbpSel         Which BP to locate on the boot device
+  @param[out]    Address        The address of the selected BP on the boot device
+
+  @retval        EFI_SUCCESS    The operation completed successfully.
+  @retval        other          The selected BP could not be found.
+**/
+EFI_STATUS
+EFIAPI
+GetBootPartitionPointer (
+  IN  BOOT_PARITION_SELECT  LbpSel,
+  OUT VOID                  **LbpPointer
+  )
+{
+  UINT32                    BpLinearAddr;
+  EFI_STATUS                Status;
+
+  DEBUG ((EFI_D_INFO, "CSE Boot Device is SPI.\n"));
+  Status = InternalGetBpSpi (LbpSel, &BpLinearAddr, LbpPointer);
+
+  return Status;
+}
+
+/**
+  Parse the Boot Partition Descriptor Table of the provided Logical Boot Partition.
+  Note: "payload" is the Sub-Partition pointed to by the BDPT Entry of the given type.
+
+  @param[in]    LbpPointer      Pointer to the start of the BootPartition to be parsed
+  @param[in]    EntryType       The entry type of the subparition(payload) to look for
+  @param[out]   BpdtPayloadPtr  Address of the Struct to put the results into (MUST be allocated by caller)
+
+  @retval       EFI_SUCCESS     The operation completed successfully.
+**/
+EFI_STATUS
+EFIAPI
+GetBpdtPayloadDataRaw (
+  IN  VOID                *LbpPointer,
+  IN  BPDT_ENTRY_TYPES    EntryType,
+  OUT BPDT_PAYLOAD_DATA   *BpdtPayloadPtr
+  )
+{
+  UINT8                   Index;
+  VOID                    *LbpOffset;
+  BPDT_HEADER             *BpdtHeaderPtr;
+  BPDT_HEADER             *sBpdtHeader;
+  BPDT_ENTRY              *BpdtEntryPtr;
+
+
+  BpdtHeaderPtr = (BPDT_HEADER *)LbpPointer;
+  do {
+  	//
+    //Reset secondary header each time to ensure proper exit.
+    //
+    sBpdtHeader = NULL;
+    BpdtEntryPtr = (BPDT_ENTRY *)((UINTN)BpdtHeaderPtr + sizeof(BPDT_HEADER));
+
+    DEBUG ((DEBUG_INFO, "BpdtHeaderPtr->Signature = %x\n", BpdtHeaderPtr->Signature));
+    if ((BpdtHeaderPtr->Signature != BPDT_SIGN_GREEN) && (BpdtHeaderPtr->Signature != BPDT_SIGN_YELLOW)) {
+      DEBUG ((EFI_D_ERROR, "Signature of BPDT Header is invalid - Stop Parsing RawBP.\n"));
+      return EFI_NOT_FOUND;
+    }
+    for (Index=0; Index < BpdtHeaderPtr->DscCount; Index++, BpdtEntryPtr++) {
+      if (BpdtEntryPtr->LbpOffset == 0) {
+        DEBUG ((EFI_D_INFO, "Skipping Stub-entry for Bpdt type: %d\n", BpdtEntryPtr->Type));
+        continue;
+      }
+      LbpOffset = (VOID *)((UINTN)LbpPointer + BpdtEntryPtr->LbpOffset);
+
+      if (BpdtEntryPtr->Type == BpdtSbpdt) {
+        sBpdtHeader = (BPDT_HEADER *)LbpOffset;
+      }
+      if (BpdtEntryPtr->Type == EntryType) {
+        DEBUG ((EFI_D_INFO, "Found BPDT Entry. Type: %d, Addr: 0x%x\n", BpdtEntryPtr->Type, LbpOffset));
+        BpdtPayloadPtr->DataPtr = LbpOffset;
+        BpdtPayloadPtr->Size = BpdtEntryPtr->Size;
+        return EFI_SUCCESS;
+      }
+    }
+    if (sBpdtHeader != NULL) {
+      BpdtHeaderPtr = sBpdtHeader;
+    }
+  } while (sBpdtHeader != NULL);
+
+  BpdtPayloadPtr->DataPtr = NULL;
+  BpdtPayloadPtr->Size = 0;
+  return EFI_NOT_FOUND;
+}
+
+/**
+  Parse the Boot Partition Descriptor Table on the selected Logical Boot Partition.
+  Takes the BP as input since some BPDT entry types can exist in both locations.
+  Note: "payload" is the Sub-Partition pointed to by the BDPT Entry of the given type.
+
+  @param[in]     LbpSel         Which BP to locate on the boot device
+  @param[in]    EntryType       The entry type of the subparition(payload) to look for
+  @param[out]   BpdtPayloadPtr  Pointer to a Struct (in a HOB) containing the Size and Absolute address
+                                in memory(or spi) of the BPDT payload(subpart) of EntryType.
+                                If the caller shadows the Payload for performance, it should update this value
+
+  @retval       EFI_SUCCESS     The operation completed successfully.
+**/
+EFI_STATUS
+EFIAPI
+GetBpdtPayloadData (
+  IN  BOOT_PARITION_SELECT  BpSel,
+  IN  BPDT_ENTRY_TYPES      EntryType,
+  OUT BPDT_PAYLOAD_DATA     **BpdtPayloadPtr
+  )
+{
+  UINT8                 Index;
+  VOID                  *LbpOffset;
+  VOID                  *LbpBuffer = NULL;
+  VOID                  *CombinedObb;
+  BPDT_PAYLOAD_DATA     *BpdtPayloadList = NULL;
+  BPDT_PAYLOAD_DATA     *AdditionalPayloadList = NULL;
+  BPDT_PAYLOAD_DATA     AdditionalObbInfo;
+  BPDT_PAYLOAD_DATA     *ObbInfoPart1Ptr;
+  BPDT_PAYLOAD_DATA     *ObbInfoPart2Ptr;
+  BPDT_HEADER           *BpdtHeaderPtr;
+  BPDT_HEADER           *sBpdtHeader;
+  BPDT_ENTRY            *BpdtEntryPtr;
+  BPDT_ENTRY            *ObbEntryPtr = NULL;
+  EFI_HOB_GUID_TYPE     *GuidHobPtr;
+  EFI_STATUS            Status;
+  EFI_GUID              CurrentBpdtDataGuid;
+  EFI_GUID              AdditionalDataGuid;
+  BOOT_PARITION_SELECT  AdditionalObbBp;
+
+  //
+  // Set the data guid's to the correct HOB's based on the selected BP.
+  // If Current contains Split OBB, then Additional needs to be the BP with the other SplitObb.
+  //
+  switch (BpSel) {
+    case BootPart1:
+      CurrentBpdtDataGuid = gEfiBpdtLibBp1DataGuid;
+      AdditionalDataGuid  = gEfiBpdtLibBp2DataGuid;
+      AdditionalObbBp     = BootPart2;
+      break;
+    case BootPart2:
+      CurrentBpdtDataGuid = gEfiBpdtLibBp2DataGuid;
+      AdditionalDataGuid  = gEfiBpdtLibBp1DataGuid;
+      AdditionalObbBp     = BootPart1;
+      break;
+    default:
+      DEBUG ((EFI_D_ERROR, "Invalid BootPartion parameter: %d\n", BpSel));
+      return EFI_NOT_FOUND;
+      break;
+  }
+
+  *BpdtPayloadPtr = NULL;
+  GuidHobPtr = GetFirstGuidHob (&CurrentBpdtDataGuid);
+  if (GuidHobPtr != NULL) {
+    DEBUG ((EFI_D_INFO, "BPDT %d already parsed. Getting Payload info from HOB\n", BpSel+1));
+    BpdtPayloadList = GET_GUID_HOB_DATA (GuidHobPtr);
+    *BpdtPayloadPtr = &BpdtPayloadList[EntryType];
+    if (*BpdtPayloadPtr == NULL) {
+      DEBUG ((EFI_D_WARN, "Requested Payload info in NULL: %d\n", EntryType));
+      return EFI_NOT_FOUND;
+    } else {
+      return EFI_SUCCESS;
+    }
+  }
+
+  //
+  //Must use ZeroPool here to ensure correct error handling of missing entries.
+  //
+  BpdtPayloadList = AllocateZeroPool (BPDT_HOB_DATA_SIZE);
+  if (BpdtPayloadList == NULL) {
+    ASSERT (BpdtPayloadList != NULL);
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Status = GetBootPartitionPointer (BpSel, &LbpBuffer);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Parse the BPDT and store the Entry offsets into the array.
+  //
+  BpdtHeaderPtr = (BPDT_HEADER *)LbpBuffer;
+  do {
+  	//
+    //reset secondary header each time to ensure proper exit.
+    //
+    sBpdtHeader = NULL;
+    BpdtEntryPtr = (BPDT_ENTRY *)((UINTN)BpdtHeaderPtr + sizeof(BPDT_HEADER));
+
+    if (BpdtHeaderPtr->Signature != BPDT_SIGN_GREEN) {
+      DEBUG ((EFI_D_ERROR, "Signature of BPDT Header is invalid - Stop Parsing BP%d.\n", BpSel+1));
+      return EFI_NOT_FOUND;
+    }
+    for (Index=0; Index < BpdtHeaderPtr->DscCount; Index++, BpdtEntryPtr++) {
+      if (BpdtEntryPtr->LbpOffset == 0) {
+        DEBUG ((EFI_D_INFO, "Skipping Stub-entry for Bpdt type: %d\n", BpdtEntryPtr->Type));
+        continue;
+      }
+      LbpOffset = (VOID *)((UINTN)LbpBuffer + BpdtEntryPtr->LbpOffset);
+
+      if (BpdtEntryPtr->Type == BpdtSbpdt) {
+        sBpdtHeader = (BPDT_HEADER *)LbpOffset;
+      }
+      if (BpdtEntryPtr->Type < BpdtMaxType) {
+        DEBUG ((EFI_D_INFO, "Saving Info of BPDT Entry. Type: %d, Addr: 0x%x\n", BpdtEntryPtr->Type, LbpOffset));
+        BpdtPayloadList[BpdtEntryPtr->Type].DataPtr = LbpOffset;
+        BpdtPayloadList[BpdtEntryPtr->Type].Size = BpdtEntryPtr->Size;
+      }
+      if (BpdtEntryPtr->Type == BpdtObb) {
+        ObbEntryPtr = BpdtEntryPtr;
+      }
+    }
+    if (sBpdtHeader != NULL) {
+      BpdtHeaderPtr = sBpdtHeader;
+    }
+  } while (sBpdtHeader != NULL);
+
+
+  //
+  // If the additional data HOB contains the address of Obb, then the special cases for
+  // Obb were already handled by a previous call to this function (no need to recombine =).
+  //
+  GuidHobPtr = GetFirstGuidHob (&AdditionalDataGuid);
+  if (GuidHobPtr != NULL) {
+    AdditionalPayloadList = GET_GUID_HOB_DATA (GuidHobPtr);
+  }
+  if (AdditionalPayloadList != NULL && AdditionalPayloadList[BpdtObb].DataPtr != NULL) {
+    //
+    // using copymem will auto scale if the struct defintion changes.
+    //
+    CopyMem (&BpdtPayloadList[BpdtObb], &AdditionalPayloadList[BpdtObb], sizeof (BPDT_PAYLOAD_DATA));
+  } else {
+    //
+    // Check for Payload overlap with non-MMIO SPI region.
+    //
+    InternalCheckAndJoinUpperSpi (BpSel, &BpdtPayloadList[BpdtObb]);
+
+    //
+    // look for and handle the Split OBB case.
+    //
+    if (ObbEntryPtr != NULL && (ObbEntryPtr->Flags & SPLIT_ENTRY_FLAGS)) {
+
+      DEBUG ((EFI_D_INFO, "Attempting to resolve Split Obb..\n"));
+      InternalLocateSplitObb (AdditionalObbBp, &AdditionalObbInfo);
+      
+      //
+      // Since each Obb part could be on either BP, then we also need to check
+      // it for overlap into the non-MMIO accessible SPI region.
+      //
+      InternalCheckAndJoinUpperSpi (AdditionalObbBp, &AdditionalObbInfo);
+
+      if (ObbEntryPtr->Flags & SPLIT_ENTRY_PART_1) {
+        ObbInfoPart1Ptr = &BpdtPayloadList[BpdtObb];
+        ObbInfoPart2Ptr = &AdditionalObbInfo;
+      } else {
+        ObbInfoPart1Ptr = &AdditionalObbInfo;
+        ObbInfoPart2Ptr = &BpdtPayloadList[BpdtObb];
+      }
+      
+      //
+      // Combine the final parts together and set the output address to the result.
+      //
+      CombinedObb = AllocatePages (EFI_SIZE_TO_PAGES ((UINTN)ObbInfoPart1Ptr->Size + ObbInfoPart2Ptr->Size));
+      CopyMem (CombinedObb, ObbInfoPart1Ptr->DataPtr, ObbInfoPart1Ptr->Size);
+      CopyMem ((VOID *)((UINTN)CombinedObb+ObbInfoPart1Ptr->Size), ObbInfoPart2Ptr->DataPtr, ObbInfoPart2Ptr->Size);
+      BpdtPayloadList[BpdtObb].DataPtr = CombinedObb;
+      BpdtPayloadList[BpdtObb].Size = ObbInfoPart1Ptr->Size + ObbInfoPart2Ptr->Size;
+    }
+  }
+
+  //
+  // Build HOB for BPDT data.
+  // Need to use a HOB (or local PPI) instead of a module global since the library will be called in PreMem,
+  // and PreMem globals will not work if executing in place (ie SPI boot with no code in CAR).
+  //
+  GuidHobPtr = BuildGuidDataHob (
+    &gEfiBpdtLibBp2DataGuid,
+    BpdtPayloadList,
+    BPDT_HOB_DATA_SIZE
+  );
+  *BpdtPayloadPtr = &BpdtPayloadList[EntryType];
+  FreePool(BpdtPayloadList);
+
+  if (GuidHobPtr == NULL || *BpdtPayloadPtr == NULL) {
+   DEBUG ((EFI_D_ERROR, "Unable to create BPDT HOB.\n"));
+   return EFI_NOT_FOUND;
+  }
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Search the Subpartition pointed to by BpdtPayloadPtr for a Directory entry with "EntryName",
+  then fill in the Struct pointed to by SubPartPayloadPtr with the Addres and Size of the Dir Entry.
+  Note: "payload" is the Data pointed to by the Directory Entry with the given name.
+
+  @param[in]   BpdtPayloadPtr     Location and Size of the Payload to search
+  @param[in]   EntryName          the String name of the Directory entry to look for
+  @param[out]  SubPartPayloadPtr  Address of the Struct to put the results into (MUST be allocated by caller)
+
+  @retval      EFI_SUCCESS        The operation completed successfully.
+**/
+EFI_STATUS
+EFIAPI
+GetSubPartitionPayloadData (
+  IN  BPDT_PAYLOAD_DATA     *BpdtPayloadPtr,
+  IN  CONST CHAR8           *EntryName,
+  OUT BPDT_PAYLOAD_DATA     *SubPartPayloadPtr
+  )
+{
+  UINT8                   Index;
+  CHAR8                   SearchName[DIR_ENTRY_NAME_SIZE];
+  UINTN                   SearchNameSize;
+  SUBPART_DIR_HEADER      *DirectoryHeader;
+  SUBPART_DIR_ENTRY       *DirectoryEntry;
+
+  //
+  // Pad Name with zeros (per spec) to ensure correct match.
+  //
+  ZeroMem(SearchName, DIR_ENTRY_NAME_SIZE);
+  
+  //
+  // Safely handle the input string to ensure we dont copy garbage when EntryName is less than 12.
+  //
+  SearchNameSize = AsciiStrnLenS (EntryName, DIR_ENTRY_NAME_SIZE);
+  CopyMem(SearchName, EntryName, SearchNameSize);
+
+  DEBUG ((EFI_D_INFO, "Looking for Directory Entry with Name: %a\n", SearchName));
+  DirectoryHeader = (SUBPART_DIR_HEADER *)BpdtPayloadPtr->DataPtr;
+  DirectoryEntry = (SUBPART_DIR_ENTRY *)((UINTN)DirectoryHeader + sizeof(SUBPART_DIR_HEADER));
+
+  if (DirectoryHeader->HeaderMarker != DIR_HDR_SIGNATURE) {
+    DEBUG ((EFI_D_ERROR, "Directory Header is invalid - return Not_Found.\n"));
+    return EFI_NOT_FOUND;
+  }
+  
+  for (Index = 0; Index < DirectoryHeader->NumOfEntries; Index++, DirectoryEntry++) {
+    DEBUG ((EFI_D_INFO, " %a Entry is located at %x\n",
+      DirectoryEntry->EntryName, (UINTN)DirectoryHeader+DirectoryEntry->EntryOffset));
+    if (!CompareMem(DirectoryEntry->EntryName, SearchName, DIR_ENTRY_NAME_SIZE)) {
+      SubPartPayloadPtr->DataPtr = (VOID *)((UINTN)DirectoryHeader + DirectoryEntry->EntryOffset);
+      SubPartPayloadPtr->Size = DirectoryEntry->EntrySize;
+      return EFI_SUCCESS;
+    }
+  }
+
+  DEBUG ((EFI_D_WARN, "Entry not found.\n"));
+  return EFI_NOT_FOUND;
+}
+
+
+/**
+  This is a wrapper function for using VerifyHashBpm that will only
+  check the hash for the payloads used during normal boot.
+
+  If you want to check other payloads (ie during recovery flow), then the
+  calling code should locate and pass in the payload directly to VerifyHashBpm().
+
+  @param[in]  PayloadSel   Which hash in BPM to compare with.
+
+  @retval     EFI_SUCCESS  The function completed successfully and the Hash matched.
+  @retval     other        An error occured when locating and computing the Hash.
+**/
+EFI_STATUS
+EFIAPI
+LocateAndVerifyHashBpm (
+  IN  BPM_HASH_SELECT    PayloadSel
+  )
+{
+
+  UINT8                  Index;
+  EFI_STATUS             Status;
+  VOID                   *HashDataPtr;
+  UINT32                 HashDataSize;
+  UINT32                 FvTailAddr;
+  BPM_DATA_FILE          *BpmPtr;
+  BPDT_PAYLOAD_DATA      *IbbPayloadPtr;
+  BPDT_PAYLOAD_DATA      *ObbPayloadPtr;
+  BPDT_PAYLOAD_DATA      SubPartPayload;
+  SUBPART_DIR_HEADER     *DirectoryHeader;
+  SUBPART_DIR_ENTRY      *DirectoryEntry;
+
+  DEBUG ((EFI_D_INFO, "Searching IBB for BPM..\n" ));
+  GetBpdtPayloadData (BootPart1, BpdtIbb, &IbbPayloadPtr);
+  if (IbbPayloadPtr == NULL) {
+    return EFI_NOT_FOUND;
+  }
+  Status = GetSubPartitionPayloadData (IbbPayloadPtr, "BPM.met", &SubPartPayload);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  BpmPtr = (BPM_DATA_FILE *)SubPartPayload.DataPtr;
+
+  switch (PayloadSel) {
+    case HashIbbl:
+      Status = GetSubPartitionPayloadData (IbbPayloadPtr, "IBBL", &SubPartPayload);
+      HashDataPtr  = SubPartPayload.DataPtr;
+      HashDataSize = SubPartPayload.Size;
+      break;
+
+    case HashIbbm:
+      Status = GetSubPartitionPayloadData (IbbPayloadPtr, "IBB", &SubPartPayload);
+      HashDataPtr  = SubPartPayload.DataPtr;
+      HashDataSize = SubPartPayload.Size;
+      break;
+
+    case HashObb:
+      Status = GetBpdtPayloadData (BootPart2, BpdtObb, &ObbPayloadPtr);
+      if (ObbPayloadPtr == NULL) {
+        return EFI_NOT_FOUND;
+      }
+      DirectoryHeader = (SUBPART_DIR_HEADER *)ObbPayloadPtr->DataPtr;
+      DirectoryEntry = (SUBPART_DIR_ENTRY *)((UINTN)DirectoryHeader + sizeof(SUBPART_DIR_HEADER));
+      HashDataPtr = (VOID *)((UINTN)DirectoryHeader + DirectoryEntry->EntryOffset);
+
+      for (Index = 1; Index < DirectoryHeader->NumOfEntries; Index++) {
+        DirectoryEntry++;
+      }
+
+      FvTailAddr = (UINT32)DirectoryHeader + DirectoryEntry->EntryOffset + DirectoryEntry->EntrySize;
+      HashDataSize = FvTailAddr - (UINT32)HashDataPtr;
+      break;
+
+    default:
+
+      return EFI_INVALID_PARAMETER;
+      break;
+  }
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = VerifyHashBpm(PayloadSel, BpmPtr, HashDataPtr, HashDataSize);
+  return Status;
+}
+
+
+
+/**
+  Computes the Hash of a given data block and compares to the one in the Boot Policy Metadata.
+
+  @param[in]  PayloadSel   Which hash in BPM to compare with.
+  @param[in]  PayloadPtr   Pointer to the begining of the data to be hashed.
+  @param[in]  DataSize     Size of the data to be hashed.
+  @param[in]  BpmPtr       Pointer to the BPM structure.
+
+  @retval EFI_SUCCESS             If the function completed successfully.
+  @retval EFI_ABORTED             If the attempt to compute the hash fails.
+  @retval EFI_INVALID_PARAMETER   If the hash type or size in BPM is unsupported.
+  @retval EFI_SECURITY_VIOLATION  If the has does not match the one in BPM.
+**/
+EFI_STATUS
+EFIAPI
+VerifyHashBpm (
+  IN BPM_HASH_SELECT   PayloadSel,
+  IN BPM_DATA_FILE     *BpmPtr,
+  IN VOID              *PayloadPtr,
+  IN UINT32            DataSize
+  )
+{
+  UINT8                Index;
+  UINT32               BpmHashAlgo;
+  UINT32               BpmHashSize;
+  UINT8                *BpmHash;
+  UINTN                ContextSize;
+  VOID                 *HashContext;
+  BOOLEAN              HashResult;
+  UINT8                Digest[SHA256_DIGEST_SIZE];
+
+
+  ZeroMem (Digest, SHA256_DIGEST_SIZE);
+  ContextSize = Sha256GetContextSize ();
+  HashContext = AllocatePool (ContextSize);
+
+  DEBUG((EFI_D_INFO, "VerifyFV: PayloadPtr = %x, DataSize = %x\n", PayloadPtr, DataSize));
+
+  switch (PayloadSel) {
+    case HashIbbl:
+      BpmHashAlgo = BpmPtr->IbblHashAlgo;
+      BpmHashSize = BpmPtr->IbblHashSize;
+      BpmHash     = BpmPtr->IbblHash;
+      break;
+
+    case HashIbbm:
+      BpmHashAlgo = BpmPtr->IbbmHashAlgo;
+      BpmHashSize = BpmPtr->IbbmHashSize;
+      BpmHash     = BpmPtr->IbbmHash;
+      break;
+
+    case HashObb:
+    default:
+      BpmHashAlgo = BpmPtr->ObbHashAlgo;
+      BpmHashSize = BpmPtr->ObbHashSize;
+      BpmHash     = BpmPtr->ObbHash;
+      break;
+  }
+  
+  if (BpmHashAlgo != 2 || BpmHashSize != SHA256_DIGEST_SIZE) {
+    DEBUG((EFI_D_ERROR, "Hash length NOT correct for SHA256.\n"));
+    return EFI_INVALID_PARAMETER;
+  }
+  
+  //
+  //If hash entry in BPM is empty (all 0s), skip the OBB verification.
+  //
+  if (!CompareMem(BpmHash, Digest, SHA256_DIGEST_SIZE)) {
+    return EFI_SUCCESS;
+  }
+
+  DEBUG((EFI_D_INFO, "BPM Info:\n" ));
+  DEBUG((EFI_D_INFO, " Payload = %d, HashAlgo = %d, HashSize = %d\n", PayloadSel, BpmHashAlgo, BpmHashSize));
+  DEBUG((EFI_D_INFO, " Hash ="));
+  for (Index = 0; Index < BpmHashSize; Index++) {
+    DEBUG((EFI_D_INFO, " %02x", BpmHash[Index]));
+  }
+  DEBUG((EFI_D_INFO, "\n"));
+
+  HashResult = Sha256Init (HashContext);
+  if (!HashResult) {
+    DEBUG((EFI_D_ERROR, "Sha256Init Failed!\n"));
+    return EFI_ABORTED;
+  }
+  HashResult = Sha256Update (HashContext, PayloadPtr, DataSize);
+  if (!HashResult) {
+    DEBUG((EFI_D_ERROR, "Sha256Update Failed!\n"));
+    return EFI_ABORTED;
+  }
+  HashResult = Sha256Final (HashContext, Digest);
+  if (!HashResult) {
+    DEBUG((EFI_D_ERROR, "Sha256Final Failed!\n"));
+    return EFI_ABORTED;
+  }
+
+  DEBUG((EFI_D_INFO, " Hash ="));
+  for (Index = 0; Index < BpmHashSize; Index ++) {
+    DEBUG((EFI_D_INFO, " %02x", Digest[Index]));
+  }
+  DEBUG((EFI_D_INFO, "\n"));
+
+  if (CompareMem(BpmHash, Digest, BpmHashSize)) {
+    DEBUG((EFI_D_ERROR, "\nHash Mis-Match. Return Security Violation\n"));
+    return EFI_SECURITY_VIOLATION;
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/BpdtLib/BpdtLib.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/BpdtLib/BpdtLib.inf
new file mode 100644
index 000000000..c07ecb05c
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/BpdtLib/BpdtLib.inf
@@ -0,0 +1,49 @@
+## @file
+#  Boot Partition Descriptor Table library.
+#
+#  Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution. The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php.
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION          = 0x00010005
+  BASE_NAME            = BpdtLib
+  FILE_GUID            = ec12d034-0ab8-4e9c-87f9-01a2d284ea6c
+  MODULE_TYPE          = PEIM
+  VERSION_STRING       = 1.0
+  LIBRARY_CLASS        = BpdtLib
+
+[Sources]
+  BpdtLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  CryptoPkg/CryptoPkg.dec
+  BroxtonSiPkg/BroxtonSiPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  DebugLib
+  HobLib
+  BaseMemoryLib
+  MemoryAllocationLib
+  PeiServicesTablePointerLib
+  ScPlatformLib
+  PeiSpiInitLib
+  BaseCryptLib
+
+[Guids]
+  gEfiBpdtLibBp1DataGuid
+  gEfiBpdtLibBp2DataGuid
+
+[Ppis]
+  gScSpiPpiGuid
+  gEfiPeiVirtualBlockIoPpiGuid
-- 
2.11.0.windows.1



^ permalink raw reply related	[flat|nested] 2+ messages in thread

* [Patch][edk2-platforms/devel-MinnowBoard3 2/2] Add PEI SPI library.
  2017-03-10  8:05 [Patch][edk2-platforms/devel-MinnowBoard3 1/2] Add BPDT library zwei4
@ 2017-03-10  8:05 ` zwei4
  0 siblings, 0 replies; 2+ messages in thread
From: zwei4 @ 2017-03-10  8:05 UTC (permalink / raw)
  To: edk2-devel

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: zwei4 <david.wei@intel.com>
---
 Silicon/BroxtonSoC/BroxtonSiPkg/SiPkgPeiLib.dsc    |   4 +-
 .../SouthCluster/Include/Library/PeiSpiInitLib.h   |  35 +++
 .../BroxtonSiPkg/SouthCluster/Include/Ppi/Spi.h    | 238 +++++++++++++++++++++
 .../Library/PeiSpiInitLib/PeiSpiInitLib.inf        |  44 ++++
 .../SouthCluster/Library/PeiSpiInitLib/ScSpi.c     | 237 ++++++++++++++++++++
 .../SouthCluster/Library/PeiSpiInitLib/ScSpi.h     |  44 ++++
 6 files changed, 601 insertions(+), 1 deletion(-)
 create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Include/Library/PeiSpiInitLib.h
 create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Include/Ppi/Spi.h
 create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiSpiInitLib/PeiSpiInitLib.inf
 create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiSpiInitLib/ScSpi.c
 create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiSpiInitLib/ScSpi.h

diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SiPkgPeiLib.dsc b/Silicon/BroxtonSoC/BroxtonSiPkg/SiPkgPeiLib.dsc
index b454329ae..5174defcf 100644
--- a/Silicon/BroxtonSoC/BroxtonSiPkg/SiPkgPeiLib.dsc
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SiPkgPeiLib.dsc
@@ -21,11 +21,13 @@
 # Common
 #
   CseVariableStorageSelectorLib|$(PLATFORM_SI_PACKAGE)/Library/Private/PeiCseVariableStorageSelectorLib/PeiCseVariableStorageSelectorLib.inf
-
+  BpdtLib|$(PLATFORM_SI_PACKAGE)/Library/BpdtLib/BpdtLib.inf
+  
 #
 # SC
 #
   PeiScPolicyLib|$(PLATFORM_SI_PACKAGE)/SouthCluster/Library/PeiScPolicyLib/PeiScPolicyLib.inf
+  PeiSpiInitLib|$(PLATFORM_SI_PACKAGE)/SouthCluster/Library/PeiSpiInitLib/PeiSpiInitLib.inf
 
 #
 # CPU
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Include/Library/PeiSpiInitLib.h b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Include/Library/PeiSpiInitLib.h
new file mode 100644
index 000000000..628de101e
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Include/Library/PeiSpiInitLib.h
@@ -0,0 +1,35 @@
+/** @file
+  Prototype of the PeiSpiInitLib library.
+
+  Copyright (c) 2014 - 2017, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _PEI_SPI_INIT_LIBRARY_H_
+#define _PEI_SPI_INIT_LIBRARY_H_
+
+#include <Ppi/ScPolicy.h>
+
+/**
+  Installs SC SPI PPI.
+
+  @param[in]  None
+
+  @retval EFI_SUCCESS             SC SPI PPI is installed successfully
+  @retval EFI_OUT_OF_RESOURCES    Can't allocate pool
+**/
+EFI_STATUS
+EFIAPI
+InstallScSpi (
+  VOID
+  );
+
+#endif
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Include/Ppi/Spi.h b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Include/Ppi/Spi.h
new file mode 100644
index 000000000..89c167cec
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Include/Ppi/Spi.h
@@ -0,0 +1,238 @@
+/** @file
+  This file defines the EFI SPI PPI which implements the
+  Intel(R) SC SPI Host Controller Compatibility Interface.
+
+  Copyright (c) 2012 - 2017, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _PEI_SPI_H_
+#define _PEI_SPI_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID                     gScSpiPpiGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _SC_SPI_PROTOCOL  SC_SPI_PROTOCOL;
+
+//
+// SPI protocol data structures and definitions
+//
+
+///
+/// Flash Region Type
+///
+typedef enum {
+  FlashRegionDescriptor,
+  FlashRegionBios,
+  FlashRegionMe,
+  FlashRegionGbE,
+  FlashRegionPlatformData,
+  FlashRegionAll,
+  FlashRegionMax
+} FLASH_REGION_TYPE;
+
+//
+// Protocol member functions
+//
+
+/**
+  Read data from the flash part.
+
+  @param[in] This                 Pointer to the SC_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.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SC_SPI_FLASH_READ) (
+  IN     SC_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 SC_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.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SC_SPI_FLASH_WRITE) (
+  IN     SC_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 SC_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.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SC_SPI_FLASH_ERASE) (
+  IN     SC_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 SC_SPI_PROTOCOL instance.
+  @param[in] ComponentNumber      The Componen Number for chip select
+  @param[in] ByteCount            Number of bytes in SFDP data portion of the SPI cycle, the max number is 64
+  @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.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SC_SPI_FLASH_READ_SFDP) (
+  IN     SC_SPI_PROTOCOL   *This,
+  IN     UINT8              ComponentNumber,
+  IN     UINT32             ByteCount,
+  OUT    UINT8              *SfdpData
+  );
+
+/**
+  Read Jedec Id from the flash part.
+
+  @param[in] This                 Pointer to the SC_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.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SC_SPI_FLASH_READ_JEDEC_ID) (
+  IN     SC_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 SC_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.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SC_SPI_FLASH_WRITE_STATUS) (
+  IN     SC_SPI_PROTOCOL   *This,
+  IN     UINT32             ByteCount,
+  IN     UINT8              *StatusValue
+  );
+
+/**
+  Read status register in the flash part.
+
+  @param[in] This                 Pointer to the SC_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.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SC_SPI_FLASH_READ_STATUS) (
+  IN     SC_SPI_PROTOCOL   *This,
+  IN     UINT32             ByteCount,
+  OUT    UINT8              *StatusValue
+  );
+
+/**
+  Read PCH Soft Strap Values
+
+  @param[in] This                 Pointer to the SC_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.
+                                  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.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SC_SPI_READ_PCH_SOFTSTRAP) (
+  IN     SC_SPI_PROTOCOL   *This,
+  IN     UINT32             SoftStrapAddr,
+  IN     UINT32             ByteCount,
+  OUT    UINT8              *SoftStrapValue
+  );
+
+/**
+  These protocols/PPI allows a platform module to perform SPI operations through the
+  Intel PCH SPI Host Controller Interface.
+**/
+struct _SC_SPI_PROTOCOL {
+  SC_SPI_FLASH_READ                FlashRead;          ///< Read data from the flash part.
+  SC_SPI_FLASH_WRITE               FlashWrite;         ///< Write data to the flash part.
+  SC_SPI_FLASH_ERASE               FlashErase;         ///< Erase some area on the flash part.
+  SC_SPI_FLASH_READ_SFDP           FlashReadSfdp;      ///< Read SFDP data from the flash part.
+  SC_SPI_FLASH_READ_JEDEC_ID       FlashReadJedecId;   ///< Read Jedec Id from the flash part.
+  SC_SPI_FLASH_WRITE_STATUS        FlashWriteStatus;   ///< Write the status register in the flash part.
+  SC_SPI_FLASH_READ_STATUS         FlashReadStatus;    ///< Read status register in the flash part.
+  SC_SPI_READ_PCH_SOFTSTRAP        ReadPchSoftStrap;   ///< Read PCH Soft Strap Values
+};
+
+#endif
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiSpiInitLib/PeiSpiInitLib.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiSpiInitLib/PeiSpiInitLib.inf
new file mode 100644
index 000000000..561a86a50
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiSpiInitLib/PeiSpiInitLib.inf
@@ -0,0 +1,44 @@
+## @file
+#  SC SPI Init Lib PEI Phase.
+#
+#  Copyright (c) 2014 - 2017, Intel Corporation. All rights reserved.<BR>
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution. The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php.
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PeiSpiInitLib
+  FILE_GUID                      = 91CFD935-551E-439E-B0D6-AE06C3B5E66
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PeiSpiInitLib
+
+[Sources]
+  ScSpi.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  BroxtonSiPkg/BroxtonSiPkg.dec
+
+[LibraryClasses]
+  S3BootScriptLib
+  BaseLib
+  IoLib
+  DebugLib
+  TimerLib
+  MemoryAllocationLib
+  BaseMemoryLib
+  HobLib
+  PeiServicesLib
+  ScSpiCommonLib
+
+[Ppis]
+  gScSpiPpiGuid                        ## PRODUCES
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiSpiInitLib/ScSpi.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiSpiInitLib/ScSpi.c
new file mode 100644
index 000000000..0c665ab85
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiSpiInitLib/ScSpi.c
@@ -0,0 +1,237 @@
+/** @file
+  SC SPI PEI Library implements the SPI Host Controller Compatibility Interface.
+
+  Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "ScSpi.h"
+
+/**
+  Hide SPI controller before OS avoid BAR0 changed.
+
+  @param[in]  None
+
+  @retval
+**/
+VOID
+HideSpiController (
+  VOID
+  )
+{
+  UINTN                                 ScSpiBase;
+
+  ScSpiBase = MmPciBase (
+                DEFAULT_PCI_BUS_NUMBER_SC,
+                PCI_DEVICE_NUMBER_SPI,
+                PCI_FUNCTION_NUMBER_SPI
+                );
+
+  MmioAndThenOr8 (
+    ScSpiBase + R_SPI_BCR + 1,
+    (UINT8)~(B_SPI_BCR_SYNC_SS >> 8),
+    (B_SPI_BC_OSFH >> 8)
+    );
+}
+
+/**
+  PCI Enumeration is not done till later in DXE.
+  Initialize SPI BAR0 to a default value till enumeration is done.
+  Also enable memory space decoding for SPI.
+
+  @param[in]  None
+
+  @retval
+
+**/
+VOID
+InitSpiBar0 (
+  VOID
+  )
+{
+  UINTN ScSpiBase;
+  ScSpiBase = MmPciBase (
+                 DEFAULT_PCI_BUS_NUMBER_SC,
+                 PCI_DEVICE_NUMBER_SPI,
+                 PCI_FUNCTION_NUMBER_SPI
+                 );
+  MmioWrite32 (ScSpiBase + R_SPI_BASE, SC_SPI_BASE_ADDRESS);
+  MmioOr32 (ScSpiBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
+}
+
+/**
+  Installs SC SPI PPI
+
+  @retval EFI_SUCCESS             SC SPI PPI is installed successfully
+  @retval EFI_OUT_OF_RESOURCES    Can't allocate pool
+**/
+EFI_STATUS
+EFIAPI
+InstallScSpi (
+  VOID
+  )
+{
+  EFI_STATUS                  Status;
+  PEI_SPI_INSTANCE            *PeiSpiInstance;
+  SPI_INSTANCE                *SpiInstance;
+  EFI_PEI_PPI_DESCRIPTOR      *OldScSpiPolicyPpiDesc;
+
+  DEBUG ((DEBUG_INFO, "InstallScSpi() Start\n"));
+
+  ///
+  /// PCI Enumeration is not done till later in DXE.
+  /// Initialize SPI BAR0 to a default value till enumeration is done.
+  /// Also enable memory space decoding for SPI.
+  ///
+  InitSpiBar0 ();
+
+  PeiSpiInstance = (PEI_SPI_INSTANCE *) AllocateZeroPool (sizeof (PEI_SPI_INSTANCE));
+  if (PeiSpiInstance == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  SpiInstance = &(PeiSpiInstance->SpiInstance);
+  SpiProtocolConstructor (SpiInstance);
+
+  PeiSpiInstance->PpiDescriptor.Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
+  PeiSpiInstance->PpiDescriptor.Guid  = &gScSpiPpiGuid;
+  PeiSpiInstance->PpiDescriptor.Ppi   = &(SpiInstance->SpiProtocol);
+
+  Status = PeiServicesLocatePpi (
+             &gScSpiPpiGuid,
+             0,
+             &OldScSpiPolicyPpiDesc,
+             NULL
+             );
+  if (EFI_ERROR (Status)) {
+    //
+    // Install Sc Spi PPI.
+    //
+    DEBUG ((DEBUG_INFO, "Locate Old ScSpiPpi fail in Post-Memory\n"));
+    Status = PeiServicesInstallPpi (&PeiSpiInstance->PpiDescriptor);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "Install ScSpiPpi fail in Post-Memory\n"));
+    }
+    ASSERT_EFI_ERROR (Status);
+  } else {
+    //
+    // ReInstall Sc Spi PPI.
+    //
+    DEBUG ((DEBUG_INFO, "Re-Install ScSpiPpi in Post-Memory\n"));
+    Status = PeiServicesReInstallPpi (OldScSpiPolicyPpiDesc, &PeiSpiInstance->PpiDescriptor);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "Re-Install ScSpiPpi fail in Post-Memory\n"));
+    }
+    ASSERT_EFI_ERROR (Status);
+  }
+
+  DEBUG ((DEBUG_INFO, "InstallScSpi() End\n"));
+
+  //
+  // Hide SPI controller before OS avoid BAR0 changed.
+  //
+  HideSpiController ();
+
+  return Status;
+}
+
+/**
+  Acquire SC SPI mmio address.
+
+  @param[in] SpiInstance          Pointer to SpiInstance to initialize
+
+  @retval ScSpiBar0               Return SPI MMIO address
+**/
+UINT32
+AcquireSpiBar0 (
+  IN     SPI_INSTANCE       *SpiInstance
+  )
+{
+  return MmioRead32 (SpiInstance->PchSpiBase + R_SPI_BASE) & ~(B_SPI_BAR0_MASK);
+}
+
+/**
+  Release SC SPI mmio address.
+
+  @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
+  )
+{
+  UINTN             SpiBaseAddress;
+
+  SpiBaseAddress = MmPciBase (
+                     DEFAULT_PCI_BUS_NUMBER_SC,
+                     PCI_DEVICE_NUMBER_SPI,
+                     PCI_FUNCTION_NUMBER_SPI
+                     );
+  if ((MmioRead8 (SpiBaseAddress + R_SPI_BCR) & B_SPI_BCR_SMM_BWP) != 0) {
+    return EFI_ACCESS_DENIED;
+  }
+  
+  ///
+  /// Enable the access to the BIOS space for both read and write cycles
+  ///
+  MmioOr8 (
+    SpiBaseAddress + R_SPI_BCR,
+    B_SPI_BCR_BIOSWE
+    );
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This function is a hook for Spi to enable BIOS Write Protect
+
+  @param[in]  None
+
+  @retval
+**/
+VOID
+EFIAPI
+EnableBiosWriteProtect (
+  VOID
+  )
+{
+  UINTN                           SpiBaseAddress;
+
+  SpiBaseAddress = MmPciBase (
+                     DEFAULT_PCI_BUS_NUMBER_SC,
+                     PCI_DEVICE_NUMBER_SPI,
+                     PCI_FUNCTION_NUMBER_SPI
+                     );
+  ///
+  /// Disable the access to the BIOS space for write cycles
+  ///
+  MmioAnd8 (
+    SpiBaseAddress + R_SPI_BCR,
+    (UINT8) (~B_SPI_BCR_BIOSWE)
+    );
+}
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiSpiInitLib/ScSpi.h b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiSpiInitLib/ScSpi.h
new file mode 100644
index 000000000..7ae0b21e1
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiSpiInitLib/ScSpi.h
@@ -0,0 +1,44 @@
+/** @file
+  Header file for the SC SPI PEI Library.
+
+  Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SC_SPI_H_
+#define _SC_SPI_H_
+
+#include <Ppi/Spi.h>
+#include <ScAccess.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/MmPciLib.h>
+#include <IndustryStandard/Pci30.h>
+#include <Library/ScSpiCommonLib.h>
+
+typedef struct {
+  EFI_PEI_PPI_DESCRIPTOR  PpiDescriptor;
+  SPI_INSTANCE            SpiInstance;
+} PEI_SPI_INSTANCE;
+
+/**
+  Installs SC SPI PPI
+
+  @retval EFI_SUCCESS             PCH SPI PPI is installed successfully
+  @retval EFI_OUT_OF_RESOURCES    Can't allocate pool
+**/
+EFI_STATUS
+EFIAPI
+InstallScSpi (
+  VOID
+  );
+#endif
-- 
2.11.0.windows.1



^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2017-03-10  8:06 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-03-10  8:05 [Patch][edk2-platforms/devel-MinnowBoard3 1/2] Add BPDT library zwei4
2017-03-10  8:05 ` [Patch][edk2-platforms/devel-MinnowBoard3 2/2] Add PEI SPI library zwei4

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox