summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MdeModulePkg/MdeModulePkg.dec4
-rw-r--r--MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariable.c132
-rw-r--r--MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf1
3 files changed, 115 insertions, 22 deletions
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index 83c8534..7a167ac 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -321,6 +321,10 @@
# This PCD is a sample to explain String typed PCD usage.
gEfiMdeModulePkgTokenSpaceGuid.PcdHelloWorldPrintString|L"UEFI Hello World!\n"|VOID*|0x40000004
+ ## This PCD defines a reserved memory range for the EMU Variable driver's NV Variable Store
+ # The range is valid if non-zero. The memory range size must be PcdVariableStoreSize.
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved|0|UINT64|0x40000008
+
[PcdsFixedAtBuild,PcdsPatchableInModule,PcdsDynamic]
## This PCD defines the times to print hello world string.
# This PCD is a sample to explain FixedAtBuild UINT32 PCD usage.
diff --git a/MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariable.c b/MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariable.c
index d2f4d67..fd0228d 100644
--- a/MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariable.c
+++ b/MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariable.c
@@ -160,18 +160,21 @@ GetVariableDataPtr (
}
/**
- Gets pointer to header of the next variable.
+ Gets pointer to header of the next potential variable.
- This function gets the pointer to the next variable header according
- to the input point to the variable header.
+ This function gets the pointer to the next potential variable header
+ according to the input point to the variable header. The return value
+ is not a valid variable if the input variable was the last variable
+ in the variabl store.
@param Variable Pointer to header of the next variable
@return Pointer to next variable header.
+ @retval NULL Input was not a valid variable header.
**/
VARIABLE_HEADER *
-GetNextVariablePtr (
+GetNextPotentialVariablePtr (
IN VARIABLE_HEADER *Variable
)
{
@@ -185,7 +188,30 @@ GetNextVariablePtr (
//
VarHeader = (VARIABLE_HEADER *) (GetVariableDataPtr (Variable) + Variable->DataSize + GET_PAD_SIZE (Variable->DataSize));
- if (VarHeader->StartId != VARIABLE_DATA) {
+ return VarHeader;
+}
+
+/**
+ Gets pointer to header of the next variable.
+
+ This function gets the pointer to the next variable header according
+ to the input point to the variable header.
+
+ @param Variable Pointer to header of the next variable
+
+ @return Pointer to next variable header.
+
+**/
+VARIABLE_HEADER *
+GetNextVariablePtr (
+ IN VARIABLE_HEADER *Variable
+ )
+{
+ VARIABLE_HEADER *VarHeader;
+
+ VarHeader = GetNextPotentialVariablePtr (Variable);
+
+ if ((VarHeader == NULL) || (VarHeader->StartId != VARIABLE_DATA)) {
return NULL;
}
@@ -193,6 +219,37 @@ GetNextVariablePtr (
}
/**
+ Updates LastVariableOffset variable for the given variable store.
+
+ LastVariableOffset points to the offset to use for the next variable
+ when updating the variable store.
+
+ @param[in] VariableStore Pointer to the start of the variable store
+ @param[out] LastVariableOffset Offset to put the next new variable in
+
+**/
+VOID
+InitializeLocationForLastVariableOffset (
+ IN VARIABLE_STORE_HEADER *VariableStore,
+ OUT UINTN *LastVariableOffset
+ )
+{
+ VARIABLE_HEADER *VarHeader;
+
+ *LastVariableOffset = sizeof (VARIABLE_STORE_HEADER);
+ VarHeader = (VARIABLE_HEADER*) ((UINT8*)VariableStore + *LastVariableOffset);
+ while (VarHeader->StartId == VARIABLE_DATA) {
+ VarHeader = GetNextPotentialVariablePtr (VarHeader);
+
+ if (VarHeader != NULL) {
+ *LastVariableOffset = (UINTN) VarHeader - (UINTN) VariableStore;
+ } else {
+ return;
+ }
+ }
+}
+
+/**
Gets pointer to the end of the variable storage area.
This function gets pointer to the end of the variable storage
@@ -1307,11 +1364,23 @@ EmuQueryVariableInfo (
**/
EFI_STATUS
InitializeVariableStore (
- OUT EFI_PHYSICAL_ADDRESS *VariableBase,
- OUT UINTN *LastVariableOffset
+ IN BOOLEAN VolatileStore
)
{
VARIABLE_STORE_HEADER *VariableStore;
+ BOOLEAN FullyInitializeStore;
+ EFI_PHYSICAL_ADDRESS *VariableBase;
+ UINTN *LastVariableOffset;
+
+ FullyInitializeStore = TRUE;
+
+ if (VolatileStore) {
+ VariableBase = &mVariableModuleGlobal->VariableGlobal[Physical].VolatileVariableBase;
+ LastVariableOffset = &mVariableModuleGlobal->VolatileLastVariableOffset;
+ } else {
+ VariableBase = &mVariableModuleGlobal->VariableGlobal[Physical].NonVolatileVariableBase;
+ LastVariableOffset = &mVariableModuleGlobal->NonVolatileLastVariableOffset;
+ }
//
// Note that in EdkII variable driver implementation, Hardware Error Record type variable
@@ -1322,22 +1391,48 @@ InitializeVariableStore (
ASSERT (FixedPcdGet32(PcdHwErrStorageSize) <= FixedPcdGet32(PcdVariableStoreSize));
//
- // Allocate memory for volatile variable store
+ // Allocate memory for variable store.
//
- VariableStore = (VARIABLE_STORE_HEADER *) AllocateRuntimePool (
- FixedPcdGet32(PcdVariableStoreSize)
- );
+ if (VolatileStore || (PcdGet64 (PcdEmuVariableNvStoreReserved) == 0)) {
+ VariableStore = (VARIABLE_STORE_HEADER *) AllocateRuntimePool (
+ FixedPcdGet32(PcdVariableStoreSize)
+ );
+ } 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 == FixedPcdGet32(PcdVariableStoreSize)) &&
+ (VariableStore->Format == VARIABLE_STORE_FORMATTED) &&
+ (VariableStore->State == VARIABLE_STORE_HEALTHY)
+ ) {
+ DEBUG((
+ EFI_D_INFO,
+ "Variable Store reserved at %p appears to be valid\n",
+ VariableStore
+ ));
+ FullyInitializeStore = FALSE;
+ }
+ }
+
if (NULL == VariableStore) {
return EFI_OUT_OF_RESOURCES;
}
- SetMem (VariableStore, FixedPcdGet32(PcdVariableStoreSize), 0xff);
+ if (FullyInitializeStore) {
+ SetMem (VariableStore, FixedPcdGet32(PcdVariableStoreSize), 0xff);
+ }
//
// Variable Specific Data
//
*VariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VariableStore;
- *LastVariableOffset = sizeof (VARIABLE_STORE_HEADER);
+ InitializeLocationForLastVariableOffset (VariableStore, LastVariableOffset);
CopyGuid (&VariableStore->Signature, &gEfiVariableGuid);
VariableStore->Size = FixedPcdGet32(PcdVariableStoreSize);
@@ -1386,11 +1481,7 @@ VariableCommonInitialize (
//
// Intialize volatile variable store
//
- Status = InitializeVariableStore (
- &mVariableModuleGlobal->VariableGlobal[Physical].VolatileVariableBase,
- &mVariableModuleGlobal->VolatileLastVariableOffset
- );
-
+ Status = InitializeVariableStore (TRUE);
if (EFI_ERROR (Status)) {
FreePool(mVariableModuleGlobal);
return Status;
@@ -1398,10 +1489,7 @@ VariableCommonInitialize (
//
// Intialize non volatile variable store
//
- Status = InitializeVariableStore (
- &mVariableModuleGlobal->VariableGlobal[Physical].NonVolatileVariableBase,
- &mVariableModuleGlobal->NonVolatileLastVariableOffset
- );
+ Status = InitializeVariableStore (FALSE);
return Status;
}
diff --git a/MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf b/MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf
index 4f7d06b..ffd92c6 100644
--- a/MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf
+++ b/MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf
@@ -60,6 +60,7 @@
gEfiVariableGuid
[Pcd.common]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize
gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize