]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
MdeModulePkg:fix browser not call EFI_BROWSER_ACTION_CHANGED
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Presentation.c
index bad8b7b122ea72d567fc27a599c659ef607bb2f9..b8c5a3919ef1629a11d8127a3143fd1850efba5c 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
 Utility functions for UI presentation.\r
 \r
-Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -178,7 +178,7 @@ UpdateStatement (
 **/\r
 VOID\r
 EFIAPI\r
-RefreshEventNotify(\r
+RefreshEventNotifyForStatement(\r
   IN      EFI_EVENT Event,\r
   IN      VOID      *Context\r
   )\r
@@ -190,6 +190,23 @@ RefreshEventNotify(
   gBS->SignalEvent (mValueChangedEvent);\r
 }\r
 \r
+/**\r
+  Refresh the questions within this form.\r
+  \r
+  @param Event    The event which has this function related.\r
+  @param Context  The input context info related to this event or the status code return to the caller.\r
+**/\r
+VOID\r
+EFIAPI\r
+RefreshEventNotifyForForm(\r
+  IN      EFI_EVENT Event,\r
+  IN      VOID      *Context\r
+  )\r
+{\r
+  gCurrentSelection->Action = UI_ACTION_REFRESH_FORMSET;\r
+\r
+  gBS->SignalEvent (mValueChangedEvent);\r
+}\r
 \r
 /**\r
   Create refresh hook event for statement which has refresh event or interval.\r
@@ -198,7 +215,7 @@ RefreshEventNotify(
 \r
 **/\r
 VOID\r
-CreateRefreshEvent (\r
+CreateRefreshEventForStatement (\r
   IN     FORM_BROWSER_STATEMENT        *Statement\r
   )\r
 {\r
@@ -212,7 +229,7 @@ CreateRefreshEvent (
   Status = gBS->CreateEventEx (\r
                     EVT_NOTIFY_SIGNAL,\r
                     TPL_CALLBACK,\r
-                    RefreshEventNotify,\r
+                    RefreshEventNotifyForStatement,\r
                     Statement,\r
                     &Statement->RefreshGuid,\r
                     &RefreshEvent);\r
@@ -224,6 +241,39 @@ CreateRefreshEvent (
   InsertTailList(&mRefreshEventList, &EventNode->Link);\r
 }\r
 \r
+/**\r
+  Create refresh hook event for form which has refresh event or interval.\r
+\r
+  @param Form           The form need to check.\r
+\r
+**/\r
+VOID\r
+CreateRefreshEventForForm (\r
+  IN     FORM_BROWSER_FORM        *Form\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  EFI_EVENT                       RefreshEvent;\r
+  FORM_BROWSER_REFRESH_EVENT_NODE *EventNode;\r
+\r
+  //\r
+  // If question has refresh guid, create the notify function.\r
+  //\r
+  Status = gBS->CreateEventEx (\r
+                    EVT_NOTIFY_SIGNAL,\r
+                    TPL_CALLBACK,\r
+                    RefreshEventNotifyForForm,\r
+                    Form,\r
+                    &Form->RefreshGuid,\r
+                    &RefreshEvent);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  EventNode = AllocateZeroPool (sizeof (FORM_BROWSER_REFRESH_EVENT_NODE));\r
+  ASSERT (EventNode != NULL);\r
+  EventNode->RefreshEvent = RefreshEvent;\r
+  InsertTailList(&mRefreshEventList, &EventNode->Link);\r
+}\r
+\r
 /**\r
 \r
   Initialize the Display statement structure data.\r
@@ -308,7 +358,7 @@ InitializeDisplayStatement (
   // Create the refresh event process function.\r
   //\r
   if (!CompareGuid (&Statement->RefreshGuid, &gZeroGuid)) {\r
-    CreateRefreshEvent (Statement);\r
+    CreateRefreshEventForStatement (Statement);\r
   }\r
 \r
   //\r
@@ -397,8 +447,11 @@ UpdateHotkeyList (
     HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);\r
 \r
     CopyKey             = AllocateCopyPool(sizeof (BROWSER_HOT_KEY), HotKey);\r
+    ASSERT (CopyKey != NULL);\r
     CopyKey->KeyData    = AllocateCopyPool(sizeof (EFI_INPUT_KEY), HotKey->KeyData);\r
+    ASSERT (CopyKey->KeyData != NULL);\r
     CopyKey->HelpString = AllocateCopyPool(StrSize (HotKey->HelpString), HotKey->HelpString);\r
+    ASSERT (CopyKey->HelpString != NULL);\r
 \r
     InsertTailList(&gDisplayFormData.HotKeyListHead, &CopyKey->Link);\r
 \r
@@ -556,6 +609,16 @@ AddStatementToDisplayForm (
     InsertTailList(&mRefreshEventList, &EventNode->Link);\r
   }\r
 \r
+  //\r
+  // Create the refresh event process function for Form.\r
+  //\r
+  if (!CompareGuid (&gCurrentSelection->Form->RefreshGuid, &gZeroGuid)) {\r
+    CreateRefreshEventForForm (gCurrentSelection->Form);\r
+    if (gDisplayFormData.FormRefreshEvent == NULL) {\r
+      gDisplayFormData.FormRefreshEvent = mValueChangedEvent;\r
+    }\r
+  }\r
+\r
   //\r
   // Update hotkey list field.\r
   //\r
@@ -814,6 +877,13 @@ UpdateStatementStatusForForm (
     Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
     Link = GetNextNode (&Form->StatementListHead, Link);\r
 \r
+    //\r
+    // For password opcode, not set the the value changed flag.\r
+    //\r
+    if (Question->Operand == EFI_IFR_PASSWORD_OP) {\r
+      continue;\r
+    }\r
+\r
     IsQuestionValueChanged(FormSet, Form, Question, GetSetValueWithBuffer);\r
   }\r
 }\r
@@ -902,8 +972,6 @@ ProcessAction (
   IN UINT16        DefaultId\r
   )\r
 {\r
-  EFI_STATUS    Status;\r
-\r
   //\r
   // This is caused by use press ESC, and it should not combine with other action type.\r
   //\r
@@ -920,15 +988,12 @@ ProcessAction (
   }\r
 \r
   if ((Action & BROWSER_ACTION_DEFAULT) == BROWSER_ACTION_DEFAULT) {\r
-    ExtractDefault (gCurrentSelection->FormSet, gCurrentSelection->Form, DefaultId, gBrowserSettingScope, GetDefaultForAll, NULL, FALSE);\r
+    ExtractDefault (gCurrentSelection->FormSet, gCurrentSelection->Form, DefaultId, gBrowserSettingScope, GetDefaultForAll, NULL, FALSE, FALSE);\r
     UpdateStatementStatus (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);\r
   }\r
 \r
   if ((Action & BROWSER_ACTION_SUBMIT) == BROWSER_ACTION_SUBMIT) {\r
-    Status = SubmitForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);\r
-    if (EFI_ERROR (Status)) {\r
-      PopupErrorMessage(BROWSER_SUBMIT_FAIL, NULL, NULL);\r
-    }\r
+    SubmitForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);\r
   }\r
 \r
   if ((Action & BROWSER_ACTION_RESET) == BROWSER_ACTION_RESET) {\r
@@ -1183,7 +1248,8 @@ ProcessChangedData (
   IN     BROWSER_SETTING_SCOPE   Scope\r
   )\r
 {\r
-  BOOLEAN  RetValue;\r
+  BOOLEAN    RetValue;\r
+  EFI_STATUS Status;\r
 \r
   RetValue = TRUE;\r
   switch (mFormDisplay->ConfirmDataChange()) {\r
@@ -1192,7 +1258,10 @@ ProcessChangedData (
       break;\r
   \r
     case BROWSER_ACTION_SUBMIT:\r
-      SubmitForm (Selection->FormSet, Selection->Form, Scope);\r
+      Status = SubmitForm (Selection->FormSet, Selection->Form, Scope);\r
+      if (EFI_ERROR (Status)) {\r
+        RetValue = FALSE;\r
+      }\r
       break;\r
 \r
     case BROWSER_ACTION_NONE:\r
@@ -1226,15 +1295,7 @@ FindParentFormSet (
   FORM_ENTRY_INFO            *ParentMenu;\r
 \r
   CurrentMenu = Selection->CurrentMenu;\r
-  ParentMenu  = UiFindParentMenu(CurrentMenu);\r
-\r
-  //\r
-  // Find a menu which has different formset guid with current.\r
-  //\r
-  while (ParentMenu != NULL && CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) {\r
-    CurrentMenu = ParentMenu;\r
-    ParentMenu  = UiFindParentMenu(CurrentMenu);\r
-  }\r
+  ParentMenu  = UiFindParentMenu(CurrentMenu, FormSetLevel);\r
 \r
   if (ParentMenu != NULL) {\r
     CopyMem (&Selection->FormSetGuid, &ParentMenu->FormSetGuid, sizeof (EFI_GUID));\r
@@ -1303,7 +1364,7 @@ ProcessGotoOpCode (
       //\r
       // Not found the EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL protocol.\r
       //\r
-      PopupErrorMessage(BROWSER_PROTOCOL_NOT_FOUND, NULL, NULL);\r
+      PopupErrorMessage(BROWSER_PROTOCOL_NOT_FOUND, NULL, NULL, NULL);\r
       FreePool (StringPtr);\r
       return Status;\r
     }\r
@@ -1380,7 +1441,7 @@ ProcessGotoOpCode (
         //\r
         // Form is suppressed. \r
         //\r
-        PopupErrorMessage(BROWSER_FORM_SUPPRESS, NULL, NULL);\r
+        PopupErrorMessage(BROWSER_FORM_SUPPRESS, NULL, NULL, NULL);\r
         return EFI_SUCCESS;\r
       }\r
     }\r
@@ -1425,6 +1486,8 @@ ProcessQuestionConfig (
   ConfigResp = GetToken (Question->QuestionConfig, Selection->FormSet->HiiHandle);\r
   if (ConfigResp == NULL) {\r
     return EFI_NOT_FOUND;\r
+  } else if (ConfigResp[0] == L'\0') {\r
+    return EFI_SUCCESS;\r
   }\r
 \r
   //\r
@@ -1444,21 +1507,20 @@ ProcessQuestionConfig (
   Process the user input data.\r
 \r
   @param UserInput               The user input data.\r
-  @param ChangeHighlight         Whether need to change the highlight statement.  \r
 \r
   @retval EFI_SUCESSS            This function always return successfully for now.\r
 \r
 **/\r
 EFI_STATUS\r
 ProcessUserInput (\r
-  IN USER_INPUT               *UserInput,\r
-  IN BOOLEAN                  ChangeHighlight\r
+  IN USER_INPUT               *UserInput\r
   )\r
 {\r
   EFI_STATUS                    Status;\r
   FORM_BROWSER_STATEMENT        *Statement;\r
 \r
-  Status = EFI_SUCCESS;\r
+  Status    = EFI_SUCCESS;\r
+  Statement = NULL;\r
 \r
   //\r
   // When Exit from FormDisplay function, one of the below two cases must be true.\r
@@ -1469,62 +1531,35 @@ ProcessUserInput (
   // Remove the last highligh question id, this id will update when show next form.\r
   //\r
   gCurrentSelection->QuestionId = 0;\r
+  if (UserInput->SelectedStatement != NULL){\r
+    Statement = GetBrowserStatement(UserInput->SelectedStatement);\r
+    ASSERT (Statement != NULL);\r
+\r
+    //\r
+    // This question is the current user select one,record it and later\r
+    // show it as the highlight question.\r
+    //\r
+    gCurrentSelection->CurrentMenu->QuestionId = Statement->QuestionId;\r
+    //\r
+    // For statement like text, actio, it not has question id.\r
+    // So use FakeQuestionId to save the question.\r
+    //\r
+    if (gCurrentSelection->CurrentMenu->QuestionId == 0) {\r
+      mCurFakeQestId = Statement->FakeQuestionId;\r
+    } else {\r
+      mCurFakeQestId = 0;\r
+    }\r
+  }\r
 \r
   //\r
   // First process the Action field in USER_INPUT.\r
   //\r
   if (UserInput->Action != 0) {\r
     Status = ProcessAction (UserInput->Action, UserInput->DefaultId);\r
-    if (EFI_ERROR (Status)) {\r
-      return Status;\r
-    }\r
-\r
-    //\r
-    // Clear the highlight info.\r
-    //\r
     gCurrentSelection->Statement = NULL;\r
-\r
-    if (UserInput->SelectedStatement != NULL) {\r
-      Statement = GetBrowserStatement(UserInput->SelectedStatement);\r
-      ASSERT (Statement != NULL);\r
-      //\r
-      // Save the current highlight menu in the menu history data.\r
-      // which will be used when later browse back to this form.\r
-      //\r
-      gCurrentSelection->CurrentMenu->QuestionId = Statement->QuestionId;\r
-      //\r
-      // For statement like text, actio, it not has question id.\r
-      // So use FakeQuestionId to save the question.\r
-      //\r
-      if (gCurrentSelection->CurrentMenu->QuestionId == 0) {\r
-        mCurFakeQestId = Statement->FakeQuestionId;\r
-      } else {\r
-        mCurFakeQestId = 0;\r
-      }\r
-    }\r
   } else {\r
-    Statement = GetBrowserStatement(UserInput->SelectedStatement);\r
     ASSERT (Statement != NULL);\r
-\r
     gCurrentSelection->Statement = Statement;\r
-\r
-    if (ChangeHighlight) {\r
-      //\r
-      // This question is the current user select one,record it and later\r
-      // show it as the highlight question.\r
-      //\r
-      gCurrentSelection->CurrentMenu->QuestionId = Statement->QuestionId;\r
-      //\r
-      // For statement like text, actio, it not has question id.\r
-      // So use FakeQuestionId to save the question.\r
-      //\r
-      if (gCurrentSelection->CurrentMenu->QuestionId == 0) {\r
-        mCurFakeQestId = Statement->FakeQuestionId;\r
-      } else {\r
-        mCurFakeQestId = 0;\r
-      }\r
-    }\r
-\r
     switch (Statement->Operand) {\r
     case EFI_IFR_REF_OP:\r
       Status = ProcessGotoOpCode(Statement, gCurrentSelection);\r
@@ -1541,7 +1576,7 @@ ProcessUserInput (
       //\r
       // Reset Question to default value specified by DefaultId\r
       //\r
-      Status = ExtractDefault (gCurrentSelection->FormSet, NULL, Statement->DefaultId, FormSetLevel, GetDefaultForAll, NULL, FALSE);\r
+      Status = ExtractDefault (gCurrentSelection->FormSet, NULL, Statement->DefaultId, FormSetLevel, GetDefaultForAll, NULL, FALSE, FALSE);\r
       UpdateStatementStatus (gCurrentSelection->FormSet, NULL, FormSetLevel);\r
       break;\r
 \r
@@ -1611,7 +1646,6 @@ DisplayForm (
   EFI_STATUS               Status;\r
   USER_INPUT               UserInput;\r
   FORM_ENTRY_INFO          *CurrentMenu;\r
-  BOOLEAN                  ChangeHighlight;\r
 \r
   ZeroMem (&UserInput, sizeof (USER_INPUT));\r
 \r
@@ -1627,11 +1661,14 @@ DisplayForm (
                                  gCurrentSelection->FormId, gCurrentSelection->QuestionId);\r
     ASSERT (CurrentMenu != NULL);\r
   }\r
-  gCurrentSelection->CurrentMenu = CurrentMenu;\r
 \r
   //\r
-  // Find currrent highlight statement.\r
+  // Back up the form view history data for this form.\r
   //\r
+  UiCopyMenuList(&gCurrentSelection->Form->FormViewListHead, &mPrivateData.FormBrowserEx2.FormViewHistoryHead);\r
+\r
+  gCurrentSelection->CurrentMenu = CurrentMenu;\r
+\r
   if (gCurrentSelection->QuestionId == 0) {\r
     //\r
     // Highlight not specified, fetch it from cached menu\r
@@ -1639,9 +1676,6 @@ DisplayForm (
     gCurrentSelection->QuestionId = CurrentMenu->QuestionId;\r
   }\r
 \r
-  //\r
-  // Evaluate all the Expressions in this Form\r
-  //\r
   Status = EvaluateFormExpressions (gCurrentSelection->FormSet, gCurrentSelection->Form);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
@@ -1649,33 +1683,15 @@ DisplayForm (
 \r
   UpdateDisplayFormData ();\r
 \r
-  //\r
-  // Three possible status maybe return.\r
-  //\r
-  // EFI_INVALID_PARAMETER: The input dimension info is not valid.\r
-  // EFI_NOT_FOUND:         The input value for oneof/orderedlist opcode is not valid\r
-  //                        and an valid value has return.\r
-  // EFI_SUCCESS:           Success shows form and get user input in UserInput paramenter.\r
-  //\r
+  ASSERT (gDisplayFormData.BrowserStatus == BROWSER_SUCCESS);\r
   Status = mFormDisplay->FormDisplay (&gDisplayFormData, &UserInput);\r
-  if (EFI_ERROR (Status) && Status != EFI_NOT_FOUND) {\r
+  if (EFI_ERROR (Status)) {\r
     FreeDisplayFormData();\r
     return Status;\r
   }\r
 \r
-  //\r
-  // If status is EFI_SUCCESS, means user has change the highlight menu and new user input return.\r
-  //                           in this case, browser need to change the highlight menu.\r
-  // If status is EFI_NOT_FOUND, means the input DisplayFormData has error for oneof/orderedlist \r
-  //                          opcode and new valid value has return, browser core need to adjust\r
-  //                          value for this opcode and shows this form again.\r
-  //\r
-  ChangeHighlight = (Status == EFI_SUCCESS ? TRUE :FALSE);\r
-\r
-  Status = ProcessUserInput (&UserInput, ChangeHighlight);\r
-\r
+  Status = ProcessUserInput (&UserInput);\r
   FreeDisplayFormData();\r
-\r
   return Status;\r
 }\r
 \r
@@ -1803,7 +1819,7 @@ IsNvUpdateRequiredForForm (
 BOOLEAN\r
 FindNextMenu (\r
   IN OUT UI_MENU_SELECTION        *Selection,\r
-  IN       BROWSER_SETTING_SCOPE  SettingLevel\r
+  IN     BROWSER_SETTING_SCOPE     SettingLevel\r
   )\r
 {\r
   FORM_ENTRY_INFO            *CurrentMenu;\r
@@ -1811,31 +1827,16 @@ FindNextMenu (
   BROWSER_SETTING_SCOPE      Scope;\r
   \r
   CurrentMenu = Selection->CurrentMenu;\r
-  ParentMenu  = NULL;\r
   Scope       = FormSetLevel;\r
 \r
-  if (CurrentMenu != NULL && (ParentMenu = UiFindParentMenu(CurrentMenu)) != NULL) {\r
-    //\r
-    // we have a parent, so go to the parent menu\r
-    //\r
-    if (CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) {\r
-      if (SettingLevel == FormSetLevel) {\r
-        //\r
-        // Find a menu which has different formset guid with current.\r
-        //\r
-        while (CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) {\r
-          CurrentMenu = ParentMenu;\r
-          if ((ParentMenu = UiFindParentMenu(CurrentMenu)) == NULL) {\r
-            break;\r
-          }\r
-        }\r
+  ParentMenu = UiFindParentMenu(CurrentMenu, SettingLevel);\r
+  while (ParentMenu != NULL && !ValidateHiiHandle(ParentMenu->HiiHandle)) {\r
+    ParentMenu = UiFindParentMenu(ParentMenu, SettingLevel);\r
+  }\r
 \r
-        if (ParentMenu != NULL) {\r
-          Scope = FormSetLevel;\r
-        }\r
-      } else {\r
-        Scope = FormLevel;\r
-      }\r
+  if (ParentMenu != NULL) {\r
+    if (CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) {\r
+      Scope = FormLevel;\r
     } else {\r
       Scope = FormSetLevel;\r
     }\r
@@ -1846,7 +1847,7 @@ FindNextMenu (
   //\r
   if ((gBrowserSettingScope == FormLevel && IsNvUpdateRequiredForForm (Selection->Form)) ||\r
       (gBrowserSettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet(Selection->FormSet) && Scope == FormSetLevel)) {\r
-    if (!ProcessChangedData(Selection, Scope)) {\r
+    if (!ProcessChangedData(Selection, gBrowserSettingScope)) {\r
       return FALSE;\r
     }\r
   }\r
@@ -1910,6 +1911,7 @@ ProcessCallBackFunction (
   )\r
 {\r
   EFI_STATUS                      Status;\r
+  EFI_STATUS                      InternalStatus;\r
   EFI_BROWSER_ACTION_REQUEST      ActionRequest;\r
   EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;\r
   EFI_HII_VALUE                   *HiiValue;\r
@@ -1977,6 +1979,7 @@ ProcessCallBackFunction (
     if (Action == EFI_BROWSER_ACTION_CHANGING) {\r
       if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
         BackUpBuffer = AllocateCopyPool(Statement->StorageWidth + sizeof(CHAR16), Statement->BufferValue);\r
+        ASSERT (BackUpBuffer != NULL);\r
       } else {\r
         CopyMem (&BackUpValue, &HiiValue->Value, sizeof (EFI_IFR_TYPE_VALUE));\r
       }\r
@@ -2063,6 +2066,11 @@ ProcessCallBackFunction (
         //\r
         Status = ValueChangedValidation (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement);\r
         if (!EFI_ERROR (Status)) {\r
+          //\r
+          //check whether the question value  changed compared with edit buffer before updating edit buffer\r
+          // if changed, set the ValueChanged flag to TRUE,in order to trig the CHANGED callback function\r
+          //\r
+          IsQuestionValueChanged(gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithEditBuffer);\r
           //\r
           // According the spec, return value from call back of "changing" and \r
           // "retrieve" should update to the question's temp buffer.\r
@@ -2098,8 +2106,13 @@ ProcessCallBackFunction (
         //\r
         // Do the question validation.\r
         //\r
-        Status = ValueChangedValidation (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement);\r
-        if (!EFI_ERROR (Status)) {\r
+        InternalStatus = ValueChangedValidation (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement);\r
+        if (!EFI_ERROR (InternalStatus)) {\r
+          //\r
+          //check whether the question value  changed compared with edit buffer before updating edit buffer\r
+          // if changed, set the ValueChanged flag to TRUE,in order to trig the CHANGED callback function\r
+          //\r
+          IsQuestionValueChanged(gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithEditBuffer);\r
           SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
         }\r
       }\r
@@ -2108,8 +2121,15 @@ ProcessCallBackFunction (
       // According the spec, return fail from call back of "changing" and \r
       // "retrieve", should restore the question's value.\r
       //\r
-      if ((Action == EFI_BROWSER_ACTION_CHANGING && Status != EFI_UNSUPPORTED) || \r
-           Action == EFI_BROWSER_ACTION_RETRIEVE) {\r
+      if (Action == EFI_BROWSER_ACTION_CHANGING && Status != EFI_UNSUPPORTED) {\r
+        if (Statement->Storage != NULL) {\r
+          GetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
+        } else if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
+          ProcessCallBackFunction (Selection, FormSet, Form, Question, EFI_BROWSER_ACTION_RETRIEVE, FALSE);\r
+        }\r
+      }\r
+\r
+      if (Action == EFI_BROWSER_ACTION_RETRIEVE) {\r
         GetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
       }\r
 \r
@@ -2124,6 +2144,15 @@ ProcessCallBackFunction (
     if (BackUpBuffer != NULL) {\r
       FreePool (BackUpBuffer);\r
     }\r
+\r
+    //\r
+    // If Question != NULL, means just process one question\r
+    // and if code reach here means this question has finished\r
+    // processing, so just break.\r
+    //\r
+    if (Question != NULL) {\r
+      break;\r
+    }\r
   }\r
 \r
   if (SubmitFormIsRequired && !SkipSaveOrDiscard) {\r
@@ -2267,6 +2296,8 @@ SetupBrowser (
   do {\r
     //\r
     // IFR is updated, force to reparse the IFR binary\r
+    // This check is shared by EFI_BROWSER_ACTION_FORM_CLOSE and \r
+    // EFI_BROWSER_ACTION_RETRIEVE, so code place here.\r
     //\r
     if (mHiiPackageListUpdated) {\r
       Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
@@ -2305,7 +2336,7 @@ SetupBrowser (
         //\r
         // Form is suppressed. \r
         //\r
-        PopupErrorMessage(BROWSER_FORM_SUPPRESS, NULL, NULL);\r
+        PopupErrorMessage(BROWSER_FORM_SUPPRESS, NULL, NULL, NULL);\r
         Status = EFI_NOT_FOUND;\r
         goto Done;\r
       }\r
@@ -2338,7 +2369,7 @@ SetupBrowser (
         }\r
 \r
         //\r
-        // IFR is updated during callback of open form, force to reparse the IFR binary\r
+        // IFR is updated during callback of EFI_BROWSER_ACTION_FORM_OPEN, force to reparse the IFR binary\r
         //\r
         if (mHiiPackageListUpdated) {\r
           Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
@@ -2416,13 +2447,19 @@ SetupBrowser (
           }\r
         }\r
 \r
-        //\r
-        // Verify whether question value has checked, update the ValueChanged flag in Question.\r
-        //\r
-        IsQuestionValueChanged(gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithBuffer);\r
 \r
-        if (!EFI_ERROR (Status) && Statement->Operand != EFI_IFR_REF_OP) {\r
+        if (!EFI_ERROR (Status) && \r
+            (Statement->Operand != EFI_IFR_REF_OP) && \r
+            ((Statement->Storage == NULL) || (Statement->Storage != NULL && Statement->ValueChanged))) {\r
+          //\r
+          // Only question value has been changed, browser will trig CHANGED callback.\r
+          //\r
           ProcessCallBackFunction(Selection, Selection->FormSet, Selection->Form, Statement, EFI_BROWSER_ACTION_CHANGED, FALSE);\r
+          //\r
+          //check whether the question value changed compared with buffer value\r
+          //if doesn't change ,set the ValueChanged flag to FALSE ,in order not to display the "configuration changed "information on the screen\r
+          //\r
+          IsQuestionValueChanged(gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithBuffer);\r
         }\r
       } else {\r
         //\r