summaryrefslogtreecommitdiff
path: root/Silicon
diff options
context:
space:
mode:
authorGuo Mang <mang.guo@intel.com>2016-12-22 19:14:43 +0800
committerGuo Mang <mang.guo@intel.com>2016-12-26 19:15:02 +0800
commit92b6719423f351e9cf5517a9413f63da57778136 (patch)
tree15d336cf2dd28fe487cceb23f3d118eb935d8ba1 /Silicon
parent0177f6d6c2bbc7fa4356c52281809bc0570549d1 (diff)
downloadedk2-platforms-92b6719423f351e9cf5517a9413f63da57778136.tar.xz
BroxtonSiPkg: Add Library
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Guo Mang <mang.guo@intel.com>
Diffstat (limited to 'Silicon')
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/BaseConfigBlockLib/BaseConfigBlockLib.c205
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/BaseConfigBlockLib/BaseConfigBlockLib.inf35
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/BaseVariableNvmStorageLib/BaseVariableNvmStorageLib.c571
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/BaseVariableNvmStorageLib/BaseVariableNvmStorageLib.inf44
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/BaseVariableStorageSelectorLib/BaseVariableStorageSelectorLib.c60
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/BaseVariableStorageSelectorLib/BaseVariableStorageSelectorLib.inf44
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/DxeAslUpdateLib/DxeAslUpdateLib.c312
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/DxeAslUpdateLib/DxeAslUpdateLib.inf42
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/GpioLib/GpioLib.c1230
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/GpioLib/GpioLib.inf43
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiDxeSmmMmPciLib/PeiDxeSmmMmPciLib.c48
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiDxeSmmMmPciLib/PeiDxeSmmMmPciLib.inf41
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiPerformanceLibFpdt/PeiPerformanceLibFpdt.c427
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiPerformanceLibFpdt/PeiPerformanceLibFpdt.inf52
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiSiPolicyLib/PeiSiPolicyLib.c148
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiSiPolicyLib/PeiSiPolicyLib.inf40
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiSiPolicyLib/PeiSiPolicyLibrary.h37
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiSiPolicyLib/SiPrintPolicy.c44
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/PmcIpcLib/BaseIpcLib.c128
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/PmcIpcLib/BaseIpcLib.inf46
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/PmcIpcLib/InternalIpcLib.c368
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/PmcIpcLib/InternalIpcLib.h75
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/BaseCseVariableStorageLib/BaseCseVariableStorageLib.c1091
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/BaseCseVariableStorageLib/BaseCseVariableStorageLib.inf59
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/DxeSmmCseVariableStorageSelectorLib/CseVariableStorageSelectorLib.c177
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/DxeSmmCseVariableStorageSelectorLib/CseVariableStorageSelectorLibInternal.h27
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/DxeSmmCseVariableStorageSelectorLib/DxeCseVariableStorageSelectorLib.c113
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/DxeSmmCseVariableStorageSelectorLib/DxeCseVariableStorageSelectorLib.inf55
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/DxeSmmCseVariableStorageSelectorLib/SmmCseVariableStorageSelectorLib.c69
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/DxeSmmCseVariableStorageSelectorLib/SmmCseVariableStorageSelectorLib.inf54
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/PeiCseVariableStorageSelectorLib/PeiCseVariableStorageSelectorLib.c165
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/PeiCseVariableStorageSelectorLib/PeiCseVariableStorageSelectorLib.inf47
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/SideBandLib/SideBandLib.c435
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/SideBandLib/SideBandLib.inf39
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/SteppingLib/SteppingLib.c162
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Library/SteppingLib/SteppingLib.inf44
36 files changed, 6577 insertions, 0 deletions
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/BaseConfigBlockLib/BaseConfigBlockLib.c b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/BaseConfigBlockLib/BaseConfigBlockLib.c
new file mode 100644
index 0000000000..5a1dfa57a2
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/BaseConfigBlockLib/BaseConfigBlockLib.c
@@ -0,0 +1,205 @@
+/** @file
+ Library functions for Config Block management.
+
+ Copyright (c) 2015 - 2016, 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 <ConfigBlock.h>
+#include <Library/ConfigBlockLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+
+
+/**
+ Create config block table.
+
+ @param[in] NumberOfBlocks Number of Config Blocks.
+
+ @retval Size Size of Config Block Table Header and Offset Table.
+
+**/
+UINT32
+EFIAPI
+GetSizeOfConfigBlockTableHeaders (
+ IN UINT16 NumberOfBlocks
+ )
+{
+ return (UINT32) (sizeof (CONFIG_BLOCK_TABLE_HEADER)) + (UINT32) (NumberOfBlocks * 4);
+}
+
+
+/**
+ Create config block table.
+
+ @param[out] ConfigBlockTableAddress On return, points to a pointer to the beginning of Config Block Table Address.
+ @param[in] NumberOfBlocks Number of Config Blocks.
+ @param[in] TotalSize Max size to be allocated for the Config Block Table.
+
+ @retval EFI_INVALID_PARAMETER Invalid Parameter.
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_SUCCESS Successfully created Config Block Table at ConfigBlockTableAddress.
+
+**/
+EFI_STATUS
+EFIAPI
+CreateConfigBlockTable (
+ OUT VOID **ConfigBlockTableAddress,
+ IN UINT16 NumberOfBlocks,
+ IN UINT32 TotalSize
+ )
+{
+ CONFIG_BLOCK_TABLE_HEADER *ConfigBlkTblAddrPtr;
+ UINT32 ConfigBlkTblHdrSize;
+
+ ConfigBlkTblHdrSize = (UINT32) (sizeof (CONFIG_BLOCK_TABLE_HEADER));
+
+ if ((NumberOfBlocks == 0) || (TotalSize <= (ConfigBlkTblHdrSize + 4 + sizeof (CONFIG_BLOCK)))) {
+ DEBUG ((DEBUG_ERROR, "Invalid Parameter\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ConfigBlkTblAddrPtr = (CONFIG_BLOCK_TABLE_HEADER *)AllocateZeroPool (TotalSize);
+ if (ConfigBlkTblAddrPtr == NULL) {
+ DEBUG ((DEBUG_ERROR, "Could not allocate memory.\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+ ConfigBlkTblAddrPtr->NumberOfBlocks = NumberOfBlocks;
+ ConfigBlkTblAddrPtr->Header.Size = TotalSize;
+ ConfigBlkTblAddrPtr->AvailableBlocks = NumberOfBlocks;
+ ConfigBlkTblAddrPtr->AvailableSize = TotalSize - GetSizeOfConfigBlockTableHeaders (NumberOfBlocks);
+
+ *ConfigBlockTableAddress = (VOID *) ConfigBlkTblAddrPtr;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Add config block into config block table structure.
+
+ @param[in] ConfigBlockTableAddress A pointer to the beginning of Config Block Table Address.
+ @param[out] ConfigBlockAddress On return, points to a pointer to the beginning of Config Block Address.
+
+ @retval EFI_OUT_OF_RESOURCES Config Block Table is full and cannot add new Config Block or
+ Config Block Offset Table is full and cannot add new Config Block.
+ @retval EFI_SUCCESS Successfully added Config Block.
+
+**/
+EFI_STATUS
+EFIAPI
+AddConfigBlock (
+ IN VOID *ConfigBlockTableAddress,
+ OUT VOID **ConfigBlockAddress
+ )
+{
+ CONFIG_BLOCK *TempConfigBlk;
+ CONFIG_BLOCK_TABLE_HEADER *ConfigBlkTblAddrPtr;
+ CONFIG_BLOCK *ConfigBlkAddrPtr;
+ UINT16 OffsetIndex;
+ UINT32 *OffsetTblPtr;
+ UINT32 *LastUsedOffsetPtr;
+ UINT32 LastUsedOffset;
+ UINT32 ConfigBlkTblHdrSize;
+ UINT16 NumOfBlocks;
+ UINT32 ConfigBlkSize;
+
+ OffsetTblPtr = NULL;
+ LastUsedOffsetPtr = NULL;
+ ConfigBlkTblHdrSize = (UINT32) (sizeof (CONFIG_BLOCK_TABLE_HEADER));
+
+ ConfigBlkTblAddrPtr = (CONFIG_BLOCK_TABLE_HEADER *) ConfigBlockTableAddress;
+ ConfigBlkAddrPtr = (CONFIG_BLOCK *) (*ConfigBlockAddress);
+ NumOfBlocks = ConfigBlkTblAddrPtr->NumberOfBlocks;
+ ConfigBlkSize = ConfigBlkAddrPtr->Header.Size;
+
+ if (ConfigBlkTblAddrPtr->AvailableSize < ConfigBlkSize) {
+ DEBUG ((DEBUG_ERROR, "Config Block Table is full and cannot add new Config Block.\n"));
+ DEBUG ((DEBUG_ERROR, "Available size: 0x%x bytes / Requested config Block Size: 0x%x bytes\n", ConfigBlkTblAddrPtr->AvailableSize, ConfigBlkSize));
+ return EFI_OUT_OF_RESOURCES;
+ } else if (ConfigBlkTblAddrPtr->AvailableBlocks == 0) {
+ DEBUG ((DEBUG_ERROR, "Config Block Offset Table is full and cannot add new Config Block.\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ OffsetIndex = NumOfBlocks - ConfigBlkTblAddrPtr->AvailableBlocks;
+ OffsetTblPtr = (UINT32 *) ((UINTN) ConfigBlkTblAddrPtr + ConfigBlkTblHdrSize + (UINTN) ((OffsetIndex) * 4));
+ if (OffsetIndex == 0) {
+ LastUsedOffset = 0;
+ } else {
+ LastUsedOffsetPtr = (UINT32 *) ((UINTN) ConfigBlkTblAddrPtr + ConfigBlkTblHdrSize + (UINTN) ((OffsetIndex - 1) * 4));
+ LastUsedOffset = (UINT32) *LastUsedOffsetPtr;
+ }
+ *OffsetTblPtr = LastUsedOffset + ConfigBlkSize;
+
+ ConfigBlkTblAddrPtr->AvailableBlocks--;
+ ConfigBlkTblAddrPtr->AvailableSize = ConfigBlkTblAddrPtr->AvailableSize - ConfigBlkSize;
+
+ TempConfigBlk = (CONFIG_BLOCK *) ((UINTN) ConfigBlkTblAddrPtr + ConfigBlkTblHdrSize + (UINTN) (NumOfBlocks * 4) + LastUsedOffset);
+ TempConfigBlk->Header.Size = ConfigBlkSize;
+ TempConfigBlk->Header.Revision = ConfigBlkAddrPtr->Header.Revision;
+ TempConfigBlk->Header.Guid = ConfigBlkAddrPtr->Header.Guid;
+
+ *ConfigBlockAddress = (VOID *) TempConfigBlk;
+ DEBUG ((DEBUG_INFO, "ConfigBlock GUID: %g at address : 0x%x\n", &(TempConfigBlk->Header.Guid), (UINT32)(UINTN)*ConfigBlockAddress));
+ DEBUG ((DEBUG_INFO, "AvailableBlocks: %d / AvailableSize: 0x%x bytes\n", ConfigBlkTblAddrPtr->AvailableBlocks, ConfigBlkTblAddrPtr->AvailableSize));
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Retrieve a specific Config Block data by GUID.
+
+ @param[in] ConfigBlockTableAddress A pointer to the beginning of Config Block Table Address.
+ @param[in] ConfigBlockGuid A pointer to the GUID uses to search specific Config Block.
+ @param[out] ConfigBlockAddress On return, points to a pointer to the beginning of Config Block Address.
+
+ @retval EFI_NOT_FOUND Could not find the Config Block.
+ @retval EFI_SUCCESS Config Block found and return.
+
+**/
+EFI_STATUS
+EFIAPI
+GetConfigBlock (
+ IN VOID *ConfigBlockTableAddress,
+ IN EFI_GUID *ConfigBlockGuid,
+ OUT VOID **ConfigBlockAddress
+ )
+{
+ UINT16 OffsetIndex;
+ CONFIG_BLOCK *TempConfigBlk;
+ UINT32 *OffsetTblPtr;
+ CONFIG_BLOCK_TABLE_HEADER *ConfigBlkTblAddrPtr;
+ UINT32 ConfigBlkTblHdrSize;
+ UINT32 ConfigBlkOffset;
+ UINT16 NumOfBlocks;
+
+ OffsetTblPtr = NULL;
+ ConfigBlkTblHdrSize = (UINT32) (sizeof (CONFIG_BLOCK_TABLE_HEADER));
+ ConfigBlkTblAddrPtr = (CONFIG_BLOCK_TABLE_HEADER *) ConfigBlockTableAddress;
+ NumOfBlocks = ConfigBlkTblAddrPtr->NumberOfBlocks;
+
+ ConfigBlkOffset = 0;
+ for (OffsetIndex = 0; OffsetIndex < NumOfBlocks; OffsetIndex++) {
+ TempConfigBlk = (CONFIG_BLOCK *) ((UINTN) ConfigBlkTblAddrPtr + (UINTN) ConfigBlkTblHdrSize + (UINTN) (NumOfBlocks * 4) + (UINTN) ConfigBlkOffset);
+ if (CompareGuid (&(TempConfigBlk->Header.Guid), ConfigBlockGuid)) {
+ *ConfigBlockAddress = (VOID *) TempConfigBlk;
+ return EFI_SUCCESS;
+ }
+ OffsetTblPtr = (UINT32 *) ((UINTN) ConfigBlkTblAddrPtr + ConfigBlkTblHdrSize + (UINTN) (OffsetIndex * 4));
+ ConfigBlkOffset = *OffsetTblPtr;
+ }
+ DEBUG ((DEBUG_ERROR, "Could not find the config block.\n"));
+ return EFI_NOT_FOUND;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/BaseConfigBlockLib/BaseConfigBlockLib.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/BaseConfigBlockLib/BaseConfigBlockLib.inf
new file mode 100644
index 0000000000..0da746348f
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/BaseConfigBlockLib/BaseConfigBlockLib.inf
@@ -0,0 +1,35 @@
+## @file
+# Component INF file for the BaseConfigBlock library.
+#
+# Copyright (c) 2015 - 2016, 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 = 0x00010017
+ BASE_NAME = BaseConfigBlockLib
+ FILE_GUID = 1EC07EA8-7808-4e06-9D79-309AE331D2D5
+ VERSION_STRING = 1.0
+ MODULE_TYPE = BASE
+ LIBRARY_CLASS = ConfigBlockLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ BroxtonSiPkg/BroxtonSiPkg.dec
+ BroxtonPlatformPkg/PlatformPkg.dec
+
+[Sources]
+ BaseConfigBlockLib.c
+
+[LibraryClasses]
+ DebugLib
+ BaseMemoryLib
+ MemoryAllocationLib
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/BaseVariableNvmStorageLib/BaseVariableNvmStorageLib.c b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/BaseVariableNvmStorageLib/BaseVariableNvmStorageLib.c
new file mode 100644
index 0000000000..986f55f883
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/BaseVariableNvmStorageLib/BaseVariableNvmStorageLib.c
@@ -0,0 +1,571 @@
+/** @file
+ Variable NVM Storage Helper library.
+
+ Copyright (c) 2016, 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 <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/VariableNvmStorageLib.h>
+
+/**
+ Returns a pointer of type VARIABLE_NVM_STORE_HEADER to a buffer containing
+ the header of an empty variable store.
+
+ @param[out] VarStoreHeader Pointer to the Variable Store Header.
+
+ @retval EFI_SUCCESS The variable store was created successfully.
+ @retval Others An error occurred creating the variable store.
+
+**/
+EFI_STATUS
+CreateEmptyVariableStore (
+ OUT VARIABLE_NVM_STORE_HEADER *VarStoreHeader
+ )
+{
+ if (VarStoreHeader == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CopyMem (&VarStoreHeader->Signature, &gNvmVariableStoreHeaderGuid, sizeof (EFI_GUID));
+
+ VarStoreHeader->Size = sizeof (VARIABLE_NVM_STORE_HEADER);
+ VarStoreHeader->Revision = VARIABLE_NVM_STORE_REVISION_1_0;
+ VarStoreHeader->Format = VAR_ADDED;
+ VarStoreHeader->State = VARIABLE_STORE_FORMATTED;
+ VarStoreHeader->VariableHeaderTotalEntries = 0;
+ VarStoreHeader->VariableHeaderTotalLength = 0;
+ VarStoreHeader->VariableDataTotalLength = 0;
+ VarStoreHeader->VariableHeaderOffset = VarStoreHeader->Size + 1;
+ VarStoreHeader->VariableHeaderOffset += NVM_GET_PAD_SIZE (VarStoreHeader->VariableHeaderOffset);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+
+ Gets the pointer to the first variable header in the given variable header region.
+
+ @param[in] VarStoreHeader Pointer to the Variable Store Header.
+
+ @return Pointer to the first variable header
+
+**/
+VARIABLE_NVM_HEADER *
+GetStartPointer (
+ IN VARIABLE_NVM_STORE_HEADER *VarStoreHeader
+ )
+{
+ //
+ // The end of the variable store header is the first variable header
+ //
+ return (VARIABLE_NVM_HEADER *) NVM_HEADER_ALIGN (VarStoreHeader + 1);
+}
+
+
+/**
+ This code gets the pointer to the last variable header in the variable header region.
+
+ @param[in] VarStoreHeader Pointer to the Variable Store Header.
+
+ @return VARIABLE_NVM_HEADER* pointer to last unavailable Variable Header.
+
+**/
+VARIABLE_NVM_HEADER *
+GetEndPointer (
+ IN VARIABLE_NVM_STORE_HEADER *VarStoreHeader
+ )
+{
+ //
+ // The end of variable store
+ //
+ return (VARIABLE_NVM_HEADER *)
+ NVM_HEADER_ALIGN (
+ (UINTN) VarStoreHeader +
+ sizeof (VARIABLE_NVM_STORE_HEADER) +
+ VarStoreHeader->VariableHeaderTotalLength
+ );
+}
+
+
+/**
+ This code checks if the variable header is valid or not.
+
+ @param[in] Variable Pointer to the Variable Header.
+ @param[in] VariableStoreEnd Pointer to the end of the Variable Store
+
+ @retval TRUE Variable header is valid.
+ @retval FALSE Variable header is not valid.
+
+**/
+BOOLEAN
+IsValidVariableHeader (
+ IN VARIABLE_NVM_HEADER *Variable,
+ IN VARIABLE_NVM_HEADER *VariableStoreEnd
+ )
+{
+ if ((Variable == NULL) || (Variable >= VariableStoreEnd) || (Variable->StartId != VARIABLE_DATA)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/**
+ Returns whether the variable store contains authenticated variables.
+
+ @param[in] VarStoreHeader Pointer to the Variable Store Header.
+ @param[out] IsAuthenticatedStore Indicates whether this store is authenticated.
+
+ @retval EFI_SUCCESS The authenticated status of the store was successfully determined.
+ @retval EFI_INVALID_PARAMETER An invalid parameter was passed to the function.
+
+**/
+EFI_STATUS
+IsAuthenticatedVariableStore (
+ IN VARIABLE_NVM_STORE_HEADER *VarStoreHeader,
+ OUT BOOLEAN *IsAuthenticatedStore
+ )
+{
+ if (VarStoreHeader == NULL || IsAuthenticatedStore == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *IsAuthenticatedStore = (BOOLEAN) (CompareGuid (&VarStoreHeader->Signature, &gEfiAuthenticatedVariableGuid));
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This code gets the size of the variable header.
+
+ @param[in] AuthFlag Authenticated variable flag.
+
+ @return Size of variable header in bytes in type UINTN.
+
+**/
+UINTN
+GetVariableHeaderSize (
+ IN BOOLEAN AuthFlag
+ )
+{
+ UINTN Value;
+
+ if (AuthFlag) {
+ Value = sizeof (AUTHENTICATED_VARIABLE_NVM_HEADER);
+ } else {
+ Value = sizeof (VARIABLE_NVM_HEADER);
+ }
+
+ return Value;
+}
+
+
+/**
+ This code gets the size of the name of the variable.
+
+ @param[in] Variable Pointer to the Variable Header.
+ @param[in] AuthFlag Authenticated variable flag.
+
+ @return Size of variable in bytes in type UINTN.
+
+**/
+UINTN
+NameSizeOfVariable (
+ IN VARIABLE_NVM_HEADER *Variable,
+ IN BOOLEAN AuthFlag
+ )
+{
+ AUTHENTICATED_VARIABLE_NVM_HEADER *AuthVariable;
+
+ if (AuthFlag) {
+ AuthVariable = (AUTHENTICATED_VARIABLE_NVM_HEADER *) Variable;
+
+ if (AuthVariable->State == (UINT8) (-1) ||
+ AuthVariable->DataSize == (UINT32) (-1) ||
+ AuthVariable->NameSize == (UINT32) (-1) ||
+ AuthVariable->Attributes == (UINT32) (-1)) {
+ return 0;
+ }
+ return (UINTN) AuthVariable->NameSize;
+ } else {
+ if (Variable->State == (UINT8) (-1) ||
+ Variable->DataSize == (UINT32) (-1) ||
+ Variable->NameSize == (UINT32) (-1) ||
+ Variable->Attributes == (UINT32) (-1)) {
+ return 0;
+ }
+ return (UINTN) Variable->NameSize;
+ }
+}
+
+
+/**
+ This code gets the size of the variable data.
+
+ @param[in] Variable Pointer to the Variable Header.
+ @param[in] AuthFlag Authenticated variable flag.
+
+ @return Size of variable in bytes in type UINTN.
+
+**/
+UINTN
+DataSizeOfVariable (
+ IN VARIABLE_NVM_HEADER *Variable,
+ IN BOOLEAN AuthFlag
+ )
+{
+ AUTHENTICATED_VARIABLE_NVM_HEADER *AuthVariable;
+
+ if (AuthFlag) {
+ AuthVariable = (AUTHENTICATED_VARIABLE_NVM_HEADER *) Variable;
+
+ if (AuthVariable->State == (UINT8) (-1) ||
+ AuthVariable->DataSize == (UINT32) (-1) ||
+ AuthVariable->NameSize == (UINT32) (-1) ||
+ AuthVariable->Attributes == (UINT32) (-1)) {
+ return 0;
+ }
+ return (UINTN) AuthVariable->DataSize;
+ } else {
+ if (Variable->State == (UINT8) (-1) ||
+ Variable->DataSize == (UINT32) (-1) ||
+ Variable->NameSize == (UINT32) (-1) ||
+ Variable->Attributes == (UINT32) (-1)) {
+ return 0;
+ }
+ return (UINTN) Variable->DataSize;
+ }
+}
+
+
+/**
+ This code gets the pointer to the variable name.
+
+ @param[in] Variable Pointer to the Variable Header.
+ @param[in] AuthFlag Authenticated variable flag.
+
+ @return A CHAR16* pointer to Variable Name.
+
+**/
+CHAR16 *
+GetVariableNamePtr (
+ IN VARIABLE_NVM_HEADER *Variable,
+ IN BOOLEAN AuthFlag
+ )
+{
+ return (CHAR16 *) ((UINTN) Variable + GetVariableHeaderSize (AuthFlag));
+}
+
+
+/**
+ This code gets the pointer to the variable GUID.
+
+ @param[in] Variable Pointer to the Variable Header.
+ @param[in] AuthFlag Authenticated variable flag.
+
+ @return A EFI_GUID* pointer to Vendor Guid.
+
+**/
+EFI_GUID *
+GetVendorGuidPtr (
+ IN VARIABLE_NVM_HEADER *Variable,
+ IN BOOLEAN AuthFlag
+ )
+{
+ AUTHENTICATED_VARIABLE_NVM_HEADER *AuthVariable;
+
+ if (AuthFlag) {
+ AuthVariable = (AUTHENTICATED_VARIABLE_NVM_HEADER *) Variable;
+
+ return &AuthVariable->VendorGuid;
+ } else {
+ return &Variable->VendorGuid;
+ }
+}
+
+
+/**
+ This code gets the pointer to the variable data.
+
+ This is an "offset" that is interpreted as needed based on the caller's requirements.
+
+ @param[in] Variable Pointer to the Variable Header.
+ @param[in] StoreInfo Pointer to a Variable Store Info structure for this variable.
+
+ @return A UINT32 value representing the offset to the variable data.
+
+**/
+UINT32
+GetVariableDataPtr (
+ IN VARIABLE_NVM_HEADER *Variable,
+ IN VARIABLE_NVM_STORE_INFO *StoreInfo
+ )
+{
+ if (StoreInfo->AuthFlag) {
+ return ((AUTHENTICATED_VARIABLE_NVM_HEADER *) Variable)->DataOffset;
+ } else {
+ return Variable->DataOffset;
+ }
+}
+
+
+/**
+ This code gets the pointer to the next variable header.
+
+ @param[in] StoreInfo Pointer to variable store info structure.
+ @param[in] VariableHeader Pointer to the Variable Header.
+
+ @return A VARIABLE_NVM_HEADER* pointer to next variable header.
+
+**/
+VARIABLE_NVM_HEADER *
+GetNextVariablePtr (
+ IN VARIABLE_NVM_STORE_INFO *StoreInfo,
+ IN VARIABLE_NVM_HEADER *VariableHeader
+ )
+{
+ UINTN Value;
+
+ if (!IsValidVariableHeader (VariableHeader, GetEndPointer(StoreInfo->VariableStoreHeader))) {
+ DEBUG ((EFI_D_ERROR, "Invalid header hit in GetNextVariablePtr() header address = 0x%x, store end = 0x%x\n",
+ VariableHeader, GetEndPointer(StoreInfo->VariableStoreHeader)));
+ return NULL;
+ }
+
+ Value = (UINTN) GetVariableNamePtr (VariableHeader, StoreInfo->AuthFlag);
+ Value += NameSizeOfVariable (VariableHeader, StoreInfo->AuthFlag);
+ Value += NVM_GET_PAD_SIZE (NameSizeOfVariable (VariableHeader, StoreInfo->AuthFlag));
+
+ return (VARIABLE_NVM_HEADER *) NVM_HEADER_ALIGN (Value);
+}
+
+
+/**
+ Get variable store status.
+
+ @param[in] VarStoreHeader Pointer to the Variable Store Header.
+
+ @retval EfiRaw Variable store is raw
+ @retval EfiValid Variable store is valid
+ @retval EfiInvalid Variable store is invalid
+
+**/
+VARIABLE_STORE_STATUS
+GetVariableStoreStatus (
+ IN VARIABLE_NVM_STORE_HEADER *VarStoreHeader
+ )
+{
+ if (CompareGuid (&VarStoreHeader->Signature, &gNvmVariableStoreHeaderGuid) &&
+ VarStoreHeader->Format == VARIABLE_STORE_FORMATTED &&
+ VarStoreHeader->State == VARIABLE_STORE_HEALTHY) {
+ return EfiValid;
+ }
+
+ if (((UINT32 *) (&VarStoreHeader->Signature))[0] == 0xffffffff &&
+ ((UINT32 *) (&VarStoreHeader->Signature))[1] == 0xffffffff &&
+ ((UINT32 *) (&VarStoreHeader->Signature))[2] == 0xffffffff &&
+ ((UINT32 *) (&VarStoreHeader->Signature))[3] == 0xffffffff &&
+ VarStoreHeader->Size == 0xffffffff &&
+ VarStoreHeader->Format == 0xff &&
+ VarStoreHeader->State == 0xff
+ ) {
+ return EfiRaw;
+ } else {
+ return EfiInvalid;
+ }
+}
+
+
+/**
+ Compare two variable names.
+
+ @param[in] StoreInfo Pointer to variable store info structure.
+ @param[in] Name1 Pointer to one variable name.
+ @param[in] Name2 Pointer to another variable name.
+ @param[in] NameSize Variable name size.
+
+ @retval TRUE Name1 and Name2 are identical.
+ @retval FALSE Name1 and Name2 are not identical.
+
+**/
+BOOLEAN
+CompareVariableName (
+ IN VARIABLE_NVM_STORE_INFO *StoreInfo,
+ IN CONST CHAR16 *Name1,
+ IN CONST CHAR16 *Name2,
+ IN UINTN NameSize
+ )
+{
+ //
+ // Both Name1 and Name2 are consecutive.
+ //
+ if (CompareMem ((UINT8 *) Name1, (UINT8 *) Name2, NameSize) == 0) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+/**
+ This function compares a variable with the variable entry in the database.
+
+ @param[in] StoreInfo Pointer to variable store info structure.
+ @param[in] Variable Pointer to the variable in our database
+ @param[in] VariableHeader Pointer to the Variable Header that has consecutive content.
+ @param[in] VariableName Name of the variable to compare to 'Variable'
+ @param[in] VendorGuid GUID of the variable to compare to 'Variable'
+ @param[in] PtrTrack Variable Track Pointer structure that contains Variable Information.
+
+ @retval EFI_SUCCESS Found match variable
+ @retval EFI_NOT_FOUND Variable not found
+
+**/
+EFI_STATUS
+CompareWithValidVariable (
+ IN VARIABLE_NVM_STORE_INFO *StoreInfo,
+ IN VARIABLE_NVM_HEADER *Variable,
+ IN VARIABLE_NVM_HEADER *VariableHeader,
+ IN CONST CHAR16 *VariableName,
+ IN CONST EFI_GUID *VendorGuid,
+ OUT VARIABLE_NVM_POINTER_TRACK *PtrTrack
+ )
+{
+ VOID *Point;
+ EFI_GUID *TempVendorGuid;
+
+ TempVendorGuid = GetVendorGuidPtr (VariableHeader, StoreInfo->AuthFlag);
+
+ if (VariableName[0] == 0) {
+ PtrTrack->CurrPtr = Variable;
+ return EFI_SUCCESS;
+ } else {
+ //
+ // Don't use CompareGuid function here for performance reasons.
+ // Instead we compare the GUID a UINT32 at a time and branch
+ // on the first failed comparison.
+ //
+ if ((((INT32 *) VendorGuid)[0] == ((INT32 *) TempVendorGuid)[0]) &&
+ (((INT32 *) VendorGuid)[1] == ((INT32 *) TempVendorGuid)[1]) &&
+ (((INT32 *) VendorGuid)[2] == ((INT32 *) TempVendorGuid)[2]) &&
+ (((INT32 *) VendorGuid)[3] == ((INT32 *) TempVendorGuid)[3])
+ ) {
+ ASSERT (NameSizeOfVariable (VariableHeader, StoreInfo->AuthFlag) != 0);
+ Point = (VOID *) GetVariableNamePtr (Variable, StoreInfo->AuthFlag);
+ if (CompareVariableName (StoreInfo, VariableName, Point, NameSizeOfVariable (VariableHeader, StoreInfo->AuthFlag))) {
+ PtrTrack->CurrPtr = Variable;
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ Validate the provided variable header.
+
+ @param[in] StoreInfo Pointer to variable store info structure.
+ @param[in] Variable Pointer to the Variable Header.
+ @param[out] VariableHeader Pointer to Pointer to the Variable Header that has consecutive content.
+
+ @retval TRUE Variable header is valid.
+ @retval FALSE Variable header is not valid.
+
+**/
+BOOLEAN
+GetVariableHeader (
+ IN VARIABLE_NVM_STORE_INFO *StoreInfo,
+ IN VARIABLE_NVM_HEADER *Variable,
+ OUT VARIABLE_NVM_HEADER **VariableHeader
+ )
+{
+ VARIABLE_NVM_HEADER *EndVariablePtr;
+
+ if (Variable == NULL) {
+ return FALSE;
+ }
+
+ *VariableHeader = Variable;
+ EndVariablePtr = GetEndPointer (StoreInfo->VariableStoreHeader);
+
+ if (Variable >= EndVariablePtr) {
+ //
+ // Reached the end of the variable store.
+ //
+ return FALSE;
+ }
+
+ return IsValidVariableHeader (*VariableHeader, EndVariablePtr);
+}
+
+
+/**
+ Copy the variable name to the output buffer.
+
+ @param[in] StoreInfo Pointer to variable store info structure.
+ @param[in] NameOrData Pointer to the variable name/data that may not be consecutive.
+ @param[in] Size Variable name/data size.
+ @param[out] Buffer Pointer to output buffer to hold the variable name/data.
+
+**/
+VOID
+GetVariableName (
+ IN VARIABLE_NVM_STORE_INFO *StoreInfo,
+ IN UINT8 *Name,
+ IN UINTN Size,
+ OUT UINT8 *Buffer
+ )
+{
+ //
+ // Variable name/data is consecutive.
+ //
+ CopyMem (Buffer, Name, Size);
+}
+
+
+/**
+ Compares two EFI_TIME data structures.
+
+ @param[in] FirstTime A pointer to the first EFI_TIME data.
+ @param[in] SecondTime A pointer to the second EFI_TIME data.
+
+ @retval TRUE The FirstTime is not later than the SecondTime.
+ @retval FALSE The FirstTime is later than the SecondTime.
+
+**/
+BOOLEAN
+VariableNvmCompareTimeStamp (
+ IN EFI_TIME *FirstTime,
+ IN EFI_TIME *SecondTime
+ )
+{
+ if (FirstTime->Year != SecondTime->Year) {
+ return (BOOLEAN) (FirstTime->Year < SecondTime->Year);
+ } else if (FirstTime->Month != SecondTime->Month) {
+ return (BOOLEAN) (FirstTime->Month < SecondTime->Month);
+ } else if (FirstTime->Day != SecondTime->Day) {
+ return (BOOLEAN) (FirstTime->Day < SecondTime->Day);
+ } else if (FirstTime->Hour != SecondTime->Hour) {
+ return (BOOLEAN) (FirstTime->Hour < SecondTime->Hour);
+ } else if (FirstTime->Minute != SecondTime->Minute) {
+ return (BOOLEAN) (FirstTime->Minute < SecondTime->Minute);
+ }
+
+ return (BOOLEAN) (FirstTime->Second <= SecondTime->Second);
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/BaseVariableNvmStorageLib/BaseVariableNvmStorageLib.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/BaseVariableNvmStorageLib/BaseVariableNvmStorageLib.inf
new file mode 100644
index 0000000000..5782525e13
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/BaseVariableNvmStorageLib/BaseVariableNvmStorageLib.inf
@@ -0,0 +1,44 @@
+## @file
+# Variable NVM Storage Helper library.
+#
+# Provides functions for common operations when using the VARIABLE_NVM_HEADER format.
+#
+# Copyright (c) 2016, 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 = BaseVariableNvmStorageLib
+ FILE_GUID = B4705047-F118-436B-8395-AA4596E819BB
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = VariableNvmStorageLib
+
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ BaseVariableNvmStorageLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ BroxtonSiPkg/BroxtonSiPkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ DebugLib
+ MemoryAllocationLib
+
+[Guids]
+ gNvmVariableStoreHeaderGuid ## CONSUMES ## GUID
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/BaseVariableStorageSelectorLib/BaseVariableStorageSelectorLib.c b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/BaseVariableStorageSelectorLib/BaseVariableStorageSelectorLib.c
new file mode 100644
index 0000000000..9931ec405c
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/BaseVariableStorageSelectorLib/BaseVariableStorageSelectorLib.c
@@ -0,0 +1,60 @@
+/** @file
+ Variable Storage Selector Library.
+
+ Copyright (c) 2016, 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 <Library/BaseMemoryLib.h>
+#include <Library/PcdLib.h>
+#include <Library/VariableStorageSelectorLib.h>
+#include <Guid/CseVariableStoragePpiInstanceGuid.h>
+#include <Guid/CseVariableStorageProtocolInstanceGuid.h>
+
+//
+// NOTE: Dynamic PCDs cannot be consumed in this library due to
+// lock conflicts with the variable driver.
+//
+
+/**
+ Gets the variable storage instance ID for the variable storage instance
+ that is used to store a given variable.
+
+ @param[in] VariableName A pointer to a null-terminated string that is
+ the variable's name.
+ @param[in] VariableGuid A pointer to an EFI_GUID that is the variable's
+ GUID. The combination of VariableGuid and
+ VariableName must be unique.
+ @param[in] AtDxe True if in DXE. False if in PEI.
+ @param[out] VariableStorageId The ID for the variable storage instance that
+ stores a given variable.
+
+ @retval EFI_SUCCESS Variable storage instance id was retrieved.
+
+**/
+EFI_STATUS
+EFIAPI
+GetVariableStorageId (
+ IN CONST CHAR16 *VariableName,
+ IN CONST EFI_GUID *VendorGuid,
+ IN BOOLEAN AtDxe,
+ OUT EFI_GUID *VariableStorageId
+ )
+{
+ if (AtDxe) {
+ CopyMem (VariableStorageId, &gCseVariableStorageProtocolInstanceGuid, sizeof (EFI_GUID));
+ } else {
+ CopyMem (VariableStorageId, &gCseVariableStoragePpiInstanceGuid, sizeof (EFI_GUID));
+ }
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/BaseVariableStorageSelectorLib/BaseVariableStorageSelectorLib.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/BaseVariableStorageSelectorLib/BaseVariableStorageSelectorLib.inf
new file mode 100644
index 0000000000..9ea465c75c
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/BaseVariableStorageSelectorLib/BaseVariableStorageSelectorLib.inf
@@ -0,0 +1,44 @@
+## @file
+# Variable Storage Selector Library.
+#
+# Copyright (c) 2016, 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 = BaseVariableStorageSelectorLib
+ FILE_GUID = 68F4E42C-93E2-4881-AF08-46F56E5983E0
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = VariableStorageSelectorLib
+
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ BaseVariableStorageSelectorLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ BroxtonSiPkg/BroxtonSiPkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ PcdLib
+
+[Guids]
+ gCseVariableStoragePpiInstanceGuid
+ gSpiVariableStoragePpiInstanceGuid
+ gCseVariableStorageProtocolInstanceGuid
+ gSpiVariableStorageProtocolInstanceGuid
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/DxeAslUpdateLib/DxeAslUpdateLib.c b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/DxeAslUpdateLib/DxeAslUpdateLib.c
new file mode 100644
index 0000000000..e1fa4faafc
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/DxeAslUpdateLib/DxeAslUpdateLib.c
@@ -0,0 +1,312 @@
+/** @file
+ Boot service DXE ASL update library implementation.
+
+ These functions in this file can be called during DXE and cannot be called during runtime
+ or in SMM which should use a RT or SMM library.
+
+ This library uses the ACPI Support protocol.
+
+ Copyright (c) 1999 - 2016, 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 <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Uefi/UefiSpec.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/AslUpdateLib.h>
+
+//
+// Function implemenations
+//
+static EFI_ACPI_SUPPORT_PROTOCOL *mAcpiSupport = NULL;
+static EFI_ACPI_TABLE_PROTOCOL *mAcpiTable = NULL;
+
+/**
+ Initialize the ASL update library state.
+ This must be called prior to invoking other library functions.
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+InitializeAslUpdateLib (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Locate ACPI tables
+ //
+ Status = gBS->LocateProtocol (&gEfiAcpiSupportProtocolGuid, NULL, (VOID **) &mAcpiSupport);
+ ASSERT_EFI_ERROR (Status);
+ Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &mAcpiTable);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+
+/**
+ This procedure will update immediate value assigned to a Name
+
+ @param[in] AslSignature The signature of Operation Region that we want to update.
+ @param[in] Buffer Source of data to be written over original aml.
+ @param[in] Length Length of data to be overwritten.
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+UpdateNameAslCode(
+ IN UINT32 AslSignature,
+ IN VOID *Buffer,
+ IN UINTN Length
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_DESCRIPTION_HEADER *Table;
+ UINT8 *CurrPtr;
+ UINT32 *Signature;
+ UINT8 *DsdtPointer;
+ UINTN Handle;
+ UINT8 DataSize;
+
+ if (mAcpiTable == NULL) {
+ InitializeAslUpdateLib ();
+ if (mAcpiTable == NULL) {
+ return EFI_NOT_READY;
+ }
+ }
+
+ //
+ // Locate table with matching ID
+ //
+ Handle = 0;
+ Status = LocateAcpiTableBySignature (
+ EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE,
+ (EFI_ACPI_DESCRIPTION_HEADER **) &Table,
+ &Handle
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Point to the beginning of the DSDT table
+ //
+ CurrPtr = (UINT8 *) Table;
+
+ //
+ // Loop through the ASL looking for values that we must fix up.
+ //
+ for (DsdtPointer = CurrPtr; DsdtPointer <= (CurrPtr + ((EFI_ACPI_COMMON_HEADER *) CurrPtr)->Length); DsdtPointer++) {
+ //
+ // Get a pointer to compare for signature
+ //
+ Signature = (UINT32 *) DsdtPointer;
+ //
+ // Check if this is the Device Object signature we are looking for
+ //
+ if ((*Signature) == AslSignature) {
+ //
+ // Look for Name Encoding
+ //
+ if (*(DsdtPointer-1) == AML_NAME_OP) {
+ //
+ // Check if size of new and old data is the same
+ //
+ DataSize = *(DsdtPointer+4);
+ if ((Length == 1 && DataSize == 0xA) ||
+ (Length == 2 && DataSize == 0xB) ||
+ (Length == 4 && DataSize == 0xC) ) {
+ CopyMem (DsdtPointer + 5, Buffer, Length);
+ } else if (Length == 1 && ((*(UINT8*)Buffer) == 0 || (*(UINT8*) Buffer) == 1) && (DataSize == 0 || DataSize == 1)) {
+ CopyMem (DsdtPointer+4, Buffer, Length);
+ } else {
+ FreePool (Table);
+ return EFI_BAD_BUFFER_SIZE;
+ }
+ Status = mAcpiTable->UninstallAcpiTable (
+ mAcpiTable,
+ Handle
+ );
+ Handle = 0;
+ Status = mAcpiTable->InstallAcpiTable (
+ mAcpiTable,
+ Table,
+ Table->Length,
+ &Handle
+ );
+ FreePool (Table);
+ return Status;
+ }
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ This function uses the ACPI SDT protocol to locate an ACPI table.
+ It is really only useful for finding tables that only have a single instance,
+ e.g. FADT, FACS, MADT, etc. It is not good for locating SSDT, etc.
+
+ @param[in] Signature Pointer to an ASCII string containing the OEM Table ID from the ACPI table header
+ @param[in, out] Table Updated with a pointer to the table
+ @param[in, out] Handle AcpiSupport protocol table handle for the table found
+ @param[in, out] Version The version of the table desired
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+LocateAcpiTableBySignature (
+ IN UINT32 Signature,
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER **Table,
+ IN OUT UINTN *Handle
+ )
+{
+ EFI_STATUS Status;
+ INTN Index;
+ EFI_ACPI_TABLE_VERSION Version;
+
+ if (mAcpiSupport == NULL) {
+ InitializeAslUpdateLib();
+ if (mAcpiSupport == NULL) {
+ return EFI_NOT_READY;
+ }
+ }
+
+ //
+ // Locate table with matching ID
+ //
+ Version = 0;
+ Index = 0;
+ do {
+ Status = mAcpiSupport->GetAcpiTable (mAcpiSupport, Index, (VOID *) Table, &Version, Handle);
+ if (Status == EFI_NOT_FOUND) {
+ break;
+ }
+
+ ASSERT_EFI_ERROR (Status);
+ Index++;
+ } while ((*Table)->Signature != Signature);
+ //
+ // If we found the table, there will be no error.
+ //
+ return Status;
+}
+
+
+/**
+ This function uses the ACPI SDT protocol to locate an ACPI SSDT table.
+
+ @param[in] TableId Pointer to an ASCII string containing the OEM Table ID from the ACPI table header
+ @param[in] TableIdSize Length of the TableId to match. Table ID are 8 bytes long, this function
+ will consider it a match if the first TableIdSize bytes match
+ @param[in, out] Table Updated with a pointer to the table
+ @param[in, out] Handle AcpiSupport protocol table handle for the table found
+ @param[in, out] Version See AcpiSupport protocol, GetAcpiTable function for use
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+LocateAcpiTableByOemTableId (
+ IN UINT8 *TableId,
+ IN UINT8 TableIdSize,
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER **Table,
+ IN OUT UINTN *Handle
+ )
+{
+ EFI_STATUS Status;
+ INTN Index;
+ EFI_ACPI_TABLE_VERSION Version;
+
+ if (mAcpiSupport == NULL) {
+ InitializeAslUpdateLib();
+ if (mAcpiSupport == NULL) {
+ return EFI_NOT_READY;
+ }
+ }
+ //
+ // Locate table with matching ID
+ //
+ Version = 0;
+ Index = 0;
+ do {
+ Status = mAcpiSupport->GetAcpiTable (mAcpiSupport, Index, (VOID **) Table, &Version, Handle);
+ if (Status == EFI_NOT_FOUND) {
+ break;
+ }
+ ASSERT_EFI_ERROR (Status);
+ Index++;
+ } while (CompareMem (&(*Table)->OemTableId, TableId, TableIdSize));
+ //
+ // If we found the table, there will be no error.
+ //
+ return Status;
+}
+
+
+/**
+ This function calculates and updates an UINT8 checksum.
+
+ @param[in] Buffer Pointer to buffer to checksum
+ @param[in] Size Number of bytes to checksum
+ @param[in] ChecksumOffset Offset to place the checksum result in
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+AcpiChecksum (
+ IN VOID *Buffer,
+ IN UINTN Size,
+ IN UINTN ChecksumOffset
+ )
+{
+ UINT8 Sum;
+ UINT8 *Ptr;
+
+ Sum = 0;
+ //
+ // Initialize pointer
+ //
+ Ptr = Buffer;
+
+ //
+ // set checksum to 0 first
+ //
+ Ptr[ChecksumOffset] = 0;
+
+ //
+ // add all content of buffer
+ //
+ while (Size--) {
+ Sum = (UINT8) (Sum + (*Ptr++));
+ }
+ //
+ // set checksum
+ //
+ Ptr = Buffer;
+ Ptr[ChecksumOffset] = (UINT8) (0xff - Sum + 1);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/DxeAslUpdateLib/DxeAslUpdateLib.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/DxeAslUpdateLib/DxeAslUpdateLib.inf
new file mode 100644
index 0000000000..b9105c0f1b
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/DxeAslUpdateLib/DxeAslUpdateLib.inf
@@ -0,0 +1,42 @@
+## @file
+# Provides services to update ASL tables.
+#
+# Copyright (c) 1999 - 2016, 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 = 0x00010017
+ BASE_NAME = DxeAslUpdateLib
+ FILE_GUID = 8621697D-4E3A-4bf2-ADB0-3E2FF06559CA
+ VERSION_STRING = 1.0
+ MODULE_TYPE = BASE
+ LIBRARY_CLASS = AslUpdateLib
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+ DebugLib
+ PcdLib
+ BaseMemoryLib
+ UefiLib
+ MemoryAllocationLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ BroxtonSiPkg/BroxtonSiPkg.dec
+
+[Sources]
+ DxeAslUpdateLib.c
+
+[Protocols]
+ gEfiAcpiTableProtocolGuid ## CONSUMES
+ gEfiAcpiSupportProtocolGuid ## CONSUMES
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/GpioLib/GpioLib.c b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/GpioLib/GpioLib.c
new file mode 100644
index 0000000000..01ac0fa66e
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/GpioLib/GpioLib.c
@@ -0,0 +1,1230 @@
+/** @file
+ This library provides the GPIO library definitions.
+
+ Copyright (c) 1999 - 2016, 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/UefiBaseType.h>
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/SideBandLib.h>
+#include <Library/ScPlatformLib.h>
+#include <SaAccess.h>
+#include <Library/GpioLib.h>
+#include <Library/SteppingLib.h>
+#include <ScAccess.h>
+#include <Guid/PlatformInfo.h>
+#include <Library/HobLib.h>
+
+#define GPIO_GET_GROUP_FROM_PAD(Pad) ((Pad) >> 16)
+#define GPIO_GET_PAD_OFFSET(Pad) ((Pad) & 0xFFFF)
+#define GPIO_GET_PAD_NUMBER(Offset) ((Offset - GPIO_PADBAR) / 8)
+
+//
+// If in GPIO_GROUP_INFO structure certain register doesn't exist
+// it will have value equal to NO_REGISTER_FOR_PROPERTY
+//
+#define NO_REGISTER_FOR_PROPERTY 0xFFFF
+
+//
+// Possible registers to be accessed
+//
+typedef enum {
+ GpioHostOwnershipRegister = 0,
+ GpioGpeEnableRegister,
+ GpioGpeStatusRegister,
+ GpioSmiEnableRegister,
+ GpioSmiStatusRegister,
+ GpioNmiEnableRegister,
+ GpioPadConfigLockRegister,
+ GpioPadLockOutputRegister
+} GPIO_REG;
+
+//
+// Structure for storing information about registers offset, community,
+// maximal pad number for available groups
+//
+typedef struct {
+ UINT8 Community;
+ UINT16 SmiStsOffset;
+ UINT16 SmiEnOffset;
+ UINT16 PadCfgLockOffset;
+ UINT16 PadCfgLockTxOffset;
+ UINT8 PadPerGroup;
+} GPIO_GROUP_INFO;
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_GROUP_INFO mBxtpGpioGroupInfo[] = {
+ {GPIO_SOUTHWEST_COMMUNITY, R_PCR_GPIO_SMI_STS_0, R_PCR_GPIO_SMI_EN_0, R_PCR_GPIO_PADCFGLOCK_0, R_PCR_GPIO_PADCFGLOCKTX_0, 32},
+ {GPIO_SOUTHWEST_COMMUNITY, R_PCR_GPIO_SMI_STS_1, R_PCR_GPIO_SMI_EN_1, R_PCR_GPIO_PADCFGLOCK_1, R_PCR_GPIO_PADCFGLOCKTX_1, 11},
+ {GPIO_WEST_COMMUNITY, R_PCR_GPIO_SMI_STS_0, R_PCR_GPIO_SMI_EN_0, R_PCR_GPIO_PADCFGLOCK_0, R_PCR_GPIO_PADCFGLOCKTX_0, 32},
+ {GPIO_WEST_COMMUNITY, R_PCR_GPIO_SMI_STS_1, R_PCR_GPIO_SMI_EN_1, R_PCR_GPIO_PADCFGLOCK_1, R_PCR_GPIO_PADCFGLOCKTX_1, 15},
+ {GPIO_NORTHWEST_COMMUNITY, R_PCR_GPIO_SMI_STS_0, R_PCR_GPIO_SMI_EN_0, R_PCR_GPIO_PADCFGLOCK_0, R_PCR_GPIO_PADCFGLOCKTX_0, 32},
+ {GPIO_NORTHWEST_COMMUNITY, R_PCR_GPIO_SMI_STS_1, R_PCR_GPIO_SMI_EN_1, R_PCR_GPIO_PADCFGLOCK_1, R_PCR_GPIO_PADCFGLOCKTX_1, 32},
+ {GPIO_NORTHWEST_COMMUNITY, R_PCR_GPIO_SMI_STS_2, R_PCR_GPIO_SMI_EN_2, R_PCR_GPIO_PADCFGLOCK_2, R_PCR_GPIO_PADCFGLOCKTX_2, 13},
+ {GPIO_NORTH_COMMUNITY, R_PCR_GPIO_SMI_STS_0, R_PCR_GPIO_SMI_EN_0, R_PCR_GPIO_PADCFGLOCK_0, R_PCR_GPIO_PADCFGLOCKTX_0, 32},
+ {GPIO_NORTH_COMMUNITY, R_PCR_GPIO_SMI_STS_1, R_PCR_GPIO_SMI_EN_1, R_PCR_GPIO_PADCFGLOCK_1, R_PCR_GPIO_PADCFGLOCKTX_1, 32},
+ {GPIO_NORTH_COMMUNITY, R_PCR_GPIO_SMI_STS_2, R_PCR_GPIO_SMI_EN_2, R_PCR_GPIO_PADCFGLOCK_2, R_PCR_GPIO_PADCFGLOCKTX_2, 13},
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_GROUP_INFO mBxtGpioGroupInfo[] = {
+ {GPIO_SOUTH_COMMUNITY, R_PCR_GPIO_SMI_STS_0, R_PCR_GPIO_SMI_EN_0, R_PCR_GPIO_PADCFGLOCK_0, R_PCR_GPIO_PADCFGLOCKTX_0, 20},
+ {GPIO_SOUTHWEST_COMMUNITY, R_PCR_GPIO_SMI_STS_0, R_PCR_GPIO_SMI_EN_0, R_PCR_GPIO_PADCFGLOCK_0, R_PCR_GPIO_PADCFGLOCKTX_0, 31},
+ {GPIO_WEST_COMMUNITY, R_PCR_GPIO_SMI_STS_0, R_PCR_GPIO_SMI_EN_0, R_PCR_GPIO_PADCFGLOCK_0, R_PCR_GPIO_PADCFGLOCKTX_0, 32},
+ {GPIO_WEST_COMMUNITY, R_PCR_GPIO_SMI_STS_1, R_PCR_GPIO_SMI_EN_1, R_PCR_GPIO_PADCFGLOCK_1, R_PCR_GPIO_PADCFGLOCKTX_1, 10},
+ {GPIO_NORTHWEST_COMMUNITY, R_PCR_GPIO_SMI_STS_0, R_PCR_GPIO_SMI_EN_0, R_PCR_GPIO_PADCFGLOCK_0, R_PCR_GPIO_PADCFGLOCKTX_0, 32},
+ {GPIO_NORTHWEST_COMMUNITY, R_PCR_GPIO_SMI_STS_1, R_PCR_GPIO_SMI_EN_1, R_PCR_GPIO_PADCFGLOCK_1, R_PCR_GPIO_PADCFGLOCKTX_1, 32},
+ {GPIO_NORTHWEST_COMMUNITY, R_PCR_GPIO_SMI_STS_2, R_PCR_GPIO_SMI_EN_2, R_PCR_GPIO_PADCFGLOCK_2, R_PCR_GPIO_PADCFGLOCKTX_2, 8},
+ {GPIO_NORTH_COMMUNITY, R_PCR_GPIO_SMI_STS_0, R_PCR_GPIO_SMI_EN_0, R_PCR_GPIO_PADCFGLOCK_0, R_PCR_GPIO_PADCFGLOCKTX_0, 32},
+ {GPIO_NORTH_COMMUNITY, R_PCR_GPIO_SMI_STS_1, R_PCR_GPIO_SMI_EN_1, R_PCR_GPIO_PADCFGLOCK_1, R_PCR_GPIO_PADCFGLOCKTX_1, 32},
+ {GPIO_NORTH_COMMUNITY, R_PCR_GPIO_SMI_STS_2, R_PCR_GPIO_SMI_EN_2, R_PCR_GPIO_PADCFGLOCK_2, R_PCR_GPIO_PADCFGLOCKTX_2, 19},
+};
+
+/**
+ This procedure will retrieve address and length of GPIO info table
+
+ @param[out] GpioGroupInfoTableLength Length of GPIO group table
+
+ @retval Pointer to GPIO group table
+
+**/
+GPIO_GROUP_INFO*
+GpioGetGroupInfoTable (
+ OUT UINT32 *GpioGroupInfoTableLength
+ )
+{
+ BXT_SERIES BxtSeries;
+
+ BxtSeries = GetBxtSeries ();
+ if (BxtSeries == BxtP) {
+ *GpioGroupInfoTableLength = sizeof (mBxtpGpioGroupInfo) / sizeof (GPIO_GROUP_INFO);
+ return mBxtpGpioGroupInfo;
+ } else if (BxtSeries == Bxt || (BxtSeries == Bxt1)) {
+ *GpioGroupInfoTableLength = sizeof (mBxtGpioGroupInfo) / sizeof (GPIO_GROUP_INFO);
+ return mBxtGpioGroupInfo;
+ } else {
+ *GpioGroupInfoTableLength = 0;
+ return NULL;
+ }
+}
+
+
+/**
+ Common interface to read an 32-bit GPIO register.
+
+ @param[in] Community Community Port ID definition.
+ SouthWest Community: 0xC0
+ South Community : 0xC2
+ NorthWest Community: 0xC4
+ North Community : 0xC5
+ West Community : 0xC7
+ @param[in] Offset The GPIO register to read.
+
+ @retval UINT32 The 32-bit value read from side band.
+
+**/
+UINT32
+GpioRead (
+ IN UINT8 Community,
+ IN UINT16 Offset
+ )
+{
+ return SideBandRead32 (Community, Offset);
+}
+
+
+/**
+ Common interface to write an 32-bit GPIO register.
+
+ @param[in] Community Community Port ID definition.
+ SouthWest Community: 0xC0
+ South Community : 0xC2
+ NorthWest Community: 0xC4
+ North Community : 0xC5
+ West Community : 0xC7
+ @param[in] Offset The GPIO register to write.
+ @param[in] Value The value to write.
+
+ @retval EFI_SUCCESS Write GPIO register successfully.
+
+**/
+EFI_STATUS
+GpioWrite (
+ IN UINT8 Community,
+ IN UINT16 Offset,
+ IN UINT32 Value
+ )
+{
+ SideBandWrite32 (Community, Offset, Value);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Common interface to read an 32-bit specific GPIO pad register.
+
+ It is recommand to use the definition of GPIO pad in GpioLib.h
+ e.g. GpioPadRead (N_GPIO_20)
+
+ @param[in] CommAndOffset It contains GPIO community and offset.
+
+ @retval UINT32 The 32-bit value read from GpioRead operation.
+
+**/
+UINT32
+GpioPadRead (
+ IN UINT32 CommAndOffset
+ )
+{
+ UINT8 Community;
+ UINT16 GpioPadOffset;
+
+ GpioPadOffset = (UINT16) (CommAndOffset & 0xFFFF);
+ Community = (UINT8) (CommAndOffset >> 16);
+
+ return GpioRead (Community, GpioPadOffset);
+}
+
+
+/**
+ Common interface to write an 32-bit to a specific GPIO pad register.
+
+ It is recommand to use the definition of GPIO pad in GpioLib.h
+ e.g. GpioPadWrite (N_GPIO_20, 0xXXXXXXXX)
+
+ @param[in] CommAndOffset It contains GPIO community and offset.
+ @param[in] Value The value to write.
+
+ @retval EFI_SUCCESS Write to a specific GPIO pad register successfully.
+ @retval Others Status depends on GpioWrite operation.
+
+**/
+EFI_STATUS
+GpioPadWrite (
+ IN UINT32 CommAndOffset,
+ IN UINT32 Value
+ )
+{
+ UINT8 Community;
+ UINT16 GpioPadOffset;
+
+ GpioPadOffset = (UINT16) (CommAndOffset & 0xFFFF);
+ Community = (UINT8) (CommAndOffset >> 16);
+
+ return GpioWrite (Community, GpioPadOffset, Value);
+}
+
+
+//
+// Common interface for GPIO pad ownership check
+//
+GPIO_PAD_OWNERSHIP
+GpioPadOwnershipCheck (
+ IN UINT32 CommAndOffset
+ )
+{
+ GPIO_PAD_OWNERSHIP Ownership = Host_Gpio_Mode;
+ UINT8 Community = 0;
+ UINT16 GpioPadOffset = 0;
+ UINT16 Index = 0;
+ UINT32 D32 = 0;
+
+ GpioPadOffset = (UINT16) (CommAndOffset & 0xFFFF);
+ Community = (UINT8) (CommAndOffset >> 16);
+ Index = (GpioPadOffset - GPIO_PADBAR) / 8;
+
+ //
+ // check pad ownership
+ //
+ D32 = GpioRead (Community, PAD_OWNERSHIP_0 + (Index / 8) * 4);
+ Ownership = (GPIO_PAD_OWNERSHIP) (D32 >> ((Index % 8) << 2)) & V_PAD_OWNERSHIP_MASK;
+
+ return Ownership;
+}
+
+
+/**
+ Program GPIO wake event for direct IRQ GPIO pins at power on.
+ Assume EVOUTEN_0 and EVMAP_0 are not initialized.
+
+ @param[in] Community GPIO community.
+ @param[in] Index GPIO pad index in its community.
+
+**/
+VOID
+ConfigureDirectIrqWakeEvent (
+ IN UINT8 Community,
+ IN UINT16 Index
+ )
+{
+ UINT64 d64 = 0;
+ UINT32 d32;
+
+ //
+ // Both North and NorthWest community GPIO index are linear
+ // But some of the GPIO pins need to be filtered due to not support Direct IRQ
+ //
+ if (Community == NORTH) {
+ if (GetBxtSeries () == BxtP) {
+ if (Index > 61) { // filter the GPIO that doesn't support Direct IRQ
+ DEBUG ((DEBUG_ERROR, "\tThere is configuration error on direct IRQ! index: %d\n", Index));
+ return;
+ }
+ } else {
+ if (Index > 73) { // filter the GPIO that doesn't support Direct IRQ
+ DEBUG ((DEBUG_ERROR, "\tThere is configuration error on direct IRQ! index: %d\n", Index));
+ return;
+ }
+ }
+ } else if (Community == NORTHWEST) {
+ if (GetBxtSeries () == BxtP) {
+ if ((Index < 33) || (Index == 52) || (Index == 60)) { // filter the GPIO that doesn't support Direct IRQ
+ DEBUG ((DEBUG_ERROR, "\tThere is configuration error on direct IRQ! index: %d\n", Index));
+ return;
+ }
+ } else {
+ if ((Index < 21) || (Index == 44) || (Index == 52)) { // filter the GPIO that doesn't support Direct IRQ
+ DEBUG ((DEBUG_ERROR, "\tThere is configuration error on direct IRQ! index: %d\n", Index));
+ return;
+ }
+ }
+ } else { // Direct IRQ wake event is only supported on North and Northwest communities.
+ return;
+ }
+
+ //
+ // program Event Trigger Mapping
+ //
+ d64 = (LShiftU64 ((UINT64) GpioRead (Community, EVMAP_0 + 4), 32)) | GpioRead (Community, EVMAP_0);
+ d64 |= LShiftU64 ((UINT64) Index / EVENT_MUX_SIZE, ((Index % EVENT_MUX_SIZE) << 2));
+ GpioWrite (Community, EVMAP_0, (UINT32) (d64 & 0xFFFFFFFF));
+ GpioWrite (Community, EVMAP_0 + 4, (UINT32) (d64 >> 32));
+
+ //
+ // program Event Trigger Output Enable
+ //
+ d32 = GpioRead (Community, EVOUTEN_0);
+ d32 |= 1 << (Index % WAKE_EVENT_NUM);
+ GpioWrite (Community, EVOUTEN_0, d32);
+
+ return;
+}
+
+
+/**
+ Set GPIO PAD DW 0 and 1 registers for South/West/SouthWest/North/NorthWest GPIO communities.
+
+ @param[in] Gpio_Pin_Num GPIO Pin Number to configure.
+ @param[in] Gpio_Conf_Data Data array of default setting for each GPIO communities.
+
+**/
+VOID
+GpioPadConfigTable (
+ IN UINT32 Gpio_Pin_Num,
+ IN BXT_GPIO_PAD_INIT *Gpio_Conf_Data
+ )
+{
+ UINT32 index;
+ BXT_GPIO_CONFIG mGpioConfigItem = {0};
+
+ for (index = 0; index < Gpio_Pin_Num; index++) {
+ mGpioConfigItem.CommAndOffset = (((UINT32) Gpio_Conf_Data[index].Community) << 16) + Gpio_Conf_Data[index].MMIO_ADDRESS;
+ mGpioConfigItem.padConfg0.padCnf0 = Gpio_Conf_Data[index].padConfg0.padCnf0;
+ mGpioConfigItem.padConfg1.padCnf1 = Gpio_Conf_Data[index].padConfg1.padCnf1;
+ mGpioConfigItem.HostSw = Gpio_Conf_Data[index].HostSw;
+ mGpioConfigItem.WakeEnabled = Gpio_Conf_Data[index].WakeEnabled;
+ GpioPadConfigItem (mGpioConfigItem);
+ }
+}
+
+
+/**
+ Program SMIP GPIO PAD DW 0 and 1 registers for South/West/SouthWest/North/NorthWest GPIO communities.
+
+ @param[in] Gpio_Pin_Num GPIO Pin Number to configure.
+ @param[in] Gpio_Smip_Conf_Data Data array from SMIP setting for each GPIO communities.
+
+**/
+VOID
+GpioSmipPadConfigTable (
+ IN UINT32 Gpio_Pin_Num,
+ IN GPIO_CONFIG_SMIP *Gpio_Smip_Conf_Data
+)
+{
+ UINT32 index = 0;
+ BXT_GPIO_CONFIG mGpioConfigItem = {0};
+ UINT8 Community = 0;
+
+ for (index = 0; index < Gpio_Pin_Num; index++) {
+ Community = (UINT8) Gpio_Smip_Conf_Data[index].Half0.r.Community;
+ //
+ // Skip null entry in SMIP GPIO table
+ //
+ if ((Community != SOUTH) && (Community != WEST) && (Community != NORTHWEST) && \
+ (Community != SOUTHWEST) && (Community != NORTH)) {
+ continue;
+ }
+ mGpioConfigItem.CommAndOffset = (UINT32) Gpio_Smip_Conf_Data[index].Half0.r.Community << 16 | Gpio_Smip_Conf_Data[index].Half0.r.Offset;
+ mGpioConfigItem.padConfg0.padCnf0 = SMIP_Config0_Convert (Gpio_Smip_Conf_Data[index].Half1.r.padConfig0);
+ mGpioConfigItem.padConfg1.padCnf1 = SMIP_Config1_Convert (Gpio_Smip_Conf_Data[index].Half1.r.padConfig1);
+ mGpioConfigItem.HostSw = (UINT8) Gpio_Smip_Conf_Data[index].Half0.r.HostSw;
+ mGpioConfigItem.WakeEnabled = (UINT8) Gpio_Smip_Conf_Data[index].Half0.r.DirectIrqWake;
+ GpioPadConfigItem (mGpioConfigItem);
+ }
+}
+
+
+/**
+ Set GPIO PAD DW 0 and 1 registers for South/West/SouthWest/North/NorthWest GPIO communities.
+
+ @param[in] Gpio_Conf_Data The structure contains GPIO community and pad 0/1 value.
+
+**/
+VOID
+GpioPadConfigItem (
+ IN BXT_GPIO_CONFIG Gpio_Conf_Data
+ )
+{
+ UINT8 community;
+ UINT16 index;
+ UINT32 pad_conf0, pad_conf1;
+ UINT16 mmio_conf0, mmio_conf1;
+ UINT32 D32;
+ GPIO_PAD_OWNERSHIP Ownership;
+
+ //
+ // Calculate the MMIO Address for specific GPIO pin CONF0 register pointed by index.
+ //
+ mmio_conf0 = (UINT16) (Gpio_Conf_Data.CommAndOffset & 0xFFFF) + BXT_GPIO_PAD_CONF0_OFFSET;
+ mmio_conf1 = (UINT16) (Gpio_Conf_Data.CommAndOffset & 0xFFFF) + BXT_GPIO_PAD_CONF1_OFFSET;
+ community = (UINT8) (Gpio_Conf_Data.CommAndOffset >> 16);
+ index = (mmio_conf0 - GPIO_PADBAR) / 8;
+
+ //
+ // check pad ownership before any programing, if it is not owned by host, skip it.
+ //
+ Ownership = GpioPadOwnershipCheck (Gpio_Conf_Data.CommAndOffset);
+ if (Ownership != Host_Gpio_Mode) {
+ DEBUG ((EFI_D_INFO, "GPIO pad is not owned by host! skip it. Ownership: %02X\n", Ownership));
+ return;
+ }
+
+ pad_conf0 = GpioRead (community, mmio_conf0);
+ pad_conf0 = (pad_conf0 & PAD_DW0_MASK) | Gpio_Conf_Data.padConfg0.padCnf0;
+ GpioWrite (community, mmio_conf0, pad_conf0);
+
+ pad_conf1 = GpioRead (community, mmio_conf1);
+ pad_conf1 = (pad_conf1 & PAD_DW1_MASK) | Gpio_Conf_Data.padConfg1.padCnf1;
+ GpioWrite (community, mmio_conf1, pad_conf1);
+
+ //
+ // ACPI/GPIO driver ownership program
+ //
+ if (Gpio_Conf_Data.HostSw == GPIO_D) {
+ D32 = GpioRead (community, HOSTSW_OWNERSHIP_0 + (index / 32) * 4);
+ D32 = D32 | (UINT32)(1 << (index%32));
+ GpioWrite (community, HOSTSW_OWNERSHIP_0 + (index / 32) * 4, D32);
+ } else {
+ D32 = GpioRead (community, HOSTSW_OWNERSHIP_0 + (index / 32) *4 );
+ D32 = D32 & (~(UINT32) (1 << (index%32)));
+ GpioWrite (community, HOSTSW_OWNERSHIP_0 + (index / 32) * 4, D32);
+ }
+
+ //
+ // GPI/GPE/SMI/NMI program
+ //
+ switch (Gpio_Conf_Data.padConfg0.r.GPIRout) {
+ case SCI: // SCI/GPE
+ if (GetBxtSeries () == BxtP) {
+ if (Gpio_Conf_Data.HostSw == ACPI_D) {
+ DEBUG ((EFI_D_INFO, "BXT-P configure GPIO to SCI/GPE. \n"));
+ //
+ // clear GPE status
+ //
+ D32 = GpioRead (community, GPI_GPE_STS_0 + (index / 32) * 4);
+ DEBUG ((EFI_D_INFO, "Original value of 0x%X: 0x%08X\n", GPI_GPE_STS_0 + (index / 32) * 4, D32));
+ D32 = D32 | (UINT32) (1 << (index % 32));
+ GpioWrite (community, GPI_GPE_STS_0 + (index / 32) * 4, D32);
+ //
+ // Set GPE enable
+ //
+ D32 = GpioRead (community, GPI_GPE_EN_0 + (index / 32) * 4);
+ DEBUG ((EFI_D_INFO, "Original value of 0x%X: 0x%08X\n", GPI_GPE_EN_0 + (index / 32) * 4, D32));
+ D32 = D32 | (UINT32) (1 << (index % 32));
+ GpioWrite (community, GPI_GPE_EN_0 + (index / 32) * 4, D32);
+ D32 = GpioRead (community, GPI_GPE_EN_0 + (index / 32) *4 );
+ DEBUG ((EFI_D_INFO, "New value of 0x%X: 0x%08X\n", GPI_GPE_EN_0 + (index / 32) * 4, D32));
+ break;
+ }
+ }
+ case SMI:// SMI
+ if (GetBxtSeries () == BxtP) {
+ if (Gpio_Conf_Data.HostSw == ACPI_D) {
+ DEBUG ((EFI_D_INFO, "BXT-P configure GPIO to SMI. \n"));
+ //
+ // clear SMI status
+ //
+ D32 = GpioRead (community, GPI_SMI_STS_0 + (index / 32) * 4);
+ DEBUG ((EFI_D_INFO, "Original value of 0x%X: 0x%08X\n", GPI_SMI_STS_0 + (index / 32) * 4, D32));
+ D32 = D32 | (UINT32) (1 << (index % 32));
+ GpioWrite (community, GPI_SMI_STS_0 + (index / 32) * 4, D32);
+
+ //
+ // Set SMI enable
+ //
+ D32 = GpioRead (community, GPI_SMI_EN_0 + (index / 32) * 4);
+ DEBUG ((EFI_D_INFO, "Original value of 0x%X: 0x%08X\n", GPI_SMI_EN_0 + (index / 32) * 4, D32));
+ D32 = D32 | (UINT32) (1 << (index % 32));
+ GpioWrite (community, GPI_SMI_EN_0 + (index / 32) * 4, D32);
+ D32 = GpioRead (community, GPI_SMI_EN_0 + (index / 32) * 4);
+ DEBUG ((EFI_D_INFO, "New value of 0x%X: 0x%08X\n", GPI_SMI_EN_0 + (index / 32) * 4, D32));
+ }
+ }
+ break;
+ case IOAPIC: // Direct IRQ
+ DEBUG ((EFI_D_INFO, "BXT-P configure GPIO to direct IRQ. \n"));
+ if (Gpio_Conf_Data.WakeEnabled == Wake_Enabled) {
+ ConfigureDirectIrqWakeEvent (community, index);
+ }
+ break;
+ case NMI: //No BXT pins are capable of NMI operation
+ break;
+ case NONE: // GPI(Shared interrupt) should be enabled by OS GPIO driver
+ break;
+ default:
+ break;
+ }
+}
+
+
+/**
+ This procedure will get GPIO pad input inversion value
+
+ @param[in] GpioPad GPIO pad
+ @param[out] InvertState GPIO inversion state
+ 0: No input inversion, 1: Inverted input
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+GpioGetInputInversion (
+ IN UINT32 GpioPad,
+ OUT UINT32 *InvertState
+ )
+{
+ UINT32 PadConfig0;
+
+ PadConfig0 = GpioPadRead (GpioPad);
+ PadConfig0 &= 0x08FFFFFF;
+ PadConfig0 >>= 23;
+
+ *InvertState = PadConfig0;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This procedure will set GPIO pad input inversion value
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value GPIO inversion value
+
+ @retval EFI_SUCCESS Set GPIO pad input inversion value successfully.
+ @retval Others Status depends on GpioPadWrite operation.
+
+**/
+EFI_STATUS
+GpioSetInputInversion (
+ IN UINT32 GpioPad,
+ IN UINT64 Value
+ )
+{
+ EFI_STATUS Status ;
+ UINT32 PadConfig0;
+
+ PadConfig0 = GpioPadRead (GpioPad);
+ PadConfig0 &= 0x08FFFFFF;
+ PadConfig0 |= (Value >>= 32 );
+
+ Status = GpioPadWrite (GpioPad, PadConfig0);
+
+ return Status;
+}
+
+
+/**
+ This procedure is used to clear SMI STS for a specified Pad
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval Others Status depends on GpioWrite operation.
+
+**/
+EFI_STATUS
+GpioClearGpiSmiSts (
+ IN UINT32 GpioPad
+ )
+{
+ UINT8 Community;
+ UINT16 Offset;
+ UINT32 PadNumber;
+ UINT16 SmiEnableOffset;
+ UINT32 SmiEnable;
+ UINT32 Data32;
+ EFI_STATUS Status ;
+
+ Community = (UINT8) ((GpioPad & 0xFFFF0000) >> 16) ;
+ Offset = GpioPad &0xFFFF;
+
+ PadNumber = (Offset - GPIO_PADBAR) / 8;
+ SmiEnableOffset = GPI_SMI_STS_0 + (UINT16) (PadNumber / 32) * 4;
+ SmiEnable = PadNumber % 32;
+
+ Data32 = GpioRead (Community, SmiEnableOffset);
+ Data32 |= SmiEnable;
+
+ Status = GpioWrite (Community, SmiEnableOffset,Data32);
+
+ return Status;
+}
+
+
+/**
+ This procedure is used by ScSmiDispatcher and will clear
+ all GPI SMI Status bits
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+GpioClearAllGpiSmiSts (
+ VOID
+ )
+{
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINT32 GpioGroupInfoSize;
+ UINT8 Index;
+
+ GpioGroupInfo = NULL;
+ GpioGroupInfoSize = 0;
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoSize);
+ DEBUG ((DEBUG_INFO, "GpioGroupInfoSize = %x\n", GpioGroupInfoSize));
+
+ for (Index = 0; Index < GpioGroupInfoSize; Index++) {
+ DEBUG ((DEBUG_INFO, "Community = %x, SmiStsOffset = %x\n", GpioGroupInfo[Index].Community, GpioGroupInfo[Index].SmiStsOffset));
+ //
+ // Clear all GPI SMI
+ //
+ GpioWrite (GpioGroupInfo[Index].Community, GpioGroupInfo[Index].SmiStsOffset, ~0u);
+ }
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This procedure is used to register GPI SMI dispatch function.
+
+ @param[in] GpioPad GPIO pad
+ @param[out] GpiNum GPI number
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+GpioGetGpiSmiNum (
+ IN UINT32 GpioPad,
+ OUT UINT64 *GpiNum
+ )
+{
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINT32 GpioGroupInfoSize;
+ UINT8 Community;
+ UINT16 Offset;
+ UINT8 Index;
+ UINT32 PadNumber;
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoSize);
+ Community = (UINT8) ((GpioPad & 0xFFFF0000) >> 16) ;
+ Offset = GpioPad &0xFFFF;
+ PadNumber = (Offset - GPIO_PADBAR) / 8;
+ *GpiNum = 0;
+
+ for (Index = 0; Index < GpioGroupInfoSize; Index++) {
+ if (GpioGroupInfo[Index].Community == Community) {
+ break;
+ }
+ *GpiNum += (UINTN) (GpioGroupInfo[Index].PadPerGroup);
+ }
+ *GpiNum += (UINTN) PadNumber;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This procedure is used by PchSmiDispatcher and will return information
+ needed to register GPI SMI. Relation between Index and GpioPad number is:
+ Index = GpioGroup + 24 * GpioPad
+
+ @param[in] Index GPI SMI number
+ @param[out] GpiSmiBitOffset GPI SMI bit position within GpiSmi Registers
+ @param[out] GpiSmiEnRegAddress Address of GPI SMI Enable register
+ @param[out] GpiSmiStsRegAddress Address of GPI SMI status register
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+
+**/
+EFI_STATUS
+GpioGetPadAndSmiRegs (
+ IN UINT32 Index,
+ OUT UINT8 *GpiSmiBitOffset,
+ OUT UINT32 *GpiSmiEnRegAddress,
+ OUT UINT32 *GpiSmiStsRegAddress
+ )
+{
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINT32 GpioGroupInfoLength;
+ UINT32 SmiRegOffset;
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+ if (GpioGroupInfo == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PadNumber = 0;
+ for (GroupIndex = 0; GroupIndex < GpioGroupInfoLength; GroupIndex++) {
+ PadNumber = Index;
+ if (PadNumber < GpioGroupInfo[GroupIndex].PadPerGroup) {
+ //
+ // Found group and pad number
+ //
+ break;
+ }
+ Index = Index - GpioGroupInfo[GroupIndex].PadPerGroup;
+ }
+
+ //
+ // Check if legal pad number
+ //
+ if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup){
+ return EFI_INVALID_PARAMETER;
+ }
+
+
+ *GpiSmiBitOffset = (UINT8) PadNumber;
+
+ SmiRegOffset = GpioGroupInfo[GroupIndex].SmiEnOffset;
+ *GpiSmiEnRegAddress = SC_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, SmiRegOffset);
+
+ SmiRegOffset = GpioGroupInfo[GroupIndex].SmiStsOffset;
+ *GpiSmiStsRegAddress = SC_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, SmiRegOffset);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This procedure will write GPIO Lock/LockTx register using SBI.
+
+ @param[in] RegType GPIO register (Lock or LockTx)
+ @param[in] Group GPIO group number
+ @param[in] PadNumber Pad number of Group.
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_UNSUPPORTED Feature is not supported for this group or pad
+
+**/
+STATIC
+EFI_STATUS
+GpioWriteLockReg (
+ IN GPIO_REG RegType,
+ IN GPIO_GROUP Group,
+ IN UINT32 PadNumber
+ )
+{
+ UINT8 Response;
+ EFI_STATUS Status;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINT32 GpioGroupInfoLength;
+ UINT32 RegOffset;
+ UINT32 OldPadCfgLockRegVal;
+ UINT32 NewPadCfgLockRegVal;
+ UINT32 GroupIndex;
+
+ RegOffset = NO_REGISTER_FOR_PROPERTY;
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+ if (GpioGroupInfo == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+ for (GroupIndex = 0; GroupIndex < GpioGroupInfoLength; GroupIndex++) {
+ if (Group == GpioGroupInfo[GroupIndex].Community) {
+ if (PadNumber < GpioGroupInfo[GroupIndex].PadPerGroup) {
+ //
+ // Found group and pad number
+ //
+ break;
+ }
+ PadNumber = PadNumber - GpioGroupInfo[GroupIndex].PadPerGroup;
+ }
+ }
+
+ switch (RegType) {
+ case GpioPadConfigLockRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].PadCfgLockOffset;
+ break;
+ case GpioPadLockOutputRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].PadCfgLockTxOffset;
+ break;
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+
+ //
+ // Check if selected register exists
+ //
+ if (RegOffset == NO_REGISTER_FOR_PROPERTY) {
+ return EFI_UNSUPPORTED;
+ }
+
+ OldPadCfgLockRegVal = MmioRead32 (SC_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, RegOffset));
+ NewPadCfgLockRegVal = OldPadCfgLockRegVal | (1 << PadNumber);
+
+ Status = PchSbiExecution (
+ GpioGroupInfo[GroupIndex].Community,
+ RegOffset,
+ GpioLockUnlock,
+ FALSE,
+ &NewPadCfgLockRegVal,
+ &Response
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+
+/**
+ This procedure will set PadCfgLock for selected pad
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+
+**/
+EFI_STATUS
+GpioLockPadCfg (
+ IN UINT32 GpioPad
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Community;
+ UINT16 Offset;
+ UINT32 PadNumber;
+
+ Community = (UINT8) GPIO_GET_GROUP_FROM_PAD (GpioPad);
+ Offset = GPIO_GET_PAD_OFFSET (GpioPad);
+ PadNumber = GPIO_GET_PAD_NUMBER (Offset);
+
+ Status = GpioWriteLockReg (
+ GpioPadConfigLockRegister,
+ Community,
+ PadNumber
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+
+/**
+ This procedure will set PadCfgLockTx for selected pad
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+
+**/
+EFI_STATUS
+GpioLockPadCfgTx (
+ IN UINT32 GpioPad
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Community;
+ UINT16 Offset;
+ UINT32 PadNumber;
+
+ Community = (UINT8) GPIO_GET_GROUP_FROM_PAD (GpioPad);
+ Offset = GPIO_GET_PAD_OFFSET (GpioPad);
+ PadNumber = GPIO_GET_PAD_NUMBER (Offset);
+
+ Status = GpioWriteLockReg (
+ GpioPadLockOutputRegister,
+ Community,
+ PadNumber
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+
+/**
+ This procedure will set GPIO output level
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Output value
+ 0: OutputLow, 1: OutputHigh
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval Others Status depends on GpioPadWrite operation.
+
+**/
+EFI_STATUS
+GpioSetOutputValue (
+ IN UINT32 GpioPad,
+ IN UINT32 Value
+ )
+{
+ EFI_STATUS Status;
+ UINT32 PadConfig0;
+
+ PadConfig0 = GpioPadRead (GpioPad);
+ PadConfig0 = (PadConfig0 & 0xFFFFFFFE) | Value;
+
+ Status = GpioPadWrite (GpioPad, PadConfig0);
+
+ return Status;
+}
+
+
+/**
+ This procedure will get GPIO input level
+
+ @param[in] GpioPad GPIO pad
+ @param[out] InputVal GPIO Input value
+ 0: InputLow, 1: InpuHigh
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval Others Status depends on GpioPadRead operation.
+
+**/
+EFI_STATUS
+GpioGetInputValue (
+ IN UINT32 GpioPad,
+ OUT UINT32 *InputVal
+ )
+{
+ EFI_STATUS Status;
+ UINT32 PadConfig0;
+
+ Status = EFI_SUCCESS;
+ PadConfig0 = GpioPadRead (GpioPad);
+ *InputVal = (PadConfig0 & 0x02) >> 1;
+
+ return Status;
+}
+
+
+/**
+ This procedure will get group index (0 based) from group
+
+ @param[in] GpioGroup GPIO Group
+
+ @retval Value Group Index
+
+**/
+UINT32
+GpioGetGroupIndexFromGroup (
+ IN GPIO_GROUP GpioGroup
+ )
+{
+ return (UINT32) GPIO_GET_GROUP_INDEX (GpioGroup);
+}
+
+
+/**
+ This procedure will get lowest group
+
+ @retval GPIO_GROUP Lowest Group
+
+**/
+GPIO_GROUP
+GpioGetLowestGroup (
+ VOID
+ )
+{
+ if (GetBxtSeries () == Bxt) {
+ return (UINT32) GPIO_BXTM_GROUP_0;
+ } else {
+ return (UINT32) GPIO_BXTP_GROUP_0;
+ }
+}
+
+
+/**
+ This procedure will get highest group
+
+ @retval GPIO_GROUP Highest Group
+**/
+GPIO_GROUP
+GpioGetHighestGroup (
+ VOID
+ )
+{
+ if (GetBxtSeries () == Bxt) {
+ return (UINT32) GPIO_BXTM_GROUP_9;
+ } else {
+ return (UINT32) GPIO_BXTP_GROUP_8;
+ }
+}
+
+
+/**
+ This procedure will set Group to GPE mapping.
+
+ @param[in] GroupToGpeDw0 GPIO group to be mapped to GPE_DW0
+ @param[in] GroupToGpeDw1 GPIO group to be mapped to GPE_DW1
+ @param[in] GroupToGpeDw2 GPIO group to be mapped to GPE_DW2
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number.
+
+**/
+EFI_STATUS
+GpioSetGroupToGpeDwX (
+ IN GPIO_GROUP GroupToGpeDw0,
+ IN GPIO_GROUP GroupToGpeDw1,
+ IN GPIO_GROUP GroupToGpeDw2
+ )
+{
+ UINT32 Data32Or;
+ UINT32 Data32And;
+ GPIO_GROUP GpioGroupLowest;
+ GPIO_GROUP GpioGroupHighest;
+
+ GpioGroupLowest = GpioGetLowestGroup ();
+ GpioGroupHighest = GpioGetHighestGroup ();
+
+ //
+ // Check if group argument exceeds GPIO group range
+ //
+ if (((UINT32) GroupToGpeDw0 < GpioGroupLowest) || ((UINT32) GroupToGpeDw0 > GpioGroupHighest) ||
+ ((UINT32) GroupToGpeDw1 < GpioGroupLowest) || ((UINT32) GroupToGpeDw1 > GpioGroupHighest) ||
+ ((UINT32) GroupToGpeDw2 < GpioGroupLowest) || ((UINT32) GroupToGpeDw2 > GpioGroupHighest)) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group argument exceeds GPIO group range\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check if each group number is unique
+ //
+ if ((GroupToGpeDw0 == GroupToGpeDw1) ||
+ (GroupToGpeDw0 == GroupToGpeDw2) ||
+ (GroupToGpeDw1 == GroupToGpeDw2)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Values in GPE0_DWx registers are 0 based
+ //
+ GroupToGpeDw0 = GpioGetGroupIndexFromGroup (GroupToGpeDw0);
+ GroupToGpeDw1 = GpioGetGroupIndexFromGroup (GroupToGpeDw1);
+ GroupToGpeDw2 = GpioGetGroupIndexFromGroup (GroupToGpeDw2);
+
+ //
+ // Program GPIO_MISCCFG
+ //
+ Data32And = (UINT32) ~(B_GPIO_MISCCFG_GPE0_DW2 | B_GPIO_MISCCFG_GPE0_DW1 | B_GPIO_MISCCFG_GPE0_DW0);
+ Data32Or = (UINT32) ((GroupToGpeDw2 << N_GPIO_MISCCFG_GPE0_DW2) |
+ (GroupToGpeDw1 << N_GPIO_MISCCFG_GPE0_DW1) |
+ (GroupToGpeDw0 << N_GPIO_MISCCFG_GPE0_DW0));
+
+ if (GetBxtSeries () == Bxt) {
+ //
+ // Program MISCCFG register for Community SOUTH
+ //
+ GpioWrite (
+ SOUTH,
+ R_GPIO_MISCCFG,
+ ((GpioRead(SOUTH ,R_GPIO_MISCCFG) & Data32And) | Data32Or)
+ );
+ }
+
+ //
+ // Program MISCCFG register for Community SOUTHWEST
+ //
+ GpioWrite (
+ SOUTHWEST,
+ R_GPIO_MISCCFG,
+ ((GpioRead (SOUTHWEST ,R_GPIO_MISCCFG) & Data32And) | Data32Or)
+ );
+
+ //
+ // Program MISCCFG register for Community WEST
+ //
+ GpioWrite (
+ WEST,
+ R_GPIO_MISCCFG,
+ ((GpioRead (WEST ,R_GPIO_MISCCFG) & Data32And) | Data32Or)
+ );
+
+ //
+ // Program MISCCFG register for Community NORTHWEST
+ //
+ GpioWrite (
+ NORTHWEST,
+ R_GPIO_MISCCFG,
+ ((GpioRead (NORTHWEST ,R_GPIO_MISCCFG) & Data32And) | Data32Or)
+ );
+
+ //
+ // Program MISCCFG register for Community NORTH
+ //
+ GpioWrite (
+ NORTH,
+ R_GPIO_MISCCFG,
+ ((GpioRead (NORTH ,R_GPIO_MISCCFG) & Data32And) | Data32Or)
+ );
+
+ return EFI_SUCCESS;
+}
+
+
+VOID
+PrintCommunity (
+ IN UINT8 community
+ )
+{
+ DEBUG ((EFI_D_INFO, "\n"));
+ switch (community) {
+ case SOUTH:
+ DEBUG ((EFI_D_INFO, "SOUTH"));
+ break;
+ case WEST:
+ DEBUG ((EFI_D_INFO, "WEST"));
+ break;
+ case NORTHWEST:
+ DEBUG ((EFI_D_INFO, "NORTHWEST"));
+ break;
+ case SOUTHWEST:
+ DEBUG ((EFI_D_INFO, "SOUTHWEST"));
+ break;
+ case NORTH:
+ DEBUG ((EFI_D_INFO, "NORTH"));
+ break;
+ default:
+ DEBUG ((EFI_D_INFO, "Unknown"));
+ break;
+ }
+ DEBUG ((EFI_D_INFO, "\n"));
+}
+
+
+VOID
+PrintGpioPadTitle (
+ VOID
+ )
+{
+ DEBUG ((EFI_D_INFO, "\nPadName "));
+ DEBUG ((EFI_D_INFO, "Mode# GPIO_CFG GPO_State IntType PullUp/Down Inverted GPI_ROUT IOSState IOSTerm "));
+ DEBUG ((EFI_D_INFO, "MMIO_CONF0 PAD_CONF0 MMIO_CONF1 PAD_CONF1\n"));
+ DEBUG ((EFI_D_INFO, "----------------------------------------------------------------------------------------------"));
+ DEBUG ((EFI_D_INFO, "-----------------------------------------------------------------------------------------------\n"));
+}
+
+
+VOID
+DumpGpioCommunityRegisters (
+ IN UINT8 community
+ )
+{
+ UINT16 index;
+ DEBUG ((EFI_D_INFO, "\nDump community registers of: "));
+
+ PrintCommunity (community);
+
+ for (index = 0; index < GPIO_PADBAR; index = index +4){
+ DEBUG ((EFI_D_INFO, "Offset: 0x%03X Value: 0x%08X\t", index, GpioRead(community, index)));
+ if (((index+4) % 16) == 0) {
+ DEBUG ((EFI_D_INFO, "\n"));
+ }
+ }
+}
+
+
+VOID
+DumpGpioPadRegisters (
+ IN UINT32 CommAndOffset,
+ IN UINT16 *PadName
+ )
+{
+ BXT_CONF_PAD0 pad_conf0;
+ BXT_CONF_PAD1 pad_conf1;
+ GPIO_PAD_OWNERSHIP Ownership;
+
+ Ownership = GpioPadOwnershipCheck (CommAndOffset);
+ if (Ownership != Host_Gpio_Mode) {
+ DEBUG ((EFI_D_INFO, " %27s GPIO pad is not owned by host! Its ownership: %02X\n", PadName, Ownership));
+ return;
+ }
+
+ pad_conf0.padCnf0 = GpioPadRead(CommAndOffset + BXT_GPIO_PAD_CONF0_OFFSET);
+ pad_conf1.padCnf1 = GpioPadRead(CommAndOffset + BXT_GPIO_PAD_CONF1_OFFSET);
+
+ DEBUG ((EFI_D_INFO, " %27s >>", PadName));
+ DEBUG ((EFI_D_INFO, " M%1d %11s %d %5s %9s %12s %6s %10s%8s",
+ pad_conf0.r.PMode,
+ (pad_conf0.r.GPIORxTxDis==0)?L"RxEn,TxEn":((pad_conf0.r.GPIORxTxDis==1)?L"RxEn,TxDis":((pad_conf0.r.GPIORxTxDis==2)?L"RxDis,TxEn":L"RxDis,TxDis")),
+ pad_conf0.r.GPIOTxState,
+ (pad_conf0.r.RxEvCfg==0)?L"Level":((pad_conf0.r.RxEvCfg==1)?L"Edge":((pad_conf0.r.RxEvCfg==2)?L"Dis":L"Both")),
+ (pad_conf1.r.Term==0||pad_conf1.r.Term==8)?L"none":((pad_conf1.r.Term==2)?L"5k wpd":((pad_conf1.r.Term==4)?L"20k wpd":((pad_conf1.r.Term==9)?L"1k wpu":((pad_conf1.r.Term==11)?L"2k wpu":((pad_conf1.r.Term==10)?L"5k wpu":((pad_conf1.r.Term==12)?L"20k wpu":((pad_conf1.r.Term==13)?L"1k&2k wpu":((pad_conf1.r.Term==15)?L"Native":L"NA")))))))),
+ (pad_conf0.r.RXINV==1)?L"Inverted":L"No_Inverted",
+ (pad_conf0.r.GPIRout==0)?L"NONE":((pad_conf0.r.GPIRout==1)?L"NMI":((pad_conf0.r.GPIRout==2)?L"SMI":((pad_conf0.r.GPIRout==4)?L"SCI":((pad_conf0.r.GPIRout==8)?L"IOAPIC":L"NA")))),
+ (pad_conf1.r.IOSState == 0)?L"Last_Value":((pad_conf1.r.IOSState == 1)?L"D0RxDRx0I":((pad_conf1.r.IOSState == 2)?L"D0RxDRx1I":((pad_conf1.r.IOSState == 3)?L"D1RxDRx0I":((pad_conf1.r.IOSState == 4)?L"D1RxDRx1I":((pad_conf1.r.IOSState == 5)?L"D0RxE":((pad_conf1.r.IOSState == 6)?L"D1RxE":((pad_conf1.r.IOSState == 7)?L"HizRx0I":((pad_conf1.r.IOSState == 8)?L"HizRx1I":((pad_conf1.r.IOSState == 9)?L"TxDRxE":((pad_conf1.r.IOSState == 15)?L"IOS_Masked":L"NA")))))))))),
+ (pad_conf1.r.IOSTerm == 0)?L"SAME":((pad_conf1.r.IOSTerm == 1)?L"DisPuPd":((pad_conf1.r.IOSTerm == 2)?L"EnPd":L"EnPu"))
+ ));
+
+ DEBUG ((EFI_D_INFO, " 0x%08X 0x%08X 0x%08X 0x%08X \n", CommAndOffset + BXT_GPIO_PAD_CONF0_OFFSET, pad_conf0.padCnf0, CommAndOffset + BXT_GPIO_PAD_CONF1_OFFSET, pad_conf1.padCnf1));
+}
+
+VOID
+DumpGpioPadTable (
+ IN UINT32 Gpio_Pin_Size,
+ IN BXT_GPIO_PAD_INIT* Gpio_Conf_Data
+ )
+{
+ UINT32 CommAndOffset;
+ UINT16 index;
+
+ PrintCommunity (Gpio_Conf_Data[0].Community);
+ PrintGpioPadTitle ();
+ for (index = 0; index < Gpio_Pin_Size; index++) {
+ CommAndOffset = (((UINT32) Gpio_Conf_Data[index].Community)<<16) + Gpio_Conf_Data[index].MMIO_ADDRESS;
+ DumpGpioPadRegisters (CommAndOffset, Gpio_Conf_Data[index].pad_name);
+ }
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/GpioLib/GpioLib.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/GpioLib/GpioLib.inf
new file mode 100644
index 0000000000..b8718f0def
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/GpioLib/GpioLib.inf
@@ -0,0 +1,43 @@
+## @file
+# GpioLib.
+#
+# Copyright (c) 1999 - 2016, 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 = GpioLib
+ FILE_GUID = 23b5006a-5987-4821-9600-4d5aef2db637
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = GpioLib
+ PI_SPECIFICATION_VERSION = 0x0001000A
+
+[Sources]
+ GpioLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ BroxtonSiPkg/BroxtonSiPkg.dec
+ BroxtonPlatformPkg/PlatformPkg.dec
+
+[LibraryClasses]
+ DebugLib
+ HobLib
+ IoLib
+ SteppingLib
+ SideBandLib
+ SteppingLib
+ ScPlatformLib
+
+[Guids]
+ gEfiPlatformInfoGuid
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiDxeSmmMmPciLib/PeiDxeSmmMmPciLib.c b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiDxeSmmMmPciLib/PeiDxeSmmMmPciLib.c
new file mode 100644
index 0000000000..7cb0556080
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiDxeSmmMmPciLib/PeiDxeSmmMmPciLib.c
@@ -0,0 +1,48 @@
+/** @file
+ This file contains routines that get PCI Express Address.
+
+ Copyright (c) 2014 - 2016, 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 <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+
+/**
+ This procedure will get PCIE address
+
+ @param[in] Bus Pci Bus Number
+ @param[in] Device Pci Device Number
+ @param[in] Function Pci Function Number
+
+ @retval PCIE address
+
+**/
+UINTN
+MmPciBase (
+ IN UINT32 Bus,
+ IN UINT32 Device,
+ IN UINT32 Function
+ )
+{
+ UINTN PcieAddress;
+
+ ASSERT ((Bus <= 0xFF) && (Device <= 0x1F) && (Function <= 0x7));
+ //
+ // Use local variable PcieAddress here. This library is for PEI\DXE\SMM
+ // When PEI, the module variable can't be updated. Need a local variable to get the pcie base address + offset.
+ //
+ PcieAddress = (UINTN) PcdGet64 (PcdPciExpressBaseAddress) + (UINTN) ((Bus << 20) + (Device << 15) + (Function << 12));
+
+ return PcieAddress;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiDxeSmmMmPciLib/PeiDxeSmmMmPciLib.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiDxeSmmMmPciLib/PeiDxeSmmMmPciLib.inf
new file mode 100644
index 0000000000..27aae6edfe
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiDxeSmmMmPciLib/PeiDxeSmmMmPciLib.inf
@@ -0,0 +1,41 @@
+## @file
+# PeiDxeSmmMmPciLib.
+#
+# Copyright (c) 2014 - 2016, 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 = 0x00010017
+ BASE_NAME = PeiDxeSmmMmPciLib
+ FILE_GUID = 504BEE78-2B97-44db-91E8-18C45AC03609
+ VERSION_STRING = 1.0
+ MODULE_TYPE = BASE
+ LIBRARY_CLASS = MmPciLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ PcdLib
+ DebugLib
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress ## SOMETIMES_CONSUMES
+
+[Sources]
+ PeiDxeSmmMmPciLib.c
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiPerformanceLibFpdt/PeiPerformanceLibFpdt.c b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiPerformanceLibFpdt/PeiPerformanceLibFpdt.c
new file mode 100644
index 0000000000..306c4d74d4
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiPerformanceLibFpdt/PeiPerformanceLibFpdt.c
@@ -0,0 +1,427 @@
+/** @file
+ Performance library instance used in PEI phase.
+
+ This file implements Performance Library class in MdePkg. It converts performance data
+ to PEI GUID event, and creates performance logging GUIDed HOB on the first performance
+ logging and then logs the performance data to the GUIDed HOB. Due to the limitation
+ of temporary RAM, the maximum number of performance logging entry is specified by PcdMaxPeiPerformanceLogEntries.
+
+ Copyright (c) 2012 - 2016, 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 <PiPei.h>
+#include <PeiFirmwarePerformance.h>
+#include <Library/PerformanceLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/BaseLib.h>
+#include <Library/TimerLib.h>
+#include <Library/PcdLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/LocalApicLib.h>
+#include <ExtendedFirmwarePerformanceData.h>
+
+
+/**
+ Convert PEI performance log to FPDT GUID boot record.
+
+ @param[in] IsStart TRUE if the performance log is start log.
+ @param[in] Handle Pointer to environment specific context used
+ to identify the component being measured.
+ @param[in] Token Pointer to a Null-terminated ASCII string
+ that identifies the component being measured.
+ @param[in] Module Pointer to a Null-terminated ASCII string
+ that identifies the module being measured.
+ @param[in] Ticker 64-bit time stamp.
+ @param[in] Identifier 32-bit identifier. If the value is 0, the created record
+ is same as the one created by StartGauge of PERFORMANCE_PROTOCOL.
+
+ @retval RETURN_SUCCESS Add FPDT boot record.
+ @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
+ @retval RETURN_UNSUPPORTED No matched FPDT record.
+
+**/
+RETURN_STATUS
+InsertPeiFpdtMeasurement (
+ IN BOOLEAN IsStart,
+ IN CONST VOID *Handle, OPTIONAL
+ IN CONST CHAR8 *Token, OPTIONAL
+ IN CONST CHAR8 *Module, OPTIONAL
+ IN UINT64 Ticker,
+ IN UINT32 Identifier
+ )
+{
+ EFI_HOB_GUID_TYPE *GuidHob;
+ UINTN PeiPerformanceSize;
+ PEI_FIRMWARE_PERFORMANCE_HOB *PeiFirmwarePerformance;
+ PEI_GUID_EVENT_RECORD *PeiGuidEvent;
+ UINT16 ProgressId;
+
+ //
+ // Create GUID HOB Data.
+ //
+ GuidHob = GetFirstGuidHob (&gPeiFirmwarePerformanceGuid);
+ if (GuidHob != NULL) {
+ //
+ // PEI Performance HOB was found, then return the existing one.
+ //
+ PeiFirmwarePerformance = GET_GUID_HOB_DATA (GuidHob);
+ } else {
+ //
+ // PEI Performance HOB was not found, then build one.
+ //
+ PeiPerformanceSize = sizeof (PEI_FIRMWARE_PERFORMANCE_HOB) +
+ sizeof (PEI_GUID_EVENT_RECORD) * (PcdGet8 (PcdMaxPeiPerformanceLogEntries) - 1);
+ PeiFirmwarePerformance = BuildGuidHob (&gPeiFirmwarePerformanceGuid, PeiPerformanceSize);
+ ASSERT (PeiFirmwarePerformance != NULL);
+ ZeroMem (PeiFirmwarePerformance, PeiPerformanceSize);
+ }
+
+ //
+ // Check whether GUID Data is enough to store new PEI GUID Event Perf Data.
+ //
+ if (PeiFirmwarePerformance->NumberOfEntries >= PcdGet8 (PcdMaxPeiPerformanceLogEntries)) {
+ return RETURN_OUT_OF_RESOURCES;
+ }
+ PeiGuidEvent = &PeiFirmwarePerformance->GuidEventRecord[PeiFirmwarePerformance->NumberOfEntries];
+
+ //
+ // Covert Performance token to ProgressId.
+ //
+ if (Identifier != 0) {
+ ProgressId = (UINT16) Identifier;
+ } else if (Token == NULL) {
+ return RETURN_UNSUPPORTED;
+ } else if (AsciiStrCmp (Token, PEIM_TOK) == 0) {
+ if (IsStart) {
+ ProgressId = MODULE_START_ID;
+ } else {
+ ProgressId = MODULE_END_ID;
+ }
+ } else if (AsciiStrCmp (Token, PREMEM_TOK) == 0) {
+ if (IsStart) {
+ ProgressId = PREMEM_START_ID;
+ } else {
+ ProgressId = PREMEM_END_ID;
+ }
+ } else if (AsciiStrCmp (Token, POSTMEM_TOK) == 0) {
+ if (IsStart) {
+ ProgressId = POSTMEM_START_ID;
+ } else {
+ ProgressId = POSTMEM_END_ID;
+ }
+ } else if (AsciiStrCmp (Token, DISMEM_TOK) == 0) {
+ if (IsStart) {
+ ProgressId = DISMEM_START_ID;
+ } else {
+ ProgressId = DISMEM_END_ID;
+ }
+ } else if (AsciiStrCmp (Token, SCRIPT_EXEC_TOK) == 0) {
+ if (IsStart) {
+ ProgressId = SCRIPT_EXEC_START_ID;
+ } else {
+ ProgressId = SCRIPT_EXEC_END_ID;
+ }
+ } else {
+ return RETURN_UNSUPPORTED;
+ }
+
+ //
+ // Fill PEI GUID Event Data.
+ //
+ if (Handle != NULL) {
+ CopyGuid (&PeiGuidEvent->Guid, Handle);
+ } else {
+ CopyGuid (&PeiGuidEvent->Guid, &gEfiCallerIdGuid);
+ }
+ PeiGuidEvent->ProgressID = ProgressId;
+ PeiGuidEvent->ApicID = GetApicId ();
+ //
+ // Get ticker value.
+ //
+ if (Ticker == 0) {
+ Ticker = GetPerformanceCounter ();
+ }
+ PeiGuidEvent->Timestamp = GetTimeInNanoSecond (Ticker);
+ PeiFirmwarePerformance->NumberOfEntries ++;
+
+ return RETURN_SUCCESS;
+}
+
+/**
+ Creates a record for the beginning of a performance measurement.
+
+ Creates a record that contains the Handle, Token, Module and Identifier.
+ If TimeStamp is not zero, then TimeStamp is added to the record as the start time.
+ If TimeStamp is zero, then this function reads the current time stamp
+ and adds that time stamp value to the record as the start time.
+
+ @param[in] Handle Pointer to environment specific context used
+ to identify the component being measured.
+ @param[in] Token Pointer to a Null-terminated ASCII string
+ that identifies the component being measured.
+ @param[in] Module Pointer to a Null-terminated ASCII string
+ that identifies the module being measured.
+ @param[in] TimeStamp 64-bit time stamp.
+ @param[in] Identifier 32-bit identifier. If the value is 0, the created record
+ is same as the one created by StartPerformanceMeasurement.
+
+ @retval RETURN_SUCCESS The start of the measurement was recorded.
+ @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
+
+**/
+RETURN_STATUS
+EFIAPI
+StartPerformanceMeasurementEx (
+ IN CONST VOID *Handle, OPTIONAL
+ IN CONST CHAR8 *Token, OPTIONAL
+ IN CONST CHAR8 *Module, OPTIONAL
+ IN UINT64 TimeStamp,
+ IN UINT32 Identifier
+ )
+{
+ return InsertPeiFpdtMeasurement (TRUE, Handle, Token, Module, TimeStamp, Identifier);
+}
+
+/**
+ Fills in the end time of a performance measurement.
+
+ Looks up the record that matches Handle, Token, Module and Identifier.
+ If the record can not be found then return RETURN_NOT_FOUND.
+ If the record is found and TimeStamp is not zero,
+ then TimeStamp is added to the record as the end time.
+ If the record is found and TimeStamp is zero, then this function reads
+ the current time stamp and adds that time stamp value to the record as the end time.
+
+ @param[in] Handle Pointer to environment specific context used
+ to identify the component being measured.
+ @param[in] Token Pointer to a Null-terminated ASCII string
+ that identifies the component being measured.
+ @param[in] Module Pointer to a Null-terminated ASCII string
+ that identifies the module being measured.
+ @param[in] TimeStamp 64-bit time stamp.
+ @param[in] Identifier 32-bit identifier. If the value is 0, the found record
+ is same as the one found by EndPerformanceMeasurement.
+
+ @retval RETURN_SUCCESS The end of the measurement was recorded.
+ @retval RETURN_NOT_FOUND The specified measurement record could not be found.
+
+**/
+RETURN_STATUS
+EFIAPI
+EndPerformanceMeasurementEx (
+ IN CONST VOID *Handle, OPTIONAL
+ IN CONST CHAR8 *Token, OPTIONAL
+ IN CONST CHAR8 *Module, OPTIONAL
+ IN UINT64 TimeStamp,
+ IN UINT32 Identifier
+ )
+{
+ return InsertPeiFpdtMeasurement (FALSE, Handle, Token, Module, TimeStamp, Identifier);
+}
+
+/**
+ Attempts to retrieve a performance measurement log entry from the performance measurement log.
+ It can also retrieve the log created by StartPerformanceMeasurement and EndPerformanceMeasurement,
+ and then assign the Identifier with 0.
+
+ Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is
+ zero on entry, then an attempt is made to retrieve the first entry from the performance log,
+ and the key for the second entry in the log is returned. If the performance log is empty,
+ then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance
+ log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
+ returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is
+ retrieved and an implementation specific non-zero key value that specifies the end of the performance
+ log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry
+ is retrieved and zero is returned. In the cases where a performance log entry can be returned,
+ the log entry is returned in Handle, Token, Module, StartTimeStamp, EndTimeStamp and Identifier.
+ If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
+ If Handle is NULL, then ASSERT().
+ If Token is NULL, then ASSERT().
+ If Module is NULL, then ASSERT().
+ If StartTimeStamp is NULL, then ASSERT().
+ If EndTimeStamp is NULL, then ASSERT().
+ If Identifier is NULL, then ASSERT().
+
+ @param[in] LogEntryKey On entry, the key of the performance measurement log entry to retrieve.
+ 0, then the first performance measurement log entry is retrieved.
+ On exit, the key of the next performance of entry entry.
+ @param[out] Handle Pointer to environment specific context used to identify the component
+ being measured.
+ @param[out] Token Pointer to a Null-terminated ASCII string that identifies the component
+ being measured.
+ @param[out] Module Pointer to a Null-terminated ASCII string that identifies the module
+ being measured.
+ @param[out] StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
+ was started.
+ @param[out] EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
+ was ended.
+ @param[out] Identifier Pointer to the 32-bit identifier that was recorded.
+
+ @return The key for the next performance log entry (in general case).
+
+**/
+UINTN
+EFIAPI
+GetPerformanceMeasurementEx (
+ IN UINTN LogEntryKey,
+ OUT CONST VOID **Handle,
+ OUT CONST CHAR8 **Token,
+ OUT CONST CHAR8 **Module,
+ OUT UINT64 *StartTimeStamp,
+ OUT UINT64 *EndTimeStamp,
+ OUT UINT32 *Identifier
+ )
+{
+ return 0;
+}
+
+/**
+ Creates a record for the beginning of a performance measurement.
+
+ Creates a record that contains the Handle, Token, and Module.
+ If TimeStamp is not zero, then TimeStamp is added to the record as the start time.
+ If TimeStamp is zero, then this function reads the current time stamp
+ and adds that time stamp value to the record as the start time.
+
+ @param[in] Handle Pointer to environment specific context used
+ to identify the component being measured.
+ @param[in] Token Pointer to a Null-terminated ASCII string
+ that identifies the component being measured.
+ @param[in] Module Pointer to a Null-terminated ASCII string
+ that identifies the module being measured.
+ @param[in] TimeStamp 64-bit time stamp.
+
+ @retval RETURN_SUCCESS The start of the measurement was recorded.
+ @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
+
+**/
+RETURN_STATUS
+EFIAPI
+StartPerformanceMeasurement (
+ IN CONST VOID *Handle, OPTIONAL
+ IN CONST CHAR8 *Token, OPTIONAL
+ IN CONST CHAR8 *Module, OPTIONAL
+ IN UINT64 TimeStamp
+ )
+{
+ return InsertPeiFpdtMeasurement (TRUE, Handle, Token, Module, TimeStamp, 0);
+}
+
+/**
+ Fills in the end time of a performance measurement.
+
+ Looks up the record that matches Handle, Token, and Module.
+ If the record can not be found then return RETURN_NOT_FOUND.
+ If the record is found and TimeStamp is not zero,
+ then TimeStamp is added to the record as the end time.
+ If the record is found and TimeStamp is zero, then this function reads
+ the current time stamp and adds that time stamp value to the record as the end time.
+
+ @param[in] Handle Pointer to environment specific context used
+ to identify the component being measured.
+ @param[in] Token Pointer to a Null-terminated ASCII string
+ that identifies the component being measured.
+ @param[in] Module Pointer to a Null-terminated ASCII string
+ that identifies the module being measured.
+ @param[in] TimeStamp 64-bit time stamp.
+
+ @retval RETURN_SUCCESS The end of the measurement was recorded.
+ @retval RETURN_NOT_FOUND The specified measurement record could not be found.
+
+**/
+RETURN_STATUS
+EFIAPI
+EndPerformanceMeasurement (
+ IN CONST VOID *Handle, OPTIONAL
+ IN CONST CHAR8 *Token, OPTIONAL
+ IN CONST CHAR8 *Module, OPTIONAL
+ IN UINT64 TimeStamp
+ )
+{
+ return InsertPeiFpdtMeasurement (FALSE, Handle, Token, Module, TimeStamp, 0);
+}
+
+/**
+ Attempts to retrieve a performance measurement log entry from the performance measurement log.
+ It can also retrieve the log created by StartPerformanceMeasurementEx and EndPerformanceMeasurementEx,
+ and then eliminate the Identifier.
+
+ Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is
+ zero on entry, then an attempt is made to retrieve the first entry from the performance log,
+ and the key for the second entry in the log is returned. If the performance log is empty,
+ then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance
+ log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
+ returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is
+ retrieved and an implementation specific non-zero key value that specifies the end of the performance
+ log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry
+ is retrieved and zero is returned. In the cases where a performance log entry can be returned,
+ the log entry is returned in Handle, Token, Module, StartTimeStamp, and EndTimeStamp.
+ If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
+ If Handle is NULL, then ASSERT().
+ If Token is NULL, then ASSERT().
+ If Module is NULL, then ASSERT().
+ If StartTimeStamp is NULL, then ASSERT().
+ If EndTimeStamp is NULL, then ASSERT().
+
+ @param[in] LogEntryKey On entry, the key of the performance measurement log entry to retrieve.
+ 0, then the first performance measurement log entry is retrieved.
+ On exit, the key of the next performance of entry entry.
+ @param[out] Handle Pointer to environment specific context used to identify the component
+ being measured.
+ @param[out] Token Pointer to a Null-terminated ASCII string that identifies the component
+ being measured.
+ @param[out] Module Pointer to a Null-terminated ASCII string that identifies the module
+ being measured.
+ @param[out] StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
+ was started.
+ @param[out] EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
+ was ended.
+
+ @return The key for the next performance log entry (in general case).
+
+**/
+UINTN
+EFIAPI
+GetPerformanceMeasurement (
+ IN UINTN LogEntryKey,
+ OUT CONST VOID **Handle,
+ OUT CONST CHAR8 **Token,
+ OUT CONST CHAR8 **Module,
+ OUT UINT64 *StartTimeStamp,
+ OUT UINT64 *EndTimeStamp
+ )
+{
+ return 0;
+}
+
+/**
+ Returns TRUE if the performance measurement macros are enabled.
+
+ This function returns TRUE if the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
+ PcdPerformanceLibraryPropertyMask is set. Otherwise FALSE is returned.
+
+ @retval TRUE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
+ PcdPerformanceLibraryPropertyMask is set.
+ @retval FALSE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
+ PcdPerformanceLibraryPropertyMask is clear.
+
+**/
+BOOLEAN
+EFIAPI
+PerformanceMeasurementEnabled (
+ VOID
+ )
+{
+ return (BOOLEAN) ((PcdGet8 (PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0);
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiPerformanceLibFpdt/PeiPerformanceLibFpdt.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiPerformanceLibFpdt/PeiPerformanceLibFpdt.inf
new file mode 100644
index 0000000000..91615b628f
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiPerformanceLibFpdt/PeiPerformanceLibFpdt.inf
@@ -0,0 +1,52 @@
+## @file
+# Performance library instance used in PEI phase.
+#
+# Copyright (c) 2012 - 2016, 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 = 0x00010017
+ BASE_NAME = PeiPerformanceLibFpdt
+ FILE_GUID = EB9433F6-91E4-45c6-B937-BAE819DA4106
+ VERSION_STRING = 1.0
+ MODULE_TYPE = PEIM
+ LIBRARY_CLASS = PerformanceLib|PEIM PEI_CORE SEC
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[LibraryClasses]
+ BaseMemoryLib
+ PcdLib
+ TimerLib
+ BaseLib
+ HobLib
+ DebugLib
+ LocalApicLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+ BroxtonPlatformPkg/PlatformPkg.dec
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMaxPeiPerformanceLogEntries
+ gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask
+
+[Sources]
+ PeiPerformanceLibFpdt.c
+
+[Guids]
+ gPeiFirmwarePerformanceGuid ## PRODUCES ## HOB
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiSiPolicyLib/PeiSiPolicyLib.c b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiSiPolicyLib/PeiSiPolicyLib.c
new file mode 100644
index 0000000000..2d66cb5385
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiSiPolicyLib/PeiSiPolicyLib.c
@@ -0,0 +1,148 @@
+/** @file
+ This file is PeiSiPolicyLib library creates default settings of RC
+ Policy and installs RC Policy PPI.
+
+ Copyright (c) 2014 - 2016, 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 "PeiSiPolicyLibrary.h"
+
+/**
+ SiCreatePolicyDefaults creates the default setting of Silicon Policy.
+ It allocates and zero out buffer, and fills in the Intel default settings.
+
+ @param[out] SiPolicyPpi The pointer to get Silicon Policy PPI instance
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer.
+
+**/
+EFI_STATUS
+EFIAPI
+SiCreatePolicyDefaults (
+ OUT SI_POLICY_PPI **SiPolicyPpi
+ )
+{
+ SI_POLICY_PPI *SiPolicy;
+
+ SiPolicy = (SI_POLICY_PPI *) AllocateZeroPool (sizeof (SI_POLICY_PPI));
+ if (SiPolicy == NULL) {
+ ASSERT (FALSE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // General intialization
+ //
+ SiPolicy->Revision = SI_POLICY_REVISION;
+
+ //
+ // PlatformData configuration
+ //
+ //
+ // FviSmbiosType is the SMBIOS OEM type (0x80 to 0xFF) defined in SMBIOS Type 14 - Group
+ // Associations structure - item type. FVI structure uses it as SMBIOS OEM type to provide
+ // version information. The default value is type 221.
+ //
+ SiPolicy->FviSmbiosType = 0xDD;
+
+ //
+ // Temporary Bus range for silicon initialization.
+ //
+ SiPolicy->TempPciBusMin = 2;
+ SiPolicy->TempPciBusMax = 6;
+
+ //
+ // Temporary Memory Base Address for PCI devices to be used to initialize MMIO registers.
+ // Minimum size is 2MB bytes.
+ //
+ SiPolicy->TempMemBaseAddr = TEMP_MEM_BASE_ADDRESS;
+ SiPolicy->TempMemSize = TEMP_MEM_SIZE;
+
+ //
+ // Temporary IO Base Address for PCI devices to be used to initialize IO registers.
+ // And size of temporary IO space.
+ //
+ SiPolicy->TempIoBaseAddr = TEMP_IO_BASE_ADDRESS;
+ SiPolicy->TempIoSize = TEMP_IO_SIZE;
+
+ *SiPolicyPpi = SiPolicy;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ SiInstallPolicyPpi installs SiPolicyPpi.
+ While installed, RC assumes the Policy is ready and finalized. So please update and override
+ any setting before calling this function.
+
+ @param[in] SiPolicyPpi The pointer to Silicon Policy PPI instance.
+
+ @retval EFI_SUCCESS The policy is installed.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer.
+
+**/
+EFI_STATUS
+EFIAPI
+SiInstallPolicyPpi (
+ IN SI_POLICY_PPI *SiPolicyPpi
+ )
+{
+ EFI_STATUS Status;
+ EFI_PEI_PPI_DESCRIPTOR *SiPolicyPpiDesc;
+ EFI_PEI_PPI_DESCRIPTOR *OldSiPolicyPpiDesc;
+
+ SiPolicyPpiDesc = (EFI_PEI_PPI_DESCRIPTOR *) AllocateZeroPool (sizeof (EFI_PEI_PPI_DESCRIPTOR));
+ if (SiPolicyPpiDesc == NULL) {
+ ASSERT (FALSE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ SiPolicyPpiDesc->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
+ SiPolicyPpiDesc->Guid = &gSiPolicyPpiGuid;
+ SiPolicyPpiDesc->Ppi = SiPolicyPpi;
+
+ //
+ // Print whole SI_POLICY_PPI and serial out.
+ //
+ SiPrintPolicyPpi (SiPolicyPpi);
+
+ Status = PeiServicesLocatePpi (
+ &gSiPolicyPpiGuid,
+ 0,
+ &OldSiPolicyPpiDesc,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, "Locate Old gSiPolicyPpiGuid fail in Post-Memory\n"));
+ Status = PeiServicesInstallPpi (SiPolicyPpiDesc);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Install gSiPolicyPpiGuid fail in Post-Memory\n"));
+ }
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ //
+ // ReInstall Sc Spi PPI
+ //
+ DEBUG ((DEBUG_INFO, "Re-Install gSiPolicyPpiGuid in Post-Memory, OldSiPolicyPpiDesc is %x, New is %x\n", OldSiPolicyPpiDesc, SiPolicyPpiDesc));
+ Status = PeiServicesReInstallPpi (OldSiPolicyPpiDesc, SiPolicyPpiDesc);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Re-Install gSiPolicyPpiGuid fail in Post-Memory\n"));
+ }
+ ASSERT_EFI_ERROR (Status);
+ }
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiSiPolicyLib/PeiSiPolicyLib.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiSiPolicyLib/PeiSiPolicyLib.inf
new file mode 100644
index 0000000000..3650843333
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiSiPolicyLib/PeiSiPolicyLib.inf
@@ -0,0 +1,40 @@
+## @file
+# PeiSiPolicyLib library.
+#
+# Copyright (c) 2014 - 2016, 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 = PeiSiPolicyLib
+ FILE_GUID = DF39567A-30C3-4913-8A8B-D4585B74E4E0
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PeiSiPolicyLib
+
+[Sources]
+ PeiSiPolicyLib.c
+ SiPrintPolicy.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ BroxtonSiPkg/BroxtonSiPkg.dec
+
+[LibraryClasses]
+ DebugLib
+ IoLib
+ PeiServicesLib
+ BaseMemoryLib
+ MemoryAllocationLib
+
+[Ppis]
+ gSiPolicyPpiGuid ## PRODUCES
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiSiPolicyLib/PeiSiPolicyLibrary.h b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiSiPolicyLib/PeiSiPolicyLibrary.h
new file mode 100644
index 0000000000..af9861c42a
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiSiPolicyLib/PeiSiPolicyLibrary.h
@@ -0,0 +1,37 @@
+/** @file
+ Header file for the PeiSiPolicyLib library.
+
+ Copyright (c) 2014 - 2016, 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_SI_POLICY_LIBRARY_H_
+#define _PEI_SI_POLICY_LIBRARY_H_
+
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Ppi/SiPolicyPpi.h>
+#include <Library/SiPolicyLib.h>
+
+#define TEMP_MEM_BASE_ADDRESS 0xFE600000
+#define TEMP_IO_BASE_ADDRESS 0xD000
+
+//
+// IO/MMIO resource limits
+//
+#define TEMP_MEM_SIZE 0x200000
+#define TEMP_IO_SIZE 0x10
+
+#endif // _PEI_SI_POLICY_LIBRARY_H_
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiSiPolicyLib/SiPrintPolicy.c b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiSiPolicyLib/SiPrintPolicy.c
new file mode 100644
index 0000000000..f7c747940d
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiSiPolicyLib/SiPrintPolicy.c
@@ -0,0 +1,44 @@
+/** @file
+ This file is PeiSiPolicyLib library creates default settings of RC
+ Policy and installs RC Policy PPI.
+
+ Copyright (c) 2014 - 2016, 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 "PeiSiPolicyLibrary.h"
+
+/**
+ Print whole SI_POLICY_PPI and serial out.
+
+ @param[in] SiPolicyPpi The RC Policy PPI instance.
+
+**/
+VOID
+EFIAPI
+SiPrintPolicyPpi (
+ IN SI_POLICY_PPI *SiPolicyPpi
+ )
+{
+#ifdef EFI_DEBUG
+ DEBUG ((DEBUG_INFO, "------------------------ Silicon Print Policy Start ------------------------\n"));
+ DEBUG ((DEBUG_INFO, " Revision= %x\n", SiPolicyPpi->Revision));
+ DEBUG ((DEBUG_INFO, " EcPresent= %x\n", SiPolicyPpi->EcPresent));
+ DEBUG ((DEBUG_INFO, " TempPciBusMin= %x\n", SiPolicyPpi->TempPciBusMin));
+ DEBUG ((DEBUG_INFO, " TempPciBusMax= %x\n", SiPolicyPpi->TempPciBusMax));
+ DEBUG ((DEBUG_INFO, " TempMemBaseAddr= %x\n", SiPolicyPpi->TempMemBaseAddr));
+ DEBUG ((DEBUG_INFO, " TempMemSize= %x\n", SiPolicyPpi->TempMemSize));
+ DEBUG ((DEBUG_INFO, " TempIoBaseAddr= %x\n", SiPolicyPpi->TempIoBaseAddr));
+ DEBUG ((DEBUG_INFO, " TempIoSize= %x\n", SiPolicyPpi->TempIoSize));
+ DEBUG ((DEBUG_INFO, "------------------------ Silicon Print Policy End --------------------------\n"));
+#endif // EFI_DEBUG
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PmcIpcLib/BaseIpcLib.c b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PmcIpcLib/BaseIpcLib.c
new file mode 100644
index 0000000000..48e037bd91
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PmcIpcLib/BaseIpcLib.c
@@ -0,0 +1,128 @@
+/** @file
+ Base IPC library implementation.
+
+ Copyright (c) 1999 - 2016, 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 <Base.h>
+#include <SaCommonDefinitions.h>
+#include <PlatformBaseAddresses.h>
+#include <ScRegs/RegsPmc.h>
+#include "InternalIpcLib.h"
+
+/**
+ Checks the IPC channel is available for a new request.
+
+ @retval EFI_SUCCESS Ready for a new IPC.
+ @retval EFI_NOT_READY Not ready for a new IPC.
+
+**/
+EFI_STATUS
+EFIAPI
+ReadyForNewIpc (
+ VOID
+ )
+{
+ UINT32 PciCfgReg;
+ UINT32 Value = 0;
+ UINT32 Addr32;
+ UINTN PmcIpc1RegBaseAddr = 0;
+
+ PciCfgReg = (UINT32) MmPciAddress (0, 0, PCI_DEVICE_NUMBER_PMC_IPC1, PCI_FUNCTION_NUMBER_PMC_IPC1, 0x10); //Bar0 Reg
+ Addr32 = MmioRead32 (PciCfgReg) & 0xFFFFFFF0;
+ PciCfgReg = (UINT32) MmPciAddress (0, 0, PCI_DEVICE_NUMBER_PMC_IPC1, PCI_FUNCTION_NUMBER_PMC_IPC1, 0x4); //Sts Reg
+ Value = MmioRead32 (PciCfgReg);
+
+ if (Addr32 != 0 && Addr32 != 0xFFFFFFF0 && ((Value & 0x06) == 0x06)) {
+ PmcIpc1RegBaseAddr = Addr32;
+ } else {
+ return EFI_NOT_READY;
+ }
+
+ return InternalReadyForNewIpc (PmcIpc1RegBaseAddr);
+}
+
+
+/**
+ Sends an IPC from the x86 CPU to the SCU and waits for the SCU to process the
+ specified opcode.
+
+ @param[in] Command The Command identifier to send in the IPC packet.
+ @param[in] SubCommand The SubCommand identifier to send in the IPC packet.
+ @param[in, out] Buffer Pointer to buffer associated with MessageId. This is an optional
+ patrametert that may be NULL for some MessageId values.
+ @param[in, out] BufferSize The size, in bytes, of Buffer. Ignored if Buffer is NULL.
+
+ @retval IPC_STATUS
+
+**/
+EFI_STATUS
+IpcSendCommandEx (
+ IN UINT32 Command,
+ IN UINT8 SubCommand,
+ IN OUT VOID *Buffer, OPTIONAL
+ IN OUT UINTN BufferSize
+ )
+{
+ UINT32 PciCfgReg;
+ UINT32 Value = 0;
+ UINT32 Addr32;
+ UINTN PmcIpc1RegBaseAddr = 0;
+
+ PciCfgReg = (UINT32) MmPciAddress (0, 0, PCI_DEVICE_NUMBER_PMC_IPC1, PCI_FUNCTION_NUMBER_PMC_IPC1, 0x10); //Bar0 Reg
+ Addr32 = MmioRead32 (PciCfgReg) & 0xFFFFFFF0;
+ PciCfgReg = (UINT32) MmPciAddress(0, 0, PCI_DEVICE_NUMBER_PMC_IPC1, PCI_FUNCTION_NUMBER_PMC_IPC1, 0x4); //Sts Reg
+ Value = MmioRead32 (PciCfgReg);
+
+ if (Addr32 != 0 && Addr32 != 0xFFFFFFF0 && ((Value & 0x06) == 0x06)) {
+ PmcIpc1RegBaseAddr = Addr32;
+ } else {
+ DEBUG ((DEBUG_ERROR, "Error IPC1 command failed MMIO address %x, status =%x \n", Addr32, Value));
+ return EFI_NOT_READY;
+ }
+
+ return InternalIpcSendCommandEx (PmcIpc1RegBaseAddr, Command, SubCommand, Buffer, BufferSize);
+}
+
+
+/**
+ Sends an IPC from the x86 CPU to the PMC and waits for the PMC to process the
+ specified opcode.
+
+ !! Use it only when you are sure that IPC PCI config space is no longer valid !!
+
+ @param[in] PciBar0 PCI config BAR0 for IPC.
+ @param[in] Command The Command identifier to send in the IPC packet.
+ @param[in] SubCommand The SubCommand identifier to send in the IPC packet.
+ @param[in, out] Buffer Pointer to buffer associated with MessageId. This is an optional
+ patrametert that may be NULL for some MessageId values.
+ @param[in, out] BufferSize The size, in bytes, of Buffer. Ignored if Buffer is NULL.
+
+**/
+RETURN_STATUS
+EFIAPI
+IpcSendCommandBar0Ex (
+ IN UINT32 PciBar0,
+ IN UINT32 Command,
+ IN UINT8 SubCommand,
+ IN OUT VOID *Buffer, OPTIONAL
+ IN OUT UINTN BufferSize
+ )
+{
+ if (PciBar0 != 0 && PciBar0 != 0xFFFFFFF0) {
+ return InternalIpcSendCommandEx (PciBar0, Command, SubCommand, Buffer, BufferSize);
+ }
+ DEBUG ((DEBUG_ERROR, "IpcSendCommandBar0Ex Error IPC1 command failed, not valid address %x\n", PciBar0));
+
+ return EFI_NOT_READY;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PmcIpcLib/BaseIpcLib.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PmcIpcLib/BaseIpcLib.inf
new file mode 100644
index 0000000000..0476e887c3
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PmcIpcLib/BaseIpcLib.inf
@@ -0,0 +1,46 @@
+## @file
+# Base IPC library.
+#
+# Copyright (c) 1999 - 2016, 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 = BaseIpcLib
+ FILE_GUID = 5177C810-CA5C-41c8-A210-B176C9BD22EF
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = BaseIpcLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ BaseIpcLib.c
+ InternalIpcLib.c
+ InternalIpcLib.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ BroxtonSiPkg/BroxtonSiPkg.dec
+
+[LibraryClasses]
+ IoLib
+ DebugLib
+ PcdLib
+ BaseLib
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress ## SOMETIMES_CONSUMES
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PmcIpcLib/InternalIpcLib.c b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PmcIpcLib/InternalIpcLib.c
new file mode 100644
index 0000000000..642ee64123
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PmcIpcLib/InternalIpcLib.c
@@ -0,0 +1,368 @@
+/** @file
+ Base IPC library implementation.
+
+ Copyright (c) 1999 - 2016, 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 <Base.h>
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include "InternalIpcLib.h"
+
+/**
+ Sends an IPC without waiting.
+
+ @param[in] BaseAddress The base address of the IPC register bank
+ @param[in] Command The message identifier to send in the IPC packet.
+ @param[in out] Buffer Pointer to buffer associated with MessageId. This is an optional
+ patrameter that may be NULL for some MessageId values.
+ Note: This buffer can be used for both Input/Output buffer at the same time
+ Whenever used as Output buffer to receive return value, it must be 1 or more DWs.
+ @param[in out] BufferSize The size, in bytes, of Buffer. Ignored if Buffer is NULL.
+
+ @retval None
+
+**/
+VOID
+InternalIpcLibSendCommandWithoutWaiting (
+ IN UINTN BaseAddress,
+ IN UINT32 Command,
+ IN OUT VOID *Buffer, OPTIONAL
+ IN OUT UINTN BufferSize
+ )
+{
+ MmioWrite32 (BaseAddress + R_IPC_CMD_OFFSET, Command);
+}
+
+
+/**
+ Sends an IPC without waiting.
+
+ @param[in] BaseAddress The base address of the IPC register bank
+ @param[in] Command The Command identifier to send in the IPC packet.
+ @param[in] CommandType The Command type to send in the IPC packet.
+ @param[in] ReturnDataSize Return Data size.
+ @param[in out] Buffer Pointer to buffer associated with MessageId. This is an optional
+ patrameter that may be NULL for some MessageId values.
+ Note: This buffer can be used for both Input/Output buffer at the same time
+ Whenever used as Output buffer to receive return value, it must be 1 or more DWs.
+ @param[in out] BufferSize The size, in bytes, of Buffer. Ignored if Buffer is NULL.
+
+ @retval IPC_STATUS.Uint32
+
+**/
+UINT32
+InternalIpcLibSendCommandAndWait (
+ IN UINTN BaseAddress,
+ IN UINT32 Command,
+ IN IPC_CMD_TYPE CommandType,
+ IN UINT32 ReturnDataSize,
+ IN OUT VOID *Buffer, OPTIONAL
+ IN OUT UINTN BufferSize
+ )
+{
+ UINTN Index;
+ IPC_STATUS IpcStatus;
+
+ MmioWrite32 (BaseAddress + R_IPC_CMD_OFFSET, Command);
+ do {
+ IpcStatus.Uint32 = MmioRead32 (BaseAddress + R_IPC_STS_OFFSET);
+ } while (IpcStatus.Bits.Busy == 1);
+
+ if ((IpcStatus.Bits.Error == 0) && (CommandType ==IPC_CMD_READ)) {
+ if (Buffer != NULL && BufferSize != 0) {
+ for (Index = 0; Index < ReturnDataSize; Index++ ){
+ *((UINT8 *) Buffer + Index) = MmioRead8 (BaseAddress + R_IPC_RBUF_OFFSET + Index);
+ }
+ }
+ }
+ return IpcStatus.Uint32;
+}
+
+
+/**
+ Checks the IPC channel is available for a new request
+
+ @param[in] BaseAddress The base address of the IPC register bank.
+
+ @retval RETURN_SUCCESS Ready for a new IPC.
+ @retval RETURN_NOT_READY Not ready for a new IPC.
+
+**/
+RETURN_STATUS
+InternalReadyForNewIpc (
+ IN UINTN BaseAddress
+ )
+{
+ IPC_STATUS IpcStatus;
+
+ IpcStatus.Uint32 = MmioRead32 (BaseAddress + R_IPC_STS_OFFSET);
+ if (IpcStatus.Bits.Busy == 1) {
+ return RETURN_NOT_READY;
+ } else {
+ return RETURN_SUCCESS;
+ }
+}
+
+
+/**
+ Sends an IPC from the x86 CPU to the PMC and waits for the PMC to process the
+ specified opcode.
+
+ @param[in] BaseAddress The base address of the IPC register bank
+ @param[in] Command The Command identifier to send in the IPC packet.
+ @param[in] SubCommand The SubCommand identifier to send in the IPC packet.
+ @param[in, out] Buffer Pointer to buffer associated with MessageId. This is an optional
+ patrameter that may be NULL for some MessageId values.
+ Note: This buffer can be used for both Input/Output buffer at the same time
+ Whenever used as Output buffer to receive return value, it must be 1 or more DWs.
+ @param[in,out] BufferSize The size, in bytes, of Buffer. Ignored if Buffer is NULL.
+
+ @retval IPC_STATUS.Uint32
+
+**/
+UINT32
+InternalIpcSendCommandEx (
+ IN UINTN BaseAddress,
+ IN UINT32 Command,
+ IN UINT8 SubCommand,
+ IN OUT VOID *Buffer, OPTIONAL
+ IN OUT UINTN BufferSize
+ )
+{
+ UINT8 IpcCommand;
+ UINT32 CommandSize;
+ UINT32 ReturnDataSize;
+ UINT32 BufferData;
+ UINT32 tempBufferData;
+ UINTN Index;
+ UINTN OffsetIndex;
+ IPC_STATUS IpcStatus;
+ IPC_CMD_TYPE CmdType;
+ UINT32 tempCommand = 0;
+ BOOLEAN State;
+
+ IpcStatus.Uint32 = 0;
+ IpcCommand = (UINT8) Command;
+ ReturnDataSize = 0;
+
+ //
+ // Make sure interrupts are disabled
+ //
+ State = SaveAndDisableInterrupts ();
+ switch (IpcCommand) {
+ case IPC_CMD_ID_USB3P3:
+ case IPC_CMD_ID_BLACKLIST_SEL:
+ case IPC_CMD_ID_SOUTH_IP_UNGATE:
+ case IPC_CMD_ID_CAPSULE_UPDATE_RESET:
+ CmdType = IPC_CMD_NONE;
+ CommandSize = 0;
+ ReturnDataSize = 0;
+ break;
+
+ case IPC_CMD_ID_FW_MSG_CTRL:
+ switch (SubCommand) {
+ case IPC_SUBCMD_ID_FW_MSG_CTRL_READ:
+ CmdType = IPC_CMD_READ;
+ ReturnDataSize = sizeof (UINT8);
+ CommandSize = 0;
+ break;
+
+ case IPC_SUBCMD_ID_FW_MSG_CTRL_WRITE:
+ CmdType = IPC_CMD_WRITE;
+ CommandSize = 1;
+ break;
+
+ default:
+ return INVALID_IPC_CMD;
+ break;
+ }
+ break;
+
+ case IPC_CMD_ID_PMC_VER:
+ switch (SubCommand) {
+ case IPC_SUBCMD_ID_PMC_VER_READ:
+ CmdType = IPC_CMD_READ;
+ ReturnDataSize = sizeof (UINT8) * 8;
+ CommandSize = 0;
+ break;
+
+ default:
+ return INVALID_IPC_CMD;
+ break;
+ }
+ break;
+
+ case IPC_CMD_ID_PHY_CFG:
+ CmdType = IPC_CMD_WRITE;
+ CommandSize = 1;
+ break;
+
+ case IPC_CMD_ID_PM_DEBUG:
+ switch (SubCommand) {
+ case IPC_SUBCMD_ID_LPSS_DEBUG_UART_ENABLE:
+ CmdType = IPC_CMD_WRITE;
+ CommandSize = 0;
+ break;
+
+ case IPC_SUBCMD_ID_LPSS_DEBUG_UART_DISABLE:
+ CmdType = IPC_CMD_WRITE;
+ CommandSize = 0;
+ break;
+
+ case IPC_SUBCMD_ID_PM_DEBUG_LTR_IGNORE_REPORT:
+ CmdType = IPC_CMD_READ;
+ CommandSize = 1;
+ ReturnDataSize = sizeof (UINT32);
+ break;
+
+ case IPC_SUBCMD_ID_PM_DEBUG_LTR_IGNORE_READ:
+ CmdType = IPC_CMD_READ;
+ CommandSize = 0;
+ ReturnDataSize = sizeof (UINT16);
+ break;
+
+ case IPC_SUBCMD_ID_PM_DEBUG_LTR_IGNORE_WRITE:
+ CmdType = IPC_CMD_WRITE;
+ CommandSize = 2;
+ break;
+ default:
+ return INVALID_IPC_CMD;
+ }
+ break;
+
+ case IPC_CMD_ID_PMIC:
+ //
+ // PMIC will read data is byte size.
+ //
+ switch (SubCommand) {
+ case IPC_SUBCMD_ID_PMIC_READ:
+ CmdType = IPC_CMD_READ;
+ CommandSize = 2;
+ ReturnDataSize = (CommandSize / 2);
+ break;
+
+ case IPC_SUBCMD_ID_PMIC_WRITE:
+ CmdType = IPC_CMD_WRITE;
+ CommandSize = 3;
+ ReturnDataSize = (CommandSize / 3);
+ break;
+
+ case IPC_SUBCMD_ID_PMIC_READ_MOD_WRITE:
+ CmdType = IPC_CMD_READ;
+ CommandSize = 4;
+ ReturnDataSize = (CommandSize / 4);
+
+ break;
+ default:
+ return INVALID_IPC_CMD;
+ }
+ break;
+
+ case IPC_CMD_ID_TELEMETRY:
+ switch (SubCommand) {
+ case 0:
+ CmdType = IPC_CMD_READ;
+ ReturnDataSize = sizeof (UINT16);
+ CommandSize = 1;
+ break;
+
+ case 2:
+ case 3:
+ case 5:
+ case 7:
+ CmdType = IPC_CMD_READ;
+ ReturnDataSize = sizeof (UINT32);
+ CommandSize = 0;
+ break;
+
+ case 1:
+ CommandSize = 1;
+ CmdType = IPC_CMD_WRITE;
+ break;
+
+ case 4:
+ case 6:
+ case 8:
+ CommandSize = 4;
+ CmdType = IPC_CMD_WRITE;
+ break;
+
+ default:
+ return INVALID_IPC_CMD;
+ }
+ break;
+
+ //
+ // EMI/RFI support
+ // Note that this command is not valid on BXT-A
+ //
+ case IPC_CMD_ID_EMI_RFI_SUPPORT:
+ CmdType = IPC_CMD_WRITE;
+ CommandSize = 16;
+ ReturnDataSize = 0;
+ break;
+
+ default:
+ return INVALID_IPC_CMD;
+ }
+
+ if (CmdType == IPC_CMD_READ) {
+ if ((ReturnDataSize > BufferSize) || (NULL == Buffer)) { //cmd 2, 3, 5, 7 Read 4 bytes data.
+ return INVALID_IPC_CMD;
+ }
+ }
+
+ tempCommand |= (SubCommand << 12);
+ tempCommand |= (CommandSize << 16);
+ tempCommand |= Command;
+
+ //
+ // Send data to R_IPC_WBUF_OFFSET.
+ //
+ if (CommandSize > 0){
+ BufferData = 0;
+
+ for (Index = 0; Index < CommandSize; Index++) {
+ tempBufferData = *(((UINT8 *) Buffer + Index));
+ OffsetIndex = Index % 4;
+ BufferData |= (tempBufferData << (OffsetIndex * 8));
+
+ if (OffsetIndex == 3) {
+ MmioWrite32 (BaseAddress + R_IPC_WBUF_OFFSET + (Index / 4 * 4), BufferData);
+ BufferData = 0;
+ } else {
+ if (Index == (CommandSize - 1)){
+ MmioWrite32 (BaseAddress + R_IPC_WBUF_OFFSET + (Index / 4 * 4), BufferData);
+ }
+ }
+ }
+ }
+
+ IpcStatus.Uint32 = InternalIpcLibSendCommandAndWait (BaseAddress, tempCommand, CmdType, ReturnDataSize, Buffer, BufferSize); // Returned 4 bytes (max) is stored in Buffer
+
+ if (IpcStatus.Bits.Error != 0) {
+ } else {
+ if (CmdType == IPC_CMD_READ) {
+ for (Index = 0; Index < ReturnDataSize; Index++) {
+ }
+ }
+ }
+
+ //
+ // Restore the original interrupt state
+ //
+ SetInterruptState (State);
+
+ return IpcStatus.Uint32;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PmcIpcLib/InternalIpcLib.h b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PmcIpcLib/InternalIpcLib.h
new file mode 100644
index 0000000000..f8babb8218
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/PmcIpcLib/InternalIpcLib.h
@@ -0,0 +1,75 @@
+/** @file
+ Header file for Base IPC library.
+
+ Copyright (c) 1999 - 2016, 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 __INTERNAL_IPC_LIB_H__
+#define __INTERNAL_IPC_LIB_H__
+
+//
+// Consumed library classes
+//
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/I2CLib.h>
+
+//
+// Produced library class
+//
+#include <Library/PmcIpcLib.h>
+
+//
+// PMC IPC1 Register Base Address
+// This base address will be dynamically changed during PCI enum
+//
+
+
+/**
+ Checks the IPC channel is available for a new request.
+
+ @param[in] BaseAddress The base address of the IPC register bank.
+
+ @retval EFI_SUCCESS Ready for a new IPC.
+ @retval EFI_NOT_READY Not ready for a new IPC.
+
+**/
+RETURN_STATUS
+InternalReadyForNewIpc (
+ IN UINTN BaseAddress
+ );
+
+/**
+ Sends an IPC from the x86 CPU to the PMC and waits for the PMC to process the
+ specified opcode.
+
+ @param[in] BaseAddress The base address of the IPC register bank
+ @param[in] MessageId The message identifier to send in the IPC packet.
+ @param[in] CommandID The SubCommand identifier to send in the IPC packet.
+ @param[in, out] Buffer Pointer to buffer associated with MessageId. This is an optional
+ patrametert that may be NULL for some MessageId values.
+ @param[in, out] BufferSize The size, in bytes, of Buffer. Ignored if Buffer is NULL.
+
+ @retval IPC_STATUS.Uint32
+
+**/
+UINT32
+InternalIpcSendCommandEx (
+ IN UINTN BaseAddress,
+ IN UINT32 MessageId,
+ IN UINT8 CommandId,
+ IN OUT VOID *Buffer, OPTIONAL
+ IN OUT UINTN BufferSize
+ );
+
+#endif
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/BaseCseVariableStorageLib/BaseCseVariableStorageLib.c b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/BaseCseVariableStorageLib/BaseCseVariableStorageLib.c
new file mode 100644
index 0000000000..f60ed52ab8
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/BaseCseVariableStorageLib/BaseCseVariableStorageLib.c
@@ -0,0 +1,1091 @@
+/** @file
+ CSE Variable Storage Library.
+
+ Copyright (c) 2016, 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 <Base.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/CseVariableStorageLib.h>
+#include <Library/CseVariableStorageSelectorLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HeciMsgLib.h>
+#include <Pi/PiMultiPhase.h>
+#include <Library/HobLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PrintLib.h>
+#include <Library/TimerLib.h> // Temporary
+#include <Library/VariableNvmStorageLib.h>
+#include <Protocol/Heci.h>
+
+
+/**
+ Creates variable stores if in DXE and necessary. Loads the variable data region
+ from CSE NVM needed to find variables.
+
+ @param[in, out] CseVariableFileInfo A pointer to a structure that contains information the CSE files available.
+ @param[in] AtDxeRuntime Determines how this function should allocate memory.
+ Caller passes TRUE if in DXE and FALSE for pre-DXE (PEI).
+
+ @retval EFI_SUCCESS The variable store was established successfully.
+ @retval Others The variable store could not be established.
+
+**/
+EFI_STATUS
+EFIAPI
+EstablishAndLoadCseVariableStores (
+ IN OUT CSE_VARIABLE_FILE_INFO **CseVariableFileInfo,
+ IN BOOLEAN AtDxeRuntime
+ )
+{
+ EFI_STATUS Status;
+ CSE_VARIABLE_FILE_TYPE Type;
+ UINTN VariableStoreSize = 0;
+ UINTN VariableHeaderRegionSize = 0;
+ UINTN VariableHeaderRegionBufferSize = 0;
+ UINT32 CseFileVariableBaseFileOffset = 0;
+ EFI_HOB_GUID_TYPE *IndexFileDataHob = NULL;
+ UINT8 *VariableHeaderRegion = NULL;
+ UINT8 *VariableHeaderRegionIndexHobData = NULL;
+ VARIABLE_NVM_STORE_HEADER VariableStoreHeader;
+
+ for (Type = (CSE_VARIABLE_FILE_TYPE) 0; Type < CseVariableFileTypeMax; Type++) {
+ ASSERT (CseVariableFileInfo[Type] != NULL);
+
+ if (CseVariableFileInfo[Type]->FileEnabled && !CseVariableFileInfo[Type]->FileStoreEstablished) {
+ Status = GetCseVariableStoreFileOffset (Type, &CseFileVariableBaseFileOffset);
+
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Attempt to load the index file data from its HOB if available
+ //
+ IndexFileDataHob = GetFirstGuidHob (CseVariableFileInfo[Type]->IndexFileDataGuid);
+
+ if (IndexFileDataHob != NULL && !AtDxeRuntime) {
+ CseVariableFileInfo[Type]->HeaderRegionBase = (EFI_PHYSICAL_ADDRESS) (UINTN) GET_GUID_HOB_DATA (IndexFileDataHob);
+ continue;
+ }
+
+ if (AtDxeRuntime) {
+ if (Type == CseVariableFileTypePreMemoryFile) {
+ VariableHeaderRegionBufferSize = CseVariableFileInfo[Type]->FileStoreMaximumSize;
+ } else {
+ VariableHeaderRegionBufferSize = CSE_MAX_FILE_DATA_SIZE;
+ }
+
+ if (IndexFileDataHob == NULL) {
+ //
+ // Writes an empty variable store to CSE NVM if it does not already exist
+ // Returns the size of the CSE NVM variable store
+ //
+ Status = CreateCseNvmVariableStore (
+ CseVariableFileInfo[Type]->FileName,
+ CseFileVariableBaseFileOffset,
+ &VariableHeaderRegionSize
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Error creating CSE variable store %d\n", (UINT32) Type));
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ } else {
+ DEBUG ((EFI_D_INFO, "Successfully created CSE variable store %d\n", (UINT32) Type));
+ }
+ } else {
+ VariableHeaderRegionSize = GET_GUID_HOB_DATA_SIZE (IndexFileDataHob);
+ }
+ } else {
+ //
+ // Check if the variable store exists
+ //
+ Status = HeciGetNVMFileSize (CseVariableFileInfo[Type]->FileName, &VariableHeaderRegionBufferSize);
+
+ //
+ // If there's an error finding the file, do not establish this store as
+ // variable stores cannot be created in PEI.
+ //
+ if (EFI_ERROR (Status) || VariableHeaderRegionBufferSize > CseVariableFileInfo[Type]->FileStoreMaximumSize) {
+ continue;
+ }
+ ASSERT (VariableHeaderRegionBufferSize > 0);
+
+ VariableHeaderRegionSize = VariableHeaderRegionBufferSize;
+ }
+
+ if (Type == CseVariableFileTypePreMemoryFile) {
+ VariableStoreSize = sizeof (VARIABLE_NVM_STORE_HEADER);
+
+ //
+ // Read the variable store header to determine the total variable header region size
+ //
+ Status = ReadCseNvmFile (
+ CseVariableFileInfo[Type]->FileName,
+ CseFileVariableBaseFileOffset,
+ (UINT8 *) &VariableStoreHeader,
+ &VariableStoreSize,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Error reading the variable header region for CSE variable store %d.\n", (UINT32) Type));
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ VariableHeaderRegionSize = sizeof (VARIABLE_NVM_STORE_HEADER) \
+ + VariableStoreHeader.VariableHeaderTotalLength \
+ + NVM_GET_PAD_SIZE (VariableStoreHeader.VariableHeaderTotalLength);
+
+ if (!AtDxeRuntime) {
+ VariableHeaderRegionBufferSize = VariableHeaderRegionSize;
+ }
+ }
+ ASSERT (
+ VariableHeaderRegionSize >= sizeof (VARIABLE_NVM_STORE_HEADER) \
+ && VariableHeaderRegionSize <= CseVariableFileInfo[Type]->FileStoreMaximumSize
+ );
+
+ if (AtDxeRuntime) {
+ VariableHeaderRegion = AllocateRuntimePool (VariableHeaderRegionBufferSize);
+ } else {
+ VariableHeaderRegion = BuildGuidHob (CseVariableFileInfo[Type]->IndexFileDataGuid, VariableHeaderRegionBufferSize);
+ }
+
+ if (VariableHeaderRegion == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ DEBUG ((EFI_D_INFO, "Total buffer size for store %d is %d bytes.\n", (UINT32) Type, VariableHeaderRegionBufferSize));
+
+ ZeroMem (VariableHeaderRegion, VariableHeaderRegionBufferSize);
+
+ if (IndexFileDataHob == NULL) {
+ //
+ // Load the variable header region for this variable store
+ //
+ Status = ReadCseNvmFile (
+ CseVariableFileInfo[Type]->FileName,
+ CseFileVariableBaseFileOffset,
+ (UINT8 *) VariableHeaderRegion,
+ &VariableHeaderRegionSize,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Error reading the variable header region for CSE variable store %d.\n", (UINT32) Type));
+
+ if (AtDxeRuntime) {
+ FreePool (VariableHeaderRegion);
+ }
+
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+ } else {
+ VariableHeaderRegionIndexHobData = GET_GUID_HOB_DATA (IndexFileDataHob);
+
+ if (VariableHeaderRegionIndexHobData == NULL) {
+ ASSERT (VariableHeaderRegionIndexHobData != NULL);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem (VariableHeaderRegion, VariableHeaderRegionIndexHobData, VariableHeaderRegionSize);
+ }
+
+ CseVariableFileInfo[Type]->HeaderRegionBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VariableHeaderRegion;
+
+ DEBUG ((EFI_D_INFO, "Setting file store %d to established. Variable header region base at 0x%x.\n", (UINT32) Type, CseVariableFileInfo[Type]->HeaderRegionBase));
+
+ CseVariableFileInfo[Type]->FileStoreEstablished = TRUE;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Initializes the global variable structures for CSE storage modules.
+
+ @param[in,out] CseVariableFileInfo A pointer to a structure that contains information the CSE files available.
+ @param[in] AtDxeRuntime Determines how this function should allocate memory.
+ Caller passes TRUE if in DXE and FALSE for pre-DXE (PEI).
+
+ @retval EFI_SUCCESS The global variables were initialized successfully.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory resources needed for allocation were available.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeCseStorageGlobalVariableStructures (
+ IN OUT CSE_VARIABLE_FILE_INFO **CseVariableFileInfo,
+ IN BOOLEAN AtDxeRuntime
+ )
+{
+ CHAR8 FileNamePtr[CSE_MAX_NVM_FILE_NAME_LENGTH];
+ CHAR16 *FileNamePtrUni;
+ UINTN FileNameSize;
+ CSE_VARIABLE_FILE_TYPE Type;
+
+ FileNamePtrUni = NULL;
+
+ ZeroMem (FileNamePtr, sizeof (FileNamePtr));
+
+ for (Type = (CSE_VARIABLE_FILE_TYPE) 0; Type < CseVariableFileTypeMax; Type++) {
+ if (AtDxeRuntime) {
+ CseVariableFileInfo[Type] = AllocateRuntimeZeroPool (sizeof (CSE_VARIABLE_FILE_INFO));
+ } else {
+ CseVariableFileInfo[Type] = AllocateZeroPool (sizeof (CSE_VARIABLE_FILE_INFO));
+ }
+
+ if (CseVariableFileInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ //
+ // Set file enable defaults
+ //
+ CseVariableFileInfo[CseVariableFileTypePreMemoryFile]->FileEnabled = FALSE;
+ CseVariableFileInfo[CseVariableFileTypePrimaryIndexFile]->FileEnabled = TRUE;
+
+ //
+ // Populate the remaining fields in the global variable structure
+ //
+ for (Type = (CSE_VARIABLE_FILE_TYPE) 0; Type < CseVariableFileTypeMax; Type++) {
+ ASSERT (CseVariableFileInfo[Type] != NULL);
+
+ CseVariableFileInfo[Type]->FileName = NULL;
+ CseVariableFileInfo[Type]->HeaderRegionBase = 0;
+ CseVariableFileInfo[Type]->FileStoreEstablished = FALSE;
+
+ if (Type == CseVariableFileTypePreMemoryFile) {
+ CseVariableFileInfo[Type]->IndexFileDataGuid = &gCsePreMemoryIndexFileDataHobGuid;
+ FileNamePtrUni = (CHAR16 *)(VOID *)PcdGetPtr (PcdEnableCseMrcTrainingDataVariables);
+
+ //
+ // A pre-memory variable store file is not required
+ //
+ if (FileNamePtrUni == NULL || FileNamePtrUni[0] == '\0') {
+ DEBUG ((EFI_D_INFO, "The pre-memory file pointer is null - Do not use the pre-memory file.\n"));
+ continue;
+ }
+
+ CseVariableFileInfo[Type]->FileStoreMaximumSize = CSE_PRE_MEMORY_FILE_MAX_STORE_SIZE;
+ CseVariableFileInfo[Type]->FileEnabled = TRUE;
+ } else if ((CSE_VARIABLE_FILE_TYPE) Type == CseVariableFileTypePrimaryIndexFile) {
+ CseVariableFileInfo[Type]->IndexFileDataGuid = &gCsePrimaryIndexFileDataHobGuid;
+ FileNamePtrUni = (CHAR16 *) (VOID *) PcdGetPtr (PcdPrimaryCseNvmStoreIndexFileName);
+ CseVariableFileInfo[Type]->FileStoreMaximumSize = CSE_PRIMARY_NVM_MAX_STORE_SIZE;
+ }
+
+ ASSERT (FileNamePtrUni != NULL);
+
+ UnicodeStrToAsciiStr (FileNamePtrUni, FileNamePtr);
+ FileNameSize = AsciiStrSize (FileNamePtr);
+ ASSERT (FileNameSize <= CSE_MAX_NVM_FILE_NAME_LENGTH);
+
+ if (AtDxeRuntime) {
+ CseVariableFileInfo[Type]->FileName = AllocateRuntimeCopyPool (FileNameSize, FileNamePtr);
+ } else {
+ CseVariableFileInfo[Type]->FileName = AllocateCopyPool (FileNameSize, FileNamePtr);
+ }
+
+ if (CseVariableFileInfo[Type]->FileName == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ DEBUG ((EFI_D_INFO, "Finished initializing global variable structure for CSE file type %d. File name = %a File name size = %d\n", (UINT32)Type, CseVariableFileInfo[Type]->FileName, FileNameSize));
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Reads data from a CSE NVM file into a specified memory buffer.
+
+ @param[in] CseFileName The name of the CSE file used in the read operation.
+ @param[in] FileOffset The offset to begin reading in the CSE file.
+ @param[in] Data A pointer to a buffer that is the destination for the read.
+ @param[in] DataSize The length in bytes of data to read from the file.
+ @param[in] HeciProtocolSelector The HECI protocol to use to write the file.
+ If not specified, the protocol will be determined internally.
+
+ @retval EFI_SUCCESS The file was read successfully.
+ @retval Others An error occurred reading the file.
+
+**/
+EFI_STATUS
+EFIAPI
+ReadCseNvmFile (
+ IN CHAR8 *CseFileName,
+ IN UINT32 FileOffset,
+ OUT UINT8 *Data,
+ OUT UINTN *DataSize,
+ IN CSE_VARIABLE_HECI_PROTOCOL *HeciProtocolSelector OPTIONAL
+ )
+{
+ CSE_VARIABLE_HECI_PROTOCOL HeciProtocolActive;
+ EFI_HECI_PROTOCOL *Heci2Protocol = NULL;
+
+ DEBUG ((EFI_D_INFO, "+++> Reading CSE NVM file.\n Name = %a\n Offset = %d\n\n", CseFileName, FileOffset));
+
+ if (CseFileName == NULL || AsciiStrnLenS (CseFileName, (UINTN) CSE_MAX_NVM_FILE_NAME_LENGTH) == (UINTN) CSE_MAX_NVM_FILE_NAME_LENGTH) {
+ DEBUG ((EFI_D_ERROR, "Invalid parameter passed, cannot read the CSE file.\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HeciProtocolActive = GetCseHeciProtocol (&Heci2Protocol);
+
+ if (HeciProtocolSelector != NULL) {
+ HeciProtocolActive = *HeciProtocolSelector;
+ }
+
+ if (HeciProtocolActive == CseVariableHeci1Protocol) {
+ return HeciReadNVMFile (CseFileName, FileOffset, Data, DataSize);
+ } else if (Heci2Protocol != NULL) {
+ return Heci2ReadNVMFile (CseFileName, FileOffset, Data, DataSize, Heci2Protocol);
+ } else {
+ ASSERT (FALSE);
+ }
+
+ return EFI_NOT_READY;
+}
+
+
+/**
+ Writes data in a memory buffer to a specified CSE NVM file.
+
+ @param[in] CseFileName The name of the CSE file used in the write operation.
+ @param[in] FileOffset The offset to begin writing in the CSE file.
+ @param[in] Data A pointer to a buffer of data to write to the file.
+ @param[in] DataSize The length in bytes of data to write to the file.
+ @param[in] HeciProtocolSelector The HECI protocol to use to write the file.
+ If not specified, the protocol will be determined internally.
+ @param[in] Truncate If true, the file will be truncated.
+
+ @retval EFI_SUCCESS The file was updated successfully.
+ @retval Others An error occurred updating the file.
+
+**/
+
+EFI_STATUS
+EFIAPI
+UpdateCseNvmFile (
+ IN CHAR8 *CseFileName,
+ IN UINT32 FileOffset,
+ IN UINT8 *Data,
+ IN UINTN DataSize,
+ IN BOOLEAN Truncate,
+ IN CSE_VARIABLE_HECI_PROTOCOL *HeciProtocolSelector OPTIONAL
+ )
+{
+ CSE_VARIABLE_HECI_PROTOCOL HeciProtocolActive;
+ EFI_HECI_PROTOCOL *Heci2Protocol = NULL;
+ EFI_STATUS Status;
+
+ DEBUG ((EFI_D_INFO, "+++> Updating CSE NVM file.\n Name = %a\n Offset = %d\n DataSize = %d\n\n", CseFileName, FileOffset, DataSize));
+
+ if (CseFileName == NULL ||
+ Data == NULL ||
+ AsciiStrnLenS (CseFileName, (UINTN) CSE_MAX_NVM_FILE_NAME_LENGTH) == (UINTN) CSE_MAX_NVM_FILE_NAME_LENGTH) {
+ DEBUG ((EFI_D_ERROR, "Invalid parameter passed, cannot write to the CSE file.\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HeciProtocolActive = GetCseHeciProtocol (&Heci2Protocol);
+
+ if (HeciProtocolSelector != NULL) {
+ HeciProtocolActive = *HeciProtocolSelector;
+ }
+
+ if (HeciProtocolActive == CseVariableHeci1Protocol) {
+ return HeciWriteNVMFile (CseFileName, FileOffset, Data, DataSize, Truncate);
+ } else if (Heci2Protocol != NULL) {
+ Status = Heci2WriteNVMFile (CseFileName, FileOffset, Data, DataSize, Truncate);
+ return Status;
+ } else {
+ ASSERT (FALSE);
+ }
+
+ return EFI_NOT_READY;
+}
+
+
+/**
+ Creates an empty variable store on the CSE NVM file specified.
+
+ @param[in] StoreFileName A pointer to the string representing the CSE file name containing this store.
+ @param[in] Offset The offset from the beginning of the CSE NVM file to the first byte of the store.
+ @param[out] StoreSize The size of the variable store created / found will be written to this pointer.
+
+ @retval EFI_SUCCESS The variable store was created successfully.
+ @retval Others The variable store could not be created.
+
+**/
+EFI_STATUS
+EFIAPI
+CreateCseNvmVariableStore (
+ IN CHAR8 *StoreFileName,
+ IN UINT32 Offset,
+ OUT UINTN *StoreSize
+ )
+{
+ VARIABLE_NVM_STORE_HEADER *VariableStoreHeader;
+ EFI_STATUS Status;
+
+ VariableStoreHeader = NULL;
+
+ if (StoreFileName == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check if a variable store already exists
+ //
+ Status = HeciGetNVMFileSize (StoreFileName, StoreSize);
+ if (Status == EFI_SUCCESS || (Status != EFI_NOT_FOUND && EFI_ERROR (Status))) {
+ return Status;
+ }
+ DEBUG ((EFI_D_INFO, "Could not find an existing variable store. Attempting to create a new store...\n"));
+
+ //
+ // Allocate memory for a new variable store
+ //
+ VariableStoreHeader = AllocateZeroPool (sizeof (VARIABLE_NVM_STORE_HEADER));
+ if (VariableStoreHeader == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Get an empty variable store
+ //
+ Status = CreateEmptyVariableStore (VariableStoreHeader);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Error creating an empty variable store.\n"));
+ FreePool (VariableStoreHeader);
+ return Status;
+ }
+
+ *StoreSize = (UINTN) VariableStoreHeader->Size;
+
+ //
+ // Write the variable store to the base of the store location
+ //
+ Status = UpdateCseNvmFile (StoreFileName, Offset, (UINT8 *) VariableStoreHeader, *StoreSize, FALSE, NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Error writing the new variable store to the CSE NVM file.\n"));
+ FreePool (VariableStoreHeader);
+ return Status;
+ }
+
+ FreePool (VariableStoreHeader);
+
+ DEBUG ((EFI_D_INFO, "Successfully wrote the new variable store to the CSE NVM file.\n"));
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Returns the file name for a CSE data file at the specified offset (file number).
+
+ @param[in] DataOffset The file number on CSE NVM (each data file is an "offset")
+ @param[out] CseVariableDataFileName The CSE file name.
+
+ @retval EFI_INVALID_PARAMETER A valid buffer was not passed to fill with the file name.
+ @retval EFI_SUCCESS File name was successfully created and copied to the buffer.
+
+**/
+EFI_STATUS
+EFIAPI
+BuildCseDataFileName (
+ IN UINT32 DataOffset,
+ OUT CHAR8 *CseVariableDataFileName
+ )
+{
+ UINTN CseVariableDataFileNamePrefixLength;
+ UINTN CseVariableDataFileNumberStrLength;
+ CHAR8 CseVariableDataFileNumberStrBuffer[8] = "";
+
+ if (CseVariableDataFileName == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CseVariableDataFileNumberStrLength = AsciiSPrint (CseVariableDataFileNumberStrBuffer, sizeof (CseVariableDataFileNumberStrBuffer), "%03d", DataOffset);
+
+ //
+ // Form the name of the CSE data file
+ //
+ CseVariableDataFileNamePrefixLength = AsciiStrnLenS (CSE_PRIMARY_NVM_DATA_FILE_PREFIX, sizeof (CSE_PRIMARY_NVM_DATA_FILE_PREFIX));
+
+ CopyMem (CseVariableDataFileName, CSE_PRIMARY_NVM_DATA_FILE_PREFIX, CseVariableDataFileNamePrefixLength);
+ CopyMem (CseVariableDataFileName + CseVariableDataFileNamePrefixLength, CseVariableDataFileNumberStrBuffer, CseVariableDataFileNumberStrLength + 1);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Finds deleted variables in the specified CSE NVM variable store.
+
+ If VariableName is an empty string, then we just return the first
+ qualified variable without comparing VariableName and VendorGuid.
+
+ @param[in] VariableName Name of the variable to be found.
+ @param[in] VendorGuid Vendor GUID to be found.
+ @param[in] VariableStore Pointer to a VARIABLE_NVM_STORE_HEADER structure which
+ is the variable store to search.
+ @param[in,out] VariableTrack Ptr Pointer to a variable NVM tracking structure which points
+ current pointer to the variable if found.
+
+ @retval EFI_INVALID_PARAMETER If VariableName is not an empty string, while
+ VendorGuid is NULL.
+ @retval EFI_SUCCESS Variable successfully found.
+ @retval EFI_NOT_FOUND Variable not found
+
+**/
+EFI_STATUS
+EFIAPI
+FindDeletedVariable (
+ IN CONST CHAR16 *VariableName,
+ IN CONST EFI_GUID *VendorGuid,
+ IN VARIABLE_NVM_STORE_HEADER *VariableStorePtr,
+ IN OUT VARIABLE_NVM_POINTER_TRACK *VariablePtrTrack
+ )
+{
+ EFI_STATUS Status;
+ VARIABLE_NVM_STORE_INFO VariableNvmStoreInfo;
+ VOID *VariableCandidateName;
+
+ VariablePtrTrack->InDeletedTransitionPtr = NULL;
+
+ Status = IsAuthenticatedVariableStore (VariableStorePtr, &VariableNvmStoreInfo.AuthFlag);
+
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ VariableNvmStoreInfo.VariableStoreHeader = VariableStorePtr;
+
+ //
+ // Find the variable by walking through the specified variable store
+ //
+ for (VariablePtrTrack->CurrPtr = VariablePtrTrack->StartPtr;
+ IsValidVariableHeader (VariablePtrTrack->CurrPtr, VariablePtrTrack->EndPtr);
+ VariablePtrTrack->CurrPtr = GetNextVariablePtr (&VariableNvmStoreInfo, VariablePtrTrack->CurrPtr)
+ ) {
+ if (VariablePtrTrack->CurrPtr->State != VAR_ADDED && VariablePtrTrack->CurrPtr->State != (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
+
+ //
+ // A variable name was given to find
+ //
+ if (CompareGuid (VendorGuid, &VariablePtrTrack->CurrPtr->VendorGuid)) {
+ VariableCandidateName = (VOID *)GetVariableNamePtr (VariablePtrTrack->CurrPtr, VariableNvmStoreInfo.AuthFlag);
+
+ ASSERT (NameSizeOfVariable (VariablePtrTrack->CurrPtr, VariableNvmStoreInfo.AuthFlag) != 0);
+ if (CompareMem (
+ VariableName,
+ VariableCandidateName,
+ NameSizeOfVariable (VariablePtrTrack->CurrPtr, VariableNvmStoreInfo.AuthFlag)
+ ) == 0) {
+ DEBUG ((EFI_D_INFO, "Returning with variable found at header address 0x%x\n", VariablePtrTrack->CurrPtr));
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ Finds the variable in the specified CSE NVM variable store.
+
+ If VariableName is an empty string, then we just return the first
+ qualified variable without comparing VariableName and VendorGuid.
+
+ @param[in] VariableName Name of the variable to be found.
+ @param[in] VendorGuid Vendor GUID to be found.
+ @param[in] VariableStore Pointer to a VARIABLE_NVM_STORE_HEADER structure which
+ is the variable store to search.
+ @param[in,out] VariableTrack Ptr Pointer to a variable NVM tracking structure which points
+ current pointer to the variable if found.
+
+ @retval EFI_INVALID_PARAMETER If VariableName is not an empty string, while
+ VendorGuid is NULL.
+ @retval EFI_SUCCESS Variable successfully found.
+ @retval EFI_NOT_FOUND Variable not found
+
+**/
+EFI_STATUS
+EFIAPI
+FindVariableEx (
+ IN CONST CHAR16 *VariableName,
+ IN CONST EFI_GUID *VendorGuid,
+ IN VARIABLE_NVM_STORE_HEADER *VariableStorePtr,
+ IN OUT VARIABLE_NVM_POINTER_TRACK *VariablePtrTrack
+ )
+{
+ EFI_STATUS Status;
+ VARIABLE_NVM_HEADER *InDeletedTransitionVariable;
+ VARIABLE_NVM_STORE_INFO VariableNvmStoreInfo;
+ VOID *VariableCandidateName;
+
+ InDeletedTransitionVariable = NULL;
+ VariablePtrTrack->InDeletedTransitionPtr = NULL;
+
+ Status = IsAuthenticatedVariableStore (VariableStorePtr, &VariableNvmStoreInfo.AuthFlag);
+
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ VariableNvmStoreInfo.VariableStoreHeader = VariableStorePtr;
+
+ //
+ // Find the variable by walking through the specified variable store
+ //
+ for (VariablePtrTrack->CurrPtr = VariablePtrTrack->StartPtr;
+ IsValidVariableHeader (VariablePtrTrack->CurrPtr, VariablePtrTrack->EndPtr);
+ VariablePtrTrack->CurrPtr = GetNextVariablePtr (&VariableNvmStoreInfo, VariablePtrTrack->CurrPtr)
+ ) {
+ if (VariablePtrTrack->CurrPtr->State == VAR_ADDED ||
+ VariablePtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)
+ ) {
+
+ if (VariableName[0] == 0) {
+ DEBUG ((EFI_D_INFO, "The variable has been requested to be deleted.\n"));
+ //
+ // The variable has been requested to be deleted
+ //
+ if (VariablePtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
+ InDeletedTransitionVariable = VariablePtrTrack->CurrPtr;
+ } else {
+ VariablePtrTrack->InDeletedTransitionPtr = InDeletedTransitionVariable;
+ return EFI_SUCCESS;
+ }
+ } else {
+ //
+ // A variable name was given to find
+ //
+ if (CompareGuid (VendorGuid, &VariablePtrTrack->CurrPtr->VendorGuid)) {
+ VariableCandidateName = (VOID *) GetVariableNamePtr (VariablePtrTrack->CurrPtr, VariableNvmStoreInfo.AuthFlag);
+
+ ASSERT (NameSizeOfVariable (VariablePtrTrack->CurrPtr, VariableNvmStoreInfo.AuthFlag) != 0);
+ if (CompareMem (VariableName, VariableCandidateName,
+ NameSizeOfVariable (VariablePtrTrack->CurrPtr, VariableNvmStoreInfo.AuthFlag)) == 0) {
+ if (VariablePtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
+ InDeletedTransitionVariable = VariablePtrTrack->CurrPtr;
+ } else {
+ VariablePtrTrack->InDeletedTransitionPtr = InDeletedTransitionVariable;
+ DEBUG ((EFI_D_INFO, "Returning with variable found at header address 0x%x\n", VariablePtrTrack->CurrPtr));
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ VariablePtrTrack->CurrPtr = InDeletedTransitionVariable;
+
+ return (VariablePtrTrack->CurrPtr == NULL) ? EFI_NOT_FOUND : EFI_SUCCESS;
+}
+
+
+/**
+ Finds the variable in CSE NVM.
+ This code finds the variable in the CSE NVM variable stores enabled.
+
+ If VariableName is an empty string, then we just return the first
+ qualified variable without comparing VariableName and VendorGuid.
+
+ @param[in] VariableName Name of the variable to be found.
+ @param[in] VendorGuid Vendor GUID to be found.
+ @param[in] CseVariableFileInfo A pointer to a structure that contains information the CSE files available.
+ @param[out] PtrTrack VARIABLE_NVM POINTER_TRACK structure for output,
+ including the range searched and the target position.
+
+ @retval EFI_INVALID_PARAMETER If VariableName is not an empty string, while
+ VendorGuid is NULL.
+ @retval EFI_SUCCESS Variable successfully found.
+ @retval EFI_NOT_FOUND Variable not found
+
+**/
+EFI_STATUS
+EFIAPI
+FindVariable (
+ IN CONST CHAR16 *VariableName,
+ IN CONST EFI_GUID *VendorGuid,
+ IN CONST CSE_VARIABLE_FILE_INFO **CseVariableFileInfo,
+ OUT VARIABLE_NVM_POINTER_TRACK *VariablePtrTrack
+ )
+{
+ EFI_STATUS Status;
+ CSE_VARIABLE_FILE_TYPE Type;
+ VARIABLE_NVM_STORE_HEADER *VariableStoreHeader;
+
+ if (VariableName[0] != 0 && VendorGuid == NULL) {
+ DEBUG ((EFI_D_ERROR, "VariableName and VendorGuid passed to FindVariable() are invalid.\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Determine the CSE store file type for this variable
+ //
+ Type = GetCseVariableStoreFileType (VariableName, VendorGuid, CseVariableFileInfo);
+
+ if (CseVariableFileInfo[Type] == NULL || !CseVariableFileInfo[Type]->FileStoreEstablished) {
+ DEBUG ((EFI_D_ERROR, "The variable store needed is not available for this variable. Variable store type = %d\n", (UINT32)Type));
+ return EFI_NOT_FOUND;
+ }
+
+ VariableStoreHeader = (VARIABLE_NVM_STORE_HEADER *) (UINTN) CseVariableFileInfo[Type]->HeaderRegionBase;
+
+ DEBUG ((EFI_D_INFO, "VariableStoreHeader Region Base in FindVariable() = 0x%x\n", VariableStoreHeader));
+
+ VariablePtrTrack->CurrPtr = NULL;
+ VariablePtrTrack->StartPtr = GetStartPointer (VariableStoreHeader);
+ VariablePtrTrack->EndPtr = GetEndPointer (VariableStoreHeader);
+
+ //
+ // Do not search in this variable store if it is empty
+ //
+ if (VariableStoreHeader->VariableHeaderTotalEntries == 0 || !IsValidVariableHeader (VariablePtrTrack->StartPtr, VariablePtrTrack->EndPtr)) {
+ DEBUG ((EFI_D_INFO, "Variable store %d is empty, not searching.\n", (UINT32) Type));
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Find the variable by searching in the variable header region of the store
+ //
+ Status = FindVariableEx (VariableName, VendorGuid, VariableStoreHeader, VariablePtrTrack);
+ if (!EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, "Found the variable\n"));
+ return Status;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ Returns the next available variable in the given CSE variable stores.
+
+ @param[in] VariableName Pointer to variable name.
+ @param[in] VendorGuid Variable Vendor Guid.
+ @param[in] CseVariableFileInfo A pointer to a structure that contains information the CSE files available.
+ @param[out] VariablePtr Pointer to variable header address.
+ @param[out] IsAuthVariable Indicates if the variable returned is an authenticated variable.
+
+ @return EFI_SUCCESS Found the specified variable.
+ @return EFI_NOT_FOUND Not found.
+
+**/
+EFI_STATUS
+EFIAPI
+GetNextCseVariableName (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VariableGuid,
+ IN CSE_VARIABLE_FILE_INFO **CseVariableFileInfo,
+ OUT VARIABLE_NVM_HEADER **VariablePtr,
+ OUT BOOLEAN *IsAuthVariable
+ )
+{
+ CSE_VARIABLE_FILE_TYPE Type;
+ EFI_STATUS Status;
+ VARIABLE_NVM_POINTER_TRACK Variable;
+ VARIABLE_NVM_POINTER_TRACK VariablePtrTrack;
+ VARIABLE_NVM_STORE_INFO StoreInfo[CseVariableFileTypeMax];
+
+ //
+ // In the case of a NULL variable name, FindVariable will return the first
+ // variable in the appropriate CSE file store. It is recommended to make
+ // a special case for the name NULL that returns the first CSE variable file
+ // store type (currently implemented in CseVariableStorageSelectorLib).
+ //
+ Status = FindVariable (VariableName, VariableGuid, CseVariableFileInfo, &Variable);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ } else if (Variable.CurrPtr == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Initialize the CSE store info structures
+ //
+ for (Type = (CSE_VARIABLE_FILE_TYPE) 0; Type < CseVariableFileTypeMax; Type++) {
+ if (CseVariableFileInfo[Type] == NULL || !CseVariableFileInfo[Type]->FileStoreEstablished) {
+ StoreInfo[Type].AuthFlag = FALSE;
+ StoreInfo[Type].VariableStoreHeader = NULL;
+ } else {
+ StoreInfo[Type].VariableStoreHeader = (VARIABLE_NVM_STORE_HEADER *) (UINTN) CseVariableFileInfo[Type]->HeaderRegionBase;
+ Status = IsAuthenticatedVariableStore (StoreInfo[Type].VariableStoreHeader, &StoreInfo[Type].AuthFlag);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+ }
+ DEBUG ((EFI_D_INFO,
+ "Init StoreInfo[%d] to: AuthFlag=%c, StoreHeader = 0x%x\n",
+ (UINT32) Type,
+ ((StoreInfo[Type].AuthFlag) ? 'T' : 'F'),
+ StoreInfo[Type].VariableStoreHeader)
+ );
+ }
+
+ //
+ // Find which CSE store the current variable is in,
+ // and get the next variable if the variable given
+ // was valid.
+ //
+ for (Type = (CSE_VARIABLE_FILE_TYPE) 0; Type < CseVariableFileTypeMax; Type++) {
+ if ((StoreInfo[Type].VariableStoreHeader != NULL) && (Variable.StartPtr == GetStartPointer (StoreInfo[Type].VariableStoreHeader))) {
+ DEBUG ((EFI_D_INFO, "Found current variable in CSE file type %d.\n", (UINT32) Type));
+ if (VariableName[0] != 0) {
+ Variable.CurrPtr = GetNextVariablePtr (&StoreInfo[Type], Variable.CurrPtr);
+ }
+ break;
+ }
+ }
+
+ while (TRUE) {
+ while (!IsValidVariableHeader (Variable.CurrPtr, Variable.EndPtr)) {
+ //
+ // Find a new valid CSE variable file store
+ //
+ for (Type = (CSE_VARIABLE_FILE_TYPE) 0; Type < CseVariableFileTypeMax; Type++) {
+ if ((StoreInfo[Type].VariableStoreHeader != NULL) && (Variable.StartPtr == GetStartPointer (StoreInfo[Type].VariableStoreHeader))) {
+ DEBUG ((EFI_D_INFO, "New CSE variable file store type is %d.\n", (UINT32) Type));
+ break;
+ }
+ }
+
+ ASSERT (Type < CseVariableFileTypeMax);
+
+ //
+ // Switch to the next CSE variable file store
+ //
+ for (Type++; Type < CseVariableFileTypeMax; Type++) {
+ if (StoreInfo[Type].VariableStoreHeader != NULL) {
+ DEBUG ((EFI_D_INFO, "Next store type in search is %d. Header at 0x%x\n", (UINT32) Type, StoreInfo[Type].VariableStoreHeader));
+ break;
+ }
+ }
+
+ //
+ // Check if the CSE variable file stores available have
+ // been exhausted and return not found if so.
+ //
+ if (Type == CseVariableFileTypeMax) {
+ return EFI_NOT_FOUND;
+ }
+
+ Variable.StartPtr = GetStartPointer (StoreInfo[Type].VariableStoreHeader);
+ Variable.EndPtr = GetEndPointer (StoreInfo[Type].VariableStoreHeader);
+ Variable.CurrPtr = Variable.StartPtr;
+ }
+
+ if (Type == CseVariableFileTypeMax) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // A valid variable was found
+ //
+ if (Variable.CurrPtr->State == VAR_ADDED || Variable.CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
+ if (Variable.CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
+ //
+ // If the variable is IN_DELETED_TRANSITION and there is
+ // also the same variable with the ADDED attribute, don't
+ // return it.
+ //
+ VariablePtrTrack.StartPtr = Variable.StartPtr;
+ VariablePtrTrack.EndPtr = Variable.EndPtr;
+
+ Status = FindVariableEx (
+ GetVariableNamePtr (Variable.CurrPtr, StoreInfo[Type].AuthFlag),
+ GetVendorGuidPtr (Variable.CurrPtr, StoreInfo[Type].AuthFlag),
+ StoreInfo[Type].VariableStoreHeader,
+ &VariablePtrTrack
+ );
+ if (!EFI_ERROR (Status) && VariablePtrTrack.CurrPtr->State == VAR_ADDED) {
+ Variable.CurrPtr = GetNextVariablePtr (&StoreInfo[Type], Variable.CurrPtr);
+ continue;
+ }
+ }
+
+ DEBUG ((EFI_D_INFO, "Found next variable. Variable header at 0x%x. StoreInfo for type %d at 0x%x\n", Variable.CurrPtr, (UINT32) Type, &StoreInfo[Type]));
+
+ *VariablePtr = Variable.CurrPtr;
+ *IsAuthVariable = StoreInfo[Type].AuthFlag;
+
+ return EFI_SUCCESS;
+ }
+
+ Variable.CurrPtr = GetNextVariablePtr (&StoreInfo[Type], Variable.CurrPtr);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Retrieves a variable's value using its name and GUID.
+
+ Read the specified variable from the CSE NVM variable store. If the Data
+ buffer is too small to hold the contents of the variable,
+ the error EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the
+ required buffer size to obtain the data.
+
+ Note: It is the caller's responsibility to extensively validate the input parameters.
+
+ @param[in] CseVariableFileInfo A pointer to an array of structures that contains information the CSE files available.
+ @param[in] VariableName A pointer to a null-terminated string that is the variable's name.
+ @param[in] VariableGuid A pointer to an EFI_GUID that is the variable's GUID. The combination of
+ VariableGuid and VariableName must be unique.
+ @param[out] Attributes If non-NULL, on return, points to the variable's attributes.
+ @param[in, out] DataSize On entry, points to the size in bytes of the Data buffer.
+ On return, points to the size of the data returned in Data.
+ @param[out] Data Points to the buffer which will hold the returned variable value.
+ @param[out] VariableHeader A pointer to the variable header.
+
+ @retval EFI_SUCCESS The variable was read successfully.
+ @retval EFI_NOT_FOUND The variable could not be found.
+ @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the resulting data.
+ DataSize is updated with the size required for
+ the specified variable.
+ @retval EFI_INVALID_PARAMETER VariableName, VariableGuid, DataSize or Data is NULL.
+ @retval EFI_DEVICE_ERROR The variable could not be retrieved because of a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+GetCseVariable (
+ IN CONST CSE_VARIABLE_FILE_INFO **CseVariableFileInfo,
+ IN CONST CHAR16 *VariableName,
+ IN CONST EFI_GUID *VariableGuid,
+ OUT UINT32 *Attributes OPTIONAL,
+ IN OUT UINTN *DataSize,
+ OUT VOID *Data,
+ OUT VARIABLE_NVM_HEADER *VariableHeader OPTIONAL
+ )
+{
+ CHAR8 CseVariableDataFileName[CSE_MAX_NVM_FILE_NAME_LENGTH];
+ CSE_VARIABLE_HECI_PROTOCOL HeciProtocolSelector;
+ CSE_VARIABLE_FILE_TYPE VariableCseFileType;
+ UINTN VariableDataSize;
+ UINT32 VariableBaseFileOffset;
+ VARIABLE_NVM_STORE_INFO VariableNvmStoreInfo;
+ VARIABLE_NVM_POINTER_TRACK VariablePtrTrack;
+ EFI_STATUS Status;
+
+ if (VariableName == NULL || VariableGuid == NULL || DataSize == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ VariableCseFileType = GetCseVariableStoreFileType (VariableName, VariableGuid, CseVariableFileInfo);
+
+ DEBUG ((EFI_D_INFO, "FileStoreEstablished = %c\n", (CseVariableFileInfo[VariableCseFileType]->FileStoreEstablished) ? 'T' : 'F'));
+
+ if (CseVariableFileInfo[VariableCseFileType] == NULL || !CseVariableFileInfo[VariableCseFileType]->FileStoreEstablished) {
+ DEBUG ((EFI_D_ERROR, "Variable store not available for this variable. Store type = %d\n", (UINT32) VariableCseFileType));
+ return EFI_NOT_FOUND;
+ }
+
+ VariableNvmStoreInfo.VariableStoreHeader = (VARIABLE_NVM_STORE_HEADER *) (UINTN) CseVariableFileInfo[VariableCseFileType]->HeaderRegionBase;
+
+ Status = IsAuthenticatedVariableStore (VariableNvmStoreInfo.VariableStoreHeader, &VariableNvmStoreInfo.AuthFlag);
+
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ Status = FindVariable (VariableName, VariableGuid, CseVariableFileInfo, &VariablePtrTrack);
+ if (EFI_ERROR (Status) || VariablePtrTrack.CurrPtr == NULL) {
+ DEBUG ((EFI_D_ERROR, "Could not find variable or error finding variable.\n"));
+ return Status;
+ }
+
+ VariableDataSize = DataSizeOfVariable (VariablePtrTrack.CurrPtr, VariableNvmStoreInfo.AuthFlag);
+
+ ASSERT (VariableDataSize != 0);
+
+ if (*DataSize < VariableDataSize) {
+ DEBUG ((EFI_D_ERROR, "Buffer passed to GetVariable() is too small.\n"));
+ *DataSize = VariableDataSize;
+ return EFI_BUFFER_TOO_SMALL;
+ } else {
+ if (Data == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ *DataSize = VariableDataSize;
+
+ if (Attributes != NULL) {
+ *Attributes = VariablePtrTrack.CurrPtr->Attributes;
+ }
+
+ Status = GetCseVariableStoreFileOffset (VariableCseFileType, &VariableBaseFileOffset);
+ ASSERT_EFI_ERROR (Status);
+
+ if (VariableHeader != NULL) {
+ VariableHeader = VariablePtrTrack.CurrPtr;
+ }
+
+ //
+ // Read the data from the CSE NVM file
+ //
+ if (VariableCseFileType == CseVariableFileTypePreMemoryFile) {
+ DEBUG ((EFI_D_INFO, "Variable is being read from the CSE mrc_trg_data file.\n"));
+
+ Status = ReadCseNvmFile (
+ CseVariableFileInfo[VariableCseFileType]->FileName,
+ VariableBaseFileOffset + VariablePtrTrack.CurrPtr->DataOffset,
+ Data,
+ DataSize,
+ NULL
+ );
+ ASSERT (*DataSize == DataSizeOfVariable (VariablePtrTrack.CurrPtr, VariableNvmStoreInfo.AuthFlag));
+ return Status;
+ } else if (VariableCseFileType == CseVariableFileTypePrimaryIndexFile) {
+
+ DEBUG ((EFI_D_INFO, "Variable is being read from primary CSE NVM storage.\n"));
+ ZeroMem (&CseVariableDataFileName[0], CSE_MAX_NVM_FILE_NAME_LENGTH);
+ Status = BuildCseDataFileName (VariablePtrTrack.CurrPtr->DataOffset, &CseVariableDataFileName[0]);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Error building the CSE NVM data file name.\n"));
+ return Status;
+ }
+ DEBUG ((EFI_D_INFO, "CSE NVM Data Filename: %a\n", &CseVariableDataFileName[0]));
+
+ HeciProtocolSelector = GetCseVariableHeciProtocol (VariableName, VariableGuid);
+
+ Status = ReadCseNvmFile (&CseVariableDataFileName[0], VariableBaseFileOffset, Data, DataSize, &HeciProtocolSelector);
+ ASSERT (*DataSize == DataSizeOfVariable (VariablePtrTrack.CurrPtr, VariableNvmStoreInfo.AuthFlag));
+
+ return Status;
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/BaseCseVariableStorageLib/BaseCseVariableStorageLib.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/BaseCseVariableStorageLib/BaseCseVariableStorageLib.inf
new file mode 100644
index 0000000000..29695598da
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/BaseCseVariableStorageLib/BaseCseVariableStorageLib.inf
@@ -0,0 +1,59 @@
+## @file
+# CSE Variable Storage Library
+#
+# Provides access to CSE-managed NVM for variable storage.
+#
+# Copyright (c) 2016, 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 = BaseCseVariableStorageLib
+ FILE_GUID = 929FB413-A173-46CD-ABA1-F45699C8AC69
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = CseVariableStorageLib
+
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ BaseCseVariableStorageLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ BroxtonSiPkg/BroxtonSiPkg.dec
+ BroxtonSiPkg/BroxtonSiPrivate.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ CseVariableStorageSelectorLib
+ DebugLib
+ HeciMsgLib
+ HobLib
+ MemoryAllocationLib
+ PcdLib
+ PrintLib
+ VariableNvmStorageLib
+
+[Guids]
+ gCsePreMemoryIndexFileDataHobGuid ## CONSUMES ## GUID
+ gCsePrimaryIndexFileDataHobGuid ## CONSUMES ## GUID
+ gEfiAuthenticatedVariableGuid ## CONSUMES ## GUID
+
+
+[Pcd]
+ gSiPkgTokenSpaceGuid.PcdEnableCseMrcTrainingDataVariables ## CONSUMES
+ gSiPkgTokenSpaceGuid.PcdPrimaryCseNvmStoreIndexFileName ## CONSUMES
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/DxeSmmCseVariableStorageSelectorLib/CseVariableStorageSelectorLib.c b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/DxeSmmCseVariableStorageSelectorLib/CseVariableStorageSelectorLib.c
new file mode 100644
index 0000000000..09e6d68423
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/DxeSmmCseVariableStorageSelectorLib/CseVariableStorageSelectorLib.c
@@ -0,0 +1,177 @@
+/** @file
+ DXE SMM CSE Variable Storage Selector Library.
+
+ Copyright (c) 2016, 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 "CseVariableStorageSelectorLibInternal.h"
+
+EFI_HECI_PROTOCOL *mHeci2Protocol = NULL;
+
+/**
+ Returns the CSE NVM file used for the requested variable.
+
+ @param[in] VariableName Name of the variable.
+ @param[in] VendorGuid Guid of the variable.
+ @param[in] CseVariableFileInfo An array of pointers to CSE
+ variable file information.
+
+ @return The type of CSE NVM file used for this variable.
+
+**/
+CSE_VARIABLE_FILE_TYPE
+EFIAPI
+GetCseVariableStoreFileType (
+ IN CONST CHAR16 *VariableName,
+ IN CONST EFI_GUID *VendorGuid,
+ IN CONST CSE_VARIABLE_FILE_INFO **CseVariableFileInfo
+ )
+{
+ CSE_VARIABLE_FILE_TYPE Type;
+
+ if (VariableName[0] == 0) {
+ //
+ // Return the first available CSE file store
+ //
+ DEBUG ((EFI_D_INFO, "CseVariableStorageSelectorLib - Variable name is NULL\n"));
+ for (Type = (CSE_VARIABLE_FILE_TYPE) 0; Type < CseVariableFileTypeMax; Type++) {
+ if (CseVariableFileInfo[Type]->FileEnabled) {
+ return Type;
+ }
+ }
+ //
+ // There should always be at least one CSE file store enabled
+ //
+ ASSERT (FALSE);
+ return (CSE_VARIABLE_FILE_TYPE) 0;
+ } else if ((StrCmp (VariableName, L"Setup") == 0) &&
+ CompareGuid (VendorGuid, &gEfiSetupVariableGuid)) {
+ //
+ // Setup variable is stored in the MRC training data file
+ // if it is enabled.
+ //
+ DEBUG ((EFI_D_INFO, "CseVariableStorageSelectorLib - Variable is Setup\n"));
+ return (CseVariableFileInfo[CseVariableFileTypePreMemoryFile]->FileEnabled ?
+ CseVariableFileTypePreMemoryFile :
+ CseVariableFileTypePrimaryIndexFile
+ );
+ } else if ((StrCmp (VariableName, L"MemoryConfig") == 0 || StrCmp (VariableName, L"MemoryBootData") == 0) &&
+ CompareGuid (VendorGuid, &gEfiMemoryConfigVariableGuid)) {
+ //
+ // Memory configuration data is preferred to be stored in
+ // the MRC training data file.
+ //
+ DEBUG ((EFI_D_INFO, "CseVariableStorageSelectorLib - Variable is MemoryConfig\n"));
+ return (CseVariableFileInfo[CseVariableFileTypePreMemoryFile]->FileEnabled ?
+ CseVariableFileTypePreMemoryFile :
+ CseVariableFileTypePrimaryIndexFile
+ );
+ } else {
+ //
+ // All other variables are stored in individual CSE files
+ //
+ DEBUG ((EFI_D_INFO, "CseVariableStorageSelectorLib - Variable is not Setup\n"));
+ return CseVariableFileTypePrimaryIndexFile;
+ }
+}
+
+
+/**
+ Returns the base offset for variable services in the CSE NVM file
+ specified for this file type.
+
+ @param[in] CseVariableFileType The type of the CSE NVM file.
+
+ @param[out] CseFileOffset The offset to base a variable store
+ in the CSE file for this variable.
+
+ @retval EFI_SUCCESS Offset successfully returned for the variable.
+ @retval Others An error occurred.
+
+**/
+EFI_STATUS
+EFIAPI
+GetCseVariableStoreFileOffset (
+ IN CSE_VARIABLE_FILE_TYPE CseVariableFileType,
+ OUT UINT32 *CseFileOffset
+ )
+{
+ if (CseFileOffset == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ switch (CseVariableFileType) {
+ case CseVariableFileTypePreMemoryFile:
+ *CseFileOffset = CSE_PRE_MEMORY_FILE_STORE_OFFSET;
+ break;
+
+ case CseVariableFileTypePrimaryIndexFile:
+ *CseFileOffset = CSE_PRIMARY_NVM_FILE_STORE_OFFSET;
+ break;
+
+ default:
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Returns the HECI protocol used to access the CSE NVM file based on the current point in the boot.
+
+ @param[out] HeciProtocol A pointer to the HECI2 protocol if it is active.
+ If HECI1 is active, the value is NULL.
+
+ @return CSE_VARIABLE_HECI_PROTOCOL The HECI protocol to currently use.
+
+**/
+CSE_VARIABLE_HECI_PROTOCOL
+EFIAPI
+GetCseHeciProtocol (
+ OUT EFI_HECI_PROTOCOL **Heci2Protocol
+ )
+{
+ *Heci2Protocol = mHeci2Protocol;
+
+ return (*Heci2Protocol == NULL) ? CseVariableHeci1Protocol : CseVariableHeci2Protocol;
+}
+
+
+/**
+ Returns the HECI protocol used to access the CSE NVM file based on a given varaible.
+
+ @param[in] VariableName Name of the variable.
+ @param[in] VendorGuid Guid of the variable.
+
+ @return CSE_VARIABLE_HECI_PROTOCOL The HECI protocol to currently use.
+
+**/
+CSE_VARIABLE_HECI_PROTOCOL
+EFIAPI
+GetCseVariableHeciProtocol (
+ IN CONST CHAR16 *VariableName,
+ IN CONST EFI_GUID *VendorGuid
+ )
+{
+ EFI_HECI_PROTOCOL *HeciProtocol;
+ CSE_VARIABLE_HECI_PROTOCOL HeciProtocolSelector;
+
+ //
+ // Custom logic can be added here to choose an appropriate HECI protocol
+ //
+
+ HeciProtocolSelector = GetCseHeciProtocol (&HeciProtocol);
+
+ return HeciProtocolSelector;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/DxeSmmCseVariableStorageSelectorLib/CseVariableStorageSelectorLibInternal.h b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/DxeSmmCseVariableStorageSelectorLib/CseVariableStorageSelectorLibInternal.h
new file mode 100644
index 0000000000..c3fc85f386
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/DxeSmmCseVariableStorageSelectorLib/CseVariableStorageSelectorLibInternal.h
@@ -0,0 +1,27 @@
+/** @file
+ DXE SMM CSE Variable Storage Selector Library.
+
+ Copyright (c) 2016, 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 _CSE_VARIABLE_STORAGE_SELECTOR_LIB_INTERNAL_H_
+#define _CSE_VARIABLE_STORAGE_SELECTOR_LIB_INTERNAL_H_
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/CseVariableStorageSelectorLib.h>
+#include <Library/DebugLib.h>
+
+extern EFI_HECI_PROTOCOL *mHeci2Protocol;
+
+#endif
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/DxeSmmCseVariableStorageSelectorLib/DxeCseVariableStorageSelectorLib.c b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/DxeSmmCseVariableStorageSelectorLib/DxeCseVariableStorageSelectorLib.c
new file mode 100644
index 0000000000..af07c8dfc5
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/DxeSmmCseVariableStorageSelectorLib/DxeCseVariableStorageSelectorLib.c
@@ -0,0 +1,113 @@
+/** @file
+ DXE CSE Variable Storage Selector Library.
+
+ Copyright (c) 2016, 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 "CseVariableStorageSelectorLibInternal.h"
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+
+/**
+ Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
+
+ This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
+ It converts pointers to a new virtual address.
+
+ @param[in] Event Event whose notification function is being invoked.
+ @param[in] Context Pointer to the notification function's context.
+
+**/
+VOID
+EFIAPI
+CseVariableStorageSelectorAddressChangeEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ gRT->ConvertPointer (0, (VOID **) &mHeci2Protocol);
+ gBS->CloseEvent (Event);
+}
+
+
+VOID
+EFIAPI
+CseVariableStorageSelectorEndOfDxeNotification (
+ IN EFI_EVENT Event,
+ IN VOID* Context
+ )
+{
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO, "CseVariableStorageSelectorLib: End of DXE event.\n"));
+ Status = gBS->LocateProtocol (
+ &gEfiHeciSmmRuntimeProtocolGuid,
+ NULL,
+ &mHeci2Protocol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ gBS->CloseEvent (Event);
+}
+
+
+/**
+ The library constructor.
+
+ @param[in] ImageHandle The firmware allocated handle for the UEFI image.
+ @param[in] SystemTable A pointer to the EFI system table.
+
+ @retval EFI_SUCCESS The function always return EFI_SUCCESS for now.
+ It will ASSERT on error for debug version.
+ @retval EFI_ERROR Please reference LocateProtocol for error code details.
+
+**/
+EFI_STATUS
+EFIAPI
+CseVariableStorageLibInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_EVENT Event;
+ EFI_STATUS Status;
+
+ //
+ // Create the End of DXE event
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ CseVariableStorageSelectorEndOfDxeNotification,
+ NULL,
+ &gEfiEndOfDxeEventGroupGuid,
+ &Event
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Register the virtual address change event
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ CseVariableStorageSelectorAddressChangeEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &Event
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/DxeSmmCseVariableStorageSelectorLib/DxeCseVariableStorageSelectorLib.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/DxeSmmCseVariableStorageSelectorLib/DxeCseVariableStorageSelectorLib.inf
new file mode 100644
index 0000000000..b2127a7900
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/DxeSmmCseVariableStorageSelectorLib/DxeCseVariableStorageSelectorLib.inf
@@ -0,0 +1,55 @@
+## @file
+# DXE CSE Variable Storage Selector Library.
+#
+# Determines which CSE resources to consume in DXE.
+# Example: HECI1 or HECI2.
+#
+# Copyright (c) 2016, 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 = DxeCseVariableStorageSelectorLib
+ FILE_GUID = 722C417A-AC90-4A90-B183-82926A2EBD34
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = CseVariableStorageSelectorLib|DXE_DRIVER DXE_SMM_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION
+ CONSTRUCTOR = CseVariableStorageLibInit
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ CseVariableStorageSelectorLib.c
+ DxeCseVariableStorageSelectorLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ BroxtonSiPkg/BroxtonSiPkg.dec
+ BroxtonSiPkg/BroxtonSiPrivate.dec
+
+[Protocols]
+ gEfiHeciSmmRuntimeProtocolGuid
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ CseVariableStorageLib
+ DebugLib
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+
+[Guids]
+ gEfiEndOfDxeEventGroupGuid
+ gEfiEventVirtualAddressChangeGuid
+ gEfiMemoryConfigVariableGuid
+ gEfiSetupVariableGuid
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/DxeSmmCseVariableStorageSelectorLib/SmmCseVariableStorageSelectorLib.c b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/DxeSmmCseVariableStorageSelectorLib/SmmCseVariableStorageSelectorLib.c
new file mode 100644
index 0000000000..fbe6dca918
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/DxeSmmCseVariableStorageSelectorLib/SmmCseVariableStorageSelectorLib.c
@@ -0,0 +1,69 @@
+/** @file
+ SMM CSE Variable Storage Selector Library.
+
+ Copyright (c) 2016, 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 "CseVariableStorageSelectorLibInternal.h"
+#include <Library/SmmServicesTableLib.h>
+
+
+EFI_STATUS
+EFIAPI
+CseVariableStorageSelectorSmmEndOfDxeNotification (
+ IN CONST EFI_GUID *Protocol,
+ IN VOID *Interface,
+ IN EFI_HANDLE Handle
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gSmst->SmmLocateProtocol (&gEfiHeciSmmProtocolGuid, NULL, (VOID **) &mHeci2Protocol);
+
+ ASSERT_EFI_ERROR (Status);
+ DEBUG ((DEBUG_INFO, "HECI2 protocol found at 0x%x.\n", mHeci2Protocol));
+
+ return Status;
+}
+
+
+/**
+ The library constructor.
+
+ @param[in] ImageHandle The firmware allocated handle for the UEFI image.
+ @param[in] SystemTable A pointer to the EFI system table.
+
+ @retval EFI_SUCCESS The function always return EFI_SUCCESS for now.
+ It will ASSERT on error for debug version.
+ @retval EFI_ERROR Please reference LocateProtocol for error code details.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmCseVariableStorageLibInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ VOID *SmmEndOfDxeRegistration;
+
+ Status = gSmst->SmmRegisterProtocolNotify (
+ &gEfiSmmEndOfDxeProtocolGuid,
+ CseVariableStorageSelectorSmmEndOfDxeNotification,
+ &SmmEndOfDxeRegistration
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/DxeSmmCseVariableStorageSelectorLib/SmmCseVariableStorageSelectorLib.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/DxeSmmCseVariableStorageSelectorLib/SmmCseVariableStorageSelectorLib.inf
new file mode 100644
index 0000000000..5956383d43
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/DxeSmmCseVariableStorageSelectorLib/SmmCseVariableStorageSelectorLib.inf
@@ -0,0 +1,54 @@
+## @file
+# SMM CSE Variable Storage Selector Library
+#
+# Determines which CSE resources to consume in SMM.
+# Example: HECI1 or HECI2.
+#
+# Copyright (c) 2016, 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 = SmmCseVariableStorageSelectorLib
+ FILE_GUID = 722C417A-AC90-4A90-B183-82926A2EBD34
+ MODULE_TYPE = DXE_SMM_DRIVER
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x0001000A
+ LIBRARY_CLASS = CseVariableStorageSelectorLib
+ CONSTRUCTOR = SmmCseVariableStorageLibInit
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ CseVariableStorageSelectorLib.c
+ SmmCseVariableStorageSelectorLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ BroxtonSiPkg/BroxtonSiPkg.dec
+ BroxtonSiPkg/BroxtonSiPrivate.dec
+
+[Protocols]
+ gEfiHeciSmmProtocolGuid
+ gEfiSmmEndOfDxeProtocolGuid
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ CseVariableStorageLib
+ DebugLib
+ SmmServicesTableLib
+
+[Guids]
+ gEfiMemoryConfigVariableGuid
+ gEfiSetupVariableGuid
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/PeiCseVariableStorageSelectorLib/PeiCseVariableStorageSelectorLib.c b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/PeiCseVariableStorageSelectorLib/PeiCseVariableStorageSelectorLib.c
new file mode 100644
index 0000000000..cee10eae56
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/PeiCseVariableStorageSelectorLib/PeiCseVariableStorageSelectorLib.c
@@ -0,0 +1,165 @@
+/** @file
+ PEI CSE Variable Storage Selector Library.
+
+ Copyright (c) 2016, 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 <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/CseVariableStorageSelectorLib.h>
+#include <Library/DebugLib.h>
+
+/**
+ Returns the CSE NVM file used for the requested variable.
+
+ @param[in] VariableName Name of the variable.
+ @param[in] VendorGuid Guid of the variable.
+ @param[in] CseVariableFileInfo An array of pointers to CSE
+ variable file information.
+
+ @return The type of CSE NVM file used for this variable.
+
+**/
+CSE_VARIABLE_FILE_TYPE
+EFIAPI
+GetCseVariableStoreFileType (
+ IN CONST CHAR16 *VariableName,
+ IN CONST EFI_GUID *VendorGuid,
+ IN CONST CSE_VARIABLE_FILE_INFO **CseVariableFileInfo
+ )
+{
+ CSE_VARIABLE_FILE_TYPE Type;
+
+ if (VariableName[0] == 0) {
+ //
+ // Return the first available CSE file store
+ //
+ for (Type = (CSE_VARIABLE_FILE_TYPE) 0; Type < CseVariableFileTypeMax; Type++) {
+ if (CseVariableFileInfo[Type]->FileEnabled) {
+ return Type;
+ }
+ }
+ //
+ // There should always be at least one CSE file store enabled
+ //
+ ASSERT (FALSE);
+ return (CSE_VARIABLE_FILE_TYPE) 0;
+ } else if ((StrCmp (VariableName, L"Setup") == 0) &&
+ CompareGuid (VendorGuid, &gEfiSetupVariableGuid)) {
+ //
+ // Setup variable is stored in the MRC training data file
+ // if it is enabled.
+ //
+ return (CseVariableFileInfo[CseVariableFileTypePreMemoryFile]->FileEnabled ?
+ CseVariableFileTypePreMemoryFile :
+ CseVariableFileTypePrimaryIndexFile
+ );
+ } else if ((StrCmp (VariableName, L"MemoryConfig") == 0 || StrCmp (VariableName, L"MemoryBootData") == 0) &&
+ CompareGuid (VendorGuid, &gEfiMemoryConfigVariableGuid)) {
+ //
+ // Memory configuration data is preferred to be stored in
+ // the MRC training data file.
+ //
+ return (CseVariableFileInfo[CseVariableFileTypePreMemoryFile]->FileEnabled ?
+ CseVariableFileTypePreMemoryFile :
+ CseVariableFileTypePrimaryIndexFile
+ );
+ } else {
+ //
+ // All other variables are stored in individual CSE files
+ //
+ return CseVariableFileTypePrimaryIndexFile;
+ }
+}
+
+
+/**
+ Returns the base offset for variable services in the CSE NVM file
+ specified for this file type.
+
+ @param[in] CseVariableFileType The type of the CSE NVM file.
+
+ @param[out] CseFileOffset The offset to base a variable store
+ in the CSE file for this variable.
+
+ @retval EFI_SUCCESS Offset successfully returned for the variable.
+ @retval Others An error occurred.
+
+**/
+EFI_STATUS
+EFIAPI
+GetCseVariableStoreFileOffset (
+ IN CSE_VARIABLE_FILE_TYPE CseVariableFileType,
+ OUT UINT32 *CseFileOffset
+ )
+{
+ if (CseFileOffset == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ switch (CseVariableFileType) {
+ case CseVariableFileTypePreMemoryFile:
+ *CseFileOffset = CSE_PRE_MEMORY_FILE_STORE_OFFSET;
+ break;
+
+ case CseVariableFileTypePrimaryIndexFile:
+ *CseFileOffset = CSE_PRIMARY_NVM_FILE_STORE_OFFSET;
+ break;
+
+ default:
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Returns the HECI protocol used to access the CSE NVM file.
+
+ @param[in] HeciProtocol A pointer to the HECI2 protocol if it is active.
+ If HECI1 is active, the value is NULL.
+
+ @return CSE_VARIABLE_HECI_PROTOCOL The HECI protocol to currently use.
+
+**/
+CSE_VARIABLE_HECI_PROTOCOL
+EFIAPI
+GetCseHeciProtocol (
+ OUT EFI_HECI_PROTOCOL **Heci2Protocol
+ )
+{
+ *Heci2Protocol = NULL;
+
+ return CseVariableHeci1Protocol;
+}
+
+
+/**
+ Returns the HECI protocol used to access the CSE NVM file based on a given varaible.
+
+ @param[in] VariableName Name of the variable.
+ @param[in] VendorGuid Guid of the variable.
+
+ @return CSE_VARIABLE_HECI_PROTOCOL The HECI protocol to currently use.
+
+**/
+CSE_VARIABLE_HECI_PROTOCOL
+EFIAPI
+GetCseVariableHeciProtocol (
+ IN CONST CHAR16 *VariableName,
+ IN CONST EFI_GUID *VendorGuid
+ )
+{
+ return CseVariableHeci1Protocol;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/PeiCseVariableStorageSelectorLib/PeiCseVariableStorageSelectorLib.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/PeiCseVariableStorageSelectorLib/PeiCseVariableStorageSelectorLib.inf
new file mode 100644
index 0000000000..bd6cce0924
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/PeiCseVariableStorageSelectorLib/PeiCseVariableStorageSelectorLib.inf
@@ -0,0 +1,47 @@
+## @file
+# PEI CSE Variable Storage Selector Library.
+#
+# Determines which CSE resources to consume in PEI.
+# Example: HECI1 or HECI2.
+#
+# Copyright (c) 2016, 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 = PeiCseVariableStorageSelectorLib
+ FILE_GUID = 58A49C3F-A0EE-4DFD-A68A-7770675F6A6A
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = CseVariableStorageSelectorLib
+
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ PeiCseVariableStorageSelectorLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ BroxtonSiPkg/BroxtonSiPkg.dec
+ BroxtonSiPkg/BroxtonSiPrivate.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ CseVariableStorageLib
+ DebugLib
+
+[Guids]
+ gEfiMemoryConfigVariableGuid
+ gEfiSetupVariableGuid
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/SideBandLib/SideBandLib.c b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/SideBandLib/SideBandLib.c
new file mode 100644
index 0000000000..89303fef5b
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/SideBandLib/SideBandLib.c
@@ -0,0 +1,435 @@
+/** @file
+ This file contains the implementation of SideBandLib library.
+ The library exposes an abstract interface to the SoC SideBand network.
+
+ Copyright (c) 2014 - 2016, 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 <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/SideBandLib.h>
+
+//
+// SocRefCode Dependencies
+//
+#include <SaAccess.h>
+#include <ScAccess.h>
+
+#define P2SB_PCI_MM_BASE (UINT32)MmPciAddress(0, \
+ 0, \
+ PCI_DEVICE_NUMBER_P2SB, \
+ PCI_FUNCTION_NUMBER_P2SB, \
+ 0)
+
+/**
+ The constructor function initializes module variables that contain base addresses
+ used by library functions.
+
+ @retval EFI_SUCCESS Always return, since there's no error codes here.
+
+**/
+EFI_STATUS
+EFIAPI
+SideBandLibConstructor (
+ VOID
+ )
+{
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Internal library utility function.
+
+ Returns the MMIO Address used to access the register over P2SB.
+
+ @param[in] TargetPortId Target port.
+ @param[in] TargetRegister Target register
+
+ @retval UINT32 The MMIO address to access TargetRegister in TargetPortId with P2SB.
+
+**/
+UINT32
+EFIAPI
+GetSideBandMmioAddress (
+ IN UINT8 TargetPortId,
+ IN UINT16 TargetRegister
+ )
+{
+ UINT32 Temp = MmioRead32 (P2SB_PCI_MM_BASE + R_P2SB_BASE) & 0xff000000;
+ Temp |= TargetPortId << 16;
+ Temp |= TargetRegister;
+
+ return Temp;
+}
+
+
+/**
+ Reads from IOSF-SB via MMIO.
+
+ In a single MMIO transaction, the "SBREG_BAR" is used
+ to form a system address to access chipset registers.
+
+ Transactions using this method will read using Private Control Register opcode CRRd(06h).
+
+ All accesses using this method must be DWORD aligned DWORDs.
+
+ @param[in] TargetPortId Target port to read.
+ @param[in] TargetRegister Target register to read.
+
+ @retval UINT32 The value read from the Target Register.
+
+**/
+UINT32
+EFIAPI
+SideBandMmioRead32 (
+ IN UINT8 TargetPortId,
+ IN UINT16 TargetRegister
+ )
+{
+ return MmioRead32 (GetSideBandMmioAddress (TargetPortId, TargetRegister));
+}
+
+
+/**
+ Reads from IOSF-SB via SideBand Message Interface Access (MMCFG).
+
+ In multiple MMIO transactions, this access method uses a mechanism provided in PCI
+ Configuration space to send IOSF-SB messages. This method should be used prior to
+ full PCI enumeration. Since multiple messages are sent this method is not thread-safe
+ but this is not an issue for single-threaded IAFW.
+
+ Transactions using this method will read using Private Control Register opcode CRRd(06h)
+
+ All accesses using this method must be DWORD aligned DWORDs.
+
+ @param[in] TargetPortId Target port to read.
+ @param[in] TargetRegister Target register to read.
+ @param[in] OpCode Opcode to use.
+ @param[in] Bar Target register access BAR.
+
+ @retval UINT32 The value read from Target Register.
+
+**/
+UINT32
+EFIAPI
+SideBandSbmiRead32 (
+ IN UINT8 TargetPortId,
+ IN UINT16 TargetRegister,
+ IN UINT8 OpCode,
+ IN UINT8 Bar
+ )
+{
+ MmioWrite32 ((P2SB_PCI_MM_BASE | P2SB_SBI_EXTADDR), (UINT32) (0x0));
+ MmioWrite32 ((P2SB_PCI_MM_BASE | P2SB_SBI_DATA), (UINT32) (0x0));
+ MmioWrite32 ((P2SB_PCI_MM_BASE | P2SB_SBI_ADDR), (UINT32) ((TargetPortId << 24) | (TargetRegister)));
+ MmioWrite16 ((P2SB_PCI_MM_BASE | P2SB_SBI_RID), (UINT16) ((Bar << 8) | (V_RID_FBE)));
+ MmioWrite16 ((P2SB_PCI_MM_BASE | P2SB_SBI_STAT), (UINT16) ((OpCode << 8) | (V_INITIATE)));
+
+ return MmioRead32(P2SB_PCI_MM_BASE | P2SB_SBI_DATA);
+}
+
+
+/**
+ SideBand Message Interface Access (MMCFG) Functions.
+
+ In multiple MMIO transactions, this access method uses a mechanism provided in PCI
+ Configuration space to send IOSF-SB messages. This method should be used prior to
+ full PCI enumeration. Since multiple messages are sent this method is not thread-safe
+ but this is not an issue for single-threaded IAFW.
+
+ All accesses using this method must be DWORD aligned DWORDs.
+
+ @param[in] TargetPortId Target port to write.
+ @param[in] TargetRegister Target register to write.
+ @param[in] OpCode Opcode to use.
+ @param[in] Value The value to write.
+ @param[in] Bar Target register access BAR.
+
+ @retval None.
+
+**/
+VOID
+EFIAPI
+SideBandSbmiWrite32 (
+ IN UINT8 TargetPortId,
+ IN UINT16 TargetRegister,
+ IN UINT8 OpCode,
+ IN UINT8 Bar,
+ IN UINT32 Value
+ )
+{
+ MmioWrite32 ((P2SB_PCI_MM_BASE | P2SB_SBI_ADDR), (UINT32) ((TargetPortId << 24) | (TargetRegister)));
+ MmioWrite16 ((P2SB_PCI_MM_BASE | P2SB_SBI_RID), (UINT16) ((Bar << 8) | (V_RID_FBE)));
+ MmioWrite32 ((P2SB_PCI_MM_BASE | P2SB_SBI_EXTADDR), (UINT32) (0x0));
+ MmioWrite32 ((P2SB_PCI_MM_BASE | P2SB_SBI_DATA), (UINT32) (Value));
+ MmioWrite16 ((P2SB_PCI_MM_BASE | P2SB_SBI_STAT), (UINT16) ((OpCode << 8) | (V_INITIATE)));
+}
+
+
+/**
+ Determines whether to call a SideBand read via MMIO or SBMI (MMCFG) based on whether
+ SBREG_REG is set up.
+
+ This is the standard Read function that should be used for SideBand transactions.
+
+ For MMIO Access:
+ In a single MMIO transaction, the "SBREG_BAR" is used
+ to form a system address to access chipset registers.
+ Transactions using this method will read using Private Control Register opcode CRRd(06h).
+ All accesses using this method must be DWORD aligned DWORDs.
+
+ For SBMI Access: Refer to SideBandSbmiRead32()
+
+ @param[in] TargetPortId Target port to read.
+ @param[in] TargetRegister Target register to read.
+
+ @retval UINT32 The value read from Target Register.
+
+**/
+UINT32
+EFIAPI
+SideBandRead32 (
+ IN UINT8 TargetPortId,
+ IN UINT16 TargetRegister
+ )
+{
+ UINT32 ReturnValue = 0;
+
+ //
+ // MMIO access requires MMIO to be valid (P2SB BAR set and Memory Decode enabled) and the address to be 32-bit aligned
+ //
+ if (SideBandMmioValid () && (GetSideBandMmioAddress (TargetPortId, TargetRegister) & 3) == 0) {
+ ReturnValue = MmioRead32 (GetSideBandMmioAddress (TargetPortId, TargetRegister));
+ } else {
+ ReturnValue = SideBandSbmiRead32 (TargetPortId, TargetRegister, V_OPCODE_CRRD, 0);
+ }
+
+ return ReturnValue;
+}
+
+
+/**
+ Determines whether to call a SideBand write via MMIO or SBMI (MMCFG) based on whether
+ SBREG_REG is set up.
+
+ This is the standard Write function that should be used for SideBand transactions.
+
+ For MMIO Access:
+ In a single MMIO transaction, the "SBREG_BAR" is used
+ to form a system address to access chipset registers.
+ Transactions using this method will write using Private Control Register opcode CRWr(07h).
+ All accesses using this method must be DWORD aligned DWORDs.
+
+ For SBMI Access: Refer to SideBandSbmiWrite32()
+
+ @param[in] TargetPortId Target port to write.
+ @param[in] TargetRegister Target register to write.
+ @param[in] Value The value to write.
+
+ @retval None.
+
+**/
+VOID
+EFIAPI
+SideBandWrite32 (
+ IN UINT8 TargetPortId,
+ IN UINT16 TargetRegister,
+ IN UINT32 Value
+ )
+{
+ //
+ // MMIO access requires MMIO to be valid (P2SB BAR set and Memory Decode enabled) and the address to be 32-bit aligned
+ //
+ if (SideBandMmioValid () == TRUE && (GetSideBandMmioAddress (TargetPortId, TargetRegister) & 3) == 0) {
+ MmioWrite32 (GetSideBandMmioAddress (TargetPortId, TargetRegister), Value);
+ } else {
+ SideBandSbmiWrite32 (TargetPortId, TargetRegister, V_OPCODE_CRWR, 0, Value);
+ }
+}
+
+
+/**
+ Determines whether to call SideBand operations via MMIO or SBMI (MMCFG) based on whether
+ SBREG_REG is set up.
+
+ This is the standard AndThenOr function that should be used for SideBand transactions.
+
+ Reads the value in the Target Register of the Target Port Id, performs a bitwise AND followed
+ by a bitwise OR between the read result and the value specified by AndData, and writes the
+ 32-bit value to the configuration register specified by Target Register.
+
+ @param[in] TargetPortId Target port to read/write.
+ @param[in] TargetRegister Target register to read/write.
+ @param[in] AndData The value to AND with Target Register data.
+ @param[in] OrData The value to OR with Target Register data.
+
+ @retval None.
+
+**/
+VOID
+EFIAPI
+SideBandAndThenOr32 (
+ IN UINT8 TargetPortId,
+ IN UINT16 TargetRegister,
+ IN UINT32 AndData,
+ IN UINT32 OrData
+ )
+{
+ UINT32 Temp = SideBandRead32 (TargetPortId, TargetRegister);
+
+ Temp = (Temp & AndData) | OrData;
+ SideBandWrite32 (TargetPortId, TargetRegister, Temp);
+}
+
+
+/**
+ This function is reserved for special case sideband access:
+ Non-private control register opcode
+
+ In multiple MMIO transactions, this access method uses a mechanism provided in PCI
+ Configuration space to send IOSF-SB messages. This method should be used prior to
+ full PCI enumeration. Since multiple messages are sent this method is not thread-safe
+ but this is not an issue for single-threaded IAFW.
+
+ Transactions using this method will read using the OpCode parameter.
+
+ All accesses using this method must be DWORD aligned DWORDs.
+
+ @param[IN] TargetPortId Target port to read.
+ @param[IN] TargetRegister Target register to read.
+ @param[IN] OpCode Opcode to use.
+ @param[in] Bar Target register access BAR.
+
+ @retval UINT32 The value read from Target Register.
+
+**/
+UINT32
+EFIAPI
+SideBandReadReserved32 (
+ IN UINT8 TargetPortId,
+ IN UINT16 TargetRegister,
+ IN UINT8 OpCode,
+ IN UINT8 Bar
+ )
+{
+ return SideBandSbmiRead32 (TargetPortId, TargetRegister, OpCode, Bar);
+}
+
+
+/**
+ This function is reserved for special case sideband access:
+ Non-private control register opcode
+
+ In multiple MMIO transactions, this access method uses a mechanism provided in PCI
+ Configuration space to send IOSF-SB messages. This method should be used prior to
+ full PCI enumeration. Since multiple messages are sent this method is not thread-safe
+ but this is not an issue for single-threaded IAFW.
+
+ Transactions using this method will write using the OpCode parameter.
+
+ All accesses using this method must be DWORD aligned DWORDs.
+
+ @param[in] TargetPortId Target port to write.
+ @param[in] TargetRegister Target register to write.
+ @param[in] OpCode Opcode to use.
+ @param[in] Bar Target register access BAR.
+ @param[in] Value The value to write.
+
+ @retval None.
+
+**/
+VOID
+EFIAPI
+SideBandWriteReserved32 (
+ IN UINT8 TargetPortId,
+ IN UINT16 TargetRegister,
+ IN UINT8 OpCode,
+ IN UINT8 Bar,
+ IN UINT32 Value
+ )
+{
+ SideBandSbmiWrite32 (TargetPortId, TargetRegister, OpCode, Bar, Value);
+}
+
+
+/**
+ This function is reserved for special case sideband access:
+ Non-private control register opcode
+
+ Reads the value in the Target Register of the Target Port Id, performs a bitwise AND followed
+ by a bitwise OR between the read result and the value specified by AndData, and writes the
+ 32-bit value to the configuration register specified by Target Register.
+
+ @param[in] TargetPortId Target port to read/write.
+ @param[in] TargetRegister Target register to read/write.
+ @param[in] ReadOpCode Opcode to use for read.
+ @param[in] WriteOpCode Opcode to use for write.
+ @param[in] Bar Target register access BAR.
+ @param[in] AndData The value to AND with Target Register data.
+ @param[in] OrData The value to OR with Target Register data.
+
+ @retval None.
+
+**/
+VOID
+EFIAPI
+SideBandAndThenOrReserved32 (
+ IN UINT8 TargetPortId,
+ IN UINT16 TargetRegister,
+ IN UINT8 ReadOpCode,
+ IN UINT8 WriteOpCode,
+ IN UINT8 Bar,
+ IN UINT32 AndData,
+ IN UINT32 OrData
+ )
+{
+ UINT32 Temp = SideBandSbmiRead32 (TargetPortId, TargetRegister, ReadOpCode, Bar);
+
+ Temp = (Temp & AndData) | OrData;
+ SideBandSbmiWrite32 (TargetPortId, TargetRegister, WriteOpCode, Bar, Temp);
+}
+
+
+/**
+ Returns if SideBand access using P2SB MMIO is valid.
+
+ @param None.
+
+ @retval BOOLEAN Returns true if SideBand access via P2SB MMIO is valid else returns false.
+
+**/
+BOOLEAN
+EFIAPI
+SideBandMmioValid(
+ VOID
+ )
+{
+ UINT32 P2sbMmioBar = 0;
+ UINT16 P2sbCmd = 0;
+ UINT32 P2sbPciMmBase = P2SB_PCI_MM_BASE;
+
+ P2sbMmioBar = MmioRead32 (P2sbPciMmBase + R_P2SB_BASE);
+ P2sbMmioBar &= B_P2SB_BAR_BA; // Mask off the last byte read from BAR
+
+ P2sbCmd = MmioRead16 (P2sbPciMmBase + R_P2SB_STSCMD);
+
+ if (P2sbMmioBar != 0 && P2sbMmioBar != B_P2SB_BAR_BA && (P2sbCmd & B_P2SB_STSCMD_MSE) != 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/SideBandLib/SideBandLib.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/SideBandLib/SideBandLib.inf
new file mode 100644
index 0000000000..855c7d98e4
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/SideBandLib/SideBandLib.inf
@@ -0,0 +1,39 @@
+## @file
+# SideBandLib library.
+#
+# Copyright (c) 2014 - 2016, 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 = SideBandLib
+ FILE_GUID = E5B3A54B-2487-41EA-8AC3-01CFED924303
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SideBandLib
+ CONSTRUCTOR = SideBandLibConstructor
+
+[Sources]
+ SideBandLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ BroxtonSiPkg/BroxtonSiPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ IoLib
+ PcdLib
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress ## SOMETIMES_CONSUMES
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/SteppingLib/SteppingLib.c b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/SteppingLib/SteppingLib.c
new file mode 100644
index 0000000000..d4930d1ced
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/SteppingLib/SteppingLib.c
@@ -0,0 +1,162 @@
+/** @file
+ This file contains routines that get Soc Stepping.
+
+ Copyright (c) 2014 - 2016, 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 <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <IndustryStandard/Pci30.h>
+#include <SaAccess.h>
+#include <ScRegs/RegsPmc.h>
+#include <Library/SteppingLib.h>
+#include <Library/MmPciLib.h>
+
+/**
+ Return SOC series type
+
+ @retval BXT_SERIES SOC series type
+
+**/
+BXT_SERIES
+EFIAPI
+GetBxtSeries (
+ VOID
+ )
+{
+ UINTN McD0Base;
+ UINT16 VenId;
+ UINT16 DevId;
+
+ McD0Base = MmPciBase (
+ SA_MC_BUS,
+ SA_MC_DEV,
+ SA_MC_FUN
+ );
+
+ VenId = MmioRead16 (McD0Base + PCI_VENDOR_ID_OFFSET);
+ DevId = MmioRead16 (McD0Base + PCI_DEVICE_ID_OFFSET);
+ if (VenId == V_SA_MC_VID) {
+ switch (DevId) {
+ case V_SA_MC_DID0:
+ return Bxt;
+ break;
+ case V_SA_MC_DID1:
+ return Bxt1;
+ break;
+ case V_SA_MC_DID3:
+ return BxtP;
+ break;
+ default:
+ DEBUG ((DEBUG_ERROR, "Unsupported BXT Series.\n"));
+ return BxtSeriesMax;
+ break;
+ }
+ }
+ return BxtSeriesMax;
+}
+
+
+/**
+ This procedure will get Soc Stepping
+
+ @retval Soc Stepping
+
+**/
+BXT_STEPPING
+EFIAPI
+BxtStepping (
+ VOID
+ )
+{
+ BXT_SERIES BxtSeries;
+ UINT8 RevId;
+ UINTN McD0Base;
+
+ McD0Base = MmPciBase (
+ SA_MC_BUS,
+ SA_MC_DEV,
+ SA_MC_FUN
+ );
+ RevId = MmioRead8 (McD0Base + PCI_REVISION_ID_OFFSET);
+ BxtSeries = GetBxtSeries ();
+
+ if (BxtSeries == BxtP) {
+ switch (RevId) {
+ case V_SA_MC_RID_3:
+ DEBUG ((DEBUG_INFO, "BXTP-A0 detected!\n"));
+ return BxtPA0;
+ break;
+ case V_SA_MC_RID_9:
+ DEBUG ((DEBUG_INFO, "BXTP-B0 detected!\n"));
+ return BxtPB0;
+ break;
+ case V_SA_MC_RID_A:
+ DEBUG ((DEBUG_INFO, "BXTP-B1 detected!\n"));
+ return BxtPB1;
+ break;
+ case V_SA_MC_RID_B:
+ DEBUG ((DEBUG_INFO, "BXTP-B2 detected!\n"));
+ return BxtPB2;
+ break;
+ default:
+ DEBUG ((DEBUG_ERROR, "Unsupported BXT-P stepping.\n"));
+ return BxtSteppingMax;
+ break;
+ }
+ } else if (BxtSeries == Bxt1) {
+ switch (RevId) {
+ case V_SA_MC_RID_6:
+ DEBUG ((DEBUG_INFO, "BXT-B0 detected!\n"));
+ return BxtB0;
+ break;
+ case V_SA_MC_RID_7:
+ DEBUG ((DEBUG_INFO, "BXT-B1 detected!\n"));
+ return BxtB1;
+ break;
+ case V_SA_MC_RID_8:
+ DEBUG ((DEBUG_INFO, "BXT-B2 detected!\n"));
+ return BxtB2;
+ break;
+ case V_SA_MC_RID_C:
+ DEBUG ((DEBUG_INFO, "BXT-C0 detected!\n"));
+ return BxtC0;
+ break;
+ default:
+ DEBUG ((DEBUG_ERROR, "Unsupported BXT1 stepping.\n"));
+ return BxtSteppingMax;
+ break;
+ }
+ } else if (BxtSeries == Bxt) {
+ switch (RevId) {
+ case V_SA_MC_RID_0:
+ DEBUG ((DEBUG_INFO, "BXT-A0 detected!\n"));
+ return BxtA0;
+ break;
+ case V_SA_MC_RID_1:
+ DEBUG ((DEBUG_INFO, "BXT-A1 detected!\n"));
+ return BxtA1;
+ break;
+ default:
+ DEBUG ((DEBUG_ERROR, "Unsupported BXT stepping.\n"));
+ return BxtSteppingMax;
+ break;
+ }
+ }
+
+ return BxtSteppingMax;
+}
+
+
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Library/SteppingLib/SteppingLib.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/SteppingLib/SteppingLib.inf
new file mode 100644
index 0000000000..4f7afab961
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Library/SteppingLib/SteppingLib.inf
@@ -0,0 +1,44 @@
+## @file
+# PeiDxeSmmMmPciLib.
+#
+# Copyright (c) 2014 - 2016, 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 = SteppingLib
+ FILE_GUID = DB2136A0-0FBD-439f-B743-59B4E6DA98DF
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SteppingLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+[Sources]
+ SteppingLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ BroxtonSiPkg/BroxtonSiPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+ PcdLib
+ DebugLib
+ MmPciLib
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress