return FALSE;\r
}\r
\r
- Variable = GetStartPointer (mNvVariableCache);\r
+ Variable = GetStartPointer ((VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase);\r
\r
while (IsValidVariableHeader (Variable)) {\r
if ((Variable->State == VAR_ADDED || Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) && \r
return NULL;\r
}\r
\r
+/**\r
+ This function is to check if the remaining variable space is enough to set\r
+ all Variables from argument list successfully. The purpose of the check\r
+ is to keep the consistency of the Variables to be in variable storage.\r
+\r
+ Note: Variables are assumed to be in same storage.\r
+ The set sequence of Variables will be same with the sequence of VariableEntry from argument list,\r
+ so follow the argument sequence to check the Variables.\r
+\r
+ @param[in] Attributes Variable attributes for Variable entries.\r
+ @param ... The variable argument list with type VARIABLE_ENTRY_CONSISTENCY *.\r
+ A NULL terminates the list. The VariableSize of \r
+ VARIABLE_ENTRY_CONSISTENCY is the variable data size as input.\r
+ It will be changed to variable total size as output.\r
+\r
+ @retval TRUE Have enough variable space to set the Variables successfully.\r
+ @retval FALSE No enough variable space to set the Variables successfully.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+CheckRemainingSpaceForConsistency (\r
+ IN UINT32 Attributes,\r
+ ...\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ VA_LIST Args;\r
+ VARIABLE_ENTRY_CONSISTENCY *VariableEntry;\r
+ UINT64 MaximumVariableStorageSize;\r
+ UINT64 RemainingVariableStorageSize;\r
+ UINT64 MaximumVariableSize;\r
+ UINTN TotalNeededSize;\r
+ UINTN OriginalVarSize;\r
+ VARIABLE_STORE_HEADER *VariableStoreHeader;\r
+ VARIABLE_POINTER_TRACK VariablePtrTrack;\r
+ VARIABLE_HEADER *NextVariable;\r
+ UINTN VarNameSize;\r
+ UINTN VarDataSize;\r
+\r
+ //\r
+ // Non-Volatile related.\r
+ //\r
+ VariableStoreHeader = mNvVariableCache;\r
+\r
+ Status = VariableServiceQueryVariableInfoInternal (\r
+ Attributes,\r
+ &MaximumVariableStorageSize,\r
+ &RemainingVariableStorageSize,\r
+ &MaximumVariableSize\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ TotalNeededSize = 0;\r
+ VA_START (Args, Attributes);\r
+ VariableEntry = VA_ARG (Args, VARIABLE_ENTRY_CONSISTENCY *);\r
+ while (VariableEntry != NULL) {\r
+ //\r
+ // Calculate variable total size.\r
+ //\r
+ VarNameSize = StrSize (VariableEntry->Name);\r
+ VarNameSize += GET_PAD_SIZE (VarNameSize);\r
+ VarDataSize = VariableEntry->VariableSize;\r
+ VarDataSize += GET_PAD_SIZE (VarDataSize);\r
+ VariableEntry->VariableSize = HEADER_ALIGN (sizeof (VARIABLE_HEADER) + VarNameSize + VarDataSize);\r
+\r
+ TotalNeededSize += VariableEntry->VariableSize;\r
+ VariableEntry = VA_ARG (Args, VARIABLE_ENTRY_CONSISTENCY *);\r
+ }\r
+ VA_END (Args);\r
+\r
+ if (RemainingVariableStorageSize >= TotalNeededSize) {\r
+ //\r
+ // Already have enough space.\r
+ //\r
+ return TRUE;\r
+ } else if (AtRuntime ()) {\r
+ //\r
+ // At runtime, no reclaim.\r
+ // The original variable space of Variables can't be reused.\r
+ //\r
+ return FALSE;\r
+ }\r
+\r
+ VA_START (Args, Attributes);\r
+ VariableEntry = VA_ARG (Args, VARIABLE_ENTRY_CONSISTENCY *);\r
+ while (VariableEntry != NULL) {\r
+ //\r
+ // Check if Variable[Index] has been present and get its size.\r
+ //\r
+ OriginalVarSize = 0;\r
+ VariablePtrTrack.StartPtr = GetStartPointer (VariableStoreHeader);\r
+ VariablePtrTrack.EndPtr = GetEndPointer (VariableStoreHeader);\r
+ Status = FindVariableEx (\r
+ VariableEntry->Name,\r
+ VariableEntry->Guid,\r
+ FALSE,\r
+ &VariablePtrTrack\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Get size of Variable[Index].\r
+ //\r
+ NextVariable = GetNextVariablePtr (VariablePtrTrack.CurrPtr);\r
+ OriginalVarSize = (UINTN) NextVariable - (UINTN) VariablePtrTrack.CurrPtr;\r
+ //\r
+ // Add the original size of Variable[Index] to remaining variable storage size.\r
+ //\r
+ RemainingVariableStorageSize += OriginalVarSize;\r
+ }\r
+ if (VariableEntry->VariableSize > RemainingVariableStorageSize) {\r
+ //\r
+ // No enough space for Variable[Index].\r
+ //\r
+ VA_END (Args);\r
+ return FALSE;\r
+ }\r
+ //\r
+ // Sub the (new) size of Variable[Index] from remaining variable storage size.\r
+ //\r
+ RemainingVariableStorageSize -= VariableEntry->VariableSize;\r
+ VariableEntry = VA_ARG (Args, VARIABLE_ENTRY_CONSISTENCY *);\r
+ }\r
+ VA_END (Args);\r
+\r
+ return TRUE;\r
+}\r
+\r
/**\r
Hook the operations in PlatformLangCodes, LangCodes, PlatformLang and Lang.\r
\r
UINT32 Attributes;\r
VARIABLE_POINTER_TRACK Variable;\r
BOOLEAN SetLanguageCodes;\r
+ VARIABLE_ENTRY_CONSISTENCY VariableEntry[2];\r
\r
//\r
// Don't do updates for delete operation\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
+ // Check the variable space for both Lang and PlatformLang variable.\r
//\r
- FindVariable (EFI_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);\r
+ VariableEntry[0].VariableSize = ISO_639_2_ENTRY_SIZE + 1;\r
+ VariableEntry[0].Guid = &gEfiGlobalVariableGuid;\r
+ VariableEntry[0].Name = EFI_LANG_VARIABLE_NAME;\r
+ \r
+ VariableEntry[1].VariableSize = AsciiStrSize (BestPlatformLang);\r
+ VariableEntry[1].Guid = &gEfiGlobalVariableGuid;\r
+ VariableEntry[1].Name = EFI_PLATFORM_LANG_VARIABLE_NAME;\r
+ if (!CheckRemainingSpaceForConsistency (VARIABLE_ATTRIBUTE_NV_BS_RT, &VariableEntry[0], &VariableEntry[1], NULL)) {\r
+ //\r
+ // No enough variable space to set both Lang and PlatformLang successfully.\r
+ //\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ } else {\r
+ //\r
+ // Successfully convert PlatformLang to Lang, and set the BestLang value into Lang variable simultaneously.\r
+ //\r
+ FindVariable (EFI_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);\r
\r
- Status = UpdateVariable (EFI_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, BestLang,\r
- ISO_639_2_ENTRY_SIZE + 1, Attributes, 0, 0, &Variable, NULL);\r
+ Status = UpdateVariable (EFI_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, BestLang,\r
+ ISO_639_2_ENTRY_SIZE + 1, Attributes, 0, 0, &Variable, NULL);\r
+ }\r
\r
DEBUG ((EFI_D_INFO, "Variable Driver Auto Update PlatformLang, PlatformLang:%a, Lang:%a Status: %r\n", BestPlatformLang, BestLang, Status));\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
+ // Check the variable space for both PlatformLang and Lang variable.\r
//\r
- FindVariable (EFI_PLATFORM_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);\r
+ VariableEntry[0].VariableSize = AsciiStrSize (BestPlatformLang);\r
+ VariableEntry[0].Guid = &gEfiGlobalVariableGuid;\r
+ VariableEntry[0].Name = EFI_PLATFORM_LANG_VARIABLE_NAME;\r
+\r
+ VariableEntry[1].VariableSize = ISO_639_2_ENTRY_SIZE + 1;\r
+ VariableEntry[1].Guid = &gEfiGlobalVariableGuid;\r
+ VariableEntry[1].Name = EFI_LANG_VARIABLE_NAME;\r
+ if (!CheckRemainingSpaceForConsistency (VARIABLE_ATTRIBUTE_NV_BS_RT, &VariableEntry[0], &VariableEntry[1], NULL)) {\r
+ //\r
+ // No enough variable space to set both PlatformLang and Lang successfully.\r
+ //\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ } else {\r
+ //\r
+ // Successfully convert Lang to PlatformLang, and set the BestPlatformLang value into PlatformLang variable simultaneously.\r
+ //\r
+ FindVariable (EFI_PLATFORM_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);\r
\r
- Status = UpdateVariable (EFI_PLATFORM_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, BestPlatformLang,\r
- AsciiStrSize (BestPlatformLang), Attributes, 0, 0, &Variable, NULL);\r
+ Status = UpdateVariable (EFI_PLATFORM_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, BestPlatformLang,\r
+ AsciiStrSize (BestPlatformLang), Attributes, 0, 0, &Variable, NULL);\r
+ }\r
\r
DEBUG ((EFI_D_INFO, "Variable Driver Auto Update Lang, Lang:%a, PlatformLang:%a Status: %r\n", BestLang, BestPlatformLang, Status));\r
}\r
}\r
}\r
\r
- return Status;\r
+ if (SetLanguageCodes) {\r
+ //\r
+ // Continue to set PlatformLangCodes or LangCodes.\r
+ //\r
+ return EFI_SUCCESS;\r
+ } else {\r
+ return Status;\r
+ }\r
}\r
\r
/**\r
goto Done;\r
}\r
}\r
- \r
- //\r
- // Hook the operation of setting PlatformLangCodes/PlatformLang and LangCodes/Lang.\r
- //\r
- Status = AutoUpdateLangVariable (VariableName, Data, DataSize);\r
- if (EFI_ERROR (Status)) {\r
+\r
+ if (!FeaturePcdGet (PcdUefiVariableDefaultLangDeprecate)) {\r
//\r
- // The auto update operation failed, directly return to avoid inconsistency between PlatformLang and Lang.\r
+ // Hook the operation of setting PlatformLangCodes/PlatformLang and LangCodes/Lang.\r
//\r
- goto Done;\r
+ Status = AutoUpdateLangVariable (VariableName, Data, DataSize);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // The auto update operation failed, directly return to avoid inconsistency between PlatformLang and Lang.\r
+ //\r
+ goto Done;\r
+ }\r
}\r
\r
//\r
@param MaximumVariableSize Pointer to the maximum size of an individual EFI variables\r
associated with the attributes specified.\r
\r
- @return EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied.\r
@return EFI_SUCCESS Query successfully.\r
- @return EFI_UNSUPPORTED The attribute is not supported on this platform.\r
\r
**/\r
EFI_STATUS\r
EFIAPI\r
-VariableServiceQueryVariableInfo (\r
+VariableServiceQueryVariableInfoInternal (\r
IN UINT32 Attributes,\r
OUT UINT64 *MaximumVariableStorageSize,\r
OUT UINT64 *RemainingVariableStorageSize,\r
VARIABLE_STORE_HEADER *VariableStoreHeader;\r
UINT64 CommonVariableTotalSize;\r
UINT64 HwErrVariableTotalSize;\r
+ EFI_STATUS Status;\r
+ VARIABLE_POINTER_TRACK VariablePtrTrack;\r
\r
CommonVariableTotalSize = 0;\r
HwErrVariableTotalSize = 0;\r
\r
- if(MaximumVariableStorageSize == NULL || RemainingVariableStorageSize == NULL || MaximumVariableSize == NULL || Attributes == 0) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == 0) {\r
- //\r
- // Make sure the Attributes combination is supported by the platform.\r
- //\r
- return EFI_UNSUPPORTED;\r
- } else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) {\r
- //\r
- // Make sure if runtime bit is set, boot service bit is set also.\r
- //\r
- return EFI_INVALID_PARAMETER;\r
- } else if (AtRuntime () && ((Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) {\r
- //\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(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
-\r
if((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {\r
//\r
// Query is Volatile related.\r
} else {\r
CommonVariableTotalSize += VariableSize;\r
}\r
+ } else if (Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {\r
+ //\r
+ // If it is a IN_DELETED_TRANSITION variable,\r
+ // and there is not also a same ADDED one at the same time,\r
+ // this IN_DELETED_TRANSITION variable is valid.\r
+ //\r
+ VariablePtrTrack.StartPtr = GetStartPointer (VariableStoreHeader);\r
+ VariablePtrTrack.EndPtr = GetEndPointer (VariableStoreHeader);\r
+ Status = FindVariableEx (\r
+ GetVariableNamePtr (Variable),\r
+ &Variable->VendorGuid,\r
+ FALSE,\r
+ &VariablePtrTrack\r
+ );\r
+ if (!EFI_ERROR (Status) && VariablePtrTrack.CurrPtr->State != VAR_ADDED) {\r
+ if ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {\r
+ HwErrVariableTotalSize += VariableSize;\r
+ } else {\r
+ CommonVariableTotalSize += VariableSize;\r
+ }\r
+ }\r
}\r
}\r
\r
*MaximumVariableSize = *RemainingVariableStorageSize - sizeof (VARIABLE_HEADER);\r
}\r
\r
- ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
return EFI_SUCCESS;\r
}\r
\r
+/**\r
+\r
+ This code returns information about the EFI variables.\r
+\r
+ Caution: This function may receive untrusted input.\r
+ This function may be invoked in SMM mode. This function will do basic validation, before parse the data.\r
+\r
+ @param Attributes Attributes bitmask to specify the type of variables\r
+ on which to return information.\r
+ @param MaximumVariableStorageSize Pointer to the maximum size of the storage space available\r
+ for the EFI variables associated with the attributes specified.\r
+ @param RemainingVariableStorageSize Pointer to the remaining size of the storage space available\r
+ for EFI variables associated with the attributes specified.\r
+ @param MaximumVariableSize Pointer to the maximum size of an individual EFI variables\r
+ associated with the attributes specified.\r
+\r
+ @return EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied.\r
+ @return EFI_SUCCESS Query successfully.\r
+ @return EFI_UNSUPPORTED The attribute is not supported on this platform.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VariableServiceQueryVariableInfo (\r
+ IN UINT32 Attributes,\r
+ OUT UINT64 *MaximumVariableStorageSize,\r
+ OUT UINT64 *RemainingVariableStorageSize,\r
+ OUT UINT64 *MaximumVariableSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ if(MaximumVariableStorageSize == NULL || RemainingVariableStorageSize == NULL || MaximumVariableSize == NULL || Attributes == 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == 0) {\r
+ //\r
+ // Make sure the Attributes combination is supported by the platform.\r
+ //\r
+ return EFI_UNSUPPORTED;\r
+ } else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) {\r
+ //\r
+ // Make sure if runtime bit is set, boot service bit is set also.\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
+ } else if (AtRuntime () && ((Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) {\r
+ //\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(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
+\r
+ Status = VariableServiceQueryVariableInfoInternal (\r
+ Attributes,\r
+ MaximumVariableStorageSize,\r
+ RemainingVariableStorageSize,\r
+ MaximumVariableSize\r
+ );\r
+\r
+ ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
+ return Status;\r
+}\r
\r
/**\r
This function reclaims variable storage if free size is below the threshold.\r