From 92b6719423f351e9cf5517a9413f63da57778136 Mon Sep 17 00:00:00 2001 From: Guo Mang Date: Thu, 22 Dec 2016 19:14:43 +0800 Subject: BroxtonSiPkg: Add Library Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Guo Mang --- .../BaseConfigBlockLib/BaseConfigBlockLib.c | 205 ++++ .../BaseConfigBlockLib/BaseConfigBlockLib.inf | 35 + .../BaseVariableNvmStorageLib.c | 571 +++++++++ .../BaseVariableNvmStorageLib.inf | 44 + .../BaseVariableStorageSelectorLib.c | 60 + .../BaseVariableStorageSelectorLib.inf | 44 + .../Library/DxeAslUpdateLib/DxeAslUpdateLib.c | 312 +++++ .../Library/DxeAslUpdateLib/DxeAslUpdateLib.inf | 42 + .../BroxtonSiPkg/Library/GpioLib/GpioLib.c | 1230 ++++++++++++++++++++ .../BroxtonSiPkg/Library/GpioLib/GpioLib.inf | 43 + .../Library/PeiDxeSmmMmPciLib/PeiDxeSmmMmPciLib.c | 48 + .../PeiDxeSmmMmPciLib/PeiDxeSmmMmPciLib.inf | 41 + .../PeiPerformanceLibFpdt/PeiPerformanceLibFpdt.c | 427 +++++++ .../PeiPerformanceLibFpdt.inf | 52 + .../Library/PeiSiPolicyLib/PeiSiPolicyLib.c | 148 +++ .../Library/PeiSiPolicyLib/PeiSiPolicyLib.inf | 40 + .../Library/PeiSiPolicyLib/PeiSiPolicyLibrary.h | 37 + .../Library/PeiSiPolicyLib/SiPrintPolicy.c | 44 + .../BroxtonSiPkg/Library/PmcIpcLib/BaseIpcLib.c | 128 ++ .../BroxtonSiPkg/Library/PmcIpcLib/BaseIpcLib.inf | 46 + .../Library/PmcIpcLib/InternalIpcLib.c | 368 ++++++ .../Library/PmcIpcLib/InternalIpcLib.h | 75 ++ .../BaseCseVariableStorageLib.c | 1091 +++++++++++++++++ .../BaseCseVariableStorageLib.inf | 59 + .../CseVariableStorageSelectorLib.c | 177 +++ .../CseVariableStorageSelectorLibInternal.h | 27 + .../DxeCseVariableStorageSelectorLib.c | 113 ++ .../DxeCseVariableStorageSelectorLib.inf | 55 + .../SmmCseVariableStorageSelectorLib.c | 69 ++ .../SmmCseVariableStorageSelectorLib.inf | 54 + .../PeiCseVariableStorageSelectorLib.c | 165 +++ .../PeiCseVariableStorageSelectorLib.inf | 47 + .../BroxtonSiPkg/Library/SideBandLib/SideBandLib.c | 435 +++++++ .../Library/SideBandLib/SideBandLib.inf | 39 + .../BroxtonSiPkg/Library/SteppingLib/SteppingLib.c | 162 +++ .../Library/SteppingLib/SteppingLib.inf | 44 + 36 files changed, 6577 insertions(+) create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/BaseConfigBlockLib/BaseConfigBlockLib.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/BaseConfigBlockLib/BaseConfigBlockLib.inf create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/BaseVariableNvmStorageLib/BaseVariableNvmStorageLib.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/BaseVariableNvmStorageLib/BaseVariableNvmStorageLib.inf create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/BaseVariableStorageSelectorLib/BaseVariableStorageSelectorLib.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/BaseVariableStorageSelectorLib/BaseVariableStorageSelectorLib.inf create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/DxeAslUpdateLib/DxeAslUpdateLib.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/DxeAslUpdateLib/DxeAslUpdateLib.inf create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/GpioLib/GpioLib.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/GpioLib/GpioLib.inf create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiDxeSmmMmPciLib/PeiDxeSmmMmPciLib.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiDxeSmmMmPciLib/PeiDxeSmmMmPciLib.inf create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiPerformanceLibFpdt/PeiPerformanceLibFpdt.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiPerformanceLibFpdt/PeiPerformanceLibFpdt.inf create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiSiPolicyLib/PeiSiPolicyLib.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiSiPolicyLib/PeiSiPolicyLib.inf create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiSiPolicyLib/PeiSiPolicyLibrary.h create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/PeiSiPolicyLib/SiPrintPolicy.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/PmcIpcLib/BaseIpcLib.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/PmcIpcLib/BaseIpcLib.inf create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/PmcIpcLib/InternalIpcLib.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/PmcIpcLib/InternalIpcLib.h create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/BaseCseVariableStorageLib/BaseCseVariableStorageLib.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/BaseCseVariableStorageLib/BaseCseVariableStorageLib.inf create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/DxeSmmCseVariableStorageSelectorLib/CseVariableStorageSelectorLib.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/DxeSmmCseVariableStorageSelectorLib/CseVariableStorageSelectorLibInternal.h create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/DxeSmmCseVariableStorageSelectorLib/DxeCseVariableStorageSelectorLib.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/DxeSmmCseVariableStorageSelectorLib/DxeCseVariableStorageSelectorLib.inf create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/DxeSmmCseVariableStorageSelectorLib/SmmCseVariableStorageSelectorLib.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/DxeSmmCseVariableStorageSelectorLib/SmmCseVariableStorageSelectorLib.inf create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/PeiCseVariableStorageSelectorLib/PeiCseVariableStorageSelectorLib.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/Private/PeiCseVariableStorageSelectorLib/PeiCseVariableStorageSelectorLib.inf create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/SideBandLib/SideBandLib.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/SideBandLib/SideBandLib.inf create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/SteppingLib/SteppingLib.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/Library/SteppingLib/SteppingLib.inf 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.
+ + 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 +#include +#include +#include +#include + + +/** + 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.
+# +# 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.
+ + 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 +#include +#include +#include + +/** + 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.
+# +# 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.
+ + 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 +#include +#include +#include +#include + +// +// 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.
+# +# 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.
+ + 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 +#include +#include +#include +#include +#include +#include +#include +#include + +// +// 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.
+# +# 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.
+ + 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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.
+# +# 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.
+ + 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 +#include +#include + +/** + 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.
+# +# 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.
+ + 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/** + 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.
+# +# 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.
+ + 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.
+# +# 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.
+ + 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 +#include +#include +#include +#include +#include +#include + +#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.
+ + 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.
+ + 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 +#include +#include +#include +#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.
+# +# 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.
+ + 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 +#include +#include +#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.
+ + 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 +#include +#include + +// +// Produced library class +// +#include + +// +// 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.
+ + 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // Temporary +#include +#include + + +/** + 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.
+# +# 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.
+ + 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.
+ + 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 +#include +#include +#include + +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.
+ + 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 +#include +#include + +/** + 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.
+# +# 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.
+ + 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 + + +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.
+# +# 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.
+ + 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 +#include +#include +#include + +/** + 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.
+# +# 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.
+ + 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 +#include +#include +#include +#include +#include + +// +// SocRefCode Dependencies +// +#include +#include + +#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.
+# +# 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.
+ + 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 +#include +#include +#include +#include +#include +#include +#include +#include + +/** + 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.
+# +# 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 -- cgit v1.2.3