]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
Fix GCC build fail.
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Presentation.c
index a5caf4426cc50289d03b576e4083f8c4a4bf8aae..bad8b7b122ea72d567fc27a599c659ef607bb2f9 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
 Utility functions for UI presentation.\r
 \r
-Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2004 - 2014, 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
@@ -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
@@ -160,7 +159,7 @@ UpdateStatement (
   //\r
   // Question value may be changed, need invoke its Callback()\r
   //\r
-  ProcessCallBackFunction (gCurrentSelection, Statement, EFI_BROWSER_ACTION_CHANGING, FALSE);\r
+  ProcessCallBackFunction (gCurrentSelection, gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, EFI_BROWSER_ACTION_RETRIEVE, FALSE);\r
   \r
   if (mHiiPackageListUpdated) {\r
     //\r
@@ -225,180 +224,23 @@ 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
 \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
@@ -491,19 +333,14 @@ 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
   //\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
@@ -569,6 +406,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
@@ -584,13 +462,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
@@ -630,21 +507,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
@@ -811,12 +693,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
@@ -917,6 +793,99 @@ 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
+    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
@@ -952,12 +921,13 @@ ProcessAction (
 \r
   if ((Action & BROWSER_ACTION_DEFAULT) == BROWSER_ACTION_DEFAULT) {\r
     ExtractDefault (gCurrentSelection->FormSet, gCurrentSelection->Form, DefaultId, gBrowserSettingScope, GetDefaultForAll, NULL, 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
+      PopupErrorMessage(BROWSER_SUBMIT_FAIL, NULL, NULL);\r
     }\r
   }\r
 \r
@@ -985,6 +955,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
@@ -993,6 +1044,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
@@ -1000,15 +1052,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
@@ -1033,32 +1083,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
@@ -1066,16 +1092,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
@@ -1102,17 +1133,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
@@ -1127,61 +1149,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
@@ -1309,7 +1284,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
@@ -1320,7 +1295,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
@@ -1328,7 +1303,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);\r
       FreePool (StringPtr);\r
       return Status;\r
     }\r
@@ -1405,7 +1380,7 @@ ProcessGotoOpCode (
         //\r
         // Form is suppressed. \r
         //\r
-        gBrowserStatus = BROWSER_FORM_SUPPRESS;\r
+        PopupErrorMessage(BROWSER_FORM_SUPPRESS, NULL, NULL);\r
         return EFI_SUCCESS;\r
       }\r
     }\r
@@ -1439,7 +1414,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
@@ -1456,12 +1430,8 @@ ProcessQuestionConfig (
   //\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
@@ -1572,6 +1542,7 @@ ProcessUserInput (
       // Reset Question to default value specified by DefaultId\r
       //\r
       Status = ExtractDefault (gCurrentSelection->FormSet, NULL, Statement->DefaultId, FormSetLevel, GetDefaultForAll, NULL, FALSE);\r
+      UpdateStatementStatus (gCurrentSelection->FormSet, NULL, FormSetLevel);\r
       break;\r
 \r
     default:\r
@@ -1618,9 +1589,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
@@ -1819,70 +1787,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
@@ -1986,6 +1890,8 @@ 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
@@ -1996,6 +1902,8 @@ FindNextMenu (
 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
@@ -2012,23 +1920,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
@@ -2045,7 +1957,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
@@ -2058,7 +1970,18 @@ 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 + sizeof(CHAR16), Statement->BufferValue);\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
@@ -2069,10 +1992,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
@@ -2115,22 +2055,62 @@ ProcessCallBackFunction (
         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
+          // 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 + sizeof(CHAR16));\r
+        } else {\r
+          CopyMem (&HiiValue->Value, &BackUpValue, sizeof (EFI_IFR_TYPE_VALUE));\r
+        }\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
-    } else {\r
+\r
       //\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
+           Action == EFI_BROWSER_ACTION_RETRIEVE) {\r
+        GetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
       }\r
 \r
       if (Status == EFI_UNSUPPORTED) {\r
@@ -2140,14 +2120,18 @@ ProcessCallBackFunction (
         Status = EFI_SUCCESS;\r
       }\r
     }\r
+\r
+    if (BackUpBuffer != NULL) {\r
+      FreePool (BackUpBuffer);\r
+    }\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
@@ -2165,6 +2149,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
@@ -2172,18 +2157,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
@@ -2205,6 +2192,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
@@ -2305,7 +2305,7 @@ SetupBrowser (
         //\r
         // Form is suppressed. \r
         //\r
-        gBrowserStatus = BROWSER_FORM_SUPPRESS;\r
+        PopupErrorMessage(BROWSER_FORM_SUPPRESS, NULL, NULL);\r
         Status = EFI_NOT_FOUND;\r
         goto Done;\r
       }\r
@@ -2316,10 +2316,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
@@ -2327,18 +2331,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 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
@@ -2350,13 +2356,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
@@ -2375,7 +2395,7 @@ SetupBrowser (
       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
@@ -2396,10 +2416,37 @@ SetupBrowser (
           }\r
         }\r
 \r
+        //\r
+        // Verify whether question value has checked, update the ValueChanged flag in Question.\r
+        //\r
+        IsQuestionValueChanged(gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithBuffer);\r
+\r
         if (!EFI_ERROR (Status) && Statement->Operand != EFI_IFR_REF_OP) {\r
-          ProcessCallBackFunction(Selection, Statement, EFI_BROWSER_ACTION_CHANGED, FALSE);\r
+          ProcessCallBackFunction(Selection, Selection->FormSet, Selection->Form, Statement, EFI_BROWSER_ACTION_CHANGED, FALSE);\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 flag and without storage and process question success till here, \r
+      // trig the gResetFlag.\r
+      //\r
+      if ((Status == EFI_SUCCESS) && \r
+          (Statement->Storage == NULL) && \r
+          ((Statement->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) != 0)) {\r
+        gResetRequired = TRUE;\r
+      }\r
     }\r
 \r
     //\r
@@ -2433,7 +2480,7 @@ SetupBrowser (
          (!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