+/**\r
+ Flush the HOB variable to flash.\r
+\r
+ @param[in] VariableName Name of variable has been updated or deleted.\r
+ @param[in] VendorGuid Guid of variable has been updated or deleted.\r
+\r
+**/\r
+VOID\r
+FlushHobVariableToFlash (\r
+ IN CHAR16 *VariableName,\r
+ IN EFI_GUID *VendorGuid\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ VARIABLE_STORE_HEADER *VariableStoreHeader;\r
+ VARIABLE_HEADER *Variable;\r
+ VOID *VariableData;\r
+ BOOLEAN ErrorFlag;\r
+\r
+ ErrorFlag = FALSE;\r
+\r
+ //\r
+ // Flush the HOB variable to flash.\r
+ //\r
+ if (mVariableModuleGlobal->VariableGlobal.HobVariableBase != 0) {\r
+ VariableStoreHeader = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase;\r
+ //\r
+ // Set HobVariableBase to 0, it can avoid SetVariable to call back.\r
+ //\r
+ mVariableModuleGlobal->VariableGlobal.HobVariableBase = 0;\r
+ for ( Variable = GetStartPointer (VariableStoreHeader)\r
+ ; (Variable < GetEndPointer (VariableStoreHeader) && IsValidVariableHeader (Variable))\r
+ ; Variable = GetNextVariablePtr (Variable)\r
+ ) {\r
+ if (Variable->State != VAR_ADDED) {\r
+ //\r
+ // The HOB variable has been set to DELETED state in local.\r
+ //\r
+ continue;\r
+ }\r
+ ASSERT ((Variable->Attributes & EFI_VARIABLE_NON_VOLATILE) != 0);\r
+ if (VendorGuid == NULL || VariableName == NULL ||\r
+ !CompareGuid (VendorGuid, &Variable->VendorGuid) ||\r
+ StrCmp (VariableName, GetVariableNamePtr (Variable)) != 0) {\r
+ VariableData = GetVariableDataPtr (Variable);\r
+ Status = VariableServiceSetVariable (\r
+ GetVariableNamePtr (Variable),\r
+ &Variable->VendorGuid,\r
+ Variable->Attributes,\r
+ Variable->DataSize,\r
+ VariableData\r
+ );\r
+ DEBUG ((EFI_D_INFO, "Variable driver flush the HOB variable to flash: %g %s %r\n", &Variable->VendorGuid, GetVariableNamePtr (Variable), Status));\r
+ } else {\r
+ //\r
+ // The updated or deleted variable is matched with the HOB variable.\r
+ // Don't break here because we will try to set other HOB variables\r
+ // since this variable could be set successfully.\r
+ //\r
+ Status = EFI_SUCCESS;\r
+ }\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // If set variable successful, or the updated or deleted variable is matched with the HOB variable,\r
+ // set the HOB variable to DELETED state in local.\r
+ //\r
+ DEBUG ((EFI_D_INFO, "Variable driver set the HOB variable to DELETED state in local: %g %s\n", &Variable->VendorGuid, GetVariableNamePtr (Variable)));\r
+ Variable->State &= VAR_DELETED;\r
+ } else {\r
+ ErrorFlag = TRUE;\r
+ }\r
+ }\r
+ if (ErrorFlag) {\r
+ //\r
+ // We still have HOB variable(s) not flushed in flash.\r
+ //\r
+ mVariableModuleGlobal->VariableGlobal.HobVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VariableStoreHeader;\r
+ } else {\r
+ //\r
+ // All HOB variables have been flushed in flash.\r
+ //\r
+ DEBUG ((EFI_D_INFO, "Variable driver: all HOB variables have been flushed in flash.\n"));\r
+ if (!AtRuntime ()) {\r
+ FreePool ((VOID *) VariableStoreHeader);\r
+ }\r
+ }\r
+ }\r
+\r
+}\r