]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
Refine the save action for the browser.
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Setup.c
index 68bb0bbf6eccddd3acb9b56a813be762023a58dc..c11b325e4d024e7e6dcc1581d29299a06f925f92 100644 (file)
@@ -50,7 +50,9 @@ LIST_ENTRY      gBrowserContextList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserCon
 LIST_ENTRY      gBrowserFormSetList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserFormSetList);\r
 LIST_ENTRY      gBrowserHotKeyList  = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserHotKeyList);\r
 LIST_ENTRY      gBrowserStorageList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserStorageList);\r
+LIST_ENTRY      gBrowserSaveFailFormSetList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserSaveFailFormSetList);\r
 \r
+BOOLEAN               mSystemSubmit = FALSE;\r
 BOOLEAN               gResetRequired;\r
 BOOLEAN               gExitRequired;\r
 BROWSER_SETTING_SCOPE gBrowserSettingScope = FormSetLevel;\r
@@ -243,6 +245,45 @@ UiFreeMenuList (
   }\r
 }\r
 \r
+/**\r
+  Copy current Menu list to the new menu list.\r
+  \r
+  @param  NewMenuListHead        New create Menu list.\r
+  @param  CurrentMenuListHead    Current Menu list.\r
+\r
+**/\r
+VOID\r
+UiCopyMenuList (\r
+  OUT LIST_ENTRY   *NewMenuListHead,\r
+  IN  LIST_ENTRY   *CurrentMenuListHead\r
+  )\r
+{\r
+  LIST_ENTRY         *Link;\r
+  FORM_ENTRY_INFO    *MenuList;\r
+  FORM_ENTRY_INFO    *NewMenuEntry;\r
+\r
+  //\r
+  // If new menu list not empty, free it first.\r
+  //\r
+  UiFreeMenuList (NewMenuListHead);\r
+\r
+  Link = GetFirstNode (CurrentMenuListHead);\r
+  while (!IsNull (CurrentMenuListHead, Link)) {\r
+    MenuList = FORM_ENTRY_INFO_FROM_LINK (Link);\r
+    Link = GetNextNode (CurrentMenuListHead, Link);\r
+\r
+    NewMenuEntry = AllocateZeroPool (sizeof (FORM_ENTRY_INFO));\r
+    ASSERT (NewMenuEntry != NULL);\r
+    NewMenuEntry->Signature  = FORM_ENTRY_INFO_SIGNATURE;\r
+    NewMenuEntry->HiiHandle  = MenuList->HiiHandle;\r
+    CopyMem (&NewMenuEntry->FormSetGuid, &MenuList->FormSetGuid, sizeof (EFI_GUID));\r
+    NewMenuEntry->FormId     = MenuList->FormId;\r
+    NewMenuEntry->QuestionId = MenuList->QuestionId;\r
+\r
+    InsertTailList (NewMenuListHead, &NewMenuEntry->Link);\r
+  }\r
+}\r
+\r
 /**\r
   Load all hii formset to the browser.\r
 \r
@@ -315,18 +356,21 @@ LoadAllHiiFormset (
   Pop up the error info.\r
 \r
   @param      BrowserStatus    The input browser status.\r
+  @param      HiiHandle        The Hiihandle for this opcode.\r
   @param      OpCode           The opcode use to get the erro info and timeout value.\r
   @param      ErrorString      Error string used by BROWSER_NO_SUBMIT_IF.\r
 \r
 **/\r
-VOID\r
+UINT32\r
 PopupErrorMessage (\r
   IN UINT32                BrowserStatus,\r
+  IN EFI_HII_HANDLE        HiiHandle,\r
   IN EFI_IFR_OP_HEADER     *OpCode, OPTIONAL\r
   IN CHAR16                *ErrorString\r
   )\r
 {\r
   FORM_DISPLAY_ENGINE_STATEMENT *Statement;\r
+  USER_INPUT                    UserInputData;\r
 \r
   Statement = NULL;\r
 \r
@@ -343,8 +387,12 @@ PopupErrorMessage (
   //\r
   gDisplayFormData.ErrorString   = ErrorString;\r
   gDisplayFormData.BrowserStatus = BrowserStatus;\r
-  \r
-  mFormDisplay->FormDisplay (&gDisplayFormData, NULL);\r
+\r
+  if (HiiHandle != NULL) {\r
+    gDisplayFormData.HiiHandle     = HiiHandle;\r
+  }\r
+\r
+  mFormDisplay->FormDisplay (&gDisplayFormData, &UserInputData);\r
 \r
   gDisplayFormData.BrowserStatus = BROWSER_SUCCESS;\r
   gDisplayFormData.ErrorString   = NULL;\r
@@ -352,6 +400,8 @@ PopupErrorMessage (
   if (OpCode != NULL) {\r
     FreePool (Statement);\r
   }\r
+\r
+  return UserInputData.Action;\r
 }\r
 \r
 /**\r
@@ -2014,7 +2064,13 @@ ValidateQuestion (
         break;\r
       }\r
 \r
-      PopupErrorMessage(BrowserStatus, Expression->OpCode, ErrorStr);\r
+      if (!((Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) && mSystemSubmit)) {\r
+        //\r
+        // If in system submit process and for no_submit_if check, not popup this error message.\r
+        // Will process this fail again later in not system submit process.\r
+        //\r
+        PopupErrorMessage(BrowserStatus, FormSet->HiiHandle, Expression->OpCode, ErrorStr);\r
+      }\r
 \r
       if (ErrorStr != NULL) {\r
         FreePool (ErrorStr);\r
@@ -2083,6 +2139,7 @@ ValueChangedValidation (
 \r
   @param  FormSet                FormSet data structure.\r
   @param  CurrentForm            Current input form data structure.\r
+  @param  Statement              The statement for this check.\r
 \r
   @retval EFI_SUCCESS            Form validation pass.\r
   @retval other                  Form validation failed.\r
@@ -2090,8 +2147,9 @@ ValueChangedValidation (
 **/\r
 EFI_STATUS\r
 NoSubmitCheck (\r
-  IN  FORM_BROWSER_FORMSET            *FormSet,\r
-  IN  FORM_BROWSER_FORM               *CurrentForm\r
+  IN      FORM_BROWSER_FORMSET            *FormSet,\r
+  IN OUT  FORM_BROWSER_FORM               **CurrentForm,\r
+  OUT     FORM_BROWSER_STATEMENT          **Statement\r
   )\r
 {\r
   EFI_STATUS              Status;\r
@@ -2105,16 +2163,21 @@ NoSubmitCheck (
     Form = FORM_BROWSER_FORM_FROM_LINK (LinkForm);\r
     LinkForm = GetNextNode (&FormSet->FormListHead, LinkForm);\r
 \r
-    if (CurrentForm != NULL && CurrentForm != Form) {\r
+    if (*CurrentForm != NULL && *CurrentForm != Form) {\r
       continue;\r
     }\r
 \r
     Link = GetFirstNode (&Form->StatementListHead);\r
     while (!IsNull (&Form->StatementListHead, Link)) {\r
       Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
-\r
       Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_NO_SUBMIT_IF);\r
       if (EFI_ERROR (Status)) {\r
+        if (*CurrentForm == NULL) {\r
+          *CurrentForm = Form;\r
+        }\r
+        if (Statement != NULL) {\r
+          *Statement = Question;\r
+        }\r
         return Status;\r
       }\r
 \r
@@ -2128,7 +2191,6 @@ NoSubmitCheck (
 /**\r
   Fill storage's edit copy with settings requested from Configuration Driver.\r
 \r
-  @param  FormSet                FormSet data structure.\r
   @param  Storage                The storage which need to sync.\r
   @param  ConfigRequest          The config request string which used to sync storage.\r
   @param  SyncOrRestore          Sync the buffer to editbuffer or Restore  the \r
@@ -2141,7 +2203,6 @@ NoSubmitCheck (
 **/\r
 EFI_STATUS\r
 SynchronizeStorage (\r
-  IN  FORM_BROWSER_FORMSET        *FormSet,\r
   OUT BROWSER_STORAGE             *Storage,\r
   IN  CHAR16                      *ConfigRequest,\r
   IN  BOOLEAN                     SyncOrRestore\r
@@ -2336,33 +2397,43 @@ ValidateFormSet (
   Also clean all ValueChanged flag in question.\r
 \r
   @param  SetFlag                Whether need to set the Reset Flag.\r
+  @param  FormSet                FormSet data structure.\r
   @param  Form                   Form data structure.\r
 \r
 **/\r
 VOID\r
 UpdateFlagForForm (\r
   IN BOOLEAN                          SetFlag,\r
+  IN FORM_BROWSER_FORMSET             *FormSet,\r
   IN FORM_BROWSER_FORM                *Form\r
   )\r
 {\r
   LIST_ENTRY              *Link;\r
   FORM_BROWSER_STATEMENT  *Question;\r
-  BOOLEAN                 FindOne;\r
+  BOOLEAN                 OldValue;\r
 \r
-  FindOne = FALSE;\r
   Link = GetFirstNode (&Form->StatementListHead);\r
   while (!IsNull (&Form->StatementListHead, Link)) {\r
     Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
-  \r
-    if (SetFlag && Question->ValueChanged && ((Question->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) != 0)) {\r
-      gResetRequired = TRUE;\r
-    } \r
+    Link = GetNextNode (&Form->StatementListHead, Link);\r
 \r
-    if (Question->ValueChanged) {\r
-      Question->ValueChanged = FALSE;\r
+    if (!Question->ValueChanged) {\r
+      continue;\r
     }\r
-  \r
-    Link = GetNextNode (&Form->StatementListHead, Link);\r
+\r
+    OldValue = Question->ValueChanged;\r
+\r
+    //\r
+    // Compare the buffer and editbuffer data to see whether the data has been saved.\r
+    //\r
+    Question->ValueChanged = IsQuestionValueChanged(FormSet, Form, Question, GetSetValueWithBothBuffer);\r
+\r
+    //\r
+    // Only the changed data has been saved, then need to set the reset flag.\r
+    //\r
+    if (SetFlag && OldValue && !Question->ValueChanged && ((Question->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) != 0)) {\r
+      gResetRequired = TRUE;\r
+    } \r
   }\r
 }\r
 \r
@@ -2387,11 +2458,8 @@ ValueChangeResetFlagUpdate (
   FORM_BROWSER_FORM       *CurrentForm;\r
   LIST_ENTRY              *Link;\r
 \r
-  //\r
-  // Form != NULL means only check form level.\r
-  //\r
   if (Form != NULL) {\r
-    UpdateFlagForForm(SetFlag, Form);\r
+    UpdateFlagForForm(SetFlag, FormSet, Form);\r
     return;\r
   }\r
 \r
@@ -2400,8 +2468,233 @@ ValueChangeResetFlagUpdate (
     CurrentForm = FORM_BROWSER_FORM_FROM_LINK (Link);\r
     Link = GetNextNode (&FormSet->FormListHead, Link);\r
 \r
-    UpdateFlagForForm(SetFlag, CurrentForm);\r
+    UpdateFlagForForm(SetFlag, FormSet, CurrentForm);\r
+  }\r
+}\r
+\r
+/**\r
+  Base on the return Progress string to find the form. \r
+  \r
+  Base on the first return Offset/Width (Name) string to find the form\r
+  which keep this string.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Storage                Storage which has this Progress string.\r
+  @param  Progress               The Progress string which has the first fail string.\r
+  @param  RetForm                The return form for this progress string.\r
+  @param  RetQuestion            The return question for the error progress string.\r
+\r
+  @retval TRUE                   Find the error form and statement for this error progress string.\r
+  @retval FALSE                  Not find the error form.\r
+\r
+**/\r
+BOOLEAN\r
+FindQuestionFromProgress (\r
+  IN FORM_BROWSER_FORMSET             *FormSet,\r
+  IN BROWSER_STORAGE                  *Storage,\r
+  IN EFI_STRING                       Progress,\r
+  OUT FORM_BROWSER_FORM               **RetForm,\r
+  OUT FORM_BROWSER_STATEMENT          **RetQuestion\r
+  )\r
+{\r
+  LIST_ENTRY                   *Link;\r
+  LIST_ENTRY                   *LinkStorage;\r
+  LIST_ENTRY                   *LinkStatement;\r
+  FORM_BROWSER_CONFIG_REQUEST  *ConfigInfo;\r
+  FORM_BROWSER_FORM            *Form;\r
+  EFI_STRING                   EndStr;\r
+  FORM_BROWSER_STATEMENT       *Statement;\r
+\r
+  ASSERT ((*Progress == '&') || (*Progress == 'G'));\r
+\r
+  ConfigInfo   = NULL;\r
+  *RetForm     = NULL;\r
+  *RetQuestion = NULL;\r
+\r
+  //\r
+  // Skip the first "&" or the ConfigHdr part.\r
+  //\r
+  if (*Progress == '&') {\r
+    Progress++;\r
+  } else {\r
+    //\r
+    // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.\r
+    //\r
+    if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+      //\r
+      // For Name/Value type, Skip the ConfigHdr part.\r
+      //\r
+      EndStr = StrStr (Progress, L"PATH=");\r
+      while (*EndStr != '&') {\r
+        EndStr++;\r
+      }\r
+\r
+      *EndStr = '\0';\r
+    } else {\r
+      //\r
+      // For Buffer type, Skip the ConfigHdr part.\r
+      //\r
+      EndStr = StrStr (Progress, L"&OFFSET=");\r
+      *EndStr = '\0';\r
+    }\r
+\r
+    Progress = EndStr + 1;\r
+  }\r
+\r
+  //\r
+  // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.\r
+  //\r
+  if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+    //\r
+    // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,\r
+    // here, just keep the "Fred" string.\r
+    //\r
+    EndStr = StrStr (Progress, L"=");\r
+    *EndStr = '\0';\r
+  } else {\r
+    //\r
+    // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",\r
+    // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.\r
+    //\r
+    EndStr = StrStr (Progress, L"&VALUE=");\r
+    *EndStr = '\0';\r
+  }\r
+\r
+  //\r
+  // Search in the form list.\r
+  //\r
+  Link = GetFirstNode (&FormSet->FormListHead);\r
+  while (!IsNull (&FormSet->FormListHead, Link)) {\r
+    Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+    Link = GetNextNode (&FormSet->FormListHead, Link);\r
+\r
+    //\r
+    // Search in the ConfigReqeust list in this form.\r
+    //\r
+    LinkStorage = GetFirstNode (&Form->ConfigRequestHead);\r
+    while (!IsNull (&Form->ConfigRequestHead, LinkStorage)) {\r
+      ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (LinkStorage);\r
+      LinkStorage = GetNextNode (&Form->ConfigRequestHead, LinkStorage);\r
+\r
+      if (Storage != ConfigInfo->Storage) {\r
+        continue;\r
+      }\r
+\r
+      if (StrStr (ConfigInfo->ConfigRequest, Progress) != NULL) {\r
+        //\r
+        // Find the OffsetWidth string in this form.\r
+        //\r
+        *RetForm = Form;\r
+        break;\r
+      }\r
+    }\r
+\r
+    if (*RetForm != NULL) {\r
+      LinkStatement = GetFirstNode (&Form->StatementListHead);\r
+      while (!IsNull (&Form->StatementListHead, LinkStatement)) {\r
+        Statement = FORM_BROWSER_STATEMENT_FROM_LINK (LinkStatement);\r
+        LinkStatement = GetNextNode (&Form->StatementListHead, LinkStatement);\r
+\r
+        if (Statement->BlockName != NULL && StrStr (Statement->BlockName, Progress) != NULL) {\r
+          *RetQuestion = Statement;\r
+          break;\r
+        }\r
+      }\r
+    }\r
+\r
+    if (*RetForm != NULL) {\r
+      break;\r
+    }\r
   }\r
+\r
+  //\r
+  // restore the OffsetWidth string to the original format.\r
+  //\r
+  if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+    *EndStr = '=';\r
+  } else {\r
+    *EndStr = '&';\r
+  }\r
+\r
+  return *RetForm != NULL;\r
+}\r
+\r
+/**\r
+  Popup an save error info and get user input.\r
+\r
+  @param  TitleId                The form title id.\r
+  @param  HiiHandle              The hii handle for this package.\r
+\r
+  @retval UINT32                 The user select option for the save fail.\r
+                                 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET\r
+**/\r
+UINT32\r
+ConfirmSaveFail (\r
+  IN EFI_STRING_ID    TitleId,\r
+  IN EFI_HII_HANDLE   HiiHandle\r
+  )\r
+{\r
+  CHAR16                  *FormTitle;\r
+  CHAR16                  *StringBuffer;\r
+  UINT32                  RetVal;\r
+\r
+  FormTitle = GetToken (TitleId, HiiHandle);\r
+\r
+  StringBuffer = AllocateZeroPool (256 * sizeof (CHAR16));\r
+  ASSERT (StringBuffer != NULL);\r
+\r
+  UnicodeSPrint (\r
+    StringBuffer, \r
+    24 * sizeof (CHAR16) + StrSize (FormTitle), \r
+    L"Submit Fail For Form: %s.", \r
+    FormTitle\r
+    );\r
+\r
+  RetVal = PopupErrorMessage(BROWSER_SUBMIT_FAIL, NULL, NULL, StringBuffer);\r
+\r
+  FreePool (StringBuffer);\r
+  FreePool (FormTitle);\r
+\r
+  return RetVal;\r
+}\r
+\r
+/**\r
+  Popup an NO_SUBMIT_IF error info and get user input.\r
+\r
+  @param  TitleId                The form title id.\r
+  @param  HiiHandle              The hii handle for this package.\r
+\r
+  @retval UINT32                 The user select option for the save fail.\r
+                                 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET\r
+**/\r
+UINT32\r
+ConfirmNoSubmitFail (\r
+  IN EFI_STRING_ID    TitleId,\r
+  IN EFI_HII_HANDLE   HiiHandle\r
+  )\r
+{\r
+  CHAR16                  *FormTitle;\r
+  CHAR16                  *StringBuffer;\r
+  UINT32                  RetVal;\r
+\r
+  FormTitle = GetToken (TitleId, HiiHandle);\r
+\r
+  StringBuffer = AllocateZeroPool (256 * sizeof (CHAR16));\r
+  ASSERT (StringBuffer != NULL);\r
+\r
+  UnicodeSPrint (\r
+    StringBuffer, \r
+    24 * sizeof (CHAR16) + StrSize (FormTitle), \r
+    L"NO_SUBMIT_IF error For Form: %s.", \r
+    FormTitle\r
+    );\r
+\r
+  RetVal = PopupErrorMessage(BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF, NULL, NULL, StringBuffer);\r
+\r
+  FreePool (StringBuffer);\r
+  FreePool (FormTitle);\r
+\r
+  return RetVal;\r
 }\r
 \r
 /**\r
@@ -2456,7 +2749,7 @@ DiscardForm (
       //\r
       // Prepare <ConfigResp>\r
       //\r
-      SynchronizeStorage(FormSet, ConfigInfo->Storage, ConfigInfo->ConfigRequest, FALSE);\r
+      SynchronizeStorage(ConfigInfo->Storage, ConfigInfo->ConfigRequest, FALSE);\r
 \r
       //\r
       // Call callback with Changed type to inform the driver.\r
@@ -2464,7 +2757,7 @@ DiscardForm (
       SendDiscardInfoToDriver (FormSet, Form);\r
     }\r
 \r
-    ValueChangeResetFlagUpdate (FALSE, NULL, Form);\r
+    ValueChangeResetFlagUpdate (FALSE, FormSet, Form);\r
   } else if (SettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet (FormSet)) {\r
 \r
     //\r
@@ -2486,7 +2779,7 @@ DiscardForm (
         continue;\r
       }\r
 \r
-      SynchronizeStorage(FormSet, Storage->BrowserStorage, Storage->ConfigRequest, FALSE);\r
+      SynchronizeStorage(Storage->BrowserStorage, Storage->ConfigRequest, FALSE);\r
     }\r
 \r
     Link = GetFirstNode (&FormSet->FormListHead);\r
@@ -2538,21 +2831,19 @@ DiscardForm (
 }\r
 \r
 /**\r
-  Submit data based on the input Setting level (Form, FormSet or System).\r
+  Submit data for a form.\r
 \r
   @param  FormSet                FormSet data structure.\r
   @param  Form                   Form data structure.\r
-  @param  SettingScope           Setting Scope for Submit action.\r
 \r
   @retval EFI_SUCCESS            The function completed successfully.\r
   @retval EFI_UNSUPPORTED        Unsupport SettingScope.\r
 \r
 **/\r
 EFI_STATUS\r
-SubmitForm (\r
+SubmitForForm (\r
   IN FORM_BROWSER_FORMSET             *FormSet,\r
-  IN FORM_BROWSER_FORM                *Form,\r
-  IN BROWSER_SETTING_SCOPE            SettingScope\r
+  IN FORM_BROWSER_FORM                *Form\r
   )\r
 {\r
   EFI_STATUS              Status;\r
@@ -2560,162 +2851,453 @@ SubmitForm (
   EFI_STRING              ConfigResp;\r
   EFI_STRING              Progress;\r
   BROWSER_STORAGE         *Storage;\r
-  FORMSET_STORAGE         *FormSetStorage;\r
-  FORM_BROWSER_FORMSET    *LocalFormSet;\r
   FORM_BROWSER_CONFIG_REQUEST  *ConfigInfo;\r
 \r
+  if (!IsNvUpdateRequiredForForm (Form)) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  Status = NoSubmitCheck (FormSet, &Form, NULL);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Link = GetFirstNode (&Form->ConfigRequestHead);\r
+  while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
+    ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
+    Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
+\r
+    Storage = ConfigInfo->Storage;\r
+    if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Skip if there is no RequestElement\r
+    //\r
+    if (ConfigInfo->ElementCount == 0) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // 1. Prepare <ConfigResp>\r
+    //\r
+    Status = StorageToConfigResp (ConfigInfo->Storage, &ConfigResp, ConfigInfo->ConfigRequest, TRUE);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // 2. Set value to hii config routine protocol.\r
+    //\r
+    Status = mHiiConfigRouting->RouteConfig (\r
+                                      mHiiConfigRouting,\r
+                                      ConfigResp,\r
+                                      &Progress\r
+                                      );\r
+    FreePool (ConfigResp);\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      InsertTailList (&gBrowserSaveFailFormSetList, &ConfigInfo->SaveFailLink);\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // 3. Config success, update storage shadow Buffer, only update the data belong to this form.\r
+    //\r
+    SynchronizeStorage (ConfigInfo->Storage, ConfigInfo->ConfigRequest, TRUE);\r
+  }\r
+\r
   //\r
-  // Check the supported setting level.\r
+  // 4. Process the save failed storage.\r
   //\r
-  if (SettingScope >= MaxLevel) {\r
-    return EFI_UNSUPPORTED;\r
+  if (!IsListEmpty (&gBrowserSaveFailFormSetList)) {\r
+    if (ConfirmSaveFail (Form->FormTitle, FormSet->HiiHandle) == BROWSER_ACTION_DISCARD) {\r
+      Link = GetFirstNode (&gBrowserSaveFailFormSetList);\r
+      while (!IsNull (&gBrowserSaveFailFormSetList, Link)) {\r
+        ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link);\r
+        Link = GetNextNode (&gBrowserSaveFailFormSetList, Link);\r
+\r
+        SynchronizeStorage(ConfigInfo->Storage, ConfigInfo->ConfigRequest, FALSE);\r
+\r
+        Status = EFI_SUCCESS;\r
+      }\r
+    } else {\r
+      Status = EFI_UNSUPPORTED;\r
+    }\r
+\r
+    //\r
+    // Free Form save fail list.\r
+    //\r
+    while (!IsListEmpty (&gBrowserSaveFailFormSetList)) {\r
+      Link = GetFirstNode (&gBrowserSaveFailFormSetList);\r
+      ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link);\r
+      RemoveEntryList (&ConfigInfo->SaveFailLink);\r
+    }\r
   }\r
 \r
   //\r
-  // Validate the Form by NoSubmit check\r
+  // 5. Update the NV flag.\r
   //\r
-  Status = EFI_SUCCESS;\r
-  if (SettingScope == FormLevel) {\r
-    Status = NoSubmitCheck (FormSet, Form);\r
-  } else if (SettingScope == FormSetLevel) {\r
-    Status = NoSubmitCheck (FormSet, NULL);\r
+  ValueChangeResetFlagUpdate(TRUE, FormSet, Form);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Submit data for a formset.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  SkipProcessFail        Whether skip to process the save failed storage.\r
+                                 If submit formset is called when do system level save, \r
+                                 set this value to true and process the failed formset \r
+                                 together. \r
+                                 if submit formset is called when do formset level save,\r
+                                 set the value to false and process the failed storage\r
+                                 right after process all storages for this formset.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+  @retval EFI_UNSUPPORTED        Unsupport SettingScope.\r
+\r
+**/\r
+EFI_STATUS\r
+SubmitForFormSet (\r
+  IN FORM_BROWSER_FORMSET             *FormSet,\r
+  IN BOOLEAN                          SkipProcessFail\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  LIST_ENTRY              *Link;\r
+  EFI_STRING              ConfigResp;\r
+  EFI_STRING              Progress;\r
+  BROWSER_STORAGE         *Storage;\r
+  FORMSET_STORAGE         *FormSetStorage;\r
+  FORM_BROWSER_FORM       *Form;\r
+  BOOLEAN                 HasInserted;\r
+  FORM_BROWSER_STATEMENT  *Question;\r
+\r
+  HasInserted = FALSE;\r
+\r
+  if (!IsNvUpdateRequiredForFormSet (FormSet)) {\r
+    return EFI_SUCCESS;\r
   }\r
+\r
+  Form = NULL; \r
+  Status = NoSubmitCheck (FormSet, &Form, &Question);\r
   if (EFI_ERROR (Status)) {\r
+    if (SkipProcessFail) {\r
+      //\r
+      // Process NO_SUBMIT check first, so insert it at head.\r
+      //\r
+      FormSet->SaveFailForm = Form;\r
+      FormSet->SaveFailStatement = Question;\r
+      InsertHeadList (&gBrowserSaveFailFormSetList, &FormSet->SaveFailLink);\r
+    }\r
+\r
     return Status;\r
   }\r
 \r
-  if (SettingScope == FormLevel && IsNvUpdateRequiredForForm (Form)) {\r
-    ConfigInfo = NULL;\r
-    Link = GetFirstNode (&Form->ConfigRequestHead);\r
-    while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
-      ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
-      Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
+  Form = NULL;\r
+  Question = NULL;\r
+  //\r
+  // Submit Buffer storage or Name/Value storage\r
+  //\r
+  Link = GetFirstNode (&FormSet->StorageListHead);\r
+  while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+    FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
+    Storage        = FormSetStorage->BrowserStorage;\r
+    Link = GetNextNode (&FormSet->StorageListHead, Link);\r
 \r
-      Storage = ConfigInfo->Storage;\r
-      if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
-        continue;\r
-      }\r
+    if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+      continue;\r
+    }\r
 \r
-      //\r
-      // Skip if there is no RequestElement\r
-      //\r
-      if (ConfigInfo->ElementCount == 0) {\r
-        continue;\r
-      }\r
+    //\r
+    // Skip if there is no RequestElement\r
+    //\r
+    if (FormSetStorage->ElementCount == 0) {\r
+      continue;\r
+    }\r
 \r
-      //\r
-      // 1. Prepare <ConfigResp>\r
-      //\r
-      Status = StorageToConfigResp (ConfigInfo->Storage, &ConfigResp, ConfigInfo->ConfigRequest, TRUE);\r
-      if (EFI_ERROR (Status)) {\r
-        return Status;\r
-      }\r
+    //\r
+    // 1. Prepare <ConfigResp>\r
+    //\r
+    Status = StorageToConfigResp (Storage, &ConfigResp, FormSetStorage->ConfigRequest, TRUE);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
 \r
-      //\r
-      // 2. Set value to hii config routine protocol.\r
-      //\r
-      Status = mHiiConfigRouting->RouteConfig (\r
-                                        mHiiConfigRouting,\r
-                                        ConfigResp,\r
-                                        &Progress\r
-                                        );\r
-      if (EFI_ERROR (Status)) {\r
-        FreePool (ConfigResp);\r
-        return Status;\r
+    //\r
+    // 2. Send <ConfigResp> to Routine config Protocol.\r
+    //\r
+    Status = mHiiConfigRouting->RouteConfig (\r
+                                      mHiiConfigRouting,\r
+                                      ConfigResp,\r
+                                      &Progress\r
+                                      );\r
+    if (EFI_ERROR (Status)) {\r
+      InsertTailList (&FormSet->SaveFailStorageListHead, &FormSetStorage->SaveFailLink);\r
+      if (!HasInserted) {\r
+        //\r
+        // Call submit formset for system level, save the formset info\r
+        // and process later.\r
+        //\r
+        FindQuestionFromProgress(FormSet, Storage, Progress, &Form, &Question);\r
+        ASSERT (Form != NULL && Question != NULL);\r
+        FormSet->SaveFailForm = Form;\r
+        FormSet->SaveFailStatement = Question;\r
+        if (SkipProcessFail) {\r
+          InsertTailList (&gBrowserSaveFailFormSetList, &FormSet->SaveFailLink);\r
+        }\r
+        HasInserted = TRUE;\r
       }\r
 \r
       FreePool (ConfigResp);\r
-      //\r
-      // 3. Config success, update storage shadow Buffer, only update the data belong to this form.\r
-      //\r
-      SynchronizeStorage (FormSet, ConfigInfo->Storage, ConfigInfo->ConfigRequest, TRUE);\r
+      continue;\r
     }\r
 \r
+    FreePool (ConfigResp);\r
     //\r
-    // 4. Update the NV flag.\r
-    // \r
-    ValueChangeResetFlagUpdate(TRUE, NULL, Form);\r
-  } else if (SettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet (FormSet)) {\r
-    //\r
-    // Submit Buffer storage or Name/Value storage\r
+    // 3. Config success, update storage shadow Buffer\r
     //\r
-    Link = GetFirstNode (&FormSet->StorageListHead);\r
-    while (!IsNull (&FormSet->StorageListHead, Link)) {\r
-      FormSetStorage = (FORMSET_STORAGE_FROM_LINK (Link));\r
-      Storage        = FormSetStorage->BrowserStorage;\r
-      Link = GetNextNode (&FormSet->StorageListHead, Link);\r
-\r
-      if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
-        continue;\r
-      }\r
+    SynchronizeStorage (Storage, FormSetStorage->ConfigRequest, TRUE);\r
+  }\r
 \r
+  //\r
+  // 4. Has save fail storage need to handle.\r
+  //\r
+  if (Form != NULL) {\r
+    if (!SkipProcessFail) {\r
       //\r
-      // Skip if there is no RequestElement\r
+      // If not in system level, just handl the save failed storage here.\r
       //\r
-      if (FormSetStorage->ElementCount == 0) {\r
-        continue;\r
-      }\r
+      if (ConfirmSaveFail (Form->FormTitle, FormSet->HiiHandle) == BROWSER_ACTION_DISCARD) {\r
+        Link = GetFirstNode (&FormSet->SaveFailStorageListHead);\r
+        while (!IsNull (&FormSet->SaveFailStorageListHead, Link)) {\r
+          FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link);\r
+          Storage        = FormSetStorage->BrowserStorage;\r
+          Link = GetNextNode (&FormSet->SaveFailStorageListHead, Link);\r
 \r
-      //\r
-      // 1. Prepare <ConfigResp>\r
-      //\r
-      Status = StorageToConfigResp (Storage, &ConfigResp, FormSetStorage->ConfigRequest, TRUE);\r
-      if (EFI_ERROR (Status)) {\r
-        return Status;\r
+          SynchronizeStorage(FormSetStorage->BrowserStorage, FormSetStorage->ConfigRequest, FALSE);\r
+\r
+          Status = EFI_SUCCESS;\r
+        }\r
+      } else {\r
+        UiCopyMenuList(&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &Form->FormViewListHead);\r
+\r
+        gCurrentSelection->Action = UI_ACTION_REFRESH_FORMSET;\r
+        gCurrentSelection->Handle = FormSet->HiiHandle;\r
+        CopyGuid (&gCurrentSelection->FormSetGuid, &FormSet->Guid);\r
+        gCurrentSelection->FormId = Form->FormId;\r
+        gCurrentSelection->QuestionId = Question->QuestionId;\r
+\r
+        Status = EFI_UNSUPPORTED;\r
       }\r
 \r
       //\r
-      // 2. Send <ConfigResp> to Routine config Protocol.\r
+      // Free FormSet save fail list.\r
       //\r
-      Status = mHiiConfigRouting->RouteConfig (\r
-                                        mHiiConfigRouting,\r
-                                        ConfigResp,\r
-                                        &Progress\r
-                                        );\r
-      if (EFI_ERROR (Status)) {\r
-        FreePool (ConfigResp);\r
-        return Status;\r
+      while (!IsListEmpty (&FormSet->SaveFailStorageListHead)) {\r
+        Link = GetFirstNode (&FormSet->SaveFailStorageListHead);\r
+        FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link);\r
+        RemoveEntryList (&FormSetStorage->SaveFailLink);\r
       }\r
-\r
-      FreePool (ConfigResp);\r
+    } else {\r
       //\r
-      // 3. Config success, update storage shadow Buffer\r
+      // If in system level, just return error and handle the failed formset later.\r
       //\r
-      SynchronizeStorage (FormSet, Storage, FormSetStorage->ConfigRequest, TRUE);\r
+      Status = EFI_UNSUPPORTED;\r
+    }\r
+  }\r
+\r
+  //\r
+  // 5. Update the NV flag.\r
+  // \r
+  ValueChangeResetFlagUpdate(TRUE, FormSet, NULL);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Submit data for all formsets.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+  @retval EFI_UNSUPPORTED        Unsupport SettingScope.\r
+\r
+**/\r
+EFI_STATUS\r
+SubmitForSystem (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  LIST_ENTRY              *Link;\r
+  LIST_ENTRY              *StorageLink;\r
+  BROWSER_STORAGE         *Storage;\r
+  FORMSET_STORAGE         *FormSetStorage;\r
+  FORM_BROWSER_FORM       *Form;\r
+  FORM_BROWSER_FORMSET    *LocalFormSet;\r
+  UINT32                  UserSelection;\r
+  FORM_BROWSER_STATEMENT  *Question;\r
+\r
+  mSystemSubmit = TRUE;\r
+  Link = GetFirstNode (&gBrowserFormSetList);\r
+  while (!IsNull (&gBrowserFormSetList, Link)) {\r
+    LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
+    Link = GetNextNode (&gBrowserFormSetList, Link);\r
+    if (!ValidateFormSet(LocalFormSet)) {\r
+      continue;\r
+    }\r
+\r
+    Status = SubmitForFormSet (LocalFormSet, TRUE);\r
+    if (EFI_ERROR (Status)) {\r
+      continue;\r
     }\r
 \r
     //\r
-    // 4. Update the NV flag.\r
-    // \r
-    ValueChangeResetFlagUpdate(TRUE, FormSet, NULL);\r
-  } else if (SettingScope == SystemLevel) {\r
-    //\r
-    // System Level Save.\r
-    //\r
+    // Remove maintain backup list after save except for the current using FormSet.\r
+    //  \r
+    if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {\r
+      CleanBrowserStorage(LocalFormSet);\r
+      RemoveEntryList (&LocalFormSet->Link);\r
+      DestroyFormSet (LocalFormSet);\r
+    }\r
+  }\r
+  mSystemSubmit = FALSE;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  // Process the save failed formsets.\r
+  //\r
+  Link = GetFirstNode (&gBrowserSaveFailFormSetList);\r
+  while (!IsNull (&gBrowserSaveFailFormSetList, Link)) {\r
+    LocalFormSet = FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link);\r
+    Link = GetNextNode (&gBrowserSaveFailFormSetList, Link);\r
+\r
+    if (!ValidateFormSet(LocalFormSet)) {\r
+      continue;\r
+    }\r
+\r
+    Form = LocalFormSet->SaveFailForm;\r
+    Question= LocalFormSet->SaveFailStatement;\r
 \r
     //\r
-    // Save changed value for each FormSet in the maintain list.\r
+    // Confirm with user, get user input.\r
     //\r
-    Link = GetFirstNode (&gBrowserFormSetList);\r
-    while (!IsNull (&gBrowserFormSetList, Link)) {\r
-      LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
-      Link = GetNextNode (&gBrowserFormSetList, Link);\r
-      if (!ValidateFormSet(LocalFormSet)) {\r
-        continue;\r
+    if (IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {\r
+      //\r
+      // NULL for SaveFailStorageListHead means error caused by NO_SUBMIT_IF check.\r
+      //\r
+      UserSelection = ConfirmNoSubmitFail (Form->FormTitle, LocalFormSet->HiiHandle);\r
+    } else {\r
+      UserSelection = ConfirmSaveFail (Form->FormTitle, LocalFormSet->HiiHandle);\r
+    }\r
+\r
+    if (UserSelection == BROWSER_ACTION_DISCARD) {\r
+      if (IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {\r
+        StorageLink = GetFirstNode (&LocalFormSet->StorageListHead);\r
+        while (!IsNull (&LocalFormSet->StorageListHead, StorageLink)) {\r
+          FormSetStorage = FORMSET_STORAGE_FROM_LINK (StorageLink);\r
+          Storage        = FormSetStorage->BrowserStorage;\r
+          StorageLink = GetNextNode (&LocalFormSet->StorageListHead, StorageLink);\r
+\r
+          SynchronizeStorage(FormSetStorage->BrowserStorage, FormSetStorage->ConfigRequest, FALSE);\r
+        }\r
+      } else {\r
+        StorageLink = GetFirstNode (&LocalFormSet->SaveFailStorageListHead);\r
+        while (!IsNull (&LocalFormSet->SaveFailStorageListHead, StorageLink)) {\r
+          FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink);\r
+          Storage        = FormSetStorage->BrowserStorage;\r
+          StorageLink = GetNextNode (&LocalFormSet->SaveFailStorageListHead, StorageLink);\r
+\r
+          SynchronizeStorage(FormSetStorage->BrowserStorage, FormSetStorage->ConfigRequest, FALSE);\r
+        }\r
       }\r
-      SubmitForm (LocalFormSet, NULL, FormSetLevel);\r
+\r
       if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {\r
-        //\r
-        // Remove maintain backup list after save except for the current using FormSet.\r
-        //\r
         CleanBrowserStorage(LocalFormSet);\r
         RemoveEntryList (&LocalFormSet->Link);\r
+        RemoveEntryList (&LocalFormSet->SaveFailLink);\r
         DestroyFormSet (LocalFormSet);\r
+      } else {\r
+        ValueChangeResetFlagUpdate(FALSE, LocalFormSet, NULL);\r
       }\r
+    } else {\r
+      if (IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {\r
+        NoSubmitCheck (LocalFormSet, &Form, &Question);\r
+      }\r
+\r
+      UiCopyMenuList(&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &Form->FormViewListHead);\r
+\r
+      gCurrentSelection->Action = UI_ACTION_REFRESH_FORMSET;\r
+      gCurrentSelection->Handle = LocalFormSet->HiiHandle;\r
+      CopyGuid (&gCurrentSelection->FormSetGuid, &LocalFormSet->Guid);\r
+      gCurrentSelection->FormId = Form->FormId;\r
+      gCurrentSelection->QuestionId = Question->QuestionId;\r
+\r
+      Status = EFI_UNSUPPORTED;\r
+      break;\r
     }\r
   }\r
 \r
-  return EFI_SUCCESS;\r
+  //\r
+  // Clean the list which will not process.\r
+  //\r
+  while (!IsListEmpty (&gBrowserSaveFailFormSetList)) {\r
+    Link = GetFirstNode (&gBrowserSaveFailFormSetList);\r
+    LocalFormSet = FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link);\r
+    RemoveEntryList (&LocalFormSet->SaveFailLink);\r
+\r
+    while (!IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {\r
+      StorageLink = GetFirstNode (&LocalFormSet->SaveFailStorageListHead);\r
+      FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink);\r
+      RemoveEntryList (&FormSetStorage->SaveFailLink);\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Submit data based on the input Setting level (Form, FormSet or System).\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   Form data structure.\r
+  @param  SettingScope           Setting Scope for Submit action.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+  @retval EFI_UNSUPPORTED        Unsupport SettingScope.\r
+\r
+**/\r
+EFI_STATUS\r
+SubmitForm (\r
+  IN FORM_BROWSER_FORMSET             *FormSet,\r
+  IN FORM_BROWSER_FORM                *Form,\r
+  IN BROWSER_SETTING_SCOPE            SettingScope\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+\r
+  switch (SettingScope) {\r
+  case FormLevel:\r
+    Status = SubmitForForm(FormSet, Form);\r
+    break;\r
+\r
+  case FormSetLevel:\r
+    Status = SubmitForFormSet (FormSet, FALSE);\r
+    break;\r
+\r
+  case SystemLevel:\r
+    Status = SubmitForSystem ();\r
+    break;\r
+\r
+  default:\r
+    Status = EFI_UNSUPPORTED;\r
+    break;\r
+  }\r
+\r
+  return Status;\r
 }\r
 \r
 /**\r
@@ -3520,6 +4102,8 @@ IsQuestionValueChanged (
 {\r
   EFI_HII_VALUE    BackUpValue;\r
   CHAR8            *BackUpBuffer;\r
+  EFI_HII_VALUE    BackUpValue2;\r
+  CHAR8            *BackUpBuffer2;\r
   EFI_STATUS       Status;\r
   BOOLEAN          ValueChanged;\r
   UINTN            BufferWidth;\r
@@ -3532,6 +4116,7 @@ IsQuestionValueChanged (
   }\r
 \r
   BackUpBuffer = NULL;\r
+  BackUpBuffer2 = NULL;\r
   ValueChanged = FALSE;\r
 \r
   switch (Question->Operand) {\r
@@ -3554,12 +4139,45 @@ IsQuestionValueChanged (
   }\r
   CopyMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE));\r
 \r
-  Status = GetQuestionValue (FormSet, Form, Question, GetValueFrom);\r
-  ASSERT_EFI_ERROR(Status);\r
+  if (GetValueFrom == GetSetValueWithBothBuffer) {\r
+    Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
+    ASSERT_EFI_ERROR(Status);\r
 \r
-  if (CompareMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE)) != 0 ||\r
-      CompareMem (BackUpBuffer, Question->BufferValue, BufferWidth) != 0) {\r
-    ValueChanged = TRUE;\r
+    switch (Question->Operand) {\r
+      case EFI_IFR_ORDERED_LIST_OP:\r
+        BufferWidth  = Question->StorageWidth;\r
+        BackUpBuffer2 = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
+        ASSERT (BackUpBuffer2 != NULL);\r
+        break;\r
+\r
+      case EFI_IFR_STRING_OP:\r
+      case EFI_IFR_PASSWORD_OP:\r
+        BufferWidth  = (UINTN) Question->Maximum * sizeof (CHAR16);\r
+        BackUpBuffer2 = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
+        ASSERT (BackUpBuffer2 != NULL);\r
+        break;\r
+\r
+      default:\r
+        BufferWidth = 0;\r
+        break;\r
+    }\r
+    CopyMem (&BackUpValue2, &Question->HiiValue, sizeof (EFI_HII_VALUE));\r
+\r
+    Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);\r
+    ASSERT_EFI_ERROR(Status);\r
+\r
+    if (CompareMem (&BackUpValue2, &Question->HiiValue, sizeof (EFI_HII_VALUE)) != 0 ||\r
+        CompareMem (BackUpBuffer2, Question->BufferValue, BufferWidth) != 0) {\r
+      ValueChanged = TRUE;\r
+    }\r
+  } else {\r
+    Status = GetQuestionValue (FormSet, Form, Question, GetValueFrom);\r
+    ASSERT_EFI_ERROR(Status);\r
+\r
+    if (CompareMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE)) != 0 ||\r
+        CompareMem (BackUpBuffer, Question->BufferValue, BufferWidth) != 0) {\r
+      ValueChanged = TRUE;\r
+    }\r
   }\r
 \r
   CopyMem (&Question->HiiValue, &BackUpValue, sizeof (EFI_HII_VALUE));\r
@@ -3569,6 +4187,10 @@ IsQuestionValueChanged (
     FreePool (BackUpBuffer);\r
   }\r
 \r
+  if (BackUpBuffer2 != NULL) {\r
+    FreePool (BackUpBuffer2);\r
+  }\r
+\r
   Question->ValueChanged = ValueChanged;\r
 \r
   return ValueChanged;\r
@@ -4272,7 +4894,7 @@ LoadStorage (
   //\r
   // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer. \r
   //\r
-  SynchronizeStorage(FormSet, Storage->BrowserStorage, NULL, TRUE);\r
+  SynchronizeStorage(Storage->BrowserStorage, NULL, TRUE);\r
 \r
   if (Storage->BrowserStorage->Type != EFI_HII_VARSTORE_NAME_VALUE) {\r
     if (ConfigRequest != NULL) {\r