summaryrefslogtreecommitdiffstats
path: root/MdeModulePkg/Universal/Variable
diff options
context:
space:
mode:
Diffstat (limited to 'MdeModulePkg/Universal/Variable')
-rw-r--r--MdeModulePkg/Universal/Variable/Pei/Variable.c301
-rw-r--r--MdeModulePkg/Universal/Variable/Pei/Variable.h3
-rw-r--r--MdeModulePkg/Universal/Variable/Pei/VariablePei.inf8
3 files changed, 310 insertions, 2 deletions
diff --git a/MdeModulePkg/Universal/Variable/Pei/Variable.c b/MdeModulePkg/Universal/Variable/Pei/Variable.c
index 26a4c73b45..26f95c6d95 100644
--- a/MdeModulePkg/Universal/Variable/Pei/Variable.c
+++ b/MdeModulePkg/Universal/Variable/Pei/Variable.c
@@ -2,7 +2,7 @@
Implement ReadOnly Variable Services required by PEIM and install
PEI ReadOnly Varaiable2 PPI. These services operates the non volatile storage space.
-Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2024, Intel Corporation. All rights reserved.<BR>
Copyright (c) Microsoft Corporation.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -25,6 +25,31 @@ EFI_PEI_PPI_DESCRIPTOR mPpiListVariable = {
};
/**
+ Build gEdkiiVariableRuntimeCacheInfoHobGuid.
+
+ @param[in] PeiServices General purpose services available to every PEIM.
+ @param[in] NotifyDescriptor The notification structure this PEIM registered on install.
+ @param[in] Ppi The memory discovered PPI. Not used.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval others Failed to build VariableRuntimeCacheInfo Hob.
+
+**/
+EFI_STATUS
+EFIAPI
+BuildVariableRuntimeCacheInfoHob (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ );
+
+EFI_PEI_NOTIFY_DESCRIPTOR mPostMemNotifyList = {
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiMemoryDiscoveredPpiGuid,
+ BuildVariableRuntimeCacheInfoHob
+};
+
+/**
Provide the functionality of the variable services.
@param FileHandle Handle of the file being invoked.
@@ -41,6 +66,10 @@ PeimInitializeVariableServices (
IN CONST EFI_PEI_SERVICES **PeiServices
)
{
+ if (FeaturePcdGet (PcdEnableVariableRuntimeCache)) {
+ PeiServicesNotifyPpi (&mPostMemNotifyList);
+ }
+
return PeiServicesInstallPpi (&mPpiListVariable);
}
@@ -1250,3 +1279,273 @@ PeiGetNextVariableName (
}
}
}
+
+/**
+ Calculate the auth variable storage size converted from normal variable storage.
+
+ @param[in] StoreInfo Pointer to the store info
+ @param[in] NormalHobVarStorage Pointer to the normal variable storage header
+
+ @retval the auth variable storage size
+**/
+UINTN
+CalculateAuthVarStorageSize (
+ IN VARIABLE_STORE_INFO *StoreInfo,
+ IN VARIABLE_STORE_HEADER *NormalHobVarStorage
+ )
+{
+ VARIABLE_HEADER *StartPtr;
+ VARIABLE_HEADER *EndPtr;
+ UINTN AuthVarStroageSize;
+
+ AuthVarStroageSize = sizeof (VARIABLE_STORE_HEADER);
+
+ //
+ // Calculate Auth Variable Storage Size
+ //
+ StartPtr = GetStartPointer (NormalHobVarStorage);
+ EndPtr = GetEndPointer (NormalHobVarStorage);
+ while (StartPtr < EndPtr) {
+ if (StartPtr->State == VAR_ADDED) {
+ AuthVarStroageSize = HEADER_ALIGN (AuthVarStroageSize);
+ AuthVarStroageSize += sizeof (AUTHENTICATED_VARIABLE_HEADER);
+ AuthVarStroageSize += StartPtr->NameSize + GET_PAD_SIZE (StartPtr->NameSize);
+ AuthVarStroageSize += StartPtr->DataSize + GET_PAD_SIZE (StartPtr->DataSize);
+ }
+
+ StartPtr = GetNextVariablePtr (StoreInfo, StartPtr, StartPtr);
+ }
+
+ return AuthVarStroageSize;
+}
+
+/**
+ Calculate Hob variable cache size.
+
+ @param[in] NvAuthFlag If the NV variable store is Auth.
+
+ @retval Maximum of Nv variable cache size.
+
+**/
+UINTN
+CalculateHobVariableCacheSize (
+ IN BOOLEAN NvAuthFlag
+ )
+{
+ VARIABLE_STORE_INFO StoreInfo;
+ VARIABLE_STORE_HEADER *VariableStoreHeader;
+
+ VariableStoreHeader = NULL;
+ GetHobVariableStore (&StoreInfo, &VariableStoreHeader);
+
+ if (VariableStoreHeader == NULL) {
+ return 0;
+ }
+
+ if (NvAuthFlag == StoreInfo.AuthFlag) {
+ return VariableStoreHeader->Size;
+ } else {
+ //
+ // Normal NV variable store + Auth HOB variable store is not supported
+ //
+ ASSERT (NvAuthFlag && (!StoreInfo.AuthFlag));
+
+ //
+ // Need to calculate auth variable storage size converted from normal variable storage
+ //
+ return CalculateAuthVarStorageSize (&StoreInfo, VariableStoreHeader);
+ }
+}
+
+/**
+ Calculate Nv variable cache size.
+
+ @param[out] NvAuthFlag If the NV variable store is Auth.
+
+ @retval Maximum of Nv variable cache size.
+
+**/
+UINTN
+CalculateNvVariableCacheSize (
+ OUT BOOLEAN *NvAuthFlag
+ )
+{
+ EFI_STATUS Status;
+ EFI_HOB_GUID_TYPE *GuidHob;
+ EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
+ VARIABLE_STORE_HEADER *VariableStoreHeader;
+ EFI_PHYSICAL_ADDRESS NvStorageBase;
+ UINT32 NvStorageSize;
+ UINT64 NvStorageSize64;
+ FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *FtwLastWriteData;
+
+ if (PcdGetBool (PcdEmuVariableNvModeEnable)) {
+ return PcdGet32 (PcdVariableStoreSize);
+ }
+
+ Status = GetVariableFlashNvStorageInfo (&NvStorageBase, &NvStorageSize64);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = SafeUint64ToUint32 (NvStorageSize64, &NvStorageSize);
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (NvStorageBase != 0);
+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)NvStorageBase;
+
+ //
+ // Check the FTW last write data hob.
+ //
+ GuidHob = GetFirstGuidHob (&gEdkiiFaultTolerantWriteGuid);
+ if (GuidHob != NULL) {
+ FtwLastWriteData = (FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *)GET_GUID_HOB_DATA (GuidHob);
+ if (FtwLastWriteData->TargetAddress == NvStorageBase) {
+ //
+ // Let FvHeader point to spare block.
+ //
+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)FtwLastWriteData->SpareAddress;
+ }
+ }
+
+ VariableStoreHeader = (VARIABLE_STORE_HEADER *)((UINT8 *)FvHeader + FvHeader->HeaderLength);
+ *NvAuthFlag = (BOOLEAN)(CompareGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid));
+
+ return NvStorageSize - FvHeader->HeaderLength;
+}
+
+/**
+ Build gEdkiiVariableRuntimeCacheInfoHobGuid.
+
+ @param[in] PeiServices General purpose services available to every PEIM.
+ @param[in] NotifyDescriptor The notification structure this PEIM registered on install.
+ @param[in] Ppi The memory discovered PPI. Not used.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval others Failed to build VariableRuntimeCacheInfo Hob.
+
+**/
+EFI_STATUS
+EFIAPI
+BuildVariableRuntimeCacheInfoHob (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+{
+ VARIABLE_RUNTIME_CACHE_INFO TempHobBuffer;
+ VARIABLE_RUNTIME_CACHE_INFO *VariableRuntimeCacheInfo;
+ EFI_STATUS Status;
+ VOID *Buffer;
+ UINTN BufferSize;
+ BOOLEAN NvAuthFlag;
+ UINTN Pages;
+
+ ZeroMem (&TempHobBuffer, sizeof (VARIABLE_RUNTIME_CACHE_INFO));
+
+ //
+ // AllocateRuntimePages for CACHE_INFO_FLAG and unblock it.
+ //
+ Pages = EFI_SIZE_TO_PAGES (sizeof (CACHE_INFO_FLAG));
+ Buffer = AllocateRuntimePages (Pages);
+ ASSERT (Buffer != NULL);
+ Status = MmUnblockMemoryRequest (
+ (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer,
+ Pages
+ );
+ if ((Status != EFI_UNSUPPORTED) && EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ TempHobBuffer.CacheInfoFlagBuffer = (UINTN)Buffer;
+ DEBUG ((
+ DEBUG_INFO,
+ "PeiVariable: CACHE_INFO_FLAG Buffer is: 0x%lx, number of pages is: 0x%x\n",
+ TempHobBuffer.CacheInfoFlagBuffer,
+ Pages
+ ));
+
+ //
+ // AllocateRuntimePages for VolatileCache and unblock it.
+ //
+ BufferSize = PcdGet32 (PcdVariableStoreSize);
+ if (BufferSize > 0) {
+ Pages = EFI_SIZE_TO_PAGES (BufferSize);
+ Buffer = AllocateRuntimePages (Pages);
+ ASSERT (Buffer != NULL);
+ Status = MmUnblockMemoryRequest (
+ (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer,
+ Pages
+ );
+ if ((Status != EFI_UNSUPPORTED) && EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ TempHobBuffer.RuntimeVolatileCacheBuffer = (UINTN)Buffer;
+ TempHobBuffer.RuntimeVolatileCachePages = Pages;
+ }
+
+ DEBUG ((
+ DEBUG_INFO,
+ "PeiVariable: Volatile cache Buffer is: 0x%lx, number of pages is: 0x%lx\n",
+ TempHobBuffer.RuntimeVolatileCacheBuffer,
+ TempHobBuffer.RuntimeVolatileCachePages
+ ));
+
+ //
+ // AllocateRuntimePages for NVCache and unblock it.
+ //
+ BufferSize = CalculateNvVariableCacheSize (&NvAuthFlag);
+ if (BufferSize > 0) {
+ Pages = EFI_SIZE_TO_PAGES (BufferSize);
+ Buffer = AllocateRuntimePages (Pages);
+ ASSERT (Buffer != NULL);
+ Status = MmUnblockMemoryRequest (
+ (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer,
+ Pages
+ );
+ if ((Status != EFI_UNSUPPORTED) && EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ TempHobBuffer.RuntimeNvCacheBuffer = (UINTN)Buffer;
+ TempHobBuffer.RuntimeNvCachePages = Pages;
+ }
+
+ DEBUG ((
+ DEBUG_INFO,
+ "PeiVariable: NV cache Buffer is: 0x%lx, number of pages is: 0x%lx\n",
+ TempHobBuffer.RuntimeNvCacheBuffer,
+ TempHobBuffer.RuntimeNvCachePages
+ ));
+
+ //
+ // AllocateRuntimePages for HobCache and unblock it.
+ //
+ BufferSize = CalculateHobVariableCacheSize (NvAuthFlag);
+ if (BufferSize > 0) {
+ Pages = EFI_SIZE_TO_PAGES (BufferSize);
+ Buffer = AllocateRuntimePages (Pages);
+ ASSERT (Buffer != NULL);
+ Status = MmUnblockMemoryRequest (
+ (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer,
+ Pages
+ );
+ if ((Status != EFI_UNSUPPORTED) && EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ TempHobBuffer.RuntimeHobCacheBuffer = (UINTN)Buffer;
+ TempHobBuffer.RuntimeHobCachePages = Pages;
+ }
+
+ DEBUG ((
+ DEBUG_INFO,
+ "PeiVariable: HOB cache Buffer is: 0x%lx, number of pages is: 0x%lx\n",
+ TempHobBuffer.RuntimeHobCacheBuffer,
+ TempHobBuffer.RuntimeHobCachePages
+ ));
+
+ VariableRuntimeCacheInfo = BuildGuidHob (&gEdkiiVariableRuntimeCacheInfoHobGuid, sizeof (VARIABLE_RUNTIME_CACHE_INFO));
+ ASSERT (VariableRuntimeCacheInfo != NULL);
+ CopyMem (VariableRuntimeCacheInfo, &TempHobBuffer, sizeof (VARIABLE_RUNTIME_CACHE_INFO));
+
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Universal/Variable/Pei/Variable.h b/MdeModulePkg/Universal/Variable/Pei/Variable.h
index 51effbf799..aa0d79f166 100644
--- a/MdeModulePkg/Universal/Variable/Pei/Variable.h
+++ b/MdeModulePkg/Universal/Variable/Pei/Variable.h
@@ -22,11 +22,14 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/PeiServicesLib.h>
#include <Library/SafeIntLib.h>
#include <Library/VariableFlashInfoLib.h>
+#include <Library/MmUnblockMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
#include <Guid/VariableFormat.h>
#include <Guid/VariableIndexTable.h>
#include <Guid/SystemNvDataGuid.h>
#include <Guid/FaultTolerantWrite.h>
+#include <Guid/VariableRuntimeCacheInfo.h>
typedef enum {
VariableStoreTypeHob,
diff --git a/MdeModulePkg/Universal/Variable/Pei/VariablePei.inf b/MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
index 7264a24bdf..f2dc7c042c 100644
--- a/MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
+++ b/MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
@@ -3,7 +3,7 @@
#
# This module implements ReadOnly Variable Services required by PEIM and installs PEI ReadOnly Varaiable2 PPI.
#
-# Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2006 - 2024, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@@ -41,6 +41,8 @@
PeiServicesLib
SafeIntLib
VariableFlashInfoLib
+ MmUnblockMemoryLib
+ MemoryAllocationLib
[Guids]
## CONSUMES ## GUID # Variable store header
@@ -56,12 +58,16 @@
## SOMETIMES_CONSUMES ## HOB
## CONSUMES ## GUID # Dependence
gEdkiiFaultTolerantWriteGuid
+ gEdkiiVariableRuntimeCacheInfoHobGuid
[Ppis]
gEfiPeiReadOnlyVariable2PpiGuid ## PRODUCES
+ gEfiPeiMemoryDiscoveredPpiGuid ## CONSUMES
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvModeEnable ## SOMETIMES_CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEnableVariableRuntimeCache ## CONSUMES
[Depex]
gEdkiiFaultTolerantWriteGuid