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.
+Copyright (c) 2006 - 2024, Intel Corporation. All rights reserved.
Copyright (c) Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent @@ -24,6 +24,31 @@ EFI_PEI_PPI_DESCRIPTOR mPpiListVariable = { &mVariablePpi }; +/** + 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. @@ -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 #include #include +#include +#include #include #include #include #include +#include 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.
+# Copyright (c) 2006 - 2024, Intel Corporation. All rights reserved.
# 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