diff options
Diffstat (limited to 'MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.c')
| -rw-r--r-- | MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.c | 694 |
1 files changed, 347 insertions, 347 deletions
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.c index 9e2d8fe0fe..363fce0a99 100644 --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.c +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.c @@ -1,347 +1,347 @@ -/** @file
- Common variable non-volatile store routines.
-
-Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "VariableNonVolatile.h"
-#include "VariableParsing.h"
-
-extern VARIABLE_MODULE_GLOBAL *mVariableModuleGlobal;
-
-/**
- Get non-volatile maximum variable size.
-
- @return Non-volatile maximum variable size.
-
-**/
-UINTN
-GetNonVolatileMaxVariableSize (
- VOID
- )
-{
- if (PcdGet32 (PcdHwErrStorageSize) != 0) {
- return MAX (
- MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxAuthVariableSize)),
- PcdGet32 (PcdMaxHardwareErrorVariableSize)
- );
- } else {
- return MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxAuthVariableSize));
- }
-}
-
-/**
- Init emulated non-volatile variable store.
-
- @param[out] VariableStoreBase Output pointer to emulated non-volatile variable store base.
-
- @retval EFI_SUCCESS Function successfully executed.
- @retval EFI_OUT_OF_RESOURCES Fail to allocate enough memory resource.
-
-**/
-EFI_STATUS
-InitEmuNonVolatileVariableStore (
- OUT EFI_PHYSICAL_ADDRESS *VariableStoreBase
- )
-{
- VARIABLE_STORE_HEADER *VariableStore;
- UINT32 VariableStoreLength;
- BOOLEAN FullyInitializeStore;
- UINT32 HwErrStorageSize;
-
- FullyInitializeStore = TRUE;
-
- VariableStoreLength = PcdGet32 (PcdVariableStoreSize);
- ASSERT (sizeof (VARIABLE_STORE_HEADER) <= VariableStoreLength);
-
- //
- // Allocate memory for variable store.
- //
- if (PcdGet64 (PcdEmuVariableNvStoreReserved) == 0) {
- VariableStore = (VARIABLE_STORE_HEADER *)AllocateRuntimePool (VariableStoreLength);
- if (VariableStore == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- } else {
- //
- // A memory location has been reserved for the NV variable store. Certain
- // platforms may be able to preserve a memory range across system resets,
- // thereby providing better NV variable emulation.
- //
- VariableStore =
- (VARIABLE_STORE_HEADER *)(VOID *)(UINTN)
- PcdGet64 (PcdEmuVariableNvStoreReserved);
- if ((VariableStore->Size == VariableStoreLength) &&
- (CompareGuid (&VariableStore->Signature, &gEfiAuthenticatedVariableGuid) ||
- CompareGuid (&VariableStore->Signature, &gEfiVariableGuid)) &&
- (VariableStore->Format == VARIABLE_STORE_FORMATTED) &&
- (VariableStore->State == VARIABLE_STORE_HEALTHY))
- {
- DEBUG ((
- DEBUG_INFO,
- "Variable Store reserved at %p appears to be valid\n",
- VariableStore
- ));
- FullyInitializeStore = FALSE;
- }
- }
-
- if (FullyInitializeStore) {
- SetMem (VariableStore, VariableStoreLength, 0xff);
- //
- // Use gEfiAuthenticatedVariableGuid for potential auth variable support.
- //
- CopyGuid (&VariableStore->Signature, &gEfiAuthenticatedVariableGuid);
- VariableStore->Size = VariableStoreLength;
- VariableStore->Format = VARIABLE_STORE_FORMATTED;
- VariableStore->State = VARIABLE_STORE_HEALTHY;
- VariableStore->Reserved = 0;
- VariableStore->Reserved1 = 0;
- }
-
- *VariableStoreBase = (EFI_PHYSICAL_ADDRESS)(UINTN)VariableStore;
-
- HwErrStorageSize = PcdGet32 (PcdHwErrStorageSize);
-
- //
- // Note that in EdkII variable driver implementation, Hardware Error Record type variable
- // is stored with common variable in the same NV region. So the platform integrator should
- // ensure that the value of PcdHwErrStorageSize is less than the value of
- // (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)).
- //
- ASSERT (HwErrStorageSize < (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)));
-
- mVariableModuleGlobal->CommonVariableSpace = ((UINTN)VariableStoreLength - sizeof (VARIABLE_STORE_HEADER) - HwErrStorageSize);
- mVariableModuleGlobal->CommonMaxUserVariableSpace = mVariableModuleGlobal->CommonVariableSpace;
- mVariableModuleGlobal->CommonRuntimeVariableSpace = mVariableModuleGlobal->CommonVariableSpace;
-
- return EFI_SUCCESS;
-}
-
-/**
- Init real non-volatile variable store.
-
- @param[out] VariableStoreBase Output pointer to real non-volatile variable store base.
-
- @retval EFI_SUCCESS Function successfully executed.
- @retval EFI_OUT_OF_RESOURCES Fail to allocate enough memory resource.
- @retval EFI_VOLUME_CORRUPTED Variable Store or Firmware Volume for Variable Store is corrupted.
-
-**/
-EFI_STATUS
-InitRealNonVolatileVariableStore (
- OUT EFI_PHYSICAL_ADDRESS *VariableStoreBase
- )
-{
- EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
- VARIABLE_STORE_HEADER *VariableStore;
- UINT32 VariableStoreLength;
- EFI_HOB_GUID_TYPE *GuidHob;
- EFI_PHYSICAL_ADDRESS NvStorageBase;
- UINT8 *NvStorageData;
- UINT32 NvStorageSize;
- UINT64 NvStorageSize64;
- FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *FtwLastWriteData;
- UINT32 BackUpOffset;
- UINT32 BackUpSize;
- UINT32 HwErrStorageSize;
- UINT32 MaxUserNvVariableSpaceSize;
- UINT32 BoottimeReservedNvVariableSpaceSize;
- EFI_STATUS Status;
- VOID *FtwProtocol;
-
- mVariableModuleGlobal->FvbInstance = NULL;
-
- Status = GetVariableFlashNvStorageInfo (&NvStorageBase, &NvStorageSize64);
- ASSERT_EFI_ERROR (Status);
-
- Status = SafeUint64ToUint32 (NvStorageSize64, &NvStorageSize);
- // This driver currently assumes the size will be UINT32 so assert the value is safe for now.
- ASSERT_EFI_ERROR (Status);
-
- ASSERT (NvStorageBase != 0);
-
- //
- // Allocate runtime memory used for a memory copy of the FLASH region.
- // Keep the memory and the FLASH in sync as updates occur.
- //
- NvStorageData = AllocateRuntimeZeroPool (NvStorageSize);
- if (NvStorageData == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // Copy NV storage data to the memory buffer.
- //
- CopyMem (NvStorageData, (UINT8 *)(UINTN)NvStorageBase, NvStorageSize);
-
- Status = GetFtwProtocol ((VOID **)&FtwProtocol);
- //
- // If FTW protocol has been installed, no need to check FTW last write data hob.
- //
- if (EFI_ERROR (Status)) {
- //
- // 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) {
- DEBUG ((DEBUG_INFO, "Variable: NV storage is backed up in spare block: 0x%x\n", (UINTN)FtwLastWriteData->SpareAddress));
- //
- // Copy the backed up NV storage data to the memory buffer from spare block.
- //
- CopyMem (NvStorageData, (UINT8 *)(UINTN)(FtwLastWriteData->SpareAddress), NvStorageSize);
- } else if ((FtwLastWriteData->TargetAddress > NvStorageBase) &&
- (FtwLastWriteData->TargetAddress < (NvStorageBase + NvStorageSize)))
- {
- //
- // Flash NV storage from the Offset is backed up in spare block.
- //
- BackUpOffset = (UINT32)(FtwLastWriteData->TargetAddress - NvStorageBase);
- BackUpSize = NvStorageSize - BackUpOffset;
- DEBUG ((DEBUG_INFO, "Variable: High partial NV storage from offset: %x is backed up in spare block: 0x%x\n", BackUpOffset, (UINTN)FtwLastWriteData->SpareAddress));
- //
- // Copy the partial backed up NV storage data to the memory buffer from spare block.
- //
- CopyMem (NvStorageData + BackUpOffset, (UINT8 *)(UINTN)FtwLastWriteData->SpareAddress, BackUpSize);
- }
- }
- }
-
- FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)NvStorageData;
-
- //
- // Check if the Firmware Volume is not corrupted
- //
- if ((FvHeader->Signature != EFI_FVH_SIGNATURE) || (!CompareGuid (&gEfiSystemNvDataFvGuid, &FvHeader->FileSystemGuid))) {
- FreePool (NvStorageData);
- DEBUG ((DEBUG_ERROR, "Firmware Volume for Variable Store is corrupted\n"));
- return EFI_VOLUME_CORRUPTED;
- }
-
- VariableStore = (VARIABLE_STORE_HEADER *)((UINTN)FvHeader + FvHeader->HeaderLength);
- VariableStoreLength = NvStorageSize - FvHeader->HeaderLength;
- ASSERT (sizeof (VARIABLE_STORE_HEADER) <= VariableStoreLength);
- ASSERT (VariableStore->Size == VariableStoreLength);
-
- //
- // Check if the Variable Store header is not corrupted
- //
- if (GetVariableStoreStatus (VariableStore) != EfiValid) {
- FreePool (NvStorageData);
- DEBUG ((DEBUG_ERROR, "Variable Store header is corrupted\n"));
- return EFI_VOLUME_CORRUPTED;
- }
-
- mNvFvHeaderCache = FvHeader;
-
- *VariableStoreBase = (EFI_PHYSICAL_ADDRESS)(UINTN)VariableStore;
-
- HwErrStorageSize = PcdGet32 (PcdHwErrStorageSize);
- MaxUserNvVariableSpaceSize = PcdGet32 (PcdMaxUserNvVariableSpaceSize);
- BoottimeReservedNvVariableSpaceSize = PcdGet32 (PcdBoottimeReservedNvVariableSpaceSize);
-
- //
- // Note that in EdkII variable driver implementation, Hardware Error Record type variable
- // is stored with common variable in the same NV region. So the platform integrator should
- // ensure that the value of PcdHwErrStorageSize is less than the value of
- // (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)).
- //
- ASSERT (HwErrStorageSize < (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)));
- //
- // Ensure that the value of PcdMaxUserNvVariableSpaceSize is less than the value of
- // (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)) - PcdGet32 (PcdHwErrStorageSize).
- //
- ASSERT (MaxUserNvVariableSpaceSize < (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER) - HwErrStorageSize));
- //
- // Ensure that the value of PcdBoottimeReservedNvVariableSpaceSize is less than the value of
- // (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)) - PcdGet32 (PcdHwErrStorageSize).
- //
- ASSERT (BoottimeReservedNvVariableSpaceSize < (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER) - HwErrStorageSize));
-
- mVariableModuleGlobal->CommonVariableSpace = ((UINTN)VariableStoreLength - sizeof (VARIABLE_STORE_HEADER) - HwErrStorageSize);
- mVariableModuleGlobal->CommonMaxUserVariableSpace = ((MaxUserNvVariableSpaceSize != 0) ? MaxUserNvVariableSpaceSize : mVariableModuleGlobal->CommonVariableSpace);
- mVariableModuleGlobal->CommonRuntimeVariableSpace = mVariableModuleGlobal->CommonVariableSpace - BoottimeReservedNvVariableSpaceSize;
-
- DEBUG ((
- DEBUG_INFO,
- "Variable driver common space: 0x%x 0x%x 0x%x\n",
- mVariableModuleGlobal->CommonVariableSpace,
- mVariableModuleGlobal->CommonMaxUserVariableSpace,
- mVariableModuleGlobal->CommonRuntimeVariableSpace
- ));
-
- //
- // The max NV variable size should be < (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)).
- //
- ASSERT (GetNonVolatileMaxVariableSize () < (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)));
-
- return EFI_SUCCESS;
-}
-
-/**
- Init non-volatile variable store.
-
- @retval EFI_SUCCESS Function successfully executed.
- @retval EFI_OUT_OF_RESOURCES Fail to allocate enough memory resource.
- @retval EFI_VOLUME_CORRUPTED Variable Store or Firmware Volume for Variable Store is corrupted.
-
-**/
-EFI_STATUS
-InitNonVolatileVariableStore (
- VOID
- )
-{
- VARIABLE_HEADER *Variable;
- VARIABLE_HEADER *NextVariable;
- EFI_PHYSICAL_ADDRESS VariableStoreBase;
- UINTN VariableSize;
- EFI_STATUS Status;
-
- if (PcdGetBool (PcdEmuVariableNvModeEnable)) {
- Status = InitEmuNonVolatileVariableStore (&VariableStoreBase);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- mVariableModuleGlobal->VariableGlobal.EmuNvMode = TRUE;
- DEBUG ((DEBUG_INFO, "Variable driver will work at emulated non-volatile variable mode!\n"));
- } else {
- Status = InitRealNonVolatileVariableStore (&VariableStoreBase);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- mVariableModuleGlobal->VariableGlobal.EmuNvMode = FALSE;
- }
-
- mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase;
- mNvVariableCache = (VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase;
- mVariableModuleGlobal->VariableGlobal.AuthFormat = (BOOLEAN)(CompareGuid (&mNvVariableCache->Signature, &gEfiAuthenticatedVariableGuid));
-
- mVariableModuleGlobal->MaxVariableSize = PcdGet32 (PcdMaxVariableSize);
- mVariableModuleGlobal->MaxAuthVariableSize = ((PcdGet32 (PcdMaxAuthVariableSize) != 0) ? PcdGet32 (PcdMaxAuthVariableSize) : mVariableModuleGlobal->MaxVariableSize);
-
- //
- // Parse non-volatile variable data and get last variable offset.
- //
- Variable = GetStartPointer (mNvVariableCache);
- while (IsValidVariableHeader (Variable, GetEndPointer (mNvVariableCache))) {
- NextVariable = GetNextVariablePtr (Variable, mVariableModuleGlobal->VariableGlobal.AuthFormat);
- VariableSize = (UINTN)NextVariable - (UINTN)Variable;
- if ((Variable->Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
- mVariableModuleGlobal->HwErrVariableTotalSize += VariableSize;
- } else {
- mVariableModuleGlobal->CommonVariableTotalSize += VariableSize;
- }
-
- Variable = NextVariable;
- }
-
- mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN)Variable - (UINTN)mNvVariableCache;
-
- return EFI_SUCCESS;
-}
+/** @file + Common variable non-volatile store routines. + +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "VariableNonVolatile.h" +#include "VariableParsing.h" + +extern VARIABLE_MODULE_GLOBAL *mVariableModuleGlobal; + +/** + Get non-volatile maximum variable size. + + @return Non-volatile maximum variable size. + +**/ +UINTN +GetNonVolatileMaxVariableSize ( + VOID + ) +{ + if (PcdGet32 (PcdHwErrStorageSize) != 0) { + return MAX ( + MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxAuthVariableSize)), + PcdGet32 (PcdMaxHardwareErrorVariableSize) + ); + } else { + return MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxAuthVariableSize)); + } +} + +/** + Init emulated non-volatile variable store. + + @param[out] VariableStoreBase Output pointer to emulated non-volatile variable store base. + + @retval EFI_SUCCESS Function successfully executed. + @retval EFI_OUT_OF_RESOURCES Fail to allocate enough memory resource. + +**/ +EFI_STATUS +InitEmuNonVolatileVariableStore ( + OUT EFI_PHYSICAL_ADDRESS *VariableStoreBase + ) +{ + VARIABLE_STORE_HEADER *VariableStore; + UINT32 VariableStoreLength; + BOOLEAN FullyInitializeStore; + UINT32 HwErrStorageSize; + + FullyInitializeStore = TRUE; + + VariableStoreLength = PcdGet32 (PcdVariableStoreSize); + ASSERT (sizeof (VARIABLE_STORE_HEADER) <= VariableStoreLength); + + // + // Allocate memory for variable store. + // + if (PcdGet64 (PcdEmuVariableNvStoreReserved) == 0) { + VariableStore = (VARIABLE_STORE_HEADER *)AllocateRuntimePool (VariableStoreLength); + if (VariableStore == NULL) { + return EFI_OUT_OF_RESOURCES; + } + } else { + // + // A memory location has been reserved for the NV variable store. Certain + // platforms may be able to preserve a memory range across system resets, + // thereby providing better NV variable emulation. + // + VariableStore = + (VARIABLE_STORE_HEADER *)(VOID *)(UINTN) + PcdGet64 (PcdEmuVariableNvStoreReserved); + if ((VariableStore->Size == VariableStoreLength) && + (CompareGuid (&VariableStore->Signature, &gEfiAuthenticatedVariableGuid) || + CompareGuid (&VariableStore->Signature, &gEfiVariableGuid)) && + (VariableStore->Format == VARIABLE_STORE_FORMATTED) && + (VariableStore->State == VARIABLE_STORE_HEALTHY)) + { + DEBUG (( + DEBUG_INFO, + "Variable Store reserved at %p appears to be valid\n", + VariableStore + )); + FullyInitializeStore = FALSE; + } + } + + if (FullyInitializeStore) { + SetMem (VariableStore, VariableStoreLength, 0xff); + // + // Use gEfiAuthenticatedVariableGuid for potential auth variable support. + // + CopyGuid (&VariableStore->Signature, &gEfiAuthenticatedVariableGuid); + VariableStore->Size = VariableStoreLength; + VariableStore->Format = VARIABLE_STORE_FORMATTED; + VariableStore->State = VARIABLE_STORE_HEALTHY; + VariableStore->Reserved = 0; + VariableStore->Reserved1 = 0; + } + + *VariableStoreBase = (EFI_PHYSICAL_ADDRESS)(UINTN)VariableStore; + + HwErrStorageSize = PcdGet32 (PcdHwErrStorageSize); + + // + // Note that in EdkII variable driver implementation, Hardware Error Record type variable + // is stored with common variable in the same NV region. So the platform integrator should + // ensure that the value of PcdHwErrStorageSize is less than the value of + // (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)). + // + ASSERT (HwErrStorageSize < (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER))); + + mVariableModuleGlobal->CommonVariableSpace = ((UINTN)VariableStoreLength - sizeof (VARIABLE_STORE_HEADER) - HwErrStorageSize); + mVariableModuleGlobal->CommonMaxUserVariableSpace = mVariableModuleGlobal->CommonVariableSpace; + mVariableModuleGlobal->CommonRuntimeVariableSpace = mVariableModuleGlobal->CommonVariableSpace; + + return EFI_SUCCESS; +} + +/** + Init real non-volatile variable store. + + @param[out] VariableStoreBase Output pointer to real non-volatile variable store base. + + @retval EFI_SUCCESS Function successfully executed. + @retval EFI_OUT_OF_RESOURCES Fail to allocate enough memory resource. + @retval EFI_VOLUME_CORRUPTED Variable Store or Firmware Volume for Variable Store is corrupted. + +**/ +EFI_STATUS +InitRealNonVolatileVariableStore ( + OUT EFI_PHYSICAL_ADDRESS *VariableStoreBase + ) +{ + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + VARIABLE_STORE_HEADER *VariableStore; + UINT32 VariableStoreLength; + EFI_HOB_GUID_TYPE *GuidHob; + EFI_PHYSICAL_ADDRESS NvStorageBase; + UINT8 *NvStorageData; + UINT32 NvStorageSize; + UINT64 NvStorageSize64; + FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *FtwLastWriteData; + UINT32 BackUpOffset; + UINT32 BackUpSize; + UINT32 HwErrStorageSize; + UINT32 MaxUserNvVariableSpaceSize; + UINT32 BoottimeReservedNvVariableSpaceSize; + EFI_STATUS Status; + VOID *FtwProtocol; + + mVariableModuleGlobal->FvbInstance = NULL; + + Status = GetVariableFlashNvStorageInfo (&NvStorageBase, &NvStorageSize64); + ASSERT_EFI_ERROR (Status); + + Status = SafeUint64ToUint32 (NvStorageSize64, &NvStorageSize); + // This driver currently assumes the size will be UINT32 so assert the value is safe for now. + ASSERT_EFI_ERROR (Status); + + ASSERT (NvStorageBase != 0); + + // + // Allocate runtime memory used for a memory copy of the FLASH region. + // Keep the memory and the FLASH in sync as updates occur. + // + NvStorageData = AllocateRuntimeZeroPool (NvStorageSize); + if (NvStorageData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Copy NV storage data to the memory buffer. + // + CopyMem (NvStorageData, (UINT8 *)(UINTN)NvStorageBase, NvStorageSize); + + Status = GetFtwProtocol ((VOID **)&FtwProtocol); + // + // If FTW protocol has been installed, no need to check FTW last write data hob. + // + if (EFI_ERROR (Status)) { + // + // 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) { + DEBUG ((DEBUG_INFO, "Variable: NV storage is backed up in spare block: 0x%x\n", (UINTN)FtwLastWriteData->SpareAddress)); + // + // Copy the backed up NV storage data to the memory buffer from spare block. + // + CopyMem (NvStorageData, (UINT8 *)(UINTN)(FtwLastWriteData->SpareAddress), NvStorageSize); + } else if ((FtwLastWriteData->TargetAddress > NvStorageBase) && + (FtwLastWriteData->TargetAddress < (NvStorageBase + NvStorageSize))) + { + // + // Flash NV storage from the Offset is backed up in spare block. + // + BackUpOffset = (UINT32)(FtwLastWriteData->TargetAddress - NvStorageBase); + BackUpSize = NvStorageSize - BackUpOffset; + DEBUG ((DEBUG_INFO, "Variable: High partial NV storage from offset: %x is backed up in spare block: 0x%x\n", BackUpOffset, (UINTN)FtwLastWriteData->SpareAddress)); + // + // Copy the partial backed up NV storage data to the memory buffer from spare block. + // + CopyMem (NvStorageData + BackUpOffset, (UINT8 *)(UINTN)FtwLastWriteData->SpareAddress, BackUpSize); + } + } + } + + FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)NvStorageData; + + // + // Check if the Firmware Volume is not corrupted + // + if ((FvHeader->Signature != EFI_FVH_SIGNATURE) || (!CompareGuid (&gEfiSystemNvDataFvGuid, &FvHeader->FileSystemGuid))) { + FreePool (NvStorageData); + DEBUG ((DEBUG_ERROR, "Firmware Volume for Variable Store is corrupted\n")); + return EFI_VOLUME_CORRUPTED; + } + + VariableStore = (VARIABLE_STORE_HEADER *)((UINTN)FvHeader + FvHeader->HeaderLength); + VariableStoreLength = NvStorageSize - FvHeader->HeaderLength; + ASSERT (sizeof (VARIABLE_STORE_HEADER) <= VariableStoreLength); + ASSERT (VariableStore->Size == VariableStoreLength); + + // + // Check if the Variable Store header is not corrupted + // + if (GetVariableStoreStatus (VariableStore) != EfiValid) { + FreePool (NvStorageData); + DEBUG ((DEBUG_ERROR, "Variable Store header is corrupted\n")); + return EFI_VOLUME_CORRUPTED; + } + + mNvFvHeaderCache = FvHeader; + + *VariableStoreBase = (EFI_PHYSICAL_ADDRESS)(UINTN)VariableStore; + + HwErrStorageSize = PcdGet32 (PcdHwErrStorageSize); + MaxUserNvVariableSpaceSize = PcdGet32 (PcdMaxUserNvVariableSpaceSize); + BoottimeReservedNvVariableSpaceSize = PcdGet32 (PcdBoottimeReservedNvVariableSpaceSize); + + // + // Note that in EdkII variable driver implementation, Hardware Error Record type variable + // is stored with common variable in the same NV region. So the platform integrator should + // ensure that the value of PcdHwErrStorageSize is less than the value of + // (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)). + // + ASSERT (HwErrStorageSize < (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER))); + // + // Ensure that the value of PcdMaxUserNvVariableSpaceSize is less than the value of + // (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)) - PcdGet32 (PcdHwErrStorageSize). + // + ASSERT (MaxUserNvVariableSpaceSize < (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER) - HwErrStorageSize)); + // + // Ensure that the value of PcdBoottimeReservedNvVariableSpaceSize is less than the value of + // (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)) - PcdGet32 (PcdHwErrStorageSize). + // + ASSERT (BoottimeReservedNvVariableSpaceSize < (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER) - HwErrStorageSize)); + + mVariableModuleGlobal->CommonVariableSpace = ((UINTN)VariableStoreLength - sizeof (VARIABLE_STORE_HEADER) - HwErrStorageSize); + mVariableModuleGlobal->CommonMaxUserVariableSpace = ((MaxUserNvVariableSpaceSize != 0) ? MaxUserNvVariableSpaceSize : mVariableModuleGlobal->CommonVariableSpace); + mVariableModuleGlobal->CommonRuntimeVariableSpace = mVariableModuleGlobal->CommonVariableSpace - BoottimeReservedNvVariableSpaceSize; + + DEBUG (( + DEBUG_INFO, + "Variable driver common space: 0x%x 0x%x 0x%x\n", + mVariableModuleGlobal->CommonVariableSpace, + mVariableModuleGlobal->CommonMaxUserVariableSpace, + mVariableModuleGlobal->CommonRuntimeVariableSpace + )); + + // + // The max NV variable size should be < (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)). + // + ASSERT (GetNonVolatileMaxVariableSize () < (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER))); + + return EFI_SUCCESS; +} + +/** + Init non-volatile variable store. + + @retval EFI_SUCCESS Function successfully executed. + @retval EFI_OUT_OF_RESOURCES Fail to allocate enough memory resource. + @retval EFI_VOLUME_CORRUPTED Variable Store or Firmware Volume for Variable Store is corrupted. + +**/ +EFI_STATUS +InitNonVolatileVariableStore ( + VOID + ) +{ + VARIABLE_HEADER *Variable; + VARIABLE_HEADER *NextVariable; + EFI_PHYSICAL_ADDRESS VariableStoreBase; + UINTN VariableSize; + EFI_STATUS Status; + + if (PcdGetBool (PcdEmuVariableNvModeEnable)) { + Status = InitEmuNonVolatileVariableStore (&VariableStoreBase); + if (EFI_ERROR (Status)) { + return Status; + } + + mVariableModuleGlobal->VariableGlobal.EmuNvMode = TRUE; + DEBUG ((DEBUG_INFO, "Variable driver will work at emulated non-volatile variable mode!\n")); + } else { + Status = InitRealNonVolatileVariableStore (&VariableStoreBase); + if (EFI_ERROR (Status)) { + return Status; + } + + mVariableModuleGlobal->VariableGlobal.EmuNvMode = FALSE; + } + + mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase; + mNvVariableCache = (VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase; + mVariableModuleGlobal->VariableGlobal.AuthFormat = (BOOLEAN)(CompareGuid (&mNvVariableCache->Signature, &gEfiAuthenticatedVariableGuid)); + + mVariableModuleGlobal->MaxVariableSize = PcdGet32 (PcdMaxVariableSize); + mVariableModuleGlobal->MaxAuthVariableSize = ((PcdGet32 (PcdMaxAuthVariableSize) != 0) ? PcdGet32 (PcdMaxAuthVariableSize) : mVariableModuleGlobal->MaxVariableSize); + + // + // Parse non-volatile variable data and get last variable offset. + // + Variable = GetStartPointer (mNvVariableCache); + while (IsValidVariableHeader (Variable, GetEndPointer (mNvVariableCache))) { + NextVariable = GetNextVariablePtr (Variable, mVariableModuleGlobal->VariableGlobal.AuthFormat); + VariableSize = (UINTN)NextVariable - (UINTN)Variable; + if ((Variable->Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) { + mVariableModuleGlobal->HwErrVariableTotalSize += VariableSize; + } else { + mVariableModuleGlobal->CommonVariableTotalSize += VariableSize; + } + + Variable = NextVariable; + } + + mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN)Variable - (UINTN)mNvVariableCache; + + return EFI_SUCCESS; +} |
