]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
MdeModulePkg: Update the device path info for the storage when former drivers not...
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Presentation.c
index e33081422bbfb5d6d2f17193d8299c66df36d5a0..ad39d22a9dd5884bb8038115f8d4f5fc6e52bfc1 100644 (file)
@@ -21,10 +21,9 @@ EFI_GUID           mCurrentFormSetGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
 UINT16             mCurrentFormId = 0;\r
 EFI_EVENT          mValueChangedEvent = NULL;\r
 LIST_ENTRY         mRefreshEventList = INITIALIZE_LIST_HEAD_VARIABLE (mRefreshEventList);\r
-UINT32             gBrowserStatus = BROWSER_SUCCESS;\r
-CHAR16             *gErrorInfo;\r
 UINT16             mCurFakeQestId;\r
 FORM_DISPLAY_ENGINE_FORM gDisplayFormData;\r
+BOOLEAN            mFinishRetrieveCall = FALSE;\r
 \r
 /**\r
   Evaluate all expressions in a Form.\r
@@ -225,162 +224,6 @@ CreateRefreshEvent (
   InsertTailList(&mRefreshEventList, &EventNode->Link);\r
 }\r
 \r
-/**\r
-  Perform value check for a question.\r
-  \r
-  @param  Question       The question need to do check.\r
-  @param  Type           Condition type need to check.\r
-  @param  ErrorInfo      Return info about the error.\r
-  \r
-  @retval  The check result.\r
-**/\r
-UINT32\r
-ConditionCheck (\r
-  IN  FORM_BROWSER_STATEMENT        *Question,\r
-  IN  UINT8                         Type,\r
-  OUT STATEMENT_ERROR_INFO          *ErrorInfo\r
-  )\r
-{\r
-  EFI_STATUS              Status;\r
-  LIST_ENTRY              *Link;\r
-  FORM_EXPRESSION         *Expression;\r
-  LIST_ENTRY              *ListHead;\r
-  UINT32                  RetVal;\r
-\r
-  RetVal     = STATEMENT_VALID;\r
-  ListHead   = NULL;\r
-\r
-  switch (Type) {\r
-  case EFI_HII_EXPRESSION_INCONSISTENT_IF:\r
-    ListHead = &Question->InconsistentListHead;\r
-    break;\r
-\r
-  case EFI_HII_EXPRESSION_WARNING_IF:\r
-    ListHead = &Question->WarningListHead;\r
-    break;\r
-\r
-  default:\r
-    ASSERT (FALSE);\r
-    return RetVal;\r
-  }\r
-\r
-  ASSERT (ListHead != NULL);\r
-  Link = GetFirstNode (ListHead);\r
-  while (!IsNull (ListHead, Link)) {\r
-    Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
-    Link = GetNextNode (ListHead, Link);\r
-\r
-    //\r
-    // Evaluate the expression\r
-    //\r
-    Status = EvaluateExpression (gCurrentSelection->FormSet, gCurrentSelection->Form, Expression);\r
-    if (EFI_ERROR (Status)) {\r
-      continue;\r
-    }\r
-\r
-    if ((Expression->Result.Type == EFI_IFR_TYPE_BOOLEAN) && Expression->Result.Value.b) {\r
-      ErrorInfo->StringId = Expression->Error;\r
-      switch (Type) {\r
-      case EFI_HII_EXPRESSION_INCONSISTENT_IF:\r
-        ErrorInfo->TimeOut  = 0;\r
-        RetVal              = INCOSISTENT_IF_TRUE;\r
-        break;\r
-\r
-      case EFI_HII_EXPRESSION_WARNING_IF:\r
-        ErrorInfo->TimeOut  = Expression->TimeOut;\r
-        RetVal              = WARNING_IF_TRUE;\r
-        break;\r
-\r
-      default:\r
-        ASSERT (FALSE);\r
-        break;\r
-      }\r
-      break;\r
-    }\r
-  }\r
-\r
-  return RetVal;\r
-}\r
-\r
-/**\r
-  Perform value check for a question.\r
-  \r
-  @param  Form       Form where Statement is in.\r
-  @param  Statement  Value will check for it.\r
-  @param  InputValue New value will be checked.\r
-  @param  ErrorInfo  Return the error info for this check.\r
-  \r
-  @retval TRUE   Input Value is valid.\r
-  @retval FALSE  Input Value is invalid.\r
-**/\r
-UINT32\r
-EFIAPI\r
-QuestionCheck (\r
-  IN  FORM_DISPLAY_ENGINE_FORM      *Form,\r
-  IN  FORM_DISPLAY_ENGINE_STATEMENT *Statement,\r
-  IN  EFI_HII_VALUE                 *InputValue,\r
-  OUT STATEMENT_ERROR_INFO          *ErrorInfo\r
-  )\r
-{\r
-  FORM_BROWSER_STATEMENT  *Question;\r
-  EFI_HII_VALUE           BackUpValue;\r
-  UINT8                   *BackUpBuffer;\r
-  UINT32                  RetVal;\r
-\r
-  BackUpBuffer = NULL;\r
-  RetVal       = STATEMENT_VALID;\r
-\r
-  ASSERT (Form != NULL && Statement != NULL && InputValue != NULL && ErrorInfo != NULL);\r
-\r
-  Question = GetBrowserStatement(Statement);\r
-  ASSERT (Question != NULL);\r
-\r
-  //\r
-  // Back up the quesion value.\r
-  //\r
-  switch (Question->Operand) {\r
-  case EFI_IFR_ORDERED_LIST_OP:\r
-    BackUpBuffer = AllocateCopyPool (Question->StorageWidth, Question->BufferValue);\r
-    ASSERT (BackUpBuffer != NULL);\r
-    CopyMem (Question->BufferValue, InputValue->Buffer, Question->StorageWidth);\r
-    break;\r
-\r
-  default:\r
-    CopyMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE));\r
-    CopyMem (&Question->HiiValue, InputValue, sizeof (EFI_HII_VALUE));\r
-    break;\r
-  }\r
-\r
-  //\r
-  // Do the inconsistentif check.\r
-  //\r
-  if (!IsListEmpty (&Question->InconsistentListHead)) {\r
-    RetVal = ConditionCheck(Question, EFI_HII_EXPRESSION_INCONSISTENT_IF, ErrorInfo);\r
-  }\r
-\r
-  //\r
-  // Do the warningif check.\r
-  //\r
-  if (RetVal == STATEMENT_VALID && !IsListEmpty (&Question->WarningListHead)) {\r
-    RetVal = ConditionCheck(Question, EFI_HII_EXPRESSION_WARNING_IF, ErrorInfo);\r
-  }\r
-\r
-  //\r
-  // Restore the quesion value.\r
-  //\r
-  switch (Question->Operand) {\r
-  case EFI_IFR_ORDERED_LIST_OP:\r
-    CopyMem (Question->BufferValue, BackUpBuffer, Question->StorageWidth);\r
-    break;\r
-\r
-  default:\r
-    CopyMem (&Question->HiiValue, &BackUpValue, sizeof (EFI_HII_VALUE));\r
-    break;\r
-  }\r
-\r
-  return RetVal;\r
-}\r
-\r
 /**\r
 \r
   Initialize the Display statement structure data.\r
@@ -490,13 +333,6 @@ InitializeDisplayStatement (
     DisplayStatement->PasswordCheck = PasswordCheck;\r
   }\r
 \r
-  //\r
-  // Save the validate check question for later use.\r
-  //\r
-  if (!IsListEmpty (&Statement->InconsistentListHead) || !IsListEmpty (&Statement->WarningListHead)) {\r
-    DisplayStatement->ValidateQuestion = QuestionCheck;\r
-  }\r
-\r
   //\r
   // If this statement is nest in the subtitle, insert to the host statement.\r
   // else insert to the form it belongs to.\r
@@ -561,8 +397,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
@@ -857,12 +696,6 @@ UpdateDisplayFormData (
   gDisplayFormData.FormRefreshEvent     = NULL;\r
   gDisplayFormData.HighLightedStatement = NULL;\r
 \r
-  gDisplayFormData.BrowserStatus = gBrowserStatus;\r
-  gDisplayFormData.ErrorString   = gErrorInfo;\r
-\r
-  gBrowserStatus = BROWSER_SUCCESS;\r
-  gErrorInfo     = NULL;\r
-\r
   UpdateDataChangedFlag ();\r
 \r
   AddStatementToDisplayForm ();\r
@@ -984,6 +817,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
@@ -1072,8 +912,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
@@ -1090,15 +928,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
-      gBrowserStatus = BROWSER_SUBMIT_FAIL;\r
-    }\r
+    SubmitForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);\r
   }\r
 \r
   if ((Action & BROWSER_ACTION_RESET) == BROWSER_ACTION_RESET) {\r
@@ -1353,7 +1188,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
@@ -1362,7 +1198,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
@@ -1396,15 +1235,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
@@ -1473,7 +1304,7 @@ ProcessGotoOpCode (
       //\r
       // Not found the EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL protocol.\r
       //\r
-      gBrowserStatus = BROWSER_PROTOCOL_NOT_FOUND;\r
+      PopupErrorMessage(BROWSER_PROTOCOL_NOT_FOUND, NULL, NULL, NULL);\r
       FreePool (StringPtr);\r
       return Status;\r
     }\r
@@ -1550,7 +1381,7 @@ ProcessGotoOpCode (
         //\r
         // Form is suppressed. \r
         //\r
-        gBrowserStatus = BROWSER_FORM_SUPPRESS;\r
+        PopupErrorMessage(BROWSER_FORM_SUPPRESS, NULL, NULL, NULL);\r
         return EFI_SUCCESS;\r
       }\r
     }\r
@@ -1614,21 +1445,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
@@ -1639,62 +1469,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
@@ -1711,7 +1514,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
@@ -1781,7 +1584,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
@@ -1797,11 +1599,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
@@ -1809,9 +1614,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
@@ -1819,33 +1621,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
@@ -1957,70 +1741,6 @@ IsNvUpdateRequiredForForm (
   return FALSE;\r
 }\r
 \r
-/**\r
-  Check whether the storage data for current form set is changed.\r
-\r
-  @param  FormSet           FormSet data structure.\r
-\r
-  @retval TRUE              Data is changed.\r
-  @retval FALSE             Data is not changed.\r
-**/\r
-BOOLEAN \r
-IsStorageDataChangedForFormSet (\r
-  IN FORM_BROWSER_FORMSET             *FormSet\r
-  )\r
-{\r
-  LIST_ENTRY              *Link;\r
-  FORMSET_STORAGE         *Storage;\r
-  BROWSER_STORAGE         *BrowserStorage;\r
-  CHAR16                  *ConfigRespNew;\r
-  CHAR16                  *ConfigRespOld;\r
-  BOOLEAN                 RetVal;\r
-\r
-  RetVal        = FALSE;\r
-  ConfigRespNew = NULL;\r
-  ConfigRespOld = NULL;\r
-\r
-  //\r
-  // Request current settings from Configuration Driver\r
-  //\r
-  Link = GetFirstNode (&FormSet->StorageListHead);\r
-  while (!IsNull (&FormSet->StorageListHead, Link)) {\r
-    Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
-    Link = GetNextNode (&FormSet->StorageListHead, Link);\r
-\r
-    BrowserStorage = Storage->BrowserStorage;\r
-\r
-    if (BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
-      continue;\r
-    }\r
-\r
-    if (Storage->ElementCount == 0) {\r
-      continue;\r
-    }\r
-\r
-    StorageToConfigResp (BrowserStorage, &ConfigRespNew, Storage->ConfigRequest, TRUE);\r
-    StorageToConfigResp (BrowserStorage, &ConfigRespOld, Storage->ConfigRequest, FALSE);\r
-    ASSERT (ConfigRespNew != NULL && ConfigRespOld != NULL);\r
-\r
-    if (StrCmp (ConfigRespNew, ConfigRespOld) != 0) {\r
-      RetVal = TRUE;\r
-    }\r
-\r
-    FreePool (ConfigRespNew);\r
-    ConfigRespNew = NULL;\r
-\r
-    FreePool (ConfigRespOld);\r
-    ConfigRespOld = NULL;\r
-\r
-    if (RetVal) {\r
-      break;\r
-    }\r
-  }\r
-\r
-  return RetVal;\r
-}\r
-\r
 /**\r
   Find menu which will show next time.\r
 \r
@@ -2037,7 +1757,7 @@ IsStorageDataChangedForFormSet (
 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
@@ -2045,31 +1765,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
@@ -2080,7 +1785,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
@@ -2156,6 +1861,7 @@ ProcessCallBackFunction (
   BROWSER_SETTING_SCOPE           SettingLevel;\r
   EFI_IFR_TYPE_VALUE              BackUpValue;\r
   UINT8                           *BackUpBuffer;\r
+  CHAR16                          *NewString;\r
 \r
   ConfigAccess = FormSet->ConfigAccess;\r
   SubmitFormIsRequired  = FALSE;\r
@@ -2210,6 +1916,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
@@ -2225,10 +1932,27 @@ ProcessCallBackFunction (
                              &ActionRequest\r
                              );\r
     if (!EFI_ERROR (Status)) {\r
+      //\r
+      // Need to sync the value between Statement->HiiValue->Value and Statement->BufferValue\r
+      //\r
+      if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
+        NewString = GetToken (Statement->HiiValue.Value.string, FormSet->HiiHandle);\r
+        ASSERT (NewString != NULL);\r
+\r
+        ASSERT (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth);\r
+        if (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth) {\r
+          CopyMem (Statement->BufferValue, NewString, StrSize (NewString));\r
+        } else {\r
+          CopyMem (Statement->BufferValue, NewString, Statement->StorageWidth);\r
+        }\r
+        FreePool (NewString);\r
+      }\r
+\r
       //\r
       // Only for EFI_BROWSER_ACTION_CHANGED need to handle this ActionRequest.\r
       //\r
-      if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
+      switch (Action) {\r
+      case EFI_BROWSER_ACTION_CHANGED:\r
         switch (ActionRequest) {\r
         case EFI_BROWSER_ACTION_REQUEST_RESET:\r
           DiscardFormIsRequired = TRUE;\r
@@ -2271,14 +1995,32 @@ ProcessCallBackFunction (
         default:\r
           break;\r
         }\r
-      }\r
+        break;\r
 \r
-      //\r
-      // According the spec, return value from call back of "changing" and \r
-      // "retrieve" should update to the question's temp buffer.\r
-      //\r
-      if (Action == EFI_BROWSER_ACTION_CHANGING || Action == EFI_BROWSER_ACTION_RETRIEVE) {\r
+      case EFI_BROWSER_ACTION_CHANGING:\r
+        //\r
+        // Do the question validation.\r
+        //\r
+        Status = ValueChangedValidation (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement);\r
+        if (!EFI_ERROR (Status)) {\r
+          //\r
+          // According the spec, return value from call back of "changing" and \r
+          // "retrieve" should update to the question's temp buffer.\r
+          //\r
+          SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
+        }\r
+        break;\r
+\r
+      case EFI_BROWSER_ACTION_RETRIEVE:\r
+        //\r
+        // According the spec, return value from call back of "changing" and \r
+        // "retrieve" should update to the question's temp buffer.\r
+        //\r
         SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
+        break;\r
+\r
+      default:\r
+        break;\r
       }\r
     } else {\r
       //\r
@@ -2292,8 +2034,14 @@ ProcessCallBackFunction (
         } else {\r
           CopyMem (&HiiValue->Value, &BackUpValue, sizeof (EFI_IFR_TYPE_VALUE));\r
         }\r
-\r
-        SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
+        \r
+        //\r
+        // Do the question validation.\r
+        //\r
+        Status = ValueChangedValidation (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement);\r
+        if (!EFI_ERROR (Status)) {\r
+          SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
+        }\r
       }\r
 \r
       //\r
@@ -2316,6 +2064,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
@@ -2341,6 +2098,7 @@ ProcessCallBackFunction (
 \r
   @param ConfigAccess          The config access protocol produced by the hii driver.\r
   @param Statement             The Question which need to call.\r
+  @param FormSet               The formset this question belong to.\r
 \r
   @retval EFI_SUCCESS          The call back function excutes successfully.\r
   @return Other value if the call back function failed to excute.  \r
@@ -2348,18 +2106,20 @@ ProcessCallBackFunction (
 EFI_STATUS \r
 ProcessRetrieveForQuestion (\r
   IN     EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess,\r
-  IN     FORM_BROWSER_STATEMENT          *Statement\r
+  IN     FORM_BROWSER_STATEMENT          *Statement,\r
+  IN     FORM_BROWSER_FORMSET            *FormSet\r
   )\r
 {\r
   EFI_STATUS                      Status;\r
   EFI_BROWSER_ACTION_REQUEST      ActionRequest;\r
   EFI_HII_VALUE                   *HiiValue;\r
   EFI_IFR_TYPE_VALUE              *TypeValue;\r
+  CHAR16                          *NewString;\r
 \r
   Status                = EFI_SUCCESS;\r
   ActionRequest         = EFI_BROWSER_ACTION_REQUEST_NONE;\r
-    \r
-  if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) {\r
+\r
+  if (((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) || ConfigAccess == NULL) {\r
     return EFI_UNSUPPORTED;\r
   }\r
 \r
@@ -2381,6 +2141,19 @@ ProcessRetrieveForQuestion (
                            TypeValue,\r
                            &ActionRequest\r
                            );\r
+  if (!EFI_ERROR (Status) && HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
+    NewString = GetToken (Statement->HiiValue.Value.string, FormSet->HiiHandle);\r
+    ASSERT (NewString != NULL);\r
+\r
+    ASSERT (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth);\r
+    if (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth) {\r
+      CopyMem (Statement->BufferValue, NewString, StrSize (NewString));\r
+    } else {\r
+      CopyMem (Statement->BufferValue, NewString, Statement->StorageWidth);\r
+    }\r
+    FreePool (NewString);\r
+  }\r
+\r
   return Status;\r
 }\r
 \r
@@ -2425,11 +2198,6 @@ SetupBrowser (
     return Status;\r
   }\r
 \r
-  if ((Selection->Handle != mCurrentHiiHandle) ||\r
-      (!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid))) {\r
-    gFinishRetrieveCall = FALSE;\r
-  }\r
-\r
   //\r
   // Initialize current settings of Questions in this FormSet\r
   //\r
@@ -2448,6 +2216,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
@@ -2486,7 +2256,7 @@ SetupBrowser (
         //\r
         // Form is suppressed. \r
         //\r
-        gBrowserStatus = BROWSER_FORM_SUPPRESS;\r
+        PopupErrorMessage(BROWSER_FORM_SUPPRESS, NULL, NULL, NULL);\r
         Status = EFI_NOT_FOUND;\r
         goto Done;\r
       }\r
@@ -2497,10 +2267,14 @@ SetupBrowser (
     // for each question with callback flag.\r
     // New form may be the first form, or the different form after another form close.\r
     //\r
-    if ((ConfigAccess != NULL) &&\r
-        ((Selection->Handle != mCurrentHiiHandle) ||\r
+    if (((Selection->Handle != mCurrentHiiHandle) ||\r
         (!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid)) ||\r
         (Selection->FormId != mCurrentFormId))) {\r
+      //\r
+      // Update Retrieve flag.\r
+      //\r
+      mFinishRetrieveCall = FALSE;\r
+\r
       //\r
       // Keep current form information\r
       //\r
@@ -2508,18 +2282,20 @@ SetupBrowser (
       CopyGuid (&mCurrentFormSetGuid, &Selection->FormSetGuid);\r
       mCurrentFormId      = Selection->FormId;\r
 \r
-      Status = ProcessCallBackFunction (Selection, gCurrentSelection->FormSet, Selection->Form, NULL, EFI_BROWSER_ACTION_FORM_OPEN, FALSE);\r
-      if (EFI_ERROR (Status)) {\r
-        goto Done;\r
-      }\r
+      if (ConfigAccess != NULL) {\r
+        Status = ProcessCallBackFunction (Selection, Selection->FormSet, Selection->Form, NULL, EFI_BROWSER_ACTION_FORM_OPEN, FALSE);\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
 \r
-      //\r
-      // IFR is updated during callback of open form, force to reparse the IFR binary\r
-      //\r
-      if (mHiiPackageListUpdated) {\r
-        Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
-        mHiiPackageListUpdated = FALSE;\r
-        break;\r
+        //\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
+          mHiiPackageListUpdated = FALSE;\r
+          break;\r
+        }\r
       }\r
     }\r
 \r
@@ -2531,18 +2307,27 @@ SetupBrowser (
       goto Done;\r
     }\r
 \r
-    //\r
-    // Finish call RETRIEVE callback for this formset.\r
-    //\r
-    gFinishRetrieveCall = TRUE;\r
+    if (!mFinishRetrieveCall) {\r
+      //\r
+      // Finish call RETRIEVE callback for this form.\r
+      //\r
+      mFinishRetrieveCall = TRUE;\r
 \r
-    //\r
-    // IFR is updated during callback of read value, force to reparse the IFR binary\r
-    //\r
-    if (mHiiPackageListUpdated) {\r
-      Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
-      mHiiPackageListUpdated = FALSE;\r
-      break;\r
+      if (ConfigAccess != NULL) {\r
+        Status = ProcessCallBackFunction (Selection, Selection->FormSet, Selection->Form, NULL, EFI_BROWSER_ACTION_RETRIEVE, FALSE);\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
+\r
+        //\r
+        // IFR is updated during callback of open form, force to reparse the IFR binary\r
+        //\r
+        if (mHiiPackageListUpdated) {\r
+          Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+          mHiiPackageListUpdated = FALSE;\r
+          break;\r
+        }\r
+      }\r
     }\r
 \r
     //\r
@@ -2582,18 +2367,33 @@ SetupBrowser (
           }\r
         }\r
 \r
-        if (!EFI_ERROR (Status) && Statement->Operand != EFI_IFR_REF_OP) {\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) && \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
-      } else if (Statement->Operand != EFI_IFR_PASSWORD_OP) {\r
-        SetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithEditBuffer);\r
+      } else {\r
+        //\r
+        // Do the question validation.\r
+        //\r
+        Status = ValueChangedValidation (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement);\r
+        if (!EFI_ERROR (Status) && (Statement->Operand != EFI_IFR_PASSWORD_OP)) {\r
+          SetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithEditBuffer);\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
       }\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
       //\r
       // If question has EFI_IFR_FLAG_RESET_REQUIRED flag and without storage and process question success till here, \r
       // trig the gResetFlag.\r