///\r
ESAL_VARIABLE_GLOBAL *mVariableModuleGlobal;\r
\r
+VARIABLE_INFO_ENTRY *gVariableInfo = NULL;\r
+\r
+///\r
+/// The size of a 3 character ISO639 language code.\r
+///\r
+#define ISO_639_2_ENTRY_SIZE 3\r
+\r
+/**\r
+ Update the variable region with Variable information. These are the same \r
+ arguments as the EFI Variable services.\r
+\r
+ @param[in] VariableName Name of variable\r
+\r
+ @param[in] VendorGuid Guid of variable\r
+\r
+ @param[in] Data Variable data\r
+\r
+ @param[in] DataSize Size of data. 0 means delete\r
+\r
+ @param[in] Attributes Attribues of the variable\r
+\r
+ @param[in] Variable The variable information which is used to keep track of variable usage.\r
+\r
+ @retval EFI_SUCCESS The update operation is success.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES Variable region is full, can not write other data into this region.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UpdateVariable (\r
+ IN CHAR16 *VariableName,\r
+ IN EFI_GUID *VendorGuid,\r
+ IN VOID *Data,\r
+ IN UINTN DataSize,\r
+ IN UINT32 Attributes OPTIONAL,\r
+ IN VARIABLE_POINTER_TRACK *Variable\r
+ );\r
+\r
+/**\r
+ Finds variable in storage blocks of volatile and non-volatile storage areas.\r
+\r
+ This code finds variable in storage blocks of volatile and non-volatile storage areas.\r
+ If VariableName is an empty string, then we just return the first\r
+ qualified variable without comparing VariableName and VendorGuid.\r
+ Otherwise, VariableName and VendorGuid are compared.\r
+\r
+ @param VariableName Name of the variable to be found.\r
+ @param VendorGuid Vendor GUID to be found.\r
+ @param PtrTrack VARIABLE_POINTER_TRACK structure for output,\r
+ including the range searched and the target position.\r
+ @param Global Pointer to VARIABLE_GLOBAL structure, including\r
+ base of volatile variable storage area, base of\r
+ NV variable storage area, and a lock.\r
+\r
+ @retval EFI_INVALID_PARAMETER If VariableName is not an empty string, while\r
+ VendorGuid is NULL.\r
+ @retval EFI_SUCCESS Variable successfully found.\r
+ @retval EFI_NOT_FOUND Variable not found.\r
+\r
+**/\r
+EFI_STATUS\r
+FindVariable (\r
+ IN CHAR16 *VariableName,\r
+ IN EFI_GUID *VendorGuid,\r
+ OUT VARIABLE_POINTER_TRACK *PtrTrack,\r
+ IN VARIABLE_GLOBAL *Global\r
+ );\r
\r
/**\r
Acquires lock only at boot time. Simply returns at runtime.\r
//\r
VarHeader = (VARIABLE_HEADER *) (GetVariableDataPtr (Variable) + Variable->DataSize + GET_PAD_SIZE (Variable->DataSize));\r
\r
- if (VarHeader->StartId != VARIABLE_DATA ||\r
- (sizeof (VARIABLE_HEADER) + VarHeader->DataSize + VarHeader->NameSize) > FixedPcdGet32(PcdMaxVariableSize)\r
- ) {\r
+ if (VarHeader->StartId != VARIABLE_DATA) {\r
return NULL;\r
}\r
\r
return (VARIABLE_HEADER *) ((UINTN) VolHeader + VolHeader->Size);\r
}\r
\r
+/**\r
+ Routine used to track statistical information about variable usage. \r
+ The data is stored in the EFI system table so it can be accessed later.\r
+ VariableInfo.efi can dump out the table. Only Boot Services variable \r
+ accesses are tracked by this code. The PcdVariableCollectStatistics\r
+ build flag controls if this feature is enabled. \r
+\r
+ A read that hits in the cache will have Read and Cache true for \r
+ the transaction. Data is allocated by this routine, but never\r
+ freed.\r
+\r
+ @param[in] VariableName Name of the Variable to track\r
+ @param[in] VendorGuid Guid of the Variable to track\r
+ @param[in] Volatile TRUE if volatile FALSE if non-volatile\r
+ @param[in] Read TRUE if GetVariable() was called\r
+ @param[in] Write TRUE if SetVariable() was called\r
+ @param[in] Delete TRUE if deleted via SetVariable()\r
+ @param[in] Cache TRUE for a cache hit.\r
+\r
+**/\r
+VOID\r
+UpdateVariableInfo (\r
+ IN CHAR16 *VariableName,\r
+ IN EFI_GUID *VendorGuid,\r
+ IN BOOLEAN Volatile,\r
+ IN BOOLEAN Read,\r
+ IN BOOLEAN Write,\r
+ IN BOOLEAN Delete,\r
+ IN BOOLEAN Cache\r
+ )\r
+{\r
+ VARIABLE_INFO_ENTRY *Entry;\r
+\r
+ if (FeaturePcdGet (PcdVariableCollectStatistics)) {\r
+\r
+ if (EfiAtRuntime ()) {\r
+ // Don't collect statistics at runtime\r
+ return;\r
+ }\r
+\r
+ if (gVariableInfo == NULL) {\r
+ //\r
+ // on the first call allocate a entry and place a pointer to it in\r
+ // the EFI System Table\r
+ //\r
+ gVariableInfo = AllocateZeroPool (sizeof (VARIABLE_INFO_ENTRY));\r
+ ASSERT (gVariableInfo != NULL);\r
+\r
+ CopyGuid (&gVariableInfo->VendorGuid, VendorGuid);\r
+ gVariableInfo->Name = AllocatePool (StrLen (VariableName));\r
+ ASSERT (gVariableInfo->Name != NULL);\r
+ StrCpy (gVariableInfo->Name, VariableName);\r
+ gVariableInfo->Volatile = Volatile;\r
+\r
+ gBS->InstallConfigurationTable (&gEfiVariableGuid, gVariableInfo);\r
+ }\r
+\r
+ \r
+ for (Entry = gVariableInfo; Entry != NULL; Entry = Entry->Next) {\r
+ if (CompareGuid (VendorGuid, &Entry->VendorGuid)) {\r
+ if (StrCmp (VariableName, Entry->Name) == 0) {\r
+ if (Read) {\r
+ Entry->ReadCount++;\r
+ }\r
+ if (Write) {\r
+ Entry->WriteCount++;\r
+ }\r
+ if (Delete) {\r
+ Entry->DeleteCount++;\r
+ }\r
+ if (Cache) {\r
+ Entry->CacheCount++;\r
+ }\r
+\r
+ return;\r
+ }\r
+ }\r
+\r
+ if (Entry->Next == NULL) {\r
+ //\r
+ // If the entry is not in the table add it.\r
+ // Next iteration of the loop will fill in the data\r
+ //\r
+ Entry->Next = AllocateZeroPool (sizeof (VARIABLE_INFO_ENTRY));\r
+ ASSERT (Entry->Next != NULL);\r
+\r
+ CopyGuid (&Entry->Next->VendorGuid, VendorGuid);\r
+ Entry->Next->Name = AllocatePool (StrLen (VariableName));\r
+ ASSERT (Entry->Next->Name != NULL);\r
+ StrCpy (Entry->Next->Name, VariableName);\r
+ Entry->Next->Volatile = Volatile;\r
+ }\r
+\r
+ }\r
+ }\r
+}\r
+\r
+/**\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
+ 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 RFC4646 language tags, take semicolon as a delimitation to find matched string and calculate the index.\r
+\r
+ For example:\r
+ SupportedLang = "engfraengfra"\r
+ Lang = "eng"\r
+ Iso639Language = TRUE\r
+ The return value is "0".\r
+ Another example:\r
+ SupportedLang = "en;fr;en-US;fr-FR"\r
+ Lang = "fr-FR"\r
+ Iso639Language = FALSE\r
+ The return value is "3".\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 RFC4646.\r
+\r
+ @retval the index of language in the language codes.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+GetIndexFromSupportedLangCodes(\r
+ IN CHAR8 *SupportedLang,\r
+ IN CHAR8 *Lang,\r
+ IN BOOLEAN Iso639Language\r
+ ) \r
+{\r
+ UINTN Index;\r
+ UINT32 CompareLength;\r
+ CHAR8 *Supported;\r
+\r
+ Index = 0;\r
+ Supported = SupportedLang;\r
+ if (Iso639Language) {\r
+ CompareLength = 3;\r
+ for (Index = 0; Index < AsciiStrLen (SupportedLang); Index += CompareLength) {\r
+ if (AsciiStrnCmp (Lang, SupportedLang + Index, CompareLength) == 0) {\r
+ //\r
+ // Successfully find the index of Lang string in SupportedLang string.\r
+ //\r
+ Index = Index / CompareLength;\r
+ return Index;\r
+ }\r
+ }\r
+ ASSERT (FALSE);\r
+ return 0;\r
+ } else {\r
+ //\r
+ // Compare RFC4646 language code\r
+ //\r
+ while (*Supported != '\0') {\r
+ //\r
+ // take semicolon as delimitation, sequentially traverse supported language codes.\r
+ //\r
+ for (CompareLength = 0; *Supported != ';' && *Supported != '\0'; CompareLength++) {\r
+ Supported++;\r
+ }\r
+ if (AsciiStrnCmp (Lang, Supported - CompareLength, CompareLength) == 0) {\r
+ //\r
+ // Successfully find the index of Lang string in SupportedLang string.\r
+ //\r
+ return Index;\r
+ }\r
+ Index++;\r
+ }\r
+ ASSERT (FALSE);\r
+ return 0;\r
+ }\r
+}\r
+\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
+ 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 RFC4646 language tags, take semicolon as a delimitation. Find language string according to the index.\r
+\r
+ For example:\r
+ SupportedLang = "engfraengfra"\r
+ Index = "1"\r
+ Iso639Language = TRUE\r
+ The return value is "fra".\r
+ Another example:\r
+ SupportedLang = "en;fr;en-US;fr-FR"\r
+ Index = "1"\r
+ Iso639Language = FALSE\r
+ The return value is "fr".\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 RFC4646.\r
+\r
+ @retval the language string in the language codes.\r
+\r
+**/\r
+CHAR8 *\r
+EFIAPI\r
+GetLangFromSupportedLangCodes (\r
+ IN CHAR8 *SupportedLang,\r
+ IN UINTN Index,\r
+ IN BOOLEAN Iso639Language\r
+)\r
+{\r
+ UINTN SubIndex;\r
+ UINT32 CompareLength;\r
+ CHAR8 *Supported;\r
+\r
+ SubIndex = 0;\r
+ Supported = SupportedLang;\r
+ if (Iso639Language) {\r
+ //\r
+ // according to the index of Lang string in SupportedLang string to get the language.\r
+ // As this code will be invoked in RUNTIME, therefore there is not memory allocate/free operation.\r
+ // In driver entry, it pre-allocates a runtime attribute memory to accommodate this string.\r
+ //\r
+ CompareLength = 3;\r
+ SetMem (mVariableModuleGlobal->Lang, sizeof(mVariableModuleGlobal->Lang), 0);\r
+ return CopyMem (mVariableModuleGlobal->Lang, SupportedLang + Index * CompareLength, CompareLength);\r
+ \r
+ } else {\r
+ while (TRUE) {\r
+ //\r
+ // take semicolon as delimitation, sequentially traverse supported language codes.\r
+ //\r
+ for (CompareLength = 0; *Supported != ';' && *Supported != '\0'; CompareLength++) {\r
+ Supported++;\r
+ }\r
+ if ((*Supported == '\0') && (SubIndex != Index)) {\r
+ //\r
+ // Have completed the traverse, but not find corrsponding string.\r
+ // This case is not allowed to happen.\r
+ //\r
+ ASSERT(FALSE);\r
+ return NULL;\r
+ }\r
+ if (SubIndex == Index) {\r
+ //\r
+ // according to the index of Lang string in SupportedLang string to get the language.\r
+ // As this code will be invoked in RUNTIME, therefore there is not memory allocate/free operation.\r
+ // In driver entry, it pre-allocates a runtime attribute memory to accommodate this string.\r
+ //\r
+ SetMem (mVariableModuleGlobal->PlatformLang, sizeof (mVariableModuleGlobal->PlatformLang), 0);\r
+ return CopyMem (mVariableModuleGlobal->PlatformLang, Supported - CompareLength, CompareLength);\r
+ }\r
+ SubIndex++; \r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Hook the operations in PlatformLangCodes, LangCodes, PlatformLang and Lang.\r
+\r
+ When setting Lang/LangCodes, simultaneously update PlatformLang/PlatformLangCodes.\r
+\r
+ According to UEFI spec, PlatformLangCodes/LangCodes are only set once in firmware initialization,\r
+ and are read-only. Therefore, in variable driver, only store the original value for other use.\r
+\r
+ @param[in] VariableName Name of variable\r
+\r
+ @param[in] Data Variable data\r
+\r
+ @param[in] DataSize Size of data. 0 means delete\r
+\r
+ @retval EFI_SUCCESS auto update operation is successful.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AutoUpdateLangVariable(\r
+ IN CHAR16 *VariableName,\r
+ IN VOID *Data,\r
+ IN UINTN DataSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CHAR8 *BestPlatformLang;\r
+ CHAR8 *BestLang;\r
+ UINTN Index;\r
+ UINT32 Attributes;\r
+ VARIABLE_POINTER_TRACK Variable;\r
+\r
+ //\r
+ // According to UEFI spec, "Lang" and "PlatformLang" is NV|BS|RT attributions.\r
+ //\r
+ Attributes = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;\r
+\r
+ if (StrCmp (VariableName, L"PlatformLangCodes") == 0) {\r
+ //\r
+ // According to UEFI spec, PlatformLangCodes is only set once in firmware initialization, and is read-only\r
+ // Therefore, in variable driver, only store the original value for other use.\r
+ //\r
+ AsciiStrnCpy (mVariableModuleGlobal->PlatformLangCodes, Data, DataSize);\r
+ } else if (StrCmp (VariableName, L"LangCodes") == 0) {\r
+ //\r
+ // According to UEFI spec, LangCodes is only set once in firmware initialization, and is read-only\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
+ ASSERT (AsciiStrLen (mVariableModuleGlobal->PlatformLangCodes) != 0);\r
+\r
+ //\r
+ // When setting PlatformLang, firstly get most matched language string from supported language codes.\r
+ //\r
+ BestPlatformLang = GetBestLanguage(mVariableModuleGlobal->PlatformLangCodes, FALSE, Data, NULL);\r
+\r
+ //\r
+ // Get the corresponding index in language codes.\r
+ //\r
+ Index = GetIndexFromSupportedLangCodes(mVariableModuleGlobal->PlatformLangCodes, BestPlatformLang, FALSE);\r
+\r
+ //\r
+ // Get the corresponding ISO639 language tag according to RFC4646 language tag.\r
+ //\r
+ BestLang = GetLangFromSupportedLangCodes(mVariableModuleGlobal->LangCodes, Index, TRUE);\r
+\r
+ //\r
+ // Successfully convert PlatformLang to Lang, and set the BestLang value into Lang variable simultaneously.\r
+ //\r
+ FindVariable(L"Lang", &gEfiGlobalVariableGuid, &Variable, (VARIABLE_GLOBAL *)mVariableModuleGlobal);\r
+\r
+ Status = UpdateVariable(L"Lang", &gEfiGlobalVariableGuid, \r
+ BestLang, ISO_639_2_ENTRY_SIZE + 1, Attributes, &Variable);\r
+\r
+ DEBUG((EFI_D_INFO, "Variable Driver Auto Update PlatformLang, PlatformLang:%a, Lang:%a\n", BestPlatformLang, BestLang));\r
+\r
+ ASSERT_EFI_ERROR(Status);\r
+\r
+ } else if (StrCmp (VariableName, L"Lang") == 0) {\r
+ ASSERT (AsciiStrLen (mVariableModuleGlobal->LangCodes) != 0);\r
+\r
+ //\r
+ // When setting Lang, firstly get most matched language string from supported language codes.\r
+ //\r
+ BestLang = GetBestLanguage(mVariableModuleGlobal->LangCodes, TRUE, Data, NULL);\r
+\r
+ //\r
+ // Get the corresponding index in language codes.\r
+ //\r
+ Index = GetIndexFromSupportedLangCodes(mVariableModuleGlobal->LangCodes, BestLang, TRUE);\r
+\r
+ //\r
+ // Get the corresponding RFC4646 language tag according to ISO639 language tag.\r
+ //\r
+ BestPlatformLang = GetLangFromSupportedLangCodes(mVariableModuleGlobal->PlatformLangCodes, Index, FALSE);\r
+\r
+ //\r
+ // Successfully convert Lang to PlatformLang, and set the BestPlatformLang value into PlatformLang variable simultaneously.\r
+ //\r
+ FindVariable(L"PlatformLang", &gEfiGlobalVariableGuid, &Variable, (VARIABLE_GLOBAL *)mVariableModuleGlobal);\r
+\r
+ Status = UpdateVariable(L"PlatformLang", &gEfiGlobalVariableGuid, \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
+ }\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Update the variable region with Variable information. These are the same \r
+ arguments as the EFI Variable services.\r
+\r
+ @param[in] VariableName Name of variable\r
+\r
+ @param[in] VendorGuid Guid of variable\r
+\r
+ @param[in] Data Variable data\r
+\r
+ @param[in] DataSize Size of data. 0 means delete\r
+\r
+ @param[in] Attributes Attribues of the variable\r
+\r
+ @param[in] Variable The variable information which is used to keep track of variable usage.\r
+\r
+ @retval EFI_SUCCESS The update operation is success.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES Variable region is full, can not write other data into this region.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UpdateVariable (\r
+ IN CHAR16 *VariableName,\r
+ IN EFI_GUID *VendorGuid,\r
+ IN VOID *Data,\r
+ IN UINTN DataSize,\r
+ IN UINT32 Attributes OPTIONAL,\r
+ IN VARIABLE_POINTER_TRACK *Variable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ VARIABLE_HEADER *NextVariable;\r
+ UINTN VarNameSize;\r
+ UINTN VarNameOffset;\r
+ UINTN VarDataOffset;\r
+ UINTN VarSize;\r
+ VARIABLE_GLOBAL *Global;\r
+ UINTN NonVolatileVarableStoreSize;\r
+\r
+ Global = &mVariableModuleGlobal->VariableGlobal[Physical];\r
+\r
+ if (Variable->CurrPtr != NULL) {\r
+ //\r
+ // Update/Delete existing variable\r
+ //\r
+\r
+ if (EfiAtRuntime ()) { \r
+ //\r
+ // If EfiAtRuntime and the variable is Volatile and Runtime Access, \r
+ // the volatile is ReadOnly, and SetVariable should be aborted and \r
+ // return EFI_WRITE_PROTECTED.\r
+ //\r
+ if (Variable->Volatile) {\r
+ Status = EFI_WRITE_PROTECTED;\r
+ goto Done;\r
+ }\r
+ //\r
+ // Only variable have NV attribute can be updated/deleted in Runtime\r
+ //\r
+ if ((Variable->CurrPtr->Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Setting a data variable with no access, or zero DataSize attributes\r
+ // specified causes it to be deleted.\r
+ //\r
+ if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) {\r
+ Variable->CurrPtr->State &= VAR_DELETED;\r
+ UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, FALSE, TRUE, FALSE);\r
+ Status = EFI_SUCCESS;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // If the variable is marked valid and the same data has been passed in\r
+ // then return to the caller immediately.\r
+ //\r
+ if (Variable->CurrPtr->DataSize == DataSize &&\r
+ CompareMem (Data, GetVariableDataPtr (Variable->CurrPtr), DataSize) == 0\r
+ ) {\r
+ Status = EFI_SUCCESS;\r
+ goto Done;\r
+ } else if (Variable->CurrPtr->State == VAR_ADDED) {\r
+ //\r
+ // Mark the old variable as in delete transition\r
+ //\r
+ Variable->CurrPtr->State &= VAR_IN_DELETED_TRANSITION;\r
+ }\r
+ \r
+ } else {\r
+ //\r
+ // No found existing variable, Create a new variable\r
+ // \r
+ \r
+ //\r
+ // Make sure we are trying to create a new variable.\r
+ // Setting a data variable with no access, or zero DataSize attributes means to delete it. \r
+ //\r
+ if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) {\r
+ Status = EFI_NOT_FOUND;\r
+ goto Done;\r
+ }\r
+ \r
+ //\r
+ // Only variable have NV|RT attribute can be created in Runtime\r
+ //\r
+ if (EfiAtRuntime () &&\r
+ (((Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) || ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0))) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ } \r
+ }\r
+ \r
+ //\r
+ // Function part - create a new variable and copy the data.\r
+ // Both update a variable and create a variable will come here.\r
+ //\r
+ \r
+ VarNameOffset = sizeof (VARIABLE_HEADER);\r
+ VarNameSize = StrSize (VariableName);\r
+ VarDataOffset = VarNameOffset + VarNameSize + GET_PAD_SIZE (VarNameSize);\r
+ VarSize = VarDataOffset + DataSize + GET_PAD_SIZE (DataSize);\r
+\r
+ if ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0) {\r
+ NonVolatileVarableStoreSize = ((VARIABLE_STORE_HEADER *)(UINTN)(Global->NonVolatileVariableBase))->Size;\r
+ if ((((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != 0) \r
+ && ((VarSize + mVariableModuleGlobal->HwErrVariableTotalSize) > FixedPcdGet32(PcdHwErrStorageSize)))\r
+ || (((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == 0) \r
+ && ((VarSize + mVariableModuleGlobal->CommonVariableTotalSize) > NonVolatileVarableStoreSize - sizeof (VARIABLE_STORE_HEADER) - FixedPcdGet32(PcdHwErrStorageSize)))) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+\r
+ NextVariable = (VARIABLE_HEADER *) (UINT8 *) (mVariableModuleGlobal->NonVolatileLastVariableOffset\r
+ + (UINTN) Global->NonVolatileVariableBase);\r
+ mVariableModuleGlobal->NonVolatileLastVariableOffset += VarSize;\r
+\r
+ if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != 0) {\r
+ mVariableModuleGlobal->HwErrVariableTotalSize += VarSize;\r
+ } else {\r
+ mVariableModuleGlobal->CommonVariableTotalSize += VarSize;\r
+ }\r
+ } else {\r
+ if ((UINT32) (VarSize + mVariableModuleGlobal->VolatileLastVariableOffset) >\r
+ ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->VolatileVariableBase)))->Size\r
+ ) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+\r
+ NextVariable = (VARIABLE_HEADER *) (UINT8 *) (mVariableModuleGlobal->VolatileLastVariableOffset\r
+ + (UINTN) Global->VolatileVariableBase);\r
+ mVariableModuleGlobal->VolatileLastVariableOffset += VarSize;\r
+ }\r
+\r
+ NextVariable->StartId = VARIABLE_DATA;\r
+ NextVariable->Attributes = Attributes;\r
+ NextVariable->State = VAR_ADDED;\r
+ NextVariable->Reserved = 0;\r
+\r
+ //\r
+ // There will be pad bytes after Data, the NextVariable->NameSize and\r
+ // NextVariable->NameSize should not include pad size so that variable\r
+ // service can get actual size in GetVariable\r
+ //\r
+ NextVariable->NameSize = (UINT32)VarNameSize;\r
+ NextVariable->DataSize = (UINT32)DataSize;\r
+\r
+ CopyMem (&NextVariable->VendorGuid, VendorGuid, sizeof (EFI_GUID));\r
+ CopyMem (\r
+ (UINT8 *) ((UINTN) NextVariable + VarNameOffset),\r
+ VariableName,\r
+ VarNameSize\r
+ );\r
+ CopyMem (\r
+ (UINT8 *) ((UINTN) NextVariable + VarDataOffset),\r
+ Data,\r
+ DataSize\r
+ );\r
+\r
+ //\r
+ // Mark the old variable as deleted\r
+ //\r
+ Variable->CurrPtr->State &= VAR_DELETED;\r
+\r
+ UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, TRUE, FALSE, FALSE);\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+Done:\r
+ return Status;\r
+}\r
+\r
/**\r
Finds variable in storage blocks of volatile and non-volatile storage areas.\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
PtrTrack->StartPtr = (VARIABLE_HEADER *) (VariableStoreHeader[Index] + 1);\r
PtrTrack->EndPtr = GetEndPointer (VariableStoreHeader[Index]);\r
\r
- while ((Variable[Index] != NULL) && (Variable[Index] <= GetEndPointer (VariableStoreHeader[Index]))) {\r
+ while ((Variable[Index] < GetEndPointer (VariableStoreHeader[Index])) && (Variable[Index] != NULL)) {\r
if (Variable[Index]->StartId == VARIABLE_DATA && Variable[Index]->State == VAR_ADDED) {\r
- if (!(EfiAtRuntime () && !(Variable[Index]->Attributes & EFI_VARIABLE_RUNTIME_ACCESS))) {\r
+ if (!(EfiAtRuntime () && ((Variable[Index]->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0))) {\r
if (VariableName[0] == 0) {\r
PtrTrack->CurrPtr = Variable[Index];\r
PtrTrack->Volatile = (BOOLEAN) Index;\r
return EFI_SUCCESS;\r
} else {\r
if (CompareGuid (VendorGuid, &Variable[Index]->VendorGuid)) {\r
- if (!CompareMem (VariableName, GET_VARIABLE_NAME_PTR (Variable[Index]), Variable[Index]->NameSize)) {\r
+ if (CompareMem (VariableName, GET_VARIABLE_NAME_PTR (Variable[Index]), Variable[Index]->NameSize) == 0) {\r
PtrTrack->CurrPtr = Variable[Index];\r
PtrTrack->Volatile = (BOOLEAN) Index;\r
return EFI_SUCCESS;\r
@param Data On input, the size in bytes of the return Data buffer. \r
On output, the size of data returned in Data.\r
@param Global Pointer to VARIABLE_GLOBAL structure\r
- @param Instance Instance of the Firmware Volume.\r
\r
@retval EFI_SUCCESS The function completed successfully. \r
@retval EFI_NOT_FOUND The variable was not found.\r
**/\r
EFI_STATUS\r
EFIAPI\r
-GetVariable (\r
+EmuGetVariable (\r
IN CHAR16 *VariableName,\r
- IN EFI_GUID * VendorGuid,\r
+ IN EFI_GUID *VendorGuid,\r
OUT UINT32 *Attributes OPTIONAL,\r
IN OUT UINTN *DataSize,\r
OUT VOID *Data,\r
- IN VARIABLE_GLOBAL * Global,\r
- IN UINT32 Instance\r
+ IN VARIABLE_GLOBAL *Global\r
)\r
{\r
VARIABLE_POINTER_TRACK Variable;\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
}\r
\r
*DataSize = VarDataSize;\r
+ UpdateVariableInfo (VariableName, VendorGuid, Variable.Volatile, TRUE, FALSE, FALSE, FALSE);\r
Status = EFI_SUCCESS;\r
goto Done;\r
} else {\r
@param VendorGuid On input, supplies the last VendorGuid that was returned by GetNextVariableName().\r
On output, returns the VendorGuid of the current variable. \r
@param Global Pointer to VARIABLE_GLOBAL structure.\r
- @param Instance Instance of the Firmware Volume.\r
\r
@retval EFI_SUCCESS The function completed successfully. \r
@retval EFI_NOT_FOUND The next variable was not found.\r
**/\r
EFI_STATUS\r
EFIAPI\r
-GetNextVariableName (\r
+EmuGetNextVariableName (\r
IN OUT UINTN *VariableNameSize,\r
IN OUT CHAR16 *VariableName,\r
IN OUT EFI_GUID *VendorGuid,\r
- IN VARIABLE_GLOBAL *Global,\r
- IN UINT32 Instance\r
+ IN VARIABLE_GLOBAL *Global\r
)\r
{\r
VARIABLE_POINTER_TRACK Variable;\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
// Variable is found\r
//\r
if (Variable.CurrPtr->StartId == VARIABLE_DATA && Variable.CurrPtr->State == VAR_ADDED) {\r
- if (!(EfiAtRuntime () && !(Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS))) {\r
+ if (!(EfiAtRuntime () && ((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0))) {\r
VarNameSize = Variable.CurrPtr->NameSize;\r
if (VarNameSize <= *VariableNameSize) {\r
CopyMem (\r
@param Global Pointer to VARIABLE_GLOBAL structure\r
@param VolatileOffset The offset of last volatile variable\r
@param NonVolatileOffset The offset of last non-volatile variable\r
- @param Instance Instance of the Firmware Volume.\r
\r
@retval EFI_SUCCESS The firmware has successfully stored the variable and its data as \r
defined by the Attributes.\r
**/\r
EFI_STATUS\r
EFIAPI\r
-SetVariable (\r
+EmuSetVariable (\r
IN CHAR16 *VariableName,\r
IN EFI_GUID *VendorGuid,\r
IN UINT32 Attributes,\r
IN VOID *Data,\r
IN VARIABLE_GLOBAL *Global,\r
IN UINTN *VolatileOffset,\r
- IN UINTN *NonVolatileOffset,\r
- IN UINT32 Instance\r
+ IN UINTN *NonVolatileOffset\r
)\r
{\r
VARIABLE_POINTER_TRACK Variable;\r
EFI_STATUS Status;\r
- VARIABLE_HEADER *NextVariable;\r
- UINTN VarNameSize;\r
- UINTN VarNameOffset;\r
- UINTN VarDataOffset;\r
- UINTN VarSize;\r
\r
//\r
// Check input parameters\r
if ((DataSize > FixedPcdGet32(PcdMaxHardwareErrorVariableSize)) || \r
(sizeof (VARIABLE_HEADER) + StrSize (VariableName) + DataSize > FixedPcdGet32(PcdMaxHardwareErrorVariableSize))) {\r
return EFI_INVALID_PARAMETER;\r
- } \r
+ }\r
+ //\r
+ // According to UEFI spec, HARDWARE_ERROR_RECORD variable name convention should be L"HwErrRecXXXX"\r
+ //\r
+ if (StrnCmp(VariableName, L"HwErrRec", StrLen(L"HwErrRec")) != 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
} else {\r
//\r
// The size of the VariableName, including the Unicode Null in bytes plus\r
(sizeof (VARIABLE_HEADER) + StrSize (VariableName) + DataSize > FixedPcdGet32(PcdMaxVariableSize))) {\r
return EFI_INVALID_PARAMETER;\r
} \r
- } \r
- //\r
- // Check whether the input variable is already existed\r
- //\r
- \r
- Status = FindVariable (VariableName, VendorGuid, &Variable, Global);\r
-\r
- if (Status == EFI_SUCCESS && Variable.CurrPtr != NULL) {\r
- //\r
- // Update/Delete existing variable\r
- //\r
-\r
- if (EfiAtRuntime ()) { \r
- //\r
- // If EfiAtRuntime and the variable is Volatile and Runtime Access, \r
- // the volatile is ReadOnly, and SetVariable should be aborted and \r
- // return EFI_WRITE_PROTECTED.\r
- //\r
- if (Variable.Volatile) {\r
- Status = EFI_WRITE_PROTECTED;\r
- goto Done;\r
- }\r
- //\r
- // Only variable have NV attribute can be updated/deleted in Runtime\r
- //\r
- if (!(Variable.CurrPtr->Attributes & EFI_VARIABLE_NON_VOLATILE)) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Done;\r
- }\r
- }\r
+ }\r
\r
- //\r
- // Setting a data variable with no access, or zero DataSize attributes\r
- // specified causes it to be deleted.\r
- //\r
- if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) {\r
- Variable.CurrPtr->State &= VAR_DELETED;\r
- Status = EFI_SUCCESS;\r
- goto Done;\r
- }\r
+ AcquireLockOnlyAtBootTime(&Global->VariableServicesLock);\r
\r
- //\r
- // If the variable is marked valid and the same data has been passed in\r
- // then return to the caller immediately.\r
- //\r
- if (Variable.CurrPtr->DataSize == DataSize &&\r
- !CompareMem (Data, GetVariableDataPtr (Variable.CurrPtr), DataSize)\r
- ) {\r
- Status = EFI_SUCCESS;\r
- goto Done;\r
- } else if (Variable.CurrPtr->State == VAR_ADDED) {\r
- //\r
- // Mark the old variable as in delete transition\r
- //\r
- Variable.CurrPtr->State &= VAR_IN_DELETED_TRANSITION;\r
- }\r
- \r
- } else if (Status == EFI_NOT_FOUND) {\r
- //\r
- // Create a new variable\r
- // \r
- \r
- //\r
- // Make sure we are trying to create a new variable.\r
- // Setting a data variable with no access, or zero DataSize attributes means to delete it. \r
- //\r
- if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) {\r
- Status = EFI_NOT_FOUND;\r
- goto Done;\r
- }\r
- \r
- //\r
- // Only variable have NV|RT attribute can be created in Runtime\r
- //\r
- if (EfiAtRuntime () &&\r
- (((Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) || ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0))) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Done;\r
- } \r
- } else {\r
- //\r
- // Status should be EFI_INVALID_PARAMETER here according to return status of FindVariable().\r
- //\r
- ASSERT (Status == EFI_INVALID_PARAMETER);\r
- goto Done;\r
- } \r
- \r
//\r
- // Function part - create a new variable and copy the data.\r
- // Both update a variable and create a variable will come here.\r
+ // Check whether the input variable is already existed\r
//\r
\r
- VarNameOffset = sizeof (VARIABLE_HEADER);\r
- VarNameSize = StrSize (VariableName);\r
- VarDataOffset = VarNameOffset + VarNameSize + GET_PAD_SIZE (VarNameSize);\r
- VarSize = VarDataOffset + DataSize + GET_PAD_SIZE (DataSize);\r
-\r
- if ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0) {\r
- if ((UINT32) (VarSize +*NonVolatileOffset) >\r
- ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->NonVolatileVariableBase)))->Size\r
- ) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Done;\r
- }\r
-\r
- NextVariable = (VARIABLE_HEADER *) (UINT8 *) (*NonVolatileOffset + (UINTN) Global->NonVolatileVariableBase);\r
- *NonVolatileOffset = *NonVolatileOffset + VarSize;\r
- } else {\r
- if ((UINT32) (VarSize +*VolatileOffset) >\r
- ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->VolatileVariableBase)))->Size\r
- ) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Done;\r
- }\r
-\r
- NextVariable = (VARIABLE_HEADER *) (UINT8 *) (*VolatileOffset + (UINTN) Global->VolatileVariableBase);\r
- *VolatileOffset = *VolatileOffset + VarSize;\r
- }\r
-\r
- NextVariable->StartId = VARIABLE_DATA;\r
- NextVariable->Attributes = Attributes;\r
- NextVariable->State = VAR_ADDED;\r
- NextVariable->Reserved = 0;\r
+ Status = FindVariable (VariableName, VendorGuid, &Variable, Global);\r
\r
//\r
- // There will be pad bytes after Data, the NextVariable->NameSize and\r
- // NextVariable->NameSize should not include pad size so that variable\r
- // service can get actual size in GetVariable\r
+ // Hook the operation of setting PlatformLangCodes/PlatformLang and LangCodes/Lang\r
//\r
- NextVariable->NameSize = (UINT32)VarNameSize;\r
- NextVariable->DataSize = (UINT32)DataSize;\r
+ AutoUpdateLangVariable (VariableName, Data, DataSize);\r
\r
- CopyMem (&NextVariable->VendorGuid, VendorGuid, sizeof (EFI_GUID));\r
- CopyMem (\r
- (UINT8 *) ((UINTN) NextVariable + VarNameOffset),\r
- VariableName,\r
- VarNameSize\r
- );\r
- CopyMem (\r
- (UINT8 *) ((UINTN) NextVariable + VarDataOffset),\r
- Data,\r
- DataSize\r
- );\r
+ Status = UpdateVariable (VariableName, VendorGuid, Data, DataSize, Attributes, &Variable);\r
\r
- //\r
- // Mark the old variable as deleted\r
- //\r
- if (!EFI_ERROR (Status)) {\r
- Variable.CurrPtr->State &= VAR_DELETED;\r
- }\r
- \r
- Status = EFI_SUCCESS;\r
-Done:\r
ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);\r
return Status;\r
}\r
@param MaximumVariableSize Returns the maximum size of an individual EFI variable \r
associated with the attributes specified.\r
@param Global Pointer to VARIABLE_GLOBAL structure.\r
- @param Instance Instance of the Firmware Volume.\r
\r
@retval EFI_SUCCESS Valid answer returned.\r
@retval EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied\r
**/\r
EFI_STATUS\r
EFIAPI\r
-QueryVariableInfo (\r
+EmuQueryVariableInfo (\r
IN UINT32 Attributes,\r
OUT UINT64 *MaximumVariableStorageSize,\r
OUT UINT64 *RemainingVariableStorageSize,\r
OUT UINT64 *MaximumVariableSize,\r
- IN VARIABLE_GLOBAL *Global,\r
- IN UINT32 Instance\r
+ IN VARIABLE_GLOBAL *Global\r
)\r
{\r
VARIABLE_HEADER *Variable;\r
VARIABLE_HEADER *NextVariable;\r
UINT64 VariableSize;\r
VARIABLE_STORE_HEADER *VariableStoreHeader;\r
+ UINT64 CommonVariableTotalSize;\r
+ UINT64 HwErrVariableTotalSize;\r
+\r
+ CommonVariableTotalSize = 0;\r
+ HwErrVariableTotalSize = 0;\r
\r
if(MaximumVariableStorageSize == NULL || RemainingVariableStorageSize == NULL || MaximumVariableSize == NULL || Attributes == 0) {\r
return EFI_INVALID_PARAMETER;\r
// Make sure RT Attribute is set if we are in Runtime phase.\r
//\r
return EFI_INVALID_PARAMETER;\r
+ } else if ((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {\r
+ //\r
+ // Make sure Hw Attribute is set with NV.\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
}\r
\r
AcquireLockOnlyAtBootTime(&Global->VariableServicesLock);\r
// with the storage size (excluding the storage header size)\r
//\r
*MaximumVariableStorageSize = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER);\r
- *RemainingVariableStorageSize = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER);\r
-\r
- //\r
- // Let *MaximumVariableSize be FixedPcdGet32(PcdMaxVariableSize) with the exception of the variable header size.\r
- //\r
- *MaximumVariableSize = FixedPcdGet32(PcdMaxVariableSize) - sizeof (VARIABLE_HEADER);\r
\r
//\r
// Harware error record variable needs larger size.\r
//\r
- if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {\r
+ if ((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {\r
+ *MaximumVariableStorageSize = FixedPcdGet32(PcdHwErrStorageSize);\r
*MaximumVariableSize = FixedPcdGet32(PcdMaxHardwareErrorVariableSize) - sizeof (VARIABLE_HEADER);\r
+ } else {\r
+ if ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0) {\r
+ ASSERT (FixedPcdGet32(PcdHwErrStorageSize) < VariableStoreHeader->Size);\r
+ *MaximumVariableStorageSize = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER) - FixedPcdGet32(PcdHwErrStorageSize);\r
+ }\r
+\r
+ //\r
+ // Let *MaximumVariableSize be FixedPcdGet32(PcdMaxVariableSize) with the exception of the variable header size.\r
+ //\r
+ *MaximumVariableSize = FixedPcdGet32(PcdMaxVariableSize) - sizeof (VARIABLE_HEADER);\r
}\r
\r
//\r
// Now walk through the related variable store.\r
//\r
while (Variable < GetEndPointer (VariableStoreHeader)) {\r
- if (Variable->StartId != VARIABLE_DATA) {\r
+ NextVariable = GetNextVariablePtr(Variable);\r
+ if (NextVariable == NULL) {\r
break;\r
}\r
-\r
- NextVariable = (VARIABLE_HEADER *) (GetVariableDataPtr (Variable) + Variable->DataSize + GET_PAD_SIZE (Variable->DataSize));\r
VariableSize = (UINT64) (UINTN) NextVariable - (UINT64) (UINTN) Variable;\r
\r
- if (Variable->State == VAR_ADDED) {\r
- *RemainingVariableStorageSize -= VariableSize;\r
+ if ((NextVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {\r
+ HwErrVariableTotalSize += VariableSize;\r
+ } else {\r
+ CommonVariableTotalSize += VariableSize;\r
}\r
\r
//\r
Variable = NextVariable;\r
}\r
\r
+ if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD){\r
+ *RemainingVariableStorageSize = *MaximumVariableStorageSize - HwErrVariableTotalSize;\r
+ } else {\r
+ *RemainingVariableStorageSize = *MaximumVariableStorageSize - CommonVariableTotalSize;\r
+ }\r
+\r
if (*RemainingVariableStorageSize < sizeof (VARIABLE_HEADER)) {\r
*MaximumVariableSize = 0;\r
} else if ((*RemainingVariableStorageSize - sizeof (VARIABLE_HEADER)) < *MaximumVariableSize) {\r
*VariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VariableStore;\r
*LastVariableOffset = sizeof (VARIABLE_STORE_HEADER);\r
\r
- VariableStore->Signature = VARIABLE_STORE_SIGNATURE;\r
+ CopyGuid (&VariableStore->Signature, &gEfiVariableGuid);\r
VariableStore->Size = FixedPcdGet32(PcdVariableStoreSize);\r
VariableStore->Format = VARIABLE_STORE_FORMATTED;\r
VariableStore->State = VARIABLE_STORE_HEALTHY;\r
//\r
// Allocate memory for mVariableModuleGlobal\r
//\r
- mVariableModuleGlobal = (ESAL_VARIABLE_GLOBAL *) AllocateRuntimePool (\r
+ mVariableModuleGlobal = (ESAL_VARIABLE_GLOBAL *) AllocateRuntimeZeroPool (\r
sizeof (ESAL_VARIABLE_GLOBAL)\r
);\r
if (NULL == mVariableModuleGlobal) {\r
);\r
\r
if (EFI_ERROR (Status)) {\r
+ FreePool(mVariableModuleGlobal);\r
return Status;\r
}\r
//\r