]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Presentation.c
index def18fd9f90b3eaec623fc9107df1d5d4d06da94..d7927725b231cc46e65dbd7739a42baf2946b7e1 100644 (file)
@@ -1,14 +1,9 @@
 /** @file\r
 Utility functions for UI presentation.\r
 \r
-Copyright (c) 2004 - 2013, 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
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
+(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -21,10 +16,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
@@ -52,6 +46,7 @@ EvaluateFormExpressions (
 \r
     if (Expression->Type == EFI_HII_EXPRESSION_INCONSISTENT_IF ||\r
         Expression->Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF ||\r
+        Expression->Type == EFI_HII_EXPRESSION_WARNING_IF ||\r
         Expression->Type == EFI_HII_EXPRESSION_WRITE ||\r
         (Expression->Type == EFI_HII_EXPRESSION_READ && Form->FormType != STANDARD_MAP_FORM_TYPE)) {\r
       //\r
@@ -69,27 +64,11 @@ EvaluateFormExpressions (
   return EFI_SUCCESS;\r
 }\r
 \r
-/**\r
-  Add empty function for event process function.\r
-\r
-  @param Event    The Event need to be process\r
-  @param Context  The context of the event.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-SetupBrowserEmptyFunction (\r
-  IN  EFI_EVENT    Event,\r
-  IN  VOID         *Context\r
-  )\r
-{\r
-}\r
-\r
 /**\r
   Base on the opcode buffer info to get the display statement.\r
 \r
   @param OpCode    The input opcode buffer for this statement.\r
-  \r
+\r
   @retval Statement  The statement use this opcode buffer.\r
 \r
 **/\r
@@ -118,7 +97,7 @@ GetDisplayStatement (
   Free the refresh event list.\r
 \r
 **/\r
-VOID \r
+VOID\r
 FreeRefreshEvent (\r
   VOID\r
   )\r
@@ -138,7 +117,7 @@ FreeRefreshEvent (
 }\r
 \r
 /**\r
-  Check whether this statement value is changed. If yes, update the statement value and return TRUE; \r
+  Check whether this statement value is changed. If yes, update the statement value and return TRUE;\r
   else return FALSE.\r
 \r
   @param Statement           The statement need to check.\r
@@ -159,8 +138,8 @@ UpdateStatement (
   //\r
   // Question value may be changed, need invoke its Callback()\r
   //\r
-  ProcessCallBackFunction (gCurrentSelection, Statement, EFI_BROWSER_ACTION_CHANGING, FALSE);\r
-  \r
+  ProcessCallBackFunction (gCurrentSelection, gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, EFI_BROWSER_ACTION_RETRIEVE, FALSE);\r
+\r
   if (mHiiPackageListUpdated) {\r
     //\r
     // Package list is updated, force to reparse IFR binary of target Formset\r
@@ -172,13 +151,13 @@ UpdateStatement (
 \r
 /**\r
   Refresh the question which has refresh guid event attribute.\r
-  \r
-  @param Event    The event which has this function related.     \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
-RefreshEventNotify(\r
+RefreshEventNotifyForStatement(\r
   IN      EFI_EVENT Event,\r
   IN      VOID      *Context\r
   )\r
@@ -190,6 +169,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 +194,7 @@ RefreshEventNotify(
 \r
 **/\r
 VOID\r
-CreateRefreshEvent (\r
+CreateRefreshEventForStatement (\r
   IN     FORM_BROWSER_STATEMENT        *Statement\r
   )\r
 {\r
@@ -212,7 +208,7 @@ CreateRefreshEvent (
   Status = gBS->CreateEventEx (\r
                     EVT_NOTIFY_SIGNAL,\r
                     TPL_CALLBACK,\r
-                    RefreshEventNotify,\r
+                    RefreshEventNotifyForStatement,\r
                     Statement,\r
                     &Statement->RefreshGuid,\r
                     &RefreshEvent);\r
@@ -225,122 +221,36 @@ CreateRefreshEvent (
 }\r
 \r
 /**\r
-  Perform value check for a question.\r
-  \r
-  @param  Question       The question need to do check.\r
-  @param  ErrorInfo      Return info about the error.\r
-  \r
-  @retval  The check result.\r
-**/\r
-UINT32\r
-InConsistentIfCheck (\r
-  IN  FORM_BROWSER_STATEMENT        *Question,\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   = &Question->InconsistentListHead;\r
-\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
-      ErrorInfo->TimeOut  = 0;\r
-      RetVal              = INCOSISTENT_IF_TRUE;\r
-      break;\r
-    }\r
-  }\r
+  Create refresh hook event for form which has refresh event or interval.\r
 \r
-  return RetVal;\r
-}\r
+  @param Form           The form need to check.\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
+VOID\r
+CreateRefreshEventForForm (\r
+  IN     FORM_BROWSER_FORM        *Form\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 = InConsistentIfCheck(Question, ErrorInfo);\r
-  }\r
+  EFI_STATUS                      Status;\r
+  EFI_EVENT                       RefreshEvent;\r
+  FORM_BROWSER_REFRESH_EVENT_NODE *EventNode;\r
 \r
   //\r
-  // Restore the quesion value.\r
+  // If question has refresh guid, create the notify function.\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
+  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
-  return RetVal;\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
@@ -349,18 +259,17 @@ QuestionCheck (
 \r
   @param DisplayStatement      Pointer to the display Statement data strucure.\r
   @param Statement             The statement need to check.\r
-  @param HostDisplayStatement  Pointer to the display Statement data strucure which is an host statement.\r
 **/\r
 VOID\r
 InitializeDisplayStatement (\r
   IN OUT FORM_DISPLAY_ENGINE_STATEMENT *DisplayStatement,\r
-  IN     FORM_BROWSER_STATEMENT        *Statement,\r
-  IN     FORM_DISPLAY_ENGINE_STATEMENT *HostDisplayStatement\r
+  IN     FORM_BROWSER_STATEMENT        *Statement\r
   )\r
 {\r
   LIST_ENTRY                 *Link;\r
   QUESTION_OPTION            *Option;\r
   DISPLAY_QUESTION_OPTION    *DisplayOption;\r
+  FORM_DISPLAY_ENGINE_STATEMENT *ParentStatement;\r
 \r
   DisplayStatement->Signature = FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE;\r
   DisplayStatement->Version   = FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1;\r
@@ -427,8 +336,8 @@ InitializeDisplayStatement (
   //\r
   // Create the refresh event process function.\r
   //\r
-  if (!CompareGuid (&Statement->RefreshGuid, &gZeroGuid)) {\r
-    CreateRefreshEvent (Statement);\r
+  if (!IsZeroGuid (&Statement->RefreshGuid)) {\r
+    CreateRefreshEventForStatement (Statement);\r
   }\r
 \r
   //\r
@@ -442,7 +351,7 @@ InitializeDisplayStatement (
   // Create the refresh guid hook event.\r
   // If the statement in this form has refresh event or refresh interval, browser will create this event for display engine.\r
   //\r
-  if ((!CompareGuid (&Statement->RefreshGuid, &gZeroGuid)) || (Statement->RefreshInterval != 0)) {\r
+  if ((!IsZeroGuid (&Statement->RefreshGuid)) || (Statement->RefreshInterval != 0)) {\r
     gDisplayFormData.FormRefreshEvent = mValueChangedEvent;\r
   }\r
 \r
@@ -453,19 +362,14 @@ InitializeDisplayStatement (
     DisplayStatement->PasswordCheck = PasswordCheck;\r
   }\r
 \r
-  //\r
-  // Save the validate check question for later use.\r
-  //\r
-  if (!IsListEmpty (&Statement->InconsistentListHead)) {\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
   //\r
-  if (Statement->InSubtitle) {\r
-    InsertTailList(&HostDisplayStatement->NestStatementList, &DisplayStatement->DisplayLink);\r
+  if (Statement->ParentStatement != NULL) {\r
+    ParentStatement = GetDisplayStatement(Statement->ParentStatement->OpCode);\r
+    ASSERT (ParentStatement != NULL);\r
+    InsertTailList(&ParentStatement->NestStatementList, &DisplayStatement->DisplayLink);\r
   } else {\r
     InsertTailList(&gDisplayFormData.StatementListHead, &DisplayStatement->DisplayLink);\r
   }\r
@@ -522,8 +426,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
@@ -531,6 +438,47 @@ UpdateHotkeyList (
   }\r
 }\r
 \r
+/**\r
+\r
+  Get the extra question attribute from override question list.\r
+\r
+  @param    QuestionId    The question id for this request question.\r
+\r
+  @retval   The attribute for this question or NULL if not found this\r
+            question in the list.\r
+\r
+**/\r
+UINT32\r
+ProcessQuestionExtraAttr (\r
+  IN   EFI_QUESTION_ID  QuestionId\r
+  )\r
+{\r
+  LIST_ENTRY                   *Link;\r
+  QUESTION_ATTRIBUTE_OVERRIDE  *QuestionDesc;\r
+\r
+  //\r
+  // Return HII_DISPLAY_NONE if input a invalid question id.\r
+  //\r
+  if (QuestionId == 0) {\r
+    return HII_DISPLAY_NONE;\r
+  }\r
+\r
+  Link = GetFirstNode (&mPrivateData.FormBrowserEx2.OverrideQestListHead);\r
+  while (!IsNull (&mPrivateData.FormBrowserEx2.OverrideQestListHead, Link)) {\r
+    QuestionDesc = FORM_QUESTION_ATTRIBUTE_OVERRIDE_FROM_LINK (Link);\r
+    Link = GetNextNode (&mPrivateData.FormBrowserEx2.OverrideQestListHead, Link);\r
+\r
+    if ((QuestionDesc->QuestionId == QuestionId) &&\r
+        (QuestionDesc->FormId     == gCurrentSelection->FormId) &&\r
+        (QuestionDesc->HiiHandle  == gCurrentSelection->Handle) &&\r
+        CompareGuid (&QuestionDesc->FormSetGuid, &gCurrentSelection->FormSetGuid)) {\r
+      return QuestionDesc->Attribute;\r
+    }\r
+  }\r
+\r
+  return HII_DISPLAY_NONE;\r
+}\r
+\r
 /**\r
 \r
   Enum all statement in current form, find all the statement can be display and\r
@@ -546,13 +494,12 @@ AddStatementToDisplayForm (
   LIST_ENTRY                    *Link;\r
   FORM_BROWSER_STATEMENT        *Statement;\r
   FORM_DISPLAY_ENGINE_STATEMENT *DisplayStatement;\r
-  FORM_DISPLAY_ENGINE_STATEMENT *HostDisplayStatement;\r
   UINT8                         MinRefreshInterval;\r
   EFI_EVENT                     RefreshIntervalEvent;\r
   FORM_BROWSER_REFRESH_EVENT_NODE *EventNode;\r
   BOOLEAN                       FormEditable;\r
+  UINT32                        ExtraAttribute;\r
 \r
-  HostDisplayStatement = NULL;\r
   MinRefreshInterval   = 0;\r
   FormEditable         = FALSE;\r
 \r
@@ -577,6 +524,21 @@ AddStatementToDisplayForm (
     InsertTailList(&gDisplayFormData.StatementListOSF, &DisplayStatement->DisplayLink);\r
   }\r
 \r
+  //\r
+  // treat formset as statement outside the form,get its opcode.\r
+  //\r
+  DisplayStatement = AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT));\r
+  ASSERT (DisplayStatement != NULL);\r
+\r
+  DisplayStatement->Signature = FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE;\r
+  DisplayStatement->Version   = FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1;\r
+  DisplayStatement->OpCode = gCurrentSelection->FormSet->OpCode;\r
+\r
+  InitializeListHead (&DisplayStatement->NestStatementList);\r
+  InitializeListHead (&DisplayStatement->OptionListHead);\r
+\r
+  InsertTailList(&gDisplayFormData.StatementListOSF, &DisplayStatement->DisplayLink);\r
+\r
   //\r
   // Process the statement in this form.\r
   //\r
@@ -592,21 +554,26 @@ AddStatementToDisplayForm (
       continue;\r
     }\r
 \r
+    //\r
+    // Check the extra attribute.\r
+    //\r
+    ExtraAttribute = ProcessQuestionExtraAttr (Statement->QuestionId);\r
+    if ((ExtraAttribute & HII_DISPLAY_SUPPRESS) != 0) {\r
+      continue;\r
+    }\r
+\r
     DisplayStatement = AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT));\r
     ASSERT (DisplayStatement != NULL);\r
 \r
     //\r
     // Initialize this statement and add it to the display form.\r
     //\r
-    InitializeDisplayStatement(DisplayStatement, Statement, HostDisplayStatement);\r
+    InitializeDisplayStatement(DisplayStatement, Statement);\r
 \r
     //\r
-    // Save the Host statement info.\r
-    // Host statement may has nest statement follow it.\r
+    // Set the extra attribute.\r
     //\r
-    if (!Statement->InSubtitle) {\r
-      HostDisplayStatement = DisplayStatement;\r
-    }\r
+    DisplayStatement->Attribute |= ExtraAttribute;\r
 \r
     if (Statement->Storage != NULL) {\r
       FormEditable = TRUE;\r
@@ -615,7 +582,7 @@ AddStatementToDisplayForm (
     //\r
     // Get the minimal refresh interval value for later use.\r
     //\r
-    if ((Statement->RefreshInterval != 0) && \r
+    if ((Statement->RefreshInterval != 0) &&\r
       (MinRefreshInterval == 0 || Statement->RefreshInterval < MinRefreshInterval)) {\r
       MinRefreshInterval = Statement->RefreshInterval;\r
     }\r
@@ -636,6 +603,16 @@ AddStatementToDisplayForm (
     InsertTailList(&mRefreshEventList, &EventNode->Link);\r
   }\r
 \r
+  //\r
+  // Create the refresh event process function for Form.\r
+  //\r
+  if (!IsZeroGuid (&gCurrentSelection->Form->RefreshGuid)) {\r
+    CreateRefreshEventForForm (gCurrentSelection->Form);\r
+    if (gDisplayFormData.FormRefreshEvent == NULL) {\r
+      gDisplayFormData.FormRefreshEvent = mValueChangedEvent;\r
+    }\r
+  }\r
+\r
   //\r
   // Update hotkey list field.\r
   //\r
@@ -666,7 +643,7 @@ UpdateDataChangedFlag (
 \r
   //\r
   // Base on the system level to check whether need to show the NV flag.\r
-  // \r
+  //\r
   switch (gBrowserSettingScope) {\r
   case SystemLevel:\r
     //\r
@@ -717,13 +694,13 @@ InitializeDisplayFormData (
   InitializeListHead (&gDisplayFormData.HotKeyListHead);\r
 \r
   Status = gBS->CreateEvent (\r
-        EVT_NOTIFY_WAIT, \r
+        EVT_NOTIFY_WAIT,\r
         TPL_CALLBACK,\r
-        SetupBrowserEmptyFunction,\r
+        EfiEventEmptyFunction,\r
         NULL,\r
         &mValueChangedEvent\r
         );\r
-  ASSERT_EFI_ERROR (Status); \r
+  ASSERT_EFI_ERROR (Status);\r
 }\r
 \r
 /**\r
@@ -773,12 +750,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
@@ -879,6 +850,106 @@ GetBrowserStatement (
   return NULL;\r
 }\r
 \r
+/**\r
+  Update the ValueChanged status for questions in this form.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   Form data structure.\r
+\r
+**/\r
+VOID\r
+UpdateStatementStatusForForm (\r
+  IN FORM_BROWSER_FORMSET             *FormSet,\r
+  IN FORM_BROWSER_FORM                *Form\r
+  )\r
+{\r
+  LIST_ENTRY                  *Link;\r
+  FORM_BROWSER_STATEMENT      *Question;\r
+\r
+  Link = GetFirstNode (&Form->StatementListHead);\r
+  while (!IsNull (&Form->StatementListHead, Link)) {\r
+    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
+\r
+/**\r
+  Update the ValueChanged status for questions in this formset.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+\r
+**/\r
+VOID\r
+UpdateStatementStatusForFormSet (\r
+  IN FORM_BROWSER_FORMSET                *FormSet\r
+  )\r
+{\r
+  LIST_ENTRY                  *Link;\r
+  FORM_BROWSER_FORM           *Form;\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
+    UpdateStatementStatusForForm (FormSet, Form);\r
+  }\r
+}\r
+\r
+/**\r
+  Update the ValueChanged status for questions.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   Form data structure.\r
+  @param  SettingScope           Setting Scope for Default action.\r
+\r
+**/\r
+VOID\r
+UpdateStatementStatus (\r
+  IN FORM_BROWSER_FORMSET             *FormSet,\r
+  IN FORM_BROWSER_FORM                *Form,\r
+  IN BROWSER_SETTING_SCOPE            SettingScope\r
+  )\r
+{\r
+  LIST_ENTRY                  *Link;\r
+  FORM_BROWSER_FORMSET        *LocalFormSet;\r
+\r
+  switch (SettingScope) {\r
+  case SystemLevel:\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
+      UpdateStatementStatusForFormSet (LocalFormSet);\r
+    }\r
+    break;\r
+\r
+  case FormSetLevel:\r
+    UpdateStatementStatusForFormSet (FormSet);\r
+    break;\r
+\r
+  case FormLevel:\r
+    UpdateStatementStatusForForm (FormSet, Form);\r
+    break;\r
+\r
+  default:\r
+    break;\r
+  }\r
+}\r
+\r
 /**\r
 \r
   Process the action request in user input.\r
@@ -889,14 +960,12 @@ GetBrowserStatement (
   @retval EFI_SUCESSS            This function always return successfully for now.\r
 \r
 **/\r
-EFI_STATUS \r
+EFI_STATUS\r
 ProcessAction (\r
   IN UINT32        Action,\r
   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
@@ -913,18 +982,17 @@ 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
-    gResetRequired = TRUE;\r
+    gResetRequiredFormLevel = TRUE;\r
+    gResetRequiredSystemLevel = TRUE;\r
   }\r
 \r
   if ((Action & BROWSER_ACTION_EXIT) == BROWSER_ACTION_EXIT) {\r
@@ -947,6 +1015,87 @@ ProcessAction (
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Check whether the formset guid is in this Hii package list.\r
+\r
+  @param  HiiHandle              The HiiHandle for this HII package list.\r
+  @param  FormSetGuid            The formset guid for the request formset.\r
+\r
+  @retval TRUE                   Find the formset guid.\r
+  @retval FALSE                  Not found the formset guid.\r
+\r
+**/\r
+BOOLEAN\r
+GetFormsetGuidFromHiiHandle (\r
+  IN EFI_HII_HANDLE       HiiHandle,\r
+  IN EFI_GUID             *FormSetGuid\r
+  )\r
+{\r
+  EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;\r
+  UINTN                        BufferSize;\r
+  UINT32                       Offset;\r
+  UINT32                       Offset2;\r
+  UINT32                       PackageListLength;\r
+  EFI_HII_PACKAGE_HEADER       PackageHeader;\r
+  UINT8                        *Package;\r
+  UINT8                        *OpCodeData;\r
+  EFI_STATUS                   Status;\r
+  BOOLEAN                      FindGuid;\r
+\r
+  BufferSize     = 0;\r
+  HiiPackageList = NULL;\r
+  FindGuid       = FALSE;\r
+\r
+  Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    HiiPackageList = AllocatePool (BufferSize);\r
+    ASSERT (HiiPackageList != NULL);\r
+\r
+    Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
+  }\r
+  if (EFI_ERROR (Status) || HiiPackageList == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Get Form package from this HII package List\r
+  //\r
+  Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+  Offset2 = 0;\r
+  CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
+\r
+  while (Offset < PackageListLength) {\r
+    Package = ((UINT8 *) HiiPackageList) + Offset;\r
+    CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
+    Offset += PackageHeader.Length;\r
+\r
+    if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
+      //\r
+      // Search FormSet in this Form Package\r
+      //\r
+      Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
+      while (Offset2 < PackageHeader.Length) {\r
+        OpCodeData = Package + Offset2;\r
+\r
+        if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
+          if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))){\r
+            FindGuid = TRUE;\r
+            break;\r
+          }\r
+        }\r
+\r
+        Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
+      }\r
+    }\r
+    if (FindGuid) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  FreePool (HiiPackageList);\r
+\r
+  return FindGuid;\r
+}\r
 \r
 /**\r
   Find HII Handle in the HII database associated with given Device Path.\r
@@ -955,6 +1104,7 @@ ProcessAction (
 \r
   @param  DevicePath             Device Path associated with the HII package list\r
                                  handle.\r
+  @param  FormsetGuid            The formset guid for this formset.\r
 \r
   @retval Handle                 HII package list Handle associated with the Device\r
                                         Path.\r
@@ -962,15 +1112,13 @@ ProcessAction (
 \r
 **/\r
 EFI_HII_HANDLE\r
-EFIAPI\r
 DevicePathToHiiHandle (\r
-  IN EFI_DEVICE_PATH_PROTOCOL   *DevicePath\r
+  IN EFI_DEVICE_PATH_PROTOCOL   *DevicePath,\r
+  IN EFI_GUID                   *FormsetGuid\r
   )\r
 {\r
   EFI_STATUS                  Status;\r
   EFI_DEVICE_PATH_PROTOCOL    *TmpDevicePath;\r
-  UINTN                       BufferSize;\r
-  UINTN                       HandleCount;\r
   UINTN                       Index;\r
   EFI_HANDLE                  Handle;\r
   EFI_HANDLE                  DriverHandle;\r
@@ -995,32 +1143,8 @@ DevicePathToHiiHandle (
   //\r
   // Retrieve all HII Handles from HII database\r
   //\r
-  BufferSize = 0x1000;\r
-  HiiHandles = AllocatePool (BufferSize);\r
-  ASSERT (HiiHandles != NULL);\r
-  Status = mHiiDatabase->ListPackageLists (\r
-                           mHiiDatabase,\r
-                           EFI_HII_PACKAGE_TYPE_ALL,\r
-                           NULL,\r
-                           &BufferSize,\r
-                           HiiHandles\r
-                           );\r
-  if (Status == EFI_BUFFER_TOO_SMALL) {\r
-    FreePool (HiiHandles);\r
-    HiiHandles = AllocatePool (BufferSize);\r
-    ASSERT (HiiHandles != NULL);\r
-\r
-    Status = mHiiDatabase->ListPackageLists (\r
-                             mHiiDatabase,\r
-                             EFI_HII_PACKAGE_TYPE_ALL,\r
-                             NULL,\r
-                             &BufferSize,\r
-                             HiiHandles\r
-                             );\r
-  }\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    FreePool (HiiHandles);\r
+  HiiHandles = HiiGetHiiHandles (NULL);\r
+  if (HiiHandles == NULL) {\r
     return NULL;\r
   }\r
 \r
@@ -1028,16 +1152,21 @@ DevicePathToHiiHandle (
   // Search Hii Handle by Driver Handle\r
   //\r
   HiiHandle = NULL;\r
-  HandleCount = BufferSize / sizeof (EFI_HII_HANDLE);\r
-  for (Index = 0; Index < HandleCount; Index++) {\r
+  for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
     Status = mHiiDatabase->GetPackageListHandle (\r
                              mHiiDatabase,\r
                              HiiHandles[Index],\r
                              &Handle\r
                              );\r
     if (!EFI_ERROR (Status) && (Handle == DriverHandle)) {\r
-      HiiHandle = HiiHandles[Index];\r
-      break;\r
+      if (GetFormsetGuidFromHiiHandle(HiiHandles[Index], FormsetGuid)) {\r
+        HiiHandle = HiiHandles[Index];\r
+        break;\r
+      }\r
+\r
+      if (HiiHandle != NULL) {\r
+        break;\r
+      }\r
     }\r
   }\r
 \r
@@ -1064,17 +1193,8 @@ FormSetGuidToHiiHandle (
   )\r
 {\r
   EFI_HII_HANDLE               *HiiHandles;\r
-  UINTN                        Index;\r
-  EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;\r
-  UINTN                        BufferSize;\r
-  UINT32                       Offset;\r
-  UINT32                       Offset2;\r
-  UINT32                       PackageListLength;\r
-  EFI_HII_PACKAGE_HEADER       PackageHeader;\r
-  UINT8                        *Package;\r
-  UINT8                        *OpCodeData;\r
-  EFI_STATUS                   Status;\r
   EFI_HII_HANDLE               HiiHandle;\r
+  UINTN                        Index;\r
 \r
   ASSERT (ComparingGuid != NULL);\r
 \r
@@ -1089,61 +1209,14 @@ FormSetGuidToHiiHandle (
   // Search for formset of each class type\r
   //\r
   for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
-    BufferSize = 0;\r
-    HiiPackageList = NULL;\r
-    Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, HiiHandles[Index], &BufferSize, HiiPackageList);\r
-    if (Status == EFI_BUFFER_TOO_SMALL) {\r
-      HiiPackageList = AllocatePool (BufferSize);\r
-      ASSERT (HiiPackageList != NULL);\r
-\r
-      Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, HiiHandles[Index], &BufferSize, HiiPackageList);\r
-    }\r
-    if (EFI_ERROR (Status) || HiiPackageList == NULL) {\r
-      return NULL;\r
+    if (GetFormsetGuidFromHiiHandle(HiiHandles[Index], ComparingGuid)) {\r
+      HiiHandle = HiiHandles[Index];\r
+      break;\r
     }\r
 \r
-    //\r
-    // Get Form package from this HII package List\r
-    //\r
-    Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
-    Offset2 = 0;\r
-    CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32)); \r
-\r
-    while (Offset < PackageListLength) {\r
-      Package = ((UINT8 *) HiiPackageList) + Offset;\r
-      CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
-\r
-      if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
-        //\r
-        // Search FormSet in this Form Package\r
-        //\r
-        Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
-        while (Offset2 < PackageHeader.Length) {\r
-          OpCodeData = Package + Offset2;\r
-\r
-          if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
-            //\r
-            // Try to compare against formset GUID\r
-            //\r
-            if (CompareGuid (ComparingGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
-              HiiHandle = HiiHandles[Index];\r
-              break;\r
-            }\r
-          }\r
-\r
-          Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
-        }\r
-      }\r
-      if (HiiHandle != NULL) {\r
-        break;\r
-      }\r
-      Offset += PackageHeader.Length;\r
+    if (HiiHandle != NULL) {\r
+      break;\r
     }\r
-    \r
-    FreePool (HiiPackageList);\r
-       if (HiiHandle != NULL) {\r
-               break;\r
-       }\r
   }\r
 \r
   FreePool (HiiHandles);\r
@@ -1170,16 +1243,20 @@ 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
     case BROWSER_ACTION_DISCARD:\r
       DiscardForm (Selection->FormSet, Selection->Form, Scope);\r
       break;\r
-  \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
@@ -1213,15 +1290,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
@@ -1256,7 +1325,7 @@ ProcessGotoOpCode (
   FORM_BROWSER_FORM               *RefForm;\r
   EFI_STATUS                      Status;\r
   EFI_HII_HANDLE                  HiiHandle;\r
-  \r
+\r
   Status    = EFI_SUCCESS;\r
   StringPtr = NULL;\r
   HiiHandle = NULL;\r
@@ -1271,7 +1340,7 @@ ProcessGotoOpCode (
   //\r
   // Check whether the device path string is a valid string.\r
   //\r
-  if (Statement->HiiValue.Value.ref.DevicePath != 0 && StringPtr != NULL) {\r
+  if (Statement->HiiValue.Value.ref.DevicePath != 0 && StringPtr != NULL && StringPtr[0] != L'\0') {\r
     if (Selection->Form->ModalForm) {\r
       return Status;\r
     }\r
@@ -1282,7 +1351,7 @@ ProcessGotoOpCode (
     if (mPathFromText != NULL) {\r
       DevicePath = mPathFromText->ConvertTextToDevicePath(StringPtr);\r
       if (DevicePath != NULL) {\r
-        HiiHandle = DevicePathToHiiHandle (DevicePath);\r
+        HiiHandle = DevicePathToHiiHandle (DevicePath, &Statement->HiiValue.Value.ref.FormSetGuid);\r
         FreePool (DevicePath);\r
       }\r
       FreePool (StringPtr);\r
@@ -1290,7 +1359,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
@@ -1320,7 +1389,7 @@ ProcessGotoOpCode (
     CopyMem (&Selection->FormSetGuid,&Statement->HiiValue.Value.ref.FormSetGuid, sizeof (EFI_GUID));\r
     Selection->FormId = Statement->HiiValue.Value.ref.FormId;\r
     Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;\r
-  } else if (!CompareGuid (&Statement->HiiValue.Value.ref.FormSetGuid, &gZeroGuid)) {\r
+  } else if (!IsZeroGuid (&Statement->HiiValue.Value.ref.FormSetGuid)) {\r
     if (Selection->Form->ModalForm) {\r
       return Status;\r
     }\r
@@ -1365,9 +1434,9 @@ ProcessGotoOpCode (
     if ((RefForm != NULL) && (RefForm->SuppressExpression != NULL)) {\r
       if (EvaluateExpressionList(RefForm->SuppressExpression, TRUE, Selection->FormSet, RefForm) != ExpressFalse) {\r
         //\r
-        // Form is suppressed. \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
@@ -1401,7 +1470,6 @@ ProcessQuestionConfig (
   EFI_STATUS                      Status;\r
   CHAR16                          *ConfigResp;\r
   CHAR16                          *Progress;\r
-  EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;\r
 \r
   if (Question->QuestionConfig == 0) {\r
     return EFI_SUCCESS;\r
@@ -1413,17 +1481,15 @@ 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
   // Send config to Configuration Driver\r
   //\r
-  ConfigAccess = Selection->FormSet->ConfigAccess;\r
-  if (ConfigAccess == NULL) {\r
-    return EFI_UNSUPPORTED;\r
-  }\r
-  Status = ConfigAccess->RouteConfig (\r
-                           ConfigAccess,\r
+  Status = mHiiConfigRouting->RouteConfig (\r
+                           mHiiConfigRouting,\r
                            ConfigResp,\r
                            &Progress\r
                            );\r
@@ -1436,21 +1502,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
@@ -1461,79 +1526,53 @@ 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
       break;\r
-    \r
+\r
     case EFI_IFR_ACTION_OP:\r
       //\r
       // Process the Config string <ConfigResp>\r
       //\r
       Status = ProcessQuestionConfig (gCurrentSelection, Statement);\r
       break;\r
-    \r
+\r
     case EFI_IFR_RESET_BUTTON_OP:\r
       //\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
     default:\r
@@ -1556,6 +1595,7 @@ ProcessUserInput (
         DeleteString(Statement->HiiValue.Value.string, gCurrentSelection->FormSet->HiiHandle);\r
         Statement->HiiValue.Value.string = UserInput->InputValue.Value.string;\r
         CopyMem (Statement->BufferValue, UserInput->InputValue.Buffer, (UINTN) UserInput->InputValue.BufferLen);\r
+        ZeroMem (UserInput->InputValue.Buffer, (UINTN) UserInput->InputValue.BufferLen);\r
         FreePool (UserInput->InputValue.Buffer);\r
         //\r
         // Two password match, send it to Configuration Driver\r
@@ -1580,9 +1620,6 @@ ProcessUserInput (
         CopyMem (&Statement->HiiValue, &UserInput->InputValue, sizeof (EFI_HII_VALUE));\r
         break;\r
       }\r
-      if (Statement->Operand != EFI_IFR_PASSWORD_OP) {\r
-        SetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithEditBuffer);\r
-      }\r
       break;\r
     }\r
   }\r
@@ -1605,7 +1642,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
@@ -1621,11 +1657,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
@@ -1633,9 +1672,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
@@ -1643,33 +1679,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
@@ -1781,70 +1799,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
@@ -1852,48 +1806,33 @@ IsStorageDataChangedForFormSet (
                          about the Selection, form and formset to be displayed.\r
                          On output, Selection return the screen item that is selected\r
                          by user.\r
-  @param SettingLevel    Input Settting level, if it is FormLevel, just exit current form. \r
+  @param SettingLevel    Input Settting level, if it is FormLevel, just exit current form.\r
                          else, we need to exit current formset.\r
-  \r
+\r
   @retval TRUE           Exit current form.\r
   @retval FALSE          User press ESC and keep in current form.\r
 **/\r
 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
   FORM_ENTRY_INFO            *ParentMenu;\r
   BROWSER_SETTING_SCOPE      Scope;\r
-  \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
@@ -1904,7 +1843,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
@@ -1941,6 +1880,30 @@ FindNextMenu (
   return TRUE;\r
 }\r
 \r
+/**\r
+  Reconnect the controller.\r
+\r
+  @param DriverHandle          The controller handle which need to be reconnect.\r
+\r
+  @retval   TRUE     do the reconnect behavior success.\r
+  @retval   FALSE    do the reconnect behavior failed.\r
+\r
+**/\r
+BOOLEAN\r
+ReconnectController (\r
+  IN EFI_HANDLE   DriverHandle\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+\r
+  Status = gBS->DisconnectController(DriverHandle, NULL, NULL);\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = gBS->ConnectController(DriverHandle, NULL, NULL, TRUE);\r
+  }\r
+\r
+  return Status == EFI_SUCCESS;\r
+}\r
+\r
 /**\r
   Call the call back function for the question and process the return action.\r
 \r
@@ -1948,22 +1911,27 @@ FindNextMenu (
                                about the Selection, form and formset to be displayed.\r
                                On output, Selection return the screen item that is selected\r
                                by user.\r
+  @param FormSet               The formset this question belong to.\r
+  @param Form                  The form this question belong to.\r
   @param Question              The Question which need to call.\r
   @param Action                The action request.\r
   @param SkipSaveOrDiscard     Whether skip save or discard action.\r
 \r
-  @retval EFI_SUCCESS          The call back function excutes successfully.\r
-  @return Other value if the call back function failed to excute.  \r
+  @retval EFI_SUCCESS          The call back function executes successfully.\r
+  @return Other value if the call back function failed to execute.\r
 **/\r
-EFI_STATUS \r
+EFI_STATUS\r
 ProcessCallBackFunction (\r
   IN OUT UI_MENU_SELECTION               *Selection,\r
+  IN     FORM_BROWSER_FORMSET            *FormSet,\r
+  IN     FORM_BROWSER_FORM               *Form,\r
   IN     FORM_BROWSER_STATEMENT          *Question,\r
   IN     EFI_BROWSER_ACTION              Action,\r
   IN     BOOLEAN                         SkipSaveOrDiscard\r
   )\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
@@ -1974,23 +1942,27 @@ ProcessCallBackFunction (
   BOOLEAN                         NeedExit;\r
   LIST_ENTRY                      *Link;\r
   BROWSER_SETTING_SCOPE           SettingLevel;\r
+  EFI_IFR_TYPE_VALUE              BackUpValue;\r
+  UINT8                           *BackUpBuffer;\r
+  CHAR16                          *NewString;\r
 \r
-  ConfigAccess = Selection->FormSet->ConfigAccess;\r
+  ConfigAccess = FormSet->ConfigAccess;\r
   SubmitFormIsRequired  = FALSE;\r
   SettingLevel          = FormSetLevel;\r
   DiscardFormIsRequired = FALSE;\r
   NeedExit              = FALSE;\r
   Status                = EFI_SUCCESS;\r
   ActionRequest         = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+  BackUpBuffer          = NULL;\r
 \r
   if (ConfigAccess == NULL) {\r
     return EFI_SUCCESS;\r
   }\r
 \r
-  Link = GetFirstNode (&Selection->Form->StatementListHead);\r
-  while (!IsNull (&Selection->Form->StatementListHead, Link)) {\r
+  Link = GetFirstNode (&Form->StatementListHead);\r
+  while (!IsNull (&Form->StatementListHead, Link)) {\r
     Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
-    Link = GetNextNode (&Selection->Form->StatementListHead, Link);\r
+    Link = GetNextNode (&Form->StatementListHead, Link);\r
 \r
     //\r
     // if Question != NULL, only process the question. Else, process all question in this form.\r
@@ -1998,7 +1970,7 @@ ProcessCallBackFunction (
     if ((Question != NULL) && (Statement != Question)) {\r
       continue;\r
     }\r
-    \r
+\r
     if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) {\r
       continue;\r
     }\r
@@ -2007,7 +1979,7 @@ ProcessCallBackFunction (
     // Check whether Statement is disabled.\r
     //\r
     if (Statement->Expression != NULL) {\r
-      if (EvaluateExpressionList(Statement->Expression, TRUE, Selection->FormSet, Selection->Form) == ExpressDisable) {\r
+      if (EvaluateExpressionList(Statement->Expression, TRUE, FormSet, Form) == ExpressDisable) {\r
         continue;\r
       }\r
     }\r
@@ -2020,7 +1992,19 @@ ProcessCallBackFunction (
       //\r
       TypeValue = (EFI_IFR_TYPE_VALUE *) Statement->BufferValue;\r
     }\r
-      \r
+\r
+    //\r
+    // If EFI_BROWSER_ACTION_CHANGING type, back up the new question value.\r
+    //\r
+    if (Action == EFI_BROWSER_ACTION_CHANGING) {\r
+      if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
+        BackUpBuffer = AllocateCopyPool(Statement->StorageWidth, Statement->BufferValue);\r
+        ASSERT (BackUpBuffer != NULL);\r
+      } else {\r
+        CopyMem (&BackUpValue, &HiiValue->Value, sizeof (EFI_IFR_TYPE_VALUE));\r
+      }\r
+    }\r
+\r
     ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
     Status = ConfigAccess->Callback (\r
                              ConfigAccess,\r
@@ -2031,14 +2015,33 @@ 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
+          ZeroMem (Statement->BufferValue, 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
-          gResetRequired = TRUE;\r
+          gResetRequiredFormLevel = TRUE;\r
+          gResetRequiredSystemLevel = TRUE;\r
           NeedExit              = TRUE;\r
           break;\r
 \r
@@ -2074,25 +2077,86 @@ ProcessCallBackFunction (
           SettingLevel          = FormLevel;\r
           break;\r
 \r
+        case EFI_BROWSER_ACTION_REQUEST_RECONNECT:\r
+          gCallbackReconnect    = TRUE;\r
+          break;\r
+\r
         default:\r
           break;\r
         }\r
-      }\r
+        break;\r
+\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
+          //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
+          //\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
-      // According the spec, return value from call back of "changing" and \r
-      // "retrieve" should update to the question's temp buffer.\r
+      // If the callback returns EFI_UNSUPPORTED for EFI_BROWSER_ACTION_CHANGING,\r
+      // then the browser will use the value passed to Callback() and ignore the\r
+      // value returned by Callback().\r
       //\r
-      if (Action == EFI_BROWSER_ACTION_CHANGING || Action == EFI_BROWSER_ACTION_RETRIEVE) {\r
-        SetQuestionValue(Selection->FormSet, Selection->Form, Statement, GetSetValueWithEditBuffer);\r
+      if (Action  == EFI_BROWSER_ACTION_CHANGING && Status == EFI_UNSUPPORTED) {\r
+        if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
+          CopyMem (Statement->BufferValue, BackUpBuffer, Statement->StorageWidth);\r
+        } else {\r
+          CopyMem (&HiiValue->Value, &BackUpValue, sizeof (EFI_IFR_TYPE_VALUE));\r
+        }\r
+\r
+        //\r
+        // Do the question validation.\r
+        //\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
-    } else {\r
+\r
       //\r
-      // According the spec, return fail from call back of "changing" and \r
+      // 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 || Action == EFI_BROWSER_ACTION_RETRIEVE) {\r
-        GetQuestionValue(Selection->FormSet, Selection->Form, Statement, GetSetValueWithEditBuffer);\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
       if (Status == EFI_UNSUPPORTED) {\r
@@ -2102,14 +2166,49 @@ ProcessCallBackFunction (
         Status = EFI_SUCCESS;\r
       }\r
     }\r
+\r
+    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 (gCallbackReconnect && (EFI_BROWSER_ACTION_CHANGED == Action)) {\r
+    //\r
+    // Confirm changes with user first.\r
+    //\r
+    if (IsNvUpdateRequiredForFormSet(FormSet)) {\r
+      if (BROWSER_ACTION_DISCARD == PopupErrorMessage(BROWSER_RECONNECT_SAVE_CHANGES, NULL, NULL, NULL)) {\r
+        gCallbackReconnect = FALSE;\r
+        DiscardFormIsRequired = TRUE;\r
+      } else {\r
+        SubmitFormIsRequired = TRUE;\r
+      }\r
+    } else {\r
+      PopupErrorMessage(BROWSER_RECONNECT_REQUIRED, NULL, NULL, NULL);\r
+    }\r
+\r
+    //\r
+    // Exit current formset before do the reconnect.\r
+    //\r
+    NeedExit = TRUE;\r
+    SettingLevel = FormSetLevel;\r
   }\r
 \r
   if (SubmitFormIsRequired && !SkipSaveOrDiscard) {\r
-    SubmitForm (Selection->FormSet, Selection->Form, SettingLevel);\r
+    SubmitForm (FormSet, Form, SettingLevel);\r
   }\r
 \r
   if (DiscardFormIsRequired && !SkipSaveOrDiscard) {\r
-    DiscardForm (Selection->FormSet, Selection->Form, SettingLevel);\r
+    DiscardForm (FormSet, Form, SettingLevel);\r
   }\r
 \r
   if (NeedExit) {\r
@@ -2121,31 +2220,34 @@ ProcessCallBackFunction (
 \r
 /**\r
   Call the retrieve type call back function for one question to get the initialize data.\r
-  \r
-  This function only used when in the initialize stage, because in this stage, the \r
+\r
+  This function only used when in the initialize stage, because in this stage, the\r
   Selection->Form is not ready. For other case, use the ProcessCallBackFunction instead.\r
 \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
+  @retval EFI_SUCCESS          The call back function executes successfully.\r
+  @return Other value if the call back function failed to execute.\r
 **/\r
-EFI_STATUS \r
+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
@@ -2157,7 +2259,7 @@ ProcessRetrieveForQuestion (
     //\r
     TypeValue = (EFI_IFR_TYPE_VALUE *) Statement->BufferValue;\r
   }\r
-    \r
+\r
   ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
   Status = ConfigAccess->Callback (\r
                            ConfigAccess,\r
@@ -2167,6 +2269,20 @@ 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
+      ZeroMem (Statement->BufferValue, 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
@@ -2227,8 +2343,16 @@ SetupBrowser (
   mCurFakeQestId = 0;\r
 \r
   do {\r
+\r
+    //\r
+    // Reset Status to prevent the next break from returning incorrect error status.\r
+    //\r
+    Status = EFI_SUCCESS;\r
+\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
@@ -2265,9 +2389,9 @@ SetupBrowser (
     if (Selection->Form->SuppressExpression != NULL) {\r
       if (EvaluateExpressionList(Selection->Form->SuppressExpression, TRUE, Selection->FormSet, Selection->Form) == ExpressSuppress) {\r
         //\r
-        // Form is suppressed. \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
@@ -2278,10 +2402,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
@@ -2289,18 +2417,20 @@ SetupBrowser (
       CopyGuid (&mCurrentFormSetGuid, &Selection->FormSetGuid);\r
       mCurrentFormId      = Selection->FormId;\r
 \r
-      Status = ProcessCallBackFunction (Selection, 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
@@ -2312,13 +2442,27 @@ SetupBrowser (
       goto Done;\r
     }\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 (!mFinishRetrieveCall) {\r
+      //\r
+      // Finish call RETRIEVE callback for this form.\r
+      //\r
+      mFinishRetrieveCall = TRUE;\r
+\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
@@ -2334,10 +2478,10 @@ SetupBrowser (
     //\r
     Statement = Selection->Statement;\r
     if (Statement != NULL) {\r
-      if ((ConfigAccess != NULL) && \r
-          ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) && \r
+      if ((ConfigAccess != NULL) &&\r
+          ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) &&\r
           (Statement->Operand != EFI_IFR_PASSWORD_OP)) {\r
-        Status = ProcessCallBackFunction(Selection, Statement, EFI_BROWSER_ACTION_CHANGING, FALSE);\r
+        Status = ProcessCallBackFunction(Selection, Selection->FormSet, Selection->Form, Statement, EFI_BROWSER_ACTION_CHANGING, FALSE);\r
         if (Statement->Operand == EFI_IFR_REF_OP) {\r
           //\r
           // Process dynamic update ref opcode.\r
@@ -2345,21 +2489,63 @@ SetupBrowser (
           if (!EFI_ERROR (Status)) {\r
             Status = ProcessGotoOpCode(Statement, Selection);\r
           }\r
-          \r
+\r
           //\r
           // Callback return error status or status return from process goto opcode.\r
           //\r
           if (EFI_ERROR (Status)) {\r
             //\r
-            // Cross reference will not be taken\r
+            // Cross reference will not be taken, restore all essential field\r
             //\r
-            Selection->FormId = Selection->Form->FormId;\r
+            Selection->Handle = mCurrentHiiHandle;\r
+            CopyMem (&Selection->FormSetGuid, &mCurrentFormSetGuid, sizeof (EFI_GUID));\r
+            Selection->FormId = mCurrentFormId;\r
             Selection->QuestionId = 0;\r
+            Selection->Action = UI_ACTION_REFRESH_FORM;\r
           }\r
         }\r
 \r
-        if (!EFI_ERROR (Status) && Statement->Operand != EFI_IFR_REF_OP) {\r
-          ProcessCallBackFunction(Selection, Statement, EFI_BROWSER_ACTION_CHANGED, FALSE);\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
+          //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
+        // 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
+      // If question has EFI_IFR_FLAG_RESET_REQUIRED/EFI_IFR_FLAG_RECONNECT_REQUIRED flag and without storage\r
+      // and process question success till here, trig the gResetFlag/gFlagReconnect.\r
+      //\r
+      if ((Status == EFI_SUCCESS) &&\r
+          (Statement->Storage == NULL)) {\r
+        if ((Statement->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) != 0) {\r
+          gResetRequiredFormLevel = TRUE;\r
+          gResetRequiredSystemLevel = TRUE;\r
+        }\r
+\r
+        if ((Statement->QuestionFlags & EFI_IFR_FLAG_RECONNECT_REQUIRED) != 0) {\r
+          gFlagReconnect = TRUE;\r
         }\r
       }\r
     }\r
@@ -2389,13 +2575,13 @@ SetupBrowser (
     // Before exit the form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_CLOSE\r
     // for each question with callback flag.\r
     //\r
-    if ((ConfigAccess != NULL) && \r
-        ((Selection->Action == UI_ACTION_EXIT) || \r
+    if ((ConfigAccess != NULL) &&\r
+        ((Selection->Action == UI_ACTION_EXIT) ||\r
          (Selection->Handle != mCurrentHiiHandle) ||\r
          (!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid)) ||\r
          (Selection->FormId != mCurrentFormId))) {\r
 \r
-      Status = ProcessCallBackFunction (Selection, NULL, EFI_BROWSER_ACTION_FORM_CLOSE, FALSE);\r
+      Status = ProcessCallBackFunction (Selection, Selection->FormSet, Selection->Form, NULL, EFI_BROWSER_ACTION_FORM_CLOSE, FALSE);\r
       if (EFI_ERROR (Status)) {\r
         goto Done;\r
       }\r