[edk2-devel] [PATCH V4 05/10] MdeModulePkg/Variable: Add a file for NV variable functions

Kubacki, Michael A michael.a.kubacki at intel.com
Mon Oct 14 23:29:56 UTC 2019


This change adds a dedicated file for variable operations specific
to non-volatile variables. This decreases the overall length of the
relatively large Variable.c file.

Cc: Dandan Bi <dandan.bi at intel.com>
Cc: Ard Biesheuvel <ard.biesheuvel at linaro.org>
Cc: Eric Dong <eric.dong at intel.com>
Cc: Laszlo Ersek <lersek at redhat.com>
Cc: Liming Gao <liming.gao at intel.com>
Cc: Michael D Kinney <michael.d.kinney at intel.com>
Cc: Ray Ni <ray.ni at intel.com>
Cc: Jian J Wang <jian.j.wang at intel.com>
Cc: Hao A Wu <hao.a.wu at intel.com>
Cc: Jiewen Yao <jiewen.yao at intel.com>
Signed-off-by: Michael Kubacki <michael.a.kubacki at intel.com>
---
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf   |   2 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf          |   2 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf |   2 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.h    |  67 ++++
 MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c               | 317 +------------------
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.c    | 334 ++++++++++++++++++++
 6 files changed, 408 insertions(+), 316 deletions(-)

diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
index c35e5fe787..08a5490787 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
@@ -36,6 +36,8 @@
   Variable.c
   VariableDxe.c
   Variable.h
+  VariableNonVolatile.c
+  VariableNonVolatile.h
   VariableParsing.c
   VariableParsing.h
   PrivilegePolymorphic.h
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
index 626738b9c7..6dc2721b81 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
@@ -45,6 +45,8 @@
   Variable.c
   VariableTraditionalMm.c
   VariableSmm.c
+  VariableNonVolatile.c
+  VariableNonVolatile.h
   VariableParsing.c
   VariableParsing.h
   VarCheck.c
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf
index ff714b193a..f8a3742959 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf
@@ -45,6 +45,8 @@
   Variable.c
   VariableSmm.c
   VariableStandaloneMm.c
+  VariableNonVolatile.c
+  VariableNonVolatile.h
   VariableParsing.c
   VariableParsing.h
   VarCheck.c
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.h b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.h
new file mode 100644
index 0000000000..43653f27e6
--- /dev/null
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.h
@@ -0,0 +1,67 @@
+/** @file
+  Common variable non-volatile store routines.
+
+Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _VARIABLE_NON_VOLATILE_H_
+#define _VARIABLE_NON_VOLATILE_H_
+
+#include "Variable.h"
+
+/**
+  Get non-volatile maximum variable size.
+
+  @return Non-volatile maximum variable size.
+
+**/
+UINTN
+GetNonVolatileMaxVariableSize (
+  VOID
+  );
+
+/**
+  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 (
+  EFI_PHYSICAL_ADDRESS  *VariableStoreBase
+  );
+
+/**
+  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
+  );
+
+/**
+  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
+  );
+
+#endif
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
index 2e32905dfe..0bd2f22e1a 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
@@ -23,6 +23,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 **/
 
 #include "Variable.h"
+#include "VariableNonVolatile.h"
 #include "VariableParsing.h"
 
 VARIABLE_MODULE_GLOBAL  *mVariableModuleGlobal;
@@ -3079,25 +3080,6 @@ ReclaimForOS(
   }
 }
 
-/**
-  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));
-  }
-}
-
 /**
   Get maximum variable size, covering both non-volatile and volatile variables.
 
@@ -3122,303 +3104,6 @@ GetMaxVariableSize (
   return MaxVariableSize;
 }
 
-/**
-  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;
-  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;
-
-  //
-  // Allocate runtime memory used for a memory copy of the FLASH region.
-  // Keep the memory and the FLASH in sync as updates occur.
-  //
-  NvStorageSize = PcdGet32 (PcdFlashNvStorageVariableSize);
-  NvStorageData = AllocateRuntimeZeroPool (NvStorageSize);
-  if (NvStorageData == NULL) {
-    return EFI_OUT_OF_RESOURCES;
-  }
-
-  NvStorageBase = NV_STORAGE_VARIABLE_BASE;
-  ASSERT (NvStorageBase != 0);
-
-  //
-  // 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 ((EFI_D_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 ((EFI_D_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 ((EFI_D_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((EFI_D_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 ((EFI_D_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 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 (
-  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 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;
-}
-
 /**
   Flush the HOB variable to flash.
 
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.c
new file mode 100644
index 0000000000..0637a828b3
--- /dev/null
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.c
@@ -0,0 +1,334 @@
+/** @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;
+  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;
+
+  //
+  // Allocate runtime memory used for a memory copy of the FLASH region.
+  // Keep the memory and the FLASH in sync as updates occur.
+  //
+  NvStorageSize = PcdGet32 (PcdFlashNvStorageVariableSize);
+  NvStorageData = AllocateRuntimeZeroPool (NvStorageSize);
+  if (NvStorageData == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  NvStorageBase = NV_STORAGE_VARIABLE_BASE;
+  ASSERT (NvStorageBase != 0);
+
+  //
+  // 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;
+}
-- 
2.16.2.windows.1


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#48944): https://edk2.groups.io/g/devel/message/48944
Mute This Topic: https://groups.io/mt/34540091/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-




More information about the edk2-devel-archive mailing list