}\r
\r
/**\r
- Gets pointer to header of the next variable.\r
+ Gets pointer to header of the next potential variable.\r
\r
- This function gets the pointer to the next variable header according\r
- to the input point to the variable header.\r
+ This function gets the pointer to the next potential variable header\r
+ according to the input point to the variable header. The return value\r
+ is not a valid variable if the input variable was the last variable\r
+ in the variabl store.\r
\r
@param Variable Pointer to header of the next variable\r
\r
@return Pointer to next variable header.\r
+ @retval NULL Input was not a valid variable header.\r
\r
**/\r
VARIABLE_HEADER *\r
-GetNextVariablePtr (\r
+GetNextPotentialVariablePtr (\r
IN VARIABLE_HEADER *Variable\r
)\r
{\r
//\r
VarHeader = (VARIABLE_HEADER *) (GetVariableDataPtr (Variable) + Variable->DataSize + GET_PAD_SIZE (Variable->DataSize));\r
\r
- if (VarHeader->StartId != VARIABLE_DATA) {\r
+ return VarHeader;\r
+}\r
+\r
+/**\r
+ Gets pointer to header of the next variable.\r
+\r
+ This function gets the pointer to the next variable header according\r
+ to the input point to the variable header.\r
+\r
+ @param Variable Pointer to header of the next variable\r
+\r
+ @return Pointer to next variable header.\r
+\r
+**/\r
+VARIABLE_HEADER *\r
+GetNextVariablePtr (\r
+ IN VARIABLE_HEADER *Variable\r
+ )\r
+{\r
+ VARIABLE_HEADER *VarHeader;\r
+\r
+ VarHeader = GetNextPotentialVariablePtr (Variable);\r
+\r
+ if ((VarHeader == NULL) || (VarHeader->StartId != VARIABLE_DATA)) {\r
return NULL;\r
}\r
\r
return VarHeader;\r
}\r
\r
+/**\r
+ Updates LastVariableOffset variable for the given variable store.\r
+\r
+ LastVariableOffset points to the offset to use for the next variable\r
+ when updating the variable store.\r
+\r
+ @param[in] VariableStore Pointer to the start of the variable store\r
+ @param[out] LastVariableOffset Offset to put the next new variable in\r
+\r
+**/\r
+VOID\r
+InitializeLocationForLastVariableOffset (\r
+ IN VARIABLE_STORE_HEADER *VariableStore,\r
+ OUT UINTN *LastVariableOffset\r
+ )\r
+{\r
+ VARIABLE_HEADER *VarHeader;\r
+\r
+ *LastVariableOffset = sizeof (VARIABLE_STORE_HEADER);\r
+ VarHeader = (VARIABLE_HEADER*) ((UINT8*)VariableStore + *LastVariableOffset);\r
+ while (VarHeader->StartId == VARIABLE_DATA) {\r
+ VarHeader = GetNextPotentialVariablePtr (VarHeader);\r
+\r
+ if (VarHeader != NULL) {\r
+ *LastVariableOffset = (UINTN) VarHeader - (UINTN) VariableStore;\r
+ } else {\r
+ return;\r
+ }\r
+ }\r
+}\r
+\r
/**\r
Gets pointer to the end of the variable storage area.\r
\r
**/\r
EFI_STATUS\r
InitializeVariableStore (\r
- OUT EFI_PHYSICAL_ADDRESS *VariableBase,\r
- OUT UINTN *LastVariableOffset\r
+ IN BOOLEAN VolatileStore\r
)\r
{\r
VARIABLE_STORE_HEADER *VariableStore;\r
+ BOOLEAN FullyInitializeStore;\r
+ EFI_PHYSICAL_ADDRESS *VariableBase;\r
+ UINTN *LastVariableOffset;\r
+\r
+ FullyInitializeStore = TRUE;\r
+\r
+ if (VolatileStore) {\r
+ VariableBase = &mVariableModuleGlobal->VariableGlobal[Physical].VolatileVariableBase;\r
+ LastVariableOffset = &mVariableModuleGlobal->VolatileLastVariableOffset;\r
+ } else {\r
+ VariableBase = &mVariableModuleGlobal->VariableGlobal[Physical].NonVolatileVariableBase;\r
+ LastVariableOffset = &mVariableModuleGlobal->NonVolatileLastVariableOffset;\r
+ }\r
\r
//\r
// Note that in EdkII variable driver implementation, Hardware Error Record type variable\r
ASSERT (FixedPcdGet32(PcdHwErrStorageSize) <= FixedPcdGet32(PcdVariableStoreSize));\r
\r
//\r
- // Allocate memory for volatile variable store\r
+ // Allocate memory for variable store.\r
//\r
- VariableStore = (VARIABLE_STORE_HEADER *) AllocateRuntimePool (\r
- FixedPcdGet32(PcdVariableStoreSize)\r
- );\r
+ if (VolatileStore || (PcdGet64 (PcdEmuVariableNvStoreReserved) == 0)) {\r
+ VariableStore = (VARIABLE_STORE_HEADER *) AllocateRuntimePool (\r
+ FixedPcdGet32(PcdVariableStoreSize)\r
+ );\r
+ } else {\r
+ //\r
+ // A memory location has been reserved for the NV variable store. Certain\r
+ // platforms may be able to preserve a memory range across system resets,\r
+ // thereby providing better NV variable emulation.\r
+ //\r
+ VariableStore =\r
+ (VARIABLE_STORE_HEADER *)(VOID*)(UINTN)\r
+ PcdGet64 (PcdEmuVariableNvStoreReserved);\r
+ if (\r
+ (VariableStore->Size == FixedPcdGet32(PcdVariableStoreSize)) &&\r
+ (VariableStore->Format == VARIABLE_STORE_FORMATTED) &&\r
+ (VariableStore->State == VARIABLE_STORE_HEALTHY)\r
+ ) {\r
+ DEBUG((\r
+ EFI_D_INFO,\r
+ "Variable Store reserved at %p appears to be valid\n",\r
+ VariableStore\r
+ ));\r
+ FullyInitializeStore = FALSE;\r
+ }\r
+ }\r
+\r
if (NULL == VariableStore) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- SetMem (VariableStore, FixedPcdGet32(PcdVariableStoreSize), 0xff);\r
+ if (FullyInitializeStore) {\r
+ SetMem (VariableStore, FixedPcdGet32(PcdVariableStoreSize), 0xff);\r
+ }\r
\r
//\r
// Variable Specific Data\r
//\r
*VariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VariableStore;\r
- *LastVariableOffset = sizeof (VARIABLE_STORE_HEADER);\r
+ InitializeLocationForLastVariableOffset (VariableStore, LastVariableOffset);\r
\r
CopyGuid (&VariableStore->Signature, &gEfiVariableGuid);\r
VariableStore->Size = FixedPcdGet32(PcdVariableStoreSize);\r
//\r
// Intialize volatile variable store\r
//\r
- Status = InitializeVariableStore (\r
- &mVariableModuleGlobal->VariableGlobal[Physical].VolatileVariableBase,\r
- &mVariableModuleGlobal->VolatileLastVariableOffset\r
- );\r
-\r
+ Status = InitializeVariableStore (TRUE);\r
if (EFI_ERROR (Status)) {\r
FreePool(mVariableModuleGlobal);\r
return Status;\r
//\r
// Intialize non volatile variable store\r
//\r
- Status = InitializeVariableStore (\r
- &mVariableModuleGlobal->VariableGlobal[Physical].NonVolatileVariableBase,\r
- &mVariableModuleGlobal->NonVolatileLastVariableOffset\r
- );\r
+ Status = InitializeVariableStore (FALSE);\r
\r
return Status;\r
}\r