]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
Update Browser to provide the customization possibilities.
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Setup.c
index 6c019f045483890425b87844fafd7cb3e2a1ecc9..c4dd18a04fd664e4320d71ffabad670625763088 100644 (file)
@@ -26,166 +26,283 @@ SETUP_DRIVER_PRIVATE_DATA  mPrivateData = {
     RegisterHotKey,\r
     RegiserExitHandler,\r
     SaveReminder\r
+  },\r
+  {\r
+    BROWSER_EXTENSION2_VERSION_1,\r
+    SetScope,\r
+    RegisterHotKey,\r
+    RegiserExitHandler,\r
+    IsBrowserDataModified,\r
+    ExecuteAction,\r
   }\r
 };\r
 \r
 EFI_HII_DATABASE_PROTOCOL         *mHiiDatabase;\r
-EFI_HII_STRING_PROTOCOL           *mHiiString;\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
 \r
-BANNER_DATA           *gBannerData;\r
-EFI_HII_HANDLE        gFrontPageHandle;\r
-UINTN                 gClassOfVfr;\r
-UINTN                 gFunctionKeySetting;\r
 BOOLEAN               gResetRequired;\r
-EFI_HII_HANDLE        gHiiHandle;\r
-UINT16                gDirection;\r
-EFI_SCREEN_DESCRIPTOR gScreenDimensions;\r
+BOOLEAN               gExitRequired;\r
 BROWSER_SETTING_SCOPE gBrowserSettingScope = FormSetLevel;\r
 BOOLEAN               mBrowserScopeFirstSet = TRUE;\r
 EXIT_HANDLER          ExitHandlerFunction = NULL;\r
-UINTN                 gFooterHeight;\r
 \r
 //\r
 // Browser Global Strings\r
 //\r
-CHAR16            *gSaveFailed;\r
-CHAR16            *gDiscardFailed;\r
-CHAR16            *gDefaultFailed;\r
-CHAR16            *gEnterString;\r
-CHAR16            *gEnterCommitString;\r
-CHAR16            *gEnterEscapeString;\r
-CHAR16            *gEscapeString;\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
-CHAR16            *gFormSuppress;\r
-CHAR16            *gProtocolNotFound;\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
 \r
 FORM_BROWSER_FORMSET  *gOldFormSet = NULL;\r
+extern UINT32   gBrowserStatus;\r
+extern CHAR16   *gErrorInfo;\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
+  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
+  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 (CompareGuid (&MenuList->FormSetGuid, &gZeroGuid)) {\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
-    NONE_FUNCTION_KEY_SETTING\r
-  },\r
+    }\r
+  }\r
+\r
+  return RetMenu;\r
+}\r
+\r
+/**\r
+  Find parent menu for current menu.\r
+\r
+  @param  CurrentMenu    Current Menu\r
+\r
+  @retval   The parent menu for current menu.\r
+**/\r
+FORM_ENTRY_INFO *\r
+UiFindParentMenu (\r
+  IN FORM_ENTRY_INFO  *CurrentMenu\r
+  )\r
+{\r
+  FORM_ENTRY_INFO    *ParentMenu;\r
+\r
+  ParentMenu = NULL;\r
+  if (CurrentMenu->Link.BackLink != &mPrivateData.FormBrowserEx2.FormViewHistoryHead) {\r
+    ParentMenu = FORM_ENTRY_INFO_FROM_LINK (CurrentMenu->Link.BackLink);\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
+  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
+\r
   //\r
-  // Device Manager\r
+  // Get all the Hii handles\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
+  HiiHandles = HiiGetHiiHandles (NULL);\r
+  ASSERT (HiiHandles != NULL);\r
+\r
   //\r
-  // BMM FormSet.\r
+  // Search for formset of each class type\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
+  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
+    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
+    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
-  // BMM File Explorer FormSet.\r
+  // Free resources, and restore gOldFormSet and gClassOfVfr\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
+  FreePool (HiiHandles);\r
+}\r
 \r
 /**\r
   This is the routine which an external caller uses to direct the browser\r
@@ -228,26 +345,14 @@ SendForm (
   UI_MENU_SELECTION             *Selection;\r
   UINTN                         Index;\r
   FORM_BROWSER_FORMSET          *FormSet;\r
-  LIST_ENTRY                    *Link;\r
+  FORM_ENTRY_INFO               *MenuList;\r
 \r
   //\r
-  // Calculate total number of Register HotKeys. \r
+  // If EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found, return EFI_UNSUPPORTED.\r
   //\r
-  Index = 0;\r
-  Link  = GetFirstNode (&gBrowserHotKeyList);\r
-  while (!IsNull (&gBrowserHotKeyList, Link)) {\r
-    Link = GetNextNode (&gBrowserHotKeyList, Link);\r
-    Index ++;\r
+  if (mFormDisplay == NULL) {\r
+    return EFI_UNSUPPORTED;\r
   }\r
-  //\r
-  // Show three HotKeys help information on one ROW.\r
-  //\r
-  gFooterHeight = FOOTER_HEIGHT + (Index / 3);\r
-\r
-  //\r
-  // Clean the history menu list.\r
-  //\r
-  InitializeListHead (&gMenuList);\r
 \r
   //\r
   // Save globals used by SendForm()\r
@@ -255,65 +360,10 @@ SendForm (
   SaveBrowserContext ();\r
 \r
   gResetRequired = FALSE;\r
-  Status = EFI_SUCCESS;\r
-  ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
-\r
-  //\r
-  // Seed the dimensions in the global\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
-            gFooterHeight +\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
-  }\r
-\r
-  gOptionBlockWidth = (CHAR16) ((gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3);\r
-  gPromptBlockWidth = (CHAR16) (gOptionBlockWidth + LEFT_SKIPPED_COLUMNS);\r
-  gHelpBlockWidth   = (CHAR16) (gOptionBlockWidth - LEFT_SKIPPED_COLUMNS);\r
-\r
-  //\r
-  // Initialize the strings for the browser, upon exit of the browser, the strings will be freed\r
-  //\r
-  InitializeBrowserStrings ();\r
-\r
-  //\r
-  // Ensure we are in Text mode\r
-  //\r
-  gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
+  gExitRequired  = 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
@@ -334,18 +384,13 @@ SendForm (
       //\r
       // Initialize internal data structures of FormSet\r
       //\r
-      Status = InitializeFormSet (Selection->Handle, &Selection->FormSetGuid, FormSet, TRUE);\r
+      Status = InitializeFormSet (Selection->Handle, &Selection->FormSetGuid, FormSet);\r
       if (EFI_ERROR (Status) || IsListEmpty (&FormSet->FormListHead)) {\r
         DestroyFormSet (FormSet);\r
         break;\r
       }\r
       Selection->FormSet = FormSet;\r
 \r
-      //\r
-      // Try to find pre FormSet in the maintain backup list.\r
-      //\r
-      gOldFormSet = GetFormSetFromHiiHandle (Selection->Handle);\r
-\r
       //\r
       // Display this formset\r
       //\r
@@ -355,26 +400,36 @@ SendForm (
 \r
       gCurrentSelection = NULL;\r
 \r
-      if (EFI_ERROR (Status)) {\r
-        break;\r
-      }\r
-\r
-    } while (Selection->Action == UI_ACTION_REFRESH_FORMSET);\r
-\r
-    if (gOldFormSet != NULL) {\r
       //\r
       // If no data is changed, don't need to save current FormSet into the maintain list.\r
       //\r
-      if (!IsNvUpdateRequired (gOldFormSet)) {\r
-        RemoveEntryList (&gOldFormSet->Link);\r
-        DestroyFormSet (gOldFormSet);\r
+      if (!IsNvUpdateRequiredForFormSet (FormSet) && !IsStorageDataChangedForFormSet(FormSet)) {\r
+        CleanBrowserStorage(FormSet);\r
+        RemoveEntryList (&FormSet->Link);\r
+        DestroyFormSet (FormSet);\r
       }\r
-      gOldFormSet = NULL;\r
-    }\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        break;\r
+      }\r
+    } while (Selection->Action == UI_ACTION_REFRESH_FORMSET);\r
 \r
     FreePool (Selection);\r
   }\r
 \r
+  //\r
+  // Still has error info, pop up a message.\r
+  //\r
+  if (gBrowserStatus != BROWSER_SUCCESS) {\r
+    gDisplayFormData.BrowserStatus = gBrowserStatus;\r
+    gDisplayFormData.ErrorString   = gErrorInfo;\r
+\r
+    gBrowserStatus = BROWSER_SUCCESS;\r
+    gErrorInfo     = NULL;\r
+\r
+    mFormDisplay->FormDisplay (&gDisplayFormData, NULL);\r
+  }\r
+\r
   if (ActionRequest != NULL) {\r
     *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
     if (gResetRequired) {\r
@@ -382,13 +437,17 @@ SendForm (
     }\r
   }\r
 \r
-  FreeBrowserStrings ();\r
-  UiFreeMenuList(&gMenuList);\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
@@ -397,10 +456,93 @@ Done:
   return Status;\r
 }\r
 \r
+/**\r
+  Get or set data to the storage.\r
+\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
+  @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  Storage                The pointer to the storage.\r
+\r
+  @retval EFI_SUCCESS            The results have been distributed or are awaiting\r
+                                 distribution.\r
+\r
+**/\r
+EFI_STATUS \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
+  CHAR16                *ConfigResp;\r
+  EFI_STATUS            Status;\r
+  CHAR16                *StrPtr;\r
+  UINTN                 BufferSize;\r
+  UINTN                 TmpSize;\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
+    //\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     = ConfigResp + StrLen (Storage->ConfigHdr) + 1;\r
+    BufferSize = StrSize (StrPtr);\r
+\r
+\r
+    //\r
+    // Copy the data if the input buffer is bigger enough.\r
+    //\r
+    if (*ResultsDataSize >= BufferSize) {\r
+      StrCpy (*ResultsData, StrPtr);\r
+    }\r
+\r
+    *ResultsDataSize = BufferSize;\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
+\r
+    StrCpy (ConfigResp, Storage->ConfigHdr);\r
+    StrCat (ConfigResp, L"&");\r
+    StrCat (ConfigResp, *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
+  return EFI_SUCCESS;\r
+}\r
 \r
 /**\r
-  This function is called by a callback handler to retrieve uncommitted state\r
-  data from the browser.\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
@@ -438,60 +580,69 @@ BrowserCallback (
 {\r
   EFI_STATUS            Status;\r
   LIST_ENTRY            *Link;\r
-  FORMSET_STORAGE       *Storage;\r
+  BROWSER_STORAGE       *Storage;\r
+  FORMSET_STORAGE       *FormsetStorage;\r
   FORM_BROWSER_FORMSET  *FormSet;\r
+  UINTN                 TotalSize;\r
   BOOLEAN               Found;\r
-  CHAR16                *ConfigResp;\r
-  CHAR16                *StrPtr;\r
-  UINTN                 BufferSize;\r
-  UINTN                 TmpSize;\r
 \r
   if (ResultsDataSize == NULL || ResultsData == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  if (gCurrentSelection == NULL) {\r
-    return EFI_NOT_READY;\r
-  }\r
-\r
-  Storage = NULL;\r
-  ConfigResp = NULL;\r
-  FormSet = gCurrentSelection->FormSet;\r
+  TotalSize = *ResultsDataSize;\r
+  Storage   = NULL;\r
+  Found     = FALSE;\r
+  Status    = EFI_SUCCESS;\r
 \r
   //\r
-  // Find target storage\r
+  // If set browser data, pre load all hii formset to avoid set the varstore which is not \r
+  // saved in browser.\r
   //\r
-  Link = GetFirstNode (&FormSet->StorageListHead);\r
-  if (IsNull (&FormSet->StorageListHead, Link)) {\r
-    return EFI_UNSUPPORTED;\r
+  if (!RetrieveData && (gBrowserSettingScope == SystemLevel)) {\r
+    LoadAllHiiFormset();\r
   }\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
-            Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_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
+        // 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
+      Status = ProcessStorage (&TotalSize, &ResultsData, RetrieveData, Storage);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\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
@@ -501,65 +652,62 @@ 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 (gCurrentSelection == NULL) {\r
+      return EFI_NOT_READY;\r
     }\r
 \r
     //\r
     // Generate <ConfigResp>\r
     //\r
-    Status = StorageToConfigResp (Storage, &ConfigResp, FALSE);\r
+    FormSet = gCurrentSelection->FormSet;\r
+    Link = GetFirstNode (&FormSet->StorageListHead);\r
+    if (IsNull (&FormSet->StorageListHead, Link)) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+\r
+    FormsetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
+    \r
+    Status = ProcessStorage (&TotalSize, &ResultsData, RetrieveData, FormsetStorage->BrowserStorage);\r
     if (EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
+  }\r
 \r
-    //\r
-    // Skip <ConfigHdr> and '&' to point to <ConfigBody>\r
-    //\r
-    StrPtr = ConfigResp + StrLen (Storage->ConfigHdr) + 1;\r
+  if (RetrieveData) {\r
+    Status = TotalSize <= *ResultsDataSize ? EFI_SUCCESS : EFI_BUFFER_TOO_SMALL;\r
+    *ResultsDataSize = TotalSize;\r
+  }\r
+   \r
+  return Status;\r
 \r
-    BufferSize = StrSize (StrPtr);\r
-    if (*ResultsDataSize < BufferSize) {\r
-      *ResultsDataSize = BufferSize;\r
+}\r
 \r
-      FreePool (ConfigResp);\r
-      return EFI_BUFFER_TOO_SMALL;\r
-    }\r
 \r
-    *ResultsDataSize = BufferSize;\r
-    CopyMem (ResultsData, StrPtr, BufferSize);\r
+/**\r
+  Callback function for SimpleTextInEx protocol install events\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
+  @param Event           the event that is signaled.\r
+  @param Context         not used here.\r
 \r
-    StrCpy (ConfigResp, Storage->ConfigHdr);\r
-    StrCat (ConfigResp, L"&");\r
-    StrCat (ConfigResp, ResultsData);\r
+**/\r
+VOID\r
+EFIAPI\r
+FormDisplayCallback (\r
+  IN EFI_EVENT    Event,\r
+  IN VOID         *Context\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
 \r
-    //\r
-    // Update Browser uncommited data\r
-    //\r
-    Status = ConfigRespToStorage (Storage, ConfigResp);\r
-    if (EFI_ERROR (Status)) {\r
-      return Status;\r
-    }\r
+  if (mFormDisplay != NULL) {\r
+    return;\r
   }\r
 \r
-  return EFI_SUCCESS;\r
+  Status = gBS->LocateProtocol (\r
+                  &gEdkiiFormDisplayEngineProtocolGuid,\r
+                  NULL,\r
+                  (VOID **) &mFormDisplay\r
+                  );\r
 }\r
 \r
 /**\r
@@ -580,8 +728,7 @@ InitializeSetup (
   )\r
 {\r
   EFI_STATUS                  Status;\r
-  EFI_INPUT_KEY               DefaultHotKey;\r
-  EFI_STRING                  HelpString;\r
+  VOID                        *Registration;\r
 \r
   //\r
   // Locate required Hii relative protocols\r
@@ -593,13 +740,6 @@ InitializeSetup (
                   );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
-  Status = gBS->LocateProtocol (\r
-                  &gEfiHiiStringProtocolGuid,\r
-                  NULL,\r
-                  (VOID **) &mHiiString\r
-                  );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
   Status = gBS->LocateProtocol (\r
                   &gEfiHiiConfigRoutingProtocolGuid,\r
                   NULL,\r
@@ -613,30 +753,6 @@ InitializeSetup (
                   (VOID **) &mPathFromText\r
                   );\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
-  //\r
-  gBannerData = AllocateZeroPool (sizeof (BANNER_DATA));\r
-  ASSERT (gBannerData != NULL);\r
-  \r
-  //\r
-  // Initialize generic help strings.\r
-  //\r
-  gSaveFailed    = GetToken (STRING_TOKEN (SAVE_FAILED), gHiiHandle);\r
-  gDiscardFailed = GetToken (STRING_TOKEN (DISCARD_FAILED), gHiiHandle);\r
-  gDefaultFailed = GetToken (STRING_TOKEN (DEFAULT_FAILED), gHiiHandle);\r
-\r
   //\r
   // Install FormBrowser2 protocol\r
   //\r
@@ -650,25 +766,18 @@ InitializeSetup (
   ASSERT_EFI_ERROR (Status);\r
 \r
   //\r
-  // Install default HotKey F10 for Save\r
-  //\r
-  DefaultHotKey.UnicodeChar = CHAR_NULL;\r
-  HelpString             = GetToken (STRING_TOKEN (FUNCTION_TEN_STRING), gHiiHandle);\r
-  DefaultHotKey.ScanCode = SCAN_F10;\r
-  RegisterHotKey (&DefaultHotKey, BROWSER_ACTION_SUBMIT, 0, HelpString);\r
-  FreePool (HelpString);\r
-  //\r
-  // Install default HotKey F9 for Reset To Defaults\r
-  //\r
-  DefaultHotKey.ScanCode    = SCAN_F9;\r
-  HelpString                = GetToken (STRING_TOKEN (FUNCTION_NINE_STRING), gHiiHandle);\r
-  RegisterHotKey (&DefaultHotKey, BROWSER_ACTION_DEFAULT, EFI_HII_DEFAULT_CLASS_STANDARD, HelpString);\r
-  FreePool (HelpString);\r
-\r
-  //\r
-  // Install FormBrowserEx protocol\r
+  // Install FormBrowserEx2 protocol\r
   //\r
+  InitializeListHead (&mPrivateData.FormBrowserEx2.FormViewHistoryHead);  \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
                   &gEfiFormBrowserExProtocolGuid,\r
@@ -677,7 +786,25 @@ InitializeSetup (
                   );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
-  return Status;\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
@@ -813,58 +940,6 @@ NewStringCat (
   *Dest = NewString;\r
 }\r
 \r
-\r
-/**\r
-  Synchronize or restore Storage's Edit copy and Shadow copy.\r
-\r
-  @param  Storage          The Storage to be synchronized.\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
-**/\r
-VOID\r
-SynchronizeStorage (\r
-  IN FORMSET_STORAGE         *Storage,\r
-  IN BOOLEAN                 SyncOrRestore\r
-  )\r
-{\r
-  LIST_ENTRY              *Link;\r
-  NAME_VALUE_NODE         *Node;\r
-\r
-  switch (Storage->Type) {\r
-  case EFI_HII_VARSTORE_BUFFER:\r
-  case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
-    if (SyncOrRestore) {\r
-      CopyMem (Storage->Buffer, Storage->EditBuffer, Storage->Size);\r
-    } else {\r
-      CopyMem (Storage->EditBuffer, Storage->Buffer, Storage->Size);\r
-    }\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
-      if (SyncOrRestore) {\r
-        NewStringCpy (&Node->Value, Node->EditValue);\r
-      } else {\r
-        NewStringCpy (&Node->EditValue, Node->Value);\r
-      }\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
@@ -879,7 +954,7 @@ SynchronizeStorage (
 **/\r
 EFI_STATUS\r
 GetValueByName (\r
-  IN FORMSET_STORAGE             *Storage,\r
+  IN BROWSER_STORAGE             *Storage,\r
   IN CHAR16                      *Name,\r
   IN OUT CHAR16                  **Value,\r
   IN GET_SET_QUESTION_VALUE_WITH GetValueFrom\r
@@ -921,6 +996,7 @@ GetValueByName (
   @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
@@ -928,10 +1004,11 @@ GetValueByName (
 **/\r
 EFI_STATUS\r
 SetValueByName (\r
-  IN FORMSET_STORAGE         *Storage,\r
-  IN CHAR16                  *Name,\r
-  IN CHAR16                  *Value,\r
-  IN GET_SET_QUESTION_VALUE_WITH SetValueTo\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
@@ -962,6 +1039,11 @@ SetValueByName (
       } else {\r
         Node->Value = Buffer;\r
       }\r
+\r
+      if (ReturnNode != NULL) {\r
+        *ReturnNode = Node;\r
+      }\r
+\r
       return EFI_SUCCESS;\r
     }\r
 \r
@@ -975,9 +1057,10 @@ SetValueByName (
 /**\r
   Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.\r
 \r
-  @param  Buffer                 The Storage to be conveted.\r
+  @param  Storage                The Storage to be conveted.\r
   @param  ConfigResp             The returned <ConfigResp>.\r
-  @param  SingleForm             Whether update data for single form or formset level.\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
@@ -985,36 +1068,28 @@ SetValueByName (
 **/\r
 EFI_STATUS\r
 StorageToConfigResp (\r
-  IN VOID                    *Buffer,\r
+  IN BROWSER_STORAGE         *Storage,\r
   IN CHAR16                  **ConfigResp,\r
-  IN BOOLEAN                 SingleForm\r
+  IN CHAR16                  *ConfigRequest,\r
+  IN BOOLEAN                 GetEditBuf\r
   )\r
 {\r
-  EFI_STATUS  Status;\r
-  EFI_STRING  Progress;\r
+  EFI_STATUS              Status;\r
+  EFI_STRING              Progress;\r
   LIST_ENTRY              *Link;\r
   NAME_VALUE_NODE         *Node;\r
-  CHAR16                  *ConfigRequest;\r
-  FORMSET_STORAGE         *Storage;\r
-  FORM_BROWSER_CONFIG_REQUEST  *ConfigInfo;\r
+  UINT8                   *SourceBuf;\r
 \r
   Status = EFI_SUCCESS;\r
-  if (SingleForm) {\r
-    ConfigInfo    = (FORM_BROWSER_CONFIG_REQUEST *) Buffer;\r
-    Storage       = ConfigInfo->Storage;\r
-    ConfigRequest = ConfigInfo->ConfigRequest;\r
-  } else {\r
-    Storage       = (FORMSET_STORAGE *) Buffer;\r
-    ConfigRequest = Storage->ConfigRequest;\r
-  }\r
 \r
   switch (Storage->Type) {\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
-                                  Storage->EditBuffer,\r
+                                  SourceBuf,\r
                                   Storage->Size,\r
                                   ConfigResp,\r
                                   &Progress\r
@@ -1033,7 +1108,11 @@ StorageToConfigResp (
         NewStringCat (ConfigResp, L"&");\r
         NewStringCat (ConfigResp, Node->Name);\r
         NewStringCat (ConfigResp, L"=");\r
-        NewStringCat (ConfigResp, Node->EditValue);\r
+        if (GetEditBuf) {\r
+          NewStringCat (ConfigResp, Node->EditValue);\r
+        } else {\r
+          NewStringCat (ConfigResp, Node->Value);\r
+        }\r
       }\r
       Link = GetNextNode (&Storage->NameValueListHead, Link);\r
     }\r
@@ -1061,7 +1140,7 @@ StorageToConfigResp (
 **/\r
 EFI_STATUS\r
 ConfigRespToStorage (\r
-  IN FORMSET_STORAGE         *Storage,\r
+  IN BROWSER_STORAGE         *Storage,\r
   IN CHAR16                  *ConfigResp\r
   )\r
 {\r
@@ -1114,7 +1193,7 @@ ConfigRespToStorage (
       if (StrPtr != NULL) {\r
         *StrPtr = 0;\r
       }\r
-      SetValueByName (Storage, Name, Value, GetSetValueWithEditBuffer);\r
+      SetValueByName (Storage, Name, Value, GetSetValueWithEditBuffer, NULL);\r
     }\r
     break;\r
 \r
@@ -1153,7 +1232,7 @@ GetQuestionValue (
   UINT8               *Dst;\r
   UINTN               StorageWidth;\r
   EFI_TIME            EfiTime;\r
-  FORMSET_STORAGE     *Storage;\r
+  BROWSER_STORAGE     *Storage;\r
   EFI_IFR_TYPE_VALUE  *QuestionValue;\r
   CHAR16              *ConfigRequest;\r
   CHAR16              *Progress;\r
@@ -1540,7 +1619,7 @@ GetQuestionValue (
     if (IsBufferStorage) {\r
       CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth);\r
     } else {\r
-      SetValueByName (Storage, Question->VariableName, Value, GetSetValueWithEditBuffer);\r
+      SetValueByName (Storage, Question->VariableName, Value, GetSetValueWithEditBuffer, NULL);\r
     }\r
 \r
     if (Result != NULL) {\r
@@ -1578,7 +1657,7 @@ SetQuestionValue (
   EFI_TIME            EfiTime;\r
   UINTN               BufferLen;\r
   UINTN               StorageWidth;\r
-  FORMSET_STORAGE     *Storage;\r
+  BROWSER_STORAGE     *Storage;\r
   EFI_IFR_TYPE_VALUE  *QuestionValue;\r
   CHAR16              *ConfigResp;\r
   CHAR16              *Progress;\r
@@ -1590,8 +1669,10 @@ SetQuestionValue (
   CHAR16              *TemName;\r
   CHAR16              *TemString;\r
   UINTN               Index;\r
+  NAME_VALUE_NODE     *Node;\r
 \r
   Status = EFI_SUCCESS;\r
+  Node   = NULL;\r
 \r
   if (SetValueTo >= GetSetValueWithMax) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -1726,6 +1807,14 @@ SetQuestionValue (
         //     \r
         CopyMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
       }\r
+      //\r
+      // Check whether question value has been changed.\r
+      //\r
+      if (CompareMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth) != 0) {\r
+        Question->ValueChanged = TRUE;\r
+      } else {\r
+        Question->ValueChanged = FALSE;\r
+      }\r
     } else {\r
       if (IsString) {\r
         //\r
@@ -1757,8 +1846,19 @@ SetQuestionValue (
         }\r
       }\r
 \r
-      Status = SetValueByName (Storage, Question->VariableName, Value, SetValueTo);\r
+      Status = SetValueByName (Storage, Question->VariableName, Value, SetValueTo, &Node);\r
       FreePool (Value);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      //\r
+      // Check whether question value has been changed.\r
+      //\r
+      if (StrCmp (Node->Value, Node->EditValue) != 0) {\r
+        Question->ValueChanged = TRUE;\r
+      } else {\r
+        Question->ValueChanged = FALSE;\r
+      }\r
     }\r
   } else if (SetValueTo == GetSetValueWithHiiDriver) {\r
     if (Storage->Type == EFI_HII_VARSTORE_BUFFER || Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
@@ -1877,12 +1977,12 @@ SetQuestionValue (
 \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
@@ -1900,12 +2000,9 @@ ValidateQuestion (
   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
+  if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {\r
     ListHead = &Question->NoSubmitListHead;\r
   } else {\r
     return EFI_UNSUPPORTED;\r
@@ -1929,10 +2026,10 @@ ValidateQuestion (
       //\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 (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {\r
+          gBrowserStatus = BROWSER_NO_SUBMIT_IF;\r
+          gErrorInfo     = PopUp;\r
+        }\r
       }\r
 \r
       return EFI_NOT_READY;\r
@@ -1996,7 +2093,8 @@ NoSubmitCheck (
   Fill storage's edit copy with settings requested from Configuration Driver.\r
 \r
   @param  FormSet                FormSet data structure.\r
-  @param  ConfigInfo             The config info related to this form.\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
@@ -2006,10 +2104,11 @@ NoSubmitCheck (
 \r
 **/\r
 EFI_STATUS\r
-SynchronizeStorageForForm (\r
-  IN FORM_BROWSER_FORMSET        *FormSet,\r
-  IN FORM_BROWSER_CONFIG_REQUEST *ConfigInfo,\r
-  IN BOOLEAN                     SyncOrRestore\r
+SynchronizeStorage (\r
+  IN  FORM_BROWSER_FORMSET        *FormSet,\r
+  OUT BROWSER_STORAGE             *Storage,\r
+  IN  CHAR16                      *ConfigRequest,\r
+  IN  BOOLEAN                     SyncOrRestore\r
   )\r
 {\r
   EFI_STATUS              Status;\r
@@ -2023,57 +2122,52 @@ SynchronizeStorageForForm (
 \r
   Status = EFI_SUCCESS;\r
   Result = NULL;\r
-  if (FormSet->ConfigAccess == NULL && ConfigInfo->Storage->Type != EFI_HII_VARSTORE_NAME_VALUE) {\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
-  if (ConfigInfo->ElementCount == 0) {\r
-    //\r
-    // Skip if there is no RequestElement\r
-    //\r
-    return EFI_SUCCESS;\r
-  }\r
 \r
-  if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
-      (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
-    BufferSize = ConfigInfo->Storage->Size;\r
+  if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
+      (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
+    BufferSize = Storage->Size;\r
 \r
     if (SyncOrRestore) {\r
-      Src = ConfigInfo->Storage->EditBuffer;\r
-      Dst = ConfigInfo->Storage->Buffer;\r
+      Src = Storage->EditBuffer;\r
+      Dst = Storage->Buffer;\r
     } else {\r
-      Src = ConfigInfo->Storage->Buffer;\r
-      Dst = ConfigInfo->Storage->EditBuffer;\r
+      Src = Storage->Buffer;\r
+      Dst = Storage->EditBuffer;\r
     }\r
 \r
-    Status = mHiiConfigRouting->BlockToConfig(\r
-                                  mHiiConfigRouting,\r
-                                  ConfigInfo->ConfigRequest,\r
-                                  Src,\r
-                                  BufferSize,\r
-                                  &Result,\r
-                                  &Progress\r
-                                  );\r
-    if (EFI_ERROR (Status)) {\r
-      return Status;\r
-    }\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
-    Status = mHiiConfigRouting->ConfigToBlock (\r
-                                  mHiiConfigRouting,\r
-                                  Result,\r
-                                  Dst,\r
-                                  &BufferSize,\r
-                                  &Progress\r
-                                  );\r
-    if (Result != NULL) {\r
-      FreePool (Result);\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 (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
-    Link = GetFirstNode (&ConfigInfo->Storage->NameValueListHead);\r
-    while (!IsNull (&ConfigInfo->Storage->NameValueListHead, Link)) {\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
-      if (StrStr (ConfigInfo->ConfigRequest, Node->Name) != NULL) {\r
+      if ((ConfigRequest != NULL && StrStr (ConfigRequest, Node->Name) != NULL) ||\r
+          (ConfigRequest == NULL)) {\r
         if (SyncOrRestore) {\r
           NewStringCpy (&Node->Value, Node->EditValue);\r
         } else {\r
@@ -2081,7 +2175,7 @@ SynchronizeStorageForForm (
         }\r
       }\r
 \r
-      Link = GetNextNode (&ConfigInfo->Storage->NameValueListHead, Link);\r
+      Link = GetNextNode (&Storage->NameValueListHead, Link);\r
     }\r
   }\r
 \r
@@ -2104,20 +2198,9 @@ SendDiscardInfoToDriver (
 {\r
   LIST_ENTRY                  *Link;\r
   FORM_BROWSER_STATEMENT      *Question;\r
-  EFI_STATUS                  Status;\r
-  EFI_HII_VALUE               HiiValue;\r
-  UINT8                       *BufferValue;\r
-  BOOLEAN                     ValueChanged;\r
   EFI_IFR_TYPE_VALUE          *TypeValue;\r
   EFI_BROWSER_ACTION_REQUEST  ActionRequest;\r
 \r
-  ValueChanged = FALSE;\r
-  BufferValue  = NULL;\r
-\r
-  if(!Form->NvUpdateRequired) {\r
-    return;\r
-  }\r
-\r
   Link = GetFirstNode (&Form->StatementListHead);\r
   while (!IsNull (&Form->StatementListHead, Link)) {\r
     Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
@@ -2131,45 +2214,10 @@ SendDiscardInfoToDriver (
       continue;\r
     }\r
 \r
-    if (Question->BufferValue != NULL) {\r
-      BufferValue = AllocateZeroPool (Question->StorageWidth);\r
-      ASSERT (BufferValue != NULL);\r
-      CopyMem (BufferValue, Question->BufferValue, Question->StorageWidth);\r
-    } else {\r
-      HiiValue.Type = Question->HiiValue.Type;\r
-      CopyMem (&HiiValue.Value, &Question->HiiValue.Value, sizeof (EFI_IFR_TYPE_VALUE));\r
-    }\r
-\r
-    Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);\r
-    if (EFI_ERROR (Status)) {\r
-      if (BufferValue != NULL) {\r
-        FreePool (BufferValue);\r
-        BufferValue = NULL;\r
-      }\r
-      continue;\r
-    }\r
-\r
-    if (Question->BufferValue != NULL) {\r
-      if (CompareMem (BufferValue, Question->BufferValue, Question->StorageWidth)) {\r
-        ValueChanged = TRUE;\r
-      }\r
-    } else {\r
-      if (CompareMem (&HiiValue.Value, &Question->HiiValue.Value, sizeof (EFI_IFR_TYPE_VALUE))) {\r
-        ValueChanged = TRUE;\r
-      }\r
-    }\r
-\r
-    if (BufferValue != NULL) {\r
-      FreePool (BufferValue);\r
-      BufferValue = NULL;\r
-    }\r
-\r
-    if (!ValueChanged) {\r
+    if (!Question->ValueChanged) {\r
       continue;\r
     }\r
 \r
-    ValueChanged = FALSE;\r
-\r
     if (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER) {\r
       TypeValue = (EFI_IFR_TYPE_VALUE *) Question->BufferValue;\r
     } else {\r
@@ -2225,6 +2273,7 @@ ValidateFormSet (
   }\r
 \r
   if (!Find) {\r
+    CleanBrowserStorage(FormSet);\r
     RemoveEntryList (&FormSet->Link);\r
     DestroyFormSet (FormSet);\r
   }\r
@@ -2233,13 +2282,85 @@ ValidateFormSet (
 \r
   return Find;\r
 }\r
-\r
 /**\r
-  Discard data based on the input setting scope (Form, FormSet or System).\r
+  Check whether need to enable the reset flag in form level.\r
+  Also clean all ValueChanged flag in question.\r
 \r
-  @param  FormSet                FormSet data structure.\r
+  @param  SetFlag                Whether need to set the Reset Flag.\r
   @param  Form                   Form data structure.\r
-  @param  SettingScope           Setting Scope for Discard action.\r
+\r
+**/\r
+VOID\r
+UpdateFlagForForm (\r
+  IN BOOLEAN                          SetFlag,\r
+  IN FORM_BROWSER_FORM                *Form\r
+  )\r
+{\r
+  LIST_ENTRY              *Link;\r
+  FORM_BROWSER_STATEMENT  *Question;\r
+  BOOLEAN                 FindOne;\r
+\r
+  FindOne = FALSE;\r
+  Link = GetFirstNode (&Form->StatementListHead);\r
+  while (!IsNull (&Form->StatementListHead, Link)) {\r
+    Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+  \r
+    if (SetFlag && Question->ValueChanged && ((Question->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) != 0)) {\r
+      gResetRequired = TRUE;\r
+    } \r
+\r
+    if (Question->ValueChanged) {\r
+      Question->ValueChanged = FALSE;\r
+    }\r
+  \r
+    Link = GetNextNode (&Form->StatementListHead, Link);\r
+  }\r
+}\r
+\r
+/**\r
+  Check whether need to enable the reset flag.\r
+  Also clean ValueChanged flag for all statements.\r
+\r
+  Form level or formset level, only one.\r
+  \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
+VOID\r
+ValueChangeResetFlagUpdate (\r
+  IN BOOLEAN                          SetFlag,\r
+  IN FORM_BROWSER_FORMSET             *FormSet,\r
+  IN FORM_BROWSER_FORM                *Form  \r
+  )\r
+{\r
+  FORM_BROWSER_FORM       *CurrentForm;\r
+  LIST_ENTRY              *Link;\r
+\r
+  //\r
+  // Form != NULL means only check form level.\r
+  //\r
+  if (Form != NULL) {\r
+    UpdateFlagForForm(SetFlag, Form);\r
+    return;\r
+  }\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
+    UpdateFlagForForm(SetFlag, CurrentForm);\r
+  }\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
@@ -2264,7 +2385,7 @@ DiscardForm (
     return EFI_UNSUPPORTED;\r
   }\r
 \r
-  if (SettingScope == FormLevel && Form->NvUpdateRequired) {\r
+  if (SettingScope == FormLevel && IsNvUpdateRequiredForForm (Form)) {\r
     ConfigInfo = NULL;\r
     Link = GetFirstNode (&Form->ConfigRequestHead);\r
     while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
@@ -2285,7 +2406,7 @@ DiscardForm (
       //\r
       // Prepare <ConfigResp>\r
       //\r
-      SynchronizeStorageForForm(FormSet, ConfigInfo, FALSE);\r
+      SynchronizeStorage(FormSet, ConfigInfo->Storage, ConfigInfo->ConfigRequest, FALSE);\r
 \r
       //\r
       // Call callback with Changed type to inform the driver.\r
@@ -2293,8 +2414,8 @@ DiscardForm (
       SendDiscardInfoToDriver (FormSet, Form);\r
     }\r
 \r
-    Form->NvUpdateRequired = FALSE;\r
-  } else if (SettingScope == FormSetLevel && IsNvUpdateRequired(FormSet)) {\r
+    ValueChangeResetFlagUpdate (FALSE, NULL, Form);\r
+  } else if (SettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet (FormSet)) {\r
 \r
     //\r
     // Discard Buffer storage or Name/Value storage\r
@@ -2304,7 +2425,7 @@ DiscardForm (
       Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
       Link = GetNextNode (&FormSet->StorageListHead, Link);\r
 \r
-      if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+      if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
         continue;\r
       }\r
 \r
@@ -2315,7 +2436,7 @@ DiscardForm (
         continue;\r
       }\r
 \r
-      SynchronizeStorage(Storage, FALSE);\r
+      SynchronizeStorage(FormSet, Storage->BrowserStorage, Storage->ConfigRequest, FALSE);\r
     }\r
 \r
     Link = GetFirstNode (&FormSet->FormListHead);\r
@@ -2329,7 +2450,7 @@ DiscardForm (
       SendDiscardInfoToDriver (FormSet, Form);\r
     }\r
 \r
-    UpdateNvInfoInForm (FormSet, FALSE);   \r
+    ValueChangeResetFlagUpdate(FALSE, FormSet, NULL);\r
   } else if (SettingScope == SystemLevel) {\r
     //\r
     // System Level Discard.\r
@@ -2350,6 +2471,7 @@ DiscardForm (
         //\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
@@ -2381,7 +2503,8 @@ SubmitForm (
   LIST_ENTRY              *Link;\r
   EFI_STRING              ConfigResp;\r
   EFI_STRING              Progress;\r
-  FORMSET_STORAGE         *Storage;\r
+  BROWSER_STORAGE         *Storage;\r
+  FORMSET_STORAGE         *FormSetStorage;\r
   UINTN                   BufferSize;\r
   UINT8                   *TmpBuf;  \r
   FORM_BROWSER_FORMSET    *LocalFormSet;\r
@@ -2407,7 +2530,7 @@ SubmitForm (
     return Status;\r
   }\r
 \r
-  if (SettingScope == FormLevel && Form->NvUpdateRequired) {\r
+  if (SettingScope == FormLevel && IsNvUpdateRequiredForForm (Form)) {\r
     ConfigInfo = NULL;\r
     Link = GetFirstNode (&Form->ConfigRequestHead);\r
     while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
@@ -2429,7 +2552,7 @@ SubmitForm (
       //\r
       // 1. Prepare <ConfigResp>\r
       //\r
-      Status = StorageToConfigResp (ConfigInfo, &ConfigResp, TRUE);\r
+      Status = StorageToConfigResp (ConfigInfo->Storage, &ConfigResp, ConfigInfo->ConfigRequest, TRUE);\r
       if (EFI_ERROR (Status)) {\r
         return Status;\r
       }\r
@@ -2505,20 +2628,21 @@ SubmitForm (
       //\r
       // 3. Config success, update storage shadow Buffer, only update the data belong to this form.\r
       //\r
-      SynchronizeStorageForForm(FormSet, ConfigInfo, TRUE);\r
+      SynchronizeStorage (FormSet, ConfigInfo->Storage, ConfigInfo->ConfigRequest, TRUE);\r
     }\r
 \r
     //\r
     // 4. Update the NV flag.\r
     // \r
-    Form->NvUpdateRequired = FALSE;\r
-  } else if (SettingScope == FormSetLevel && IsNvUpdateRequired(FormSet)) {\r
+    ValueChangeResetFlagUpdate(TRUE, NULL, Form);\r
+  } else if (SettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet (FormSet)) {\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
+      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
@@ -2528,14 +2652,14 @@ SubmitForm (
       //\r
       // Skip if there is no RequestElement\r
       //\r
-      if (Storage->ElementCount == 0) {\r
+      if (FormSetStorage->ElementCount == 0) {\r
         continue;\r
       }\r
 \r
       //\r
       // 1. Prepare <ConfigResp>\r
       //\r
-      Status = StorageToConfigResp (Storage, &ConfigResp, FALSE);\r
+      Status = StorageToConfigResp (Storage, &ConfigResp, FormSetStorage->ConfigRequest, TRUE);\r
       if (EFI_ERROR (Status)) {\r
         return Status;\r
       }\r
@@ -2607,13 +2731,13 @@ SubmitForm (
       //\r
       // 3. Config success, update storage shadow Buffer\r
       //\r
-      SynchronizeStorage (Storage, TRUE);\r
+      SynchronizeStorage (FormSet, Storage, FormSetStorage->ConfigRequest, TRUE);\r
     }\r
 \r
     //\r
     // 4. Update the NV flag.\r
     // \r
-    UpdateNvInfoInForm (FormSet, FALSE);\r
+    ValueChangeResetFlagUpdate(TRUE, FormSet, NULL);\r
   } else if (SettingScope == SystemLevel) {\r
     //\r
     // System Level Save.\r
@@ -2634,6 +2758,7 @@ SubmitForm (
         //\r
         // Remove maintain backup list after save except for the current using FormSet.\r
         //\r
+        CleanBrowserStorage(LocalFormSet);\r
         RemoveEntryList (&LocalFormSet->Link);\r
         DestroyFormSet (LocalFormSet);\r
       }\r
@@ -2663,7 +2788,7 @@ GetDefaultValueFromAltCfg (
   BOOLEAN             IsBufferStorage;\r
   BOOLEAN             IsString;  \r
   UINTN               Length;\r
-  FORMSET_STORAGE     *Storage;\r
+  BROWSER_STORAGE     *Storage;\r
   CHAR16              *ConfigRequest;\r
   CHAR16              *Progress;\r
   CHAR16              *Result;\r
@@ -2868,6 +2993,138 @@ GetDefaultIdForCallBack (
   }\r
 }\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
+/**\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
+\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
+        return Option;\r
+      }\r
+    }\r
+\r
+    Link = GetNextNode (&Question->OptionListHead, Link);\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+\r
 /**\r
   Reset Question to its default value.\r
 \r
@@ -3151,7 +3408,7 @@ ExtractDefault (
   IN UINT16                           DefaultId,\r
   IN BROWSER_SETTING_SCOPE            SettingScope,\r
   IN BROWSER_GET_DEFAULT_VALUE        GetDefaultValueScope,\r
-  IN FORMSET_STORAGE                  *Storage OPTIONAL,\r
+  IN BROWSER_STORAGE                  *Storage OPTIONAL,\r
   IN BOOLEAN                          RetrieveValueFirst\r
   )\r
 {\r
@@ -3159,11 +3416,7 @@ ExtractDefault (
   LIST_ENTRY              *FormLink;\r
   LIST_ENTRY              *Link;\r
   FORM_BROWSER_STATEMENT  *Question;\r
-  FORM_BROWSER_FORMSET    *BackUpFormSet;\r
   FORM_BROWSER_FORMSET    *LocalFormSet;\r
-  EFI_HII_HANDLE          *HiiHandles;\r
-  UINTN                   Index;\r
-  EFI_GUID                ZeroGuid;\r
 \r
   Status = EFI_SUCCESS;\r
 \r
@@ -3233,10 +3486,6 @@ ExtractDefault (
       if ((Question->Storage != NULL) &&\r
           (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
         SetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
-        //\r
-        // Update Form NV flag.\r
-        //\r
-        Form->NvUpdateRequired = TRUE;\r
       }\r
     }\r
   } else if (SettingScope == FormSetLevel) {\r
@@ -3248,65 +3497,9 @@ ExtractDefault (
     }\r
   } else if (SettingScope == SystemLevel) {\r
     //\r
-    // Open all FormSet by locate HII packages.\r
-    // Initiliaze the maintain FormSet to store default data as back up data.\r
-    //\r
-    BackUpFormSet    = gOldFormSet;\r
-    gOldFormSet      = NULL;\r
-\r
-    //\r
-    // Get all the Hii handles\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
-      ZeroMem (&ZeroGuid, sizeof (ZeroGuid));\r
-      Status = InitializeFormSet (HiiHandles[Index], &ZeroGuid, LocalFormSet, FALSE);\r
-      if (EFI_ERROR (Status) || IsListEmpty (&LocalFormSet->FormListHead)) {\r
-        DestroyFormSet (LocalFormSet);\r
-        continue;\r
-      }\r
-      Status = InitializeCurrentSetting (LocalFormSet);\r
-      if (EFI_ERROR (Status)) {\r
-        DestroyFormSet (LocalFormSet);\r
-        continue;\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
-      // Add FormSet into the maintain list.\r
-      //\r
-      InsertTailList (&gBrowserFormSetList, &LocalFormSet->Link);\r
-    }\r
-    \r
-    //\r
-    // Free resources, and restore gOldFormSet and gClassOfVfr\r
+    // Preload all Hii formset.\r
     //\r
-    FreePool (HiiHandles);\r
-    gOldFormSet = BackUpFormSet;\r
+    LoadAllHiiFormset();\r
        \r
     //\r
     // Set Default Value for each FormSet in the maintain list.\r
@@ -3325,6 +3518,81 @@ ExtractDefault (
   return EFI_SUCCESS;\r
 }\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_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
+  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
+  CopyMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE));\r
+\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
+    ValueChanged = TRUE;\r
+  }\r
+\r
+  CopyMem (&Question->HiiValue, &BackUpValue, sizeof (EFI_HII_VALUE));\r
+  CopyMem (Question->BufferValue, BackUpBuffer, BufferWidth);\r
+\r
+  if (BackUpBuffer != NULL) {\r
+    FreePool (BackUpBuffer);\r
+  }\r
+\r
+  return ValueChanged;\r
+}\r
+\r
 /**\r
   Initialize Question's Edit copy from Storage.\r
 \r
@@ -3358,7 +3626,11 @@ LoadFormConfig (
     //\r
     // Initialize local copy of Value for each Question\r
     //\r
-    Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\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
     if (EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
@@ -3398,6 +3670,11 @@ LoadFormConfig (
       Status = ProcessCallBackFunction(Selection, Question, EFI_BROWSER_ACTION_RETRIEVE, TRUE);\r
     }\r
 \r
+    //\r
+    // Update Question Value changed flag.\r
+    //\r
+    Question->ValueChanged = IsQuestionValueChanged(FormSet, Form, Question, GetSetValueWithBuffer);\r
+\r
     Link = GetNextNode (&Form->StatementListHead, Link);\r
   }\r
 \r
@@ -3441,203 +3718,596 @@ LoadFormSetConfig (
     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
-  Fill storage's edit copy with settings requested from Configuration Driver.\r
+  Remove the Request element from the Config Request.\r
 \r
-  @param  FormSet                FormSet data structure.\r
-  @param  Storage                Buffer Storage.\r
+  @param  Storage                Pointer to the browser storage.\r
+  @param  RequestElement         The pointer to the Request element.\r
 \r
-  @retval EFI_SUCCESS            The function completed successfully.\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 browser storage.\r
+  @param  ConfigRequest          The pointer to the Request element.\r
 \r
 **/\r
-EFI_STATUS\r
-LoadStorage (\r
-  IN FORM_BROWSER_FORMSET    *FormSet,\r
-  IN FORMSET_STORAGE         *Storage\r
+VOID\r
+RemoveConfigRequest (\r
+  BROWSER_STORAGE   *Storage,\r
+  CHAR16            *ConfigRequest\r
   )\r
 {\r
-  EFI_STATUS  Status;\r
-  EFI_STRING  Progress;\r
-  EFI_STRING  Result;\r
-  CHAR16      *StrPtr;\r
+  CHAR16       *RequestElement;\r
+  CHAR16       *NextRequestElement;\r
+  CHAR16       *SearchKey;\r
 \r
-  if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
-    return EFI_SUCCESS;\r
+  //\r
+  // No request element in it, just return.\r
+  //\r
+  if (ConfigRequest == NULL) {\r
+    return;\r
   }\r
 \r
-  if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
-    Status = gRT->GetVariable (\r
-                     Storage->Name,\r
-                     &Storage->Guid,\r
-                     NULL,\r
-                     (UINTN*)&Storage->Size,\r
-                     Storage->EditBuffer\r
-                     );\r
-    return Status;\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
   }\r
 \r
-  if (FormSet->ConfigAccess == NULL) {\r
-    return EFI_NOT_FOUND;\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
-  if (Storage->ElementCount == 0) {\r
+  while (RequestElement != NULL) {\r
     //\r
-    // Skip if there is no RequestElement\r
+    // +1 to avoid find header itself.\r
     //\r
-    return EFI_SUCCESS;\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, 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
-  // Request current settings from Configuration Driver\r
+  // If no request element remain, just remove the ConfigRequest string.\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
+  if (StrCmp (Storage->ConfigRequest, Storage->ConfigHdr) == 0) {\r
+    FreePool (Storage->ConfigRequest);\r
+    Storage->ConfigRequest = NULL;\r
+    Storage->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
+  CHAR16                *ConfigRequest;\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_BUFFER) && \r
+        (Storage->BrowserStorage->Type != EFI_HII_VARSTORE_NAME_VALUE) && \r
+        (Storage->BrowserStorage->Type != EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
+      continue;\r
+    }\r
+\r
+    if (Storage->ConfigRequest == NULL || Storage->BrowserStorage->ConfigRequest == NULL) {\r
+      continue;\r
+    }\r
+\r
+    ConfigRequest = FormSet->QuestionInited ? Storage->ConfigRequest : Storage->ConfigElements;\r
+    RemoveConfigRequest (Storage->BrowserStorage, ConfigRequest);\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
+\r
+  StrLength = StrLen (RequestElement);\r
 \r
   //\r
-  // Convert Result from <ConfigAltResp> to <ConfigResp>\r
+  // Append <RequestElement> to <ConfigRequest>\r
   //\r
-  StrPtr = StrStr (Result, L"&GUID=");\r
-  if (StrPtr != NULL) {\r
-    *StrPtr = L'\0';\r
+  if (StrLength > *SpareStrLen) {\r
+    //\r
+    // Old String buffer is not sufficient for RequestElement, allocate a new one\r
+    //\r
+    StringSize = (*ConfigRequest != NULL) ? StrSize (*ConfigRequest) : sizeof (CHAR16);\r
+    NewStr = AllocateZeroPool (StringSize + CONFIG_REQUEST_STRING_INCREMENTAL * sizeof (CHAR16));\r
+    ASSERT (NewStr != NULL);\r
+\r
+    if (*ConfigRequest != NULL) {\r
+      CopyMem (NewStr, *ConfigRequest, StringSize);\r
+      FreePool (*ConfigRequest);\r
+    }\r
+    *ConfigRequest = NewStr;\r
+    *SpareStrLen   = CONFIG_REQUEST_STRING_INCREMENTAL;\r
   }\r
 \r
-  Status = ConfigRespToStorage (Storage, Result);\r
-  FreePool (Result);\r
-  return Status;\r
+  StrCat (*ConfigRequest, RequestElement);\r
+  *SpareStrLen -= StrLength;\r
 }\r
 \r
-\r
 /**\r
-  Copy uncommitted data from source Storage to destination Storage.\r
+  Adjust the config request info, remove the request elements which already in AllConfigRequest string.\r
 \r
-  @param  Dst                    Target Storage for uncommitted data.\r
-  @param  Src                    Source Storage for uncommitted data.\r
+  @param  Storage                Form set Storage.\r
 \r
-  @retval EFI_SUCCESS            The function completed successfully.\r
-  @retval EFI_INVALID_PARAMETER  Source and destination Storage is not the same type.\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
-EFI_STATUS\r
-CopyStorage (\r
-  IN OUT FORMSET_STORAGE     *Dst,\r
-  IN FORMSET_STORAGE         *Src\r
+BOOLEAN \r
+ConfigRequestAdjust (\r
+  IN  FORMSET_STORAGE         *Storage\r
   )\r
 {\r
-  LIST_ENTRY          *Link;\r
-  NAME_VALUE_NODE     *Node;\r
+  CHAR16       *RequestElement;\r
+  CHAR16       *NextRequestElement;\r
+  CHAR16       *RetBuf;\r
+  UINTN        SpareBufLen;\r
+  CHAR16       *SearchKey;\r
+  BOOLEAN      RetVal;\r
+\r
+  SpareBufLen    = 0;\r
+  RetBuf         = NULL;\r
+  RetVal         = FALSE;\r
+\r
+  if (Storage->BrowserStorage->ConfigRequest == NULL) {\r
+    Storage->BrowserStorage->ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigRequest), Storage->ConfigRequest);\r
+    if (Storage->ConfigElements != NULL) {\r
+      FreePool (Storage->ConfigElements);\r
+    }\r
+    Storage->ConfigElements = AllocateCopyPool (StrSize (Storage->ConfigRequest), Storage->ConfigRequest);\r
+    return TRUE;\r
+  }\r
 \r
-  if ((Dst->Type != Src->Type) || (Dst->Size != Src->Size)) {\r
-    return EFI_INVALID_PARAMETER;\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
-  switch (Src->Type) {\r
-  case EFI_HII_VARSTORE_BUFFER:\r
-  case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
-    CopyMem (Dst->EditBuffer, Src->EditBuffer, Src->Size);\r
-    CopyMem (Dst->Buffer, Src->Buffer, Src->Size);\r
-    break;\r
+  //\r
+  // Prepare the config header.\r
+  // \r
+  RetBuf = AllocateCopyPool(StrSize (Storage->BrowserStorage->ConfigHdr), Storage->BrowserStorage->ConfigHdr);\r
+  ASSERT (RetBuf != NULL);\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
+  //\r
+  // Find SearchKey storage\r
+  //\r
+  if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+    RequestElement = StrStr (Storage->ConfigRequest, L"PATH");\r
+    ASSERT (RequestElement != NULL);\r
+    RequestElement = StrStr (RequestElement, SearchKey);    \r
+  } else {\r
+    RequestElement = StrStr (Storage->ConfigRequest, SearchKey);\r
+  }\r
 \r
-      SetValueByName (Dst, Node->Name, Node->EditValue, GetSetValueWithEditBuffer);\r
-      SetValueByName (Dst, Node->Name, Node->Value, GetSetValueWithBuffer);\r
+  while (RequestElement != NULL) {\r
+    //\r
+    // +1 to avoid find header itself.\r
+    //\r
+    NextRequestElement = StrStr (RequestElement + 1, SearchKey);\r
 \r
-      Link = GetNextNode (&Src->NameValueListHead, Link);\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
+    if (!ElementValidation (Storage->BrowserStorage, RequestElement)) {\r
+      //\r
+      // Add this element to the Storage->BrowserStorage->AllRequestElement.\r
+      //\r
+      AppendConfigRequest(&Storage->BrowserStorage->ConfigRequest, &Storage->BrowserStorage->SpareStrLen, RequestElement);\r
+      AppendConfigRequest (&RetBuf, &SpareBufLen, RequestElement);\r
+      RetVal = TRUE;\r
     }\r
-    break;\r
 \r
-  case EFI_HII_VARSTORE_EFI_VARIABLE:\r
-  default:\r
-    break;\r
+    if (NextRequestElement != NULL) {\r
+      //\r
+      // Restore '&' with '\0' for later used.\r
+      //\r
+      *NextRequestElement = L'&';\r
+    }\r
+\r
+    RequestElement = NextRequestElement;\r
   }\r
 \r
-  return EFI_SUCCESS;\r
+  if (RetVal) {\r
+    if (Storage->ConfigElements != NULL) {\r
+      FreePool (Storage->ConfigElements);\r
+    }\r
+    Storage->ConfigElements = RetBuf;\r
+  } else {\r
+    FreePool (RetBuf);\r
+  }\r
+\r
+  return RetVal;\r
 }\r
 \r
 /**\r
-  Get old question value from the saved formset.\r
 \r
-  @param  Statement              The question which need to get old question value.\r
-  @param  OldFormSet             FormSet data structure saved in the list.\r
+  Base on ConfigRequest info to get default value for current formset. \r
+\r
+  ConfigRequest info include the info about which questions in current formset need to \r
+  get default value. This function only get these questions default value.\r
+  \r
+  @param  FormSet                FormSet data structure.\r
+  @param  Storage                Storage need to update value.\r
+  @param  ConfigRequest          The config request string.\r
 \r
 **/\r
-VOID \r
-GetOldQuestionValue (\r
-  IN OUT FORM_BROWSER_STATEMENT  *Statement,\r
-  IN     FORM_BROWSER_FORMSET    *OldFormSet\r
+VOID\r
+GetDefaultForFormset (\r
+  IN FORM_BROWSER_FORMSET    *FormSet,\r
+  IN BROWSER_STORAGE         *Storage,\r
+  IN CHAR16                  *ConfigRequest\r
   )\r
 {\r
-  LIST_ENTRY              *FormLink;\r
-  LIST_ENTRY              *Link;\r
-  FORM_BROWSER_STATEMENT  *Question;\r
-  FORM_BROWSER_FORM       *Form;\r
+  UINT8             *BackUpBuf;\r
+  UINTN             BufferSize;\r
+  LIST_ENTRY        BackUpList;\r
+  NAME_VALUE_NODE   *Node;\r
+  LIST_ENTRY        *Link;\r
+  LIST_ENTRY        *NodeLink;\r
+  NAME_VALUE_NODE   *TmpNode;\r
+  EFI_STATUS        Status;\r
+  EFI_STRING        Progress;\r
+  EFI_STRING        Result;\r
+\r
+  BackUpBuf = NULL;\r
+  InitializeListHead(&BackUpList);\r
+\r
+  //\r
+  // Back update the edit buffer.\r
+  // \r
+  if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
+      (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
+    BackUpBuf = AllocateCopyPool (Storage->Size, Storage->EditBuffer);\r
+    ASSERT (BackUpBuf != NULL);\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
+      Link = GetNextNode (&Storage->NameValueListHead, Link);\r
 \r
-  FormLink = GetFirstNode (&OldFormSet->FormListHead);\r
-  while (!IsNull (&OldFormSet->FormListHead, FormLink)) {\r
-    Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);\r
-    FormLink = GetNextNode (&OldFormSet->FormListHead, FormLink);\r
+      //\r
+      // Only back Node belong to this formset.\r
+      //\r
+      if (StrStr (Storage->ConfigRequest, Node->Name) == NULL) {\r
+        continue;\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
+      TmpNode = AllocateCopyPool (sizeof (NAME_VALUE_NODE), Node);\r
+      TmpNode->Name = AllocateCopyPool (StrSize(Node->Name) * sizeof (CHAR16), Node->Name);\r
+      TmpNode->EditValue = AllocateCopyPool (StrSize(Node->EditValue) * sizeof (CHAR16), Node->EditValue);\r
+\r
+      InsertTailList(&BackUpList, &TmpNode->Link);\r
+    }\r
+  }\r
+\r
+  //\r
+  // Get default value.\r
+  //\r
+  ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForStorage, Storage, TRUE);\r
 \r
-      if (Question->QuestionId != Statement->QuestionId) {\r
+  //\r
+  // Update the question value based on the input ConfigRequest.\r
+  //\r
+  if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
+      (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
+    ASSERT (BackUpBuf != NULL);\r
+    BufferSize = Storage->Size;\r
+    Status = mHiiConfigRouting->BlockToConfig(\r
+                                  mHiiConfigRouting,\r
+                                  ConfigRequest,\r
+                                  Storage->EditBuffer,\r
+                                  BufferSize,\r
+                                  &Result,\r
+                                  &Progress\r
+                                  );\r
+    ASSERT_EFI_ERROR (Status);\r
+    \r
+    Status = mHiiConfigRouting->ConfigToBlock (\r
+                                  mHiiConfigRouting,\r
+                                  Result,\r
+                                  BackUpBuf,\r
+                                  &BufferSize,\r
+                                  &Progress\r
+                                  );\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    if (Result != NULL) {\r
+      FreePool (Result);\r
+    }\r
+    \r
+    CopyMem (Storage->EditBuffer, BackUpBuf, Storage->Size);\r
+    FreePool (BackUpBuf);\r
+  } else if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+    //\r
+    // Update question value, only element in ConfigReqeust will be update.\r
+    //\r
+    Link = GetFirstNode (&BackUpList);\r
+    while (!IsNull (&BackUpList, Link)) {\r
+      Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
+      Link = GetNextNode (&BackUpList, Link);\r
+\r
+      if (StrStr (ConfigRequest, Node->Name) != NULL) {\r
         continue;\r
       }\r
 \r
-      CopyMem (&Statement->HiiValue, &Question->HiiValue, sizeof (EFI_HII_VALUE));\r
-      return;\r
-    }\r
-  }\r
-}\r
+      NodeLink = GetFirstNode (&Storage->NameValueListHead);\r
+      while (!IsNull (&Storage->NameValueListHead, NodeLink)) {\r
+        TmpNode  = NAME_VALUE_NODE_FROM_LINK (NodeLink);\r
+        NodeLink = GetNextNode (&Storage->NameValueListHead, NodeLink);\r
+      \r
+        if (StrCmp (Node->Name, TmpNode->Name) != 0) {\r
+          continue;\r
+        }\r
+\r
+        FreePool (TmpNode->EditValue);\r
+        TmpNode->EditValue = AllocateCopyPool (StrSize(Node->EditValue) * sizeof (CHAR16), Node->EditValue);\r
+\r
+        RemoveEntryList (&Node->Link);\r
+        FreePool (Node->EditValue);\r
+        FreePool (Node->Name);\r
+        FreePool (Node);\r
+      }\r
+    }\r
+\r
+    //\r
+    // Restore the Name/Value node.\r
+    //  \r
+    Link = GetFirstNode (&BackUpList);\r
+    while (!IsNull (&BackUpList, Link)) {\r
+      Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
+      Link = GetNextNode (&BackUpList, Link);\r
\r
+      //\r
+      // Free this node.\r
+      //\r
+      RemoveEntryList (&Node->Link);\r
+      FreePool (Node->EditValue);\r
+      FreePool (Node->Name);\r
+      FreePool (Node);\r
+    }\r
+  }\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
+\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->ReferenceCount > 1) {\r
+        ConfigRequestAdjust(Storage);\r
+        return;\r
+      }\r
+\r
+      Status = gRT->GetVariable (\r
+                       Storage->BrowserStorage->Name,\r
+                       &Storage->BrowserStorage->Guid,\r
+                       NULL,\r
+                       (UINTN*)&Storage->BrowserStorage->Size,\r
+                       Storage->BrowserStorage->EditBuffer\r
+                       );\r
+      //\r
+      // If get variable 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);\r
+      }\r
+\r
+      Storage->BrowserStorage->ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigRequest), Storage->ConfigRequest);\r
+      //\r
+      // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer. \r
+      //\r
+      SynchronizeStorage(FormSet, Storage->BrowserStorage, NULL, TRUE);\r
+      break;\r
 \r
-/**\r
-  Get old question value from the saved formset, all these questions not have\r
-  storage.\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
-  @param  FormSet                FormSet data structure which is used now.\r
-  @param  OldFormSet             FormSet data structure saved in the list.\r
+      //\r
+      // Adjust the ConfigRequest string, only the field not saved in BrowserStorage->AllConfig\r
+      // will used to call ExtractConfig.\r
+      // If not elements need to udpate, return.\r
+      //\r
+      if (!ConfigRequestAdjust(Storage)) {\r
+        return;\r
+      }\r
+      ASSERT (Storage->ConfigElements != NULL);\r
 \r
-**/\r
-VOID\r
-CopyOldValueForNoStorageQst (\r
-  IN OUT FORM_BROWSER_FORMSET             *FormSet,\r
-  IN     FORM_BROWSER_FORMSET             *OldFormSet\r
-  )\r
-{\r
-  LIST_ENTRY              *FormLink;\r
-  LIST_ENTRY              *Link;\r
-  FORM_BROWSER_STATEMENT  *Question;\r
-  FORM_BROWSER_FORM       *Form;\r
+      Status = EFI_NOT_FOUND;\r
+      if (FormSet->ConfigAccess != NULL) { \r
+        //\r
+        // Request current settings from Configuration Driver\r
+        //\r
+        Status = FormSet->ConfigAccess->ExtractConfig (\r
+                                          FormSet->ConfigAccess,\r
+                                          Storage->ConfigElements,\r
+                                          &Progress,\r
+                                          &Result\r
+                                          );\r
+        \r
+        if (!EFI_ERROR (Status)) {\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
 \r
-  FormLink = GetFirstNode (&FormSet->FormListHead);\r
-  while (!IsNull (&FormSet->FormListHead, FormLink)) {\r
-    Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);\r
-    FormLink = GetNextNode (&FormSet->FormListHead, FormLink);\r
+      if (EFI_ERROR (Status)) {\r
+        //\r
+        // Base on the configRequest string to get default value.\r
+        //\r
+        GetDefaultForFormset (FormSet, Storage->BrowserStorage, Storage->ConfigElements);\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
+      SynchronizeStorage(FormSet, Storage->BrowserStorage, Storage->ConfigElements, TRUE);\r
+      break;\r
 \r
-      if (Question->Storage == NULL) {\r
-        GetOldQuestionValue (Question, OldFormSet);\r
-      }\r
-    }\r
+    default:\r
+      break;\r
   }\r
 }\r
 \r
@@ -3646,22 +4316,15 @@ CopyOldValueForNoStorageQst (
 \r
   @param  FormSet                FormSet data structure.\r
 \r
-  @retval EFI_SUCCESS            The function completed successfully.\r
-\r
 **/\r
-EFI_STATUS\r
+VOID\r
 InitializeCurrentSetting (\r
   IN OUT FORM_BROWSER_FORMSET             *FormSet\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
-  FORM_BROWSER_FORM       *Form2;\r
-  EFI_STATUS              Status;\r
+  FORM_BROWSER_FORMSET    *OldFormSet;\r
 \r
   //\r
   // Extract default from IFR binary for no storage questions.\r
@@ -3675,81 +4338,21 @@ InitializeCurrentSetting (
   while (!IsNull (&FormSet->StorageListHead, Link)) {\r
     Storage = FORMSET_STORAGE_FROM_LINK (Link);\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
-\r
-        if (StorageSrc->VarStoreId == Storage->VarStoreId) {\r
-          OldStorage = StorageSrc;\r
-          break;\r
-        }\r
-\r
-        Link2 = GetNextNode (&gOldFormSet->StorageListHead, Link2);\r
-      }\r
-    }\r
-\r
-    if (OldStorage == NULL) {\r
-      //\r
-      // Storage is not found in backup formset, request it from ConfigDriver\r
-      //\r
-      Status = LoadStorage (FormSet, Storage);\r
-\r
-      if (EFI_ERROR (Status)) {\r
-        //\r
-        // If get last time changed value failed, extract default from IFR binary\r
-        //\r
-        ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForStorage, Storage, TRUE);\r
-        //\r
-        // ExtractDefault will set the NV flag to TRUE, so need this function to clean the flag\r
-        // in current situation.\r
-        //\r
-        UpdateNvInfoInForm (FormSet, FALSE);\r
-      }\r
-\r
-      //\r
-      // Now Edit Buffer is filled with default values(lower priority) or current\r
-      // settings(higher priority), sychronize it to shadow Buffer\r
-      //\r
-      SynchronizeStorage (Storage, TRUE);\r
-    } else {\r
-      //\r
-      // Storage found in backup formset, use it\r
-      //\r
-      Status = CopyStorage (Storage, OldStorage);\r
-    }\r
+    LoadStorage (FormSet, Storage);\r
 \r
     Link = GetNextNode (&FormSet->StorageListHead, Link);\r
   }\r
 \r
   //\r
-  // If has old formset, get the old nv update status.\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
-  if (gOldFormSet != NULL) {\r
-    Link = GetFirstNode (&FormSet->FormListHead);\r
-    while (!IsNull (&FormSet->FormListHead, Link)) {\r
-      Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
-\r
-      Link2 = GetFirstNode (&gOldFormSet->FormListHead);\r
-      while (!IsNull (&gOldFormSet->FormListHead, Link2)) {\r
-        Form2 = FORM_BROWSER_FORM_FROM_LINK (Link2);\r
-\r
-        if (Form->FormId == Form2->FormId) {\r
-          Form->NvUpdateRequired = Form2->NvUpdateRequired;\r
-          break;\r
-        }\r
-\r
-        Link2 = GetNextNode (&gOldFormSet->FormListHead, Link2);\r
-      }\r
-      Link = GetNextNode (&FormSet->FormListHead, Link);\r
-    }\r
+  OldFormSet = GetFormSetFromHiiHandle (FormSet->HiiHandle);\r
+  if (OldFormSet != NULL) {\r
+    RemoveEntryList (&OldFormSet->Link);\r
+    DestroyFormSet (OldFormSet);\r
   }\r
-\r
-  return EFI_SUCCESS;\r
+  InsertTailList (&gBrowserFormSetList, &FormSet->Link);\r
 }\r
 \r
 \r
@@ -3932,7 +4535,6 @@ GetIfrBinaryData (
                                  found in package list.\r
                                  On output, GUID of the formset found(if not NULL).\r
   @param  FormSet                FormSet data structure.\r
-  @param  UpdateGlobalVar        Whether need to update the global variable.\r
 \r
   @retval EFI_SUCCESS            The function completed successfully.\r
   @retval EFI_NOT_FOUND          The specified FormSet could not be found.\r
@@ -3942,13 +4544,11 @@ EFI_STATUS
 InitializeFormSet (\r
   IN  EFI_HII_HANDLE                   Handle,\r
   IN OUT EFI_GUID                      *FormSetGuid,\r
-  OUT FORM_BROWSER_FORMSET             *FormSet,\r
-  IN  BOOLEAN                          UpdateGlobalVar                   \r
+  OUT FORM_BROWSER_FORMSET             *FormSet\r
   )\r
 {\r
   EFI_STATUS                Status;\r
   EFI_HANDLE                DriverHandle;\r
-  UINT16                    Index;\r
 \r
   Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);\r
   if (EFI_ERROR (Status)) {\r
@@ -3958,6 +4558,7 @@ InitializeFormSet (
   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
@@ -3984,55 +4585,8 @@ InitializeFormSet (
   // Parse the IFR binary OpCodes\r
   //\r
   Status = ParseOpCodes (FormSet);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  // \r
-  // If not need to update the global variable, just return.\r
-  //\r
-  if (!UpdateGlobalVar) {\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // Set VFR type by FormSet SubClass field\r
-  //\r
-  gClassOfVfr = FORMSET_CLASS_PLATFORM_SETUP;\r
-  if (FormSet->SubClass == EFI_FRONT_PAGE_SUBCLASS) {\r
-    gClassOfVfr = FORMSET_CLASS_FRONT_PAGE;\r
-  }\r
-  \r
-  //\r
-  // Set VFR type by FormSet class guid\r
-  //\r
-  for (Index = 0; Index < 3; Index ++) {\r
-    if (CompareGuid (&FormSet->ClassGuid[Index], &gEfiHiiPlatformSetupFormsetGuid)) {\r
-      gClassOfVfr |= FORMSET_CLASS_PLATFORM_SETUP;\r
-      break;\r
-    }\r
-  }\r
-\r
-  gFunctionKeySetting = ENABLE_FUNCTION_KEY_SETTING;\r
-\r
-  if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == FORMSET_CLASS_FRONT_PAGE) {\r
-    gFrontPageHandle = FormSet->HiiHandle;\r
-    gFunctionKeySetting = NONE_FUNCTION_KEY_SETTING;\r
-  }\r
-\r
-  //\r
-  // Match GUID to find out the function key setting. If match fail, use the default setting.\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
-  }\r
 \r
-  return EFI_SUCCESS;\r
+  return Status;\r
 }\r
 \r
 \r
@@ -4048,6 +4602,7 @@ SaveBrowserContext (
   )\r
 {\r
   BROWSER_CONTEXT  *Context;\r
+  FORM_ENTRY_INFO     *MenuList;\r
 \r
   gBrowserContextCount++;\r
   if (gBrowserContextCount == 1) {\r
@@ -4057,6 +4612,11 @@ SaveBrowserContext (
     return;\r
   }\r
 \r
+  //\r
+  // Not support SendForm nest in another SendForm, assert here.\r
+  //\r
+  ASSERT (FALSE);\r
+\r
   Context = AllocatePool (sizeof (BROWSER_CONTEXT));\r
   ASSERT (Context != NULL);\r
 \r
@@ -4065,47 +4625,20 @@ SaveBrowserContext (
   //\r
   // Save FormBrowser context\r
   //\r
-  Context->BannerData           = gBannerData;\r
-  Context->ClassOfVfr           = gClassOfVfr;\r
-  Context->FunctionKeySetting   = gFunctionKeySetting;\r
   Context->ResetRequired        = gResetRequired;\r
-  Context->Direction            = gDirection;\r
-  Context->EnterString          = gEnterString;\r
-  Context->EnterCommitString    = gEnterCommitString;\r
-  Context->EnterEscapeString    = gEnterEscapeString;\r
-  Context->EscapeString         = gEscapeString;\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->FormSuppress         = gFormSuppress;\r
-  Context->PromptBlockWidth     = gPromptBlockWidth;\r
-  Context->OptionBlockWidth     = gOptionBlockWidth;\r
-  Context->HelpBlockWidth       = gHelpBlockWidth;\r
-  Context->OldFormSet           = gOldFormSet;\r
-  Context->MenuRefreshHead      = gMenuRefreshHead;\r
-  Context->ProtocolNotFound     = gProtocolNotFound;\r
-\r
-  CopyMem (&Context->ScreenDimensions, &gScreenDimensions, sizeof (gScreenDimensions));\r
-  CopyMem (&Context->MenuOption, &gMenuOption, sizeof (gMenuOption));\r
+  Context->ExitRequired         = gExitRequired;\r
+  Context->HiiHandle            = mCurrentHiiHandle;\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
   // Insert to FormBrowser context list\r
@@ -4125,6 +4658,7 @@ RestoreBrowserContext (
 {\r
   LIST_ENTRY       *Link;\r
   BROWSER_CONTEXT  *Context;\r
+  FORM_ENTRY_INFO     *MenuList;\r
 \r
   ASSERT (gBrowserContextCount != 0);\r
   gBrowserContextCount--;\r
@@ -4143,47 +4677,19 @@ RestoreBrowserContext (
   //\r
   // Restore FormBrowser context\r
   //\r
-  gBannerData           = Context->BannerData;\r
-  gClassOfVfr           = Context->ClassOfVfr;\r
-  gFunctionKeySetting   = Context->FunctionKeySetting;\r
   gResetRequired        = Context->ResetRequired;\r
-  gDirection            = Context->Direction;\r
-  gEnterString          = Context->EnterString;\r
-  gEnterCommitString    = Context->EnterCommitString;\r
-  gEnterEscapeString    = Context->EnterEscapeString;\r
-  gEscapeString         = Context->EscapeString;\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
-  gFormSuppress         = Context->FormSuppress;\r
-  gPromptBlockWidth     = Context->PromptBlockWidth;\r
-  gOptionBlockWidth     = Context->OptionBlockWidth;\r
-  gHelpBlockWidth       = Context->HelpBlockWidth;\r
-  gOldFormSet           = Context->OldFormSet;\r
-  gMenuRefreshHead      = Context->MenuRefreshHead;\r
-  gProtocolNotFound     = Context->ProtocolNotFound;\r
-\r
-  CopyMem (&gScreenDimensions, &Context->ScreenDimensions, sizeof (gScreenDimensions));\r
-  CopyMem (&gMenuOption, &Context->MenuOption, sizeof (gMenuOption));\r
+  gExitRequired         = Context->ExitRequired;\r
+  mCurrentHiiHandle     = Context->HiiHandle;\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
   // Remove from FormBrowser context list\r
@@ -4243,7 +4749,7 @@ IsHiiHandleInBrowserContext (
   //\r
   // HiiHandle is Current FormSet.\r
   //\r
-  if ((gOldFormSet != NULL) && (gOldFormSet->HiiHandle == Handle)) {\r
+  if (mCurrentHiiHandle == Handle) {\r
     return TRUE;\r
   }\r
 \r
@@ -4253,7 +4759,7 @@ IsHiiHandleInBrowserContext (
   Link = GetFirstNode (&gBrowserContextList);\r
   while (!IsNull (&gBrowserContextList, Link)) {\r
     Context = BROWSER_CONTEXT_FROM_LINK (Link);\r
-    if (Context->OldFormSet->HiiHandle == Handle) {\r
+    if (Context->HiiHandle == Handle) {\r
       //\r
       // HiiHandle is in BrowserContext\r
       //\r
@@ -4265,6 +4771,83 @@ IsHiiHandleInBrowserContext (
   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
+    if (PasswordString == NULL) {\r
+      return EFI_SUCCESS;\r
+    } \r
+    \r
+    if (StrnCmp (PasswordString, (CHAR16 *) Question->BufferValue, Question->StorageWidth/sizeof (CHAR16)) == 0) {\r
+      return EFI_SUCCESS;\r
+    } else {\r
+      return EFI_NOT_READY;\r
+    }\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
@@ -4315,7 +4898,7 @@ SetScope (
   if (Scope >= MaxLevel) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
-  \r
+\r
   //\r
   // When no hot key registered in system or on the first setting,\r
   // Scope can be set.\r
@@ -4439,6 +5022,128 @@ RegiserExitHandler (
   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
+  if (gCurrentSelection == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  switch (gBrowserSettingScope) {\r
+    case FormLevel:\r
+      return IsNvUpdateRequiredForForm (gCurrentSelection->Form);\r
+\r
+    case FormSetLevel:\r
+      return IsNvUpdateRequiredForFormSet (gCurrentSelection->FormSet);\r
+\r
+    case SystemLevel:\r
+      Link = GetFirstNode (&gBrowserFormSetList);\r
+      while (!IsNull (&gBrowserFormSetList, Link)) {\r
+        FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
+        if (IsNvUpdateRequiredForFormSet (FormSet)) {\r
+          return TRUE;\r
+        }\r
+        Link = GetNextNode (&gBrowserFormSetList, Link);\r
+      }\r
+      return FALSE;\r
+\r
+    default:\r
+      return FALSE;\r
+  }\r
+}\r
+\r
+/**\r
+  Execute the action requested by the Action parameter.\r
+\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              Execute the request action succss.\r
+  @retval EFI_INVALID_PARAMETER    The input action value is invalid.\r
+\r
+**/\r
+EFI_STATUS \r
+EFIAPI\r
+ExecuteAction (\r
+  IN UINT32        Action,\r
+  IN UINT16        DefaultId\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+\r
+  if (gCurrentSelection == NULL) {\r
+    return EFI_NOT_READY;\r
+  }\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  // Executet the discard action.\r
+  //\r
+  if ((Action & BROWSER_ACTION_DISCARD) != 0) {\r
+    Status = DiscardForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Executet the difault action.\r
+  //\r
+  if ((Action & BROWSER_ACTION_DEFAULT) != 0) {\r
+    Status = ExtractDefault (gCurrentSelection->FormSet, gCurrentSelection->Form, DefaultId, gBrowserSettingScope, GetDefaultForAll, NULL, FALSE);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Executet the submit action.\r
+  //\r
+  if ((Action & BROWSER_ACTION_SUBMIT) != 0) {\r
+    Status = SubmitForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Executet the reset action.\r
+  //\r
+  if ((Action & BROWSER_ACTION_RESET) != 0) {\r
+    gResetRequired = TRUE;\r
+  }\r
+\r
+  //\r
+  // Executet the exit action.\r
+  //\r
+  if ((Action & BROWSER_ACTION_EXIT) != 0) {\r
+    DiscardForm (gCurrentSelection->FormSet, gCurrentSelection->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
   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
@@ -4458,12 +5163,6 @@ SaveReminder (
   FORM_BROWSER_FORMSET    *FormSet;\r
   BOOLEAN                 IsDataChanged;\r
   UINT32                  DataSavedAction;\r
-  CHAR16                  *YesResponse;\r
-  CHAR16                  *NoResponse;\r
-  CHAR16                  *EmptyString;\r
-  CHAR16                  *ChangeReminderString;\r
-  CHAR16                  *SaveConfirmString;\r
-  EFI_INPUT_KEY           Key;\r
 \r
   DataSavedAction  = BROWSER_NO_CHANGES;\r
   IsDataChanged    = FALSE;\r
@@ -4474,7 +5173,7 @@ SaveReminder (
     if (!ValidateFormSet(FormSet)) {\r
       continue;\r
     }\r
-    if (IsNvUpdateRequired (FormSet)) {\r
+    if (IsNvUpdateRequiredForFormSet (FormSet)) {\r
       IsDataChanged = TRUE;\r
       break;\r
     }\r
@@ -4488,42 +5187,19 @@ SaveReminder (
   }\r
   \r
   //\r
-  // If data is changed, prompt user\r
+  // If data is changed, prompt user to save or discard it. \r
   //\r
-  gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
-\r
-  YesResponse          = GetToken (STRING_TOKEN (ARE_YOU_SURE_YES), gHiiHandle);\r
-  ASSERT (YesResponse != NULL);\r
-  NoResponse           = GetToken (STRING_TOKEN (ARE_YOU_SURE_NO), gHiiHandle);\r
-  ASSERT (NoResponse  != NULL);\r
-  EmptyString          = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
-  ChangeReminderString = GetToken (STRING_TOKEN (CHANGE_REMINDER), gHiiHandle);\r
-  SaveConfirmString    = GetToken (STRING_TOKEN (SAVE_CONFIRM), gHiiHandle);\r
-\r
   do {\r
-    CreateDialog (4, TRUE, 0, NULL, &Key, EmptyString, ChangeReminderString, SaveConfirmString, EmptyString);\r
-  } while\r
-  (((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (NoResponse[0] | UPPER_LOWER_CASE_OFFSET)) &&\r
-   ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (YesResponse[0] | UPPER_LOWER_CASE_OFFSET))\r
-  );\r
+    DataSavedAction = (UINT32) mFormDisplay->ConfirmDataChange();\r
 \r
-  //\r
-  // If the user hits the YesResponse key\r
-  //\r
-  if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse[0] | UPPER_LOWER_CASE_OFFSET)) {\r
-    SubmitForm (NULL, NULL, SystemLevel);\r
-    DataSavedAction = BROWSER_SAVE_CHANGES;\r
-  } else {\r
-    DiscardForm (NULL, NULL, SystemLevel);\r
-    DataSavedAction = BROWSER_DISCARD_CHANGES;\r
-    gResetRequired  = FALSE;\r
-  }\r
-\r
-  FreePool (YesResponse);\r
-  FreePool (NoResponse);\r
-  FreePool (EmptyString);\r
-  FreePool (SaveConfirmString);\r
-  FreePool (ChangeReminderString);\r
+    if (DataSavedAction == BROWSER_SAVE_CHANGES) {\r
+      SubmitForm (NULL, NULL, SystemLevel);\r
+      break;\r
+    } else if (DataSavedAction == BROWSER_DISCARD_CHANGES) {\r
+      DiscardForm (NULL, NULL, SystemLevel);\r
+      break;\r
+    }\r
+  } while (1);\r
 \r
   return DataSavedAction;\r
 }\r