]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Setup.c
index 05e690527daf03ff642ba52adb3bb893424b2d10..5158baf5bd55e9cd9c87c7c7744aed4aee012e3f 100644 (file)
@@ -1,20 +1,13 @@
 /** @file\r
 Entry and initialization module for the browser.\r
 \r
-Copyright (c) 2007 - 2009, Intel Corporation\r
-All rights reserved. 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) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
+(C) Copyright 2020 - 2022 Hewlett Packard Enterprise Development LP<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
 #include "Setup.h"\r
-#include "Ui.h"\r
-\r
 \r
 SETUP_DRIVER_PRIVATE_DATA  mPrivateData = {\r
   SETUP_DRIVER_SIGNATURE,\r
@@ -22,158 +15,428 @@ SETUP_DRIVER_PRIVATE_DATA  mPrivateData = {
   {\r
     SendForm,\r
     BrowserCallback\r
+  },\r
+  {\r
+    SetScope,\r
+    RegisterHotKey,\r
+    RegiserExitHandler,\r
+    SaveReminder\r
+  },\r
+  {\r
+    BROWSER_EXTENSION2_VERSION_1_1,\r
+    SetScope,\r
+    RegisterHotKey,\r
+    RegiserExitHandler,\r
+    IsBrowserDataModified,\r
+    ExecuteAction,\r
+    { NULL,                        NULL  },\r
+    { NULL,                        NULL  },\r
+    IsResetRequired\r
   }\r
 };\r
 \r
-EFI_HII_DATABASE_PROTOCOL         *mHiiDatabase;\r
-EFI_HII_STRING_PROTOCOL           *mHiiString;\r
-EFI_HII_CONFIG_ROUTING_PROTOCOL   *mHiiConfigRouting;\r
-\r
-UINTN           gBrowserContextCount = 0;\r
-LIST_ENTRY      gBrowserContextList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserContextList);\r
-\r
-BANNER_DATA           *gBannerData;\r
-EFI_HII_HANDLE        gFrontPageHandle;\r
-UINTN                 gClassOfVfr;\r
-UINTN                 gFunctionKeySetting;\r
-BOOLEAN               gResetRequired;\r
-BOOLEAN               gNvUpdateRequired;\r
-EFI_HII_HANDLE        gHiiHandle;\r
-UINT16                gDirection;\r
-EFI_SCREEN_DESCRIPTOR gScreenDimensions;\r
+EFI_HII_DATABASE_PROTOCOL           *mHiiDatabase;\r
+EFI_HII_CONFIG_ROUTING_PROTOCOL     *mHiiConfigRouting;\r
+EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL  *mPathFromText;\r
+EDKII_FORM_DISPLAY_ENGINE_PROTOCOL  *mFormDisplay;\r
+\r
+UINTN       gBrowserContextCount        = 0;\r
+LIST_ENTRY  gBrowserContextList         = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserContextList);\r
+LIST_ENTRY  gBrowserFormSetList         = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserFormSetList);\r
+LIST_ENTRY  gBrowserHotKeyList          = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserHotKeyList);\r
+LIST_ENTRY  gBrowserStorageList         = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserStorageList);\r
+LIST_ENTRY  gBrowserSaveFailFormSetList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserSaveFailFormSetList);\r
+\r
+BOOLEAN                mSystemSubmit = FALSE;\r
+BOOLEAN                gResetRequiredFormLevel;\r
+BOOLEAN                gResetRequiredSystemLevel = FALSE;\r
+BOOLEAN                gExitRequired;\r
+BOOLEAN                gFlagReconnect;\r
+BOOLEAN                gCallbackReconnect;\r
+BROWSER_SETTING_SCOPE  gBrowserSettingScope  = FormSetLevel;\r
+BOOLEAN                mBrowserScopeFirstSet = TRUE;\r
+EXIT_HANDLER           ExitHandlerFunction   = NULL;\r
+FORM_BROWSER_FORMSET   *mSystemLevelFormSet;\r
 \r
 //\r
 // Browser Global Strings\r
 //\r
-CHAR16            *gFunctionNineString;\r
-CHAR16            *gFunctionTenString;\r
-CHAR16            *gEnterString;\r
-CHAR16            *gEnterCommitString;\r
-CHAR16            *gEnterEscapeString;\r
-CHAR16            *gEscapeString;\r
-CHAR16            *gSaveFailed;\r
-CHAR16            *gMoveHighlight;\r
-CHAR16            *gMakeSelection;\r
-CHAR16            *gDecNumericInput;\r
-CHAR16            *gHexNumericInput;\r
-CHAR16            *gToggleCheckBox;\r
-CHAR16            *gPromptForData;\r
-CHAR16            *gPromptForPassword;\r
-CHAR16            *gPromptForNewPassword;\r
-CHAR16            *gConfirmPassword;\r
-CHAR16            *gConfirmError;\r
-CHAR16            *gPassowordInvalid;\r
-CHAR16            *gPressEnter;\r
-CHAR16            *gEmptyString;\r
-CHAR16            *gAreYouSure;\r
-CHAR16            *gYesResponse;\r
-CHAR16            *gNoResponse;\r
-CHAR16            *gMiniString;\r
-CHAR16            *gPlusString;\r
-CHAR16            *gMinusString;\r
-CHAR16            *gAdjustNumber;\r
-CHAR16            *gSaveChanges;\r
-CHAR16            *gOptionMismatch;\r
-\r
-CHAR16            *mUnknownString = L"!";\r
-\r
-CHAR16            gPromptBlockWidth;\r
-CHAR16            gOptionBlockWidth;\r
-CHAR16            gHelpBlockWidth;\r
-\r
-EFI_GUID  gZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};\r
-EFI_GUID  gSetupBrowserGuid = {\r
-  0xab368524, 0xb60c, 0x495b, {0xa0, 0x9, 0x12, 0xe8, 0x5b, 0x1a, 0xea, 0x32}\r
-};\r
+CHAR16  *gEmptyString;\r
+CHAR16  *mUnknownString = L"!";\r
+\r
+extern EFI_GUID                  mCurrentFormSetGuid;\r
+extern EFI_HII_HANDLE            mCurrentHiiHandle;\r
+extern UINT16                    mCurrentFormId;\r
+extern FORM_DISPLAY_ENGINE_FORM  gDisplayFormData;\r
+\r
+/**\r
+  Create a menu with specified formset GUID and form ID, and add it as a child\r
+  of the given parent menu.\r
+\r
+  @param  HiiHandle              Hii handle related to this formset.\r
+  @param  FormSetGuid            The Formset Guid of menu to be added.\r
+  @param  FormId                 The Form ID of menu to be added.\r
+  @param  QuestionId             The question id of this menu to be added.\r
+\r
+  @return A pointer to the newly added menu or NULL if memory is insufficient.\r
+\r
+**/\r
+FORM_ENTRY_INFO *\r
+UiAddMenuList (\r
+  IN EFI_HII_HANDLE  HiiHandle,\r
+  IN EFI_GUID        *FormSetGuid,\r
+  IN UINT16          FormId,\r
+  IN UINT16          QuestionId\r
+  )\r
+{\r
+  FORM_ENTRY_INFO  *MenuList;\r
+\r
+  MenuList = AllocateZeroPool (sizeof (FORM_ENTRY_INFO));\r
+  if (MenuList == NULL) {\r
+    return NULL;\r
+  }\r
 \r
-FORM_BROWSER_FORMSET  *gOldFormSet;\r
+  MenuList->Signature = FORM_ENTRY_INFO_SIGNATURE;\r
+\r
+  MenuList->HiiHandle = HiiHandle;\r
+  CopyMem (&MenuList->FormSetGuid, FormSetGuid, sizeof (EFI_GUID));\r
+  MenuList->FormId     = FormId;\r
+  MenuList->QuestionId = QuestionId;\r
 \r
-FUNCTIION_KEY_SETTING gFunctionKeySettingTable[] = {\r
   //\r
-  // Boot Manager\r
+  // If parent is not specified, it is the root Form of a Formset\r
   //\r
-  {\r
-    {\r
-      0x847bc3fe,\r
-      0xb974,\r
-      0x446d,\r
-      {\r
-        0x94,\r
-        0x49,\r
-        0x5a,\r
-        0xd5,\r
-        0x41,\r
-        0x2e,\r
-        0x99,\r
-        0x3b\r
-      }\r
-    },\r
-    NONE_FUNCTION_KEY_SETTING\r
-  },\r
+  InsertTailList (&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &MenuList->Link);\r
+\r
+  return MenuList;\r
+}\r
+\r
+/**\r
+  Return the form id for the input hiihandle and formset.\r
+\r
+  @param  HiiHandle              HiiHandle for FormSet.\r
+  @param  FormSetGuid            The Formset GUID of the menu to search.\r
+\r
+  @return First form's id for this form set.\r
+\r
+**/\r
+EFI_FORM_ID\r
+GetFirstFormId (\r
+  IN EFI_HII_HANDLE  HiiHandle,\r
+  IN EFI_GUID        *FormSetGuid\r
+  )\r
+{\r
+  LIST_ENTRY         *Link;\r
+  FORM_BROWSER_FORM  *Form;\r
+\r
+  Link = GetFirstNode (&gCurrentSelection->FormSet->FormListHead);\r
+  Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+\r
+  return Form->FormId;\r
+}\r
+\r
+/**\r
+  Search Menu with given FormSetGuid and FormId in all cached menu list.\r
+\r
+  @param  HiiHandle              HiiHandle for FormSet.\r
+  @param  FormSetGuid            The Formset GUID of the menu to search.\r
+  @param  FormId                 The Form ID of menu to search.\r
+\r
+  @return A pointer to menu found or NULL if not found.\r
+\r
+**/\r
+FORM_ENTRY_INFO *\r
+UiFindMenuList (\r
+  IN EFI_HII_HANDLE  HiiHandle,\r
+  IN EFI_GUID        *FormSetGuid,\r
+  IN UINT16          FormId\r
+  )\r
+{\r
+  LIST_ENTRY       *Link;\r
+  FORM_ENTRY_INFO  *MenuList;\r
+  FORM_ENTRY_INFO  *RetMenu;\r
+  EFI_FORM_ID      FirstFormId;\r
+\r
+  RetMenu = NULL;\r
+\r
+  Link = GetFirstNode (&mPrivateData.FormBrowserEx2.FormViewHistoryHead);\r
+  while (!IsNull (&mPrivateData.FormBrowserEx2.FormViewHistoryHead, Link)) {\r
+    MenuList = FORM_ENTRY_INFO_FROM_LINK (Link);\r
+    Link     = GetNextNode (&mPrivateData.FormBrowserEx2.FormViewHistoryHead, Link);\r
+\r
+    //\r
+    // If already find the menu, free the menus behind it.\r
+    //\r
+    if (RetMenu != NULL) {\r
+      RemoveEntryList (&MenuList->Link);\r
+      FreePool (MenuList);\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Find the same FromSet.\r
+    //\r
+    if (MenuList->HiiHandle == HiiHandle) {\r
+      if (IsZeroGuid (&MenuList->FormSetGuid)) {\r
+        //\r
+        // FormSetGuid is not specified.\r
+        //\r
+        RetMenu = MenuList;\r
+      } else if (CompareGuid (&MenuList->FormSetGuid, FormSetGuid)) {\r
+        if (MenuList->FormId == FormId) {\r
+          RetMenu = MenuList;\r
+        } else if ((FormId == 0) || (MenuList->FormId == 0)) {\r
+          FirstFormId = GetFirstFormId (HiiHandle, FormSetGuid);\r
+          if (((FormId == 0) && (FirstFormId == MenuList->FormId)) || ((MenuList->FormId == 0) && (FirstFormId == FormId))) {\r
+            RetMenu = MenuList;\r
+          }\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  return RetMenu;\r
+}\r
+\r
+/**\r
+  Find parent menu for current menu.\r
+\r
+  @param  CurrentMenu    Current Menu\r
+  @param  SettingLevel   Whether find parent menu in Form Level or Formset level.\r
+                         In form level, just find the parent menu;\r
+                         In formset level, find the parent menu which has different\r
+                         formset guid value.\r
+\r
+  @retval   The parent menu for current menu.\r
+**/\r
+FORM_ENTRY_INFO *\r
+UiFindParentMenu (\r
+  IN FORM_ENTRY_INFO        *CurrentMenu,\r
+  IN BROWSER_SETTING_SCOPE  SettingLevel\r
+  )\r
+{\r
+  FORM_ENTRY_INFO  *ParentMenu;\r
+  LIST_ENTRY       *Link;\r
+\r
+  ASSERT (SettingLevel == FormLevel || SettingLevel == FormSetLevel);\r
+\r
+  if (CurrentMenu == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  ParentMenu = NULL;\r
+  Link       = &CurrentMenu->Link;\r
+\r
+  while (Link->BackLink != &mPrivateData.FormBrowserEx2.FormViewHistoryHead) {\r
+    ParentMenu = FORM_ENTRY_INFO_FROM_LINK (Link->BackLink);\r
+\r
+    if (SettingLevel == FormLevel) {\r
+      //\r
+      // For FormLevel, just find the parent menu, return.\r
+      //\r
+      break;\r
+    }\r
+\r
+    if (!CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) {\r
+      //\r
+      // For SystemLevel, must find the menu which has different formset.\r
+      //\r
+      break;\r
+    }\r
+\r
+    Link = Link->BackLink;\r
+  }\r
+\r
   //\r
-  // Device Manager\r
+  // Not find the parent menu, just return NULL.\r
   //\r
-  {\r
-    {\r
-      0x3ebfa8e6,\r
-      0x511d,\r
-      0x4b5b,\r
-      {\r
-        0xa9,\r
-        0x5f,\r
-        0xfb,\r
-        0x38,\r
-        0x26,\r
-        0xf,\r
-        0x1c,\r
-        0x27\r
-      }\r
-    },\r
-    NONE_FUNCTION_KEY_SETTING\r
-  },\r
+  if (Link->BackLink == &mPrivateData.FormBrowserEx2.FormViewHistoryHead) {\r
+    return NULL;\r
+  }\r
+\r
+  return ParentMenu;\r
+}\r
+\r
+/**\r
+  Free Menu list linked list.\r
+\r
+  @param  MenuListHead    One Menu list point in the menu list.\r
+\r
+**/\r
+VOID\r
+UiFreeMenuList (\r
+  LIST_ENTRY  *MenuListHead\r
+  )\r
+{\r
+  FORM_ENTRY_INFO  *MenuList;\r
+\r
+  while (!IsListEmpty (MenuListHead)) {\r
+    MenuList = FORM_ENTRY_INFO_FROM_LINK (MenuListHead->ForwardLink);\r
+    RemoveEntryList (&MenuList->Link);\r
+\r
+    FreePool (MenuList);\r
+  }\r
+}\r
+\r
+/**\r
+  Copy current Menu list to the new menu list.\r
+\r
+  @param  NewMenuListHead        New create Menu list.\r
+  @param  CurrentMenuListHead    Current Menu list.\r
+\r
+**/\r
+VOID\r
+UiCopyMenuList (\r
+  OUT LIST_ENTRY  *NewMenuListHead,\r
+  IN  LIST_ENTRY  *CurrentMenuListHead\r
+  )\r
+{\r
+  LIST_ENTRY       *Link;\r
+  FORM_ENTRY_INFO  *MenuList;\r
+  FORM_ENTRY_INFO  *NewMenuEntry;\r
+\r
   //\r
-  // BMM FormSet.\r
+  // If new menu list not empty, free it first.\r
   //\r
-  {\r
-    {\r
-      0x642237c7,\r
-      0x35d4,\r
-      0x472d,\r
-      {\r
-        0x83,\r
-        0x65,\r
-        0x12,\r
-        0xe0,\r
-        0xcc,\r
-        0xf2,\r
-        0x7a,\r
-        0x22\r
-      }\r
-    },\r
-    NONE_FUNCTION_KEY_SETTING\r
-  },\r
+  UiFreeMenuList (NewMenuListHead);\r
+\r
+  Link = GetFirstNode (CurrentMenuListHead);\r
+  while (!IsNull (CurrentMenuListHead, Link)) {\r
+    MenuList = FORM_ENTRY_INFO_FROM_LINK (Link);\r
+    Link     = GetNextNode (CurrentMenuListHead, Link);\r
+\r
+    NewMenuEntry = AllocateZeroPool (sizeof (FORM_ENTRY_INFO));\r
+    ASSERT (NewMenuEntry != NULL);\r
+    NewMenuEntry->Signature = FORM_ENTRY_INFO_SIGNATURE;\r
+    NewMenuEntry->HiiHandle = MenuList->HiiHandle;\r
+    CopyMem (&NewMenuEntry->FormSetGuid, &MenuList->FormSetGuid, sizeof (EFI_GUID));\r
+    NewMenuEntry->FormId     = MenuList->FormId;\r
+    NewMenuEntry->QuestionId = MenuList->QuestionId;\r
+\r
+    InsertTailList (NewMenuListHead, &NewMenuEntry->Link);\r
+  }\r
+}\r
+\r
+/**\r
+  Load all hii formset to the browser.\r
+\r
+**/\r
+VOID\r
+LoadAllHiiFormset (\r
+  VOID\r
+  )\r
+{\r
+  FORM_BROWSER_FORMSET  *LocalFormSet;\r
+  EFI_HII_HANDLE        *HiiHandles;\r
+  UINTN                 Index;\r
+  EFI_GUID              ZeroGuid;\r
+  EFI_STATUS            Status;\r
+  FORM_BROWSER_FORMSET  *OldFormset;\r
+\r
+  OldFormset = mSystemLevelFormSet;\r
+\r
   //\r
-  // BMM File Explorer FormSet.\r
+  // Get all the Hii handles\r
   //\r
-  {\r
-    {\r
-      0x1f2d63e1,\r
-      0xfebd,\r
-      0x4dc7,\r
-      {\r
-        0x9c,\r
-        0xc5,\r
-        0xba,\r
-        0x2b,\r
-        0x1c,\r
-        0xef,\r
-        0x9c,\r
-        0x5b\r
-      }\r
-    },\r
-    NONE_FUNCTION_KEY_SETTING\r
-  },\r
-};\r
+  HiiHandles = HiiGetHiiHandles (NULL);\r
+  ASSERT (HiiHandles != NULL);\r
+\r
+  //\r
+  // Search for formset of each class type\r
+  //\r
+  for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
+    //\r
+    // Check HiiHandles[Index] does exist in global maintain list.\r
+    //\r
+    if (GetFormSetFromHiiHandle (HiiHandles[Index]) != NULL) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Initilize FormSet Setting\r
+    //\r
+    LocalFormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));\r
+    ASSERT (LocalFormSet != NULL);\r
+    mSystemLevelFormSet = LocalFormSet;\r
+\r
+    ZeroMem (&ZeroGuid, sizeof (ZeroGuid));\r
+    Status = InitializeFormSet (HiiHandles[Index], &ZeroGuid, LocalFormSet);\r
+    if (EFI_ERROR (Status) || IsListEmpty (&LocalFormSet->FormListHead)) {\r
+      DestroyFormSet (LocalFormSet);\r
+      continue;\r
+    }\r
+\r
+    InitializeCurrentSetting (LocalFormSet);\r
+\r
+    //\r
+    // Initilize Questions' Value\r
+    //\r
+    Status = LoadFormSetConfig (NULL, LocalFormSet);\r
+    if (EFI_ERROR (Status)) {\r
+      DestroyFormSet (LocalFormSet);\r
+      continue;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Free resources, and restore gOldFormSet and gClassOfVfr\r
+  //\r
+  FreePool (HiiHandles);\r
+\r
+  mSystemLevelFormSet = OldFormset;\r
+}\r
+\r
+/**\r
+  Pop up the error info.\r
+\r
+  @param      BrowserStatus    The input browser status.\r
+  @param      HiiHandle        The Hiihandle for this opcode.\r
+  @param      OpCode           The opcode use to get the erro info and timeout value.\r
+  @param      ErrorString      Error string used by BROWSER_NO_SUBMIT_IF.\r
+\r
+**/\r
+UINT32\r
+PopupErrorMessage (\r
+  IN UINT32             BrowserStatus,\r
+  IN EFI_HII_HANDLE     HiiHandle,\r
+  IN EFI_IFR_OP_HEADER  *OpCode  OPTIONAL,\r
+  IN CHAR16             *ErrorString\r
+  )\r
+{\r
+  FORM_DISPLAY_ENGINE_STATEMENT  *Statement;\r
+  USER_INPUT                     UserInputData;\r
+\r
+  Statement = NULL;\r
+\r
+  if (OpCode != NULL) {\r
+    Statement = AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT));\r
+    ASSERT (Statement != NULL);\r
+    Statement->OpCode                     = OpCode;\r
+    gDisplayFormData.HighLightedStatement = Statement;\r
+  }\r
+\r
+  //\r
+  // Used to compatible with old display engine.\r
+  // New display engine not use this field.\r
+  //\r
+  gDisplayFormData.ErrorString   = ErrorString;\r
+  gDisplayFormData.BrowserStatus = BrowserStatus;\r
+\r
+  if (HiiHandle != NULL) {\r
+    gDisplayFormData.HiiHandle = HiiHandle;\r
+  }\r
+\r
+  mFormDisplay->FormDisplay (&gDisplayFormData, &UserInputData);\r
+\r
+  gDisplayFormData.BrowserStatus = BROWSER_SUCCESS;\r
+  gDisplayFormData.ErrorString   = NULL;\r
+\r
+  if (OpCode != NULL) {\r
+    FreePool (Statement);\r
+  }\r
+\r
+  return UserInputData.Action;\r
+}\r
 \r
 /**\r
   This is the routine which an external caller uses to direct the browser\r
@@ -203,87 +466,42 @@ FUNCTIION_KEY_SETTING gFunctionKeySettingTable[] = {
 EFI_STATUS\r
 EFIAPI\r
 SendForm (\r
-  IN  CONST EFI_FORM_BROWSER2_PROTOCOL *This,\r
-  IN  EFI_HII_HANDLE                   *Handles,\r
-  IN  UINTN                            HandleCount,\r
-  IN  EFI_GUID                         *FormSetGuid, OPTIONAL\r
-  IN  UINT16                           FormId, OPTIONAL\r
-  IN  CONST EFI_SCREEN_DESCRIPTOR      *ScreenDimensions, OPTIONAL\r
-  OUT EFI_BROWSER_ACTION_REQUEST       *ActionRequest  OPTIONAL\r
+  IN  CONST EFI_FORM_BROWSER2_PROTOCOL  *This,\r
+  IN  EFI_HII_HANDLE                    *Handles,\r
+  IN  UINTN                             HandleCount,\r
+  IN  EFI_GUID                          *FormSetGuid  OPTIONAL,\r
+  IN  UINT16                            FormId  OPTIONAL,\r
+  IN  CONST EFI_SCREEN_DESCRIPTOR       *ScreenDimensions  OPTIONAL,\r
+  OUT EFI_BROWSER_ACTION_REQUEST        *ActionRequest  OPTIONAL\r
   )\r
 {\r
-  EFI_STATUS                    Status;\r
-  UI_MENU_SELECTION             *Selection;\r
-  UINTN                         Index;\r
-  FORM_BROWSER_FORMSET          *FormSet;\r
-\r
-  //\r
-  // Save globals used by SendForm()\r
-  //\r
-  SaveBrowserContext ();\r
-\r
-  Status = EFI_SUCCESS;\r
-  ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
+  EFI_STATUS            Status;\r
+  UI_MENU_SELECTION     *Selection;\r
+  UINTN                 Index;\r
+  FORM_BROWSER_FORMSET  *FormSet;\r
+  FORM_ENTRY_INFO       *MenuList;\r
+  BOOLEAN               RetVal;\r
 \r
   //\r
-  // Seed the dimensions in the global\r
+  // If EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found, return EFI_UNSUPPORTED.\r
   //\r
-  gST->ConOut->QueryMode (\r
-                 gST->ConOut,\r
-                 gST->ConOut->Mode->Mode,\r
-                 &gScreenDimensions.RightColumn,\r
-                 &gScreenDimensions.BottomRow\r
-                 );\r
-\r
-  if (ScreenDimensions != NULL) {\r
-    //\r
-    // Check local dimension vs. global dimension.\r
-    //\r
-    if ((gScreenDimensions.RightColumn < ScreenDimensions->RightColumn) ||\r
-        (gScreenDimensions.BottomRow < ScreenDimensions->BottomRow)\r
-        ) {\r
-      Status = EFI_INVALID_PARAMETER;\r
-      goto Done;\r
-    } else {\r
-      //\r
-      // Local dimension validation.\r
-      //\r
-      if ((ScreenDimensions->RightColumn > ScreenDimensions->LeftColumn) &&\r
-          (ScreenDimensions->BottomRow > ScreenDimensions->TopRow) &&\r
-          ((ScreenDimensions->RightColumn - ScreenDimensions->LeftColumn) > 2) &&\r
-          (\r
-            (ScreenDimensions->BottomRow - ScreenDimensions->TopRow) > STATUS_BAR_HEIGHT +\r
-            SCROLL_ARROW_HEIGHT *\r
-            2 +\r
-            FRONT_PAGE_HEADER_HEIGHT +\r
-            FOOTER_HEIGHT +\r
-            1\r
-          )\r
-        ) {\r
-        CopyMem (&gScreenDimensions, (VOID *) ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
-      } else {\r
-        Status = EFI_INVALID_PARAMETER;\r
-        goto Done;\r
-      }\r
-    }\r
+  if (mFormDisplay == NULL) {\r
+    DEBUG ((DEBUG_ERROR, "Fatal Error! EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found!"));\r
+    return EFI_UNSUPPORTED;\r
   }\r
 \r
-  gOptionBlockWidth = (CHAR16) ((gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3);\r
-  gHelpBlockWidth   = gOptionBlockWidth;\r
-  gPromptBlockWidth = gOptionBlockWidth;\r
-\r
   //\r
-  // Initialize the strings for the browser, upon exit of the browser, the strings will be freed\r
+  // Save globals used by SendForm()\r
   //\r
-  InitializeBrowserStrings ();\r
-\r
-  gFunctionKeySetting = DEFAULT_FUNCTION_KEY_SETTING;\r
-  gClassOfVfr         = FORMSET_CLASS_PLATFORM_SETUP;\r
+  SaveBrowserContext ();\r
 \r
-  //\r
-  // Ensure we are in Text mode\r
-  //\r
-  gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
+  gFlagReconnect                    = FALSE;\r
+  gResetRequiredFormLevel           = FALSE;\r
+  gExitRequired                     = FALSE;\r
+  gCallbackReconnect                = FALSE;\r
+  Status                            = EFI_SUCCESS;\r
+  gEmptyString                      = L"";\r
+  gDisplayFormData.ScreenDimensions = (EFI_SCREEN_DESCRIPTOR *)ScreenDimensions;\r
 \r
   for (Index = 0; Index < HandleCount; Index++) {\r
     Selection = AllocateZeroPool (sizeof (UI_MENU_SELECTION));\r
@@ -293,15 +511,22 @@ SendForm (
     if (FormSetGuid != NULL) {\r
       CopyMem (&Selection->FormSetGuid, FormSetGuid, sizeof (EFI_GUID));\r
       Selection->FormId = FormId;\r
+    } else {\r
+      CopyMem (&Selection->FormSetGuid, &gEfiHiiPlatformSetupFormsetGuid, sizeof (EFI_GUID));\r
     }\r
 \r
-    gOldFormSet = NULL;\r
-    gNvUpdateRequired = FALSE;\r
-\r
     do {\r
       FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));\r
       ASSERT (FormSet != NULL);\r
 \r
+      //\r
+      // Validate the HiiHandle\r
+      // if validate failed, find the first validate parent HiiHandle.\r
+      //\r
+      if (!ValidateHiiHandle (Selection->Handle)) {\r
+        FindNextMenu (Selection, FormSetLevel);\r
+      }\r
+\r
       //\r
       // Initialize internal data structures of FormSet\r
       //\r
@@ -310,7 +535,9 @@ SendForm (
         DestroyFormSet (FormSet);\r
         break;\r
       }\r
-      Selection->FormSet = FormSet;\r
+\r
+      Selection->FormSet  = FormSet;\r
+      mSystemLevelFormSet = FormSet;\r
 \r
       //\r
       // Display this formset\r
@@ -319,35 +546,57 @@ SendForm (
 \r
       Status = SetupBrowser (Selection);\r
 \r
-      gCurrentSelection = NULL;\r
+      gCurrentSelection   = NULL;\r
+      mSystemLevelFormSet = NULL;\r
+\r
+      //\r
+      // Check incoming formset whether is same with previous. If yes, that means action is not exiting of formset so do not reconnect controller.\r
+      //\r
+      if ((gFlagReconnect || gCallbackReconnect) && !CompareGuid (&FormSet->Guid, &Selection->FormSetGuid)) {\r
+        RetVal = ReconnectController (FormSet->DriverHandle);\r
+        if (!RetVal) {\r
+          PopupErrorMessage (BROWSER_RECONNECT_FAIL, NULL, NULL, NULL);\r
+        }\r
+\r
+        gFlagReconnect     = FALSE;\r
+        gCallbackReconnect = FALSE;\r
+      }\r
+\r
+      //\r
+      // If no data is changed, don't need to save current FormSet into the maintain list.\r
+      //\r
+      if (!IsNvUpdateRequiredForFormSet (FormSet)) {\r
+        CleanBrowserStorage (FormSet);\r
+        RemoveEntryList (&FormSet->Link);\r
+        DestroyFormSet (FormSet);\r
+      }\r
 \r
       if (EFI_ERROR (Status)) {\r
         break;\r
       }\r
-\r
     } while (Selection->Action == UI_ACTION_REFRESH_FORMSET);\r
 \r
-    if (gOldFormSet != NULL) {\r
-      DestroyFormSet (gOldFormSet);\r
-      gOldFormSet = NULL;\r
-    }\r
-\r
     FreePool (Selection);\r
   }\r
 \r
   if (ActionRequest != NULL) {\r
     *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
-    if (gResetRequired) {\r
+    if (gResetRequiredFormLevel) {\r
       *ActionRequest = EFI_BROWSER_ACTION_REQUEST_RESET;\r
     }\r
   }\r
 \r
-  FreeBrowserStrings ();\r
+  mFormDisplay->ExitDisplay ();\r
 \r
-  gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
-  gST->ConOut->ClearScreen (gST->ConOut);\r
+  //\r
+  // Clear the menu history data.\r
+  //\r
+  while (!IsListEmpty (&mPrivateData.FormBrowserEx2.FormViewHistoryHead)) {\r
+    MenuList = FORM_ENTRY_INFO_FROM_LINK (mPrivateData.FormBrowserEx2.FormViewHistoryHead.ForwardLink);\r
+    RemoveEntryList (&MenuList->Link);\r
+    FreePool (MenuList);\r
+  }\r
 \r
-Done:\r
   //\r
   // Restore globals used by SendForm()\r
   //\r
@@ -356,15 +605,10 @@ Done:
   return Status;\r
 }\r
 \r
-\r
 /**\r
-  This function is called by a callback handler to retrieve uncommitted state\r
-  data from the browser.\r
+  Get or set data to the storage.\r
 \r
-  @param  This                   A pointer to the EFI_FORM_BROWSER2_PROTOCOL\r
-                                 instance.\r
-  @param  ResultsDataSize        A pointer to the size of the buffer associated\r
-                                 with ResultsData.\r
+  @param  ResultsDataSize        The size of the buffer associatedwith ResultsData.\r
   @param  ResultsData            A string returned from an IFR browser or\r
                                  equivalent. The results string will have no\r
                                  routing information in them.\r
@@ -373,83 +617,196 @@ Done:
                                  browser state information or set (if RetrieveData\r
                                  = FALSE) data in the uncommitted browser state\r
                                  information.\r
-  @param  VariableGuid           An optional field to indicate the target variable\r
-                                 GUID name to use.\r
-  @param  VariableName           An optional field to indicate the target\r
-                                 human-readable variable name.\r
+  @param  Storage                The pointer to the storage.\r
 \r
   @retval EFI_SUCCESS            The results have been distributed or are awaiting\r
                                  distribution.\r
-  @retval EFI_BUFFER_TOO_SMALL   The ResultsDataSize specified was too small to\r
-                                 contain the results data.\r
 \r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
-BrowserCallback (\r
-  IN CONST EFI_FORM_BROWSER2_PROTOCOL  *This,\r
-  IN OUT UINTN                         *ResultsDataSize,\r
-  IN OUT EFI_STRING                    ResultsData,\r
-  IN BOOLEAN                           RetrieveData,\r
-  IN CONST EFI_GUID                    *VariableGuid, OPTIONAL\r
-  IN CONST CHAR16                      *VariableName  OPTIONAL\r
+ProcessStorage (\r
+  IN OUT UINTN        *ResultsDataSize,\r
+  IN OUT EFI_STRING   *ResultsData,\r
+  IN BOOLEAN          RetrieveData,\r
+  IN BROWSER_STORAGE  *Storage\r
   )\r
 {\r
-  EFI_STATUS            Status;\r
-  LIST_ENTRY            *Link;\r
-  FORMSET_STORAGE       *Storage;\r
-  FORM_BROWSER_FORMSET  *FormSet;\r
-  BOOLEAN               Found;\r
-  CHAR16                *ConfigResp;\r
-  CHAR16                *StrPtr;\r
-  UINTN                 BufferSize;\r
-  UINTN                 TmpSize;\r
+  CHAR16           *ConfigResp;\r
+  EFI_STATUS       Status;\r
+  CHAR16           *StrPtr;\r
+  UINTN            BufferSize;\r
+  UINTN            TmpSize;\r
+  UINTN            MaxLen;\r
+  FORMSET_STORAGE  *BrowserStorage;\r
 \r
-  if (ResultsDataSize == NULL || ResultsData == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
+  if (RetrieveData) {\r
+    //\r
+    // Generate <ConfigResp>\r
+    //\r
+    Status = StorageToConfigResp (Storage, &ConfigResp, Storage->ConfigRequest, TRUE);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
 \r
-  if (gCurrentSelection == NULL) {\r
-    return EFI_NOT_READY;\r
+    //\r
+    // Skip <ConfigHdr> and '&' to point to <ConfigBody> when first copy the configbody.\r
+    // Also need to consider add "\0" at first time.\r
+    //\r
+    StrPtr = StrStr (ConfigResp, L"PATH");\r
+    ASSERT (StrPtr != NULL);\r
+    StrPtr     = StrStr (StrPtr, L"&");\r
+    StrPtr    += 1;\r
+    BufferSize = StrSize (StrPtr);\r
+\r
+    //\r
+    // Copy the data if the input buffer is bigger enough.\r
+    //\r
+    if (*ResultsDataSize >= BufferSize) {\r
+      StrCpyS (*ResultsData, *ResultsDataSize / sizeof (CHAR16), StrPtr);\r
+    }\r
+\r
+    *ResultsDataSize = BufferSize;\r
+    FreePool (ConfigResp);\r
+  } else {\r
+    //\r
+    // Prepare <ConfigResp>\r
+    //\r
+    BrowserStorage = GetFstStgFromBrsStg (Storage);\r
+    ASSERT (BrowserStorage != NULL);\r
+    TmpSize    = StrLen (*ResultsData);\r
+    BufferSize = (TmpSize + StrLen (BrowserStorage->ConfigHdr) + 2) * sizeof (CHAR16);\r
+    MaxLen     = BufferSize / sizeof (CHAR16);\r
+    ConfigResp = AllocateZeroPool (BufferSize);\r
+    ASSERT (ConfigResp != NULL);\r
+\r
+    StrCpyS (ConfigResp, MaxLen, BrowserStorage->ConfigHdr);\r
+    StrCatS (ConfigResp, MaxLen, L"&");\r
+    StrCatS (ConfigResp, MaxLen, *ResultsData);\r
+\r
+    //\r
+    // Update Browser uncommited data\r
+    //\r
+    Status = ConfigRespToStorage (Storage, ConfigResp);\r
+    FreePool (ConfigResp);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
   }\r
 \r
-  Storage = NULL;\r
-  ConfigResp = NULL;\r
-  FormSet = gCurrentSelection->FormSet;\r
+  return EFI_SUCCESS;\r
+}\r
 \r
-  //\r
-  // Find target storage\r
-  //\r
-  Link = GetFirstNode (&FormSet->StorageListHead);\r
-  if (IsNull (&FormSet->StorageListHead, Link)) {\r
-    return EFI_UNSUPPORTED;\r
+/**\r
+  This routine called this service in the browser to retrieve or set certain uncommitted\r
+  state information that resides in the open formsets.\r
+\r
+  @param  This                   A pointer to the EFI_FORM_BROWSER2_PROTOCOL\r
+                                 instance.\r
+  @param  ResultsDataSize        A pointer to the size of the buffer associated\r
+                                 with ResultsData.\r
+  @param  ResultsData            A string returned from an IFR browser or\r
+                                 equivalent. The results string will have no\r
+                                 routing information in them.\r
+  @param  RetrieveData           A BOOLEAN field which allows an agent to retrieve\r
+                                 (if RetrieveData = TRUE) data from the uncommitted\r
+                                 browser state information or set (if RetrieveData\r
+                                 = FALSE) data in the uncommitted browser state\r
+                                 information.\r
+  @param  VariableGuid           An optional field to indicate the target variable\r
+                                 GUID name to use.\r
+  @param  VariableName           An optional field to indicate the target\r
+                                 human-readable variable name.\r
+\r
+  @retval EFI_SUCCESS            The results have been distributed or are awaiting\r
+                                 distribution.\r
+  @retval EFI_BUFFER_TOO_SMALL   The ResultsDataSize specified was too small to\r
+                                 contain the results data.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BrowserCallback (\r
+  IN CONST EFI_FORM_BROWSER2_PROTOCOL  *This,\r
+  IN OUT UINTN                         *ResultsDataSize,\r
+  IN OUT EFI_STRING                    ResultsData,\r
+  IN BOOLEAN                           RetrieveData,\r
+  IN CONST EFI_GUID                    *VariableGuid  OPTIONAL,\r
+  IN CONST CHAR16                      *VariableName  OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS       Status;\r
+  LIST_ENTRY       *Link;\r
+  BROWSER_STORAGE  *Storage;\r
+  FORMSET_STORAGE  *FormsetStorage;\r
+  UINTN            TotalSize;\r
+  BOOLEAN          Found;\r
+\r
+  if ((ResultsDataSize == NULL) || (ResultsData == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
   }\r
 \r
+  TotalSize = *ResultsDataSize;\r
+  Storage   = NULL;\r
+  Found     = FALSE;\r
+  Status    = EFI_SUCCESS;\r
+\r
   if (VariableGuid != NULL) {\r
     //\r
-    // Try to find target storage\r
+    // Try to find target storage in the current formset.\r
     //\r
-    Found = FALSE;\r
-    while (!IsNull (&FormSet->StorageListHead, Link)) {\r
-      Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
-      Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+    Link = GetFirstNode (&gBrowserStorageList);\r
+    while (!IsNull (&gBrowserStorageList, Link)) {\r
+      Storage = BROWSER_STORAGE_FROM_LINK (Link);\r
+      Link    = GetNextNode (&gBrowserStorageList, Link);\r
+      //\r
+      // Check the current storage.\r
+      //\r
+      if (!CompareGuid (&Storage->Guid, (EFI_GUID *)VariableGuid)) {\r
+        continue;\r
+      }\r
 \r
-      if (CompareGuid (&Storage->Guid, (EFI_GUID *) VariableGuid)) {\r
-        if (Storage->Type == EFI_HII_VARSTORE_BUFFER) {\r
-          //\r
-          // Buffer storage require both GUID and Name\r
-          //\r
-          if (VariableName == NULL) {\r
-            return EFI_NOT_FOUND;\r
-          }\r
+      if ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ||\r
+          (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER))\r
+      {\r
+        //\r
+        // Buffer storage require both GUID and Name\r
+        //\r
+        if (VariableName == NULL) {\r
+          return EFI_NOT_FOUND;\r
+        }\r
 \r
-          if (StrCmp (Storage->Name, (CHAR16 *) VariableName) != 0) {\r
-            continue;\r
-          }\r
+        if (StrCmp (Storage->Name, (CHAR16 *)VariableName) != 0) {\r
+          continue;\r
         }\r
-        Found = TRUE;\r
-        break;\r
       }\r
+\r
+      if ((Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) ||\r
+          (Storage->Type == EFI_HII_VARSTORE_BUFFER))\r
+      {\r
+        if ((mSystemLevelFormSet == NULL) || (mSystemLevelFormSet->HiiHandle == NULL)) {\r
+          return EFI_NOT_FOUND;\r
+        }\r
+\r
+        if (Storage->HiiHandle != mSystemLevelFormSet->HiiHandle) {\r
+          continue;\r
+        }\r
+      }\r
+\r
+      Status = ProcessStorage (&TotalSize, &ResultsData, RetrieveData, Storage);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
+        ConfigRequestAdjust (Storage, ResultsData, TRUE);\r
+      }\r
+\r
+      //\r
+      // Different formsets may have same varstore, so here just set the flag\r
+      // not exit the circle.\r
+      //\r
+      Found = TRUE;\r
+      break;\r
     }\r
 \r
     if (!Found) {\r
@@ -459,68 +816,59 @@ BrowserCallback (
     //\r
     // GUID/Name is not specified, take the first storage in FormSet\r
     //\r
-    Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
-  }\r
-\r
-  if (RetrieveData) {\r
-    //\r
-    // Skip if there is no RequestElement\r
-    //\r
-    if (Storage->ElementCount == 0) {\r
-      return EFI_SUCCESS;\r
+    if (mSystemLevelFormSet == NULL) {\r
+      return EFI_NOT_READY;\r
     }\r
 \r
     //\r
     // Generate <ConfigResp>\r
     //\r
-    Status = StorageToConfigResp (Storage, &ConfigResp);\r
-    if (EFI_ERROR (Status)) {\r
-      return Status;\r
+    Link = GetFirstNode (&mSystemLevelFormSet->StorageListHead);\r
+    if (IsNull (&mSystemLevelFormSet->StorageListHead, Link)) {\r
+      return EFI_UNSUPPORTED;\r
     }\r
 \r
-    //\r
-    // Skip <ConfigHdr> and '&' to point to <ConfigBody>\r
-    //\r
-    StrPtr = ConfigResp + StrLen (Storage->ConfigHdr) + 1;\r
-\r
-    BufferSize = StrSize (StrPtr);\r
-    if (*ResultsDataSize < BufferSize) {\r
-      *ResultsDataSize = BufferSize;\r
+    FormsetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
 \r
-      FreePool (ConfigResp);\r
-      return EFI_BUFFER_TOO_SMALL;\r
+    Status = ProcessStorage (&TotalSize, &ResultsData, RetrieveData, FormsetStorage->BrowserStorage);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
     }\r
+  }\r
 \r
-    *ResultsDataSize = BufferSize;\r
-    CopyMem (ResultsData, StrPtr, BufferSize);\r
+  if (RetrieveData) {\r
+    Status           = TotalSize <= *ResultsDataSize ? EFI_SUCCESS : EFI_BUFFER_TOO_SMALL;\r
+    *ResultsDataSize = TotalSize;\r
+  }\r
 \r
-    FreePool (ConfigResp);\r
-  } else {\r
-    //\r
-    // Prepare <ConfigResp>\r
-    //\r
-    TmpSize = StrLen (ResultsData);\r
-    BufferSize = (TmpSize + StrLen (Storage->ConfigHdr) + 2) * sizeof (CHAR16);\r
-    ConfigResp = AllocateZeroPool (BufferSize);\r
-    ASSERT (ConfigResp != NULL);\r
+  return Status;\r
+}\r
 \r
-    StrCpy (ConfigResp, Storage->ConfigHdr);\r
-    StrCat (ConfigResp, L"&");\r
-    StrCat (ConfigResp, ResultsData);\r
+/**\r
+  Callback function for SimpleTextInEx protocol install events\r
 \r
-    //\r
-    // Update Browser uncommited data\r
-    //\r
-    Status = ConfigRespToStorage (Storage, ConfigResp);\r
-    if (EFI_ERROR (Status)) {\r
-      return Status;\r
-    }\r
+  @param Event           the event that is signaled.\r
+  @param Context         not used here.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+FormDisplayCallback (\r
+  IN EFI_EVENT  Event,\r
+  IN VOID       *Context\r
+  )\r
+{\r
+  if (mFormDisplay != NULL) {\r
+    return;\r
   }\r
 \r
-  return EFI_SUCCESS;\r
+  gBS->LocateProtocol (\r
+         &gEdkiiFormDisplayEngineProtocolGuid,\r
+         NULL,\r
+         (VOID **)&mFormDisplay\r
+         );\r
 }\r
 \r
-\r
 /**\r
   Initialize Setup Browser driver.\r
 \r
@@ -534,11 +882,12 @@ BrowserCallback (
 EFI_STATUS\r
 EFIAPI\r
 InitializeSetup (\r
-  IN EFI_HANDLE           ImageHandle,\r
-  IN EFI_SYSTEM_TABLE     *SystemTable\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
   )\r
 {\r
-  EFI_STATUS                  Status;\r
+  EFI_STATUS  Status;\r
+  VOID        *Registration;\r
 \r
   //\r
   // Locate required Hii relative protocols\r
@@ -546,56 +895,77 @@ InitializeSetup (
   Status = gBS->LocateProtocol (\r
                   &gEfiHiiDatabaseProtocolGuid,\r
                   NULL,\r
-                  (VOID **) &mHiiDatabase\r
+                  (VOID **)&mHiiDatabase\r
                   );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
   Status = gBS->LocateProtocol (\r
-                  &gEfiHiiStringProtocolGuid,\r
+                  &gEfiHiiConfigRoutingProtocolGuid,\r
                   NULL,\r
-                  (VOID **) &mHiiString\r
+                  (VOID **)&mHiiConfigRouting\r
                   );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
   Status = gBS->LocateProtocol (\r
-                  &gEfiHiiConfigRoutingProtocolGuid,\r
+                  &gEfiDevicePathFromTextProtocolGuid,\r
                   NULL,\r
-                  (VOID **) &mHiiConfigRouting\r
+                  (VOID **)&mPathFromText\r
                   );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  //\r
-  // Publish our HII data\r
-  //\r
-  gHiiHandle = HiiAddPackages (\r
-                 &gSetupBrowserGuid,\r
-                 ImageHandle,\r
-                 SetupBrowserStrings,\r
-                 NULL\r
-                 );\r
-  ASSERT (gHiiHandle != NULL);\r
 \r
   //\r
-  // Initialize Driver private data\r
+  // Install FormBrowser2 protocol\r
   //\r
-  gBannerData = AllocateZeroPool (sizeof (BANNER_DATA));\r
-  ASSERT (gBannerData != NULL);\r
+  mPrivateData.Handle = NULL;\r
+  Status              = gBS->InstallProtocolInterface (\r
+                               &mPrivateData.Handle,\r
+                               &gEfiFormBrowser2ProtocolGuid,\r
+                               EFI_NATIVE_INTERFACE,\r
+                               &mPrivateData.FormBrowser2\r
+                               );\r
+  ASSERT_EFI_ERROR (Status);\r
 \r
   //\r
-  // Install FormBrowser2 protocol\r
+  // Install FormBrowserEx2 protocol\r
   //\r
+  InitializeListHead (&mPrivateData.FormBrowserEx2.FormViewHistoryHead);\r
+  InitializeListHead (&mPrivateData.FormBrowserEx2.OverrideQestListHead);\r
   mPrivateData.Handle = NULL;\r
+  Status              = gBS->InstallProtocolInterface (\r
+                               &mPrivateData.Handle,\r
+                               &gEdkiiFormBrowserEx2ProtocolGuid,\r
+                               EFI_NATIVE_INTERFACE,\r
+                               &mPrivateData.FormBrowserEx2\r
+                               );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
   Status = gBS->InstallProtocolInterface (\r
                   &mPrivateData.Handle,\r
-                  &gEfiFormBrowser2ProtocolGuid,\r
+                  &gEdkiiFormBrowserExProtocolGuid,\r
                   EFI_NATIVE_INTERFACE,\r
-                  &mPrivateData.FormBrowser2\r
+                  &mPrivateData.FormBrowserEx\r
                   );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
-  return Status;\r
-}\r
+  InitializeDisplayFormData ();\r
+\r
+  Status = gBS->LocateProtocol (\r
+                  &gEdkiiFormDisplayEngineProtocolGuid,\r
+                  NULL,\r
+                  (VOID **)&mFormDisplay\r
+                  );\r
 \r
+  if (EFI_ERROR (Status)) {\r
+    EfiCreateProtocolNotifyEvent (\r
+      &gEdkiiFormDisplayEngineProtocolGuid,\r
+      TPL_CALLBACK,\r
+      FormDisplayCallback,\r
+      NULL,\r
+      &Registration\r
+      );\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
 \r
 /**\r
   Create a new string in HII Package List.\r
@@ -609,8 +979,8 @@ InitializeSetup (
 **/\r
 EFI_STRING_ID\r
 NewString (\r
-  IN  CHAR16                   *String,\r
-  IN  EFI_HII_HANDLE           HiiHandle\r
+  IN  CHAR16          *String,\r
+  IN  EFI_HII_HANDLE  HiiHandle\r
   )\r
 {\r
   EFI_STRING_ID  StringId;\r
@@ -621,7 +991,6 @@ NewString (
   return StringId;\r
 }\r
 \r
-\r
 /**\r
   Delete a string from HII Package List.\r
 \r
@@ -633,8 +1002,8 @@ NewString (
 **/\r
 EFI_STATUS\r
 DeleteString (\r
-  IN  EFI_STRING_ID            StringId,\r
-  IN  EFI_HII_HANDLE           HiiHandle\r
+  IN  EFI_STRING_ID   StringId,\r
+  IN  EFI_HII_HANDLE  HiiHandle\r
   )\r
 {\r
   CHAR16  NullChar;\r
@@ -644,7 +1013,6 @@ DeleteString (
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Get the string based on the StringId and HII Package List Handle.\r
 \r
@@ -657,20 +1025,24 @@ DeleteString (
 **/\r
 CHAR16 *\r
 GetToken (\r
-  IN  EFI_STRING_ID                Token,\r
-  IN  EFI_HII_HANDLE               HiiHandle\r
+  IN  EFI_STRING_ID   Token,\r
+  IN  EFI_HII_HANDLE  HiiHandle\r
   )\r
 {\r
   EFI_STRING  String;\r
 \r
+  if (HiiHandle == NULL) {\r
+    return NULL;\r
+  }\r
+\r
   String = HiiGetString (HiiHandle, Token, NULL);\r
   if (String == NULL) {\r
-    String = AllocateCopyPool (sizeof (mUnknownString), mUnknownString);\r
+    String = AllocateCopyPool (StrSize (mUnknownString), mUnknownString);\r
     ASSERT (String != NULL);\r
   }\r
-  return (CHAR16 *) String;\r
-}\r
 \r
+  return (CHAR16 *)String;\r
+}\r
 \r
 /**\r
   Allocate new memory and then copy the Unicode string Source to Destination.\r
@@ -681,18 +1053,18 @@ GetToken (
 **/\r
 VOID\r
 NewStringCpy (\r
-  IN OUT CHAR16       **Dest,\r
-  IN CHAR16           *Src\r
+  IN OUT CHAR16  **Dest,\r
+  IN CHAR16      *Src\r
   )\r
 {\r
   if (*Dest != NULL) {\r
     FreePool (*Dest);\r
   }\r
+\r
   *Dest = AllocateCopyPool (StrSize (Src), Src);\r
   ASSERT (*Dest != NULL);\r
 }\r
 \r
-\r
 /**\r
   Allocate new memory and concatinate Source on the end of Destination.\r
 \r
@@ -702,73 +1074,36 @@ NewStringCpy (
 **/\r
 VOID\r
 NewStringCat (\r
-  IN OUT CHAR16       **Dest,\r
-  IN CHAR16           *Src\r
+  IN OUT CHAR16  **Dest,\r
+  IN CHAR16      *Src\r
   )\r
 {\r
   CHAR16  *NewString;\r
-  UINTN   TmpSize;\r
+  UINTN   MaxLen;\r
 \r
   if (*Dest == NULL) {\r
     NewStringCpy (Dest, Src);\r
     return;\r
   }\r
 \r
-  TmpSize = StrSize (*Dest);\r
-  NewString = AllocateZeroPool (TmpSize + StrSize (Src) - 1);\r
+  MaxLen    = (StrSize (*Dest) + StrSize (Src) - 1) / sizeof (CHAR16);\r
+  NewString = AllocateZeroPool (MaxLen * sizeof (CHAR16));\r
   ASSERT (NewString != NULL);\r
 \r
-  StrCpy (NewString, *Dest);\r
-  StrCat (NewString, Src);\r
+  StrCpyS (NewString, MaxLen, *Dest);\r
+  StrCatS (NewString, MaxLen, Src);\r
 \r
   FreePool (*Dest);\r
   *Dest = NewString;\r
 }\r
 \r
-\r
-/**\r
-  Synchronize Storage's Edit copy to Shadow copy.\r
-\r
-  @param  Storage                The Storage to be synchronized.\r
-\r
-**/\r
-VOID\r
-SynchronizeStorage (\r
-  IN FORMSET_STORAGE         *Storage\r
-  )\r
-{\r
-  LIST_ENTRY              *Link;\r
-  NAME_VALUE_NODE         *Node;\r
-\r
-  switch (Storage->Type) {\r
-  case EFI_HII_VARSTORE_BUFFER:\r
-    CopyMem (Storage->Buffer, Storage->EditBuffer, Storage->Size);\r
-    break;\r
-\r
-  case EFI_HII_VARSTORE_NAME_VALUE:\r
-    Link = GetFirstNode (&Storage->NameValueListHead);\r
-    while (!IsNull (&Storage->NameValueListHead, Link)) {\r
-      Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
-\r
-      NewStringCpy (&Node->Value, Node->EditValue);\r
-\r
-      Link = GetNextNode (&Storage->NameValueListHead, Link);\r
-    }\r
-    break;\r
-\r
-  case EFI_HII_VARSTORE_EFI_VARIABLE:\r
-  default:\r
-    break;\r
-  }\r
-}\r
-\r
-\r
 /**\r
   Get Value for given Name from a NameValue Storage.\r
 \r
   @param  Storage                The NameValue Storage.\r
   @param  Name                   The Name.\r
   @param  Value                  The retured Value.\r
+  @param  GetValueFrom           Where to get source value, from EditValue or Value.\r
 \r
   @retval EFI_SUCCESS            Value found for given Name.\r
   @retval EFI_NOT_FOUND          No such Name found in NameValue storage.\r
@@ -776,13 +1111,18 @@ SynchronizeStorage (
 **/\r
 EFI_STATUS\r
 GetValueByName (\r
-  IN FORMSET_STORAGE         *Storage,\r
-  IN CHAR16                  *Name,\r
-  IN OUT CHAR16              **Value\r
+  IN BROWSER_STORAGE              *Storage,\r
+  IN CHAR16                       *Name,\r
+  IN OUT CHAR16                   **Value,\r
+  IN GET_SET_QUESTION_VALUE_WITH  GetValueFrom\r
   )\r
 {\r
-  LIST_ENTRY              *Link;\r
-  NAME_VALUE_NODE         *Node;\r
+  LIST_ENTRY       *Link;\r
+  NAME_VALUE_NODE  *Node;\r
+\r
+  if ((GetValueFrom != GetSetValueWithEditBuffer) && (GetValueFrom != GetSetValueWithBuffer)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
 \r
   *Value = NULL;\r
 \r
@@ -791,7 +1131,12 @@ GetValueByName (
     Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
 \r
     if (StrCmp (Name, Node->Name) == 0) {\r
-      NewStringCpy (Value, Node->EditValue);\r
+      if (GetValueFrom == GetSetValueWithEditBuffer) {\r
+        NewStringCpy (Value, Node->EditValue);\r
+      } else {\r
+        NewStringCpy (Value, Node->Value);\r
+      }\r
+\r
       return EFI_SUCCESS;\r
     }\r
 \r
@@ -801,13 +1146,14 @@ GetValueByName (
   return EFI_NOT_FOUND;\r
 }\r
 \r
-\r
 /**\r
   Set Value of given Name in a NameValue Storage.\r
 \r
   @param  Storage                The NameValue Storage.\r
   @param  Name                   The Name.\r
   @param  Value                  The Value to set.\r
+  @param  SetValueTo             Whether update editValue or Value.\r
+  @param  ReturnNode             The node use the input name.\r
 \r
   @retval EFI_SUCCESS            Value found for given Name.\r
   @retval EFI_NOT_FOUND          No such Name found in NameValue storage.\r
@@ -815,24 +1161,48 @@ GetValueByName (
 **/\r
 EFI_STATUS\r
 SetValueByName (\r
-  IN FORMSET_STORAGE         *Storage,\r
-  IN CHAR16                  *Name,\r
-  IN CHAR16                  *Value\r
+  IN  BROWSER_STORAGE              *Storage,\r
+  IN  CHAR16                       *Name,\r
+  IN  CHAR16                       *Value,\r
+  IN  GET_SET_QUESTION_VALUE_WITH  SetValueTo,\r
+  OUT NAME_VALUE_NODE              **ReturnNode\r
   )\r
 {\r
-  LIST_ENTRY              *Link;\r
-  NAME_VALUE_NODE         *Node;\r
+  LIST_ENTRY       *Link;\r
+  NAME_VALUE_NODE  *Node;\r
+  CHAR16           *Buffer;\r
+\r
+  if ((SetValueTo != GetSetValueWithEditBuffer) && (SetValueTo != GetSetValueWithBuffer)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
 \r
   Link = GetFirstNode (&Storage->NameValueListHead);\r
   while (!IsNull (&Storage->NameValueListHead, Link)) {\r
     Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
 \r
     if (StrCmp (Name, Node->Name) == 0) {\r
-      if (Node->EditValue != NULL) {\r
-        FreePool (Node->EditValue);\r
+      if (SetValueTo == GetSetValueWithEditBuffer) {\r
+        Buffer = Node->EditValue;\r
+      } else {\r
+        Buffer = Node->Value;\r
+      }\r
+\r
+      if (Buffer != NULL) {\r
+        FreePool (Buffer);\r
+      }\r
+\r
+      Buffer = AllocateCopyPool (StrSize (Value), Value);\r
+      ASSERT (Buffer != NULL);\r
+      if (SetValueTo == GetSetValueWithEditBuffer) {\r
+        Node->EditValue = Buffer;\r
+      } else {\r
+        Node->Value = Buffer;\r
+      }\r
+\r
+      if (ReturnNode != NULL) {\r
+        *ReturnNode = Node;\r
       }\r
-      Node->EditValue = AllocateCopyPool (StrSize (Value), Value);\r
-      ASSERT (Node->EditValue != NULL);\r
+\r
       return EFI_SUCCESS;\r
     }\r
 \r
@@ -842,12 +1212,13 @@ SetValueByName (
   return EFI_NOT_FOUND;\r
 }\r
 \r
-\r
 /**\r
   Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.\r
 \r
   @param  Storage                The Storage to be conveted.\r
   @param  ConfigResp             The returned <ConfigResp>.\r
+  @param  ConfigRequest          The ConfigRequest string.\r
+  @param  GetEditBuf             Get the data from editbuffer or buffer.\r
 \r
   @retval EFI_SUCCESS            Convert success.\r
   @retval EFI_INVALID_PARAMETER  Incorrect storage type.\r
@@ -855,56 +1226,70 @@ SetValueByName (
 **/\r
 EFI_STATUS\r
 StorageToConfigResp (\r
-  IN FORMSET_STORAGE         *Storage,\r
-  IN CHAR16                  **ConfigResp\r
+  IN BROWSER_STORAGE  *Storage,\r
+  IN CHAR16           **ConfigResp,\r
+  IN CHAR16           *ConfigRequest,\r
+  IN BOOLEAN          GetEditBuf\r
   )\r
 {\r
-  EFI_STATUS  Status;\r
-  EFI_STRING  Progress;\r
-  LIST_ENTRY              *Link;\r
-  NAME_VALUE_NODE         *Node;\r
+  EFI_STATUS       Status;\r
+  EFI_STRING       Progress;\r
+  LIST_ENTRY       *Link;\r
+  NAME_VALUE_NODE  *Node;\r
+  UINT8            *SourceBuf;\r
+  FORMSET_STORAGE  *FormsetStorage;\r
 \r
   Status = EFI_SUCCESS;\r
 \r
   switch (Storage->Type) {\r
-  case EFI_HII_VARSTORE_BUFFER:\r
-    Status = mHiiConfigRouting->BlockToConfig (\r
-                                  mHiiConfigRouting,\r
-                                  Storage->ConfigRequest,\r
-                                  Storage->EditBuffer,\r
-                                  Storage->Size,\r
-                                  ConfigResp,\r
-                                  &Progress\r
-                                  );\r
-    break;\r
-\r
-  case EFI_HII_VARSTORE_NAME_VALUE:\r
-    *ConfigResp = NULL;\r
-    NewStringCat (ConfigResp, Storage->ConfigHdr);\r
-\r
-    Link = GetFirstNode (&Storage->NameValueListHead);\r
-    while (!IsNull (&Storage->NameValueListHead, Link)) {\r
-      Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
+    case EFI_HII_VARSTORE_BUFFER:\r
+    case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
+      SourceBuf = GetEditBuf ? Storage->EditBuffer : Storage->Buffer;\r
+      Status    = mHiiConfigRouting->BlockToConfig (\r
+                                       mHiiConfigRouting,\r
+                                       ConfigRequest,\r
+                                       SourceBuf,\r
+                                       Storage->Size,\r
+                                       ConfigResp,\r
+                                       &Progress\r
+                                       );\r
+      break;\r
+\r
+    case EFI_HII_VARSTORE_NAME_VALUE:\r
+      *ConfigResp    = NULL;\r
+      FormsetStorage = GetFstStgFromBrsStg (Storage);\r
+      ASSERT (FormsetStorage != NULL);\r
+      NewStringCat (ConfigResp, FormsetStorage->ConfigHdr);\r
+\r
+      Link = GetFirstNode (&Storage->NameValueListHead);\r
+      while (!IsNull (&Storage->NameValueListHead, Link)) {\r
+        Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
+\r
+        if (StrStr (ConfigRequest, Node->Name) != NULL) {\r
+          NewStringCat (ConfigResp, L"&");\r
+          NewStringCat (ConfigResp, Node->Name);\r
+          NewStringCat (ConfigResp, L"=");\r
+          if (GetEditBuf) {\r
+            NewStringCat (ConfigResp, Node->EditValue);\r
+          } else {\r
+            NewStringCat (ConfigResp, Node->Value);\r
+          }\r
+        }\r
 \r
-      NewStringCat (ConfigResp, L"&");\r
-      NewStringCat (ConfigResp, Node->Name);\r
-      NewStringCat (ConfigResp, L"=");\r
-      NewStringCat (ConfigResp, Node->EditValue);\r
+        Link = GetNextNode (&Storage->NameValueListHead, Link);\r
+      }\r
 \r
-      Link = GetNextNode (&Storage->NameValueListHead, Link);\r
-    }\r
-    break;\r
+      break;\r
 \r
-  case EFI_HII_VARSTORE_EFI_VARIABLE:\r
-  default:\r
-    Status = EFI_INVALID_PARAMETER;\r
-    break;\r
+    case EFI_HII_VARSTORE_EFI_VARIABLE:\r
+    default:\r
+      Status = EFI_INVALID_PARAMETER;\r
+      break;\r
   }\r
 \r
   return Status;\r
 }\r
 \r
-\r
 /**\r
   Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.\r
 \r
@@ -917,8 +1302,8 @@ StorageToConfigResp (
 **/\r
 EFI_STATUS\r
 ConfigRespToStorage (\r
-  IN FORMSET_STORAGE         *Storage,\r
-  IN CHAR16                  *ConfigResp\r
+  IN BROWSER_STORAGE  *Storage,\r
+  IN CHAR16           *ConfigResp\r
   )\r
 {\r
   EFI_STATUS  Status;\r
@@ -931,53 +1316,255 @@ ConfigRespToStorage (
   Status = EFI_SUCCESS;\r
 \r
   switch (Storage->Type) {\r
-  case EFI_HII_VARSTORE_BUFFER:\r
-    BufferSize = Storage->Size;\r
-    Status = mHiiConfigRouting->ConfigToBlock (\r
-                                  mHiiConfigRouting,\r
-                                  ConfigResp,\r
-                                  Storage->EditBuffer,\r
-                                  &BufferSize,\r
-                                  &Progress\r
-                                  );\r
-    break;\r
+    case EFI_HII_VARSTORE_BUFFER:\r
+    case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
+      BufferSize = Storage->Size;\r
+      Status     = mHiiConfigRouting->ConfigToBlock (\r
+                                        mHiiConfigRouting,\r
+                                        ConfigResp,\r
+                                        Storage->EditBuffer,\r
+                                        &BufferSize,\r
+                                        &Progress\r
+                                        );\r
+      break;\r
 \r
-  case EFI_HII_VARSTORE_NAME_VALUE:\r
-    StrPtr = StrStr (ConfigResp, L"&");\r
-    while (StrPtr != NULL) {\r
-      //\r
-      // Skip '&'\r
-      //\r
-      StrPtr = StrPtr + 1;\r
-      Name = StrPtr;\r
-      StrPtr = StrStr (StrPtr, L"=");\r
+    case EFI_HII_VARSTORE_NAME_VALUE:\r
+      StrPtr = StrStr (ConfigResp, L"PATH");\r
       if (StrPtr == NULL) {\r
         break;\r
       }\r
-      *StrPtr = 0;\r
 \r
-      //\r
-      // Skip '='\r
-      //\r
-      StrPtr = StrPtr + 1;\r
-      Value = StrPtr;\r
-      StrPtr = StrStr (StrPtr, L"&");\r
-      if (StrPtr != NULL) {\r
+      StrPtr = StrStr (ConfigResp, L"&");\r
+      while (StrPtr != NULL) {\r
+        //\r
+        // Skip '&'\r
+        //\r
+        StrPtr = StrPtr + 1;\r
+        Name   = StrPtr;\r
+        StrPtr = StrStr (StrPtr, L"=");\r
+        if (StrPtr == NULL) {\r
+          break;\r
+        }\r
+\r
         *StrPtr = 0;\r
+\r
+        //\r
+        // Skip '='\r
+        //\r
+        StrPtr = StrPtr + 1;\r
+        Value  = StrPtr;\r
+        StrPtr = StrStr (StrPtr, L"&");\r
+        if (StrPtr != NULL) {\r
+          *StrPtr = 0;\r
+        }\r
+\r
+        SetValueByName (Storage, Name, Value, GetSetValueWithEditBuffer, NULL);\r
       }\r
-      SetValueByName (Storage, Name, Value);\r
-    }\r
-    break;\r
 \r
-  case EFI_HII_VARSTORE_EFI_VARIABLE:\r
-  default:\r
-    Status = EFI_INVALID_PARAMETER;\r
-    break;\r
+      break;\r
+\r
+    case EFI_HII_VARSTORE_EFI_VARIABLE:\r
+    default:\r
+      Status = EFI_INVALID_PARAMETER;\r
+      break;\r
   }\r
 \r
   return Status;\r
 }\r
 \r
+/**\r
+  Get bit field value from the buffer and then set the value for the question.\r
+  Note: Data type UINT32 can cover all the bit field value.\r
+\r
+  @param  Question        The question refer to bit field.\r
+  @param  Buffer          Point to the buffer which the question value get from.\r
+\r
+**/\r
+VOID\r
+GetBitsQuestionValue (\r
+  IN  FORM_BROWSER_STATEMENT  *Question,\r
+  IN  UINT8                   *Buffer\r
+  )\r
+{\r
+  UINTN   StartBit;\r
+  UINTN   EndBit;\r
+  UINT32  RetVal;\r
+  UINT32  BufferValue;\r
+\r
+  StartBit = Question->BitVarOffset % 8;\r
+  EndBit   = StartBit + Question->BitStorageWidth - 1;\r
+\r
+  CopyMem ((UINT8 *)&BufferValue, Buffer, Question->StorageWidth);\r
+\r
+  RetVal = BitFieldRead32 (BufferValue, StartBit, EndBit);\r
+\r
+  //\r
+  // Set question value.\r
+  // Note: Since Question with BufferValue (orderedlist, password, string)are not supported to refer bit field.\r
+  // Only oneof/checkbox/oneof can support bit field.So we can copy the value to the Hiivalue of Question directly.\r
+  //\r
+  CopyMem ((UINT8 *)&Question->HiiValue.Value, (UINT8 *)&RetVal, Question->StorageWidth);\r
+}\r
+\r
+/**\r
+  Set bit field value to the buffer.\r
+  Note: Data type UINT32 can cover all the bit field value.\r
+\r
+  @param  Question        The question refer to bit field.\r
+  @param  Buffer          Point to the buffer which the question value set to.\r
+  @param  Value           The bit field value need to set.\r
+\r
+**/\r
+VOID\r
+SetBitsQuestionValue (\r
+  IN     FORM_BROWSER_STATEMENT  *Question,\r
+  IN OUT UINT8                   *Buffer,\r
+  IN     UINT32                  Value\r
+  )\r
+{\r
+  UINT32  Operand;\r
+  UINTN   StartBit;\r
+  UINTN   EndBit;\r
+  UINT32  RetVal;\r
+\r
+  StartBit = Question->BitVarOffset % 8;\r
+  EndBit   = StartBit + Question->BitStorageWidth - 1;\r
+\r
+  CopyMem ((UINT8 *)&Operand, Buffer, Question->StorageWidth);\r
+\r
+  RetVal = BitFieldWrite32 (Operand, StartBit, EndBit, Value);\r
+\r
+  CopyMem (Buffer, (UINT8 *)&RetVal, Question->StorageWidth);\r
+}\r
+\r
+/**\r
+  Convert the buffer value to HiiValue.\r
+\r
+  @param  Question               The question.\r
+  @param  Value                  Unicode buffer save the question value.\r
+\r
+  @retval  Status whether convert the value success.\r
+\r
+**/\r
+EFI_STATUS\r
+BufferToValue (\r
+  IN OUT FORM_BROWSER_STATEMENT  *Question,\r
+  IN     CHAR16                  *Value\r
+  )\r
+{\r
+  CHAR16      *StringPtr;\r
+  BOOLEAN     IsBufferStorage;\r
+  CHAR16      *DstBuf;\r
+  CHAR16      TempChar;\r
+  UINTN       LengthStr;\r
+  UINT8       *Dst;\r
+  CHAR16      TemStr[5];\r
+  UINTN       Index;\r
+  UINT8       DigitUint8;\r
+  BOOLEAN     IsString;\r
+  UINTN       Length;\r
+  EFI_STATUS  Status;\r
+  UINT8       *Buffer;\r
+\r
+  Buffer = NULL;\r
+\r
+  IsString = (BOOLEAN)((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ?  TRUE : FALSE);\r
+  if ((Question->Storage->Type == EFI_HII_VARSTORE_BUFFER) ||\r
+      (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER))\r
+  {\r
+    IsBufferStorage = TRUE;\r
+  } else {\r
+    IsBufferStorage = FALSE;\r
+  }\r
+\r
+  //\r
+  // Question Value is provided by Buffer Storage or NameValue Storage\r
+  //\r
+  if (Question->BufferValue != NULL) {\r
+    //\r
+    // This Question is password or orderedlist\r
+    //\r
+    Dst = Question->BufferValue;\r
+  } else {\r
+    //\r
+    // Other type of Questions\r
+    //\r
+    if (Question->QuestionReferToBitField) {\r
+      Buffer = (UINT8 *)AllocateZeroPool (Question->StorageWidth);\r
+      if (Buffer == NULL) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      Dst = Buffer;\r
+    } else {\r
+      Dst = (UINT8 *)&Question->HiiValue.Value;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Temp cut at the end of this section, end with '\0' or '&'.\r
+  //\r
+  StringPtr = Value;\r
+  while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
+    StringPtr++;\r
+  }\r
+\r
+  TempChar   = *StringPtr;\r
+  *StringPtr = L'\0';\r
+\r
+  LengthStr = StrLen (Value);\r
+\r
+  //\r
+  // Value points to a Unicode hexadecimal string, we need to convert the string to the value with CHAR16/UINT8...type.\r
+  // When generating the Value string, we follow this rule: 1 byte -> 2 Unicode characters (for string: 2 byte(CHAR16) ->4 Unicode characters).\r
+  // So the maximum value string length of a question is : Question->StorageWidth * 2.\r
+  // If the value string length > Question->StorageWidth * 2, only set the string length as Question->StorageWidth * 2, then convert.\r
+  //\r
+  if (LengthStr > (UINTN)Question->StorageWidth * 2) {\r
+    Length = (UINTN)Question->StorageWidth * 2;\r
+  } else {\r
+    Length = LengthStr;\r
+  }\r
+\r
+  Status = EFI_SUCCESS;\r
+  if (!IsBufferStorage && IsString) {\r
+    //\r
+    // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
+    // Add string tail char L'\0' into Length\r
+    //\r
+    DstBuf = (CHAR16 *)Dst;\r
+    ZeroMem (TemStr, sizeof (TemStr));\r
+    for (Index = 0; Index < Length; Index += 4) {\r
+      StrnCpyS (TemStr, sizeof (TemStr) / sizeof (CHAR16), Value + Index, 4);\r
+      DstBuf[Index/4] = (CHAR16)StrHexToUint64 (TemStr);\r
+    }\r
+\r
+    //\r
+    // Add tailing L'\0' character\r
+    //\r
+    DstBuf[Index/4] = L'\0';\r
+  } else {\r
+    ZeroMem (TemStr, sizeof (TemStr));\r
+    for (Index = 0; Index < Length; Index++) {\r
+      TemStr[0]  = Value[LengthStr - Index - 1];\r
+      DigitUint8 = (UINT8)StrHexToUint64 (TemStr);\r
+      if ((Index & 1) == 0) {\r
+        Dst[Index/2] = DigitUint8;\r
+      } else {\r
+        Dst[Index/2] = (UINT8)((DigitUint8 << 4) + Dst[Index/2]);\r
+      }\r
+    }\r
+  }\r
+\r
+  *StringPtr = TempChar;\r
+\r
+  if ((Buffer != NULL) && Question->QuestionReferToBitField) {\r
+    GetBitsQuestionValue (Question, Buffer);\r
+    FreePool (Buffer);\r
+  }\r
+\r
+  return Status;\r
+}\r
 \r
 /**\r
   Get Question's current Value.\r
@@ -985,18 +1572,17 @@ ConfigRespToStorage (
   @param  FormSet                FormSet data structure.\r
   @param  Form                   Form data structure.\r
   @param  Question               Question to be initialized.\r
-  @param  Cached                 TRUE:  get from Edit copy FALSE: get from original\r
-                                 Storage\r
+  @param  GetValueFrom           Where to get value, may from editbuffer, buffer or hii driver.\r
 \r
   @retval EFI_SUCCESS            The function completed successfully.\r
 \r
 **/\r
 EFI_STATUS\r
 GetQuestionValue (\r
-  IN FORM_BROWSER_FORMSET             *FormSet,\r
-  IN FORM_BROWSER_FORM                *Form,\r
-  IN OUT FORM_BROWSER_STATEMENT       *Question,\r
-  IN BOOLEAN                          Cached\r
+  IN FORM_BROWSER_FORMSET         *FormSet,\r
+  IN FORM_BROWSER_FORM            *Form,\r
+  IN OUT FORM_BROWSER_STATEMENT   *Question,\r
+  IN GET_SET_QUESTION_VALUE_WITH  GetValueFrom\r
   )\r
 {\r
   EFI_STATUS          Status;\r
@@ -1005,28 +1591,23 @@ GetQuestionValue (
   UINT8               *Dst;\r
   UINTN               StorageWidth;\r
   EFI_TIME            EfiTime;\r
-  FORMSET_STORAGE     *Storage;\r
+  BROWSER_STORAGE     *Storage;\r
+  FORMSET_STORAGE     *FormsetStorage;\r
   EFI_IFR_TYPE_VALUE  *QuestionValue;\r
   CHAR16              *ConfigRequest;\r
   CHAR16              *Progress;\r
   CHAR16              *Result;\r
   CHAR16              *Value;\r
-  CHAR16              *StringPtr;\r
   UINTN               Length;\r
-  UINTN               Index;\r
-  UINTN               LengthStr;\r
   BOOLEAN             IsBufferStorage;\r
-  BOOLEAN             IsString;\r
-  CHAR16              TemStr[5];\r
-  UINT8               DigitUint8;\r
+  UINTN               MaxLen;\r
 \r
   Status = EFI_SUCCESS;\r
+  Value  = NULL;\r
+  Result = NULL;\r
 \r
-  //\r
-  // Statement don't have storage, skip them\r
-  //\r
-  if (Question->QuestionId == 0) {\r
-    return Status;\r
+  if (GetValueFrom >= GetSetValueWithMax) {\r
+    return EFI_INVALID_PARAMETER;\r
   }\r
 \r
   //\r
@@ -1035,43 +1616,98 @@ GetQuestionValue (
   if (Question->ValueExpression != NULL) {\r
     Status = EvaluateExpression (FormSet, Form, Question->ValueExpression);\r
     if (!EFI_ERROR (Status)) {\r
-      CopyMem (&Question->HiiValue, &Question->ValueExpression->Result, sizeof (EFI_HII_VALUE));\r
+      if (Question->ValueExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {\r
+        ASSERT (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER && Question->HiiValue.Buffer != NULL);\r
+        if (Question->StorageWidth > Question->ValueExpression->Result.BufferLen) {\r
+          CopyMem (Question->HiiValue.Buffer, Question->ValueExpression->Result.Buffer, Question->ValueExpression->Result.BufferLen);\r
+          Question->HiiValue.BufferLen = Question->ValueExpression->Result.BufferLen;\r
+        } else {\r
+          CopyMem (Question->HiiValue.Buffer, Question->ValueExpression->Result.Buffer, Question->StorageWidth);\r
+          Question->HiiValue.BufferLen = Question->StorageWidth;\r
+        }\r
+\r
+        FreePool (Question->ValueExpression->Result.Buffer);\r
+      }\r
+\r
+      Question->HiiValue.Type = Question->ValueExpression->Result.Type;\r
+      CopyMem (&Question->HiiValue.Value, &Question->ValueExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE));\r
     }\r
+\r
     return Status;\r
   }\r
 \r
+  //\r
+  // Get question value by read expression.\r
+  //\r
+  if ((Question->ReadExpression != NULL) && (Form->FormType == STANDARD_MAP_FORM_TYPE)) {\r
+    Status = EvaluateExpression (FormSet, Form, Question->ReadExpression);\r
+    if (!EFI_ERROR (Status) &&\r
+        ((Question->ReadExpression->Result.Type < EFI_IFR_TYPE_OTHER) || (Question->ReadExpression->Result.Type == EFI_IFR_TYPE_BUFFER)))\r
+    {\r
+      //\r
+      // Only update question value to the valid result.\r
+      //\r
+      if (Question->ReadExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {\r
+        ASSERT (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER && Question->HiiValue.Buffer != NULL);\r
+        if (Question->StorageWidth > Question->ReadExpression->Result.BufferLen) {\r
+          CopyMem (Question->HiiValue.Buffer, Question->ReadExpression->Result.Buffer, Question->ReadExpression->Result.BufferLen);\r
+          Question->HiiValue.BufferLen = Question->ReadExpression->Result.BufferLen;\r
+        } else {\r
+          CopyMem (Question->HiiValue.Buffer, Question->ReadExpression->Result.Buffer, Question->StorageWidth);\r
+          Question->HiiValue.BufferLen = Question->StorageWidth;\r
+        }\r
+\r
+        FreePool (Question->ReadExpression->Result.Buffer);\r
+      }\r
+\r
+      Question->HiiValue.Type = Question->ReadExpression->Result.Type;\r
+      CopyMem (&Question->HiiValue.Value, &Question->ReadExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE));\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
   //\r
   // Question value is provided by RTC\r
   //\r
-  Storage = Question->Storage;\r
+  Storage       = Question->Storage;\r
   QuestionValue = &Question->HiiValue.Value;\r
   if (Storage == NULL) {\r
     //\r
     // It's a Question without storage, or RTC date/time\r
     //\r
-    if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {\r
+    if ((Question->Operand == EFI_IFR_DATE_OP) || (Question->Operand == EFI_IFR_TIME_OP)) {\r
       //\r
       // Date and time define the same Flags bit\r
       //\r
       switch (Question->Flags & EFI_QF_DATE_STORAGE) {\r
-      case QF_DATE_STORAGE_TIME:\r
-        Status = gRT->GetTime (&EfiTime, NULL);\r
-        break;\r
+        case QF_DATE_STORAGE_TIME:\r
+          Status = gRT->GetTime (&EfiTime, NULL);\r
+          break;\r
 \r
-      case QF_DATE_STORAGE_WAKEUP:\r
-        Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
-        break;\r
+        case QF_DATE_STORAGE_WAKEUP:\r
+          Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
+          break;\r
 \r
-      case QF_DATE_STORAGE_NORMAL:\r
-      default:\r
-        //\r
-        // For date/time without storage\r
-        //\r
-        return EFI_SUCCESS;\r
+        case QF_DATE_STORAGE_NORMAL:\r
+        default:\r
+          //\r
+          // For date/time without storage\r
+          //\r
+          return EFI_SUCCESS;\r
       }\r
 \r
       if (EFI_ERROR (Status)) {\r
-        return Status;\r
+        if (Question->Operand == EFI_IFR_DATE_OP) {\r
+          QuestionValue->date.Year  = 0xff;\r
+          QuestionValue->date.Month = 0xff;\r
+          QuestionValue->date.Day   = 0xff;\r
+        } else {\r
+          QuestionValue->time.Hour   = 0xff;\r
+          QuestionValue->time.Minute = 0xff;\r
+          QuestionValue->time.Second = 0xff;\r
+        }\r
+\r
+        return EFI_SUCCESS;\r
       }\r
 \r
       if (Question->Operand == EFI_IFR_DATE_OP) {\r
@@ -1096,16 +1732,16 @@ GetQuestionValue (
     if (Question->BufferValue != NULL) {\r
       Dst = Question->BufferValue;\r
     } else {\r
-      Dst = (UINT8 *) QuestionValue;\r
+      Dst = (UINT8 *)QuestionValue;\r
     }\r
 \r
     Status = gRT->GetVariable (\r
-                     Question->VariableName,\r
-                     &Storage->Guid,\r
-                     NULL,\r
-                     &StorageWidth,\r
-                     Dst\r
-                     );\r
+                    Question->VariableName,\r
+                    &Storage->Guid,\r
+                    NULL,\r
+                    &StorageWidth,\r
+                    Dst\r
+                    );\r
     //\r
     // Always return success, even this EFI variable doesn't exist\r
     //\r
@@ -1124,100 +1760,89 @@ GetQuestionValue (
     //\r
     // Other type of Questions\r
     //\r
-    Dst = (UINT8 *) &Question->HiiValue.Value;\r
+    Dst = (UINT8 *)&Question->HiiValue.Value;\r
   }\r
 \r
-  IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);\r
-  IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ?  TRUE : FALSE);\r
-  if (Cached) {\r
-    if (IsBufferStorage) {\r
-      //\r
-      // Copy from storage Edit buffer\r
-      //\r
-      CopyMem (Dst, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth);\r
-    } else {\r
-      Status = GetValueByName (Storage, Question->VariableName, &Value);\r
-      if (EFI_ERROR (Status)) {\r
-        return Status;\r
-      }\r
+  if ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ||\r
+      (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER))\r
+  {\r
+    IsBufferStorage = TRUE;\r
+  } else {\r
+    IsBufferStorage = FALSE;\r
+  }\r
 \r
-      LengthStr = StrLen (Value);\r
-      Status    = EFI_SUCCESS;\r
-      if (IsString) {\r
+  if ((GetValueFrom == GetSetValueWithEditBuffer) || (GetValueFrom == GetSetValueWithBuffer)) {\r
+    if (IsBufferStorage) {\r
+      if (GetValueFrom == GetSetValueWithEditBuffer) {\r
         //\r
-        // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
-        // Add string tail char L'\0' into Length\r
+        // Copy from storage Edit buffer\r
+        // If the Question refer to bit filed, get the value in the related bit filed.\r
         //\r
-        Length    = StorageWidth + sizeof (CHAR16);\r
-        if (Length < ((LengthStr / 4 + 1) * 2)) {\r
-          Status = EFI_BUFFER_TOO_SMALL;\r
+        if (Question->QuestionReferToBitField) {\r
+          GetBitsQuestionValue (Question, Storage->EditBuffer + Question->VarStoreInfo.VarOffset);\r
         } else {\r
-          StringPtr = (CHAR16 *) Dst;\r
-          ZeroMem (TemStr, sizeof (TemStr));\r
-          for (Index = 0; Index < LengthStr; Index += 4) {\r
-            StrnCpy (TemStr, Value + Index, 4);\r
-            StringPtr[Index/4] = (CHAR16) StrHexToUint64 (TemStr);\r
-          }\r
-          //\r
-          // Add tailing L'\0' character\r
-          //\r
-          StringPtr[Index/4] = L'\0';\r
+          CopyMem (Dst, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth);\r
         }\r
       } else {\r
-        if (StorageWidth < ((LengthStr + 1) / 2)) {\r
-          Status = EFI_BUFFER_TOO_SMALL;\r
+        //\r
+        // Copy from storage Edit buffer\r
+        // If the Question refer to bit filed, get the value in the related bit filed.\r
+        //\r
+        if (Question->QuestionReferToBitField) {\r
+          GetBitsQuestionValue (Question, Storage->Buffer + Question->VarStoreInfo.VarOffset);\r
         } else {\r
-          ZeroMem (TemStr, sizeof (TemStr));\r
-          for (Index = 0; Index < LengthStr; Index ++) {\r
-            TemStr[0] = Value[LengthStr - Index - 1];\r
-            DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
-            if ((Index & 1) == 0) {\r
-              Dst [Index/2] = DigitUint8;\r
-            } else {\r
-              Dst [Index/2] = (UINT8) ((DigitUint8 << 4) + Dst [Index/2]);\r
-            }\r
-          }\r
+          CopyMem (Dst, Storage->Buffer + Question->VarStoreInfo.VarOffset, StorageWidth);\r
         }\r
       }\r
+    } else {\r
+      Value  = NULL;\r
+      Status = GetValueByName (Storage, Question->VariableName, &Value, GetValueFrom);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
 \r
+      ASSERT (Value != NULL);\r
+      Status = BufferToValue (Question, Value);\r
       FreePool (Value);\r
     }\r
   } else {\r
-    //\r
-    // Request current settings from Configuration Driver\r
-    //\r
-    if (FormSet->ConfigAccess == NULL) {\r
-      return EFI_NOT_FOUND;\r
-    }\r
-\r
+    FormsetStorage = GetFstStgFromVarId (FormSet, Question->VarStoreId);\r
+    ASSERT (FormsetStorage != NULL);\r
     //\r
     // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||\r
     //                   <ConfigHdr> + "&" + <VariableName>\r
     //\r
     if (IsBufferStorage) {\r
-      Length = StrLen (Storage->ConfigHdr);\r
+      Length  = StrLen (FormsetStorage->ConfigHdr);\r
       Length += StrLen (Question->BlockName);\r
     } else {\r
-      Length = StrLen (Storage->ConfigHdr);\r
+      Length  = StrLen (FormsetStorage->ConfigHdr);\r
       Length += StrLen (Question->VariableName) + 1;\r
     }\r
-    ConfigRequest = AllocateZeroPool ((Length + 1) * sizeof (CHAR16));\r
+\r
+    // Allocate buffer include '\0'\r
+    MaxLen        = Length + 1;\r
+    ConfigRequest = AllocateZeroPool (MaxLen * sizeof (CHAR16));\r
     ASSERT (ConfigRequest != NULL);\r
 \r
-    StrCpy (ConfigRequest, Storage->ConfigHdr);\r
+    StrCpyS (ConfigRequest, MaxLen, FormsetStorage->ConfigHdr);\r
     if (IsBufferStorage) {\r
-      StrCat (ConfigRequest, Question->BlockName);\r
+      StrCatS (ConfigRequest, MaxLen, Question->BlockName);\r
     } else {\r
-      StrCat (ConfigRequest, L"&");\r
-      StrCat (ConfigRequest, Question->VariableName);\r
+      StrCatS (ConfigRequest, MaxLen, L"&");\r
+      StrCatS (ConfigRequest, MaxLen, Question->VariableName);\r
     }\r
 \r
-    Status = FormSet->ConfigAccess->ExtractConfig (\r
-                                      FormSet->ConfigAccess,\r
-                                      ConfigRequest,\r
-                                      &Progress,\r
-                                      &Result\r
-                                      );\r
+    //\r
+    // Request current settings from Configuration Driver\r
+    //\r
+    Status = mHiiConfigRouting->ExtractConfig (\r
+                                  mHiiConfigRouting,\r
+                                  ConfigRequest,\r
+                                  &Progress,\r
+                                  &Result\r
+                                  );\r
+    FreePool (ConfigRequest);\r
     if (EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
@@ -1225,70 +1850,32 @@ GetQuestionValue (
     //\r
     // Skip <ConfigRequest>\r
     //\r
-    Value = Result + Length;\r
     if (IsBufferStorage) {\r
+      Value = StrStr (Result, L"&VALUE");\r
+      if (Value == NULL) {\r
+        FreePool (Result);\r
+        return EFI_NOT_FOUND;\r
+      }\r
+\r
       //\r
       // Skip "&VALUE"\r
       //\r
       Value = Value + 6;\r
+    } else {\r
+      Value = Result + Length;\r
     }\r
+\r
     if (*Value != '=') {\r
       FreePool (Result);\r
       return EFI_NOT_FOUND;\r
     }\r
+\r
     //\r
     // Skip '=', point to value\r
     //\r
     Value = Value + 1;\r
 \r
-    //\r
-    // Suppress <AltResp> if any\r
-    //\r
-    StringPtr = Value;\r
-    while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
-      StringPtr++;\r
-    }\r
-    *StringPtr = L'\0';\r
-\r
-    LengthStr = StrLen (Value);\r
-    Status    = EFI_SUCCESS;\r
-    if (!IsBufferStorage && IsString) {\r
-      //\r
-      // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
-      // Add string tail char L'\0' into Length\r
-      //\r
-      Length    = StorageWidth + sizeof (CHAR16);\r
-      if (Length < ((LengthStr / 4 + 1) * 2)) {\r
-        Status = EFI_BUFFER_TOO_SMALL;\r
-      } else {\r
-        StringPtr = (CHAR16 *) Dst;\r
-        ZeroMem (TemStr, sizeof (TemStr));\r
-        for (Index = 0; Index < LengthStr; Index += 4) {\r
-          StrnCpy (TemStr, Value + Index, 4);\r
-          StringPtr[Index/4] = (CHAR16) StrHexToUint64 (TemStr);\r
-        }\r
-        //\r
-        // Add tailing L'\0' character\r
-        //\r
-        StringPtr[Index/4] = L'\0';\r
-      }\r
-    } else {\r
-      if (StorageWidth < ((LengthStr + 1) / 2)) {\r
-        Status = EFI_BUFFER_TOO_SMALL;\r
-      } else {\r
-        ZeroMem (TemStr, sizeof (TemStr));\r
-        for (Index = 0; Index < LengthStr; Index ++) {\r
-          TemStr[0] = Value[LengthStr - Index - 1];\r
-          DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
-          if ((Index & 1) == 0) {\r
-            Dst [Index/2] = DigitUint8;\r
-          } else {\r
-            Dst [Index/2] = (UINT8) ((DigitUint8 << 4) + Dst [Index/2]);\r
-          }\r
-        }\r
-      }\r
-    }\r
-\r
+    Status = BufferToValue (Question, Value);\r
     if (EFI_ERROR (Status)) {\r
       FreePool (Result);\r
       return Status;\r
@@ -1300,34 +1887,34 @@ GetQuestionValue (
     if (IsBufferStorage) {\r
       CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth);\r
     } else {\r
-      SetValueByName (Storage, Question->VariableName, Value);\r
+      SetValueByName (Storage, Question->VariableName, Value, GetSetValueWithEditBuffer, NULL);\r
     }\r
 \r
-    FreePool (Result);\r
+    if (Result != NULL) {\r
+      FreePool (Result);\r
+    }\r
   }\r
 \r
   return Status;\r
 }\r
 \r
-\r
 /**\r
   Save Question Value to edit copy(cached) or Storage(uncached).\r
 \r
   @param  FormSet                FormSet data structure.\r
   @param  Form                   Form data structure.\r
   @param  Question               Pointer to the Question.\r
-  @param  Cached                 TRUE:  set to Edit copy FALSE: set to original\r
-                                 Storage\r
+  @param  SetValueTo             Update the question value to editbuffer , buffer or hii driver.\r
 \r
   @retval EFI_SUCCESS            The function completed successfully.\r
 \r
 **/\r
 EFI_STATUS\r
 SetQuestionValue (\r
-  IN FORM_BROWSER_FORMSET             *FormSet,\r
-  IN FORM_BROWSER_FORM                *Form,\r
-  IN OUT FORM_BROWSER_STATEMENT       *Question,\r
-  IN BOOLEAN                          Cached\r
+  IN FORM_BROWSER_FORMSET         *FormSet,\r
+  IN FORM_BROWSER_FORM            *Form,\r
+  IN OUT FORM_BROWSER_STATEMENT   *Question,\r
+  IN GET_SET_QUESTION_VALUE_WITH  SetValueTo\r
   )\r
 {\r
   EFI_STATUS          Status;\r
@@ -1337,7 +1924,8 @@ SetQuestionValue (
   EFI_TIME            EfiTime;\r
   UINTN               BufferLen;\r
   UINTN               StorageWidth;\r
-  FORMSET_STORAGE     *Storage;\r
+  BROWSER_STORAGE     *Storage;\r
+  FORMSET_STORAGE     *FormsetStorage;\r
   EFI_IFR_TYPE_VALUE  *QuestionValue;\r
   CHAR16              *ConfigResp;\r
   CHAR16              *Progress;\r
@@ -1349,14 +1937,14 @@ SetQuestionValue (
   CHAR16              *TemName;\r
   CHAR16              *TemString;\r
   UINTN               Index;\r
+  NAME_VALUE_NODE     *Node;\r
+  UINTN               MaxLen;\r
 \r
   Status = EFI_SUCCESS;\r
+  Node   = NULL;\r
 \r
-  //\r
-  // Statement don't have storage, skip them\r
-  //\r
-  if (Question->QuestionId == 0) {\r
-    return Status;\r
+  if (SetValueTo >= GetSetValueWithMax) {\r
+    return EFI_INVALID_PARAMETER;\r
   }\r
 \r
   //\r
@@ -1366,34 +1954,44 @@ SetQuestionValue (
     return Status;\r
   }\r
 \r
+  //\r
+  // Before set question value, evaluate its write expression.\r
+  //\r
+  if ((Question->WriteExpression != NULL) && (Form->FormType == STANDARD_MAP_FORM_TYPE)) {\r
+    Status = EvaluateExpression (FormSet, Form, Question->WriteExpression);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
   //\r
   // Question value is provided by RTC\r
   //\r
-  Storage = Question->Storage;\r
+  Storage       = Question->Storage;\r
   QuestionValue = &Question->HiiValue.Value;\r
   if (Storage == NULL) {\r
     //\r
     // It's a Question without storage, or RTC date/time\r
     //\r
-    if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {\r
+    if ((Question->Operand == EFI_IFR_DATE_OP) || (Question->Operand == EFI_IFR_TIME_OP)) {\r
       //\r
       // Date and time define the same Flags bit\r
       //\r
       switch (Question->Flags & EFI_QF_DATE_STORAGE) {\r
-      case QF_DATE_STORAGE_TIME:\r
-        Status = gRT->GetTime (&EfiTime, NULL);\r
-        break;\r
+        case QF_DATE_STORAGE_TIME:\r
+          Status = gRT->GetTime (&EfiTime, NULL);\r
+          break;\r
 \r
-      case QF_DATE_STORAGE_WAKEUP:\r
-        Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
-        break;\r
+        case QF_DATE_STORAGE_WAKEUP:\r
+          Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
+          break;\r
 \r
-      case QF_DATE_STORAGE_NORMAL:\r
-      default:\r
-        //\r
-        // For date/time without storage\r
-        //\r
-        return EFI_SUCCESS;\r
+        case QF_DATE_STORAGE_NORMAL:\r
+        default:\r
+          //\r
+          // For date/time without storage\r
+          //\r
+          return EFI_SUCCESS;\r
       }\r
 \r
       if (EFI_ERROR (Status)) {\r
@@ -1428,16 +2026,16 @@ SetQuestionValue (
     if (Question->BufferValue != NULL) {\r
       Src = Question->BufferValue;\r
     } else {\r
-      Src = (UINT8 *) QuestionValue;\r
+      Src = (UINT8 *)QuestionValue;\r
     }\r
 \r
     Status = gRT->SetVariable (\r
-                     Question->VariableName,\r
-                     &Storage->Guid,\r
-                     Storage->Attributes,\r
-                     StorageWidth,\r
-                     Src\r
-                     );\r
+                    Question->VariableName,\r
+                    &Storage->Guid,\r
+                    Storage->Attributes,\r
+                    StorageWidth,\r
+                    Src\r
+                    );\r
     return Status;\r
   }\r
 \r
@@ -1447,52 +2045,94 @@ SetQuestionValue (
   if (Question->BufferValue != NULL) {\r
     Src = Question->BufferValue;\r
   } else {\r
-    Src = (UINT8 *) &Question->HiiValue.Value;\r
+    Src = (UINT8 *)&Question->HiiValue.Value;\r
   }\r
 \r
-  IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);\r
-  IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ?  TRUE : FALSE);\r
-  if (IsBufferStorage) {\r
-    //\r
-    // Copy to storage edit buffer\r
-    //\r
-    CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
+  if ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ||\r
+      (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER))\r
+  {\r
+    IsBufferStorage = TRUE;\r
   } else {\r
-    if (IsString) {\r
-      //\r
-      // Allocate enough string buffer.\r
-      //\r
-      Value = NULL;\r
-      BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16);\r
-      Value = AllocateZeroPool (BufferLen);\r
-      ASSERT (Value != NULL);\r
-      //\r
-      // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
-      //\r
-      TemName = (CHAR16 *) Src;\r
-      TemString = Value;\r
-      for (; *TemName != L'\0'; TemName++) {\r
-        TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);\r
+    IsBufferStorage = FALSE;\r
+  }\r
+\r
+  IsString = (BOOLEAN)((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ?  TRUE : FALSE);\r
+\r
+  if ((SetValueTo == GetSetValueWithEditBuffer) || (SetValueTo == GetSetValueWithBuffer)) {\r
+    if (IsBufferStorage) {\r
+      if (SetValueTo == GetSetValueWithEditBuffer) {\r
+        //\r
+        // Copy to storage edit buffer\r
+        // If the Question refer to bit filed, copy the value in related bit filed to storage edit buffer.\r
+        //\r
+        if (Question->QuestionReferToBitField) {\r
+          SetBitsQuestionValue (Question, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, (UINT32)(*Src));\r
+        } else {\r
+          CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
+        }\r
+      } else if (SetValueTo == GetSetValueWithBuffer) {\r
+        //\r
+        // Copy to storage buffer\r
+        // If the Question refer to bit filed, copy the value in related bit filed to storage buffer.\r
+        //\r
+        if (Question->QuestionReferToBitField) {\r
+          SetBitsQuestionValue (Question, Storage->Buffer + Question->VarStoreInfo.VarOffset, (UINT32)(*Src));\r
+        } else {\r
+          CopyMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
+        }\r
       }\r
     } else {\r
-      BufferLen = StorageWidth * 2 + 1;\r
-      Value = AllocateZeroPool (BufferLen * sizeof (CHAR16));\r
-      ASSERT (Value != NULL);\r
-      //\r
-      // Convert Buffer to Hex String\r
-      //\r
-      TemBuffer = Src + StorageWidth - 1;\r
-      TemString = Value;\r
-      for (Index = 0; Index < StorageWidth; Index ++, TemBuffer --) {\r
-        TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
+      if (IsString) {\r
+        //\r
+        // Allocate enough string buffer.\r
+        //\r
+        Value     = NULL;\r
+        BufferLen = ((StrLen ((CHAR16 *)Src) * 4) + 1) * sizeof (CHAR16);\r
+        Value     = AllocateZeroPool (BufferLen);\r
+        ASSERT (Value != NULL);\r
+        //\r
+        // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
+        //\r
+        TemName   = (CHAR16 *)Src;\r
+        TemString = Value;\r
+        for ( ; *TemName != L'\0'; TemName++) {\r
+          UnicodeValueToStringS (\r
+            TemString,\r
+            BufferLen - ((UINTN)TemString - (UINTN)Value),\r
+            PREFIX_ZERO | RADIX_HEX,\r
+            *TemName,\r
+            4\r
+            );\r
+          TemString += StrnLenS (TemString, (BufferLen - ((UINTN)TemString - (UINTN)Value)) / sizeof (CHAR16));\r
+        }\r
+      } else {\r
+        BufferLen = StorageWidth * 2 + 1;\r
+        Value     = AllocateZeroPool (BufferLen * sizeof (CHAR16));\r
+        ASSERT (Value != NULL);\r
+        //\r
+        // Convert Buffer to Hex String\r
+        //\r
+        TemBuffer = Src + StorageWidth - 1;\r
+        TemString = Value;\r
+        for (Index = 0; Index < StorageWidth; Index++, TemBuffer--) {\r
+          UnicodeValueToStringS (\r
+            TemString,\r
+            BufferLen * sizeof (CHAR16) - ((UINTN)TemString - (UINTN)Value),\r
+            PREFIX_ZERO | RADIX_HEX,\r
+            *TemBuffer,\r
+            2\r
+            );\r
+          TemString += StrnLenS (TemString, BufferLen - ((UINTN)TemString - (UINTN)Value) / sizeof (CHAR16));\r
+        }\r
       }\r
-    }\r
 \r
-    Status = SetValueByName (Storage, Question->VariableName, Value);\r
-    FreePool (Value);\r
-  }\r
-\r
-  if (!Cached) {\r
+      Status = SetValueByName (Storage, Question->VariableName, Value, SetValueTo, &Node);\r
+      FreePool (Value);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+    }\r
+  } else if (SetValueTo == GetSetValueWithHiiDriver) {\r
     //\r
     // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||\r
     //                <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"\r
@@ -1502,22 +2142,27 @@ SetQuestionValue (
     } else {\r
       Length = StrLen (Question->VariableName) + 2;\r
     }\r
+\r
     if (!IsBufferStorage && IsString) {\r
-      Length += (StrLen ((CHAR16 *) Src) * 4);\r
+      Length += (StrLen ((CHAR16 *)Src) * 4);\r
     } else {\r
       Length += (StorageWidth * 2);\r
     }\r
-    ConfigResp = AllocateZeroPool ((StrLen (Storage->ConfigHdr) + Length + 1) * sizeof (CHAR16));\r
+\r
+    FormsetStorage = GetFstStgFromVarId (FormSet, Question->VarStoreId);\r
+    ASSERT (FormsetStorage != NULL);\r
+    MaxLen     = StrLen (FormsetStorage->ConfigHdr) + Length + 1;\r
+    ConfigResp = AllocateZeroPool (MaxLen * sizeof (CHAR16));\r
     ASSERT (ConfigResp != NULL);\r
 \r
-    StrCpy (ConfigResp, Storage->ConfigHdr);\r
+    StrCpyS (ConfigResp, MaxLen, FormsetStorage->ConfigHdr);\r
     if (IsBufferStorage) {\r
-      StrCat (ConfigResp, Question->BlockName);\r
-      StrCat (ConfigResp, L"&VALUE=");\r
+      StrCatS (ConfigResp, MaxLen, Question->BlockName);\r
+      StrCatS (ConfigResp, MaxLen, L"&VALUE=");\r
     } else {\r
-      StrCat (ConfigResp, L"&");\r
-      StrCat (ConfigResp, Question->VariableName);\r
-      StrCat (ConfigResp, L"=");\r
+      StrCatS (ConfigResp, MaxLen, L"&");\r
+      StrCatS (ConfigResp, MaxLen, Question->VariableName);\r
+      StrCatS (ConfigResp, MaxLen, L"=");\r
     }\r
 \r
     Value = ConfigResp + StrLen (ConfigResp);\r
@@ -1526,10 +2171,17 @@ SetQuestionValue (
       //\r
       // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
       //\r
-      TemName = (CHAR16 *) Src;\r
+      TemName   = (CHAR16 *)Src;\r
       TemString = Value;\r
-      for (; *TemName != L'\0'; TemName++) {\r
-        TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);\r
+      for ( ; *TemName != L'\0'; TemName++) {\r
+        UnicodeValueToStringS (\r
+          TemString,\r
+          MaxLen * sizeof (CHAR16) - ((UINTN)TemString - (UINTN)ConfigResp),\r
+          PREFIX_ZERO | RADIX_HEX,\r
+          *TemName,\r
+          4\r
+          );\r
+        TemString += StrnLenS (TemString, MaxLen - ((UINTN)TemString - (UINTN)ConfigResp) / sizeof (CHAR16));\r
       }\r
     } else {\r
       //\r
@@ -1537,8 +2189,15 @@ SetQuestionValue (
       //\r
       TemBuffer = Src + StorageWidth - 1;\r
       TemString = Value;\r
-      for (Index = 0; Index < StorageWidth; Index ++, TemBuffer --) {\r
-        TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
+      for (Index = 0; Index < StorageWidth; Index++, TemBuffer--) {\r
+        UnicodeValueToStringS (\r
+          TemString,\r
+          MaxLen * sizeof (CHAR16) - ((UINTN)TemString - (UINTN)ConfigResp),\r
+          PREFIX_ZERO | RADIX_HEX,\r
+          *TemBuffer,\r
+          2\r
+          );\r
+        TemString += StrnLenS (TemString, MaxLen - ((UINTN)TemString - (UINTN)ConfigResp) / sizeof (CHAR16));\r
       }\r
     }\r
 \r
@@ -1546,44 +2205,42 @@ SetQuestionValue (
     // Convert to lower char.\r
     //\r
     for (TemString = Value; *Value != L'\0'; Value++) {\r
-      if (*Value >= L'A' && *Value <= L'Z') {\r
-        *Value = (CHAR16) (*Value - L'A' + L'a');\r
+      if ((*Value >= L'A') && (*Value <= L'Z')) {\r
+        *Value = (CHAR16)(*Value - L'A' + L'a');\r
       }\r
     }\r
 \r
     //\r
     // Submit Question Value to Configuration Driver\r
     //\r
-    if (FormSet->ConfigAccess != NULL) {\r
-      Status = FormSet->ConfigAccess->RouteConfig (\r
-                                        FormSet->ConfigAccess,\r
-                                        ConfigResp,\r
-                                        &Progress\r
-                                        );\r
-      if (EFI_ERROR (Status)) {\r
-        FreePool (ConfigResp);\r
-        return Status;\r
-      }\r
+    Status = mHiiConfigRouting->RouteConfig (\r
+                                  mHiiConfigRouting,\r
+                                  ConfigResp,\r
+                                  &Progress\r
+                                  );\r
+    if (EFI_ERROR (Status)) {\r
+      FreePool (ConfigResp);\r
+      return Status;\r
     }\r
+\r
     FreePool (ConfigResp);\r
 \r
     //\r
-    // Synchronize shadow Buffer\r
+    // Sync storage, from editbuffer to buffer.\r
     //\r
-    SynchronizeStorage (Storage);\r
+    CopyMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
   }\r
 \r
   return Status;\r
 }\r
 \r
-\r
 /**\r
-  Perform inconsistent check for a Form.\r
+  Perform nosubmitif check for a Form.\r
 \r
   @param  FormSet                FormSet data structure.\r
   @param  Form                   Form data structure.\r
   @param  Question               The Question to be validated.\r
-  @param  Type                   Validation type: InConsistent or NoSubmit\r
+  @param  Type                   Validation type: NoSubmit\r
 \r
   @retval EFI_SUCCESS            Form validation pass.\r
   @retval other                  Form validation failed.\r
@@ -1591,25 +2248,38 @@ SetQuestionValue (
 **/\r
 EFI_STATUS\r
 ValidateQuestion (\r
-  IN  FORM_BROWSER_FORMSET            *FormSet,\r
-  IN  FORM_BROWSER_FORM               *Form,\r
-  IN  FORM_BROWSER_STATEMENT          *Question,\r
-  IN  UINTN                           Type\r
+  IN  FORM_BROWSER_FORMSET    *FormSet,\r
+  IN  FORM_BROWSER_FORM       *Form,\r
+  IN  FORM_BROWSER_STATEMENT  *Question,\r
+  IN  UINTN                   Type\r
   )\r
 {\r
-  EFI_STATUS              Status;\r
-  LIST_ENTRY              *Link;\r
-  LIST_ENTRY              *ListHead;\r
-  EFI_STRING              PopUp;\r
-  EFI_INPUT_KEY           Key;\r
-  FORM_EXPRESSION         *Expression;\r
-\r
-  if (Type == EFI_HII_EXPRESSION_INCONSISTENT_IF) {\r
-    ListHead = &Question->InconsistentListHead;\r
-  } else if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {\r
-    ListHead = &Question->NoSubmitListHead;\r
-  } else {\r
-    return EFI_UNSUPPORTED;\r
+  EFI_STATUS       Status;\r
+  LIST_ENTRY       *Link;\r
+  LIST_ENTRY       *ListHead;\r
+  FORM_EXPRESSION  *Expression;\r
+  UINT32           BrowserStatus;\r
+  CHAR16           *ErrorStr;\r
+\r
+  BrowserStatus = BROWSER_SUCCESS;\r
+  ErrorStr      = 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
+    case EFI_HII_EXPRESSION_NO_SUBMIT_IF:\r
+      ListHead = &Question->NoSubmitListHead;\r
+      break;\r
+\r
+    default:\r
+      ASSERT (FALSE);\r
+      return EFI_UNSUPPORTED;\r
   }\r
 \r
   Link = GetFirstNode (ListHead);\r
@@ -1624,19 +2294,50 @@ ValidateQuestion (
       return Status;\r
     }\r
 \r
-    if (Expression->Result.Value.b) {\r
-      //\r
-      // Condition meet, show up error message\r
-      //\r
-      if (Expression->Error != 0) {\r
-        PopUp = GetToken (Expression->Error, FormSet->HiiHandle);\r
-        do {\r
-          CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, PopUp, gPressEnter, gEmptyString);\r
-        } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
-        FreePool (PopUp);\r
+    if (IsTrue (&Expression->Result)) {\r
+      switch (Type) {\r
+        case EFI_HII_EXPRESSION_INCONSISTENT_IF:\r
+          BrowserStatus = BROWSER_INCONSISTENT_IF;\r
+          break;\r
+\r
+        case EFI_HII_EXPRESSION_WARNING_IF:\r
+          BrowserStatus = BROWSER_WARNING_IF;\r
+          break;\r
+\r
+        case EFI_HII_EXPRESSION_NO_SUBMIT_IF:\r
+          BrowserStatus = BROWSER_NO_SUBMIT_IF;\r
+          //\r
+          // This code only used to compatible with old display engine,\r
+          // New display engine will not use this field.\r
+          //\r
+          if (Expression->Error != 0) {\r
+            ErrorStr = GetToken (Expression->Error, FormSet->HiiHandle);\r
+          }\r
+\r
+          break;\r
+\r
+        default:\r
+          ASSERT (FALSE);\r
+          break;\r
       }\r
 \r
-      return EFI_NOT_READY;\r
+      if (!((Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) && mSystemSubmit)) {\r
+        //\r
+        // If in system submit process and for no_submit_if check, not popup this error message.\r
+        // Will process this fail again later in not system submit process.\r
+        //\r
+        PopupErrorMessage (BrowserStatus, FormSet->HiiHandle, Expression->OpCode, ErrorStr);\r
+      }\r
+\r
+      if (ErrorStr != NULL) {\r
+        FreePool (ErrorStr);\r
+      }\r
+\r
+      if (Type == EFI_HII_EXPRESSION_WARNING_IF) {\r
+        return EFI_SUCCESS;\r
+      } else {\r
+        return EFI_NOT_READY;\r
+      }\r
     }\r
 \r
     Link = GetNextNode (ListHead, Link);\r
@@ -1645,1045 +2346,4397 @@ ValidateQuestion (
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
-  Perform NoSubmit check for a Form.\r
+  Perform question check.\r
+\r
+  If one question has more than one check, process form high priority to low.\r
+  Only one error info will be popup.\r
 \r
   @param  FormSet                FormSet data structure.\r
   @param  Form                   Form data structure.\r
+  @param  Question               The Question to be validated.\r
 \r
   @retval EFI_SUCCESS            Form validation pass.\r
   @retval other                  Form validation failed.\r
 \r
 **/\r
 EFI_STATUS\r
-NoSubmitCheck (\r
-  IN  FORM_BROWSER_FORMSET            *FormSet,\r
-  IN  FORM_BROWSER_FORM               *Form\r
+ValueChangedValidation (\r
+  IN  FORM_BROWSER_FORMSET    *FormSet,\r
+  IN  FORM_BROWSER_FORM       *Form,\r
+  IN  FORM_BROWSER_STATEMENT  *Question\r
   )\r
 {\r
-  EFI_STATUS              Status;\r
-  LIST_ENTRY              *Link;\r
-  FORM_BROWSER_STATEMENT  *Question;\r
+  EFI_STATUS  Status;\r
 \r
-  Link = GetFirstNode (&Form->StatementListHead);\r
-  while (!IsNull (&Form->StatementListHead, Link)) {\r
-    Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+  Status = EFI_SUCCESS;\r
 \r
-    Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_NO_SUBMIT_IF);\r
+  //\r
+  // Do the inconsistentif check.\r
+  //\r
+  if (!IsListEmpty (&Question->InconsistentListHead)) {\r
+    Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);\r
     if (EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
+  }\r
 \r
-    Link = GetNextNode (&Form->StatementListHead, Link);\r
+  //\r
+  // Do the warningif check.\r
+  //\r
+  if (!IsListEmpty (&Question->WarningListHead)) {\r
+    Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_WARNING_IF);\r
   }\r
 \r
-  return EFI_SUCCESS;\r
+  return Status;\r
 }\r
 \r
-\r
 /**\r
-  Submit a Form.\r
+  Perform NoSubmit check for each Form in FormSet.\r
 \r
   @param  FormSet                FormSet data structure.\r
-  @param  Form                   Form data structure.\r
+  @param  CurrentForm            Current input form data structure.\r
+  @param  Statement              The statement for this check.\r
 \r
-  @retval EFI_SUCCESS            The function completed successfully.\r
+  @retval EFI_SUCCESS            Form validation pass.\r
+  @retval other                  Form validation failed.\r
 \r
 **/\r
 EFI_STATUS\r
-SubmitForm (\r
-  IN FORM_BROWSER_FORMSET             *FormSet,\r
-  IN FORM_BROWSER_FORM                *Form\r
+NoSubmitCheck (\r
+  IN      FORM_BROWSER_FORMSET    *FormSet,\r
+  IN OUT  FORM_BROWSER_FORM       **CurrentForm,\r
+  OUT     FORM_BROWSER_STATEMENT  **Statement\r
   )\r
 {\r
   EFI_STATUS              Status;\r
   LIST_ENTRY              *Link;\r
-  EFI_STRING              ConfigResp;\r
-  EFI_STRING              Progress;\r
-  FORMSET_STORAGE         *Storage;\r
-\r
-  //\r
-  // Validate the Form by NoSubmit check\r
-  //\r
-  Status = NoSubmitCheck (FormSet, Form);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
+  FORM_BROWSER_STATEMENT  *Question;\r
+  FORM_BROWSER_FORM       *Form;\r
+  LIST_ENTRY              *LinkForm;\r
 \r
-  //\r
-  // Submit Buffer storage or Name/Value storage\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
+  LinkForm = GetFirstNode (&FormSet->FormListHead);\r
+  while (!IsNull (&FormSet->FormListHead, LinkForm)) {\r
+    Form     = FORM_BROWSER_FORM_FROM_LINK (LinkForm);\r
+    LinkForm = GetNextNode (&FormSet->FormListHead, LinkForm);\r
 \r
-    if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+    if ((*CurrentForm != NULL) && (*CurrentForm != Form)) {\r
       continue;\r
     }\r
 \r
-    //\r
-    // Skip if there is no RequestElement\r
-    //\r
-    if (Storage->ElementCount == 0) {\r
-      continue;\r
-    }\r
+    Link = GetFirstNode (&Form->StatementListHead);\r
+    while (!IsNull (&Form->StatementListHead, Link)) {\r
+      Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+      Status   = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_NO_SUBMIT_IF);\r
+      if (EFI_ERROR (Status)) {\r
+        if (*CurrentForm == NULL) {\r
+          *CurrentForm = Form;\r
+        }\r
 \r
-    //\r
-    // Prepare <ConfigResp>\r
-    //\r
-    Status = StorageToConfigResp (Storage, &ConfigResp);\r
-    if (EFI_ERROR (Status)) {\r
-      return Status;\r
-    }\r
+        if (Statement != NULL) {\r
+          *Statement = Question;\r
+        }\r
 \r
-    //\r
-    // Send <ConfigResp> to Configuration Driver\r
-    //\r
-    if (FormSet->ConfigAccess != NULL) {\r
-      Status = FormSet->ConfigAccess->RouteConfig (\r
-                                        FormSet->ConfigAccess,\r
-                                        ConfigResp,\r
-                                        &Progress\r
-                                        );\r
-      if (EFI_ERROR (Status)) {\r
-        FreePool (ConfigResp);\r
         return Status;\r
       }\r
-    }\r
-    FreePool (ConfigResp);\r
 \r
-    //\r
-    // Config success, update storage shadow Buffer\r
-    //\r
-    SynchronizeStorage (Storage);\r
+      Link = GetNextNode (&Form->StatementListHead, Link);\r
+    }\r
   }\r
 \r
-  gNvUpdateRequired = FALSE;\r
-\r
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
-  Reset Question to its default value.\r
+  Fill storage's edit copy with settings requested from Configuration Driver.\r
 \r
-  @param  FormSet                The form set.\r
-  @param  Form                   The form.\r
-  @param  Question               The question.\r
-  @param  DefaultId              The Class of the default.\r
+  @param  Storage                The storage which need to sync.\r
+  @param  ConfigRequest          The config request string which used to sync storage.\r
+  @param  SyncOrRestore          Sync the buffer to editbuffer or Restore  the\r
+                                 editbuffer to buffer\r
+                                 if TRUE, copy the editbuffer to the buffer.\r
+                                 if FALSE, copy the buffer to the editbuffer.\r
 \r
-  @retval EFI_SUCCESS            Question is reset to default value.\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
 \r
 **/\r
 EFI_STATUS\r
-GetQuestionDefault (\r
-  IN FORM_BROWSER_FORMSET             *FormSet,\r
-  IN FORM_BROWSER_FORM                *Form,\r
-  IN FORM_BROWSER_STATEMENT           *Question,\r
-  IN UINT16                           DefaultId\r
+SynchronizeStorage (\r
+  OUT BROWSER_STORAGE  *Storage,\r
+  IN  CHAR16           *ConfigRequest,\r
+  IN  BOOLEAN          SyncOrRestore\r
   )\r
 {\r
-  EFI_STATUS              Status;\r
-  LIST_ENTRY              *Link;\r
-  QUESTION_DEFAULT        *Default;\r
-  QUESTION_OPTION         *Option;\r
-  EFI_HII_VALUE           *HiiValue;\r
-  UINT8                   Index;\r
-  EFI_STRING              StrValue;\r
+  EFI_STATUS       Status;\r
+  EFI_STRING       Progress;\r
+  EFI_STRING       Result;\r
+  UINTN            BufferSize;\r
+  LIST_ENTRY       *Link;\r
+  NAME_VALUE_NODE  *Node;\r
+  UINT8            *Src;\r
+  UINT8            *Dst;\r
 \r
-  Status   = EFI_SUCCESS;\r
-  StrValue = NULL;\r
+  Status = EFI_SUCCESS;\r
+  Result = NULL;\r
 \r
-  //\r
-  // Statement don't have storage, skip them\r
-  //\r
-  if (Question->QuestionId == 0) {\r
-    return Status;\r
-  }\r
+  if ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ||\r
+      (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER))\r
+  {\r
+    BufferSize = Storage->Size;\r
 \r
-  //\r
-  // There are three ways to specify default value for a Question:\r
-  //  1, use nested EFI_IFR_DEFAULT (highest priority)\r
-  //  2, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)\r
-  //  3, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)\r
-  //\r
-  HiiValue = &Question->HiiValue;\r
+    if (SyncOrRestore) {\r
+      Src = Storage->EditBuffer;\r
+      Dst = Storage->Buffer;\r
+    } else {\r
+      Src = Storage->Buffer;\r
+      Dst = Storage->EditBuffer;\r
+    }\r
 \r
-  //\r
-  // EFI_IFR_DEFAULT has highest priority\r
-  //\r
-  if (!IsListEmpty (&Question->DefaultListHead)) {\r
-    Link = GetFirstNode (&Question->DefaultListHead);\r
-    while (!IsNull (&Question->DefaultListHead, Link)) {\r
-      Default = QUESTION_DEFAULT_FROM_LINK (Link);\r
+    if (ConfigRequest != NULL) {\r
+      Status = mHiiConfigRouting->BlockToConfig (\r
+                                    mHiiConfigRouting,\r
+                                    ConfigRequest,\r
+                                    Src,\r
+                                    BufferSize,\r
+                                    &Result,\r
+                                    &Progress\r
+                                    );\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
 \r
-      if (Default->DefaultId == DefaultId) {\r
-        if (Default->ValueExpression != NULL) {\r
-          //\r
-          // Default is provided by an Expression, evaluate it\r
-          //\r
-          Status = EvaluateExpression (FormSet, Form, Default->ValueExpression);\r
-          if (EFI_ERROR (Status)) {\r
-            return Status;\r
-          }\r
+      Status = mHiiConfigRouting->ConfigToBlock (\r
+                                    mHiiConfigRouting,\r
+                                    Result,\r
+                                    Dst,\r
+                                    &BufferSize,\r
+                                    &Progress\r
+                                    );\r
+      if (Result != NULL) {\r
+        FreePool (Result);\r
+      }\r
+    } else {\r
+      CopyMem (Dst, Src, BufferSize);\r
+    }\r
+  } else if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+    Link = GetFirstNode (&Storage->NameValueListHead);\r
+    while (!IsNull (&Storage->NameValueListHead, Link)) {\r
+      Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
 \r
-          CopyMem (HiiValue, &Default->ValueExpression->Result, sizeof (EFI_HII_VALUE));\r
+      if (((ConfigRequest != NULL) && (StrStr (ConfigRequest, Node->Name) != NULL)) ||\r
+          (ConfigRequest == NULL))\r
+      {\r
+        if (SyncOrRestore) {\r
+          NewStringCpy (&Node->Value, Node->EditValue);\r
         } else {\r
-          //\r
-          // Default value is embedded in EFI_IFR_DEFAULT\r
-          //\r
-          CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));\r
-        }\r
-\r
-        if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
-          StrValue = HiiGetString (FormSet->HiiHandle, HiiValue->Value.string, NULL);\r
-          if (StrValue == NULL) {\r
-            return EFI_NOT_FOUND;\r
-          }\r
-          Question->BufferValue = AllocateCopyPool (StrSize (StrValue), StrValue);\r
+          NewStringCpy (&Node->EditValue, Node->Value);\r
         }\r
-\r
-        return EFI_SUCCESS;\r
       }\r
 \r
-      Link = GetNextNode (&Question->DefaultListHead, Link);\r
+      Link = GetNextNode (&Storage->NameValueListHead, Link);\r
     }\r
   }\r
 \r
-  //\r
-  // EFI_ONE_OF_OPTION\r
-  //\r
-  if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {\r
-    if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING)  {\r
-      //\r
-      // OneOfOption could only provide Standard and Manufacturing default\r
-      //\r
-      Link = GetFirstNode (&Question->OptionListHead);\r
-      while (!IsNull (&Question->OptionListHead, Link)) {\r
-        Option = QUESTION_OPTION_FROM_LINK (Link);\r
+  return Status;\r
+}\r
 \r
-        if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||\r
-            ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))\r
-           ) {\r
-          CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
+/**\r
+  When discard the question value, call the callback function with Changed type\r
+  to inform the hii driver.\r
 \r
-          return EFI_SUCCESS;\r
-        }\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   Form data structure.\r
 \r
-        Link = GetNextNode (&Question->OptionListHead, Link);\r
-      }\r
-    }\r
+**/\r
+VOID\r
+SendDiscardInfoToDriver (\r
+  IN FORM_BROWSER_FORMSET  *FormSet,\r
+  IN FORM_BROWSER_FORM     *Form\r
+  )\r
+{\r
+  LIST_ENTRY                  *Link;\r
+  FORM_BROWSER_STATEMENT      *Question;\r
+  EFI_IFR_TYPE_VALUE          *TypeValue;\r
+  EFI_BROWSER_ACTION_REQUEST  ActionRequest;\r
+\r
+  if (FormSet->ConfigAccess == NULL) {\r
+    return;\r
   }\r
 \r
-  //\r
-  // EFI_IFR_CHECKBOX - lowest priority\r
-  //\r
-  if (Question->Operand == EFI_IFR_CHECKBOX_OP) {\r
-    if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING)  {\r
-      //\r
-      // Checkbox could only provide Standard and Manufacturing default\r
-      //\r
-      if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0)) ||\r
-          ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0))\r
-         ) {\r
-        HiiValue->Value.b = TRUE;\r
-      } else {\r
-        HiiValue->Value.b = FALSE;\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
-      return EFI_SUCCESS;\r
+    if ((Question->Storage == NULL) || (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
+      continue;\r
     }\r
-  }\r
 \r
-  //\r
-  // For Questions without default\r
-  //\r
-  switch (Question->Operand) {\r
-  case EFI_IFR_ONE_OF_OP:\r
-    //\r
-    // Take first oneof option as oneof's default value\r
-    //\r
-    if (ValueToOption (Question, HiiValue) == NULL) {\r
-      Link = GetFirstNode (&Question->OptionListHead);\r
-      if (!IsNull (&Question->OptionListHead, Link)) {\r
-        Option = QUESTION_OPTION_FROM_LINK (Link);\r
-        CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
-      }\r
+    if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) {\r
+      continue;\r
+    }\r
+\r
+    if (Question->Operand == EFI_IFR_PASSWORD_OP) {\r
+      continue;\r
+    }\r
+\r
+    if (!Question->ValueChanged) {\r
+      continue;\r
     }\r
-    break;\r
 \r
-  case EFI_IFR_ORDERED_LIST_OP:\r
     //\r
-    // Take option sequence in IFR as ordered list's default value\r
+    // Restore the question value before call the CHANGED callback type.\r
     //\r
-    Index = 0;\r
-    Link = GetFirstNode (&Question->OptionListHead);\r
-    while (!IsNull (&Question->OptionListHead, Link)) {\r
-      Option = QUESTION_OPTION_FROM_LINK (Link);\r
+    GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
 \r
-      SetArrayData (Question->BufferValue, Question->ValueType, Index, Option->Value.Value.u64);\r
-\r
-      Index++;\r
-      if (Index >= Question->MaxContainers) {\r
-        break;\r
-      }\r
+    if (Question->Operand == EFI_IFR_STRING_OP) {\r
+      HiiSetString (FormSet->HiiHandle, Question->HiiValue.Value.string, (CHAR16 *)Question->BufferValue, NULL);\r
+    }\r
 \r
-      Link = GetNextNode (&Question->OptionListHead, Link);\r
+    if (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER) {\r
+      TypeValue = (EFI_IFR_TYPE_VALUE *)Question->BufferValue;\r
+    } else {\r
+      TypeValue = &Question->HiiValue.Value;\r
     }\r
-    break;\r
 \r
-  default:\r
-    Status = EFI_NOT_FOUND;\r
-    break;\r
+    ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+    FormSet->ConfigAccess->Callback (\r
+                             FormSet->ConfigAccess,\r
+                             EFI_BROWSER_ACTION_CHANGED,\r
+                             Question->QuestionId,\r
+                             Question->HiiValue.Type,\r
+                             TypeValue,\r
+                             &ActionRequest\r
+                             );\r
   }\r
-\r
-  return Status;\r
 }\r
 \r
-\r
 /**\r
-  Reset Questions in a Form to their default value.\r
+  When submit the question value, call the callback function with Submitted type\r
+  to inform the hii driver.\r
 \r
   @param  FormSet                FormSet data structure.\r
-  @param  Form                   The Form which to be reset.\r
-  @param  DefaultId              The Class of the default.\r
-\r
-  @retval EFI_SUCCESS            The function completed successfully.\r
+  @param  Form                   Form data structure.\r
 \r
 **/\r
-EFI_STATUS\r
-ExtractFormDefault (\r
-  IN FORM_BROWSER_FORMSET             *FormSet,\r
-  IN FORM_BROWSER_FORM                *Form,\r
-  IN UINT16                           DefaultId\r
+VOID\r
+SubmitCallbackForForm (\r
+  IN FORM_BROWSER_FORMSET  *FormSet,\r
+  IN FORM_BROWSER_FORM     *Form\r
   )\r
 {\r
-  EFI_STATUS              Status;\r
-  LIST_ENTRY              *Link;\r
-  FORM_BROWSER_STATEMENT  *Question;\r
+  LIST_ENTRY                  *Link;\r
+  FORM_BROWSER_STATEMENT      *Question;\r
+  EFI_IFR_TYPE_VALUE          *TypeValue;\r
+  EFI_BROWSER_ACTION_REQUEST  ActionRequest;\r
+\r
+  if (FormSet->ConfigAccess == NULL) {\r
+    return;\r
+  }\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
+    Link     = GetNextNode (&Form->StatementListHead, Link);\r
 \r
-    //\r
-    // If Question is disabled, don't reset it to default\r
-    //\r
-    if (Question->DisableExpression != NULL) {\r
-      Status = EvaluateExpression (FormSet, Form, Question->DisableExpression);\r
-      if (!EFI_ERROR (Status) && Question->DisableExpression->Result.Value.b) {\r
-        continue;\r
-      }\r
+    if ((Question->Storage == NULL) || (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
+      continue;\r
     }\r
 \r
-    //\r
-    // Reset Question to its default value\r
-    //\r
-    Status = GetQuestionDefault (FormSet, Form, Question, DefaultId);\r
-    if (EFI_ERROR (Status)) {\r
+    if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) {\r
       continue;\r
     }\r
 \r
-    //\r
-    // Synchronize Buffer storage's Edit buffer\r
-    //\r
-    if ((Question->Storage != NULL) &&\r
-        (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
-      SetQuestionValue (FormSet, Form, Question, TRUE);\r
+    if (Question->Operand == EFI_IFR_PASSWORD_OP) {\r
+      continue;\r
     }\r
-  }\r
 \r
-  return EFI_SUCCESS;\r
-}\r
+    if (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER) {\r
+      TypeValue = (EFI_IFR_TYPE_VALUE *)Question->BufferValue;\r
+    } else {\r
+      TypeValue = &Question->HiiValue.Value;\r
+    }\r
 \r
+    ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+    FormSet->ConfigAccess->Callback (\r
+                             FormSet->ConfigAccess,\r
+                             EFI_BROWSER_ACTION_SUBMITTED,\r
+                             Question->QuestionId,\r
+                             Question->HiiValue.Type,\r
+                             TypeValue,\r
+                             &ActionRequest\r
+                             );\r
+  }\r
+}\r
 \r
 /**\r
-  Initialize Question's Edit copy from Storage.\r
+  When value set Success, call the submit callback function.\r
 \r
   @param  FormSet                FormSet data structure.\r
   @param  Form                   Form data structure.\r
 \r
-  @retval EFI_SUCCESS            The function completed successfully.\r
-\r
 **/\r
-EFI_STATUS\r
-LoadFormConfig (\r
-  IN FORM_BROWSER_FORMSET             *FormSet,\r
-  IN FORM_BROWSER_FORM                *Form\r
+VOID\r
+SubmitCallback (\r
+  IN FORM_BROWSER_FORMSET  *FormSet,\r
+  IN FORM_BROWSER_FORM     *Form\r
   )\r
 {\r
-  EFI_STATUS              Status;\r
-  LIST_ENTRY              *Link;\r
-  FORM_BROWSER_STATEMENT  *Question;\r
+  FORM_BROWSER_FORM  *CurrentForm;\r
+  LIST_ENTRY         *Link;\r
 \r
-  Link = GetFirstNode (&Form->StatementListHead);\r
-  while (!IsNull (&Form->StatementListHead, Link)) {\r
-    Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+  if (Form != NULL) {\r
+    SubmitCallbackForForm (FormSet, Form);\r
+    return;\r
+  }\r
 \r
-    //\r
-    // Initialize local copy of Value for each Question\r
-    //\r
-    Status = GetQuestionValue (FormSet, Form, Question, TRUE);\r
-    if (EFI_ERROR (Status)) {\r
-      return Status;\r
-    }\r
+  Link = GetFirstNode (&FormSet->FormListHead);\r
+  while (!IsNull (&FormSet->FormListHead, Link)) {\r
+    CurrentForm = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+    Link        = GetNextNode (&FormSet->FormListHead, Link);\r
 \r
-    Link = GetNextNode (&Form->StatementListHead, Link);\r
+    SubmitCallbackForForm (FormSet, CurrentForm);\r
   }\r
-\r
-  return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
-  Initialize Question's Edit copy from Storage for the whole Formset.\r
+  Validate the HiiHandle.\r
 \r
-  @param  FormSet                FormSet data structure.\r
+  @param  HiiHandle              The input HiiHandle which need to validate.\r
 \r
-  @retval EFI_SUCCESS            The function completed successfully.\r
+  @retval TRUE                   The handle is validate.\r
+  @retval FALSE                  The handle is invalidate.\r
 \r
 **/\r
-EFI_STATUS\r
-LoadFormSetConfig (\r
-  IN FORM_BROWSER_FORMSET             *FormSet\r
+BOOLEAN\r
+ValidateHiiHandle (\r
+  EFI_HII_HANDLE  HiiHandle\r
   )\r
 {\r
-  EFI_STATUS          Status;\r
-  LIST_ENTRY          *Link;\r
-  FORM_BROWSER_FORM   *Form;\r
+  EFI_HII_HANDLE  *HiiHandles;\r
+  UINTN           Index;\r
+  BOOLEAN         Find;\r
 \r
-  Link = GetFirstNode (&FormSet->FormListHead);\r
-  while (!IsNull (&FormSet->FormListHead, Link)) {\r
-    Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+  if (HiiHandle == NULL) {\r
+    return FALSE;\r
+  }\r
 \r
-    //\r
-    // Initialize local copy of Value for each Form\r
-    //\r
-    Status = LoadFormConfig (FormSet, Form);\r
-    if (EFI_ERROR (Status)) {\r
-      return Status;\r
-    }\r
+  Find = FALSE;\r
 \r
-    Link = GetNextNode (&FormSet->FormListHead, Link);\r
+  HiiHandles = HiiGetHiiHandles (NULL);\r
+  ASSERT (HiiHandles != NULL);\r
+\r
+  for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
+    if (HiiHandles[Index] == HiiHandle) {\r
+      Find = TRUE;\r
+      break;\r
+    }\r
   }\r
 \r
-  return EFI_SUCCESS;\r
-}\r
+  FreePool (HiiHandles);\r
 \r
+  return Find;\r
+}\r
 \r
 /**\r
-  Fill storage's edit copy with settings requested from Configuration Driver.\r
+  Validate the FormSet. If the formset is not validate, remove it from the list.\r
 \r
-  @param  FormSet                FormSet data structure.\r
-  @param  Storage                Buffer Storage.\r
+  @param  FormSet                The input FormSet which need to validate.\r
 \r
-  @retval EFI_SUCCESS            The function completed successfully.\r
+  @retval TRUE                   The handle is validate.\r
+  @retval FALSE                  The handle is invalidate.\r
 \r
 **/\r
-EFI_STATUS\r
-LoadStorage (\r
-  IN FORM_BROWSER_FORMSET    *FormSet,\r
-  IN FORMSET_STORAGE         *Storage\r
+BOOLEAN\r
+ValidateFormSet (\r
+  FORM_BROWSER_FORMSET  *FormSet\r
   )\r
 {\r
-  EFI_STATUS  Status;\r
-  EFI_STRING  Progress;\r
-  EFI_STRING  Result;\r
-  CHAR16      *StrPtr;\r
-\r
-  if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  if (FormSet->ConfigAccess == NULL) {\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
-  if (Storage->ElementCount == 0) {\r
-    //\r
-    // Skip if there is no RequestElement\r
-    //\r
-    return EFI_SUCCESS;\r
-  }\r
+  BOOLEAN  Find;\r
 \r
-  //\r
-  // Request current settings from Configuration Driver\r
-  //\r
-  Status = FormSet->ConfigAccess->ExtractConfig (\r
-                                    FormSet->ConfigAccess,\r
-                                    Storage->ConfigRequest,\r
-                                    &Progress,\r
-                                    &Result\r
-                                    );\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
+  ASSERT (FormSet != NULL);\r
 \r
+  Find = ValidateHiiHandle (FormSet->HiiHandle);\r
   //\r
-  // Convert Result from <ConfigAltResp> to <ConfigResp>\r
+  // Should not remove the formset which is being used.\r
   //\r
-  StrPtr = StrStr (Result, L"ALTCFG");\r
-  if (StrPtr != NULL) {\r
-    *StrPtr = L'\0';\r
+  if (!Find && (FormSet != gCurrentSelection->FormSet)) {\r
+    CleanBrowserStorage (FormSet);\r
+    RemoveEntryList (&FormSet->Link);\r
+    DestroyFormSet (FormSet);\r
   }\r
 \r
-  Status = ConfigRespToStorage (Storage, Result);\r
-  FreePool (Result);\r
-  return Status;\r
+  return Find;\r
 }\r
 \r
-\r
 /**\r
-  Copy uncommitted data from source Storage to destination Storage.\r
+  Check whether need to enable the reset flag in form level.\r
+  Also clean all ValueChanged flag in question.\r
 \r
-  @param  Dst                    Target Storage for uncommitted data.\r
-  @param  Src                    Source Storage for uncommitted data.\r
-\r
-  @retval EFI_SUCCESS            The function completed successfully.\r
-  @retval EFI_INVALID_PARAMETER  Source and destination Storage is not the same type.\r
+  @param  SetFlag                Whether need to set the Reset Flag.\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   Form data structure.\r
 \r
 **/\r
-EFI_STATUS\r
-CopyStorage (\r
-  IN OUT FORMSET_STORAGE     *Dst,\r
-  IN FORMSET_STORAGE         *Src\r
+VOID\r
+UpdateFlagForForm (\r
+  IN BOOLEAN               SetFlag,\r
+  IN FORM_BROWSER_FORMSET  *FormSet,\r
+  IN FORM_BROWSER_FORM     *Form\r
   )\r
 {\r
-  LIST_ENTRY          *Link;\r
-  NAME_VALUE_NODE     *Node;\r
+  LIST_ENTRY              *Link;\r
+  FORM_BROWSER_STATEMENT  *Question;\r
+  BOOLEAN                 OldValue;\r
 \r
-  if ((Dst->Type != Src->Type) || (Dst->Size != Src->Size)) {\r
-    return EFI_INVALID_PARAMETER;\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
-  switch (Src->Type) {\r
-  case EFI_HII_VARSTORE_BUFFER:\r
-    CopyMem (Dst->EditBuffer, Src->EditBuffer, Src->Size);\r
-    break;\r
+    if (!Question->ValueChanged) {\r
+      continue;\r
+    }\r
 \r
-  case EFI_HII_VARSTORE_NAME_VALUE:\r
-    Link = GetFirstNode (&Src->NameValueListHead);\r
-    while (!IsNull (&Src->NameValueListHead, Link)) {\r
-      Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
+    OldValue = Question->ValueChanged;\r
 \r
-      SetValueByName (Dst, Node->Name, Node->EditValue);\r
+    //\r
+    // Compare the buffer and editbuffer data to see whether the data has been saved.\r
+    //\r
+    Question->ValueChanged = IsQuestionValueChanged (FormSet, Form, Question, GetSetValueWithBothBuffer);\r
 \r
-      Link = GetNextNode (&Src->NameValueListHead, Link);\r
-    }\r
-    break;\r
+    //\r
+    // Only the changed data has been saved, then need to set the reset flag.\r
+    //\r
+    if (SetFlag && OldValue && !Question->ValueChanged) {\r
+      if ((Question->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) != 0) {\r
+        gResetRequiredFormLevel   = TRUE;\r
+        gResetRequiredSystemLevel = TRUE;\r
+      }\r
 \r
-  case EFI_HII_VARSTORE_EFI_VARIABLE:\r
-  default:\r
-    break;\r
+      if ((Question->QuestionFlags & EFI_IFR_FLAG_RECONNECT_REQUIRED) != 0) {\r
+        gFlagReconnect = TRUE;\r
+      }\r
+    }\r
   }\r
-\r
-  return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
-  Get current setting of Questions.\r
+  Check whether need to enable the reset flag.\r
+  Also clean ValueChanged flag for all statements.\r
 \r
-  @param  FormSet                FormSet data structure.\r
+  Form level or formset level, only one.\r
 \r
-  @retval EFI_SUCCESS            The function completed successfully.\r
+  @param  SetFlag                Whether need to set the Reset Flag.\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   Form data structure.\r
 \r
 **/\r
-EFI_STATUS\r
-InitializeCurrentSetting (\r
-  IN OUT FORM_BROWSER_FORMSET             *FormSet\r
+VOID\r
+ValueChangeResetFlagUpdate (\r
+  IN BOOLEAN               SetFlag,\r
+  IN FORM_BROWSER_FORMSET  *FormSet,\r
+  IN FORM_BROWSER_FORM     *Form\r
   )\r
 {\r
-  LIST_ENTRY              *Link;\r
-  LIST_ENTRY              *Link2;\r
-  FORMSET_STORAGE         *Storage;\r
-  FORMSET_STORAGE         *StorageSrc;\r
-  FORMSET_STORAGE         *OldStorage;\r
-  FORM_BROWSER_FORM       *Form;\r
-  EFI_STATUS              Status;\r
+  FORM_BROWSER_FORM  *CurrentForm;\r
+  LIST_ENTRY         *Link;\r
+\r
+  if (Form != NULL) {\r
+    UpdateFlagForForm (SetFlag, FormSet, Form);\r
+    return;\r
+  }\r
 \r
-  //\r
-  // Extract default from IFR binary\r
-  //\r
   Link = GetFirstNode (&FormSet->FormListHead);\r
   while (!IsNull (&FormSet->FormListHead, Link)) {\r
-    Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
-\r
-    Status = ExtractFormDefault (FormSet, Form, EFI_HII_DEFAULT_CLASS_STANDARD);\r
+    CurrentForm = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+    Link        = GetNextNode (&FormSet->FormListHead, Link);\r
 \r
-    Link = GetNextNode (&FormSet->FormListHead, Link);\r
+    UpdateFlagForForm (SetFlag, FormSet, CurrentForm);\r
   }\r
+}\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
+/**\r
+  Base on the return Progress string to find the form.\r
 \r
-    OldStorage = NULL;\r
-    if (gOldFormSet != NULL) {\r
-      //\r
-      // Try to find the Storage in backup formset gOldFormSet\r
-      //\r
-      Link2 = GetFirstNode (&gOldFormSet->StorageListHead);\r
-      while (!IsNull (&gOldFormSet->StorageListHead, Link2)) {\r
-        StorageSrc = FORMSET_STORAGE_FROM_LINK (Link2);\r
+  Base on the first return Offset/Width (Name) string to find the form\r
+  which keep this string.\r
 \r
-        if (StorageSrc->VarStoreId == Storage->VarStoreId) {\r
-          OldStorage = StorageSrc;\r
-          break;\r
-        }\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Storage                Storage which has this Progress string.\r
+  @param  Progress               The Progress string which has the first fail string.\r
+  @param  RetForm                The return form for this progress string.\r
+  @param  RetQuestion            The return question for the error progress string.\r
 \r
-        Link2 = GetNextNode (&gOldFormSet->StorageListHead, Link2);\r
-      }\r
-    }\r
+  @retval TRUE                   Find the error form and statement for this error progress string.\r
+  @retval FALSE                  Not find the error form.\r
+\r
+**/\r
+BOOLEAN\r
+FindQuestionFromProgress (\r
+  IN FORM_BROWSER_FORMSET     *FormSet,\r
+  IN BROWSER_STORAGE          *Storage,\r
+  IN EFI_STRING               Progress,\r
+  OUT FORM_BROWSER_FORM       **RetForm,\r
+  OUT FORM_BROWSER_STATEMENT  **RetQuestion\r
+  )\r
+{\r
+  LIST_ENTRY                   *Link;\r
+  LIST_ENTRY                   *LinkStorage;\r
+  LIST_ENTRY                   *LinkStatement;\r
+  FORM_BROWSER_CONFIG_REQUEST  *ConfigInfo;\r
+  FORM_BROWSER_FORM            *Form;\r
+  EFI_STRING                   EndStr;\r
+  FORM_BROWSER_STATEMENT       *Statement;\r
+\r
+  ASSERT ((*Progress == '&') || (*Progress == 'G'));\r
+\r
+  ConfigInfo   = NULL;\r
+  *RetForm     = NULL;\r
+  *RetQuestion = NULL;\r
 \r
-    if (OldStorage == NULL) {\r
+  //\r
+  // Skip the first "&" or the ConfigHdr part.\r
+  //\r
+  if (*Progress == '&') {\r
+    Progress++;\r
+  } else {\r
+    //\r
+    // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.\r
+    //\r
+    if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
       //\r
-      // Storage is not found in backup formset, request it from ConfigDriver\r
+      // For Name/Value type, Skip the ConfigHdr part.\r
       //\r
-      Status = LoadStorage (FormSet, Storage);\r
+      EndStr = StrStr (Progress, L"PATH=");\r
+      ASSERT (EndStr != NULL);\r
+      while (*EndStr != '&') {\r
+        EndStr++;\r
+      }\r
+\r
+      *EndStr = '\0';\r
     } else {\r
       //\r
-      // Storage found in backup formset, use it\r
+      // For Buffer type, Skip the ConfigHdr part.\r
       //\r
-      Status = CopyStorage (Storage, OldStorage);\r
+      EndStr = StrStr (Progress, L"&OFFSET=");\r
+      ASSERT (EndStr != NULL);\r
+      *EndStr = '\0';\r
     }\r
 \r
+    Progress = EndStr + 1;\r
+  }\r
+\r
+  //\r
+  // Prepare the "NAME" or "OFFSET=0x####&WIDTH=0x####" string.\r
+  //\r
+  if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
     //\r
-    // Now Edit Buffer is filled with default values(lower priority) and current\r
-    // settings(higher priority), sychronize it to shadow Buffer\r
+    // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,\r
+    // here, just keep the "Fred" string.\r
     //\r
-    if (!EFI_ERROR (Status)) {\r
-      SynchronizeStorage (Storage);\r
-    }\r
-\r
-    Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+    EndStr = StrStr (Progress, L"=");\r
+    ASSERT (EndStr != NULL);\r
+    *EndStr = '\0';\r
+  } else {\r
+    //\r
+    // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",\r
+    // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.\r
+    //\r
+    EndStr = StrStr (Progress, L"&VALUE=");\r
+    ASSERT (EndStr != NULL);\r
+    *EndStr = '\0';\r
   }\r
 \r
-  return EFI_SUCCESS;\r
-}\r
+  //\r
+  // Search in the form list.\r
+  //\r
+  Link = GetFirstNode (&FormSet->FormListHead);\r
+  while (!IsNull (&FormSet->FormListHead, Link)) {\r
+    Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+    Link = GetNextNode (&FormSet->FormListHead, Link);\r
+\r
+    //\r
+    // Search in the ConfigReqeust list in this form.\r
+    //\r
+    LinkStorage = GetFirstNode (&Form->ConfigRequestHead);\r
+    while (!IsNull (&Form->ConfigRequestHead, LinkStorage)) {\r
+      ConfigInfo  = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (LinkStorage);\r
+      LinkStorage = GetNextNode (&Form->ConfigRequestHead, LinkStorage);\r
+\r
+      if (Storage != ConfigInfo->Storage) {\r
+        continue;\r
+      }\r
+\r
+      if (StrStr (ConfigInfo->ConfigRequest, Progress) != NULL) {\r
+        //\r
+        // Find the OffsetWidth string in this form.\r
+        //\r
+        *RetForm = Form;\r
+        break;\r
+      }\r
+    }\r
+\r
+    if (*RetForm != NULL) {\r
+      LinkStatement = GetFirstNode (&Form->StatementListHead);\r
+      while (!IsNull (&Form->StatementListHead, LinkStatement)) {\r
+        Statement     = FORM_BROWSER_STATEMENT_FROM_LINK (LinkStatement);\r
+        LinkStatement = GetNextNode (&Form->StatementListHead, LinkStatement);\r
+\r
+        if ((Statement->BlockName != NULL) && (StrStr (Statement->BlockName, Progress) != NULL)) {\r
+          *RetQuestion = Statement;\r
+          break;\r
+        }\r
+\r
+        if ((Statement->VariableName != NULL) && (StrStr (Statement->VariableName, Progress) != NULL)) {\r
+          *RetQuestion = Statement;\r
+          break;\r
+        }\r
+      }\r
+    }\r
+\r
+    if (*RetForm != NULL) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  //\r
+  // restore the OffsetWidth string to the original format.\r
+  //\r
+  if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+    *EndStr = '=';\r
+  } else {\r
+    *EndStr = '&';\r
+  }\r
+\r
+  return (BOOLEAN)(*RetForm != NULL);\r
+}\r
+\r
+/**\r
+  Base on the return Progress string to get the SyncConfigRequest and RestoreConfigRequest\r
+  for form and formset.\r
+\r
+  @param  Storage                 Storage which has this Progress string.\r
+  @param  ConfigRequest           The ConfigRequest string.\r
+  @param  Progress                The Progress string which has the first fail string.\r
+  @param  RestoreConfigRequest    Return the RestoreConfigRequest string.\r
+  @param  SyncConfigRequest       Return the SyncConfigRequest string.\r
+\r
+**/\r
+VOID\r
+GetSyncRestoreConfigRequest (\r
+  IN  BROWSER_STORAGE  *Storage,\r
+  IN  EFI_STRING       ConfigRequest,\r
+  IN  EFI_STRING       Progress,\r
+  OUT EFI_STRING       *RestoreConfigRequest,\r
+  OUT EFI_STRING       *SyncConfigRequest\r
+  )\r
+{\r
+  EFI_STRING  EndStr;\r
+  EFI_STRING  ConfigHdrEndStr;\r
+  EFI_STRING  ElementStr;\r
+  UINTN       TotalSize;\r
+  UINTN       RestoreEleSize;\r
+  UINTN       SyncSize;\r
+\r
+  ASSERT ((*Progress == L'&') || (*Progress == L'G'));\r
+  //\r
+  // If the Progress starts with ConfigHdr, means the failure is in the first name / value pair.\r
+  // Need to restore all the fields in the ConfigRequest.\r
+  //\r
+  if (*Progress == L'G') {\r
+    *RestoreConfigRequest = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);\r
+    ASSERT (*RestoreConfigRequest != NULL);\r
+    return;\r
+  }\r
+\r
+  //\r
+  // Find the first fail "NAME" or "OFFSET=0x####&WIDTH=0x####" string.\r
+  //\r
+  if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+    //\r
+    // For Name/Value type, the data is "&Fred=16&George=16&Ron=12" formset,\r
+    // here, just keep the "Fred" string.\r
+    //\r
+    EndStr = StrStr (Progress, L"=");\r
+    ASSERT (EndStr != NULL);\r
+    *EndStr = L'\0';\r
+    //\r
+    // Find the ConfigHdr in ConfigRequest.\r
+    //\r
+    ConfigHdrEndStr = StrStr (ConfigRequest, L"PATH=");\r
+    ASSERT (ConfigHdrEndStr != NULL);\r
+    while (*ConfigHdrEndStr != L'&') {\r
+      ConfigHdrEndStr++;\r
+    }\r
+  } else {\r
+    //\r
+    // For Buffer type, the data is "OFFSET=0x####&WIDTH=0x####&VALUE=0x####",\r
+    // here, just keep the "OFFSET=0x####&WIDTH=0x####" string.\r
+    //\r
+    EndStr = StrStr (Progress, L"&VALUE=");\r
+    ASSERT (EndStr != NULL);\r
+    *EndStr = L'\0';\r
+    //\r
+    // Find the ConfigHdr in ConfigRequest.\r
+    //\r
+    ConfigHdrEndStr = StrStr (ConfigRequest, L"&OFFSET=");\r
+  }\r
+\r
+  //\r
+  // Find the first fail pair in the ConfigRequest.\r
+  //\r
+  ElementStr = StrStr (ConfigRequest, Progress);\r
+  ASSERT (ElementStr != NULL);\r
+  //\r
+  // To get the RestoreConfigRequest.\r
+  //\r
+  RestoreEleSize        = StrSize (ElementStr);\r
+  TotalSize             = (ConfigHdrEndStr - ConfigRequest) * sizeof (CHAR16) + RestoreEleSize + sizeof (CHAR16);\r
+  *RestoreConfigRequest = AllocateZeroPool (TotalSize);\r
+  ASSERT (*RestoreConfigRequest != NULL);\r
+  StrnCpyS (*RestoreConfigRequest, TotalSize / sizeof (CHAR16), ConfigRequest, ConfigHdrEndStr - ConfigRequest);\r
+  StrCatS (*RestoreConfigRequest, TotalSize / sizeof (CHAR16), ElementStr);\r
+  //\r
+  // To get the SyncConfigRequest.\r
+  //\r
+  SyncSize           = StrSize (ConfigRequest) - RestoreEleSize + sizeof (CHAR16);\r
+  *SyncConfigRequest = AllocateZeroPool (SyncSize);\r
+  ASSERT (*SyncConfigRequest != NULL);\r
+  StrnCpyS (*SyncConfigRequest, SyncSize / sizeof (CHAR16), ConfigRequest, SyncSize / sizeof (CHAR16) - 1);\r
+\r
+  //\r
+  // restore the Progress string to the original format.\r
+  //\r
+  if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+    *EndStr = L'=';\r
+  } else {\r
+    *EndStr = L'&';\r
+  }\r
+}\r
+\r
+/**\r
+  Popup an save error info and get user input.\r
+\r
+  @param  TitleId                The form title id.\r
+  @param  HiiHandle              The hii handle for this package.\r
+\r
+  @retval UINT32                 The user select option for the save fail.\r
+                                 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET\r
+**/\r
+UINT32\r
+ConfirmSaveFail (\r
+  IN EFI_STRING_ID   TitleId,\r
+  IN EFI_HII_HANDLE  HiiHandle\r
+  )\r
+{\r
+  CHAR16  *FormTitle;\r
+  CHAR16  *StringBuffer;\r
+  UINT32  RetVal;\r
+\r
+  FormTitle = GetToken (TitleId, HiiHandle);\r
+\r
+  StringBuffer = AllocateZeroPool (256 * sizeof (CHAR16));\r
+  ASSERT (StringBuffer != NULL);\r
+\r
+  UnicodeSPrint (\r
+    StringBuffer,\r
+    24 * sizeof (CHAR16) + StrSize (FormTitle),\r
+    L"Submit Fail For Form: %s.",\r
+    FormTitle\r
+    );\r
+\r
+  RetVal = PopupErrorMessage (BROWSER_SUBMIT_FAIL, NULL, NULL, StringBuffer);\r
+\r
+  FreePool (StringBuffer);\r
+  FreePool (FormTitle);\r
+\r
+  return RetVal;\r
+}\r
+\r
+/**\r
+  Popup an NO_SUBMIT_IF error info and get user input.\r
+\r
+  @param  TitleId                The form title id.\r
+  @param  HiiHandle              The hii handle for this package.\r
+\r
+  @retval UINT32                 The user select option for the save fail.\r
+                                 BROWSER_ACTION_DISCARD or BROWSER_ACTION_JUMP_TO_FORMSET\r
+**/\r
+UINT32\r
+ConfirmNoSubmitFail (\r
+  IN EFI_STRING_ID   TitleId,\r
+  IN EFI_HII_HANDLE  HiiHandle\r
+  )\r
+{\r
+  CHAR16  *FormTitle;\r
+  CHAR16  *StringBuffer;\r
+  UINT32  RetVal;\r
+\r
+  FormTitle = GetToken (TitleId, HiiHandle);\r
+\r
+  StringBuffer = AllocateZeroPool (256 * sizeof (CHAR16));\r
+  ASSERT (StringBuffer != NULL);\r
+\r
+  UnicodeSPrint (\r
+    StringBuffer,\r
+    24 * sizeof (CHAR16) + StrSize (FormTitle),\r
+    L"NO_SUBMIT_IF error For Form: %s.",\r
+    FormTitle\r
+    );\r
+\r
+  RetVal = PopupErrorMessage (BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF, NULL, NULL, StringBuffer);\r
+\r
+  FreePool (StringBuffer);\r
+  FreePool (FormTitle);\r
+\r
+  return RetVal;\r
+}\r
+\r
+/**\r
+  Discard data based on the input setting scope (Form, FormSet or System).\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   Form data structure.\r
+  @param  SettingScope           Setting Scope for Discard action.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+  @retval EFI_UNSUPPORTED        Unsupport SettingScope.\r
+\r
+**/\r
+EFI_STATUS\r
+DiscardForm (\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
+  FORMSET_STORAGE              *Storage;\r
+  FORM_BROWSER_CONFIG_REQUEST  *ConfigInfo;\r
+  FORM_BROWSER_FORMSET         *LocalFormSet;\r
+  FORM_BROWSER_FORMSET         *OldFormSet;\r
+\r
+  //\r
+  // Check the supported setting level.\r
+  //\r
+  if (SettingScope >= MaxLevel) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if ((SettingScope == FormLevel) && IsNvUpdateRequiredForForm (Form)) {\r
+    ConfigInfo = NULL;\r
+    Link       = GetFirstNode (&Form->ConfigRequestHead);\r
+    while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
+      ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
+      Link       = GetNextNode (&Form->ConfigRequestHead, Link);\r
+\r
+      if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+        continue;\r
+      }\r
+\r
+      //\r
+      // Skip if there is no RequestElement\r
+      //\r
+      if (ConfigInfo->ElementCount == 0) {\r
+        continue;\r
+      }\r
+\r
+      //\r
+      // Prepare <ConfigResp>\r
+      //\r
+      SynchronizeStorage (ConfigInfo->Storage, ConfigInfo->ConfigRequest, FALSE);\r
+\r
+      //\r
+      // Call callback with Changed type to inform the driver.\r
+      //\r
+      SendDiscardInfoToDriver (FormSet, Form);\r
+    }\r
+\r
+    ValueChangeResetFlagUpdate (FALSE, FormSet, Form);\r
+  } else if ((SettingScope == FormSetLevel) && IsNvUpdateRequiredForFormSet (FormSet)) {\r
+    //\r
+    // Discard Buffer storage or Name/Value storage\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
+      if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+        continue;\r
+      }\r
+\r
+      //\r
+      // Skip if there is no RequestElement\r
+      //\r
+      if (Storage->ElementCount == 0) {\r
+        continue;\r
+      }\r
+\r
+      SynchronizeStorage (Storage->BrowserStorage, Storage->ConfigRequest, FALSE);\r
+    }\r
+\r
+    Link = GetFirstNode (&FormSet->FormListHead);\r
+    while (!IsNull (&FormSet->FormListHead, Link)) {\r
+      Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+      Link = GetNextNode (&FormSet->FormListHead, Link);\r
+\r
+      //\r
+      // Call callback with Changed type to inform the driver.\r
+      //\r
+      SendDiscardInfoToDriver (FormSet, Form);\r
+    }\r
+\r
+    ValueChangeResetFlagUpdate (FALSE, FormSet, NULL);\r
+  } else if (SettingScope == SystemLevel) {\r
+    //\r
+    // System Level Discard.\r
+    //\r
+    OldFormSet = mSystemLevelFormSet;\r
+\r
+    //\r
+    // Discard changed value for each FormSet in the maintain list.\r
+    //\r
+    Link = GetFirstNode (&gBrowserFormSetList);\r
+    while (!IsNull (&gBrowserFormSetList, Link)) {\r
+      LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
+      Link         = GetNextNode (&gBrowserFormSetList, Link);\r
+      if (!ValidateFormSet (LocalFormSet)) {\r
+        continue;\r
+      }\r
+\r
+      mSystemLevelFormSet = LocalFormSet;\r
+\r
+      DiscardForm (LocalFormSet, NULL, FormSetLevel);\r
+      if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {\r
+        //\r
+        // Remove maintain backup list after discard except for the current using FormSet.\r
+        //\r
+        CleanBrowserStorage (LocalFormSet);\r
+        RemoveEntryList (&LocalFormSet->Link);\r
+        DestroyFormSet (LocalFormSet);\r
+      }\r
+    }\r
+\r
+    mSystemLevelFormSet = OldFormSet;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Submit data for a form.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   Form data structure.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+  @retval EFI_UNSUPPORTED        Unsupport SettingScope.\r
+\r
+**/\r
+EFI_STATUS\r
+SubmitForForm (\r
+  IN FORM_BROWSER_FORMSET  *FormSet,\r
+  IN FORM_BROWSER_FORM     *Form\r
+  )\r
+{\r
+  EFI_STATUS                   Status;\r
+  LIST_ENTRY                   *Link;\r
+  EFI_STRING                   ConfigResp;\r
+  EFI_STRING                   Progress;\r
+  BROWSER_STORAGE              *Storage;\r
+  FORM_BROWSER_CONFIG_REQUEST  *ConfigInfo;\r
+  BOOLEAN                      SubmitFormFail;\r
+\r
+  SubmitFormFail = FALSE;\r
+\r
+  if (!IsNvUpdateRequiredForForm (Form)) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  Status = NoSubmitCheck (FormSet, &Form, NULL);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Link = GetFirstNode (&Form->ConfigRequestHead);\r
+  while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
+    ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
+    Link       = GetNextNode (&Form->ConfigRequestHead, Link);\r
+\r
+    Storage = ConfigInfo->Storage;\r
+    if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Skip if there is no RequestElement\r
+    //\r
+    if (ConfigInfo->ElementCount == 0) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // 1. Prepare <ConfigResp>\r
+    //\r
+    Status = StorageToConfigResp (ConfigInfo->Storage, &ConfigResp, ConfigInfo->ConfigRequest, TRUE);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // 2. Set value to hii config routine protocol.\r
+    //\r
+    Status = mHiiConfigRouting->RouteConfig (\r
+                                  mHiiConfigRouting,\r
+                                  ConfigResp,\r
+                                  &Progress\r
+                                  );\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // Submit fail, to get the RestoreConfigRequest and SyncConfigRequest.\r
+      //\r
+      SubmitFormFail = TRUE;\r
+      GetSyncRestoreConfigRequest (ConfigInfo->Storage, ConfigInfo->ConfigRequest, Progress, &ConfigInfo->RestoreConfigRequest, &ConfigInfo->SyncConfigRequest);\r
+      InsertTailList (&gBrowserSaveFailFormSetList, &ConfigInfo->SaveFailLink);\r
+      FreePool (ConfigResp);\r
+      continue;\r
+    }\r
+\r
+    FreePool (ConfigResp);\r
+    //\r
+    // 3. Config success, update storage shadow Buffer, only update the data belong to this form.\r
+    //\r
+    SynchronizeStorage (ConfigInfo->Storage, ConfigInfo->ConfigRequest, TRUE);\r
+  }\r
+\r
+  //\r
+  // 4. Process the save failed storage.\r
+  //\r
+  if (!IsListEmpty (&gBrowserSaveFailFormSetList)) {\r
+    if (ConfirmSaveFail (Form->FormTitle, FormSet->HiiHandle) == BROWSER_ACTION_DISCARD) {\r
+      Link = GetFirstNode (&gBrowserSaveFailFormSetList);\r
+      while (!IsNull (&gBrowserSaveFailFormSetList, Link)) {\r
+        ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link);\r
+        Link       = GetNextNode (&gBrowserSaveFailFormSetList, Link);\r
+        //\r
+        // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer\r
+        // base on the SyncConfigRequest to Sync the buffer.\r
+        //\r
+        SynchronizeStorage (ConfigInfo->Storage, ConfigInfo->RestoreConfigRequest, FALSE);\r
+        FreePool (ConfigInfo->RestoreConfigRequest);\r
+        ConfigInfo->RestoreConfigRequest = NULL;\r
+        if (ConfigInfo->SyncConfigRequest != NULL) {\r
+          SynchronizeStorage (ConfigInfo->Storage, ConfigInfo->SyncConfigRequest, TRUE);\r
+          FreePool (ConfigInfo->SyncConfigRequest);\r
+          ConfigInfo->SyncConfigRequest = NULL;\r
+        }\r
+\r
+        Status = EFI_SUCCESS;\r
+      }\r
+\r
+      SendDiscardInfoToDriver (FormSet, Form);\r
+    } else {\r
+      Status = EFI_UNSUPPORTED;\r
+    }\r
+\r
+    //\r
+    // Free Form save fail list.\r
+    //\r
+    while (!IsListEmpty (&gBrowserSaveFailFormSetList)) {\r
+      Link       = GetFirstNode (&gBrowserSaveFailFormSetList);\r
+      ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_SAVE_FAIL_LINK (Link);\r
+      RemoveEntryList (&ConfigInfo->SaveFailLink);\r
+    }\r
+  }\r
+\r
+  //\r
+  // 5. Update the NV flag.\r
+  //\r
+  ValueChangeResetFlagUpdate (TRUE, FormSet, Form);\r
+\r
+  //\r
+  // 6 Call callback with Submitted type to inform the driver.\r
+  //\r
+  if (!SubmitFormFail) {\r
+    SubmitCallback (FormSet, Form);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Submit data for a formset.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  SkipProcessFail        Whether skip to process the save failed storage.\r
+                                 If submit formset is called when do system level save,\r
+                                 set this value to true and process the failed formset\r
+                                 together.\r
+                                 if submit formset is called when do formset level save,\r
+                                 set the value to false and process the failed storage\r
+                                 right after process all storages for this formset.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+  @retval EFI_UNSUPPORTED        Unsupport SettingScope.\r
+\r
+**/\r
+EFI_STATUS\r
+SubmitForFormSet (\r
+  IN FORM_BROWSER_FORMSET  *FormSet,\r
+  IN BOOLEAN               SkipProcessFail\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  LIST_ENTRY              *Link;\r
+  EFI_STRING              ConfigResp;\r
+  EFI_STRING              Progress;\r
+  BROWSER_STORAGE         *Storage;\r
+  FORMSET_STORAGE         *FormSetStorage;\r
+  FORM_BROWSER_FORM       *Form;\r
+  BOOLEAN                 HasInserted;\r
+  FORM_BROWSER_STATEMENT  *Question;\r
+  BOOLEAN                 SubmitFormSetFail;\r
+  BOOLEAN                 DiscardChange;\r
+\r
+  HasInserted       = FALSE;\r
+  SubmitFormSetFail = FALSE;\r
+  DiscardChange     = FALSE;\r
+\r
+  if (!IsNvUpdateRequiredForFormSet (FormSet)) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  Form   = NULL;\r
+  Status = NoSubmitCheck (FormSet, &Form, &Question);\r
+  if (EFI_ERROR (Status)) {\r
+    if (SkipProcessFail) {\r
+      //\r
+      // Process NO_SUBMIT check first, so insert it at head.\r
+      //\r
+      FormSet->SaveFailForm      = Form;\r
+      FormSet->SaveFailStatement = Question;\r
+      InsertHeadList (&gBrowserSaveFailFormSetList, &FormSet->SaveFailLink);\r
+    }\r
+\r
+    return Status;\r
+  }\r
+\r
+  Form     = NULL;\r
+  Question = NULL;\r
+  //\r
+  // Submit Buffer storage or Name/Value storage\r
+  //\r
+  Link = GetFirstNode (&FormSet->StorageListHead);\r
+  while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+    FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
+    Storage        = FormSetStorage->BrowserStorage;\r
+    Link           = GetNextNode (&FormSet->StorageListHead, Link);\r
+\r
+    if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Skip if there is no RequestElement\r
+    //\r
+    if (FormSetStorage->ElementCount == 0) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // 1. Prepare <ConfigResp>\r
+    //\r
+    Status = StorageToConfigResp (Storage, &ConfigResp, FormSetStorage->ConfigRequest, TRUE);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // 2. Send <ConfigResp> to Routine config Protocol.\r
+    //\r
+    Status = mHiiConfigRouting->RouteConfig (\r
+                                  mHiiConfigRouting,\r
+                                  ConfigResp,\r
+                                  &Progress\r
+                                  );\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // Submit fail, to get the RestoreConfigRequest and SyncConfigRequest.\r
+      //\r
+      SubmitFormSetFail = TRUE;\r
+      GetSyncRestoreConfigRequest (FormSetStorage->BrowserStorage, FormSetStorage->ConfigRequest, Progress, &FormSetStorage->RestoreConfigRequest, &FormSetStorage->SyncConfigRequest);\r
+      InsertTailList (&FormSet->SaveFailStorageListHead, &FormSetStorage->SaveFailLink);\r
+      if (!HasInserted) {\r
+        //\r
+        // Call submit formset for system level, save the formset info\r
+        // and process later.\r
+        //\r
+        FindQuestionFromProgress (FormSet, Storage, Progress, &Form, &Question);\r
+        ASSERT (Form != NULL && Question != NULL);\r
+        FormSet->SaveFailForm      = Form;\r
+        FormSet->SaveFailStatement = Question;\r
+        if (SkipProcessFail) {\r
+          InsertTailList (&gBrowserSaveFailFormSetList, &FormSet->SaveFailLink);\r
+        }\r
+\r
+        HasInserted = TRUE;\r
+      }\r
+\r
+      FreePool (ConfigResp);\r
+      continue;\r
+    }\r
+\r
+    FreePool (ConfigResp);\r
+    //\r
+    // 3. Config success, update storage shadow Buffer\r
+    //\r
+    SynchronizeStorage (Storage, FormSetStorage->ConfigRequest, TRUE);\r
+  }\r
+\r
+  //\r
+  // 4. Has save fail storage need to handle.\r
+  //\r
+  if (Form != NULL) {\r
+    if (!SkipProcessFail) {\r
+      //\r
+      // If not in system level, just handl the save failed storage here.\r
+      //\r
+      if (ConfirmSaveFail (Form->FormTitle, FormSet->HiiHandle) == BROWSER_ACTION_DISCARD) {\r
+        DiscardChange = TRUE;\r
+        Link          = GetFirstNode (&FormSet->SaveFailStorageListHead);\r
+        while (!IsNull (&FormSet->SaveFailStorageListHead, Link)) {\r
+          FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link);\r
+          Storage        = FormSetStorage->BrowserStorage;\r
+          Link           = GetNextNode (&FormSet->SaveFailStorageListHead, Link);\r
+          //\r
+          // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer\r
+          // base on the SyncConfigRequest to Sync the buffer.\r
+          //\r
+          SynchronizeStorage (FormSetStorage->BrowserStorage, FormSetStorage->RestoreConfigRequest, FALSE);\r
+          FreePool (FormSetStorage->RestoreConfigRequest);\r
+          FormSetStorage->RestoreConfigRequest = NULL;\r
+          if (FormSetStorage->SyncConfigRequest != NULL) {\r
+            SynchronizeStorage (FormSetStorage->BrowserStorage, FormSetStorage->SyncConfigRequest, TRUE);\r
+            FreePool (FormSetStorage->SyncConfigRequest);\r
+            FormSetStorage->SyncConfigRequest = NULL;\r
+          }\r
+\r
+          Status = EFI_SUCCESS;\r
+        }\r
+      } else {\r
+        UiCopyMenuList (&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &Form->FormViewListHead);\r
+\r
+        gCurrentSelection->Action = UI_ACTION_REFRESH_FORMSET;\r
+        gCurrentSelection->Handle = FormSet->HiiHandle;\r
+        CopyGuid (&gCurrentSelection->FormSetGuid, &FormSet->Guid);\r
+        gCurrentSelection->FormId     = Form->FormId;\r
+        gCurrentSelection->QuestionId = Question->QuestionId;\r
+\r
+        Status = EFI_UNSUPPORTED;\r
+      }\r
+\r
+      //\r
+      // Free FormSet save fail list.\r
+      //\r
+      while (!IsListEmpty (&FormSet->SaveFailStorageListHead)) {\r
+        Link           = GetFirstNode (&FormSet->SaveFailStorageListHead);\r
+        FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (Link);\r
+        RemoveEntryList (&FormSetStorage->SaveFailLink);\r
+      }\r
+    } else {\r
+      //\r
+      // If in system level, just return error and handle the failed formset later.\r
+      //\r
+      Status = EFI_UNSUPPORTED;\r
+    }\r
+  }\r
+\r
+  //\r
+  // If user discard the change, send the discard info to driver.\r
+  //\r
+  if (DiscardChange) {\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
+      // Call callback with Changed type to inform the driver.\r
+      //\r
+      SendDiscardInfoToDriver (FormSet, Form);\r
+    }\r
+  }\r
+\r
+  //\r
+  // 5. Update the NV flag.\r
+  //\r
+  ValueChangeResetFlagUpdate (TRUE, FormSet, NULL);\r
+\r
+  //\r
+  // 6. Call callback with Submitted type to inform the driver.\r
+  //\r
+  if (!SubmitFormSetFail) {\r
+    SubmitCallback (FormSet, NULL);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Submit data for all formsets.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+  @retval EFI_UNSUPPORTED        Unsupport SettingScope.\r
+\r
+**/\r
+EFI_STATUS\r
+SubmitForSystem (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  LIST_ENTRY              *Link;\r
+  LIST_ENTRY              *FormLink;\r
+  LIST_ENTRY              *StorageLink;\r
+  FORMSET_STORAGE         *FormSetStorage;\r
+  FORM_BROWSER_FORM       *Form;\r
+  FORM_BROWSER_FORMSET    *LocalFormSet;\r
+  UINT32                  UserSelection;\r
+  FORM_BROWSER_STATEMENT  *Question;\r
+\r
+  mSystemSubmit = TRUE;\r
+  Link          = GetFirstNode (&gBrowserFormSetList);\r
+  while (!IsNull (&gBrowserFormSetList, Link)) {\r
+    LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
+    Link         = GetNextNode (&gBrowserFormSetList, Link);\r
+    if (!ValidateFormSet (LocalFormSet)) {\r
+      continue;\r
+    }\r
+\r
+    Status = SubmitForFormSet (LocalFormSet, TRUE);\r
+    if (EFI_ERROR (Status)) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Remove maintain backup list after save except for the current using FormSet.\r
+    //\r
+    if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {\r
+      CleanBrowserStorage (LocalFormSet);\r
+      RemoveEntryList (&LocalFormSet->Link);\r
+      DestroyFormSet (LocalFormSet);\r
+    }\r
+  }\r
+\r
+  mSystemSubmit = FALSE;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  // Process the save failed formsets.\r
+  //\r
+  Link = GetFirstNode (&gBrowserSaveFailFormSetList);\r
+  while (!IsNull (&gBrowserSaveFailFormSetList, Link)) {\r
+    LocalFormSet = FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link);\r
+    Link         = GetNextNode (&gBrowserSaveFailFormSetList, Link);\r
+\r
+    if (!ValidateFormSet (LocalFormSet)) {\r
+      continue;\r
+    }\r
+\r
+    Form     = LocalFormSet->SaveFailForm;\r
+    Question = LocalFormSet->SaveFailStatement;\r
+\r
+    //\r
+    // Confirm with user, get user input.\r
+    //\r
+    if (IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {\r
+      //\r
+      // NULL for SaveFailStorageListHead means error caused by NO_SUBMIT_IF check.\r
+      //\r
+      UserSelection = ConfirmNoSubmitFail (Form->FormTitle, LocalFormSet->HiiHandle);\r
+    } else {\r
+      UserSelection = ConfirmSaveFail (Form->FormTitle, LocalFormSet->HiiHandle);\r
+    }\r
+\r
+    if (UserSelection == BROWSER_ACTION_DISCARD) {\r
+      if (IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {\r
+        StorageLink = GetFirstNode (&LocalFormSet->StorageListHead);\r
+        while (!IsNull (&LocalFormSet->StorageListHead, StorageLink)) {\r
+          FormSetStorage = FORMSET_STORAGE_FROM_LINK (StorageLink);\r
+          StorageLink    = GetNextNode (&LocalFormSet->StorageListHead, StorageLink);\r
+\r
+          SynchronizeStorage (FormSetStorage->BrowserStorage, FormSetStorage->ConfigRequest, FALSE);\r
+        }\r
+      } else {\r
+        StorageLink = GetFirstNode (&LocalFormSet->SaveFailStorageListHead);\r
+        while (!IsNull (&LocalFormSet->SaveFailStorageListHead, StorageLink)) {\r
+          FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink);\r
+          StorageLink    = GetNextNode (&LocalFormSet->SaveFailStorageListHead, StorageLink);\r
+          //\r
+          // Process the submit fail question, base on the RestoreConfigRequest to restore the EditBuffer\r
+          // base on the SyncConfigRequest to Sync the buffer.\r
+          //\r
+          SynchronizeStorage (FormSetStorage->BrowserStorage, FormSetStorage->RestoreConfigRequest, FALSE);\r
+          FreePool (FormSetStorage->RestoreConfigRequest);\r
+          FormSetStorage->RestoreConfigRequest = NULL;\r
+          if ( FormSetStorage->SyncConfigRequest != NULL) {\r
+            SynchronizeStorage (FormSetStorage->BrowserStorage, FormSetStorage->SyncConfigRequest, TRUE);\r
+            FreePool (FormSetStorage->SyncConfigRequest);\r
+            FormSetStorage->SyncConfigRequest = NULL;\r
+          }\r
+        }\r
+      }\r
+\r
+      FormLink = GetFirstNode (&LocalFormSet->FormListHead);\r
+      while (!IsNull (&LocalFormSet->FormListHead, FormLink)) {\r
+        Form     = FORM_BROWSER_FORM_FROM_LINK (FormLink);\r
+        FormLink = GetNextNode (&LocalFormSet->FormListHead, FormLink);\r
+        //\r
+        // Call callback with Changed type to inform the driver.\r
+        //\r
+        SendDiscardInfoToDriver (LocalFormSet, Form);\r
+      }\r
+\r
+      if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {\r
+        CleanBrowserStorage (LocalFormSet);\r
+        RemoveEntryList (&LocalFormSet->Link);\r
+        RemoveEntryList (&LocalFormSet->SaveFailLink);\r
+        DestroyFormSet (LocalFormSet);\r
+      } else {\r
+        ValueChangeResetFlagUpdate (FALSE, LocalFormSet, NULL);\r
+      }\r
+    } else {\r
+      if (IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {\r
+        NoSubmitCheck (LocalFormSet, &Form, &Question);\r
+      }\r
+\r
+      UiCopyMenuList (&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &Form->FormViewListHead);\r
+\r
+      gCurrentSelection->Action = UI_ACTION_REFRESH_FORMSET;\r
+      gCurrentSelection->Handle = LocalFormSet->HiiHandle;\r
+      CopyGuid (&gCurrentSelection->FormSetGuid, &LocalFormSet->Guid);\r
+      gCurrentSelection->FormId     = Form->FormId;\r
+      gCurrentSelection->QuestionId = Question->QuestionId;\r
+\r
+      Status = EFI_UNSUPPORTED;\r
+      break;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Clean the list which will not process.\r
+  //\r
+  while (!IsListEmpty (&gBrowserSaveFailFormSetList)) {\r
+    Link         = GetFirstNode (&gBrowserSaveFailFormSetList);\r
+    LocalFormSet = FORM_BROWSER_FORMSET_FROM_SAVE_FAIL_LINK (Link);\r
+    RemoveEntryList (&LocalFormSet->SaveFailLink);\r
+\r
+    while (!IsListEmpty (&LocalFormSet->SaveFailStorageListHead)) {\r
+      StorageLink    = GetFirstNode (&LocalFormSet->SaveFailStorageListHead);\r
+      FormSetStorage = FORMSET_STORAGE_FROM_SAVE_FAIL_LINK (StorageLink);\r
+      RemoveEntryList (&FormSetStorage->SaveFailLink);\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Submit data based on the input Setting level (Form, FormSet or System).\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   Form data structure.\r
+  @param  SettingScope           Setting Scope for Submit action.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+  @retval EFI_UNSUPPORTED        Unsupport SettingScope.\r
+\r
+**/\r
+EFI_STATUS\r
+SubmitForm (\r
+  IN FORM_BROWSER_FORMSET   *FormSet,\r
+  IN FORM_BROWSER_FORM      *Form,\r
+  IN BROWSER_SETTING_SCOPE  SettingScope\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  switch (SettingScope) {\r
+    case FormLevel:\r
+      Status = SubmitForForm (FormSet, Form);\r
+      break;\r
+\r
+    case FormSetLevel:\r
+      Status = SubmitForFormSet (FormSet, FALSE);\r
+      break;\r
+\r
+    case SystemLevel:\r
+      Status = SubmitForSystem ();\r
+      break;\r
+\r
+    default:\r
+      Status = EFI_UNSUPPORTED;\r
+      break;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Converts the unicode character of the string from uppercase to lowercase.\r
+  This is a internal function.\r
+\r
+  @param ConfigString  String to be converted\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+HiiToLower (\r
+  IN EFI_STRING  ConfigString\r
+  )\r
+{\r
+  EFI_STRING  String;\r
+  BOOLEAN     Lower;\r
+\r
+  ASSERT (ConfigString != NULL);\r
+\r
+  //\r
+  // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
+  //\r
+  for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {\r
+    if (*String == L'=') {\r
+      Lower = TRUE;\r
+    } else if (*String == L'&') {\r
+      Lower = FALSE;\r
+    } else if (Lower && (*String >= L'A') && (*String <= L'F')) {\r
+      *String = (CHAR16)(*String - L'A' + L'a');\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  Find the point in the ConfigResp string for this question.\r
+\r
+  @param  Question               The question.\r
+  @param  ConfigResp             Get ConfigResp string.\r
+\r
+  @retval  point to the offset where is for this question.\r
+\r
+**/\r
+CHAR16 *\r
+GetOffsetFromConfigResp (\r
+  IN FORM_BROWSER_STATEMENT  *Question,\r
+  IN CHAR16                  *ConfigResp\r
+  )\r
+{\r
+  CHAR16  *RequestElement;\r
+  CHAR16  *BlockData;\r
+\r
+  //\r
+  // Type is EFI_HII_VARSTORE_NAME_VALUE.\r
+  //\r
+  if (Question->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+    RequestElement = StrStr (ConfigResp, Question->VariableName);\r
+    if (RequestElement != NULL) {\r
+      //\r
+      // Skip the "VariableName=" field.\r
+      //\r
+      RequestElement += StrLen (Question->VariableName) + 1;\r
+    }\r
+\r
+    return RequestElement;\r
+  }\r
+\r
+  //\r
+  // Type is EFI_HII_VARSTORE_EFI_VARIABLE or EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER\r
+  //\r
+\r
+  //\r
+  // Convert all hex digits in ConfigResp to lower case before searching.\r
+  //\r
+  HiiToLower (ConfigResp);\r
+\r
+  //\r
+  // 1. Directly use Question->BlockName to find.\r
+  //\r
+  RequestElement = StrStr (ConfigResp, Question->BlockName);\r
+  if (RequestElement != NULL) {\r
+    //\r
+    // Skip the "Question->BlockName&VALUE=" field.\r
+    //\r
+    RequestElement += StrLen (Question->BlockName) + StrLen (L"&VALUE=");\r
+    return RequestElement;\r
+  }\r
+\r
+  //\r
+  // 2. Change all hex digits in Question->BlockName to lower and compare again.\r
+  //\r
+  BlockData = AllocateCopyPool (StrSize (Question->BlockName), Question->BlockName);\r
+  ASSERT (BlockData != NULL);\r
+  HiiToLower (BlockData);\r
+  RequestElement = StrStr (ConfigResp, BlockData);\r
+  FreePool (BlockData);\r
+\r
+  if (RequestElement != NULL) {\r
+    //\r
+    // Skip the "Question->BlockName&VALUE=" field.\r
+    //\r
+    RequestElement += StrLen (Question->BlockName) + StrLen (L"&VALUE=");\r
+  }\r
+\r
+  return RequestElement;\r
+}\r
+\r
+/**\r
+  Get Question default value from AltCfg string.\r
+\r
+  @param  FormSet                The form set.\r
+  @param  Form                   The form\r
+  @param  Question               The question.\r
+\r
+  @retval EFI_SUCCESS            Question is reset to default value.\r
+\r
+**/\r
+EFI_STATUS\r
+GetDefaultValueFromAltCfg (\r
+  IN     FORM_BROWSER_FORMSET    *FormSet,\r
+  IN     FORM_BROWSER_FORM       *Form,\r
+  IN OUT FORM_BROWSER_STATEMENT  *Question\r
+  )\r
+{\r
+  BROWSER_STORAGE              *Storage;\r
+  FORMSET_STORAGE              *FormSetStorage;\r
+  CHAR16                       *ConfigResp;\r
+  CHAR16                       *Value;\r
+  LIST_ENTRY                   *Link;\r
+  FORM_BROWSER_CONFIG_REQUEST  *ConfigInfo;\r
+\r
+  Storage = Question->Storage;\r
+  if ((Storage == NULL) || (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  //\r
+  // Try to get AltCfg string from form. If not found it, then\r
+  // try to get it from formset.\r
+  //\r
+  ConfigResp = NULL;\r
+  Link       = GetFirstNode (&Form->ConfigRequestHead);\r
+  while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
+    ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
+    Link       = GetNextNode (&Form->ConfigRequestHead, Link);\r
+\r
+    if (Storage == ConfigInfo->Storage) {\r
+      ConfigResp = ConfigInfo->ConfigAltResp;\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (ConfigResp == NULL) {\r
+    Link = GetFirstNode (&FormSet->StorageListHead);\r
+    while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+      FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
+      Link           = GetNextNode (&FormSet->StorageListHead, Link);\r
+\r
+      if (Storage == FormSetStorage->BrowserStorage) {\r
+        ConfigResp = FormSetStorage->ConfigAltResp;\r
+        break;\r
+      }\r
+    }\r
+  }\r
+\r
+  if (ConfigResp == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  Value = GetOffsetFromConfigResp (Question, ConfigResp);\r
+  if (Value == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  return BufferToValue (Question, Value);\r
+}\r
+\r
+/**\r
+  Get default Id value used for browser.\r
+\r
+  @param  DefaultId              The default id value used by hii.\r
+\r
+  @retval Browser used default value.\r
+\r
+**/\r
+INTN\r
+GetDefaultIdForCallBack (\r
+  UINTN  DefaultId\r
+  )\r
+{\r
+  if (DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) {\r
+    return EFI_BROWSER_ACTION_DEFAULT_STANDARD;\r
+  } else if (DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
+    return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING;\r
+  } else if (DefaultId == EFI_HII_DEFAULT_CLASS_SAFE) {\r
+    return EFI_BROWSER_ACTION_DEFAULT_SAFE;\r
+  } else if ((DefaultId >= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN) && (DefaultId < EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN + 0x1000)) {\r
+    return EFI_BROWSER_ACTION_DEFAULT_PLATFORM + DefaultId - EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN;\r
+  } else if ((DefaultId >= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN) && (DefaultId < EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN + 0x1000)) {\r
+    return EFI_BROWSER_ACTION_DEFAULT_HARDWARE + DefaultId - EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN;\r
+  } else if ((DefaultId >= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN) && (DefaultId < EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN + 0x1000)) {\r
+    return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE + DefaultId - EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN;\r
+  } else {\r
+    return -1;\r
+  }\r
+}\r
+\r
+/**\r
+  Return data element in an Array by its Index.\r
+\r
+  @param  Array                  The data array.\r
+  @param  Type                   Type of the data in this array.\r
+  @param  Index                  Zero based index for data in this array.\r
+\r
+  @retval Value                  The data to be returned\r
+\r
+**/\r
+UINT64\r
+GetArrayData (\r
+  IN VOID   *Array,\r
+  IN UINT8  Type,\r
+  IN UINTN  Index\r
+  )\r
+{\r
+  UINT64  Data;\r
+\r
+  ASSERT (Array != NULL);\r
+\r
+  Data = 0;\r
+  switch (Type) {\r
+    case EFI_IFR_TYPE_NUM_SIZE_8:\r
+      Data = (UINT64)*(((UINT8 *)Array) + Index);\r
+      break;\r
+\r
+    case EFI_IFR_TYPE_NUM_SIZE_16:\r
+      Data = (UINT64)*(((UINT16 *)Array) + Index);\r
+      break;\r
+\r
+    case EFI_IFR_TYPE_NUM_SIZE_32:\r
+      Data = (UINT64)*(((UINT32 *)Array) + Index);\r
+      break;\r
+\r
+    case EFI_IFR_TYPE_NUM_SIZE_64:\r
+      Data = (UINT64)*(((UINT64 *)Array) + Index);\r
+      break;\r
+\r
+    default:\r
+      break;\r
+  }\r
+\r
+  return Data;\r
+}\r
+\r
+/**\r
+  Set value of a data element in an Array by its Index.\r
+\r
+  @param  Array                  The data array.\r
+  @param  Type                   Type of the data in this array.\r
+  @param  Index                  Zero based index for data in this array.\r
+  @param  Value                  The value to be set.\r
+\r
+**/\r
+VOID\r
+SetArrayData (\r
+  IN VOID    *Array,\r
+  IN UINT8   Type,\r
+  IN UINTN   Index,\r
+  IN UINT64  Value\r
+  )\r
+{\r
+  ASSERT (Array != NULL);\r
+\r
+  switch (Type) {\r
+    case EFI_IFR_TYPE_NUM_SIZE_8:\r
+      *(((UINT8 *)Array) + Index) = (UINT8)Value;\r
+      break;\r
+\r
+    case EFI_IFR_TYPE_NUM_SIZE_16:\r
+      *(((UINT16 *)Array) + Index) = (UINT16)Value;\r
+      break;\r
+\r
+    case EFI_IFR_TYPE_NUM_SIZE_32:\r
+      *(((UINT32 *)Array) + Index) = (UINT32)Value;\r
+      break;\r
+\r
+    case EFI_IFR_TYPE_NUM_SIZE_64:\r
+      *(((UINT64 *)Array) + Index) = (UINT64)Value;\r
+      break;\r
+\r
+    default:\r
+      break;\r
+  }\r
+}\r
+\r
+/**\r
+  Search an Option of a Question by its value.\r
+\r
+  @param  Question               The Question\r
+  @param  OptionValue            Value for Option to be searched.\r
+\r
+  @retval Pointer                Pointer to the found Option.\r
+  @retval NULL                   Option not found.\r
+\r
+**/\r
+QUESTION_OPTION *\r
+ValueToOption (\r
+  IN FORM_BROWSER_STATEMENT  *Question,\r
+  IN EFI_HII_VALUE           *OptionValue\r
+  )\r
+{\r
+  LIST_ENTRY       *Link;\r
+  QUESTION_OPTION  *Option;\r
+  INTN             Result;\r
+\r
+  Link = GetFirstNode (&Question->OptionListHead);\r
+  while (!IsNull (&Question->OptionListHead, Link)) {\r
+    Option = QUESTION_OPTION_FROM_LINK (Link);\r
+\r
+    if ((CompareHiiValue (&Option->Value, OptionValue, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {\r
+      //\r
+      // Check the suppressif condition, only a valid option can be return.\r
+      //\r
+      if ((Option->SuppressExpression == NULL) ||\r
+          ((EvaluateExpressionList (Option->SuppressExpression, FALSE, NULL, NULL) == ExpressFalse)))\r
+      {\r
+        return Option;\r
+      }\r
+    }\r
+\r
+    Link = GetNextNode (&Question->OptionListHead, Link);\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Reset Question to its default value.\r
+\r
+  @param  FormSet                The form set.\r
+  @param  Form                   The form.\r
+  @param  Question               The question.\r
+  @param  DefaultId              The Class of the default.\r
+\r
+  @retval EFI_SUCCESS            Question is reset to default value.\r
+\r
+**/\r
+EFI_STATUS\r
+GetQuestionDefault (\r
+  IN FORM_BROWSER_FORMSET    *FormSet,\r
+  IN FORM_BROWSER_FORM       *Form,\r
+  IN FORM_BROWSER_STATEMENT  *Question,\r
+  IN UINT16                  DefaultId\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  LIST_ENTRY                      *Link;\r
+  QUESTION_DEFAULT                *Default;\r
+  QUESTION_OPTION                 *Option;\r
+  EFI_HII_VALUE                   *HiiValue;\r
+  UINT8                           Index;\r
+  EFI_STRING                      StrValue;\r
+  EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;\r
+  EFI_BROWSER_ACTION_REQUEST      ActionRequest;\r
+  INTN                            Action;\r
+  CHAR16                          *NewString;\r
+  EFI_IFR_TYPE_VALUE              *TypeValue;\r
+  UINT16                          OriginalDefaultId;\r
+  FORMSET_DEFAULTSTORE            *DefaultStore;\r
+  LIST_ENTRY                      *DefaultLink;\r
+\r
+  Status            = EFI_NOT_FOUND;\r
+  StrValue          = NULL;\r
+  OriginalDefaultId = DefaultId;\r
+  DefaultLink       = GetFirstNode (&FormSet->DefaultStoreListHead);\r
+\r
+  //\r
+  // Statement don't have storage, skip them\r
+  //\r
+  if (Question->QuestionId == 0) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // There are Five ways to specify default value for a Question:\r
+  //  1, use call back function (highest priority)\r
+  //  2, use ExtractConfig function\r
+  //  3, use nested EFI_IFR_DEFAULT\r
+  //  4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)\r
+  //  5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)\r
+  //\r
+ReGetDefault:\r
+  HiiValue  = &Question->HiiValue;\r
+  TypeValue = &HiiValue->Value;\r
+  if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
+    //\r
+    // For orderedlist, need to pass the BufferValue to Callback function.\r
+    //\r
+    TypeValue = (EFI_IFR_TYPE_VALUE *)Question->BufferValue;\r
+  }\r
+\r
+  //\r
+  // Get Question defaut value from call back function.\r
+  //\r
+  ConfigAccess = FormSet->ConfigAccess;\r
+  Action       = GetDefaultIdForCallBack (DefaultId);\r
+  if ((Action > 0) && ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) && (ConfigAccess != NULL)) {\r
+    ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+    Status        = ConfigAccess->Callback (\r
+                                    ConfigAccess,\r
+                                    Action,\r
+                                    Question->QuestionId,\r
+                                    HiiValue->Type,\r
+                                    TypeValue,\r
+                                    &ActionRequest\r
+                                    );\r
+    if (!EFI_ERROR (Status)) {\r
+      if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
+        NewString = GetToken (Question->HiiValue.Value.string, FormSet->HiiHandle);\r
+        ASSERT (NewString != NULL);\r
+\r
+        ASSERT (StrLen (NewString) * sizeof (CHAR16) <= Question->StorageWidth);\r
+        if (StrLen (NewString) * sizeof (CHAR16) <= Question->StorageWidth) {\r
+          ZeroMem (Question->BufferValue, Question->StorageWidth);\r
+          CopyMem (Question->BufferValue, NewString, StrSize (NewString));\r
+        } else {\r
+          CopyMem (Question->BufferValue, NewString, Question->StorageWidth);\r
+        }\r
+\r
+        FreePool (NewString);\r
+      }\r
+\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Get default value from altcfg string.\r
+  //\r
+  if (ConfigAccess != NULL) {\r
+    Status = GetDefaultValueFromAltCfg (FormSet, Form, Question);\r
+    if (!EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  //\r
+  // EFI_IFR_DEFAULT has highest priority\r
+  //\r
+  if (!IsListEmpty (&Question->DefaultListHead)) {\r
+    Link = GetFirstNode (&Question->DefaultListHead);\r
+    while (!IsNull (&Question->DefaultListHead, Link)) {\r
+      Default = QUESTION_DEFAULT_FROM_LINK (Link);\r
+\r
+      if (Default->DefaultId == DefaultId) {\r
+        if (Default->ValueExpression != NULL) {\r
+          //\r
+          // Default is provided by an Expression, evaluate it\r
+          //\r
+          Status = EvaluateExpression (FormSet, Form, Default->ValueExpression);\r
+          if (EFI_ERROR (Status)) {\r
+            return Status;\r
+          }\r
+\r
+          if (Default->ValueExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {\r
+            ASSERT (HiiValue->Type == EFI_IFR_TYPE_BUFFER && Question->BufferValue != NULL);\r
+            if (Question->StorageWidth > Default->ValueExpression->Result.BufferLen) {\r
+              CopyMem (Question->HiiValue.Buffer, Default->ValueExpression->Result.Buffer, Default->ValueExpression->Result.BufferLen);\r
+              Question->HiiValue.BufferLen = Default->ValueExpression->Result.BufferLen;\r
+            } else {\r
+              CopyMem (Question->HiiValue.Buffer, Default->ValueExpression->Result.Buffer, Question->StorageWidth);\r
+              Question->HiiValue.BufferLen = Question->StorageWidth;\r
+            }\r
+\r
+            FreePool (Default->ValueExpression->Result.Buffer);\r
+          }\r
+\r
+          HiiValue->Type = Default->ValueExpression->Result.Type;\r
+          CopyMem (&HiiValue->Value, &Default->ValueExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE));\r
+        } else {\r
+          //\r
+          // Default value is embedded in EFI_IFR_DEFAULT\r
+          //\r
+          if (Default->Value.Type == EFI_IFR_TYPE_BUFFER) {\r
+            ASSERT (HiiValue->Buffer != NULL);\r
+            CopyMem (HiiValue->Buffer, Default->Value.Buffer, Default->Value.BufferLen);\r
+          } else {\r
+            CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));\r
+          }\r
+        }\r
+\r
+        if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
+          StrValue = HiiGetString (FormSet->HiiHandle, HiiValue->Value.string, NULL);\r
+          if (StrValue == NULL) {\r
+            return EFI_NOT_FOUND;\r
+          }\r
+\r
+          if (Question->StorageWidth > StrSize (StrValue)) {\r
+            ZeroMem (Question->BufferValue, Question->StorageWidth);\r
+            CopyMem (Question->BufferValue, StrValue, StrSize (StrValue));\r
+          } else {\r
+            CopyMem (Question->BufferValue, StrValue, Question->StorageWidth);\r
+          }\r
+        }\r
+\r
+        return EFI_SUCCESS;\r
+      }\r
+\r
+      Link = GetNextNode (&Question->DefaultListHead, Link);\r
+    }\r
+  }\r
+\r
+  //\r
+  // EFI_ONE_OF_OPTION\r
+  //\r
+  if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {\r
+    if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
+      //\r
+      // OneOfOption could only provide Standard and Manufacturing default\r
+      //\r
+      Link = GetFirstNode (&Question->OptionListHead);\r
+      while (!IsNull (&Question->OptionListHead, Link)) {\r
+        Option = QUESTION_OPTION_FROM_LINK (Link);\r
+        Link   = GetNextNode (&Question->OptionListHead, Link);\r
+\r
+        if ((Option->SuppressExpression != NULL) &&\r
+            (EvaluateExpressionList (Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse))\r
+        {\r
+          continue;\r
+        }\r
+\r
+        if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||\r
+            ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))\r
+            )\r
+        {\r
+          CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
+\r
+          return EFI_SUCCESS;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // EFI_IFR_CHECKBOX - lowest priority\r
+  //\r
+  if (Question->Operand == EFI_IFR_CHECKBOX_OP) {\r
+    if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
+      //\r
+      // Checkbox could only provide Standard and Manufacturing default\r
+      //\r
+      if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0)) ||\r
+          ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0))\r
+          )\r
+      {\r
+        HiiValue->Value.b = TRUE;\r
+      }\r
+\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  //\r
+  // For question without default value for current default Id, we try to re-get the default value form other default id in the DefaultStoreList.\r
+  // If get, will exit the function, if not, will choose next default id in the DefaultStoreList.\r
+  // The default id in DefaultStoreList are in ascending order to make sure choose the smallest default id every time.\r
+  //\r
+  while (!IsNull (&FormSet->DefaultStoreListHead, DefaultLink)) {\r
+    DefaultStore = FORMSET_DEFAULTSTORE_FROM_LINK (DefaultLink);\r
+    DefaultLink  = GetNextNode (&FormSet->DefaultStoreListHead, DefaultLink);\r
+    DefaultId    = DefaultStore->DefaultId;\r
+    if (DefaultId == OriginalDefaultId) {\r
+      continue;\r
+    }\r
+\r
+    goto ReGetDefault;\r
+  }\r
+\r
+  //\r
+  // For Questions without default value for all the default id in the DefaultStoreList.\r
+  //\r
+  Status = EFI_NOT_FOUND;\r
+  switch (Question->Operand) {\r
+    case EFI_IFR_CHECKBOX_OP:\r
+      HiiValue->Value.b = FALSE;\r
+      Status            = EFI_SUCCESS;\r
+      break;\r
+\r
+    case EFI_IFR_NUMERIC_OP:\r
+      //\r
+      // Take minimum value as numeric default value\r
+      //\r
+      if ((Question->Flags & EFI_IFR_DISPLAY) == 0) {\r
+        //\r
+        // In EFI_IFR_DISPLAY_INT_DEC type, should check value with int* type.\r
+        //\r
+        switch (Question->Flags & EFI_IFR_NUMERIC_SIZE) {\r
+          case EFI_IFR_NUMERIC_SIZE_1:\r
+            if (((INT8)HiiValue->Value.u8 < (INT8)Question->Minimum) || ((INT8)HiiValue->Value.u8 > (INT8)Question->Maximum)) {\r
+              HiiValue->Value.u8 = (UINT8)Question->Minimum;\r
+              Status             = EFI_SUCCESS;\r
+            }\r
+\r
+            break;\r
+          case EFI_IFR_NUMERIC_SIZE_2:\r
+            if (((INT16)HiiValue->Value.u16 < (INT16)Question->Minimum) || ((INT16)HiiValue->Value.u16 > (INT16)Question->Maximum)) {\r
+              HiiValue->Value.u16 = (UINT16)Question->Minimum;\r
+              Status              = EFI_SUCCESS;\r
+            }\r
+\r
+            break;\r
+          case EFI_IFR_NUMERIC_SIZE_4:\r
+            if (((INT32)HiiValue->Value.u32 < (INT32)Question->Minimum) || ((INT32)HiiValue->Value.u32 > (INT32)Question->Maximum)) {\r
+              HiiValue->Value.u32 = (UINT32)Question->Minimum;\r
+              Status              = EFI_SUCCESS;\r
+            }\r
+\r
+            break;\r
+          case EFI_IFR_NUMERIC_SIZE_8:\r
+            if (((INT64)HiiValue->Value.u64 < (INT64)Question->Minimum) || ((INT64)HiiValue->Value.u64 > (INT64)Question->Maximum)) {\r
+              HiiValue->Value.u64 = Question->Minimum;\r
+              Status              = EFI_SUCCESS;\r
+            }\r
+\r
+            break;\r
+          default:\r
+            break;\r
+        }\r
+      } else {\r
+        if ((HiiValue->Value.u64 < Question->Minimum) || (HiiValue->Value.u64 > Question->Maximum)) {\r
+          HiiValue->Value.u64 = Question->Minimum;\r
+          Status              = EFI_SUCCESS;\r
+        }\r
+      }\r
+\r
+      break;\r
+\r
+    case EFI_IFR_ONE_OF_OP:\r
+      //\r
+      // Take first oneof option as oneof's default value\r
+      //\r
+      if (ValueToOption (Question, HiiValue) == NULL) {\r
+        Link = GetFirstNode (&Question->OptionListHead);\r
+        while (!IsNull (&Question->OptionListHead, Link)) {\r
+          Option = QUESTION_OPTION_FROM_LINK (Link);\r
+          Link   = GetNextNode (&Question->OptionListHead, Link);\r
+\r
+          if ((Option->SuppressExpression != NULL) &&\r
+              (EvaluateExpressionList (Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse))\r
+          {\r
+            continue;\r
+          }\r
+\r
+          CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
+          Status = EFI_SUCCESS;\r
+          break;\r
+        }\r
+      }\r
+\r
+      break;\r
+\r
+    case EFI_IFR_ORDERED_LIST_OP:\r
+      //\r
+      // Take option sequence in IFR as ordered list's default value\r
+      //\r
+      Index = 0;\r
+      Link  = GetFirstNode (&Question->OptionListHead);\r
+      while (!IsNull (&Question->OptionListHead, Link)) {\r
+        Status = EFI_SUCCESS;\r
+        Option = QUESTION_OPTION_FROM_LINK (Link);\r
+        Link   = GetNextNode (&Question->OptionListHead, Link);\r
+\r
+        if ((Option->SuppressExpression != NULL) &&\r
+            (EvaluateExpressionList (Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse))\r
+        {\r
+          continue;\r
+        }\r
+\r
+        SetArrayData (Question->BufferValue, Question->ValueType, Index, Option->Value.Value.u64);\r
+\r
+        Index++;\r
+        if (Index >= Question->MaxContainers) {\r
+          break;\r
+        }\r
+      }\r
+\r
+      break;\r
+\r
+    default:\r
+      break;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Get AltCfg string for current form.\r
+\r
+  @param  FormSet                Form data structure.\r
+  @param  Form                   Form data structure.\r
+  @param  DefaultId              The Class of the default.\r
+  @param  BrowserStorage         The input request storage for the questions.\r
+\r
+**/\r
+VOID\r
+ExtractAltCfgForForm (\r
+  IN FORM_BROWSER_FORMSET  *FormSet,\r
+  IN FORM_BROWSER_FORM     *Form,\r
+  IN UINT16                DefaultId,\r
+  IN BROWSER_STORAGE       *BrowserStorage\r
+  )\r
+{\r
+  EFI_STATUS                   Status;\r
+  LIST_ENTRY                   *Link;\r
+  CHAR16                       *ConfigResp;\r
+  CHAR16                       *Progress;\r
+  CHAR16                       *Result;\r
+  BROWSER_STORAGE              *Storage;\r
+  FORM_BROWSER_CONFIG_REQUEST  *ConfigInfo;\r
+  FORMSET_STORAGE              *FormSetStorage;\r
+\r
+  //\r
+  // Check whether has get AltCfg string for this formset.\r
+  // If yes, no need to get AltCfg for form.\r
+  //\r
+  Link = GetFirstNode (&FormSet->StorageListHead);\r
+  while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+    FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
+    Storage        = FormSetStorage->BrowserStorage;\r
+    Link           = GetNextNode (&FormSet->StorageListHead, Link);\r
+    if ((BrowserStorage != NULL) && (BrowserStorage != Storage)) {\r
+      continue;\r
+    }\r
+\r
+    if ((Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE) &&\r
+        (FormSetStorage->ElementCount != 0) &&\r
+        FormSetStorage->HasCallAltCfg)\r
+    {\r
+      return;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Get AltCfg string for each form.\r
+  //\r
+  Link = GetFirstNode (&Form->ConfigRequestHead);\r
+  while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
+    ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
+    Link       = GetNextNode (&Form->ConfigRequestHead, Link);\r
+\r
+    Storage = ConfigInfo->Storage;\r
+    if ((BrowserStorage != NULL) && (BrowserStorage != Storage)) {\r
+      continue;\r
+    }\r
+\r
+    if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // 1. Skip if there is no RequestElement\r
+    //\r
+    if (ConfigInfo->ElementCount == 0) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // 2. Get value through hii config routine protocol.\r
+    //\r
+    Status = mHiiConfigRouting->ExtractConfig (\r
+                                  mHiiConfigRouting,\r
+                                  ConfigInfo->ConfigRequest,\r
+                                  &Progress,\r
+                                  &Result\r
+                                  );\r
+    if (EFI_ERROR (Status)) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)\r
+    //    Get the default configuration string according to the default ID.\r
+    //\r
+    Status = mHiiConfigRouting->GetAltConfig (\r
+                                  mHiiConfigRouting,\r
+                                  Result,\r
+                                  &Storage->Guid,\r
+                                  Storage->Name,\r
+                                  NULL,\r
+                                  &DefaultId,  // it can be NULL to get the current setting.\r
+                                  &ConfigResp\r
+                                  );\r
+    FreePool (Result);\r
+    if (EFI_ERROR (Status)) {\r
+      continue;\r
+    }\r
+\r
+    ConfigInfo->ConfigAltResp = ConfigResp;\r
+  }\r
+}\r
+\r
+/**\r
+  Clean AltCfg string for current form.\r
+\r
+  @param  Form                   Form data structure.\r
+\r
+**/\r
+VOID\r
+CleanAltCfgForForm (\r
+  IN FORM_BROWSER_FORM  *Form\r
+  )\r
+{\r
+  LIST_ENTRY                   *Link;\r
+  FORM_BROWSER_CONFIG_REQUEST  *ConfigInfo;\r
+\r
+  Link = GetFirstNode (&Form->ConfigRequestHead);\r
+  while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
+    ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
+    Link       = GetNextNode (&Form->ConfigRequestHead, Link);\r
+\r
+    if (ConfigInfo->ConfigAltResp != NULL) {\r
+      FreePool (ConfigInfo->ConfigAltResp);\r
+      ConfigInfo->ConfigAltResp = NULL;\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  Get AltCfg string for current formset.\r
+\r
+  @param  FormSet                Form data structure.\r
+  @param  DefaultId              The Class of the default.\r
+  @param  BrowserStorage         The input request storage for the questions.\r
+\r
+**/\r
+VOID\r
+ExtractAltCfgForFormSet (\r
+  IN FORM_BROWSER_FORMSET  *FormSet,\r
+  IN UINT16                DefaultId,\r
+  IN BROWSER_STORAGE       *BrowserStorage\r
+  )\r
+{\r
+  EFI_STATUS       Status;\r
+  LIST_ENTRY       *Link;\r
+  CHAR16           *ConfigResp;\r
+  CHAR16           *Progress;\r
+  CHAR16           *Result;\r
+  BROWSER_STORAGE  *Storage;\r
+  FORMSET_STORAGE  *FormSetStorage;\r
+\r
+  Link = GetFirstNode (&FormSet->StorageListHead);\r
+  while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+    FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
+    Storage        = FormSetStorage->BrowserStorage;\r
+    Link           = GetNextNode (&FormSet->StorageListHead, Link);\r
+\r
+    if ((BrowserStorage != NULL) && (BrowserStorage != Storage)) {\r
+      continue;\r
+    }\r
+\r
+    if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // 1. Skip if there is no RequestElement\r
+    //\r
+    if (FormSetStorage->ElementCount == 0) {\r
+      continue;\r
+    }\r
+\r
+    FormSetStorage->HasCallAltCfg = TRUE;\r
+\r
+    //\r
+    // 2. Get value through hii config routine protocol.\r
+    //\r
+    Status = mHiiConfigRouting->ExtractConfig (\r
+                                  mHiiConfigRouting,\r
+                                  FormSetStorage->ConfigRequest,\r
+                                  &Progress,\r
+                                  &Result\r
+                                  );\r
+    if (EFI_ERROR (Status)) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)\r
+    //    Get the default configuration string according to the default ID.\r
+    //\r
+    Status = mHiiConfigRouting->GetAltConfig (\r
+                                  mHiiConfigRouting,\r
+                                  Result,\r
+                                  &Storage->Guid,\r
+                                  Storage->Name,\r
+                                  NULL,\r
+                                  &DefaultId,  // it can be NULL to get the current setting.\r
+                                  &ConfigResp\r
+                                  );\r
+\r
+    FreePool (Result);\r
+    if (EFI_ERROR (Status)) {\r
+      continue;\r
+    }\r
+\r
+    FormSetStorage->ConfigAltResp = ConfigResp;\r
+  }\r
+}\r
+\r
+/**\r
+  Clean AltCfg string for current formset.\r
+\r
+  @param  FormSet                Form data structure.\r
+\r
+**/\r
+VOID\r
+CleanAltCfgForFormSet (\r
+  IN FORM_BROWSER_FORMSET  *FormSet\r
+  )\r
+{\r
+  LIST_ENTRY       *Link;\r
+  FORMSET_STORAGE  *FormSetStorage;\r
+\r
+  Link = GetFirstNode (&FormSet->StorageListHead);\r
+  while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+    FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
+    Link           = GetNextNode (&FormSet->StorageListHead, Link);\r
+\r
+    if (FormSetStorage->ConfigAltResp != NULL) {\r
+      FreePool (FormSetStorage->ConfigAltResp);\r
+      FormSetStorage->ConfigAltResp = NULL;\r
+    }\r
+\r
+    FormSetStorage->HasCallAltCfg = FALSE;\r
+  }\r
+}\r
+\r
+/**\r
+  Reset Questions to their initial value or default value in a Form, Formset or System.\r
+\r
+  GetDefaultValueScope parameter decides which questions will reset\r
+  to its default value.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   Form data structure.\r
+  @param  DefaultId              The Class of the default.\r
+  @param  SettingScope           Setting Scope for Default action.\r
+  @param  GetDefaultValueScope   Get default value scope.\r
+  @param  Storage                Get default value only for this storage.\r
+  @param  RetrieveValueFirst     Whether call the retrieve call back to\r
+                                 get the initial value before get default\r
+                                 value.\r
+  @param  SkipGetAltCfg          Whether skip the get altcfg string process.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+  @retval EFI_UNSUPPORTED        Unsupport SettingScope.\r
+\r
+**/\r
+EFI_STATUS\r
+ExtractDefault (\r
+  IN FORM_BROWSER_FORMSET       *FormSet,\r
+  IN FORM_BROWSER_FORM          *Form,\r
+  IN UINT16                     DefaultId,\r
+  IN BROWSER_SETTING_SCOPE      SettingScope,\r
+  IN BROWSER_GET_DEFAULT_VALUE  GetDefaultValueScope,\r
+  IN BROWSER_STORAGE            *Storage OPTIONAL,\r
+  IN BOOLEAN                    RetrieveValueFirst,\r
+  IN BOOLEAN                    SkipGetAltCfg\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  LIST_ENTRY              *FormLink;\r
+  LIST_ENTRY              *Link;\r
+  FORM_BROWSER_STATEMENT  *Question;\r
+  FORM_BROWSER_FORMSET    *LocalFormSet;\r
+  FORM_BROWSER_FORMSET    *OldFormSet;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  // Check the supported setting level.\r
+  //\r
+  if ((SettingScope >= MaxLevel) || (GetDefaultValueScope >= GetDefaultForMax)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if ((GetDefaultValueScope == GetDefaultForStorage) && (Storage == NULL)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (SettingScope == FormLevel) {\r
+    //\r
+    // Prepare the AltCfg String for form.\r
+    //\r
+    if (!SkipGetAltCfg && (GetDefaultValueScope != GetDefaultForNoStorage)) {\r
+      ExtractAltCfgForForm (FormSet, Form, DefaultId, Storage);\r
+    }\r
+\r
+    //\r
+    // Extract Form default\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
+      // If get default value only for this storage, check the storage first.\r
+      //\r
+      if ((GetDefaultValueScope == GetDefaultForStorage) && (Question->Storage != Storage)) {\r
+        continue;\r
+      }\r
+\r
+      //\r
+      // If get default value only for no storage question, just skip the question which has storage.\r
+      //\r
+      if ((GetDefaultValueScope == GetDefaultForNoStorage) && (Question->Storage != NULL)) {\r
+        continue;\r
+      }\r
+\r
+      //\r
+      // If Question is disabled, don't reset it to default\r
+      //\r
+      if (Question->Expression != NULL) {\r
+        if (EvaluateExpressionList (Question->Expression, TRUE, FormSet, Form) == ExpressDisable) {\r
+          continue;\r
+        }\r
+      }\r
+\r
+      if (RetrieveValueFirst) {\r
+        //\r
+        // Call the Retrieve call back to get the initial question value.\r
+        //\r
+        Status = ProcessRetrieveForQuestion (FormSet->ConfigAccess, Question, FormSet);\r
+      }\r
+\r
+      //\r
+      // If not request to get the initial value or get initial value fail, then get default value.\r
+      //\r
+      if (!RetrieveValueFirst || EFI_ERROR (Status)) {\r
+        Status = GetQuestionDefault (FormSet, Form, Question, DefaultId);\r
+        if (EFI_ERROR (Status)) {\r
+          continue;\r
+        }\r
+      }\r
+\r
+      //\r
+      // Synchronize Buffer storage's Edit buffer\r
+      //\r
+      if ((Question->Storage != NULL) &&\r
+          (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE))\r
+      {\r
+        SetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
+      }\r
+    }\r
+\r
+    //\r
+    // Clean the AltCfg String.\r
+    //\r
+    if (!SkipGetAltCfg && (GetDefaultValueScope != GetDefaultForNoStorage)) {\r
+      CleanAltCfgForForm (Form);\r
+    }\r
+  } else if (SettingScope == FormSetLevel) {\r
+    //\r
+    // Prepare the AltCfg String for formset.\r
+    //\r
+    if (!SkipGetAltCfg && (GetDefaultValueScope != GetDefaultForNoStorage)) {\r
+      ExtractAltCfgForFormSet (FormSet, DefaultId, Storage);\r
+    }\r
+\r
+    FormLink = GetFirstNode (&FormSet->FormListHead);\r
+    while (!IsNull (&FormSet->FormListHead, FormLink)) {\r
+      Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);\r
+      ExtractDefault (FormSet, Form, DefaultId, FormLevel, GetDefaultValueScope, Storage, RetrieveValueFirst, SkipGetAltCfg);\r
+      FormLink = GetNextNode (&FormSet->FormListHead, FormLink);\r
+    }\r
+\r
+    //\r
+    // Clean the AltCfg String.\r
+    //\r
+    if (!SkipGetAltCfg && (GetDefaultValueScope != GetDefaultForNoStorage)) {\r
+      CleanAltCfgForFormSet (FormSet);\r
+    }\r
+  } else if (SettingScope == SystemLevel) {\r
+    //\r
+    // Preload all Hii formset.\r
+    //\r
+    LoadAllHiiFormset ();\r
+\r
+    OldFormSet = mSystemLevelFormSet;\r
+\r
+    //\r
+    // Set Default Value for each FormSet in the maintain list.\r
+    //\r
+    Link = GetFirstNode (&gBrowserFormSetList);\r
+    while (!IsNull (&gBrowserFormSetList, Link)) {\r
+      LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
+      Link         = GetNextNode (&gBrowserFormSetList, Link);\r
+      if (!ValidateFormSet (LocalFormSet)) {\r
+        continue;\r
+      }\r
+\r
+      mSystemLevelFormSet = LocalFormSet;\r
+\r
+      ExtractDefault (LocalFormSet, NULL, DefaultId, FormSetLevel, GetDefaultValueScope, Storage, RetrieveValueFirst, SkipGetAltCfg);\r
+    }\r
+\r
+    mSystemLevelFormSet = OldFormSet;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Validate whether this question's value has changed.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   Form data structure.\r
+  @param  Question               Question to be initialized.\r
+  @param  GetValueFrom           Where to get value, may from editbuffer, buffer or hii driver.\r
+\r
+  @retval TRUE                   Question's value has changed.\r
+  @retval FALSE                  Question's value has not changed\r
+\r
+**/\r
+BOOLEAN\r
+IsQuestionValueChanged (\r
+  IN FORM_BROWSER_FORMSET         *FormSet,\r
+  IN FORM_BROWSER_FORM            *Form,\r
+  IN OUT FORM_BROWSER_STATEMENT   *Question,\r
+  IN GET_SET_QUESTION_VALUE_WITH  GetValueFrom\r
+  )\r
+{\r
+  EFI_HII_VALUE  BackUpValue;\r
+  CHAR8          *BackUpBuffer;\r
+  EFI_HII_VALUE  BackUpValue2;\r
+  CHAR8          *BackUpBuffer2;\r
+  EFI_STATUS     Status;\r
+  BOOLEAN        ValueChanged;\r
+  UINTN          BufferWidth;\r
+\r
+  //\r
+  // For quetion without storage, always mark it as data not changed.\r
+  //\r
+  if ((Question->Storage == NULL) && (Question->Operand != EFI_IFR_TIME_OP) && (Question->Operand != EFI_IFR_DATE_OP)) {\r
+    return FALSE;\r
+  }\r
+\r
+  BackUpBuffer  = NULL;\r
+  BackUpBuffer2 = NULL;\r
+  ValueChanged  = FALSE;\r
+\r
+  switch (Question->Operand) {\r
+    case EFI_IFR_ORDERED_LIST_OP:\r
+      BufferWidth  = Question->StorageWidth;\r
+      BackUpBuffer = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
+      ASSERT (BackUpBuffer != NULL);\r
+      break;\r
+\r
+    case EFI_IFR_STRING_OP:\r
+    case EFI_IFR_PASSWORD_OP:\r
+      BufferWidth  = (UINTN)Question->Maximum * sizeof (CHAR16);\r
+      BackUpBuffer = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
+      ASSERT (BackUpBuffer != NULL);\r
+      break;\r
+\r
+    default:\r
+      BufferWidth = 0;\r
+      break;\r
+  }\r
+\r
+  CopyMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE));\r
+\r
+  if (GetValueFrom == GetSetValueWithBothBuffer) {\r
+    Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    switch (Question->Operand) {\r
+      case EFI_IFR_ORDERED_LIST_OP:\r
+        BufferWidth   = Question->StorageWidth;\r
+        BackUpBuffer2 = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
+        ASSERT (BackUpBuffer2 != NULL);\r
+        break;\r
+\r
+      case EFI_IFR_STRING_OP:\r
+      case EFI_IFR_PASSWORD_OP:\r
+        BufferWidth   = (UINTN)Question->Maximum * sizeof (CHAR16);\r
+        BackUpBuffer2 = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
+        ASSERT (BackUpBuffer2 != NULL);\r
+        break;\r
+\r
+      default:\r
+        BufferWidth = 0;\r
+        break;\r
+    }\r
+\r
+    CopyMem (&BackUpValue2, &Question->HiiValue, sizeof (EFI_HII_VALUE));\r
+\r
+    Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    if ((CompareMem (&BackUpValue2, &Question->HiiValue, sizeof (EFI_HII_VALUE)) != 0) ||\r
+        (CompareMem (BackUpBuffer2, Question->BufferValue, BufferWidth) != 0))\r
+    {\r
+      ValueChanged = TRUE;\r
+    }\r
+  } else {\r
+    Status = GetQuestionValue (FormSet, Form, Question, GetValueFrom);\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    if ((CompareMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE)) != 0) ||\r
+        (CompareMem (BackUpBuffer, Question->BufferValue, BufferWidth) != 0))\r
+    {\r
+      ValueChanged = TRUE;\r
+    }\r
+  }\r
+\r
+  CopyMem (&Question->HiiValue, &BackUpValue, sizeof (EFI_HII_VALUE));\r
+  if (BackUpBuffer != NULL) {\r
+    CopyMem (Question->BufferValue, BackUpBuffer, BufferWidth);\r
+    FreePool (BackUpBuffer);\r
+  }\r
+\r
+  if (BackUpBuffer2 != NULL) {\r
+    FreePool (BackUpBuffer2);\r
+  }\r
+\r
+  Question->ValueChanged = ValueChanged;\r
+\r
+  return ValueChanged;\r
+}\r
+\r
+/**\r
+  Initialize Question's Edit copy from Storage.\r
+\r
+  @param  Selection              Selection contains the information about\r
+                                 the Selection, form and formset to be displayed.\r
+                                 Selection action may be updated in retrieve callback.\r
+                                 If Selection is NULL, only initialize Question value.\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   Form data structure.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+LoadFormConfig (\r
+  IN OUT UI_MENU_SELECTION  *Selection,\r
+  IN FORM_BROWSER_FORMSET   *FormSet,\r
+  IN FORM_BROWSER_FORM      *Form\r
+  )\r
+{\r
+  EFI_STATUS              Status;\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
+\r
+    //\r
+    // Initialize local copy of Value for each Question\r
+    //\r
+    if ((Question->Operand == EFI_IFR_PASSWORD_OP) && ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == 0)) {\r
+      Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithHiiDriver);\r
+    } else {\r
+      Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
+    }\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    if ((Question->Operand == EFI_IFR_STRING_OP) || (Question->Operand == EFI_IFR_PASSWORD_OP)) {\r
+      HiiSetString (FormSet->HiiHandle, Question->HiiValue.Value.string, (CHAR16 *)Question->BufferValue, NULL);\r
+    }\r
+\r
+    Link = GetNextNode (&Form->StatementListHead, Link);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Initialize Question's Edit copy from Storage for the whole Formset.\r
+\r
+  @param  Selection              Selection contains the information about\r
+                                 the Selection, form and formset to be displayed.\r
+                                 Selection action may be updated in retrieve callback.\r
+                                 If Selection is NULL, only initialize Question value.\r
+  @param  FormSet                FormSet data structure.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+LoadFormSetConfig (\r
+  IN OUT UI_MENU_SELECTION     *Selection,\r
+  IN     FORM_BROWSER_FORMSET  *FormSet\r
+  )\r
+{\r
+  EFI_STATUS         Status;\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
+\r
+    //\r
+    // Initialize local copy of Value for each Form\r
+    //\r
+    Status = LoadFormConfig (Selection, FormSet, Form);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    Link = GetNextNode (&FormSet->FormListHead, Link);\r
+  }\r
+\r
+  //\r
+  // Finished question initialization.\r
+  //\r
+  FormSet->QuestionInited = TRUE;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Remove the Request element from the Config Request.\r
+\r
+  @param  Storage                Pointer to the browser storage.\r
+  @param  RequestElement         The pointer to the Request element.\r
+\r
+**/\r
+VOID\r
+RemoveElement (\r
+  IN OUT BROWSER_STORAGE  *Storage,\r
+  IN     CHAR16           *RequestElement\r
+  )\r
+{\r
+  CHAR16  *NewStr;\r
+  CHAR16  *DestStr;\r
+\r
+  ASSERT (Storage->ConfigRequest != NULL && RequestElement != NULL);\r
+\r
+  NewStr = StrStr (Storage->ConfigRequest, RequestElement);\r
+\r
+  if (NewStr == NULL) {\r
+    return;\r
+  }\r
+\r
+  //\r
+  // Remove this element from this ConfigRequest.\r
+  //\r
+  DestStr = NewStr;\r
+  NewStr += StrLen (RequestElement);\r
+  CopyMem (DestStr, NewStr, StrSize (NewStr));\r
+\r
+  Storage->SpareStrLen += StrLen (RequestElement);\r
+}\r
+\r
+/**\r
+  Adjust config request in storage, remove the request elements existed in the input ConfigRequest.\r
+\r
+  @param  Storage                Pointer to the formset storage.\r
+  @param  ConfigRequest          The pointer to the Request element.\r
+\r
+**/\r
+VOID\r
+RemoveConfigRequest (\r
+  FORMSET_STORAGE  *Storage,\r
+  CHAR16           *ConfigRequest\r
+  )\r
+{\r
+  CHAR16  *RequestElement;\r
+  CHAR16  *NextRequestElement;\r
+  CHAR16  *SearchKey;\r
+\r
+  //\r
+  // No request element in it, just return.\r
+  //\r
+  if (ConfigRequest == NULL) {\r
+    return;\r
+  }\r
+\r
+  if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+    //\r
+    // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage\r
+    //\r
+    SearchKey = L"&";\r
+  } else {\r
+    //\r
+    // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage\r
+    //\r
+    SearchKey = L"&OFFSET";\r
+  }\r
+\r
+  //\r
+  // Find SearchKey storage\r
+  //\r
+  if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+    RequestElement = StrStr (ConfigRequest, L"PATH");\r
+    ASSERT (RequestElement != NULL);\r
+    RequestElement = StrStr (RequestElement, SearchKey);\r
+  } else {\r
+    RequestElement = StrStr (ConfigRequest, SearchKey);\r
+  }\r
+\r
+  while (RequestElement != NULL) {\r
+    //\r
+    // +1 to avoid find header itself.\r
+    //\r
+    NextRequestElement = StrStr (RequestElement + 1, SearchKey);\r
+\r
+    //\r
+    // The last Request element in configRequest string.\r
+    //\r
+    if (NextRequestElement != NULL) {\r
+      //\r
+      // Replace "&" with '\0'.\r
+      //\r
+      *NextRequestElement = L'\0';\r
+    }\r
+\r
+    RemoveElement (Storage->BrowserStorage, RequestElement);\r
+\r
+    if (NextRequestElement != NULL) {\r
+      //\r
+      // Restore '&' with '\0' for later used.\r
+      //\r
+      *NextRequestElement = L'&';\r
+    }\r
+\r
+    RequestElement = NextRequestElement;\r
+  }\r
+\r
+  //\r
+  // If no request element remain, just remove the ConfigRequest string.\r
+  //\r
+  if (StrCmp (Storage->BrowserStorage->ConfigRequest, Storage->ConfigHdr) == 0) {\r
+    FreePool (Storage->BrowserStorage->ConfigRequest);\r
+    Storage->BrowserStorage->ConfigRequest = NULL;\r
+    Storage->BrowserStorage->SpareStrLen   = 0;\r
+  }\r
+}\r
+\r
+/**\r
+  Base on the current formset info, clean the ConfigRequest string in browser storage.\r
+\r
+  @param  FormSet                Pointer of the FormSet\r
+\r
+**/\r
+VOID\r
+CleanBrowserStorage (\r
+  IN OUT FORM_BROWSER_FORMSET  *FormSet\r
+  )\r
+{\r
+  LIST_ENTRY       *Link;\r
+  FORMSET_STORAGE  *Storage;\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
+    if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
+      if ((Storage->ConfigRequest == NULL) || (Storage->BrowserStorage->ConfigRequest == NULL)) {\r
+        continue;\r
+      }\r
+\r
+      RemoveConfigRequest (Storage, Storage->ConfigRequest);\r
+    } else if ((Storage->BrowserStorage->Type == EFI_HII_VARSTORE_BUFFER) ||\r
+               (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_NAME_VALUE))\r
+    {\r
+      if (Storage->BrowserStorage->ConfigRequest != NULL) {\r
+        FreePool (Storage->BrowserStorage->ConfigRequest);\r
+        Storage->BrowserStorage->ConfigRequest = NULL;\r
+      }\r
+\r
+      Storage->BrowserStorage->Initialized = FALSE;\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  Check whether current element in the ConfigReqeust string.\r
+\r
+  @param  BrowserStorage                Storage which includes ConfigReqeust.\r
+  @param  RequestElement                New element need to check.\r
+\r
+  @retval TRUE        The Element is in the ConfigReqeust string.\r
+  @retval FALSE       The Element not in the configReqeust String.\r
+\r
+**/\r
+BOOLEAN\r
+ElementValidation (\r
+  BROWSER_STORAGE  *BrowserStorage,\r
+  CHAR16           *RequestElement\r
+  )\r
+{\r
+  return StrStr (BrowserStorage->ConfigRequest, RequestElement) != NULL ? TRUE : FALSE;\r
+}\r
+\r
+/**\r
+  Append the Request element to the Config Request.\r
+\r
+  @param  ConfigRequest          Current ConfigRequest info.\r
+  @param  SpareStrLen            Current remain free buffer for config reqeust.\r
+  @param  RequestElement         New Request element.\r
+\r
+**/\r
+VOID\r
+AppendConfigRequest (\r
+  IN OUT CHAR16  **ConfigRequest,\r
+  IN OUT UINTN   *SpareStrLen,\r
+  IN     CHAR16  *RequestElement\r
+  )\r
+{\r
+  CHAR16  *NewStr;\r
+  UINTN   StringSize;\r
+  UINTN   StrLength;\r
+  UINTN   MaxLen;\r
+\r
+  StrLength  = StrLen (RequestElement);\r
+  StringSize = (*ConfigRequest != NULL) ? StrSize (*ConfigRequest) : sizeof (CHAR16);\r
+  MaxLen     = StringSize / sizeof (CHAR16) + *SpareStrLen;\r
+\r
+  //\r
+  // Append <RequestElement> to <ConfigRequest>\r
+  //\r
+  if (StrLength > *SpareStrLen) {\r
+    //\r
+    // Old String buffer is not sufficient for RequestElement, allocate a new one\r
+    //\r
+    MaxLen = StringSize / sizeof (CHAR16) + CONFIG_REQUEST_STRING_INCREMENTAL;\r
+    NewStr = AllocateZeroPool (MaxLen * sizeof (CHAR16));\r
+    ASSERT (NewStr != NULL);\r
+\r
+    if (*ConfigRequest != NULL) {\r
+      CopyMem (NewStr, *ConfigRequest, StringSize);\r
+      FreePool (*ConfigRequest);\r
+    }\r
+\r
+    *ConfigRequest = NewStr;\r
+    *SpareStrLen   = CONFIG_REQUEST_STRING_INCREMENTAL;\r
+  }\r
+\r
+  StrCatS (*ConfigRequest, MaxLen, RequestElement);\r
+  *SpareStrLen -= StrLength;\r
+}\r
+\r
+/**\r
+  Adjust the config request info, remove the request elements which already in AllConfigRequest string.\r
+\r
+  @param  Storage                Form set Storage.\r
+  @param  Request                The input request string.\r
+  @param  RespString             Whether the input is ConfigRequest or ConfigResp format.\r
+\r
+  @retval TRUE                   Has element not covered by current used elements, need to continue to call ExtractConfig\r
+  @retval FALSE                  All elements covered by current used elements.\r
+\r
+**/\r
+BOOLEAN\r
+ConfigRequestAdjust (\r
+  IN  BROWSER_STORAGE  *Storage,\r
+  IN  CHAR16           *Request,\r
+  IN  BOOLEAN          RespString\r
+  )\r
+{\r
+  CHAR16   *RequestElement;\r
+  CHAR16   *NextRequestElement;\r
+  CHAR16   *NextElementBakup;\r
+  CHAR16   *SearchKey;\r
+  CHAR16   *ValueKey;\r
+  BOOLEAN  RetVal;\r
+  CHAR16   *ConfigRequest;\r
+\r
+  RetVal           = FALSE;\r
+  NextElementBakup = NULL;\r
+  ValueKey         = NULL;\r
+\r
+  if (Request != NULL) {\r
+    ConfigRequest = Request;\r
+  } else {\r
+    ConfigRequest = Storage->ConfigRequest;\r
+  }\r
+\r
+  if (Storage->ConfigRequest == NULL) {\r
+    Storage->ConfigRequest = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);\r
+    return TRUE;\r
+  }\r
+\r
+  if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+    //\r
+    // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage\r
+    //\r
+    SearchKey = L"&";\r
+  } else {\r
+    //\r
+    // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage\r
+    //\r
+    SearchKey = L"&OFFSET";\r
+    ValueKey  = L"&VALUE";\r
+  }\r
+\r
+  //\r
+  // Find SearchKey storage\r
+  //\r
+  if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+    RequestElement = StrStr (ConfigRequest, L"PATH");\r
+    ASSERT (RequestElement != NULL);\r
+    RequestElement = StrStr (RequestElement, SearchKey);\r
+  } else {\r
+    RequestElement = StrStr (ConfigRequest, SearchKey);\r
+  }\r
+\r
+  while (RequestElement != NULL) {\r
+    //\r
+    // +1 to avoid find header itself.\r
+    //\r
+    NextRequestElement = StrStr (RequestElement + 1, SearchKey);\r
+\r
+    //\r
+    // The last Request element in configRequest string.\r
+    //\r
+    if (NextRequestElement != NULL) {\r
+      if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
+        NextElementBakup   = NextRequestElement;\r
+        NextRequestElement = StrStr (RequestElement, ValueKey);\r
+        ASSERT (NextRequestElement != NULL);\r
+      }\r
+\r
+      //\r
+      // Replace "&" with '\0'.\r
+      //\r
+      *NextRequestElement = L'\0';\r
+    } else {\r
+      if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
+        NextElementBakup   = NextRequestElement;\r
+        NextRequestElement = StrStr (RequestElement, ValueKey);\r
+        ASSERT (NextRequestElement != NULL);\r
+        //\r
+        // Replace "&" with '\0'.\r
+        //\r
+        *NextRequestElement = L'\0';\r
+      }\r
+    }\r
+\r
+    if (!ElementValidation (Storage, RequestElement)) {\r
+      //\r
+      // Add this element to the Storage->BrowserStorage->AllRequestElement.\r
+      //\r
+      AppendConfigRequest (&Storage->ConfigRequest, &Storage->SpareStrLen, RequestElement);\r
+      RetVal = TRUE;\r
+    }\r
+\r
+    if (NextRequestElement != NULL) {\r
+      //\r
+      // Restore '&' with '\0' for later used.\r
+      //\r
+      *NextRequestElement = L'&';\r
+    }\r
+\r
+    if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
+      RequestElement = NextElementBakup;\r
+    } else {\r
+      RequestElement = NextRequestElement;\r
+    }\r
+  }\r
+\r
+  return RetVal;\r
+}\r
+\r
+/**\r
+  Fill storage's edit copy with settings requested from Configuration Driver.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Storage                Buffer Storage.\r
+\r
+**/\r
+VOID\r
+LoadStorage (\r
+  IN FORM_BROWSER_FORMSET  *FormSet,\r
+  IN FORMSET_STORAGE       *Storage\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  EFI_STRING  Progress;\r
+  EFI_STRING  Result;\r
+  CHAR16      *StrPtr;\r
+  EFI_STRING  ConfigRequest;\r
+  UINTN       StrLen;\r
+\r
+  ConfigRequest = NULL;\r
+\r
+  switch (Storage->BrowserStorage->Type) {\r
+    case EFI_HII_VARSTORE_EFI_VARIABLE:\r
+      return;\r
+\r
+    case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
+      if (Storage->BrowserStorage->ConfigRequest != NULL) {\r
+        ConfigRequestAdjust (Storage->BrowserStorage, Storage->ConfigRequest, FALSE);\r
+        return;\r
+      }\r
+\r
+      break;\r
+\r
+    case EFI_HII_VARSTORE_BUFFER:\r
+    case EFI_HII_VARSTORE_NAME_VALUE:\r
+      //\r
+      // Skip if there is no RequestElement.\r
+      //\r
+      if (Storage->ElementCount == 0) {\r
+        return;\r
+      }\r
+\r
+      //\r
+      // Just update the ConfigRequest, if storage already initialized.\r
+      //\r
+      if (Storage->BrowserStorage->Initialized) {\r
+        ConfigRequestAdjust (Storage->BrowserStorage, Storage->ConfigRequest, FALSE);\r
+        return;\r
+      }\r
+\r
+      Storage->BrowserStorage->Initialized = TRUE;\r
+      break;\r
+\r
+    default:\r
+      return;\r
+  }\r
+\r
+  if (Storage->BrowserStorage->Type != EFI_HII_VARSTORE_NAME_VALUE) {\r
+    //\r
+    // Create the config request string to get all fields for this storage.\r
+    // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
+    // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator\r
+    //\r
+    StrLen        = StrSize (Storage->ConfigHdr) + 20 * sizeof (CHAR16);\r
+    ConfigRequest = AllocateZeroPool (StrLen);\r
+    ASSERT (ConfigRequest != NULL);\r
+    UnicodeSPrint (\r
+      ConfigRequest,\r
+      StrLen,\r
+      L"%s&OFFSET=0&WIDTH=%04x",\r
+      Storage->ConfigHdr,\r
+      Storage->BrowserStorage->Size\r
+      );\r
+  } else {\r
+    ConfigRequest = Storage->ConfigRequest;\r
+  }\r
+\r
+  //\r
+  // Request current settings from Configuration Driver\r
+  //\r
+  Status = mHiiConfigRouting->ExtractConfig (\r
+                                mHiiConfigRouting,\r
+                                ConfigRequest,\r
+                                &Progress,\r
+                                &Result\r
+                                );\r
+\r
+  //\r
+  // If get value fail, extract default from IFR binary\r
+  //\r
+  if (EFI_ERROR (Status)) {\r
+    ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForStorage, Storage->BrowserStorage, TRUE, TRUE);\r
+  } else {\r
+    //\r
+    // Convert Result from <ConfigAltResp> to <ConfigResp>\r
+    //\r
+    StrPtr = StrStr (Result, L"&GUID=");\r
+    if (StrPtr != NULL) {\r
+      *StrPtr = L'\0';\r
+    }\r
+\r
+    Status = ConfigRespToStorage (Storage->BrowserStorage, Result);\r
+    FreePool (Result);\r
+  }\r
+\r
+  Storage->BrowserStorage->ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigRequest), Storage->ConfigRequest);\r
+\r
+  //\r
+  // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer.\r
+  //\r
+  SynchronizeStorage (Storage->BrowserStorage, NULL, TRUE);\r
+\r
+  if (Storage->BrowserStorage->Type != EFI_HII_VARSTORE_NAME_VALUE) {\r
+    if (ConfigRequest != NULL) {\r
+      FreePool (ConfigRequest);\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  Get Value changed status from old question.\r
+\r
+  @param  NewFormSet                FormSet data structure.\r
+  @param  OldQuestion               Old question which has value changed.\r
+\r
+**/\r
+VOID\r
+SyncStatusForQuestion (\r
+  IN OUT FORM_BROWSER_FORMSET    *NewFormSet,\r
+  IN     FORM_BROWSER_STATEMENT  *OldQuestion\r
+  )\r
+{\r
+  LIST_ENTRY              *Link;\r
+  LIST_ENTRY              *QuestionLink;\r
+  FORM_BROWSER_FORM       *Form;\r
+  FORM_BROWSER_STATEMENT  *Question;\r
+\r
+  //\r
+  // For each form in one formset.\r
+  //\r
+  Link = GetFirstNode (&NewFormSet->FormListHead);\r
+  while (!IsNull (&NewFormSet->FormListHead, Link)) {\r
+    Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+    Link = GetNextNode (&NewFormSet->FormListHead, Link);\r
+\r
+    //\r
+    // for each question in one form.\r
+    //\r
+    QuestionLink = GetFirstNode (&Form->StatementListHead);\r
+    while (!IsNull (&Form->StatementListHead, QuestionLink)) {\r
+      Question     = FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink);\r
+      QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);\r
+\r
+      if (Question->QuestionId == OldQuestion->QuestionId) {\r
+        Question->ValueChanged = TRUE;\r
+        return;\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  Get Value changed status from old formset.\r
+\r
+  @param  NewFormSet                FormSet data structure.\r
+  @param  OldFormSet                FormSet data structure.\r
+\r
+**/\r
+VOID\r
+SyncStatusForFormSet (\r
+  IN OUT FORM_BROWSER_FORMSET  *NewFormSet,\r
+  IN     FORM_BROWSER_FORMSET  *OldFormSet\r
+  )\r
+{\r
+  LIST_ENTRY              *Link;\r
+  LIST_ENTRY              *QuestionLink;\r
+  FORM_BROWSER_FORM       *Form;\r
+  FORM_BROWSER_STATEMENT  *Question;\r
+\r
+  //\r
+  // For each form in one formset.\r
+  //\r
+  Link = GetFirstNode (&OldFormSet->FormListHead);\r
+  while (!IsNull (&OldFormSet->FormListHead, Link)) {\r
+    Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+    Link = GetNextNode (&OldFormSet->FormListHead, Link);\r
+\r
+    //\r
+    // for each question in one form.\r
+    //\r
+    QuestionLink = GetFirstNode (&Form->StatementListHead);\r
+    while (!IsNull (&Form->StatementListHead, QuestionLink)) {\r
+      Question     = FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink);\r
+      QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);\r
+\r
+      if (!Question->ValueChanged) {\r
+        continue;\r
+      }\r
+\r
+      //\r
+      // Find the same question in new formset and update the value changed flag.\r
+      //\r
+      SyncStatusForQuestion (NewFormSet, Question);\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  Get current setting of Questions.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+\r
+**/\r
+VOID\r
+InitializeCurrentSetting (\r
+  IN OUT FORM_BROWSER_FORMSET  *FormSet\r
+  )\r
+{\r
+  LIST_ENTRY            *Link;\r
+  FORMSET_STORAGE       *Storage;\r
+  FORM_BROWSER_FORMSET  *OldFormSet;\r
+\r
+  //\r
+  // Try to find pre FormSet in the maintain backup list.\r
+  // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.\r
+  //\r
+  OldFormSet = GetFormSetFromHiiHandle (FormSet->HiiHandle);\r
+  if (OldFormSet != NULL) {\r
+    SyncStatusForFormSet (FormSet, OldFormSet);\r
+    RemoveEntryList (&OldFormSet->Link);\r
+    DestroyFormSet (OldFormSet);\r
+  }\r
+\r
+  InsertTailList (&gBrowserFormSetList, &FormSet->Link);\r
+\r
+  //\r
+  // Extract default from IFR binary for no storage questions.\r
+  //\r
+  ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForNoStorage, NULL, TRUE, FALSE);\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
+\r
+    LoadStorage (FormSet, Storage);\r
+\r
+    Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+  }\r
+}\r
+\r
+/**\r
+  Fetch the Ifr binary data of a FormSet.\r
+\r
+  @param  Handle                 PackageList Handle\r
+  @param  FormSetGuid            On input, GUID or class GUID of a formset. If not\r
+                                 specified (NULL or zero GUID), take the first\r
+                                 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
+                                 found in package list.\r
+                                 On output, GUID of the formset found(if not NULL).\r
+  @param  BinaryLength           The length of the FormSet IFR binary.\r
+  @param  BinaryData             The buffer designed to receive the FormSet.\r
+\r
+  @retval EFI_SUCCESS            Buffer filled with the requested FormSet.\r
+                                 BufferLength was updated.\r
+  @retval EFI_INVALID_PARAMETER  The handle is unknown.\r
+  @retval EFI_NOT_FOUND          A form or FormSet on the requested handle cannot\r
+                                 be found with the requested FormId.\r
+\r
+**/\r
+EFI_STATUS\r
+GetIfrBinaryData (\r
+  IN  EFI_HII_HANDLE  Handle,\r
+  IN OUT EFI_GUID     *FormSetGuid,\r
+  OUT UINTN           *BinaryLength,\r
+  OUT UINT8           **BinaryData\r
+  )\r
+{\r
+  EFI_STATUS                   Status;\r
+  EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;\r
+  UINTN                        BufferSize;\r
+  UINT8                        *Package;\r
+  UINT8                        *OpCodeData;\r
+  UINT32                       Offset;\r
+  UINT32                       Offset2;\r
+  UINT32                       PackageListLength;\r
+  EFI_HII_PACKAGE_HEADER       PackageHeader;\r
+  UINT8                        Index;\r
+  UINT8                        NumberOfClassGuid;\r
+  BOOLEAN                      ClassGuidMatch;\r
+  EFI_GUID                     *ClassGuid;\r
+  EFI_GUID                     *ComparingGuid;\r
+\r
+  OpCodeData = NULL;\r
+  Package    = NULL;\r
+  ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
+\r
+  //\r
+  // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list\r
+  //\r
+  if (FormSetGuid == NULL) {\r
+    ComparingGuid = &gZeroGuid;\r
+  } else {\r
+    ComparingGuid = FormSetGuid;\r
+  }\r
+\r
+  //\r
+  // Get HII PackageList\r
+  //\r
+  BufferSize     = 0;\r
+  HiiPackageList = NULL;\r
+  Status         = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    HiiPackageList = AllocatePool (BufferSize);\r
+    ASSERT (HiiPackageList != NULL);\r
+\r
+    Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  ASSERT (HiiPackageList != NULL);\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
+  ClassGuidMatch = FALSE;\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 (IsZeroGuid (ComparingGuid) ||\r
+              CompareGuid (ComparingGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER))))\r
+          {\r
+            break;\r
+          }\r
+\r
+          if (((EFI_IFR_OP_HEADER *)OpCodeData)->Length > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) {\r
+            //\r
+            // Try to compare against formset class GUID\r
+            //\r
+            NumberOfClassGuid = (UINT8)(((EFI_IFR_FORM_SET *)OpCodeData)->Flags & 0x3);\r
+            ClassGuid         = (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_FORM_SET));\r
+            for (Index = 0; Index < NumberOfClassGuid; Index++) {\r
+              if (CompareGuid (ComparingGuid, ClassGuid + Index)) {\r
+                ClassGuidMatch = TRUE;\r
+                break;\r
+              }\r
+            }\r
+\r
+            if (ClassGuidMatch) {\r
+              break;\r
+            }\r
+          } else if (ComparingGuid == &gEfiHiiPlatformSetupFormsetGuid) {\r
+            ClassGuidMatch = TRUE;\r
+            break;\r
+          }\r
+        }\r
+\r
+        Offset2 += ((EFI_IFR_OP_HEADER *)OpCodeData)->Length;\r
+      }\r
+\r
+      if (Offset2 < PackageHeader.Length) {\r
+        //\r
+        // Target formset found\r
+        //\r
+        break;\r
+      }\r
+    }\r
+\r
+    Offset += PackageHeader.Length;\r
+  }\r
+\r
+  if (Offset >= PackageListLength) {\r
+    //\r
+    // Form package not found in this Package List\r
+    //\r
+    FreePool (HiiPackageList);\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  if (FormSetGuid != NULL) {\r
+    //\r
+    // Return the FormSet GUID\r
+    //\r
+    CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *)OpCodeData)->Guid, sizeof (EFI_GUID));\r
+  }\r
+\r
+  //\r
+  // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes\r
+  // in this FormSet; So, here just simply copy the data from start of a FormSet to the end\r
+  // of the Form Package.\r
+  //\r
+  *BinaryLength = PackageHeader.Length - Offset2;\r
+  *BinaryData   = AllocateCopyPool (*BinaryLength, OpCodeData);\r
+\r
+  FreePool (HiiPackageList);\r
+\r
+  if (*BinaryData == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Initialize the internal data structure of a FormSet.\r
+\r
+  @param  Handle                 PackageList Handle\r
+  @param  FormSetGuid            On input, GUID or class GUID of a formset. If not\r
+                                 specified (NULL or zero GUID), take the first\r
+                                 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
+                                 found in package list.\r
+                                 On output, GUID of the formset found(if not NULL).\r
+  @param  FormSet                FormSet data structure.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+  @retval EFI_NOT_FOUND          The specified FormSet could not be found.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeFormSet (\r
+  IN  EFI_HII_HANDLE        Handle,\r
+  IN OUT EFI_GUID           *FormSetGuid,\r
+  OUT FORM_BROWSER_FORMSET  *FormSet\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  EFI_HANDLE  DriverHandle;\r
+\r
+  Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  FormSet->Signature = FORM_BROWSER_FORMSET_SIGNATURE;\r
+  FormSet->HiiHandle = Handle;\r
+  CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));\r
+  FormSet->QuestionInited = FALSE;\r
+\r
+  //\r
+  // Retrieve ConfigAccess Protocol associated with this HiiPackageList\r
+  //\r
+  Status = mHiiDatabase->GetPackageListHandle (mHiiDatabase, Handle, &DriverHandle);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  FormSet->DriverHandle = DriverHandle;\r
+  Status                = gBS->HandleProtocol (\r
+                                 DriverHandle,\r
+                                 &gEfiHiiConfigAccessProtocolGuid,\r
+                                 (VOID **)&FormSet->ConfigAccess\r
+                                 );\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // Configuration Driver don't attach ConfigAccess protocol to its HII package\r
+    // list, then there will be no configuration action required\r
+    //\r
+    FormSet->ConfigAccess = NULL;\r
+  }\r
+\r
+  //\r
+  // Parse the IFR binary OpCodes\r
+  //\r
+  Status = ParseOpCodes (FormSet);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Save globals used by previous call to SendForm(). SendForm() may be called from\r
+  HiiConfigAccess.Callback(), this will cause SendForm() be reentried.\r
+  So, save globals of previous call to SendForm() and restore them upon exit.\r
+\r
+**/\r
+VOID\r
+SaveBrowserContext (\r
+  VOID\r
+  )\r
+{\r
+  BROWSER_CONTEXT       *Context;\r
+  FORM_ENTRY_INFO       *MenuList;\r
+  FORM_BROWSER_FORMSET  *FormSet;\r
+\r
+  gBrowserContextCount++;\r
+  if (gBrowserContextCount == 1) {\r
+    //\r
+    // This is not reentry of SendForm(), no context to save\r
+    //\r
+    return;\r
+  }\r
+\r
+  Context = AllocatePool (sizeof (BROWSER_CONTEXT));\r
+  ASSERT (Context != NULL);\r
+\r
+  Context->Signature = BROWSER_CONTEXT_SIGNATURE;\r
+\r
+  //\r
+  // Save FormBrowser context\r
+  //\r
+  Context->Selection         = gCurrentSelection;\r
+  Context->ResetRequired     = gResetRequiredFormLevel;\r
+  Context->FlagReconnect     = gFlagReconnect;\r
+  Context->CallbackReconnect = gCallbackReconnect;\r
+  Context->ExitRequired      = gExitRequired;\r
+  Context->HiiHandle         = mCurrentHiiHandle;\r
+  Context->FormId            = mCurrentFormId;\r
+  CopyGuid (&Context->FormSetGuid, &mCurrentFormSetGuid);\r
+  Context->SystemLevelFormSet    = mSystemLevelFormSet;\r
+  Context->CurFakeQestId         = mCurFakeQestId;\r
+  Context->HiiPackageListUpdated = mHiiPackageListUpdated;\r
+  Context->FinishRetrieveCall    = mFinishRetrieveCall;\r
+\r
+  //\r
+  // Save the menu history data.\r
+  //\r
+  InitializeListHead (&Context->FormHistoryList);\r
+  while (!IsListEmpty (&mPrivateData.FormBrowserEx2.FormViewHistoryHead)) {\r
+    MenuList = FORM_ENTRY_INFO_FROM_LINK (mPrivateData.FormBrowserEx2.FormViewHistoryHead.ForwardLink);\r
+    RemoveEntryList (&MenuList->Link);\r
+\r
+    InsertTailList (&Context->FormHistoryList, &MenuList->Link);\r
+  }\r
+\r
+  //\r
+  // Save formset list.\r
+  //\r
+  InitializeListHead (&Context->FormSetList);\r
+  while (!IsListEmpty (&gBrowserFormSetList)) {\r
+    FormSet = FORM_BROWSER_FORMSET_FROM_LINK (gBrowserFormSetList.ForwardLink);\r
+    RemoveEntryList (&FormSet->Link);\r
+\r
+    InsertTailList (&Context->FormSetList, &FormSet->Link);\r
+  }\r
+\r
+  //\r
+  // Insert to FormBrowser context list\r
+  //\r
+  InsertHeadList (&gBrowserContextList, &Context->Link);\r
+}\r
+\r
+/**\r
+  Restore globals used by previous call to SendForm().\r
+\r
+**/\r
+VOID\r
+RestoreBrowserContext (\r
+  VOID\r
+  )\r
+{\r
+  LIST_ENTRY            *Link;\r
+  BROWSER_CONTEXT       *Context;\r
+  FORM_ENTRY_INFO       *MenuList;\r
+  FORM_BROWSER_FORMSET  *FormSet;\r
+\r
+  ASSERT (gBrowserContextCount != 0);\r
+  gBrowserContextCount--;\r
+  if (gBrowserContextCount == 0) {\r
+    //\r
+    // This is not reentry of SendForm(), no context to restore\r
+    //\r
+    return;\r
+  }\r
+\r
+  ASSERT (!IsListEmpty (&gBrowserContextList));\r
+\r
+  Link    = GetFirstNode (&gBrowserContextList);\r
+  Context = BROWSER_CONTEXT_FROM_LINK (Link);\r
+\r
+  //\r
+  // Restore FormBrowser context\r
+  //\r
+  gCurrentSelection       = Context->Selection;\r
+  gResetRequiredFormLevel = Context->ResetRequired;\r
+  gFlagReconnect          = Context->FlagReconnect;\r
+  gCallbackReconnect      = Context->CallbackReconnect;\r
+  gExitRequired           = Context->ExitRequired;\r
+  mCurrentHiiHandle       = Context->HiiHandle;\r
+  mCurrentFormId          = Context->FormId;\r
+  CopyGuid (&mCurrentFormSetGuid, &Context->FormSetGuid);\r
+  mSystemLevelFormSet    = Context->SystemLevelFormSet;\r
+  mCurFakeQestId         = Context->CurFakeQestId;\r
+  mHiiPackageListUpdated = Context->HiiPackageListUpdated;\r
+  mFinishRetrieveCall    = Context->FinishRetrieveCall;\r
+\r
+  //\r
+  // Restore the menu history data.\r
+  //\r
+  while (!IsListEmpty (&Context->FormHistoryList)) {\r
+    MenuList = FORM_ENTRY_INFO_FROM_LINK (Context->FormHistoryList.ForwardLink);\r
+    RemoveEntryList (&MenuList->Link);\r
+\r
+    InsertTailList (&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &MenuList->Link);\r
+  }\r
+\r
+  //\r
+  // Restore the Formset data.\r
+  //\r
+  while (!IsListEmpty (&Context->FormSetList)) {\r
+    FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Context->FormSetList.ForwardLink);\r
+    RemoveEntryList (&FormSet->Link);\r
+\r
+    InsertTailList (&gBrowserFormSetList, &FormSet->Link);\r
+  }\r
+\r
+  //\r
+  // Remove from FormBrowser context list\r
+  //\r
+  RemoveEntryList (&Context->Link);\r
+  gBS->FreePool (Context);\r
+}\r
+\r
+/**\r
+  Find the matched FormSet context in the backup maintain list based on HiiHandle.\r
+\r
+  @param Handle  The Hii Handle.\r
+\r
+  @return the found FormSet context. If no found, NULL will return.\r
+\r
+**/\r
+FORM_BROWSER_FORMSET *\r
+GetFormSetFromHiiHandle (\r
+  EFI_HII_HANDLE  Handle\r
+  )\r
+{\r
+  LIST_ENTRY            *Link;\r
+  FORM_BROWSER_FORMSET  *FormSet;\r
+\r
+  Link = GetFirstNode (&gBrowserFormSetList);\r
+  while (!IsNull (&gBrowserFormSetList, Link)) {\r
+    FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
+    Link    = GetNextNode (&gBrowserFormSetList, Link);\r
+    if (!ValidateFormSet (FormSet)) {\r
+      continue;\r
+    }\r
+\r
+    if (FormSet->HiiHandle == Handle) {\r
+      return FormSet;\r
+    }\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Check whether the input HII handle is the FormSet that is being used.\r
+\r
+  @param Handle  The Hii Handle.\r
+\r
+  @retval TRUE   HII handle is being used.\r
+  @retval FALSE  HII handle is not being used.\r
+\r
+**/\r
+BOOLEAN\r
+IsHiiHandleInBrowserContext (\r
+  EFI_HII_HANDLE  Handle\r
+  )\r
+{\r
+  LIST_ENTRY       *Link;\r
+  BROWSER_CONTEXT  *Context;\r
+\r
+  //\r
+  // HiiHandle is Current FormSet.\r
+  //\r
+  if (mCurrentHiiHandle == Handle) {\r
+    return TRUE;\r
+  }\r
+\r
+  //\r
+  // Check whether HiiHandle is in BrowserContext.\r
+  //\r
+  Link = GetFirstNode (&gBrowserContextList);\r
+  while (!IsNull (&gBrowserContextList, Link)) {\r
+    Context = BROWSER_CONTEXT_FROM_LINK (Link);\r
+    if (Context->HiiHandle == Handle) {\r
+      //\r
+      // HiiHandle is in BrowserContext\r
+      //\r
+      return TRUE;\r
+    }\r
+\r
+    Link = GetNextNode (&gBrowserContextList, Link);\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Perform Password check.\r
+  Passwork may be encrypted by driver that requires the specific check.\r
+\r
+  @param  Form             Form where Password Statement is in.\r
+  @param  Statement        Password statement\r
+  @param  PasswordString   Password string to be checked. It may be NULL.\r
+                           NULL means to restore password.\r
+                           "" string can be used to checked whether old password does exist.\r
+\r
+  @return Status     Status of Password check.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PasswordCheck (\r
+  IN FORM_DISPLAY_ENGINE_FORM       *Form,\r
+  IN FORM_DISPLAY_ENGINE_STATEMENT  *Statement,\r
+  IN EFI_STRING                     PasswordString  OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;\r
+  EFI_BROWSER_ACTION_REQUEST      ActionRequest;\r
+  EFI_IFR_TYPE_VALUE              IfrTypeValue;\r
+  FORM_BROWSER_STATEMENT          *Question;\r
+\r
+  ConfigAccess = gCurrentSelection->FormSet->ConfigAccess;\r
+  Question     = GetBrowserStatement (Statement);\r
+  ASSERT (Question != NULL);\r
+\r
+  if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) {\r
+    if (ConfigAccess == NULL) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+  } else {\r
+    //\r
+    // If a password doesn't have the CALLBACK flag, browser will not handle it.\r
+    //\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Prepare password string in HII database\r
+  //\r
+  if (PasswordString != NULL) {\r
+    IfrTypeValue.string = NewString (PasswordString, gCurrentSelection->FormSet->HiiHandle);\r
+  } else {\r
+    IfrTypeValue.string = 0;\r
+  }\r
+\r
+  //\r
+  // Send password to Configuration Driver for validation\r
+  //\r
+  Status = ConfigAccess->Callback (\r
+                           ConfigAccess,\r
+                           EFI_BROWSER_ACTION_CHANGING,\r
+                           Question->QuestionId,\r
+                           Question->HiiValue.Type,\r
+                           &IfrTypeValue,\r
+                           &ActionRequest\r
+                           );\r
+\r
+  //\r
+  // Remove password string from HII database\r
+  //\r
+  if (PasswordString != NULL) {\r
+    DeleteString (IfrTypeValue.string, gCurrentSelection->FormSet->HiiHandle);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Find the registered HotKey based on KeyData.\r
+\r
+  @param[in] KeyData     A pointer to a buffer that describes the keystroke\r
+                         information for the hot key.\r
+\r
+  @return The registered HotKey context. If no found, NULL will return.\r
+**/\r
+BROWSER_HOT_KEY *\r
+GetHotKeyFromRegisterList (\r
+  IN EFI_INPUT_KEY  *KeyData\r
+  )\r
+{\r
+  LIST_ENTRY       *Link;\r
+  BROWSER_HOT_KEY  *HotKey;\r
+\r
+  Link = GetFirstNode (&gBrowserHotKeyList);\r
+  while (!IsNull (&gBrowserHotKeyList, Link)) {\r
+    HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);\r
+    if (HotKey->KeyData->ScanCode == KeyData->ScanCode) {\r
+      return HotKey;\r
+    }\r
+\r
+    Link = GetNextNode (&gBrowserHotKeyList, Link);\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Configure what scope the hot key will impact.\r
+  All hot keys have the same scope. The mixed hot keys with the different level are not supported.\r
+  If no scope is set, the default scope will be FormSet level.\r
+  After all registered hot keys are removed, previous Scope can reset to another level.\r
+\r
+  @param[in] Scope               Scope level to be set.\r
+\r
+  @retval EFI_SUCCESS            Scope is set correctly.\r
+  @retval EFI_INVALID_PARAMETER  Scope is not the valid value specified in BROWSER_SETTING_SCOPE.\r
+  @retval EFI_UNSPPORTED         Scope level is different from current one that the registered hot keys have.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetScope (\r
+  IN BROWSER_SETTING_SCOPE  Scope\r
+  )\r
+{\r
+  if (Scope >= MaxLevel) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // When no hot key registered in system or on the first setting,\r
+  // Scope can be set.\r
+  //\r
+  if (mBrowserScopeFirstSet || IsListEmpty (&gBrowserHotKeyList)) {\r
+    gBrowserSettingScope  = Scope;\r
+    mBrowserScopeFirstSet = FALSE;\r
+  } else if (Scope != gBrowserSettingScope) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
 \r
+  return EFI_SUCCESS;\r
+}\r
 \r
 /**\r
-  Fetch the Ifr binary data of a FormSet.\r
-\r
-  @param  Handle                 PackageList Handle\r
-  @param  FormSetGuid            GUID of a formset. If not specified (NULL or zero\r
-                                 GUID), take the first FormSet found in package\r
-                                 list.\r
-  @param  BinaryLength           The length of the FormSet IFR binary.\r
-  @param  BinaryData             The buffer designed to receive the FormSet.\r
-\r
-  @retval EFI_SUCCESS            Buffer filled with the requested FormSet.\r
-                                 BufferLength was updated.\r
-  @retval EFI_INVALID_PARAMETER  The handle is unknown.\r
-  @retval EFI_NOT_FOUND          A form or FormSet on the requested handle cannot\r
-                                 be found with the requested FormId.\r
-\r
+  Register the hot key with its browser action, or unregistered the hot key.\r
+  Only support hot key that is not printable character (control key, function key, etc.).\r
+  If the action value is zero, the hot key will be unregistered if it has been registered.\r
+  If the same hot key has been registered, the new action and help string will override the previous ones.\r
+\r
+  @param[in] KeyData     A pointer to a buffer that describes the keystroke\r
+                         information for the hot key. Its type is EFI_INPUT_KEY to\r
+                         be supported by all ConsoleIn devices.\r
+  @param[in] Action      Action value that describes what action will be trigged when the hot key is pressed.\r
+  @param[in] DefaultId   Specifies the type of defaults to retrieve, which is only for DEFAULT action.\r
+  @param[in] HelpString  Help string that describes the hot key information.\r
+                         Its value may be NULL for the unregistered hot key.\r
+\r
+  @retval EFI_SUCCESS            Hot key is registered or unregistered.\r
+  @retval EFI_INVALID_PARAMETER  KeyData is NULL or HelpString is NULL on register.\r
+  @retval EFI_NOT_FOUND          KeyData is not found to be unregistered.\r
+  @retval EFI_UNSUPPORTED        Key represents a printable character. It is conflicted with Browser.\r
+  @retval EFI_ALREADY_STARTED    Key already been registered for one hot key.\r
 **/\r
 EFI_STATUS\r
-GetIfrBinaryData (\r
-  IN  EFI_HII_HANDLE   Handle,\r
-  IN OUT EFI_GUID      *FormSetGuid,\r
-  OUT UINTN            *BinaryLength,\r
-  OUT UINT8            **BinaryData\r
+EFIAPI\r
+RegisterHotKey (\r
+  IN EFI_INPUT_KEY  *KeyData,\r
+  IN UINT32         Action,\r
+  IN UINT16         DefaultId,\r
+  IN EFI_STRING     HelpString OPTIONAL\r
   )\r
 {\r
-  EFI_STATUS                   Status;\r
-  EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;\r
-  UINTN                        BufferSize;\r
-  UINT8                        *Package;\r
-  UINT8                        *OpCodeData;\r
-  UINT32                       Offset;\r
-  UINT32                       Offset2;\r
-  BOOLEAN                      ReturnDefault;\r
-  UINT32                       PackageListLength;\r
-  EFI_HII_PACKAGE_HEADER       PackageHeader;\r
-  UINT8                        Index;\r
-  UINT8                        NumberOfClassGuid;\r
-  BOOLEAN                      IsSetupClassGuid;\r
-  EFI_GUID                     *ClassGuid;\r
-\r
-  OpCodeData = NULL;\r
-  Package = NULL;\r
-  ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));;\r
+  BROWSER_HOT_KEY  *HotKey;\r
 \r
   //\r
-  // if FormSetGuid is NULL or zero GUID, return first FormSet in the package list\r
+  // Check input parameters.\r
   //\r
-  if (FormSetGuid == NULL || CompareGuid (FormSetGuid, &gZeroGuid)) {\r
-    ReturnDefault = TRUE;\r
-  } else {\r
-    ReturnDefault = FALSE;\r
+  if ((KeyData == NULL) || (KeyData->UnicodeChar != CHAR_NULL) ||\r
+      ((Action != BROWSER_ACTION_UNREGISTER) && (HelpString == NULL)))\r
+  {\r
+    return EFI_INVALID_PARAMETER;\r
   }\r
 \r
   //\r
-  // Get HII PackageList\r
+  // Check whether the input KeyData is in BrowserHotKeyList.\r
   //\r
-  BufferSize = 0;\r
-  HiiPackageList = NULL;\r
-  Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
-  if (Status == EFI_BUFFER_TOO_SMALL) {\r
-    HiiPackageList = AllocatePool (BufferSize);\r
-    ASSERT (HiiPackageList != NULL);\r
+  HotKey = GetHotKeyFromRegisterList (KeyData);\r
 \r
-    Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
+  //\r
+  // Unregister HotKey\r
+  //\r
+  if (Action == BROWSER_ACTION_UNREGISTER) {\r
+    if (HotKey != NULL) {\r
+      //\r
+      // The registered HotKey is found.\r
+      // Remove it from List, and free its resource.\r
+      //\r
+      RemoveEntryList (&HotKey->Link);\r
+      FreePool (HotKey->KeyData);\r
+      FreePool (HotKey->HelpString);\r
+      return EFI_SUCCESS;\r
+    } else {\r
+      //\r
+      // The registered HotKey is not found.\r
+      //\r
+      return EFI_NOT_FOUND;\r
+    }\r
   }\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
+\r
+  if (HotKey != NULL) {\r
+    return EFI_ALREADY_STARTED;\r
   }\r
-  ASSERT (HiiPackageList != NULL);\r
 \r
   //\r
-  // Get Form package from this HII package List\r
+  // Create new Key, and add it into List.\r
   //\r
-  Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
-  Offset2 = 0;\r
-  CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
+  HotKey = AllocateZeroPool (sizeof (BROWSER_HOT_KEY));\r
+  ASSERT (HotKey != NULL);\r
+  HotKey->Signature = BROWSER_HOT_KEY_SIGNATURE;\r
+  HotKey->KeyData   = AllocateCopyPool (sizeof (EFI_INPUT_KEY), KeyData);\r
+  InsertTailList (&gBrowserHotKeyList, &HotKey->Link);\r
 \r
-  while (Offset < PackageListLength) {\r
-    Package = ((UINT8 *) HiiPackageList) + Offset;\r
-    CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
+  //\r
+  // Fill HotKey information.\r
+  //\r
+  HotKey->Action    = Action;\r
+  HotKey->DefaultId = DefaultId;\r
+  if (HotKey->HelpString != NULL) {\r
+    FreePool (HotKey->HelpString);\r
+  }\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
+  HotKey->HelpString = AllocateCopyPool (StrSize (HelpString), HelpString);\r
 \r
-        if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
-          //\r
-          // Check whether return default FormSet\r
-          //\r
-          if (ReturnDefault) {\r
-            //\r
-            // Check ClassGuid of formset OpCode\r
-            //\r
-            IsSetupClassGuid  = FALSE;\r
-            NumberOfClassGuid = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3);\r
-            ClassGuid         = (EFI_GUID *) (OpCodeData + sizeof (EFI_IFR_FORM_SET));\r
-            for (Index = 0; Index < NumberOfClassGuid; Index++) {\r
-              if (CompareGuid (ClassGuid + Index, &gEfiHiiPlatformSetupFormsetGuid)) {\r
-                IsSetupClassGuid = TRUE;\r
-                break;\r
-              }\r
-            }\r
-            if (IsSetupClassGuid) {\r
-              break;\r
-            }\r
-          }\r
+  return EFI_SUCCESS;\r
+}\r
 \r
-          //\r
-          // FormSet GUID is specified, check it\r
-          //\r
-          if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
-            break;\r
-          }\r
-        }\r
+/**\r
+  Register Exit handler function.\r
+  When more than one handler function is registered, the latter one will override the previous one.\r
+  When NULL handler is specified, the previous Exit handler will be unregistered.\r
+\r
+  @param[in] Handler      Pointer to handler function.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+RegiserExitHandler (\r
+  IN EXIT_HANDLER  Handler\r
+  )\r
+{\r
+  ExitHandlerFunction = Handler;\r
+  return;\r
+}\r
+\r
+/**\r
+  Check whether the browser data has been modified.\r
+\r
+  @retval TRUE        Browser data is modified.\r
+  @retval FALSE       No browser data is modified.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsBrowserDataModified (\r
+  VOID\r
+  )\r
+{\r
+  LIST_ENTRY            *Link;\r
+  FORM_BROWSER_FORMSET  *FormSet;\r
 \r
-        Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
+  switch (gBrowserSettingScope) {\r
+    case FormLevel:\r
+      if (gCurrentSelection == NULL) {\r
+        return FALSE;\r
       }\r
 \r
-      if (Offset2 < PackageHeader.Length) {\r
-        //\r
-        // Target formset found\r
-        //\r
-        break;\r
+      return IsNvUpdateRequiredForForm (gCurrentSelection->Form);\r
+\r
+    case FormSetLevel:\r
+      if (gCurrentSelection == NULL) {\r
+        return FALSE;\r
       }\r
-    }\r
 \r
-    Offset += PackageHeader.Length;\r
-  }\r
+      return IsNvUpdateRequiredForFormSet (gCurrentSelection->FormSet);\r
 \r
-  if (Offset >= PackageListLength) {\r
-    //\r
-    // Form package not found in this Package List\r
-    //\r
-    FreePool (HiiPackageList);\r
-    return EFI_NOT_FOUND;\r
-  }\r
+    case SystemLevel:\r
+      Link = GetFirstNode (&gBrowserFormSetList);\r
+      while (!IsNull (&gBrowserFormSetList, Link)) {\r
+        FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
+        if (!ValidateFormSet (FormSet)) {\r
+          continue;\r
+        }\r
 \r
-  if (ReturnDefault && FormSetGuid != NULL) {\r
-    //\r
-    // Return the default FormSet GUID\r
-    //\r
-    CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
-  }\r
+        if (IsNvUpdateRequiredForFormSet (FormSet)) {\r
+          return TRUE;\r
+        }\r
 \r
-  //\r
-  // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes\r
-  // in this FormSet; So, here just simply copy the data from start of a FormSet to the end\r
-  // of the Form Package.\r
-  //\r
-  *BinaryLength = PackageHeader.Length - Offset2;\r
-  *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);\r
+        Link = GetNextNode (&gBrowserFormSetList, Link);\r
+      }\r
 \r
-  FreePool (HiiPackageList);\r
+      return FALSE;\r
 \r
-  if (*BinaryData == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
+    default:\r
+      return FALSE;\r
   }\r
-\r
-  return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
-  Initialize the internal data structure of a FormSet.\r
+  Execute the action requested by the Action parameter.\r
 \r
-  @param  Handle                 PackageList Handle\r
-  @param  FormSetGuid            GUID of a formset. If not specified (NULL or zero\r
-                                 GUID), take the first FormSet found in package\r
-                                 list.\r
-  @param  FormSet                FormSet data structure.\r
+  @param[in] Action     Execute the request action.\r
+  @param[in] DefaultId  The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.\r
 \r
-  @retval EFI_SUCCESS            The function completed successfully.\r
-  @retval EFI_NOT_FOUND          The specified FormSet could not be found.\r
+  @retval EFI_SUCCESS              Execute the request action succss.\r
+  @retval EFI_INVALID_PARAMETER    The input action value is invalid.\r
 \r
 **/\r
 EFI_STATUS\r
-InitializeFormSet (\r
-  IN  EFI_HII_HANDLE                   Handle,\r
-  IN OUT EFI_GUID                      *FormSetGuid,\r
-  OUT FORM_BROWSER_FORMSET             *FormSet\r
+EFIAPI\r
+ExecuteAction (\r
+  IN UINT32  Action,\r
+  IN UINT16  DefaultId\r
   )\r
 {\r
-  EFI_STATUS                Status;\r
-  EFI_HANDLE                DriverHandle;\r
-  UINT16                    Index;\r
+  EFI_STATUS            Status;\r
+  FORM_BROWSER_FORMSET  *FormSet;\r
+  FORM_BROWSER_FORM     *Form;\r
 \r
-  Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
+  if ((gBrowserSettingScope < SystemLevel) && (gCurrentSelection == NULL)) {\r
+    return EFI_NOT_READY;\r
   }\r
 \r
-  FormSet->HiiHandle = Handle;\r
-  CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));\r
+  Status  = EFI_SUCCESS;\r
+  FormSet = NULL;\r
+  Form    = NULL;\r
+  if (gBrowserSettingScope < SystemLevel) {\r
+    FormSet = gCurrentSelection->FormSet;\r
+    Form    = gCurrentSelection->Form;\r
+  }\r
 \r
   //\r
-  // Retrieve ConfigAccess Protocol associated with this HiiPackageList\r
+  // Executet the discard action.\r
   //\r
-  Status = mHiiDatabase->GetPackageListHandle (mHiiDatabase, Handle, &DriverHandle);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-  FormSet->DriverHandle = DriverHandle;\r
-  Status = gBS->HandleProtocol (\r
-                  DriverHandle,\r
-                  &gEfiHiiConfigAccessProtocolGuid,\r
-                  (VOID **) &FormSet->ConfigAccess\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    //\r
-    // Configuration Driver don't attach ConfigAccess protocol to its HII package\r
-    // list, then there will be no configuration action required\r
-    //\r
-    FormSet->ConfigAccess = NULL;\r
+  if ((Action & BROWSER_ACTION_DISCARD) != 0) {\r
+    Status = DiscardForm (FormSet, Form, gBrowserSettingScope);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
   }\r
 \r
   //\r
-  // Parse the IFR binary OpCodes\r
+  // Executet the difault action.\r
   //\r
-  Status = ParseOpCodes (FormSet);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
+  if ((Action & BROWSER_ACTION_DEFAULT) != 0) {\r
+    Status = ExtractDefault (FormSet, Form, DefaultId, gBrowserSettingScope, GetDefaultForAll, NULL, FALSE, FALSE);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    UpdateStatementStatus (FormSet, Form, gBrowserSettingScope);\r
   }\r
 \r
-  gClassOfVfr = FORMSET_CLASS_PLATFORM_SETUP;\r
-  if (FormSet->SubClass == EFI_FRONT_PAGE_SUBCLASS) {\r
-    gClassOfVfr = FORMSET_CLASS_FRONT_PAGE;\r
-    gFrontPageHandle = FormSet->HiiHandle;\r
+  //\r
+  // Executet the submit action.\r
+  //\r
+  if ((Action & BROWSER_ACTION_SUBMIT) != 0) {\r
+    Status = SubmitForm (FormSet, Form, gBrowserSettingScope);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
   }\r
 \r
   //\r
-  // Match GUID to find out the function key setting. If match fail, use the default setting.\r
+  // Executet the reset action.\r
   //\r
-  for (Index = 0; Index < sizeof (gFunctionKeySettingTable) / sizeof (FUNCTIION_KEY_SETTING); Index++) {\r
-    if (CompareGuid (&FormSet->Guid, &(gFunctionKeySettingTable[Index].FormSetGuid))) {\r
-      //\r
-      // Update the function key setting.\r
-      //\r
-      gFunctionKeySetting = gFunctionKeySettingTable[Index].KeySetting;\r
-      //\r
-      // Function key prompt can not be displayed if the function key has been disabled.\r
-      //\r
-      if ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE) {\r
-        gFunctionNineString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
-      }\r
+  if ((Action & BROWSER_ACTION_RESET) != 0) {\r
+    gResetRequiredFormLevel   = TRUE;\r
+    gResetRequiredSystemLevel = TRUE;\r
+  }\r
 \r
-      if ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN) {\r
-        gFunctionTenString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
+  //\r
+  // Executet the exit action.\r
+  //\r
+  if ((Action & BROWSER_ACTION_EXIT) != 0) {\r
+    DiscardForm (FormSet, Form, gBrowserSettingScope);\r
+    if (gBrowserSettingScope == SystemLevel) {\r
+      if (ExitHandlerFunction != NULL) {\r
+        ExitHandlerFunction ();\r
       }\r
     }\r
+\r
+    gExitRequired = TRUE;\r
   }\r
 \r
   return Status;\r
 }\r
 \r
-\r
 /**\r
-  Save globals used by previous call to SendForm(). SendForm() may be called from \r
-  HiiConfigAccess.Callback(), this will cause SendForm() be reentried.\r
-  So, save globals of previous call to SendForm() and restore them upon exit.\r
+  Create reminder to let user to choose save or discard the changed browser data.\r
+  Caller can use it to actively check the changed browser data.\r
+\r
+  @retval BROWSER_NO_CHANGES       No browser data is changed.\r
+  @retval BROWSER_SAVE_CHANGES     The changed browser data is saved.\r
+  @retval BROWSER_DISCARD_CHANGES  The changed browser data is discard.\r
+  @retval BROWSER_KEEP_CURRENT     Browser keep current changes.\r
 \r
 **/\r
-VOID\r
-SaveBrowserContext (\r
+UINT32\r
+EFIAPI\r
+SaveReminder (\r
   VOID\r
   )\r
 {\r
-  BROWSER_CONTEXT  *Context;\r
+  LIST_ENTRY            *Link;\r
+  FORM_BROWSER_FORMSET  *FormSet;\r
+  BOOLEAN               IsDataChanged;\r
+  UINT32                DataSavedAction;\r
+  UINT32                ConfirmRet;\r
+\r
+  DataSavedAction = BROWSER_NO_CHANGES;\r
+  IsDataChanged   = FALSE;\r
+  Link            = GetFirstNode (&gBrowserFormSetList);\r
+  while (!IsNull (&gBrowserFormSetList, Link)) {\r
+    FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
+    Link    = GetNextNode (&gBrowserFormSetList, Link);\r
+    if (!ValidateFormSet (FormSet)) {\r
+      continue;\r
+    }\r
 \r
-  gBrowserContextCount++;\r
-  if (gBrowserContextCount == 1) {\r
-    //\r
-    // This is not reentry of SendForm(), no context to save\r
-    //\r
-    return;\r
+    if (IsNvUpdateRequiredForFormSet (FormSet)) {\r
+      IsDataChanged = TRUE;\r
+      break;\r
+    }\r
   }\r
 \r
-  Context = AllocatePool (sizeof (BROWSER_CONTEXT));\r
-  ASSERT (Context != NULL);\r
-\r
-  Context->Signature = BROWSER_CONTEXT_SIGNATURE;\r
-\r
   //\r
-  // Save FormBrowser context\r
+  // No data is changed. No save is required.\r
   //\r
-  Context->BannerData           = gBannerData;\r
-  Context->ClassOfVfr           = gClassOfVfr;\r
-  Context->FunctionKeySetting   = gFunctionKeySetting;\r
-  Context->ResetRequired        = gResetRequired;\r
-  Context->NvUpdateRequired     = gNvUpdateRequired;\r
-  Context->Direction            = gDirection;\r
-  Context->FunctionNineString   = gFunctionNineString;\r
-  Context->FunctionTenString    = gFunctionTenString;\r
-  Context->EnterString          = gEnterString;\r
-  Context->EnterCommitString    = gEnterCommitString;\r
-  Context->EnterEscapeString    = gEnterEscapeString;\r
-  Context->EscapeString         = gEscapeString;\r
-  Context->SaveFailed           = gSaveFailed;\r
-  Context->MoveHighlight        = gMoveHighlight;\r
-  Context->MakeSelection        = gMakeSelection;\r
-  Context->DecNumericInput      = gDecNumericInput;\r
-  Context->HexNumericInput      = gHexNumericInput;\r
-  Context->ToggleCheckBox       = gToggleCheckBox;\r
-  Context->PromptForData        = gPromptForData;\r
-  Context->PromptForPassword    = gPromptForPassword;\r
-  Context->PromptForNewPassword = gPromptForNewPassword;\r
-  Context->ConfirmPassword      = gConfirmPassword;\r
-  Context->ConfirmError         = gConfirmError;\r
-  Context->PassowordInvalid     = gPassowordInvalid;\r
-  Context->PressEnter           = gPressEnter;\r
-  Context->EmptyString          = gEmptyString;\r
-  Context->AreYouSure           = gAreYouSure;\r
-  Context->YesResponse          = gYesResponse;\r
-  Context->NoResponse           = gNoResponse;\r
-  Context->MiniString           = gMiniString;\r
-  Context->PlusString           = gPlusString;\r
-  Context->MinusString          = gMinusString;\r
-  Context->AdjustNumber         = gAdjustNumber;\r
-  Context->SaveChanges          = gSaveChanges;\r
-  Context->OptionMismatch       = gOptionMismatch;\r
-  Context->PromptBlockWidth     = gPromptBlockWidth;\r
-  Context->OptionBlockWidth     = gOptionBlockWidth;\r
-  Context->HelpBlockWidth       = gHelpBlockWidth;\r
-  Context->OldFormSet           = gOldFormSet;\r
-  Context->MenuRefreshHead      = gMenuRefreshHead;\r
-\r
-  CopyMem (&Context->ScreenDimensions, &gScreenDimensions, sizeof (gScreenDimensions));\r
-  CopyMem (&Context->MenuOption, &gMenuOption, sizeof (gMenuOption));\r
+  if (!IsDataChanged) {\r
+    return DataSavedAction;\r
+  }\r
 \r
   //\r
-  // Insert to FormBrowser context list\r
+  // If data is changed, prompt user to save or discard it.\r
   //\r
-  InsertHeadList (&gBrowserContextList, &Context->Link);\r
-}\r
+  do {\r
+    ConfirmRet = (UINT32)mFormDisplay->ConfirmDataChange ();\r
+\r
+    if (ConfirmRet == BROWSER_ACTION_SUBMIT) {\r
+      SubmitForm (NULL, NULL, SystemLevel);\r
+      DataSavedAction = BROWSER_SAVE_CHANGES;\r
+      break;\r
+    } else if (ConfirmRet == BROWSER_ACTION_DISCARD) {\r
+      DiscardForm (NULL, NULL, SystemLevel);\r
+      DataSavedAction = BROWSER_DISCARD_CHANGES;\r
+      break;\r
+    } else if (ConfirmRet == BROWSER_ACTION_NONE) {\r
+      DataSavedAction = BROWSER_KEEP_CURRENT;\r
+      break;\r
+    }\r
+  } while (1);\r
 \r
+  return DataSavedAction;\r
+}\r
 \r
 /**\r
-  Restore globals used by previous call to SendForm().\r
+  Check whether the Reset Required for the browser\r
+\r
+  @retval TRUE      Browser required to reset after exit.\r
+  @retval FALSE     Browser not need to reset after exit.\r
 \r
 **/\r
-VOID\r
-RestoreBrowserContext (\r
+BOOLEAN\r
+EFIAPI\r
+IsResetRequired (\r
   VOID\r
   )\r
 {\r
-  LIST_ENTRY       *Link;\r
-  BROWSER_CONTEXT  *Context;\r
-\r
-  ASSERT (gBrowserContextCount != 0);\r
-  gBrowserContextCount--;\r
-  if (gBrowserContextCount == 0) {\r
-    //\r
-    // This is not reentry of SendForm(), no context to restore\r
-    //\r
-    return;\r
-  }\r
-\r
-  ASSERT (!IsListEmpty (&gBrowserContextList));\r
-\r
-  Link = GetFirstNode (&gBrowserContextList);\r
-  Context = BROWSER_CONTEXT_FROM_LINK (Link);\r
-\r
-  //\r
-  // Restore FormBrowser context\r
-  //\r
-  gBannerData           = Context->BannerData;\r
-  gClassOfVfr           = Context->ClassOfVfr;\r
-  gFunctionKeySetting   = Context->FunctionKeySetting;\r
-  gResetRequired        = Context->ResetRequired;\r
-  gNvUpdateRequired     = Context->NvUpdateRequired;\r
-  gDirection            = Context->Direction;\r
-  gFunctionNineString   = Context->FunctionNineString;\r
-  gFunctionTenString    = Context->FunctionTenString;\r
-  gEnterString          = Context->EnterString;\r
-  gEnterCommitString    = Context->EnterCommitString;\r
-  gEnterEscapeString    = Context->EnterEscapeString;\r
-  gEscapeString         = Context->EscapeString;\r
-  gSaveFailed           = Context->SaveFailed;\r
-  gMoveHighlight        = Context->MoveHighlight;\r
-  gMakeSelection        = Context->MakeSelection;\r
-  gDecNumericInput      = Context->DecNumericInput;\r
-  gHexNumericInput      = Context->HexNumericInput;\r
-  gToggleCheckBox       = Context->ToggleCheckBox;\r
-  gPromptForData        = Context->PromptForData;\r
-  gPromptForPassword    = Context->PromptForPassword;\r
-  gPromptForNewPassword = Context->PromptForNewPassword;\r
-  gConfirmPassword      = Context->ConfirmPassword;\r
-  gConfirmError         = Context->ConfirmError;\r
-  gPassowordInvalid     = Context->PassowordInvalid;\r
-  gPressEnter           = Context->PressEnter;\r
-  gEmptyString          = Context->EmptyString;\r
-  gAreYouSure           = Context->AreYouSure;\r
-  gYesResponse          = Context->YesResponse;\r
-  gNoResponse           = Context->NoResponse;\r
-  gMiniString           = Context->MiniString;\r
-  gPlusString           = Context->PlusString;\r
-  gMinusString          = Context->MinusString;\r
-  gAdjustNumber         = Context->AdjustNumber;\r
-  gSaveChanges          = Context->SaveChanges;\r
-  gOptionMismatch       = Context->OptionMismatch;\r
-  gPromptBlockWidth     = Context->PromptBlockWidth;\r
-  gOptionBlockWidth     = Context->OptionBlockWidth;\r
-  gHelpBlockWidth       = Context->HelpBlockWidth;\r
-  gOldFormSet           = Context->OldFormSet;\r
-  gMenuRefreshHead      = Context->MenuRefreshHead;\r
-\r
-  CopyMem (&gScreenDimensions, &Context->ScreenDimensions, sizeof (gScreenDimensions));\r
-  CopyMem (&gMenuOption, &Context->MenuOption, sizeof (gMenuOption));\r
-\r
-  //\r
-  // Remove from FormBrowser context list\r
-  //\r
-  RemoveEntryList (&Context->Link);\r
-  gBS->FreePool (Context);\r
+  return gResetRequiredSystemLevel;\r
 }\r