From f04d976eba34af603a73d973ab63edc9c2412401 Mon Sep 17 00:00:00 2001 From: Guo Mang Date: Fri, 23 Dec 2016 13:11:00 +0800 Subject: BroxtonSiPkg: Add VariableStorage Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Guo Mang --- .../CseVariableStorage.c | 1201 ++++++++++++++++++++ .../CseVariableStorage.h | 72 ++ .../CseVariableStorageRuntimeDxe.c | 114 ++ .../CseVariableStorageRuntimeDxe.inf | 67 ++ .../CseVariableStorageSmmRuntimeDxe.c | 61 + .../CseVariableStorageSmmRuntimeDxe.h | 311 +++++ .../CseVariableStorageSmmRuntimeDxe.inf | 68 ++ .../CseVariableStoragePei/CseVariableStoragePei.c | 353 ++++++ .../CseVariableStoragePei/CseVariableStoragePei.h | 146 +++ .../CseVariableStoragePei.inf | 58 + 10 files changed, 2451 insertions(+) create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Dxe/CseVariableStorageSmmRuntimeDxe/CseVariableStorage.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Dxe/CseVariableStorageSmmRuntimeDxe/CseVariableStorage.h create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Dxe/CseVariableStorageSmmRuntimeDxe/CseVariableStorageRuntimeDxe.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Dxe/CseVariableStorageSmmRuntimeDxe/CseVariableStorageRuntimeDxe.inf create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Dxe/CseVariableStorageSmmRuntimeDxe/CseVariableStorageSmmRuntimeDxe.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Dxe/CseVariableStorageSmmRuntimeDxe/CseVariableStorageSmmRuntimeDxe.h create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Dxe/CseVariableStorageSmmRuntimeDxe/CseVariableStorageSmmRuntimeDxe.inf create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Pei/CseVariableStoragePei/CseVariableStoragePei.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Pei/CseVariableStoragePei/CseVariableStoragePei.h create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Pei/CseVariableStoragePei/CseVariableStoragePei.inf (limited to 'Silicon/BroxtonSoC') diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Dxe/CseVariableStorageSmmRuntimeDxe/CseVariableStorage.c b/Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Dxe/CseVariableStorageSmmRuntimeDxe/CseVariableStorage.c new file mode 100644 index 0000000000..7ceaf5e902 --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Dxe/CseVariableStorageSmmRuntimeDxe/CseVariableStorage.c @@ -0,0 +1,1201 @@ +/** @file + Implements CSE Variable Storage Services and installs + an instance of the VariableStorage Runtime DXE protocol. + + 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 "CseVariableStorage.h" + +// +// Module globals +// +CSE_VARIABLE_FILE_INFO *mCseVariableFileInfo[CseVariableFileTypeMax]; + +VARIABLE_STORAGE_PROTOCOL mCseVariableStorageProtocol = { + CseVariableStorageGetId, + CseVariableStorageGetVariable, + CseVariableStorageGetAuthenticatedVariable, + CseVariableStorageGetNextVariableName, + CseVariableStorageGetStorageUsage, + CseVariableStorageGetAuthenticatedSupport, + CseVariableStorageSetVariable, + CseVariableStorageWriteServiceIsReady, + CseVariableStorageRegisterWriteServiceReadyCallback, +}; + +BOOLEAN mIsEmmcBoot = FALSE; + +/** + Performs common initialization needed for this module. + + @param None + + @retval EFI_SUCCESS The module was initialized successfully. + @retval Others The module could not be initialized. + +**/ +EFI_STATUS +EFIAPI +CseVariableStorageCommonInitialize ( + VOID + ) +{ + EFI_STATUS Status; + UINT8 BootMedia; + EFI_HOB_GUID_TYPE *GuidHobPtr; + MBP_CURRENT_BOOT_MEDIA *BootMediaData; + + // + // Allocate and initialize the global variable structure + // + Status = InitializeCseStorageGlobalVariableStructures (mCseVariableFileInfo, TRUE); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + // + // Establish the CSE variable stores + // Create an enabled variable store if it does not exist + // Load the variable header data regions needed to find variables + // + Status = EstablishAndLoadCseVariableStores (mCseVariableFileInfo, TRUE); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Error returned from EstablishAndLoadCseVariableStores()\n")); + ASSERT_EFI_ERROR (Status); + return Status; + } + + DEBUG ((EFI_D_INFO, " CSE Pre-memory File Enabled: %c\n CSE Pre-memory Store Established: %c\n CSE NVM File Enabled: %c\n CSE NVM Store Established: %c\n\n", + (mCseVariableFileInfo[CseVariableFileTypePreMemoryFile]->FileEnabled ? 'T' : 'F'), + (mCseVariableFileInfo[CseVariableFileTypePreMemoryFile]->FileStoreEstablished ? 'T' : 'F'), + (mCseVariableFileInfo[CseVariableFileTypePrimaryIndexFile]->FileEnabled ? 'T' : 'F'), + (mCseVariableFileInfo[CseVariableFileTypePrimaryIndexFile]->FileStoreEstablished ? 'T' : 'F') + )); + + GuidHobPtr = GetFirstGuidHob (&gEfiBootMediaHobGuid); + if (GuidHobPtr == NULL) { + DEBUG ((DEBUG_ERROR, "CseVariableStorage Error: Boot Media HOB does not exist!\n")); + ASSERT (GuidHobPtr != NULL); + return FALSE; + } + + BootMediaData = (MBP_CURRENT_BOOT_MEDIA *) GET_GUID_HOB_DATA (GuidHobPtr); + BootMedia = (UINT8) BootMediaData->PhysicalData; + if (BootMedia != BOOT_FROM_SPI) { + mIsEmmcBoot = TRUE; + } + + return EFI_SUCCESS; +} + + +/** + Update the CSE NVM variable with the supplied data. These are the same + arguments as the EFI Variable services. + + @param[in] VariableName Name of variable. + @param[in] VendorGuid Guid of variable. + @param[in] Data Variable data. + @param[in] DataSize Size of data. 0 means delete. + @param[in] Attributes Attributes of the variable. + @param[in, out] IndexVariable The variable found in the header region corresponding to this variable. + + @retval EFI_SUCCESS The update operation is success. + @retval Others The variable update operation failed. + +**/ +EFI_STATUS +UpdateVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN VOID *Data, + IN UINTN DataSize, + IN UINT32 Attributes, + IN OUT VARIABLE_NVM_POINTER_TRACK *IndexVariable, + IN UINT32 KeyIndex OPTIONAL, + IN UINT64 MonotonicCount OPTIONAL, + IN EFI_TIME *TimeStamp OPTIONAL + ) +{ + BOOLEAN UpdatingExistingVariable; + CSE_VARIABLE_FILE_TYPE VariableCseFileType; + EFI_STATUS Status; + UINT8 EmptyBuffer = 0; + UINTN NewVariableTotalSize = 0; + UINT32 NewVariableHeaderSize = 0; + INT32 TotalVariableHeaderRemainingSize = 0; + INT32 TotalVariableStoreRemainingSize = 0; + UINT32 VariablePaddingSize = 0; + UINT32 VariableStoreBaseOffset = 0; ///< The offset from the beginning of the file to the variable store + UINT32 VariableIndexFileWriteOffset = 0; ///< The offset from the beginning of the index file to the variable header + UINT32 VariableDataWriteOffset = 0; ///< The offset from the beginning of the data file to the data + UINT32 VariableDataFileNumber = 0; ///< The variable data file number (if data is stored in individual files) + CHAR8 CseVariableDataFileName[CSE_MAX_NVM_FILE_NAME_LENGTH]; + + AUTHENTICATED_VARIABLE_NVM_HEADER *AuthenticatedVariableHeader = NULL; + VARIABLE_NVM_HEADER *NewVariableHeader = NULL; + VARIABLE_NVM_STORE_INFO VariableStoreInfo; + VARIABLE_NVM_POINTER_TRACK VariableNvmDeletedVariablePtrTrack; + + VariableNvmDeletedVariablePtrTrack.StartPtr = NULL; + VariableNvmDeletedVariablePtrTrack.EndPtr = NULL; + VariableNvmDeletedVariablePtrTrack.CurrPtr = NULL; + VariableNvmDeletedVariablePtrTrack.InDeletedTransitionPtr = NULL; + + UpdatingExistingVariable = (BOOLEAN) (IndexVariable->CurrPtr != NULL && IsValidVariableHeader (IndexVariable->CurrPtr, IndexVariable->EndPtr)); + VariableCseFileType = GetCseVariableStoreFileType (VariableName, VendorGuid, mCseVariableFileInfo); + + if (VariableCseFileType >= CseVariableFileTypeMax) { + return EFI_UNSUPPORTED; + } + + if (mCseVariableFileInfo[VariableCseFileType] == NULL) { + DEBUG ((EFI_D_ERROR, "The global CSE file info variable was not populated for this file type.\n")); + return EFI_NOT_FOUND; + } + + VariableStoreInfo.VariableStoreHeader = (VARIABLE_NVM_STORE_HEADER *) (UINTN) mCseVariableFileInfo[VariableCseFileType]->HeaderRegionBase; + Status = IsAuthenticatedVariableStore (VariableStoreInfo.VariableStoreHeader, &VariableStoreInfo.AuthFlag); + + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + if (VariableStoreInfo.VariableStoreHeader == NULL) { + DEBUG ((EFI_D_ERROR, "The variable store could not be found for this file type.\n")); + return EFI_NOT_FOUND; + } + + if (!mCseVariableFileInfo[VariableCseFileType]->FileEnabled || !mCseVariableFileInfo[VariableCseFileType]->FileStoreEstablished) { + DEBUG ((EFI_D_ERROR, "Error: Attempted to set a variable with a CSE file type not enabled.\n")); + return EFI_INVALID_PARAMETER; + } + + // + // Check to see if this is a variable that has been previously deleted + // + if (!UpdatingExistingVariable && VariableCseFileType != CseVariableFileTypePreMemoryFile) { + VariableNvmDeletedVariablePtrTrack.StartPtr = GetStartPointer (VariableStoreInfo.VariableStoreHeader); + VariableNvmDeletedVariablePtrTrack.EndPtr = GetEndPointer (VariableStoreInfo.VariableStoreHeader); + + Status = FindDeletedVariable (VariableName, VendorGuid, VariableStoreInfo.VariableStoreHeader, &VariableNvmDeletedVariablePtrTrack); + + if (EFI_ERROR (Status)) { + VariableNvmDeletedVariablePtrTrack.CurrPtr = NULL; + } + } + + // + // Update the offsets for the CSE file store type + // + // Pre-memory file: This is an offset in the file + // Primary index file: This is the number of the CSE NVM data file + // + GetCseVariableStoreFileOffset (VariableCseFileType, &VariableStoreBaseOffset); + + if (VariableCseFileType == CseVariableFileTypePreMemoryFile) { + if (UpdatingExistingVariable) { + VariableDataWriteOffset = IndexVariable->CurrPtr->DataOffset; + } else { + VariableDataWriteOffset = (UINT32) (mCseVariableFileInfo[VariableCseFileType]->FileStoreMaximumSize \ + - VariableStoreInfo.VariableStoreHeader->VariableDataTotalLength \ + - DataSize + ); + + if (VariableStoreInfo.VariableStoreHeader->VariableDataTotalLength == 0) { + VariableDataWriteOffset--; + } + + VariablePaddingSize = NVM_GET_PAD_SIZE_N (VariableDataWriteOffset); + VariableDataWriteOffset -= VariablePaddingSize; + } + } else { + if (UpdatingExistingVariable) { + VariableDataFileNumber = IndexVariable->CurrPtr->DataOffset; + + if (CSE_PRIMARY_NVM_MAX_DATA_FILES < 1 || VariableDataFileNumber >= CSE_PRIMARY_NVM_MAX_DATA_FILES) { + DEBUG ((EFI_D_ERROR, "Cannot save new variable - maximum number of CSE NVM files reached.\n")); + return EFI_OUT_OF_RESOURCES; + } + } else { + if (VariableNvmDeletedVariablePtrTrack.CurrPtr != NULL) { + DEBUG ((EFI_D_INFO, "Recycling CSE NVM variable file %d.\n", VariableNvmDeletedVariablePtrTrack.CurrPtr->DataOffset)); + VariableDataFileNumber = VariableNvmDeletedVariablePtrTrack.CurrPtr->DataOffset; + } else { + VariableDataFileNumber = VariableStoreInfo.VariableStoreHeader->VariableHeaderTotalEntries; + } + } + } + + // + // Calculate the space remaining in the variable header region + // + if (VariableCseFileType == CseVariableFileTypePreMemoryFile) { + TotalVariableHeaderRemainingSize = (INT32) (mCseVariableFileInfo[VariableCseFileType]->FileStoreMaximumSize \ + - sizeof (VARIABLE_NVM_STORE_HEADER) \ + - VariableStoreInfo.VariableStoreHeader->VariableHeaderTotalLength \ + - VariableStoreInfo.VariableStoreHeader->VariableDataTotalLength \ + - StrSize (VariableName) + ); + } else { + TotalVariableHeaderRemainingSize = (INT32) (CSE_MAX_FILE_DATA_SIZE \ + - sizeof (VARIABLE_NVM_STORE_HEADER) \ + - VariableStoreInfo.VariableStoreHeader->VariableHeaderTotalLength \ + - StrSize (VariableName) + ); + } + + // + // Calculate the index file offset for the new variable header and ensure there is enough space + // + if (UpdatingExistingVariable) { + ASSERT ((UINTN) IndexVariable->CurrPtr > (UINTN) VariableStoreInfo.VariableStoreHeader); + + VariableIndexFileWriteOffset = NVM_HEADER_ALIGN ((UINT32) (VariableStoreBaseOffset + \ + ((UINTN) (IndexVariable->CurrPtr) - \ + (UINTN) VariableStoreInfo.VariableStoreHeader)) + ); + } else { + if (TotalVariableHeaderRemainingSize < (INT32) GetVariableHeaderSize (VariableStoreInfo.AuthFlag)) { + DEBUG ((EFI_D_ERROR, "Cannot save new variable - CSE NVM header region is at maximum capacity.\n")); + return EFI_OUT_OF_RESOURCES; + } + if (VariableNvmDeletedVariablePtrTrack.CurrPtr == NULL) { + VariableIndexFileWriteOffset = NVM_HEADER_ALIGN ((UINT32) (VariableStoreBaseOffset + \ + ((UINTN) GetEndPointer (VariableStoreInfo.VariableStoreHeader) - \ + (UINTN) VariableStoreInfo.VariableStoreHeader)) + ); + } else { + VariableIndexFileWriteOffset = NVM_HEADER_ALIGN ((UINT32) (VariableStoreBaseOffset + \ + ((UINTN) (VariableNvmDeletedVariablePtrTrack.CurrPtr) - \ + (UINTN) VariableStoreInfo.VariableStoreHeader)) + ); + } + } + + // + // Construct the data file name + // + ZeroMem (&CseVariableDataFileName[0], CSE_MAX_NVM_FILE_NAME_LENGTH); + if (VariableCseFileType == CseVariableFileTypePreMemoryFile) { + // + // The pre-memory file is a single file that serves as both the index file + // and the data file. Therefore, the data filename is the index filename. + // + CopyMem (&CseVariableDataFileName[0], mCseVariableFileInfo[VariableCseFileType]->FileName, AsciiStrLen (mCseVariableFileInfo[VariableCseFileType]->FileName)); + } else { + Status = BuildCseDataFileName (VariableDataFileNumber, &CseVariableDataFileName[0]); + if (EFI_ERROR (Status)) { + return Status; + } + } + + DEBUG ((EFI_D_INFO, "CSE NVM Data Filename: %a\n", &CseVariableDataFileName[0])); + + // + // Check if the variable is being deleted + // + // Note: Setting a variable with no access or zero DataSize attributes + // causes it to be deleted. + // + if (UpdatingExistingVariable) { + if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) { + DEBUG ((EFI_D_INFO, "Variable has been requested for delete.\n")); + + if (VariableCseFileType == CseVariableFileTypePreMemoryFile) { + DEBUG ((EFI_D_WARN, "WARNING: Variable deletion is not supported in the pre-memory file.\n")); + return EFI_UNSUPPORTED; + } + + // + // Update variable store properties + // + VariableStoreInfo.VariableStoreHeader->VariableDataTotalLength -= IndexVariable->CurrPtr->DataSize; + + VariableStoreInfo.VariableStoreHeader->Size = sizeof (VARIABLE_NVM_STORE_HEADER) \ + + VariableStoreInfo.VariableStoreHeader->VariableDataTotalLength \ + + VariableStoreInfo.VariableStoreHeader->VariableHeaderTotalLength; + + DEBUG ((EFI_D_INFO, " CseVariableStorageProtocol: Total data length before delete = %d bytes. Data size of deleted variable = %d bytes.\n", + VariableStoreInfo.VariableStoreHeader->VariableDataTotalLength, + IndexVariable->CurrPtr->DataSize + )); + IndexVariable->CurrPtr->State &= VAR_DELETED; + + DEBUG ((EFI_D_INFO, " Offset written in CSE NVM index file = %d.\n", VariableIndexFileWriteOffset)); + + // + // Update the variable store header with the new sizes + // + Status = UpdateCseNvmFile ( + mCseVariableFileInfo[VariableCseFileType]->FileName, + VariableStoreBaseOffset, + (UINT8 *) VariableStoreInfo.VariableStoreHeader, + sizeof (VARIABLE_NVM_STORE_HEADER), + FALSE, + NULL + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Update the variable header with the deleted state + // + Status = UpdateCseNvmFile ( + mCseVariableFileInfo[VariableCseFileType]->FileName, + VariableIndexFileWriteOffset, + (UINT8 *) IndexVariable->CurrPtr, + GetVariableHeaderSize (VariableStoreInfo.AuthFlag), + FALSE, + NULL + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Failed to put the CSE NVM variable header in the deleted state.\n")); + return Status; + } + + // + // Delete the data file + // + Status = UpdateCseNvmFile ( + &CseVariableDataFileName[0], + 0, + (UINT8 *) &EmptyBuffer, + 0, + TRUE, + NULL + ); + + if (!EFI_ERROR (Status)) { + DEBUG ((EFI_D_INFO, "Successfully deleted the CSE NVM file.\n")); + } + + return Status; + } + } + // + // Note: Do not check if data already exists on NVM to prevent re-write as HECI I/O is the bottleneck. + // + if (UpdatingExistingVariable) { + DEBUG ((EFI_D_INFO, "The variable already exists.\n")); + + if (!IsValidVariableHeader (IndexVariable->CurrPtr, IndexVariable->EndPtr)) { + DEBUG ((EFI_D_ERROR, "The existing variable header is not valid.\n")); + return EFI_INVALID_PARAMETER; + } + + if (VariableStoreInfo.AuthFlag) { + AuthenticatedVariableHeader = (AUTHENTICATED_VARIABLE_NVM_HEADER *) IndexVariable->CurrPtr; + } + } else { + DEBUG ((EFI_D_INFO, "The variable does not exist yet. Creating a new variable.\n")); + + // + // Make sure a new variable does not contain invalid attributes + // + if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) { + DEBUG ((EFI_D_ERROR, "Invalid attributes specified for new variable.\n")); + return EFI_INVALID_PARAMETER; + } + + NewVariableHeaderSize = (VariableNvmDeletedVariablePtrTrack.CurrPtr == NULL) ? (UINT32) GetVariableHeaderSize (VariableStoreInfo.AuthFlag) : 0; + + TotalVariableStoreRemainingSize = (mCseVariableFileInfo[VariableCseFileType]->FileStoreMaximumSize - \ + sizeof (VARIABLE_NVM_STORE_HEADER) - \ + NewVariableHeaderSize - \ + VariableStoreInfo.VariableStoreHeader->VariableHeaderTotalLength - \ + VariableStoreInfo.VariableStoreHeader->VariableDataTotalLength + ); + + DEBUG ((EFI_D_INFO, "Note: Total remaining size in variable store BEFORE adding the variable %d bytes of maximum %d bytes.\n", + TotalVariableStoreRemainingSize, + mCseVariableFileInfo[VariableCseFileType]->FileStoreMaximumSize + )); + + if (VariableNvmDeletedVariablePtrTrack.CurrPtr == NULL) { + NewVariableTotalSize = NewVariableHeaderSize + StrSize (VariableName) + DataSize; + } else { + NewVariableTotalSize = DataSize; + } + + DEBUG ((EFI_D_INFO, "New variable total size (header + data): %d bytes.\n", NewVariableTotalSize)); + + if (TotalVariableStoreRemainingSize < (INT32) NewVariableTotalSize) { + DEBUG ((EFI_D_ERROR, "Cannot save new variable - variable would exceed the maximum store size.\n")); + return EFI_OUT_OF_RESOURCES; + } + + if (VariableNvmDeletedVariablePtrTrack.CurrPtr != NULL) { + NewVariableHeader = VariableNvmDeletedVariablePtrTrack.CurrPtr; + VariableStoreInfo.VariableStoreHeader->VariableHeaderTotalLength -= ((UINT32)GetVariableHeaderSize (VariableStoreInfo.AuthFlag) + + NewVariableHeader->NameSize + + NVM_GET_PAD_SIZE (NewVariableHeader->NameSize) + ); + ZeroMem ( + NewVariableHeader, + GetVariableHeaderSize (VariableStoreInfo.AuthFlag) + + NewVariableHeader->NameSize + + NVM_GET_PAD_SIZE (NewVariableHeader->NameSize) + ); + } else { + NewVariableHeader = GetEndPointer (VariableStoreInfo.VariableStoreHeader); + VariableStoreInfo.VariableStoreHeader->VariableHeaderTotalEntries++; + } + + DEBUG ((EFI_D_INFO, "New variable header (memory) at address 0x%x\n", NewVariableHeader)); + + NewVariableHeader->StartId = VARIABLE_DATA; + NewVariableHeader->State = VAR_ADDED; + NewVariableHeader->Attributes = Attributes; + + NewVariableHeader->DataSize = (UINT32) DataSize; + NewVariableHeader->NameSize = (UINT32) StrSize (VariableName); + + if (VariableCseFileType == CseVariableFileTypePreMemoryFile) { + NewVariableHeader->DataOffset = VariableDataWriteOffset; + } else { + NewVariableHeader->DataOffset = VariableDataFileNumber; + } + + DEBUG ((EFI_D_INFO, "Pre-existing variable header total length = %d bytes\n", VariableStoreInfo.VariableStoreHeader->VariableHeaderTotalLength)); + + CopyMem ( + GetVariableNamePtr (NewVariableHeader, VariableStoreInfo.AuthFlag), + VariableName, + NewVariableHeader->NameSize + ); + CopyMem (&NewVariableHeader->VendorGuid, VendorGuid, sizeof (EFI_GUID)); + + if (VariableStoreInfo.AuthFlag) { + AuthenticatedVariableHeader = (AUTHENTICATED_VARIABLE_NVM_HEADER *) NewVariableHeader; + } + } + + if (VariableStoreInfo.AuthFlag && AuthenticatedVariableHeader != NULL) { + AuthenticatedVariableHeader->MonotonicCount = MonotonicCount; + AuthenticatedVariableHeader->PubKeyIndex = KeyIndex; + + if (((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) && + (TimeStamp != NULL)) { + ZeroMem (&AuthenticatedVariableHeader->TimeStamp, sizeof (EFI_TIME)); + + if ((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) { + CopyMem (&AuthenticatedVariableHeader->TimeStamp, TimeStamp, sizeof (EFI_TIME)); + } else { + // + // In the case when the EFI_VARIABLE_APPEND_WRITE attribute is set, only + // when the new TimeStamp value is later than the current timestamp associated + // with the variable, we need to associate the new timestamp with the updated value. + // + if (VariableNvmCompareTimeStamp (&(((AUTHENTICATED_VARIABLE_HEADER *)IndexVariable->CurrPtr)->TimeStamp), TimeStamp)) { + CopyMem (&AuthenticatedVariableHeader->TimeStamp, TimeStamp, sizeof (EFI_TIME)); + } + } + } + } + + // + // At this point, several writes are pending that will almost certainly increase the size + // of the total variable store. This would be an opportunity to check if a reclaim operation + // is needed based on the known size increase coming. + // + // + // Primary Index File Flow: + // ------------------------ + // If the file exists: + // 1. Update the variable store accounting fields for the new data size if the size has changed. + // 2. Update the data size in the variable header for the data being passed in this function call. + // 2. Write the data out to the existing data file (increasing or decreasing the data in the file). + // If the file does not exist: + // 1. Update the variable store accounting fields for the new variable. + // 2. Write the variable header out to the end of the existing variable store + // 3. Write the variable data out to a new data file + // + + if (UpdatingExistingVariable) { + // + // Update the variable's data size to the new size if needed + // + DEBUG ((EFI_D_INFO, "Checking to see if the existing variable\'s data size varies from the new data...\n")); + if (IndexVariable->CurrPtr->DataSize != DataSize) { + DEBUG ((EFI_D_INFO, "Need to update the size. Updating from %d bytes to %d bytes...\n", IndexVariable->CurrPtr->DataSize, DataSize)); + + if (VariableCseFileType == CseVariableFileTypePreMemoryFile) { + DEBUG ((EFI_D_WARN, "WARNING: The pre-memory file does not support updates that change variable data size!\n")); + return EFI_UNSUPPORTED; + } + + if (IndexVariable->CurrPtr->DataSize < DataSize) { + VariableStoreInfo.VariableStoreHeader->VariableDataTotalLength += (UINT32)(DataSize - IndexVariable->CurrPtr->DataSize); + + } else { + VariableStoreInfo.VariableStoreHeader->VariableDataTotalLength -= (UINT32)(IndexVariable->CurrPtr->DataSize - DataSize); + } + + VariableStoreInfo.VariableStoreHeader->Size = sizeof (VARIABLE_NVM_STORE_HEADER) \ + + VariableStoreInfo.VariableStoreHeader->VariableDataTotalLength \ + + VariableStoreInfo.VariableStoreHeader->VariableHeaderTotalLength; + + // + // The EFI_VARIABLE_APPEND_WRITE attribute will never be set in the returned in the Attributes bitmask. + // + IndexVariable->CurrPtr->Attributes = Attributes & (~EFI_VARIABLE_APPEND_WRITE); + + IndexVariable->CurrPtr->DataSize = (UINT32) DataSize; + + // + // Update the variable header with the new data size + // + Status = UpdateCseNvmFile ( + mCseVariableFileInfo[VariableCseFileType]->FileName, + VariableIndexFileWriteOffset, + (UINT8 *) IndexVariable->CurrPtr, + GetVariableHeaderSize (VariableStoreInfo.AuthFlag), + FALSE, + NULL + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Update the data size in the variable store header + // + Status = UpdateCseNvmFile ( + mCseVariableFileInfo[VariableCseFileType]->FileName, + VariableStoreBaseOffset, + (UINT8 *) VariableStoreInfo.VariableStoreHeader, + sizeof (VARIABLE_NVM_STORE_HEADER), + FALSE, + NULL + ); + + if (EFI_ERROR (Status)) { + return Status; + } + } + } else { + // + // Write out the new variable header and name to the variable header region + // + DEBUG ((EFI_D_INFO, "Writing the variable header to the header region in file since this is a new variable.\n")); + + // + // The EFI_VARIABLE_APPEND_WRITE attribute will never be set in the returned in the Attributes bitmask. + // + NewVariableHeader->Attributes = Attributes & (~EFI_VARIABLE_APPEND_WRITE); + + DEBUG ((EFI_D_INFO, "Writing new variable header to offset 0x%x in the header region.\n", VariableIndexFileWriteOffset)); + + Status = UpdateCseNvmFile ( + mCseVariableFileInfo[VariableCseFileType]->FileName, + VariableIndexFileWriteOffset, + (UINT8 *) NewVariableHeader, + GetVariableHeaderSize (VariableStoreInfo.AuthFlag) + NewVariableHeader->NameSize, + FALSE, + NULL + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Update the variable store properties in the variable store header + // + if (VariableCseFileType == CseVariableFileTypePreMemoryFile) { + VariableStoreInfo.VariableStoreHeader->VariableDataTotalLength += (UINT32) (DataSize + VariablePaddingSize); + } else { + VariableStoreInfo.VariableStoreHeader->VariableDataTotalLength += (UINT32) DataSize; + } + VariableStoreInfo.VariableStoreHeader->VariableHeaderTotalLength += ((UINT32) GetVariableHeaderSize (VariableStoreInfo.AuthFlag) + + NewVariableHeader->NameSize + + NVM_GET_PAD_SIZE (NewVariableHeader->NameSize) + ); + + VariableStoreInfo.VariableStoreHeader->Size = sizeof (VARIABLE_NVM_STORE_HEADER) \ + + VariableStoreInfo.VariableStoreHeader->VariableDataTotalLength \ + + VariableStoreInfo.VariableStoreHeader->VariableHeaderTotalLength; + + DEBUG ((EFI_D_INFO, "Updated the local (memory) variable store for the new variable. Current data:\n")); + + DEBUG ((EFI_D_INFO, " Total size of variable data %d bytes\n", VariableStoreInfo.VariableStoreHeader->VariableDataTotalLength)); + DEBUG ((EFI_D_INFO, " Total size of all variable headers: %d bytes\n", VariableStoreInfo.VariableStoreHeader->VariableHeaderTotalLength)); + DEBUG ((EFI_D_INFO, " Total number of variable entries: %d\n", VariableStoreInfo.VariableStoreHeader->VariableHeaderTotalEntries)); + + DEBUG ((EFI_D_INFO, "Updating the CSE NVM store file with the update to the local variable store:\n")); + + // + // Update the variable store header on NVM to reflect the changes + // + Status = UpdateCseNvmFile ( + mCseVariableFileInfo[VariableCseFileType]->FileName, + VariableStoreBaseOffset, + (UINT8 *) VariableStoreInfo.VariableStoreHeader, + sizeof (VARIABLE_NVM_STORE_HEADER), + FALSE, + NULL + ); + } + + + DEBUG ((EFI_D_INFO, "Writing the variable data to the CSE NVM data file...\n")); + + // + // Write out the variable data to the data file + // + Status = UpdateCseNvmFile ( + &CseVariableDataFileName[0], + VariableDataWriteOffset, + (UINT8 *) Data, + DataSize, + VariableCseFileType != CseVariableFileTypePreMemoryFile, + NULL + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + + +/** + Retrieves a protocol instance-specific GUID. + + Returns a unique GUID per VARIABLE_STORAGE_PROTOCOL instance. + + @param[out] VariableGuid A pointer to an EFI_GUID that is this protocol instance's GUID. + + @retval EFI_SUCCESS The data was returned successfully. + @retval EFI_INVALID_PARAMETER A required parameter is NULL. + +**/ +EFI_STATUS +EFIAPI +CseVariableStorageGetId ( + OUT EFI_GUID *InstanceGuid + ) +{ + if (InstanceGuid == NULL) { + return EFI_INVALID_PARAMETER; + } + + CopyMem (InstanceGuid, &gCseVariableStorageProtocolInstanceGuid, sizeof (EFI_GUID)); + + return EFI_SUCCESS; +} + + +/** + This service 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. + + @param[in] This A pointer to this instance of the VARIABLE_STORAGE_PROTOCOL. + @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. + + @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 +CseVariableStorageGetVariable ( + IN CONST VARIABLE_STORAGE_PROTOCOL *This, + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VariableGuid, + OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, + OUT VOID *Data + ) +{ + // + // Check input parameters + // + if (VariableName == NULL || VariableGuid == NULL || DataSize == NULL) { + return EFI_INVALID_PARAMETER; + } + + DEBUG ((EFI_D_INFO, "Attempting to read CSE NVM variable.\n Name=\'%ls\'\n GUID=%g\n\n", \ + VariableName, VariableGuid)); + + DEBUG ((EFI_D_INFO, "Preparing to call GetCseVariable()\n")); + + return GetCseVariable (mCseVariableFileInfo, VariableName, VariableGuid, Attributes, DataSize, Data, NULL); +} + + +/** + This service retrieves an authenticated variable's value using its name and GUID. + + Read the specified authenticated variable from the UEFI 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. + + @param[in] This A pointer to this instance of the VARIABLE_STORAGE_PROTOCOL. + @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] KeyIndex Index of associated public key in database + @param[out] MonotonicCount Associated monotonic count value to protect against replay attack + @param[out] TimeStamp Associated TimeStamp value to protect against replay attack + + @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 +CseVariableStorageGetAuthenticatedVariable ( + IN CONST VARIABLE_STORAGE_PROTOCOL *This, + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VariableGuid, + OUT UINT32 *Attributes, + IN OUT UINTN *DataSize, + OUT VOID *Data, + OUT UINT32 *KeyIndex, + OUT UINT64 *MonotonicCount, + OUT EFI_TIME *TimeStamp + ) +{ + EFI_STATUS Status; + AUTHENTICATED_VARIABLE_NVM_HEADER *AuthenticatedVariableHeader = NULL; + + // + // Check input parameters + // + if (VariableName == NULL || VariableGuid == NULL || DataSize == NULL || + KeyIndex == NULL || MonotonicCount == NULL || TimeStamp == NULL) { + return EFI_INVALID_PARAMETER; + } + + DEBUG ((EFI_D_INFO, "Attempting to read CSE NVM authenticated variable.\n Name=\'%ls\'\n GUID=%g\n\n", \ + VariableName, VariableGuid)); + + DEBUG ((EFI_D_INFO, "Preparing to call GetCseVariable()\n")); + + Status = GetCseVariable (mCseVariableFileInfo, VariableName, VariableGuid, Attributes, DataSize, Data, (VARIABLE_NVM_HEADER *) AuthenticatedVariableHeader); + + if (!EFI_ERROR (Status) && AuthenticatedVariableHeader != NULL) { + *KeyIndex = AuthenticatedVariableHeader->PubKeyIndex; + *MonotonicCount = AuthenticatedVariableHeader->MonotonicCount; + + CopyMem (TimeStamp, &AuthenticatedVariableHeader->TimeStamp, sizeof (EFI_TIME)); + } + + return Status; +} + + +/** + Return the next variable name and GUID. + + This function is called multiple times to retrieve the VariableName + and VariableGuid of all variables currently available in the system. + On each call, the previous results are passed into the interface, + and, on return, the interface returns the data for the next + interface. When the entire variable list has been returned, + EFI_NOT_FOUND is returned. + + @param[in] This A pointer to this instance of the VARIABLE_STORAGE_PROTOCOL. + + @param[in, out] VariableNameSize On entry, points to the size of the buffer pointed to by + VariableName. On return, the size of the variable name buffer. + @param[in, out] VariableName On entry, a pointer to a null-terminated string that is the + variable's name. On return, points to the next variable's + null-terminated name string. + @param[in, out] VariableGuid On entry, a pointer to an EFI_GUID that is the variable's GUID. + On return, a pointer to the next variable's GUID. + @param[out] VariableAttributes A pointer to the variable attributes. + + @retval EFI_SUCCESS The variable was read successfully. + @retval EFI_NOT_FOUND The variable could not be found. + @retval EFI_BUFFER_TOO_SMALL The VariableNameSize is too small for the resulting + data. VariableNameSize is updated with the size + required for the specified variable. + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or + VariableNameSize is NULL. + @retval EFI_DEVICE_ERROR The variable could not be retrieved because of a device error. + +**/ +EFI_STATUS +EFIAPI +CseVariableStorageGetNextVariableName ( + IN CONST VARIABLE_STORAGE_PROTOCOL *This, + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VariableGuid, + OUT UINT32 *VariableAttributes + ) +{ + EFI_STATUS Status; + BOOLEAN IsAuthVariable; + UINTN VarNameSize; + VARIABLE_NVM_HEADER *VariablePtr; + + if (VariableNameSize == NULL || VariableName == NULL || VariableGuid == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = GetNextCseVariableName (VariableName, VariableGuid, mCseVariableFileInfo, &VariablePtr, &IsAuthVariable); + + if (EFI_ERROR (Status)) { + return Status; + } + + VarNameSize = NameSizeOfVariable (VariablePtr, IsAuthVariable); + ASSERT (VarNameSize != 0); + + if (VarNameSize <= *VariableNameSize) { + CopyMem (VariableName, GetVariableNamePtr (VariablePtr, IsAuthVariable), VarNameSize); + CopyMem (VariableGuid, GetVendorGuidPtr (VariablePtr, IsAuthVariable), sizeof (EFI_GUID)); + Status = EFI_SUCCESS; + } else { + Status = EFI_BUFFER_TOO_SMALL; + } + *VariableNameSize = VarNameSize; + *VariableAttributes = VariablePtr->Attributes; + + return Status; +} + + +/** + Returns information on the amount of space available in the variable store. If the amount of data that can be written + depends on if the platform is in Pre-OS stage or OS stage, the AtRuntime parameter should be used to compute usage. + + @param[in] This A pointer to this instance of the VARIABLE_STORAGE_PROTOCOL. + @param[in] AtRuntime TRUE is the platform is in OS Runtime, FALSE if still in Pre-OS stage + @param[out] VariableStoreSize The total size of the NV storage. Indicates the maximum amount + of data that can be stored in this NV storage area. + @param[out] CommonVariablesTotalSize The total combined size of all the common UEFI variables that are + stored in this NV storage area. Excludes variables with the + EFI_VARIABLE_HARDWARE_ERROR_RECORD attribute set. + @param[out] HwErrVariablesTotalSize The total combined size of all the UEFI variables that have the + EFI_VARIABLE_HARDWARE_ERROR_RECORD attribute set and which are + stored in this NV storage area. Excludes all other variables. + + @retval EFI_INVALID_PARAMETER Any of the given parameters are NULL + @retval EFI_SUCCESS Space information returned successfully. + +**/ +EFI_STATUS +EFIAPI +CseVariableStorageGetStorageUsage ( + IN CONST VARIABLE_STORAGE_PROTOCOL *This, + IN BOOLEAN AtRuntime, + OUT UINT32 *VariableStoreSize, + OUT UINT32 *CommonVariablesTotalSize, + OUT UINT32 *HwErrVariablesTotalSize + ) +{ + BOOLEAN IsAuthVariable; + CSE_VARIABLE_FILE_TYPE Type; + EFI_GUID Guid; + EFI_STATUS Status; + UINT32 Attributes; + VARIABLE_NVM_POINTER_TRACK VariablePtrTrack; + CHAR16 *VariableName = NULL; + UINTN VariableNameSize = 0; + UINTN NewVariableNameSize = 0; + UINTN CseVariableTotalStoreSizeInternal = 0; + UINTN CseCommonVariablesTotalSizeInternal = 0; + UINTN CseHwErrVariablesTotalSizeInternal = 0; + + for (Type = (CSE_VARIABLE_FILE_TYPE) 0; Type < CseVariableFileTypeMax; Type++) { + if (mCseVariableFileInfo[Type] != NULL && mCseVariableFileInfo[Type]->FileStoreEstablished) { + CseVariableTotalStoreSizeInternal += (mCseVariableFileInfo[Type]->FileStoreMaximumSize - sizeof (VARIABLE_NVM_STORE_HEADER)); + DEBUG ((EFI_D_INFO, "Current store maximum size = %d bytes.\n", mCseVariableFileInfo[Type]->FileStoreMaximumSize)); + } + + } + ASSERT (CseVariableTotalStoreSizeInternal > 0); + + VariableNameSize = sizeof (CHAR16); + VariableName = AllocateZeroPool (VariableNameSize); + if (VariableName == NULL) { + ASSERT (VariableName != NULL); + return EFI_OUT_OF_RESOURCES; + } + + while (TRUE) { + NewVariableNameSize = VariableNameSize; + Status = CseVariableStorageGetNextVariableName (This, &NewVariableNameSize, VariableName, &Guid, &Attributes); + + if (Status == EFI_BUFFER_TOO_SMALL) { + VariableName = ReallocatePool (VariableNameSize, NewVariableNameSize, VariableName); + if (VariableName == NULL) { + ASSERT (VariableName != NULL); + return EFI_OUT_OF_RESOURCES; + } + Status = CseVariableStorageGetNextVariableName (This, &NewVariableNameSize, VariableName, &Guid, &Attributes); + VariableNameSize = NewVariableNameSize; + } + + if (Status == EFI_NOT_FOUND) { + break; + } + ASSERT_EFI_ERROR (Status); + + // + // Get the variable header for this variable + // + Status = FindVariable (VariableName, &Guid, mCseVariableFileInfo, &VariablePtrTrack); + + if (EFI_ERROR (Status) || VariablePtrTrack.CurrPtr == NULL) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + Type = GetCseVariableStoreFileType (VariableName, &Guid, mCseVariableFileInfo); + + Status = IsAuthenticatedVariableStore ((VARIABLE_NVM_STORE_HEADER *) (UINTN) mCseVariableFileInfo[Type]->HeaderRegionBase, &IsAuthVariable); + + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + // + // When the reclaim operation is implemented, need to do a runtime check. + // At runtime, don't worry about the variable state. At boot time, the + // state needs to be taken into account because the variables can be reclaimed. + // + if ((VariablePtrTrack.CurrPtr->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) { + CseHwErrVariablesTotalSizeInternal += GetVariableHeaderSize (IsAuthVariable); + CseHwErrVariablesTotalSizeInternal += VariablePtrTrack.CurrPtr->NameSize; + CseHwErrVariablesTotalSizeInternal += VariablePtrTrack.CurrPtr->DataSize; + } else { + CseCommonVariablesTotalSizeInternal += GetVariableHeaderSize (IsAuthVariable); + CseCommonVariablesTotalSizeInternal += VariablePtrTrack.CurrPtr->NameSize; + CseCommonVariablesTotalSizeInternal += VariablePtrTrack.CurrPtr->DataSize; + } + } + + FreePool (VariableName); + + *VariableStoreSize = (UINT32) CseVariableTotalStoreSizeInternal; + *CommonVariablesTotalSize = (UINT32) CseCommonVariablesTotalSizeInternal; + *HwErrVariablesTotalSize = (UINT32) CseHwErrVariablesTotalSizeInternal; + + return EFI_SUCCESS; +} + + +/** + Returns whether this NV storage area supports storing authenticated variables or not + + @param[in] This A pointer to this instance of the VARIABLE_STORAGE_PROTOCOL. + @param[out] AuthSupported TRUE if this NV storage area can store authenticated variables, + FALSE otherwise + + @retval EFI_SUCCESS AuthSupported was returned successfully. + +**/ +EFI_STATUS +EFIAPI +CseVariableStorageGetAuthenticatedSupport ( + IN CONST VARIABLE_STORAGE_PROTOCOL *This, + OUT BOOLEAN *AuthSupported + ) +{ + *AuthSupported = TRUE; + + return EFI_SUCCESS; +} + + +/** + This code sets a variable's value using its name and GUID. + + Caution: This function may receive untrusted input. + This function may be invoked in SMM mode, and datasize and data are external input. + This function will do basic validation, before parsing the data. + This function will parse the authentication carefully to avoid security issues, like + buffer overflow, integer overflow. + This function will check attribute carefully to avoid authentication bypass. + + @param[in] This A pointer to this instance of the VARIABLE_STORAGE_PROTOCOL. + @param[in] VariableName Name of Variable to be found. + @param[in] VendorGuid Variable vendor GUID. + @param[in] Attributes Attribute value of the variable found + @param[in] DataSize Size of Data found. If size is less than the + data, this value contains the required size. + @param[in] Data Data pointer. + @param[in] AtRuntime TRUE is the platform is in OS Runtime, FALSE if still in Pre-OS stage + @param[in] KeyIndex If writing an authenticated variable, the public key index + @param[in] MonotonicCount If writing a monotonic counter authenticated variable, the counter value + @param[in] TimeStamp If writing a timestamp authenticated variable, the timestamp value + + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_SUCCESS Set successfully. + @retval EFI_OUT_OF_RESOURCES Resource not enough to set variable. + @retval EFI_NOT_FOUND Not found. + @retval EFI_WRITE_PROTECTED Variable is read-only. + +**/ +EFI_STATUS +EFIAPI +CseVariableStorageSetVariable ( + IN CONST VARIABLE_STORAGE_PROTOCOL *This, + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN UINTN DataSize, + IN VOID *Data, + IN BOOLEAN AtRuntime, + IN UINT32 KeyIndex OPTIONAL, + IN UINT64 MonotonicCount OPTIONAL, + IN EFI_TIME *TimeStamp OPTIONAL + ) +{ + EFI_STATUS Status; + VARIABLE_NVM_POINTER_TRACK VariablePtrTrack; + + // + // Check input parameters. + // + if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (DataSize != 0 && Data == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (((Attributes & EFI_VARIABLE_NON_VOLATILE) != EFI_VARIABLE_NON_VOLATILE) && (DataSize != 0)) { + DEBUG ((EFI_D_ERROR, "A volatile variable was passed to the CSE storage protocol.\n")); + return EFI_INVALID_PARAMETER; + } + + + if (AtRuntime && mIsEmmcBoot) { + DEBUG ((EFI_D_ERROR, "Performing workaround for eMMC boot issue\n")); + return EFI_SUCCESS; + } + + DEBUG ((EFI_D_INFO, "Attempting to set CSE NVM variable.\n Name=\'%ls\'\n GUID=%g\n Attributes=0x%x\n\n", \ + VariableName, *VendorGuid, Attributes)); + + if (PcdGet32 (PcdMaxVariableSize) - sizeof (VARIABLE_NVM_HEADER) <= StrSize (VariableName) + DataSize) { + DEBUG ((EFI_D_ERROR, "The variable being written is larger than the maximum specified variable size.\n")); + return EFI_INVALID_PARAMETER; + } + + // + // Check if the variable already exists + // + Status = FindVariable (VariableName, VendorGuid, mCseVariableFileInfo, &VariablePtrTrack); + if (!EFI_ERROR (Status)) { + if (Attributes != 0 && (Attributes & (~EFI_VARIABLE_APPEND_WRITE)) != VariablePtrTrack.CurrPtr->Attributes) { + DEBUG ((EFI_D_ERROR, "Error: Attributes given do not match the existing variable.\n")); + DEBUG ((EFI_D_ERROR, " Attributes given = 0x%x. Existing attributes = 0x%x.\n", Attributes, VariablePtrTrack.CurrPtr->Attributes)); + return EFI_INVALID_PARAMETER; + } + } else if (Status != EFI_NOT_FOUND) { + DEBUG ((EFI_D_ERROR, "Error occurred finding the variable.\n")); + return Status; + } + + DEBUG ((EFI_D_INFO, "VariablePtrTrack->CurrPtr is null = %c\n", (VariablePtrTrack.CurrPtr == NULL ? 'T' : 'F'))); + + Status = UpdateVariable (VariableName, VendorGuid, Data, DataSize, Attributes, &VariablePtrTrack, KeyIndex, MonotonicCount, TimeStamp); + if (!EFI_ERROR (Status)) { + DEBUG ((EFI_D_INFO, "The variable was updated successfully.\n")); + } + + return Status; +} + + +/** + Returns whether this NV storage area is ready to accept calls to SetVariable() or not + + @param[in] This A pointer to this instance of the VARIABLE_STORAGE_PROTOCOL. + + @retval TRUE The NV storage area is ready to accept calls to SetVariable() + @retval FALSE The NV storage area is not ready to accept calls to SetVariable() + +**/ +BOOLEAN +EFIAPI +CseVariableStorageWriteServiceIsReady ( + IN CONST VARIABLE_STORAGE_PROTOCOL *This + ) +{ + // + // CSE should be ready to service write commands when this driver is loaded + // + return TRUE; +} + + +/** + Sets the callback to be invoked when the VARIABLE_STORAGE_PROTOCOL is ready to accept calls to SetVariable() + + The VARIABLE_STORAGE_PROTOCOL is required to invoke the callback as quickly as possible after the core + variable driver invokes RegisterWriteServiceReadyCallback() to set the callback. + + @param[in] This A pointer to this instance of the VARIABLE_STORAGE_PROTOCOL. + @param[in] CallbackFunction The callback function + + @retval EFI_SUCCESS The callback function was sucessfully registered + +**/ +EFI_STATUS +EFIAPI +CseVariableStorageRegisterWriteServiceReadyCallback ( + IN CONST VARIABLE_STORAGE_PROTOCOL *This, + IN VARIABLE_STORAGE_WRITE_SERVICE_READY_CALLBACK CallbackFunction + ) +{ + // + // CSE should be ready to service write commands when this driver is loaded + // immediately invoke the callback function + // + return CallbackFunction (); +} + diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Dxe/CseVariableStorageSmmRuntimeDxe/CseVariableStorage.h b/Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Dxe/CseVariableStorageSmmRuntimeDxe/CseVariableStorage.h new file mode 100644 index 0000000000..57dce9d4ff --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Dxe/CseVariableStorageSmmRuntimeDxe/CseVariableStorage.h @@ -0,0 +1,72 @@ +/** @file + Defines common functions used in CseVariableStorage. + + 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_H_ +#define _CSE_VARIABLE_STORAGE_H_ + +#include "CseVariableStorageSmmRuntimeDxe.h" +#include +#include +#include + +extern CSE_VARIABLE_FILE_INFO *mCseVariableFileInfo[]; +extern VARIABLE_STORAGE_PROTOCOL mCseVariableStorageProtocol; + +/** + Performs common initialization needed for this module. + + @param None + + @retval EFI_SUCCESS The module was initialized successfully. + @retval Others The module could not be initialized. + +**/ +EFI_STATUS +EFIAPI +CseVariableStorageCommonInitialize ( + VOID + ); + +/** + Update the CSE NVM variable with the supplied data. These are the same + arguments as the EFI Variable services. + + @param[in] VariableName Name of variable. + @param[in] VendorGuid Guid of variable. + @param[in] Data Variable data. + @param[in] DataSize Size of data. 0 means delete. + @param[in] Attributes Attributes of the variable. + @param[in, out] IndexVariable The variable found in the header region corresponding to this variable. + + @retval EFI_SUCCESS The update operation is success. + @retval Others The variable update operation failed. + +**/ +EFI_STATUS +UpdateVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN VOID *Data, + IN UINTN DataSize, + IN UINT32 Attributes, + IN OUT VARIABLE_NVM_POINTER_TRACK *IndexVariable, + IN UINT32 KeyIndex OPTIONAL, + IN UINT64 MonotonicCount OPTIONAL, + IN EFI_TIME *TimeStamp OPTIONAL + ); + +#endif + diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Dxe/CseVariableStorageSmmRuntimeDxe/CseVariableStorageRuntimeDxe.c b/Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Dxe/CseVariableStorageSmmRuntimeDxe/CseVariableStorageRuntimeDxe.c new file mode 100644 index 0000000000..c1562ef541 --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Dxe/CseVariableStorageSmmRuntimeDxe/CseVariableStorageRuntimeDxe.c @@ -0,0 +1,114 @@ +/** @file + Implements CSE Variable Storage Services and installs + an instance of the VariableStorage Runtime DXE protocol. + + 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 "CseVariableStorage.h" +#include +#include + +// +// Module globals +// +static EFI_EVENT mVirtualAddressChangeEvent = NULL; + +/** + 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 +CseVariableStorageAddressChangeEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + CSE_VARIABLE_FILE_TYPE Type; + + EfiConvertPointer (0x0, (VOID **) &mCseVariableStorageProtocol.GetAuthenticatedSupport); + EfiConvertPointer (0x0, (VOID **) &mCseVariableStorageProtocol.GetAuthenticatedVariable); + EfiConvertPointer (0x0, (VOID **) &mCseVariableStorageProtocol.GetId); + EfiConvertPointer (0x0, (VOID **) &mCseVariableStorageProtocol.GetNextVariableName); + EfiConvertPointer (0x0, (VOID **) &mCseVariableStorageProtocol.GetStorageUsage); + EfiConvertPointer (0x0, (VOID **) &mCseVariableStorageProtocol.GetVariable); + EfiConvertPointer (0x0, (VOID **) &mCseVariableStorageProtocol.RegisterWriteServiceReadyCallback); + EfiConvertPointer (0x0, (VOID **) &mCseVariableStorageProtocol.SetVariable); + EfiConvertPointer (0x0, (VOID **) &mCseVariableStorageProtocol.WriteServiceIsReady); + EfiConvertPointer (0x0, (VOID **) &mCseVariableStorageProtocol); + + for (Type = (CSE_VARIABLE_FILE_TYPE) 0; Type < CseVariableFileTypeMax; Type++) { + EfiConvertPointer (0x0, (VOID **) &mCseVariableFileInfo[Type]->FileName); + EfiConvertPointer (0x0, (VOID **) &mCseVariableFileInfo[Type]->HeaderRegionBase); + EfiConvertPointer (0x0, (VOID **) &mCseVariableFileInfo[Type]); + } +} + + +/** + Provide DXE functionality of CSE NVM variable storage services. + + @param[in] ImageHandle The image handle. + @param[in] SystemTable The system table. + + @retval EFI_SUCCESS The protocol was installed successfully. + @retval Others Protocol could not be installed. + +**/ +EFI_STATUS +EFIAPI +CseVariableStorageDxeRuntimeInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle = NULL; + EFI_HOB_GUID_TYPE *FdoEnabledGuidHob = NULL; + + DEBUG ((EFI_D_INFO, "\n\n======\nCSE Variable Storage DXE Protocol Initialization\n======\n\n")); + + FdoEnabledGuidHob = GetFirstGuidHob (&gFdoModeEnabledHobGuid); + + if (FdoEnabledGuidHob == NULL) { + Status = CseVariableStorageCommonInitialize (); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + CseVariableStorageAddressChangeEvent, + NULL, + &gEfiEventVirtualAddressChangeGuid, + &mVirtualAddressChangeEvent + ); + ASSERT_EFI_ERROR (Status); + } + Status = gBS->InstallProtocolInterface ( + &Handle, + &gVariableStorageProtocolGuid, + EFI_NATIVE_INTERFACE, + &mCseVariableStorageProtocol + ); + + return Status; +} + diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Dxe/CseVariableStorageSmmRuntimeDxe/CseVariableStorageRuntimeDxe.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Dxe/CseVariableStorageSmmRuntimeDxe/CseVariableStorageRuntimeDxe.inf new file mode 100644 index 0000000000..b679c3bce7 --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Dxe/CseVariableStorageSmmRuntimeDxe/CseVariableStorageRuntimeDxe.inf @@ -0,0 +1,67 @@ +## @file +# Component description file for the CSE Variable Storage Runtime DXE Module. +# +# 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 = 0x00010017 + BASE_NAME = CseVariableStorageRuntimeDxe + FILE_GUID = CB46E28C-1A19-439F-B306-719BEF3C4500 + MODULE_TYPE = DXE_RUNTIME_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = CseVariableStorageDxeRuntimeInitialize + +[Sources] + CseVariableStorage.c + CseVariableStorageRuntimeDxe.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + BroxtonSiPkg/BroxtonSiPkg.dec + BroxtonSiPkg/BroxtonSiPrivate.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + CseVariableStorageLib + CseVariableStorageSelectorLib + DebugLib + HeciMsgLib + HobLib + MemoryAllocationLib + PcdLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UefiRuntimeLib + VariableNvmStorageLib + +[Guids] + gCseVariableStorageProtocolInstanceGuid ## PRODUCES + gCseVariableFileInfoHobGuid ## CONSUMES ## GUID + gCsePreMemoryIndexFileDataHobGuid ## CONSUMES ## GUID + gCsePrimaryIndexFileDataHobGuid ## CONSUMES ## GUID + gFdoModeEnabledHobGuid ## CONSUMES ## GUID + gEfiSetupVariableGuid ## CONSUMES ## GUID + gEfiEventVirtualAddressChangeGuid ## CONSUMES ## Event + gEfiBootMediaHobGuid ## CONSUMES + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize ## CONSUMES + +[Protocols] + gEfiHeciProtocolGuid ## CONSUMES + gVariableStorageProtocolGuid ## PRODUCES + +[Depex] + TRUE diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Dxe/CseVariableStorageSmmRuntimeDxe/CseVariableStorageSmmRuntimeDxe.c b/Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Dxe/CseVariableStorageSmmRuntimeDxe/CseVariableStorageSmmRuntimeDxe.c new file mode 100644 index 0000000000..f9fd9bcf59 --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Dxe/CseVariableStorageSmmRuntimeDxe/CseVariableStorageSmmRuntimeDxe.c @@ -0,0 +1,61 @@ +/** @file + Implements CSE Variable Storage Services and installs + an instance of the VariableStorage Runtime DXE protocol. + + 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 "CseVariableStorage.h" +#include + +/** + Provide SMM functionality of CSE NVM variable storage services. + + @param[in] ImageHandle The image handle. + @param[in] SystemTable The system table. + + @retval EFI_SUCCESS The protocol was installed successfully. + @retval Others Protocol could not be installed. + +**/ +EFI_STATUS +EFIAPI +CseVariableStorageSmmRuntimeInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle = NULL; + EFI_HOB_GUID_TYPE *FdoEnabledGuidHob = NULL; + + FdoEnabledGuidHob = GetFirstGuidHob (&gFdoModeEnabledHobGuid); + + if (FdoEnabledGuidHob == NULL) { + Status = CseVariableStorageCommonInitialize (); + + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + } + + Status = gSmst->SmmInstallProtocolInterface ( + &Handle, + &gVariableStorageProtocolGuid, + EFI_NATIVE_INTERFACE, + &mCseVariableStorageProtocol + ); + + return Status; +} + diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Dxe/CseVariableStorageSmmRuntimeDxe/CseVariableStorageSmmRuntimeDxe.h b/Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Dxe/CseVariableStorageSmmRuntimeDxe/CseVariableStorageSmmRuntimeDxe.h new file mode 100644 index 0000000000..04865e0a75 --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Dxe/CseVariableStorageSmmRuntimeDxe/CseVariableStorageSmmRuntimeDxe.h @@ -0,0 +1,311 @@ +/** @file + This file contains the required header files for the + CSE Variable Storage Runtime DXE protocol. + + 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_PROTOCOL_H_ +#define _CSE_VARIABLE_STORAGE_PROTOCOL_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + Provide the functionality of CSE NVM variable storage services. + + @param[in] ImageHandle The image handle. + @param[in] SystemTable The system table. + + @retval EFI_SUCCESS The protocol was installed successfully. + @retval Others Protocol could not be installed. + +**/ +EFI_STATUS +EFIAPI +CseVariableStorageSmmRuntimeInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Retrieves a protocol instance-specific GUID. + + Returns a unique GUID per VARIABLE_STORAGE_PROTOCOL instance. + + @param[out] VariableGuid A pointer to an EFI_GUID that is this protocol instance's GUID. + + @retval EFI_SUCCESS The data was returned successfully. + @retval EFI_INVALID_PARAMETER A required parameter is NULL. + +**/ +EFI_STATUS +EFIAPI +CseVariableStorageGetId ( + OUT EFI_GUID *InstanceGuid + ); + +/** + This service 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. + + @param[in] This A pointer to this instance of the VARIABLE_STORAGE_PROTOCOL. + @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. + + @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 +CseVariableStorageGetVariable ( + IN CONST VARIABLE_STORAGE_PROTOCOL *This, + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VariableGuid, + OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, + OUT VOID *Data + ); + +/** + This service retrieves an authenticated variable's value using its name and GUID. + + Read the specified authenticated variable from the UEFI 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. + + @param[in] This A pointer to this instance of the VARIABLE_STORAGE_PROTOCOL. + @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] KeyIndex Index of associated public key in database + @param[out] MonotonicCount Associated monotonic count value to protect against replay attack + @param[out] TimeStamp Associated TimeStamp value to protect against replay attack + + @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 +CseVariableStorageGetAuthenticatedVariable ( + IN CONST VARIABLE_STORAGE_PROTOCOL *This, + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VariableGuid, + OUT UINT32 *Attributes, + IN OUT UINTN *DataSize, + OUT VOID *Data, + OUT UINT32 *KeyIndex, + OUT UINT64 *MonotonicCount, + OUT EFI_TIME *TimeStamp + ); + +/** + Return the next variable name and GUID. + + This function is called multiple times to retrieve the VariableName + and VariableGuid of all variables currently available in the system. + On each call, the previous results are passed into the interface, + and, on return, the interface returns the data for the next + interface. When the entire variable list has been returned, + EFI_NOT_FOUND is returned. + + @param[in] This A pointer to this instance of the VARIABLE_STORAGE_PROTOCOL. + + @param[in, out] VariableNameSize On entry, points to the size of the buffer pointed to by + VariableName. On return, the size of the variable name buffer. + @param[in, out] VariableName On entry, a pointer to a null-terminated string that is the + variable's name. On return, points to the next variable's + null-terminated name string. + @param[in, out] VariableGuid On entry, a pointer to an EFI_GUID that is the variable's GUID. + On return, a pointer to the next variable's GUID. + @param[out] VariableAttributes A pointer to the variable attributes. + + @retval EFI_SUCCESS The variable was read successfully. + @retval EFI_NOT_FOUND The variable could not be found. + @retval EFI_BUFFER_TOO_SMALL The VariableNameSize is too small for the resulting + data. VariableNameSize is updated with the size + required for the specified variable. + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or + VariableNameSize is NULL. + @retval EFI_DEVICE_ERROR The variable could not be retrieved because of a device error. +**/ +EFI_STATUS +EFIAPI +CseVariableStorageGetNextVariableName ( + IN CONST VARIABLE_STORAGE_PROTOCOL *This, + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VariableGuid, + OUT UINT32 *VariableAttributes + ); + +/** + Returns information on the amount of space available in the variable store + + @param[in] This A pointer to this instance of the VARIABLE_STORAGE_PROTOCOL. + @param[in] AtRuntime TRUE is the platform is in OS Runtime, FALSE if still in Pre-OS stage + @param[out] VariableStoreSize The total size of the NV storage. Indicates the maximum amount + of data that can be stored in this NV storage area. + @param[out] CommonVariablesTotalSize The total combined size of all the common UEFI variables that are + stored in this NV storage area. Excludes variables with the + EFI_VARIABLE_HARDWARE_ERROR_RECORD attribute set. + @param[out] HwErrVariablesTotalSize The total combined size of all the UEFI variables that have the + EFI_VARIABLE_HARDWARE_ERROR_RECORD attribute set and which are + stored in this NV storage area. Excludes all other variables. + + @retval EFI_INVALID_PARAMETER Any of the given parameters are NULL + @retval EFI_SUCCESS Space information returned successfully. + +**/ +EFI_STATUS +EFIAPI +CseVariableStorageGetStorageUsage ( + IN CONST VARIABLE_STORAGE_PROTOCOL *This, + IN BOOLEAN AtRuntime, + OUT UINT32 *VariableStoreSize, + OUT UINT32 *CommonVariablesTotalSize, + OUT UINT32 *HwErrVariablesTotalSize + ); + +/** + Returns whether this NV storage area supports storing authenticated variables or not + + @param[in] This A pointer to this instance of the VARIABLE_STORAGE_PROTOCOL. + @param[out] AuthSupported TRUE if this NV storage area can store authenticated variables, + FALSE otherwise + + @retval EFI_SUCCESS AuthSupported was returned successfully. + +**/ +EFI_STATUS +EFIAPI +CseVariableStorageGetAuthenticatedSupport ( + IN CONST VARIABLE_STORAGE_PROTOCOL *This, + OUT BOOLEAN *AuthSupported + ); + +/** + This code sets a variable's value using its name and GUID. + + Caution: This function may receive untrusted input. + This function may be invoked in SMM mode, and datasize and data are external input. + This function will do basic validation, before parsing the data. + This function will parse the authentication carefully to avoid security issues, like + buffer overflow, integer overflow. + This function will check attribute carefully to avoid authentication bypass. + + @param[in] This A pointer to this instance of the VARIABLE_STORAGE_PROTOCOL. + @param[in] VariableName Name of Variable to be found. + @param[in] VendorGuid Variable vendor GUID. + @param[in] Attributes Attribute value of the variable found + @param[in] DataSize Size of Data found. If size is less than the + data, this value contains the required size. + @param[in] Data Data pointer. + @param[in] AtRuntime TRUE is the platform is in OS Runtime, FALSE if still in Pre-OS stage + @param[in] KeyIndex If writing an authenticated variable, the public key index + @param[in] MonotonicCount If writing a monotonic counter authenticated variable, the counter value + @param[in] TimeStamp If writing a timestamp authenticated variable, the timestamp value + + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_SUCCESS Set successfully. + @retval EFI_OUT_OF_RESOURCES Resource not enough to set variable. + @retval EFI_NOT_FOUND Not found. + @retval EFI_WRITE_PROTECTED Variable is read-only. + +**/ +EFI_STATUS +EFIAPI +CseVariableStorageSetVariable ( + IN CONST VARIABLE_STORAGE_PROTOCOL *This, + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN UINTN DataSize, + IN VOID *Data, + IN BOOLEAN AtRuntime, + IN UINT32 KeyIndex OPTIONAL, + IN UINT64 MonotonicCount OPTIONAL, + IN EFI_TIME *TimeStamp OPTIONAL + ); + +/** + Returns whether this NV storage area is ready to accept calls to SetVariable() or not + + @param[in] This A pointer to this instance of the VARIABLE_STORAGE_PROTOCOL. + + @retval TRUE The NV storage area is ready to accept calls to SetVariable() + @retval FALSE The NV storage area is not ready to accept calls to SetVariable() + +**/ +BOOLEAN +EFIAPI +CseVariableStorageWriteServiceIsReady ( + IN CONST VARIABLE_STORAGE_PROTOCOL *This + ); + +/** + Sets the callback to be invoked when the VARIABLE_STORAGE_PROTOCOL is ready to accept calls to SetVariable() + + The VARIABLE_STORAGE_PROTOCOL is required to invoke the callback as quickly as possible after the core + variable driver invokes RegisterWriteServiceReadyCallback() to set the callback. + + @param[in] This A pointer to this instance of the VARIABLE_STORAGE_PROTOCOL. + @param[in] CallbackFunction The callback function + + @retval EFI_SUCCESS The callback function was sucessfully registered + +**/ +EFI_STATUS +EFIAPI +CseVariableStorageRegisterWriteServiceReadyCallback ( + IN CONST VARIABLE_STORAGE_PROTOCOL *This, + IN VARIABLE_STORAGE_WRITE_SERVICE_READY_CALLBACK CallbackFunction + ); + +#endif + diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Dxe/CseVariableStorageSmmRuntimeDxe/CseVariableStorageSmmRuntimeDxe.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Dxe/CseVariableStorageSmmRuntimeDxe/CseVariableStorageSmmRuntimeDxe.inf new file mode 100644 index 0000000000..3f24f12fa0 --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Dxe/CseVariableStorageSmmRuntimeDxe/CseVariableStorageSmmRuntimeDxe.inf @@ -0,0 +1,68 @@ +## @file +# Component description file for the CSE Variable Storage Runtime SMM Module. +# +# 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 = CseVariableStorageSmmRuntimeDxe + FILE_GUID = 17B06CE0-E98A-40E5-8ABE-657C95121F4E + MODULE_TYPE = DXE_SMM_DRIVER + VERSION_STRING = 1.0 + PI_SPECIFICATION_VERSION = 0x0001000A + ENTRY_POINT = CseVariableStorageSmmRuntimeInitialize + +[Sources] + CseVariableStorage.c + CseVariableStorageSmmRuntimeDxe.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + BroxtonSiPkg/BroxtonSiPkg.dec + BroxtonSiPkg/BroxtonSiPrivate.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + CseVariableStorageLib + CseVariableStorageSelectorLib + DebugLib + HeciMsgLib + HobLib + MemoryAllocationLib + PcdLib + SmmHeciMsgLib + SmmServicesTableLib + UefiDriverEntryPoint + VariableNvmStorageLib + +[Guids] + gCseVariableStorageProtocolInstanceGuid ## PRODUCES + gCseVariableFileInfoHobGuid ## CONSUMES ## GUID + gCsePreMemoryIndexFileDataHobGuid ## CONSUMES ## GUID + gCsePrimaryIndexFileDataHobGuid ## CONSUMES ## GUID + gFdoModeEnabledHobGuid ## CONSUMES ## GUID + gEfiSetupVariableGuid ## CONSUMES ## GUID + gEfiEventVirtualAddressChangeGuid ## CONSUMES ## Event + gEfiBootMediaHobGuid ## CONSUMES + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize ## CONSUMES + +[Protocols] + gEfiHeciProtocolGuid ## CONSUMES + gVariableStorageProtocolGuid ## PRODUCES + +[Depex] + TRUE diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Pei/CseVariableStoragePei/CseVariableStoragePei.c b/Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Pei/CseVariableStoragePei/CseVariableStoragePei.c new file mode 100644 index 0000000000..7040418c48 --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Pei/CseVariableStoragePei/CseVariableStoragePei.c @@ -0,0 +1,353 @@ +/** @file + This PEIM implements CSE Variable Storage Services and installs + an instance of the VariableStorage PPI. + + 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 "CseVariableStoragePei.h" + +// +// Module globals +// +static VARIABLE_STORAGE_PPI mCseVariableStoragePpi = { + PeiCseVariableStorageGetId, + PeiCseVariableStorageGetVariable, + PeiCseVariableStorageGetNextVariableName +}; + +static EFI_PEI_PPI_DESCRIPTOR mPpiListVariable = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gVariableStoragePpiGuid, + &mCseVariableStoragePpi +}; + +/** + Initializes data structures used by the PEIM. + + @param None + + @retval EFI_SUCCESS The data structures were initialized successfully. + @retval Others An error occurred initializing the data structures. + +**/ +EFI_STATUS +EFIAPI +PeimInitializeDataStructures ( + VOID + ) +{ + EFI_STATUS Status; + UINTN CseVariableFileInfoHobSize = 0; + EFI_HOB_GUID_TYPE *CseVariableFileInfoHob = NULL; + CSE_VARIABLE_FILE_INFO **CseVariableFileInfo = NULL; + + CseVariableFileInfoHob = GetFirstGuidHob (&gCseVariableFileInfoHobGuid); + + if (CseVariableFileInfoHob == NULL) { + // + // Create the variable file info HOB for the first time + // + DEBUG ((EFI_D_INFO, "Initializing CSE Variable PEI storage structures\n")); + + CseVariableFileInfoHobSize = sizeof (CSE_VARIABLE_FILE_INFO *) * CseVariableFileTypeMax; + + CseVariableFileInfo = (CSE_VARIABLE_FILE_INFO **) BuildGuidHob (&gCseVariableFileInfoHobGuid, CseVariableFileInfoHobSize); + } else { + CseVariableFileInfo = GET_GUID_HOB_DATA (CseVariableFileInfoHob); + } + + if (CseVariableFileInfo == NULL) { + ASSERT (CseVariableFileInfo != NULL); + return EFI_OUT_OF_RESOURCES; + } + + ZeroMem (CseVariableFileInfo, CseVariableFileInfoHobSize); + + Status = InitializeCseStorageGlobalVariableStructures (CseVariableFileInfo, FALSE); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + // + // Load existing variable stores if they exist + // + Status = EstablishAndLoadCseVariableStores (CseVariableFileInfo, FALSE); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + } + + return Status; +} + + +/** + Provide the functionality of CSE NVM variable storage services. + + @param[in] FileHandle Handle of the file being invoked. + Type EFI_PEI_FILE_HANDLE is defined in FfsFindNextFile(). + @param[in] PeiServices General purpose services available to every PEIM. + + @retval EFI_SUCCESS If the interface could be successfully installed. + @retval Others Returned from PeiServicesInstallPpi(). + +**/ +EFI_STATUS +EFIAPI +PeimInitializeCseVariableStorageServices ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + BOOLEAN ImageInPermanentMemory; + UINTN Instance; + EFI_GUID DiscoveredInstanceGuid; + EFI_STATUS Status; + EFI_PEI_PPI_DESCRIPTOR *VariableStoragePpiDescriptor = NULL; + VARIABLE_STORAGE_PPI *VariableStoragePpi = NULL; + + ImageInPermanentMemory = FALSE; + + if (PcdGetBool (PcdReinstallCseVariablePpi)) { + Status = PeiServicesRegisterForShadow (FileHandle); + if (EFI_ERROR (Status)) { + if (Status == EFI_ALREADY_STARTED) { + ImageInPermanentMemory = TRUE; + } else { + ASSERT_EFI_ERROR (Status); + return Status; + } + } + } + + if (!ImageInPermanentMemory) { + Status = PeiServicesInstallPpi (&mPpiListVariable); + ASSERT_EFI_ERROR (Status); + } else { + // + // Search for any instances of VARIABLE_STORAGE_PPI installed + // by this PEIM before permanent memory + // If discovered, reinstall the PPI for post memory + // + for (Instance = 0; Status != EFI_NOT_FOUND; Instance++) { + Status = PeiServicesLocatePpi ( + &gVariableStoragePpiGuid, + Instance, + &VariableStoragePpiDescriptor, + (VOID **) &VariableStoragePpi + ); + + if (!EFI_ERROR (Status) && !EFI_ERROR (VariableStoragePpi->GetId (&DiscoveredInstanceGuid))) { + if (CompareGuid (&gCseVariableStoragePpiInstanceGuid, &DiscoveredInstanceGuid)) { + Status = PeiServicesReInstallPpi (VariableStoragePpiDescriptor, &mPpiListVariable); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + break; + } + } else if (Status != EFI_NOT_FOUND) { + ASSERT_EFI_ERROR (Status); + return Status; + } + } + + if (Status == EFI_NOT_FOUND) { + // + // This PEIM did not install an instance of VARIABLE_STORAGE_PPI + // Install the instance for the first time + // + Status = PeiServicesInstallPpi (&mPpiListVariable); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + } + } + + Status = PeimInitializeDataStructures (); + ASSERT_EFI_ERROR (Status); + + return Status; +} + + +/** + Retrieves a PPI instance-specific GUID. + + Returns a unique GUID per VARIABLE_STORAGE_PPI instance. + + @param[out] VariableGuid A pointer to an EFI_GUID that is this PPI instance's GUID. + + @retval EFI_SUCCESS The data was returned successfully. + @retval EFI_INVALID_PARAMETER A required parameter is NULL. + +**/ +EFI_STATUS +EFIAPI +PeiCseVariableStorageGetId ( + OUT EFI_GUID *InstanceGuid + ) +{ + if (InstanceGuid == NULL) { + return EFI_INVALID_PARAMETER; + } + + CopyMem (InstanceGuid, &gCseVariableStoragePpiInstanceGuid, sizeof (EFI_GUID)); + + return EFI_SUCCESS; +} + + +/** + This service 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. + + @param[in] This A pointer to this instance of the VARIABLE_STORAGE_PPI. + @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. + + @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 +PeiCseVariableStorageGetVariable ( + IN CONST VARIABLE_STORAGE_PPI *This, + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VariableGuid, + OUT UINT32 *Attributes, + IN OUT UINTN *DataSize, + OUT VOID *Data + ) +{ + EFI_HOB_GUID_TYPE *CseVariableFileInfoHob = NULL; + CSE_VARIABLE_FILE_INFO **CseVariableFileInfo = NULL; + + // + // Check input parameters + // + if (VariableName == NULL || VariableGuid == NULL || DataSize == NULL) { + return EFI_INVALID_PARAMETER; + } + + CseVariableFileInfoHob = GetFirstGuidHob (&gCseVariableFileInfoHobGuid); + ASSERT (CseVariableFileInfoHob != NULL); + + CseVariableFileInfo = GET_GUID_HOB_DATA (CseVariableFileInfoHob); + + DEBUG ((EFI_D_INFO, "Attempting to read CSE NVM variable.\n Name=\'%ls\'\n GUID=%g\n", \ + VariableName, VariableGuid)); + + DEBUG ((EFI_D_INFO, "CseVariableFileInfoHob = 0x%x\n", CseVariableFileInfoHob)); + DEBUG ((EFI_D_INFO, "CseVariableFileInfo = 0x%x\n", CseVariableFileInfo)); + + DEBUG ((EFI_D_INFO, "Preparing to call FindVariable() in CseVariableStorage->GetVariable()\n")); + + return GetCseVariable (CseVariableFileInfo, VariableName, VariableGuid, Attributes, DataSize, Data, NULL); +} + + +/** + Return the next variable name and GUID. + + This function is called multiple times to retrieve the VariableName + and VariableGuid of all variables currently available in the system. + On each call, the previous results are passed into the interface, + and, on return, the interface returns the data for the next + interface. When the entire variable list has been returned, + EFI_NOT_FOUND is returned. + + @param[in] This A pointer to this instance of the VARIABLE_STORAGE_PPI. + + @param[in, out] VariableNameSize On entry, points to the size of the buffer pointed to by + VariableName. On return, the size of the variable name buffer. + @param[in, out] VariableName On entry, a pointer to a null-terminated string that is the + variable's name. On return, points to the next variable's + null-terminated name string. + @param[in, out] VariableGuid On entry, a pointer to an EFI_GUID that is the variable's GUID. + On return, a pointer to the next variable's GUID. + @param[out] VariableAttributes A pointer to the variable attributes. + + @retval EFI_SUCCESS The variable was read successfully. + @retval EFI_NOT_FOUND The variable could not be found. + @retval EFI_BUFFER_TOO_SMALL The VariableNameSize is too small for the resulting + data. VariableNameSize is updated with the size + required for the specified variable. + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or + VariableNameSize is NULL. + @retval EFI_DEVICE_ERROR The variable could not be retrieved because of a device error. +**/ +EFI_STATUS +EFIAPI +PeiCseVariableStorageGetNextVariableName ( + IN CONST VARIABLE_STORAGE_PPI *This, + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VariableGuid, + OUT UINT32 *VariableAttributes + ) +{ + EFI_STATUS Status; + BOOLEAN IsAuthVariable; + UINTN VarNameSize; + VARIABLE_NVM_HEADER *VariablePtr; + EFI_HOB_GUID_TYPE *CseVariableFileInfoHob = NULL; + CSE_VARIABLE_FILE_INFO **CseVariableFileInfo = NULL; + + if (VariableNameSize == NULL || VariableName == NULL || VariableGuid == NULL) { + return EFI_INVALID_PARAMETER; + } + + CseVariableFileInfoHob = GetFirstGuidHob (&gCseVariableFileInfoHobGuid); + ASSERT (CseVariableFileInfoHob != NULL); + + CseVariableFileInfo = GET_GUID_HOB_DATA (CseVariableFileInfoHob); + + Status = GetNextCseVariableName (VariableName, VariableGuid, CseVariableFileInfo, &VariablePtr, &IsAuthVariable); + + if (EFI_ERROR (Status)) { + return Status; + } + + VarNameSize = NameSizeOfVariable (VariablePtr, IsAuthVariable); + ASSERT (VarNameSize != 0); + + if (VarNameSize <= *VariableNameSize) { + CopyMem (VariableName, GetVariableNamePtr (VariablePtr, IsAuthVariable), VarNameSize); + CopyMem (VariableGuid, GetVendorGuidPtr (VariablePtr, IsAuthVariable), sizeof (EFI_GUID)); + Status = EFI_SUCCESS; + } else { + Status = EFI_BUFFER_TOO_SMALL; + } + *VariableNameSize = VarNameSize; + *VariableAttributes = VariablePtr->Attributes; + + return Status; +} + diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Pei/CseVariableStoragePei/CseVariableStoragePei.h b/Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Pei/CseVariableStoragePei/CseVariableStoragePei.h new file mode 100644 index 0000000000..6f05d7d07d --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Pei/CseVariableStoragePei/CseVariableStoragePei.h @@ -0,0 +1,146 @@ +/** @file + This file contains the required header files for the CSE Variable Storage PEIM. + + 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_PEI_H_ +#define _CSE_VARIABLE_STORAGE_PEI_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern EFI_GUID gCseVariableFileInfoHobGuid; + +/** + Provide the functionality of CSE NVM variable storage services. + + @param[in] FileHandle Handle of the file being invoked. + Type EFI_PEI_FILE_HANDLE is defined in FfsFindNextFile(). + @param[in] PeiServices General purpose services available to every PEIM. + + @retval EFI_SUCCESS If the interface could be successfully installed. + @retval Others Returned from PeiServicesInstallPpi(). + +**/ +EFI_STATUS +EFIAPI +PeimInitializeCseVariableStorageServices ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ); + +/** + Retrieves a PPI instance-specific GUID. + + Returns a unique GUID per VARIABLE_STORAGE_PPI instance. + + @param[out] VariableGuid A pointer to an EFI_GUID that is this PPI instance's GUID. + + @retval EFI_SUCCESS The data was returned successfully. + @retval EFI_INVALID_PARAMETER A required parameter is NULL. + +**/ +EFI_STATUS +EFIAPI +PeiCseVariableStorageGetId ( + OUT EFI_GUID *InstanceGuid + ); + +/** + This service 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. + + @param[in] This A pointer to this instance of the VARIABLE_STORAGE_PPI. + @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. + + @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 +PeiCseVariableStorageGetVariable ( + IN CONST VARIABLE_STORAGE_PPI *This, + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VariableGuid, + OUT UINT32 *Attributes, + IN OUT UINTN *DataSize, + OUT VOID *Data + ); + +/** + Return the next variable name and GUID. + + This function is called multiple times to retrieve the VariableName + and VariableGuid of all variables currently available in the system. + On each call, the previous results are passed into the interface, + and, on return, the interface returns the data for the next + interface. When the entire variable list has been returned, + EFI_NOT_FOUND is returned. + + @param[in] This A pointer to this instance of the VARIABLE_STORAGE_PPI. + + @param[in, out] VariableNameSize On entry, points to the size of the buffer pointed to by + VariableName. On return, the size of the variable name buffer. + @param[in, out] VariableName On entry, a pointer to a null-terminated string that is the + variable's name. On return, points to the next variable's + null-terminated name string. + @param[in, out] VariableGuid On entry, a pointer to an EFI_GUID that is the variable's GUID. + On return, a pointer to the next variable's GUID. + @param[out] VariableAttributes A pointer to the variable attributes. + + @retval EFI_SUCCESS The variable was read successfully. + @retval EFI_NOT_FOUND The variable could not be found. + @retval EFI_BUFFER_TOO_SMALL The VariableNameSize is too small for the resulting + data. VariableNameSize is updated with the size + required for the specified variable. + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or + VariableNameSize is NULL. + @retval EFI_DEVICE_ERROR The variable could not be retrieved because of a device error. +**/ +EFI_STATUS +EFIAPI +PeiCseVariableStorageGetNextVariableName ( + IN CONST VARIABLE_STORAGE_PPI *This, + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VariableGuid, + OUT UINT32 *VariableAttributes + ); + +#endif + diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Pei/CseVariableStoragePei/CseVariableStoragePei.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Pei/CseVariableStoragePei/CseVariableStoragePei.inf new file mode 100644 index 0000000000..e60a085b2a --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/VariableStorage/Pei/CseVariableStoragePei/CseVariableStoragePei.inf @@ -0,0 +1,58 @@ +## @file +# Component description file for the CSE Variable Storage PEIM. +# +# 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 = 0x00010017 + BASE_NAME = CseVariableStoragePei + FILE_GUID = E0FCD2AB-AA88-4498-A925-AFE14207EBFC + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + ENTRY_POINT = PeimInitializeCseVariableStorageServices + +[Sources] + CseVariableStoragePei.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + BroxtonSiPkg/BroxtonSiPkg.dec + BroxtonSiPkg/BroxtonSiPrivate.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + CseVariableStorageLib + CseVariableStorageSelectorLib + DebugLib + HobLib + PcdLib + PeimEntryPoint + PeiServicesLib + VariableNvmStorageLib + +[Pcd] + gSiPkgTokenSpaceGuid.PcdReinstallCseVariablePpi ## CONSUMES + +[Guids] + gCseVariableStoragePpiInstanceGuid ## CONSUMES ## GUID + gEfiAuthenticatedVariableGuid ## CONSUMES ## GUID + gCseVariableFileInfoHobGuid ## CONSUMES ## GUI + +[Ppis] + gPeiHeciPpiGuid ## CONSUMES + gVariableStoragePpiGuid ## PRODUCES + +[Depex] + TRUE -- cgit v1.2.3