}\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
ASSERT (gVariableInfo != NULL);\r
\r
CopyGuid (&gVariableInfo->VendorGuid, VendorGuid);\r
- gVariableInfo->Name = AllocatePool (StrLen (VariableName));\r
+ gVariableInfo->Name = AllocatePool (StrSize (VariableName));\r
ASSERT (gVariableInfo->Name != NULL);\r
StrCpy (gVariableInfo->Name, VariableName);\r
gVariableInfo->Volatile = Volatile;\r
ASSERT (Entry->Next != NULL);\r
\r
CopyGuid (&Entry->Next->VendorGuid, VendorGuid);\r
- Entry->Next->Name = AllocatePool (StrLen (VariableName));\r
+ Entry->Next->Name = AllocatePool (StrSize (VariableName));\r
ASSERT (Entry->Next->Name != NULL);\r
StrCpy (Entry->Next->Name, VariableName);\r
Entry->Next->Volatile = Volatile;\r
Get index from supported language codes according to language string.\r
\r
This code is used to get corresponding index in supported language codes. It can handle\r
- RFC3066 and ISO639 language tags.\r
+ RFC4646 and ISO639 language tags.\r
In ISO639 language tags, take 3-characters as a delimitation to find matched string and calculate the index.\r
- In RFC3066 language tags, take semicolon as a delimitation to find matched string and calculate the index.\r
+ In RFC4646 language tags, take semicolon as a delimitation to find matched string and calculate the index.\r
\r
For example:\r
SupportedLang = "engfraengfra"\r
\r
@param SupportedLang Platform supported language codes.\r
@param Lang Configured language.\r
- @param Iso639Language A bool value to signify if the handler is operated on ISO639 or RFC3066.\r
+ @param Iso639Language A bool value to signify if the handler is operated on ISO639 or RFC4646.\r
\r
@retval the index of language in the language codes.\r
\r
return 0;\r
} else {\r
//\r
- // Compare RFC3066 language code\r
+ // Compare RFC4646 language code\r
//\r
while (*Supported != '\0') {\r
//\r
Get language string from supported language codes according to index.\r
\r
This code is used to get corresponding language string in supported language codes. It can handle\r
- RFC3066 and ISO639 language tags.\r
+ RFC4646 and ISO639 language tags.\r
In ISO639 language tags, take 3-characters as a delimitation. Find language string according to the index.\r
- In RFC3066 language tags, take semicolon as a delimitation. Find language string according to the index.\r
+ In RFC4646 language tags, take semicolon as a delimitation. Find language string according to the index.\r
\r
For example:\r
SupportedLang = "engfraengfra"\r
\r
@param SupportedLang Platform supported language codes.\r
@param Index the index in supported language codes.\r
- @param Iso639Language A bool value to signify if the handler is operated on ISO639 or RFC3066.\r
+ @param Iso639Language A bool value to signify if the handler is operated on ISO639 or RFC4646.\r
\r
@retval the language string in the language codes.\r
\r
// Therefore, in variable driver, only store the original value for other use.\r
//\r
AsciiStrnCpy (mVariableModuleGlobal->LangCodes, Data, DataSize);\r
- } else if (StrCmp (VariableName, L"PlatformLang") == 0) {\r
+ } else if ((StrCmp (VariableName, L"PlatformLang") == 0) && (DataSize != 0)) {\r
ASSERT (AsciiStrLen (mVariableModuleGlobal->PlatformLangCodes) != 0);\r
\r
//\r
Index = GetIndexFromSupportedLangCodes(mVariableModuleGlobal->PlatformLangCodes, BestPlatformLang, FALSE);\r
\r
//\r
- // Get the corresponding ISO639 language tag according to RFC3066 language tag.\r
+ // Get the corresponding ISO639 language tag according to RFC4646 language tag.\r
//\r
BestLang = GetLangFromSupportedLangCodes(mVariableModuleGlobal->LangCodes, Index, TRUE);\r
\r
\r
ASSERT_EFI_ERROR(Status);\r
\r
- } else if (StrCmp (VariableName, L"Lang") == 0) {\r
+ } else if ((StrCmp (VariableName, L"Lang") == 0) && (DataSize != 0)) {\r
ASSERT (AsciiStrLen (mVariableModuleGlobal->LangCodes) != 0);\r
\r
//\r
Index = GetIndexFromSupportedLangCodes(mVariableModuleGlobal->LangCodes, BestLang, TRUE);\r
\r
//\r
- // Get the corresponding RFC3066 language tag according to ISO639 language tag.\r
+ // Get the corresponding RFC4646 language tag according to ISO639 language tag.\r
//\r
BestPlatformLang = GetLangFromSupportedLangCodes(mVariableModuleGlobal->PlatformLangCodes, Index, FALSE);\r
\r
FindVariable(L"PlatformLang", &gEfiGlobalVariableGuid, &Variable, (VARIABLE_GLOBAL *)mVariableModuleGlobal);\r
\r
Status = UpdateVariable(L"PlatformLang", &gEfiGlobalVariableGuid, \r
- BestPlatformLang, AsciiStrLen (BestPlatformLang), Attributes, &Variable);\r
+ BestPlatformLang, AsciiStrSize (BestPlatformLang), Attributes, &Variable);\r
\r
DEBUG((EFI_D_INFO, "Variable Driver Auto Update Lang, Lang:%a, PlatformLang:%a\n", BestLang, BestPlatformLang));\r
ASSERT_EFI_ERROR(Status);\r
UINTN VarDataOffset;\r
UINTN VarSize;\r
VARIABLE_GLOBAL *Global;\r
- UINTN NonVolatileVarableStoreSize;\r
+ UINTN NonVolatileVarableStoreSize;\r
\r
Global = &mVariableModuleGlobal->VariableGlobal[Physical];\r
\r
//\r
// Mark the old variable as deleted\r
//\r
- Variable->CurrPtr->State &= VAR_DELETED;\r
+ if (Variable->CurrPtr != NULL) {\r
+ Variable->CurrPtr->State &= VAR_DELETED;\r
+ }\r
\r
UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, TRUE, FALSE, FALSE);\r
\r
VARIABLE_STORE_HEADER *VariableStoreHeader[2];\r
UINTN Index;\r
\r
- //\r
- // We aquire the lock at the entry of FindVariable as GetVariable, GetNextVariableName\r
- // SetVariable all call FindVariable at entry point. Please move "Aquire Lock" to\r
- // the correct places if this assumption does not hold TRUE anymore.\r
- //\r
- AcquireLockOnlyAtBootTime(&Global->VariableServicesLock);\r
-\r
//\r
// 0: Non-Volatile, 1: Volatile\r
//\r
if (VariableName == NULL || VendorGuid == NULL || DataSize == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
+\r
+ AcquireLockOnlyAtBootTime(&Global->VariableServicesLock);\r
+\r
//\r
// Find existing variable\r
//\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
+ AcquireLockOnlyAtBootTime(&Global->VariableServicesLock);\r
+\r
Status = FindVariable (VariableName, VendorGuid, &Variable, Global);\r
\r
if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {\r
if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {\r
return EFI_INVALID_PARAMETER;\r
} \r
+\r
+ if (DataSize != 0 && Data == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
//\r
// Make sure if runtime bit is set, boot service bit is set also\r
//\r
} \r
}\r
\r
+ AcquireLockOnlyAtBootTime(&Global->VariableServicesLock);\r
+\r
//\r
// Check whether the input variable is already existed\r
//\r
\r
This function allocates memory space for variable store area and initializes its attributes.\r
\r
- @param VariableBase Base of the variable store area created\r
- @param LastVariableOffset Size of VARIABLE_STORE_HEADER\r
+ @param VolatileStore Indicates if the variable store is volatile.\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
- // Allocate memory for volatile variable store\r
+ // Note that in EdkII variable driver implementation, Hardware Error Record type variable\r
+ // is stored with common variable in the same NV region. So the platform integrator should\r
+ // ensure that the value of PcdHwErrStorageSize is less than or equal to the value of \r
+ // PcdVariableStoreSize.\r
+ //\r
+ ASSERT (FixedPcdGet32(PcdHwErrStorageSize) <= FixedPcdGet32(PcdVariableStoreSize));\r
+\r
//\r
- VariableStore = (VARIABLE_STORE_HEADER *) AllocateRuntimePool (\r
- FixedPcdGet32(PcdVariableStoreSize)\r
- );\r
+ // Allocate memory for variable store.\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