* [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