]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
Rollback patch 14537 & 14538, because patch 14537 is not tested by Laszlo Ersek,...
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Setup.c
index 381cefeae5937690e40442d22a4175b9486fefcb..ed904161b619dd538b8ce296c83764791da2f225 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
 Entry and initialization module for the browser.\r
 \r
-Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -32,11 +32,13 @@ SETUP_DRIVER_PRIVATE_DATA  mPrivateData = {
 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
 \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
@@ -84,6 +86,7 @@ CHAR16            *gAdjustNumber;
 CHAR16            *gSaveChanges;\r
 CHAR16            *gOptionMismatch;\r
 CHAR16            *gFormSuppress;\r
+CHAR16            *gProtocolNotFound;\r
 \r
 CHAR16            *mUnknownString = L"!";\r
 \r
@@ -242,6 +245,11 @@ SendForm (
   //\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
   //\r
@@ -303,8 +311,6 @@ SendForm (
   //\r
   InitializeBrowserStrings ();\r
 \r
-  gFunctionKeySetting = ENABLE_FUNCTION_KEY_SETTING;\r
-\r
   //\r
   // Ensure we are in Text mode\r
   //\r
@@ -361,6 +367,7 @@ SendForm (
       // If no data is changed, don't need to save current FormSet into the maintain list.\r
       //\r
       if (!IsNvUpdateRequired (gOldFormSet)) {\r
+        CleanBrowserStorage(gOldFormSet);\r
         RemoveEntryList (&gOldFormSet->Link);\r
         DestroyFormSet (gOldFormSet);\r
       }\r
@@ -378,6 +385,7 @@ SendForm (
   }\r
 \r
   FreeBrowserStrings ();\r
+  UiFreeMenuList(&gMenuList);\r
 \r
   gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
   gST->ConOut->ClearScreen (gST->ConOut);\r
@@ -469,9 +477,9 @@ BrowserCallback (
       Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
       Link = GetNextNode (&FormSet->StorageListHead, Link);\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
+      if (CompareGuid (&Storage->BrowserStorage->Guid, (EFI_GUID *) VariableGuid)) {\r
+        if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_BUFFER ||\r
+            Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
           //\r
           // Buffer storage require both GUID and Name\r
           //\r
@@ -479,7 +487,7 @@ BrowserCallback (
             return EFI_NOT_FOUND;\r
           }\r
 \r
-          if (StrCmp (Storage->Name, (CHAR16 *) VariableName) != 0) {\r
+          if (StrCmp (Storage->BrowserStorage->Name, (CHAR16 *) VariableName) != 0) {\r
             continue;\r
           }\r
         }\r
@@ -509,7 +517,7 @@ BrowserCallback (
     //\r
     // Generate <ConfigResp>\r
     //\r
-    Status = StorageToConfigResp (Storage, &ConfigResp, FALSE);\r
+    Status = StorageToConfigResp (Storage->BrowserStorage, &ConfigResp, Storage->ConfigRequest);\r
     if (EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
@@ -517,7 +525,7 @@ BrowserCallback (
     //\r
     // Skip <ConfigHdr> and '&' to point to <ConfigBody>\r
     //\r
-    StrPtr = ConfigResp + StrLen (Storage->ConfigHdr) + 1;\r
+    StrPtr = ConfigResp + StrLen (Storage->BrowserStorage->ConfigHdr) + 1;\r
 \r
     BufferSize = StrSize (StrPtr);\r
     if (*ResultsDataSize < BufferSize) {\r
@@ -536,18 +544,18 @@ BrowserCallback (
     // Prepare <ConfigResp>\r
     //\r
     TmpSize = StrLen (ResultsData);\r
-    BufferSize = (TmpSize + StrLen (Storage->ConfigHdr) + 2) * sizeof (CHAR16);\r
+    BufferSize = (TmpSize + StrLen (Storage->BrowserStorage->ConfigHdr) + 2) * sizeof (CHAR16);\r
     ConfigResp = AllocateZeroPool (BufferSize);\r
     ASSERT (ConfigResp != NULL);\r
 \r
-    StrCpy (ConfigResp, Storage->ConfigHdr);\r
+    StrCpy (ConfigResp, Storage->BrowserStorage->ConfigHdr);\r
     StrCat (ConfigResp, L"&");\r
     StrCat (ConfigResp, ResultsData);\r
 \r
     //\r
     // Update Browser uncommited data\r
     //\r
-    Status = ConfigRespToStorage (Storage, ConfigResp);\r
+    Status = ConfigRespToStorage (Storage->BrowserStorage, ConfigResp);\r
     if (EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
@@ -556,66 +564,6 @@ BrowserCallback (
   return EFI_SUCCESS;\r
 }\r
 \r
-/**\r
-  Notify function will remove the formset in the maintain list \r
-  once this formset is removed.\r
-  \r
-  Functions which are registered to receive notification of\r
-  database events have this prototype. The actual event is encoded\r
-  in NotifyType. The following table describes how PackageType,\r
-  PackageGuid, Handle, and Package are used for each of the\r
-  notification types.\r
-\r
-  @param PackageType  Package type of the notification.\r
-\r
-  @param PackageGuid  If PackageType is\r
-                      EFI_HII_PACKAGE_TYPE_GUID, then this is\r
-                      the pointer to the GUID from the Guid\r
-                      field of EFI_HII_PACKAGE_GUID_HEADER.\r
-                      Otherwise, it must be NULL.\r
-\r
-  @param Package  Points to the package referred to by the\r
-                  notification Handle The handle of the package\r
-                  list which contains the specified package.\r
-\r
-  @param Handle       The HII handle.\r
-\r
-  @param NotifyType   The type of change concerning the\r
-                      database. See\r
-                      EFI_HII_DATABASE_NOTIFY_TYPE.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-FormsetRemoveNotify (\r
-  IN UINT8                              PackageType,\r
-  IN CONST EFI_GUID                     *PackageGuid,\r
-  IN CONST EFI_HII_PACKAGE_HEADER       *Package,\r
-  IN EFI_HII_HANDLE                     Handle,\r
-  IN EFI_HII_DATABASE_NOTIFY_TYPE       NotifyType\r
-  )\r
-{\r
-  FORM_BROWSER_FORMSET *FormSet;\r
-\r
-  //\r
-  // Ignore the update for current using formset, which is handled by another notify function.\r
-  //\r
-  if (IsHiiHandleInBrowserContext (Handle)) {\r
-    return EFI_SUCCESS;\r
-  }\r
-  \r
-  //\r
-  // Remove the backup FormSet data when the Form Package is removed.\r
-  //\r
-  FormSet = GetFormSetFromHiiHandle (Handle);\r
-  if (FormSet != NULL) {\r
-    RemoveEntryList (&FormSet->Link);\r
-    DestroyFormSet (FormSet);\r
-  }\r
-  \r
-  return EFI_SUCCESS;\r
-}\r
-\r
 /**\r
   Initialize Setup Browser driver.\r
 \r
@@ -634,7 +582,6 @@ InitializeSetup (
   )\r
 {\r
   EFI_STATUS                  Status;\r
-  EFI_HANDLE                  NotifyHandle;\r
   EFI_INPUT_KEY               DefaultHotKey;\r
   EFI_STRING                  HelpString;\r
 \r
@@ -662,6 +609,12 @@ InitializeSetup (
                   );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiDevicePathFromTextProtocolGuid,\r
+                  NULL,\r
+                  (VOID **) &mPathFromText\r
+                  );\r
+\r
   //\r
   // Publish our HII data\r
   //\r
@@ -726,19 +679,6 @@ InitializeSetup (
                   );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
-  //\r
-  // Register notify for Form package remove\r
-  //\r
-  Status = mHiiDatabase->RegisterPackageNotify (\r
-                           mHiiDatabase,\r
-                           EFI_HII_PACKAGE_FORMS,\r
-                           NULL,\r
-                           FormsetRemoveNotify,\r
-                           EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
-                           &NotifyHandle\r
-                           );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
   return Status;\r
 }\r
 \r
@@ -888,7 +828,7 @@ NewStringCat (
 **/\r
 VOID\r
 SynchronizeStorage (\r
-  IN FORMSET_STORAGE         *Storage,\r
+  IN BROWSER_STORAGE         *Storage,\r
   IN BOOLEAN                 SyncOrRestore\r
   )\r
 {\r
@@ -941,7 +881,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
@@ -990,7 +930,7 @@ GetValueByName (
 **/\r
 EFI_STATUS\r
 SetValueByName (\r
-  IN FORMSET_STORAGE         *Storage,\r
+  IN BROWSER_STORAGE         *Storage,\r
   IN CHAR16                  *Name,\r
   IN CHAR16                  *Value,\r
   IN GET_SET_QUESTION_VALUE_WITH SetValueTo\r
@@ -1037,9 +977,9 @@ 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
 \r
   @retval EFI_SUCCESS            Convert success.\r
   @retval EFI_INVALID_PARAMETER  Incorrect storage type.\r
@@ -1047,28 +987,17 @@ 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
   )\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
 \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
@@ -1123,7 +1052,7 @@ StorageToConfigResp (
 **/\r
 EFI_STATUS\r
 ConfigRespToStorage (\r
-  IN FORMSET_STORAGE         *Storage,\r
+  IN BROWSER_STORAGE         *Storage,\r
   IN CHAR16                  *ConfigResp\r
   )\r
 {\r
@@ -1215,7 +1144,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
@@ -1640,7 +1569,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
@@ -2250,6 +2179,53 @@ SendDiscardInfoToDriver (
   }\r
 }\r
 \r
+/**\r
+  Validate the FormSet. If the formset is not validate, remove it from the list.\r
+\r
+  @param  FormSet                The input FormSet which need to validate.\r
+\r
+  @retval TRUE                   The handle is validate.\r
+  @retval FALSE                  The handle is invalidate.\r
+\r
+**/\r
+BOOLEAN\r
+ValidateFormSet (\r
+  FORM_BROWSER_FORMSET    *FormSet\r
+  )\r
+{\r
+  EFI_HII_HANDLE          *HiiHandles;\r
+  UINTN                   Index;\r
+  BOOLEAN                 Find;\r
+\r
+  ASSERT (FormSet != NULL);\r
+  Find = FALSE;\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
+    if (HiiHandles[Index] == FormSet->HiiHandle) {\r
+      Find = TRUE;\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (!Find) {\r
+    CleanBrowserStorage(FormSet);\r
+    RemoveEntryList (&FormSet->Link);\r
+    DestroyFormSet (FormSet);\r
+  }\r
+\r
+  FreePool (HiiHandles);\r
+\r
+  return Find;\r
+}\r
+\r
 /**\r
   Discard data based on the input setting scope (Form, FormSet or System).\r
 \r
@@ -2320,7 +2296,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
@@ -2331,7 +2307,7 @@ DiscardForm (
         continue;\r
       }\r
 \r
-      SynchronizeStorage(Storage, FALSE);\r
+      SynchronizeStorage(Storage->BrowserStorage, FALSE);\r
     }\r
 \r
     Link = GetFirstNode (&FormSet->FormListHead);\r
@@ -2357,12 +2333,16 @@ DiscardForm (
     Link = GetFirstNode (&gBrowserFormSetList);\r
     while (!IsNull (&gBrowserFormSetList, Link)) {\r
       LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
-      DiscardForm (LocalFormSet, NULL, FormSetLevel);\r
       Link = GetNextNode (&gBrowserFormSetList, Link);\r
+      if (!ValidateFormSet(LocalFormSet)) {\r
+        continue;\r
+      }\r
+      DiscardForm (LocalFormSet, NULL, FormSetLevel);\r
       if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {\r
         //\r
         // Remove maintain backup list after discard except for the current using FormSet.\r
         //\r
+        CleanBrowserStorage(LocalFormSet);\r
         RemoveEntryList (&LocalFormSet->Link);\r
         DestroyFormSet (LocalFormSet);\r
       }\r
@@ -2394,7 +2374,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
@@ -2442,7 +2423,7 @@ SubmitForm (
       //\r
       // 1. Prepare <ConfigResp>\r
       //\r
-      Status = StorageToConfigResp (ConfigInfo, &ConfigResp, TRUE);\r
+      Status = StorageToConfigResp (ConfigInfo->Storage, &ConfigResp, ConfigInfo->ConfigRequest);\r
       if (EFI_ERROR (Status)) {\r
         return Status;\r
       }\r
@@ -2531,7 +2512,8 @@ SubmitForm (
     //\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
@@ -2541,14 +2523,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);\r
       if (EFI_ERROR (Status)) {\r
         return Status;\r
       }\r
@@ -2638,12 +2620,16 @@ SubmitForm (
     Link = GetFirstNode (&gBrowserFormSetList);\r
     while (!IsNull (&gBrowserFormSetList, Link)) {\r
       LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
-      SubmitForm (LocalFormSet, NULL, FormSetLevel);\r
       Link = GetNextNode (&gBrowserFormSetList, Link);\r
+      if (!ValidateFormSet(LocalFormSet)) {\r
+        continue;\r
+      }\r
+      SubmitForm (LocalFormSet, NULL, FormSetLevel);\r
       if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {\r
         //\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
@@ -2673,7 +2659,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
@@ -3161,7 +3147,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
@@ -3324,8 +3310,11 @@ ExtractDefault (
     Link = GetFirstNode (&gBrowserFormSetList);\r
     while (!IsNull (&gBrowserFormSetList, Link)) {\r
       LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
-      ExtractDefault (LocalFormSet, NULL, DefaultId, FormSetLevel, GetDefaultValueScope, Storage, RetrieveValueFirst);\r
       Link = GetNextNode (&gBrowserFormSetList, Link);\r
+      if (!ValidateFormSet(LocalFormSet)) {\r
+        continue;\r
+      }\r
+      ExtractDefault (LocalFormSet, NULL, DefaultId, FormSetLevel, GetDefaultValueScope, Storage, RetrieveValueFirst);\r
     }\r
   }\r
 \r
@@ -3452,200 +3441,405 @@ LoadFormSetConfig (
 }\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
-\r
-  @retval EFI_SUCCESS            The function completed successfully.\r
+  @param  Storage                Pointer to the browser storage.\r
+  @param  RequestElement         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
+RemoveElement (\r
+  IN OUT BROWSER_STORAGE      *Storage,\r
+  IN     CHAR16               *RequestElement\r
   )\r
 {\r
-  EFI_STATUS  Status;\r
-  EFI_STRING  Progress;\r
-  EFI_STRING  Result;\r
-  CHAR16      *StrPtr;\r
+  CHAR16   *NewStr;\r
+  CHAR16   *DestStr;\r
 \r
-  if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
-    return EFI_SUCCESS;\r
-  }\r
+  ASSERT (Storage->ConfigRequest != NULL && RequestElement != NULL);\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
-  }\r
+  NewStr = StrStr (Storage->ConfigRequest, RequestElement);\r
 \r
-  if (FormSet->ConfigAccess == NULL) {\r
-    return EFI_NOT_FOUND;\r
+  if (NewStr == NULL) {\r
+    return;\r
   }\r
 \r
-  if (Storage->ElementCount == 0) {\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
+VOID\r
+RemoveConfigRequest (\r
+  BROWSER_STORAGE   *Storage,\r
+  CHAR16            *ConfigRequest\r
+  )\r
+{\r
+  CHAR16       *RequestElement;\r
+  CHAR16       *NextRequestElement;\r
+  CHAR16       *SearchKey;\r
+\r
+  if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
     //\r
-    // Skip if there is no RequestElement\r
+    // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage\r
     //\r
-    return EFI_SUCCESS;\r
+    SearchKey = L"&";\r
+  } else {\r
+    //\r
+    // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage\r
+    //\r
+    SearchKey = L"&OFFSET";\r
   }\r
 \r
   //\r
-  // Request current settings from Configuration Driver\r
+  // Find SearchKey storage\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 (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+    RequestElement = StrStr (ConfigRequest, L"PATH");\r
+    ASSERT (RequestElement != NULL);\r
+    RequestElement = StrStr (RequestElement, SearchKey);    \r
+  } else {\r
+    RequestElement = StrStr (ConfigRequest, SearchKey);\r
+  }\r
+\r
+  while (RequestElement != NULL) {\r
+    //\r
+    // +1 to avoid find header itself.\r
+    //\r
+    NextRequestElement = StrStr (RequestElement + 1, SearchKey);\r
+\r
+    //\r
+    // The last Request element in configRequest string.\r
+    //\r
+    if (NextRequestElement != NULL) {\r
+      //\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
-  // Convert Result from <ConfigAltResp> to <ConfigResp>\r
+  // If no request element remain, just remove the ConfigRequest string.\r
   //\r
-  StrPtr = StrStr (Result, L"ALTCFG");\r
-  if (StrPtr != NULL) {\r
-    *StrPtr = L'\0';\r
+  if (StrCmp (Storage->ConfigRequest, Storage->ConfigHdr) == 0) {\r
+    FreePool (Storage->ConfigRequest);\r
+    Storage->ConfigRequest = NULL;\r
+    Storage->SpareStrLen   = 0;\r
   }\r
-\r
-  Status = ConfigRespToStorage (Storage, Result);\r
-  FreePool (Result);\r
-  return Status;\r
 }\r
 \r
+/**\r
+  Base on the current formset info, clean the ConfigRequest string in browser storage.\r
+\r
+  @param  FormSet                Pointer of the FormSet\r
+\r
+**/\r
+VOID\r
+CleanBrowserStorage (\r
+  IN OUT FORM_BROWSER_FORMSET  *FormSet\r
+  )\r
+{\r
+  LIST_ENTRY            *Link;\r
+  FORMSET_STORAGE       *Storage;\r
+\r
+  Link = GetFirstNode (&FormSet->StorageListHead);\r
+  while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+    Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
+    Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+\r
+    if ((Storage->BrowserStorage->Type != EFI_HII_VARSTORE_BUFFER) && \r
+        (Storage->BrowserStorage->Type != EFI_HII_VARSTORE_NAME_VALUE)) {\r
+      continue;\r
+    }\r
+\r
+    if (Storage->ConfigRequest == NULL || Storage->BrowserStorage->ConfigRequest == NULL) {\r
+      continue;\r
+    }\r
+\r
+    RemoveConfigRequest (Storage->BrowserStorage, Storage->ConfigRequest);\r
+  }\r
+}\r
 \r
 /**\r
-  Copy uncommitted data from source Storage to destination Storage.\r
+  Check whether current element in the ConfigReqeust string.\r
 \r
-  @param  Dst                    Target Storage for uncommitted data.\r
-  @param  Src                    Source Storage for uncommitted data.\r
+  @param  BrowserStorage                Storage which includes ConfigReqeust.\r
+  @param  RequestElement                New element need to check.\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        The Element is in the ConfigReqeust string.\r
+  @retval FALSE       The Element not in the configReqeust String.\r
 \r
 **/\r
-EFI_STATUS\r
-CopyStorage (\r
-  IN OUT FORMSET_STORAGE     *Dst,\r
-  IN FORMSET_STORAGE         *Src\r
+BOOLEAN \r
+ElementValidation (\r
+  BROWSER_STORAGE   *BrowserStorage,\r
+  CHAR16            *RequestElement\r
   )\r
 {\r
-  LIST_ENTRY          *Link;\r
-  NAME_VALUE_NODE     *Node;\r
+  return StrStr (BrowserStorage->ConfigRequest, RequestElement) != NULL ? TRUE : FALSE;\r
+}\r
 \r
-  if ((Dst->Type != Src->Type) || (Dst->Size != Src->Size)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
+/**\r
+  Append the Request element to the Config Request.\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
+  @param  ConfigRequest          Current ConfigRequest info.\r
+  @param  SpareStrLen            Current remain free buffer for config reqeust.\r
+  @param  RequestElement         New Request element.\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
+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
-      SetValueByName (Dst, Node->Name, Node->EditValue, GetSetValueWithEditBuffer);\r
-      SetValueByName (Dst, Node->Name, Node->Value, GetSetValueWithBuffer);\r
+  StrLength = StrLen (RequestElement);\r
 \r
-      Link = GetNextNode (&Src->NameValueListHead, Link);\r
-    }\r
-    break;\r
+  //\r
+  // Append <RequestElement> to <ConfigRequest>\r
+  //\r
+  if (StrLength > *SpareStrLen) {\r
+    //\r
+    // Old String buffer is not sufficient for RequestElement, allocate a new one\r
+    //\r
+    StringSize = (*ConfigRequest != NULL) ? StrSize (*ConfigRequest) : sizeof (CHAR16);\r
+    NewStr = AllocateZeroPool (StringSize + CONFIG_REQUEST_STRING_INCREMENTAL * sizeof (CHAR16));\r
+    ASSERT (NewStr != NULL);\r
 \r
-  case EFI_HII_VARSTORE_EFI_VARIABLE:\r
-  default:\r
-    break;\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
-  return EFI_SUCCESS;\r
+  StrCat (*ConfigRequest, RequestElement);\r
+  *SpareStrLen -= StrLength;\r
 }\r
 \r
 /**\r
-  Get old question value from the saved formset.\r
+  Adjust the config request info, remove the request elements which already in AllConfigRequest string.\r
 \r
-  @param  Statement              The question which need to get old question value.\r
-  @param  OldFormSet             FormSet data structure saved in the list.\r
+  @param  Storage                Form set Storage.\r
+  @param  ConfigRequest          Return the ConfigRequest info.\r
+\r
+  @retval TRUE                   Has element not covered by current used elements, need to continue to call ExtractConfig\r
+  @retval FALSE                  All elements covered by current used elements.\r
 \r
 **/\r
-VOID \r
-GetOldQuestionValue (\r
-  IN OUT FORM_BROWSER_STATEMENT  *Statement,\r
-  IN     FORM_BROWSER_FORMSET    *OldFormSet\r
+BOOLEAN \r
+ConfigRequestAdjust (\r
+  IN  FORMSET_STORAGE         *Storage,\r
+  OUT CHAR16                  **ConfigRequest\r
   )\r
 {\r
-  LIST_ENTRY              *FormLink;\r
-  LIST_ENTRY              *Link;\r
-  FORM_BROWSER_STATEMENT  *Question;\r
-  FORM_BROWSER_FORM       *Form;\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
+    *ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigRequest), Storage->ConfigRequest);\r
+    return TRUE;\r
+  }\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
+  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
-    Link = GetFirstNode (&Form->StatementListHead);\r
-    while (!IsNull (&Form->StatementListHead, Link)) {\r
-      Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
-      Link = GetNextNode (&Form->StatementListHead, Link);\r
+  //\r
+  // Prepare the config header.\r
+  // \r
+  RetBuf = AllocateCopyPool(StrSize (Storage->BrowserStorage->ConfigHdr), Storage->BrowserStorage->ConfigHdr);\r
+  ASSERT (RetBuf != NULL);\r
 \r
-      if (Question->QuestionId != Statement->QuestionId) {\r
-        continue;\r
-      }\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
+  while (RequestElement != NULL) {\r
+    //\r
+    // +1 to avoid find header itself.\r
+    //\r
+    NextRequestElement = StrStr (RequestElement + 1, SearchKey);\r
+\r
+    //\r
+    // The last Request element in configRequest string.\r
+    //\r
+    if (NextRequestElement != NULL) {\r
+      //\r
+      // Replace "&" with '\0'.\r
+      //\r
+      *NextRequestElement = L'\0';\r
+    }\r
\r
+    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
 \r
-      CopyMem (&Statement->HiiValue, &Question->HiiValue, sizeof (EFI_HII_VALUE));\r
-      return;\r
+    if (NextRequestElement != NULL) {\r
+      //\r
+      // Restore '&' with '\0' for later used.\r
+      //\r
+      *NextRequestElement = L'&';\r
     }\r
+\r
+    RequestElement = NextRequestElement;\r
   }\r
+\r
+  if (RetVal) {\r
+    *ConfigRequest = RetBuf;\r
+  } else {\r
+    FreePool (RetBuf);\r
+  }\r
+\r
+  return RetVal;\r
 }\r
 \r
 /**\r
-  Get old question value from the saved formset, all these questions not have\r
-  storage.\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
-  @param  FormSet                FormSet data structure which is used now.\r
-  @param  OldFormSet             FormSet data structure saved in the list.\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
 \r
 **/\r
-VOID\r
-CopyOldValueForNoStorageQst (\r
-  IN OUT FORM_BROWSER_FORMSET             *FormSet,\r
-  IN     FORM_BROWSER_FORMSET             *OldFormSet\r
+EFI_STATUS\r
+LoadStorage (\r
+  IN FORM_BROWSER_FORMSET    *FormSet,\r
+  IN FORMSET_STORAGE         *Storage\r
   )\r
 {\r
-  LIST_ENTRY              *FormLink;\r
-  LIST_ENTRY              *Link;\r
-  FORM_BROWSER_STATEMENT  *Question;\r
-  FORM_BROWSER_FORM       *Form;\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
+  EFI_STATUS  Status;\r
+  EFI_STRING  Progress;\r
+  EFI_STRING  Result;\r
+  CHAR16      *StrPtr;\r
+  CHAR16      *ConfigRequest;\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
+  if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+    return EFI_SUCCESS;\r
+  }\r
 \r
-      if (Question->Storage == NULL) {\r
-        GetOldQuestionValue (Question, OldFormSet);\r
-      }\r
+  if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
+    Status = EFI_SUCCESS;\r
+    //\r
+    // EFI varstore data all get from variable, so no need to get again.\r
+    //\r
+    if (Storage->BrowserStorage->ReferenceCount == 1) {\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
+    return Status;\r
+  }\r
+\r
+  if (FormSet->ConfigAccess == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  if (Storage->ElementCount == 0) {\r
+    //\r
+    // Skip if there is no RequestElement\r
+    //\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Adjust the ConfigRequest string, only the field not saved in BrowserStorage->AllConfig\r
+  // will used to call ExtractConfig.\r
+  //\r
+  if (!ConfigRequestAdjust(Storage, &ConfigRequest)) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Request current settings from Configuration Driver\r
+  //\r
+  Status = FormSet->ConfigAccess->ExtractConfig (\r
+                                    FormSet->ConfigAccess,\r
+                                    ConfigRequest,\r
+                                    &Progress,\r
+                                    &Result\r
+                                    );\r
+  FreePool (ConfigRequest);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\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
+  return Status;\r
 }\r
 \r
 /**\r
@@ -3700,17 +3894,18 @@ InitializeCurrentSetting (
       }\r
     }\r
 \r
+    //\r
+    // Storage is not found in backup formset and current global storage not has other driver used,\r
+    // request it from ConfigDriver\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
+        ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForStorage, Storage->BrowserStorage, TRUE);\r
         //\r
         // ExtractDefault will set the NV flag to TRUE, so need this function to clean the flag\r
         // in current situation.\r
@@ -3722,12 +3917,7 @@ InitializeCurrentSetting (
       // 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
+      SynchronizeStorage (Storage->BrowserStorage, TRUE);\r
     }\r
 \r
     Link = GetNextNode (&FormSet->StorageListHead, Link);\r
@@ -4020,6 +4210,8 @@ InitializeFormSet (
     }\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
@@ -4107,6 +4299,7 @@ SaveBrowserContext (
   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
@@ -4184,6 +4377,7 @@ RestoreBrowserContext (
   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
@@ -4214,10 +4408,13 @@ GetFormSetFromHiiHandle (
   Link = GetFirstNode (&gBrowserFormSetList);\r
   while (!IsNull (&gBrowserFormSetList, Link)) {\r
     FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
+    Link = GetNextNode (&gBrowserFormSetList, Link);\r
+    if (!ValidateFormSet(FormSet)) {\r
+      continue;\r
+    }\r
     if (FormSet->HiiHandle == Handle) {\r
       return FormSet;\r
     }\r
-    Link = GetNextNode (&gBrowserFormSetList, Link);\r
   }\r
   \r
   return NULL;\r
@@ -4470,11 +4667,14 @@ SaveReminder (
   Link = GetFirstNode (&gBrowserFormSetList);\r
   while (!IsNull (&gBrowserFormSetList, Link)) {\r
     FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
+    Link = GetNextNode (&gBrowserFormSetList, Link);\r
+    if (!ValidateFormSet(FormSet)) {\r
+      continue;\r
+    }\r
     if (IsNvUpdateRequired (FormSet)) {\r
       IsDataChanged = TRUE;\r
       break;\r
     }\r
-    Link = GetNextNode (&gBrowserFormSetList, Link);\r
   }\r
   \r
   //\r