]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
When finish using the browser storage for one formset, browser should clean the Confi...
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Setup.c
index d14dac037393ae91b16a8c6a519d20c88a8c7be4..ed904161b619dd538b8ce296c83764791da2f225 100644 (file)
-/** @file
-Copyright (c) 2007, Intel Corporation
-All rights reserved. This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-Module Name:
-
-  Setup.c
-
-Abstract:
-
-  Entry and initialization module for the browser.
-
-
-**/
-
-#include "Setup.h"
-#include "Ui.h"
-
-
-SETUP_DRIVER_PRIVATE_DATA  mPrivateData = {
-  SETUP_DRIVER_SIGNATURE,
-  NULL,
-  {
-    SendForm,
-    BrowserCallback
-  },
-  {
-    UnicodeVSPrint
-  }
-};
-
-EFI_HII_DATABASE_PROTOCOL         *mHiiDatabase;
-EFI_HII_STRING_PROTOCOL           *mHiiString;
-EFI_HII_CONFIG_ROUTING_PROTOCOL   *mHiiConfigRouting;
-
-BANNER_DATA           *BannerData;
-EFI_HII_HANDLE        FrontPageHandle;
-UINTN                 gClassOfVfr;
-UINTN                 gFunctionKeySetting;
-BOOLEAN               gResetRequired;
-BOOLEAN               gNvUpdateRequired;
-EFI_HII_HANDLE        gHiiHandle;
-BOOLEAN               gFirstIn;
-UINT16                gDirection;
-EFI_SCREEN_DESCRIPTOR gScreenDimensions;
-BOOLEAN               gUpArrow;
-BOOLEAN               gDownArrow;
-
-//
-// Browser Global Strings
-//
-CHAR16            *gFunctionOneString;
-CHAR16            *gFunctionTwoString;
-CHAR16            *gFunctionNineString;
-CHAR16            *gFunctionTenString;
-CHAR16            *gEnterString;
-CHAR16            *gEnterCommitString;
-CHAR16            *gEscapeString;
-CHAR16            *gSaveFailed;
-CHAR16            *gMoveHighlight;
-CHAR16            *gMakeSelection;
-CHAR16            *gDecNumericInput;
-CHAR16            *gHexNumericInput;
-CHAR16            *gToggleCheckBox;
-CHAR16            *gPromptForData;
-CHAR16            *gPromptForPassword;
-CHAR16            *gPromptForNewPassword;
-CHAR16            *gConfirmPassword;
-CHAR16            *gConfirmError;
-CHAR16            *gPassowordInvalid;
-CHAR16            *gPressEnter;
-CHAR16            *gEmptyString;
-CHAR16            *gAreYouSure;
-CHAR16            *gYesResponse;
-CHAR16            *gNoResponse;
-CHAR16            *gMiniString;
-CHAR16            *gPlusString;
-CHAR16            *gMinusString;
-CHAR16            *gAdjustNumber;
-
-CHAR16            gPromptBlockWidth;
-CHAR16            gOptionBlockWidth;
-CHAR16            gHelpBlockWidth;
-
-EFI_GUID  gZeroGuid = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-EFI_GUID  gSetupBrowserGuid = {
-  0xab368524, 0xb60c, 0x495b, 0xa0, 0x9, 0x12, 0xe8, 0x5b, 0x1a, 0xea, 0x32
-};
-
-FUNCTIION_KEY_SETTING gFunctionKeySettingTable[] = {
-  //
-  // Boot Manager
-  //
-  {
-    {
-      0x847bc3fe,
-      0xb974,
-      0x446d,
-      0x94,
-      0x49,
-      0x5a,
-      0xd5,
-      0x41,
-      0x2e,
-      0x99,
-      0x3b
-    },
-    NONE_FUNCTION_KEY_SETTING
-  },
-  //
-  // Device Manager
-  //
-  {
-    {
-      0x3ebfa8e6,
-      0x511d,
-      0x4b5b,
-      0xa9,
-      0x5f,
-      0xfb,
-      0x38,
-      0x26,
-      0xf,
-      0x1c,
-      0x27
-    },
-    NONE_FUNCTION_KEY_SETTING
-  },
-  //
-  // BMM FormSet.
-  //
-  {
-    {
-      0x642237c7,
-      0x35d4,
-      0x472d,
-      0x83,
-      0x65,
-      0x12,
-      0xe0,
-      0xcc,
-      0xf2,
-      0x7a,
-      0x22
-    },
-    NONE_FUNCTION_KEY_SETTING
-  },
-  //
-  // BMM File Explorer FormSet.
-  //
-  {
-    {
-      0x1f2d63e1,
-      0xfebd,
-      0x4dc7,
-      0x9c,
-      0xc5,
-      0xba,
-      0x2b,
-      0x1c,
-      0xef,
-      0x9c,
-      0x5b
-    },
-    NONE_FUNCTION_KEY_SETTING
-  },
-};
-
-//@MT: EFI_DRIVER_ENTRY_POINT (InitializeSetup)
-
-EFI_STATUS
-EFIAPI
-SendForm (
-  IN  CONST EFI_FORM_BROWSER2_PROTOCOL *This,
-  IN  EFI_HII_HANDLE                   *Handles,
-  IN  UINTN                            HandleCount,
-  IN  EFI_GUID                         *FormSetGuid, OPTIONAL
-  IN  UINT16                           FormId, OPTIONAL
-  IN  CONST EFI_SCREEN_DESCRIPTOR      *ScreenDimensions, OPTIONAL
-  OUT EFI_BROWSER_ACTION_REQUEST       *ActionRequest  OPTIONAL
-  )
-/*++
-
-Routine Description:
-  This is the routine which an external caller uses to direct the browser
-  where to obtain it's information.
-
-Arguments:
-  This            - The Form Browser protocol instanse.
-  Handles         - A pointer to an array of Handles.  If HandleCount > 1 we
-                    display a list of the formsets for the handles specified.
-  HandleCount     - The number of Handles specified in Handle.
-  FormSetGuid     - This field points to the EFI_GUID which must match the Guid
-                    field in the EFI_IFR_FORM_SET op-code for the specified
-                    forms-based package. If FormSetGuid is NULL, then this
-                    function will display the first found forms package.
-  FormId          - This field specifies which EFI_IFR_FORM to render as the first
-                    displayable page. If this field has a value of 0x0000, then
-                    the forms browser will render the specified forms in their encoded order.
-  ScreenDimenions - This allows the browser to be called so that it occupies a
-                    portion of the physical screen instead of dynamically determining the screen dimensions.
-  ActionRequest   - Points to the action recommended by the form.
-
-Returns:
-  EFI_SUCCESS           -  The function completed successfully.
-  EFI_INVALID_PARAMETER -  One of the parameters has an invalid value.
-  EFI_NOT_FOUND         -  No valid forms could be found to display.
-
---*/
-{
-  EFI_STATUS            Status;
-  UI_MENU_SELECTION     *Selection;
-  UINTN                 Index;
-  FORM_BROWSER_FORMSET  *FormSet;
-
-  Status = EFI_SUCCESS;
-  ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
-
-  //
-  // Seed the dimensions in the global
-  //
-  gST->ConOut->QueryMode (
-                 gST->ConOut,
-                 gST->ConOut->Mode->Mode,
-                 &gScreenDimensions.RightColumn,
-                 &gScreenDimensions.BottomRow
-                 );
-
-  if (ScreenDimensions != NULL) {
-    //
-    // Check local dimension vs. global dimension.
-    //
-    if ((gScreenDimensions.RightColumn < ScreenDimensions->RightColumn) ||
-        (gScreenDimensions.BottomRow < ScreenDimensions->BottomRow)
-        ) {
-      return EFI_INVALID_PARAMETER;
-    } else {
-      //
-      // Local dimension validation.
-      //
-      if ((ScreenDimensions->RightColumn > ScreenDimensions->LeftColumn) &&
-          (ScreenDimensions->BottomRow > ScreenDimensions->TopRow) &&
-          ((ScreenDimensions->RightColumn - ScreenDimensions->LeftColumn) > 2) &&
-          (
-            (ScreenDimensions->BottomRow - ScreenDimensions->TopRow) > STATUS_BAR_HEIGHT +
-            SCROLL_ARROW_HEIGHT *
-            2 +
-            FRONT_PAGE_HEADER_HEIGHT +
-            FOOTER_HEIGHT +
-            1
-          )
-        ) {
-        CopyMem (&gScreenDimensions, (VOID *) ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
-      } else {
-        return EFI_INVALID_PARAMETER;
-      }
-    }
-  }
-
-  gOptionBlockWidth = (CHAR16) ((gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3);
-  gHelpBlockWidth   = gOptionBlockWidth;
-  gPromptBlockWidth = gOptionBlockWidth;
-
-  //
-  // Initialize the strings for the browser, upon exit of the browser, the strings will be freed
-  //
-  InitializeBrowserStrings ();
-
-  gFunctionKeySetting = DEFAULT_FUNCTION_KEY_SETTING;
-  gClassOfVfr         = EFI_SETUP_APPLICATION_SUBCLASS;
-
-  //
-  // Ensure we are in Text mode
-  //
-  if (gFirstIn) {
-    gFirstIn = FALSE;
-    gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
-    DisableQuietBoot ();
-  }
-
-  for (Index = 0; Index < HandleCount; Index++) {
-    Selection = AllocateZeroPool (sizeof (UI_MENU_SELECTION));
-    ASSERT (Selection != NULL);
-
-    Selection->Handle = Handles[Index];
-    if (FormSetGuid != NULL) {
-      CopyMem (&Selection->FormSetGuid, FormSetGuid, sizeof (EFI_GUID));
-      Selection->FormId = FormId;
-    }
-
-    do {
-      FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));
-      ASSERT (FormSet != NULL);
-
-      //
-      // Initialize internal data structures of FormSet
-      //
-      Status = InitializeFormSet (Selection->Handle, &Selection->FormSetGuid, FormSet);
-      if (EFI_ERROR (Status)) {
-        DestroyFormSet (FormSet);
-        break;
-      }
-      Selection->FormSet = FormSet;
-
-      //
-      // Initialize current settings of Questions in this FormSet
-      //
-      Status = InitializeCurrentSetting (FormSet);
-      if (EFI_ERROR (Status)) {
-        DestroyFormSet (FormSet);
-        break;
-      }
-
-      //
-      // Display this formset
-      //
-      gCurrentSelection = Selection;
-
-      Status = SetupBrowser (Selection);
-
-      gCurrentSelection = NULL;
-      DestroyFormSet (FormSet);
-
-      if (EFI_ERROR (Status)) {
-        break;
-      }
-
-    } while (Selection->Action == UI_ACTION_REFRESH_FORMSET);
-
-    gBS->FreePool (Selection);
-  }
-
-  if (ActionRequest != NULL) {
-    *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
-    if (gResetRequired) {
-      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_RESET;
-    }
-  }
-
-  FreeBrowserStrings ();
-
-  gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
-  gST->ConOut->ClearScreen (gST->ConOut);
-
-  return Status;
-}
-
-
-/**
-  This function is called by a callback handler to retrieve uncommitted state
-  data from the browser.
-
-  @param  This                   A pointer to the EFI_FORM_BROWSER2_PROTOCOL
-                                 instance.
-  @param  ResultsDataSize        A pointer to the size of the buffer associated
-                                 with ResultsData.
-  @param  ResultsData            A string returned from an IFR browser or
-                                 equivalent. The results string will have no
-                                 routing information in them.
-  @param  RetrieveData           A BOOLEAN field which allows an agent to retrieve
-                                 (if RetrieveData = TRUE) data from the uncommitted
-                                 browser state information or set (if RetrieveData
-                                 = FALSE) data in the uncommitted browser state
-                                 information.
-  @param  VariableGuid           An optional field to indicate the target variable
-                                 GUID name to use.
-  @param  VariableName           An optional field to indicate the target
-                                 human-readable variable name.
-
-  @retval EFI_SUCCESS            The results have been distributed or are awaiting
-                                 distribution.
-  @retval EFI_BUFFER_TOO_SMALL   The ResultsDataSize specified was too small to
-                                 contain the results data.
-
-**/
-EFI_STATUS
-EFIAPI
-BrowserCallback (
-  IN CONST EFI_FORM_BROWSER2_PROTOCOL  *This,
-  IN OUT UINTN                         *ResultsDataSize,
-  IN OUT EFI_STRING                    ResultsData,
-  IN BOOLEAN                           RetrieveData,
-  IN CONST EFI_GUID                    *VariableGuid, OPTIONAL
-  IN CONST CHAR16                      *VariableName  OPTIONAL
-  )
-{
-  EFI_STATUS            Status;
-  LIST_ENTRY            *Link;
-  FORMSET_STORAGE       *Storage;
-  FORM_BROWSER_FORMSET  *FormSet;
-  BOOLEAN               Found;
-  CHAR16                *ConfigResp;
-  CHAR16                *StrPtr;
-  UINTN                 BufferSize;
-  UINTN                 TmpSize;
-
-  if (ResultsDataSize == NULL || ResultsData == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  if (gCurrentSelection == NULL) {
-    return EFI_NOT_READY;
-  }
-
-  Storage = NULL;
-  ConfigResp = NULL;
-  FormSet = gCurrentSelection->FormSet;
-
-  //
-  // Find target storage
-  //
-  Link = GetFirstNode (&FormSet->StorageListHead);
-  if (IsNull (&FormSet->StorageListHead, Link)) {
-    return EFI_UNSUPPORTED;
-  }
-
-  if (VariableGuid != NULL) {
-    //
-    // Try to find target storage
-    //
-    Found = FALSE;
-    while (!IsNull (&FormSet->StorageListHead, Link)) {
-      Storage = FORMSET_STORAGE_FROM_LINK (Link);
-      Link = GetNextNode (&FormSet->StorageListHead, Link);
-
-      if (CompareGuid (&Storage->Guid, (EFI_GUID *) VariableGuid)) {
-        if (Storage->Type == EFI_HII_VARSTORE_BUFFER) {
-          //
-          // Buffer storage require both GUID and Name
-          //
-          if (VariableName == NULL) {
-            return EFI_NOT_FOUND;
-          }
-
-          if (StrCmp (Storage->Name, (CHAR16 *) VariableName) != 0) {
-            continue;
-          }
-        }
-        Found = TRUE;
-        break;
-      }
-    }
-
-    if (!Found) {
-      return EFI_NOT_FOUND;
-    }
-  } else {
-    //
-    // GUID/Name is not specified, take the first storage in FormSet
-    //
-    Storage = FORMSET_STORAGE_FROM_LINK (Link);
-  }
-
-  if (RetrieveData) {
-    //
-    // Skip if there is no RequestElement
-    //
-    if (Storage->ElementCount == 0) {
-      return EFI_SUCCESS;
-    }
-
-    //
-    // Generate <ConfigResp>
-    //
-    Status = StorageToConfigResp (Storage, &ConfigResp);
-    if (EFI_ERROR (Status)) {
-      return Status;
-    }
-
-    //
-    // Skip <ConfigHdr> and '&' to point to <ConfigBody>
-    //
-    StrPtr = ConfigResp + StrLen (Storage->ConfigHdr) + 1;
-
-    BufferSize = StrSize (StrPtr);
-    if (*ResultsDataSize < BufferSize) {
-      *ResultsDataSize = BufferSize;
-
-      gBS->FreePool (ConfigResp);
-      return EFI_BUFFER_TOO_SMALL;
-    }
-
-    *ResultsDataSize = BufferSize;
-    CopyMem (ResultsData, StrPtr, BufferSize);
-
-    gBS->FreePool (ConfigResp);
-  } else {
-    //
-    // Prepare <ConfigResp>
-    //
-    TmpSize = StrLen (ResultsData);
-    BufferSize = (TmpSize + StrLen (Storage->ConfigHdr) + 2) * sizeof (CHAR16);
-    ConfigResp = AllocateZeroPool (BufferSize);
-    ASSERT (ConfigResp != NULL);
-
-    StrCpy (ConfigResp, Storage->ConfigHdr);
-    StrCat (ConfigResp, L"&");
-    StrCat (ConfigResp, ResultsData);
-
-    //
-    // Update Browser uncommited data
-    //
-    Status = ConfigRespToStorage (Storage, ConfigResp);
-    if (EFI_ERROR (Status)) {
-      return Status;
-    }
-  }
-
-  return EFI_SUCCESS;
-}
-
-
-/**
-  Initialize Setup
-
-  @param  entry                  EFI_IMAGE_ENTRY_POINT)
-
-  @retval EFI_SUCCESS            Setup loaded.
-  @retval other                  Setup Error
-
-**/
-EFI_STATUS
-EFIAPI
-InitializeSetup (
-  IN EFI_HANDLE           ImageHandle,
-  IN EFI_SYSTEM_TABLE     *SystemTable
-  )
-{
-  EFI_STATUS                  Status;
-  EFI_HANDLE                  HiiDriverHandle;
-  EFI_HII_PACKAGE_LIST_HEADER *PackageList;
-
-  //@MT: EfiInitializeDriverLib (ImageHandle, SystemTable);
-
-  //
-  // Locate required Hii relative protocols
-  //
-  Status = gBS->LocateProtocol (
-                  &gEfiHiiDatabaseProtocolGuid,
-                  NULL,
-                  (VOID **) &mHiiDatabase
-                  );
-  ASSERT_EFI_ERROR (Status);
-
-  Status = gBS->LocateProtocol (
-                  &gEfiHiiStringProtocolGuid,
-                  NULL,
-                  (VOID **) &mHiiString
-                  );
-  ASSERT_EFI_ERROR (Status);
-
-  Status = gBS->LocateProtocol (
-                  &gEfiHiiConfigRoutingProtocolGuid,
-                  NULL,
-                  (VOID **) &mHiiConfigRouting
-                  );
-  ASSERT_EFI_ERROR (Status);
-
-  //
-  // Publish our HII data
-  //
-  Status = HiiLibCreateHiiDriverHandle (&HiiDriverHandle);
-  ASSERT_EFI_ERROR (Status);
-
-  PackageList = PreparePackageList (1, &gSetupBrowserGuid, SetupBrowserStrings);
-  ASSERT (PackageList != NULL);
-  Status = mHiiDatabase->NewPackageList (
-                           mHiiDatabase,
-                           PackageList,
-                           HiiDriverHandle,
-                           &gHiiHandle
-                           );
-  ASSERT_EFI_ERROR (Status);
-
-  //
-  // Initialize Driver private data
-  //
-  gFirstIn = TRUE;
-  BannerData = AllocateZeroPool (sizeof (BANNER_DATA));
-  ASSERT (BannerData != NULL);
-
-  //
-  // Install FormBrowser2 protocol
-  //
-  mPrivateData.Handle = NULL;
-  Status = gBS->InstallProtocolInterface (
-                  &mPrivateData.Handle,
-                  &gEfiFormBrowser2ProtocolGuid,
-                  EFI_NATIVE_INTERFACE,
-                  &mPrivateData.FormBrowser2
-                  );
-  ASSERT_EFI_ERROR (Status);
-
-  //
-  // Install Print protocol
-  //
-  Status = gBS->InstallProtocolInterface (
-                  &mPrivateData.Handle,
-                  &gEfiPrintProtocolGuid,
-                  EFI_NATIVE_INTERFACE,
-                  &mPrivateData.Print
-                  );
-
-  return Status;
-}
-
-
-/**
-  Create a new string in HII Package List.
-
-  @param  String                 The String to be added
-  @param  HiiHandle              The package list in the HII database to insert the
-                                 specified string.
-
-  @return The output string.
-
-**/
-EFI_STRING_ID
-NewString (
-  IN  CHAR16                   *String,
-  IN  EFI_HII_HANDLE           HiiHandle
-  )
-{
-  EFI_STRING_ID  StringId;
-  EFI_STATUS     Status;
-
-  StringId = 0;
-  Status = IfrLibNewString (HiiHandle, &StringId, String);
-  ASSERT_EFI_ERROR (Status);
-
-  return StringId;
-}
-
-
-/**
-  Delete a string from HII Package List.
-
-  @param  StringId               Id of the string in HII database.
-  @param  HiiHandle              The HII package list handle.
-
-  @retval EFI_SUCCESS            The string was deleted successfully.
-
-**/
-EFI_STATUS
-DeleteString (
-  IN  EFI_STRING_ID            StringId,
-  IN  EFI_HII_HANDLE           HiiHandle
-  )
-{
-  CHAR16  NullChar;
-
-  NullChar = CHAR_NULL;
-  return IfrLibSetString (HiiHandle, StringId, &NullChar);
-}
-
-
-/**
-  Get the string based on the StringId and HII Package List Handle.
-
-  @param  Token                  The String's ID.
-  @param  HiiHandle              The package list in the HII database to search for
-                                 the specified string.
-
-  @return The output string.
-
-**/
-CHAR16 *
-GetToken (
-  IN  EFI_STRING_ID                Token,
-  IN  EFI_HII_HANDLE               HiiHandle
-  )
-{
-  EFI_STATUS  Status;
-  CHAR16      *String;
-  UINTN       BufferLength;
-
-  //
-  // Set default string size assumption at no more than 256 bytes
-  //
-  BufferLength = 0x100;
-  String = AllocateZeroPool (BufferLength);
-  ASSERT (String != NULL);
-
-  Status = IfrLibGetString (HiiHandle, Token, String, &BufferLength);
-
-  if (Status == EFI_BUFFER_TOO_SMALL) {
-    gBS->FreePool (String);
-    String = AllocateZeroPool (BufferLength);
-    ASSERT (String != NULL);
-
-    Status = IfrLibGetString (HiiHandle, Token, String, &BufferLength);
-  }
-  ASSERT_EFI_ERROR (Status);
-
-  return String;
-}
-
-
-/**
-  Allocate new memory and then copy the Unicode string Source to Destination.
-
-  @param  Dest                   Location to copy string
-  @param  Src                    String to copy
-
-  @return NONE
-
-**/
-VOID
-NewStringCpy (
-  IN OUT CHAR16       **Dest,
-  IN CHAR16           *Src
-  )
-{
-  SafeFreePool (*Dest);
-  *Dest = AllocateCopyPool (StrSize (Src), Src);
-  ASSERT (*Dest != NULL);
-}
-
-
-/**
-  Allocate new memory and concatinate Source on the end of Destination.
-
-  @param  Dest                   String to added to the end of.
-  @param  Src                    String to concatinate.
-
-  @return NONE
-
-**/
-VOID
-NewStringCat (
-  IN OUT CHAR16       **Dest,
-  IN CHAR16           *Src
-  )
-{
-  CHAR16  *NewString;
-  UINTN   TmpSize;
-
-  if (*Dest == NULL) {
-    NewStringCpy (Dest, Src);
-    return;
-  }
-
-  TmpSize = StrSize (*Dest);
-  NewString = AllocateZeroPool (TmpSize + StrSize (Src) - 1);
-  ASSERT (NewString != NULL);
-
-  StrCpy (NewString, *Dest);
-  StrCat (NewString, Src);
-
-  gBS->FreePool (*Dest);
-  *Dest = NewString;
-}
-
-
-/**
-  Synchronize Storage's Edit copy to Shadow copy.
-
-  @param  Storage                The Storage to be synchronized.
-
-  @return NONE
-
-**/
-VOID
-SynchronizeStorage (
-  IN FORMSET_STORAGE         *Storage
-  )
-{
-  LIST_ENTRY              *Link;
-  NAME_VALUE_NODE         *Node;
-
-  switch (Storage->Type) {
-  case EFI_HII_VARSTORE_BUFFER:
-    CopyMem (Storage->Buffer, Storage->EditBuffer, Storage->Size);
-    break;
-
-  case EFI_HII_VARSTORE_NAME_VALUE:
-    Link = GetFirstNode (&Storage->NameValueListHead);
-    while (!IsNull (&Storage->NameValueListHead, Link)) {
-      Node = NAME_VALUE_NODE_FROM_LINK (Link);
-
-      NewStringCpy (&Node->Value, Node->EditValue);
-
-      Link = GetNextNode (&Storage->NameValueListHead, Link);
-    }
-    break;
-
-  case EFI_HII_VARSTORE_EFI_VARIABLE:
-  default:
-    break;
-  }
-}
-
-
-/**
-  Get Value for given Name from a NameValue Storage.
-
-  @param  Storage                The NameValue Storage.
-  @param  Name                   The Name.
-  @param  Value                  The retured Value.
-
-  @retval EFI_SUCCESS            Value found for given Name.
-  @retval EFI_NOT_FOUND          No such Name found in NameValue storage.
-
-**/
-EFI_STATUS
-GetValueByName (
-  IN FORMSET_STORAGE         *Storage,
-  IN CHAR16                  *Name,
-  IN OUT CHAR16              **Value
-  )
-{
-  LIST_ENTRY              *Link;
-  NAME_VALUE_NODE         *Node;
-
-  *Value = NULL;
-
-  Link = GetFirstNode (&Storage->NameValueListHead);
-  while (!IsNull (&Storage->NameValueListHead, Link)) {
-    Node = NAME_VALUE_NODE_FROM_LINK (Link);
-
-    if (StrCmp (Name, Node->Name) == 0) {
-      NewStringCpy (Value, Node->EditValue);
-      return EFI_SUCCESS;
-    }
-
-    Link = GetNextNode (&Storage->NameValueListHead, Link);
-  }
-
-  return EFI_NOT_FOUND;
-}
-
-
-/**
-  Set Value of given Name in a NameValue Storage.
-
-  @param  Storage                The NameValue Storage.
-  @param  Name                   The Name.
-  @param  Value                  The Value to set.
-
-  @retval EFI_SUCCESS            Value found for given Name.
-  @retval EFI_NOT_FOUND          No such Name found in NameValue storage.
-
-**/
-EFI_STATUS
-SetValueByName (
-  IN FORMSET_STORAGE         *Storage,
-  IN CHAR16                  *Name,
-  IN CHAR16                  *Value
-  )
-{
-  LIST_ENTRY              *Link;
-  NAME_VALUE_NODE         *Node;
-
-  Link = GetFirstNode (&Storage->NameValueListHead);
-  while (!IsNull (&Storage->NameValueListHead, Link)) {
-    Node = NAME_VALUE_NODE_FROM_LINK (Link);
-
-    if (StrCmp (Name, Node->Name) == 0) {
-      SafeFreePool (Node->EditValue);
-      Node->EditValue = AllocateCopyPool (StrSize (Value), Value);
-      ASSERT (Node->EditValue != NULL);
-      return EFI_SUCCESS;
-    }
-
-    Link = GetNextNode (&Storage->NameValueListHead, Link);
-  }
-
-  return EFI_NOT_FOUND;
-}
-
-
-/**
-  Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
-
-  @param  Storage                The Storage to be conveted.
-  @param  ConfigResp             The returned <ConfigResp>.
-
-  @retval EFI_SUCCESS            Convert success.
-  @retval EFI_INVALID_PARAMETER  Incorrect storage type.
-
-**/
-EFI_STATUS
-StorageToConfigResp (
-  IN FORMSET_STORAGE         *Storage,
-  IN CHAR16                  **ConfigResp
-  )
-{
-  EFI_STATUS  Status;
-  EFI_STRING  Progress;
-  LIST_ENTRY              *Link;
-  NAME_VALUE_NODE         *Node;
-
-  Status = EFI_SUCCESS;
-
-  switch (Storage->Type) {
-  case EFI_HII_VARSTORE_BUFFER:
-    Status = mHiiConfigRouting->BlockToConfig (
-                                  mHiiConfigRouting,
-                                  Storage->ConfigRequest,
-                                  Storage->EditBuffer,
-                                  Storage->Size,
-                                  ConfigResp,
-                                  &Progress
-                                  );
-    break;
-
-  case EFI_HII_VARSTORE_NAME_VALUE:
-    *ConfigResp = NULL;
-    NewStringCat (ConfigResp, Storage->ConfigHdr);
-
-    Link = GetFirstNode (&Storage->NameValueListHead);
-    while (!IsNull (&Storage->NameValueListHead, Link)) {
-      Node = NAME_VALUE_NODE_FROM_LINK (Link);
-
-      NewStringCat (ConfigResp, L"&");
-      NewStringCat (ConfigResp, Node->Name);
-      NewStringCat (ConfigResp, L"=");
-      NewStringCat (ConfigResp, Node->EditValue);
-
-      Link = GetNextNode (&Storage->NameValueListHead, Link);
-    }
-    break;
-
-  case EFI_HII_VARSTORE_EFI_VARIABLE:
-  default:
-    Status = EFI_INVALID_PARAMETER;
-    break;
-  }
-
-  return Status;
-}
-
-
-/**
-  Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
-
-  @param  Storage                The Storage to receive the settings.
-  @param  ConfigResp             The <ConfigResp> to be converted.
-
-  @retval EFI_SUCCESS            Convert success.
-  @retval EFI_INVALID_PARAMETER  Incorrect storage type.
-
-**/
-EFI_STATUS
-ConfigRespToStorage (
-  IN FORMSET_STORAGE         *Storage,
-  IN CHAR16                  *ConfigResp
-  )
-{
-  EFI_STATUS  Status;
-  EFI_STRING  Progress;
-  UINTN       BufferSize;
-  CHAR16      *StrPtr;
-  CHAR16      *Name;
-  CHAR16      *Value;
-
-  Status = EFI_SUCCESS;
-
-  switch (Storage->Type) {
-  case EFI_HII_VARSTORE_BUFFER:
-    BufferSize = Storage->Size;
-    Status = mHiiConfigRouting->ConfigToBlock (
-                                  mHiiConfigRouting,
-                                  ConfigResp,
-                                  Storage->EditBuffer,
-                                  &BufferSize,
-                                  &Progress
-                                  );
-    break;
-
-  case EFI_HII_VARSTORE_NAME_VALUE:
-    StrPtr = StrStr (ConfigResp, L"&");
-    while (StrPtr != NULL) {
-      //
-      // Skip '&'
-      //
-      StrPtr = StrPtr + 1;
-      Name = StrPtr;
-      StrPtr = StrStr (StrPtr, L"=");
-      if (StrPtr == NULL) {
-        break;
-      }
-      *StrPtr = 0;
-
-      //
-      // Skip '='
-      //
-      StrPtr = StrPtr + 1;
-      Value = StrPtr;
-      StrPtr = StrStr (StrPtr, L"&");
-      if (StrPtr != NULL) {
-        *StrPtr = 0;
-      }
-      SetValueByName (Storage, Name, Value);
-    }
-    break;
-
-  case EFI_HII_VARSTORE_EFI_VARIABLE:
-  default:
-    Status = EFI_INVALID_PARAMETER;
-    break;
-  }
-
-  return Status;
-}
-
-
-/**
-  Get Question's current Value.
-
-  @param  FormSet                FormSet data structure.
-  @param  Form                   Form data structure.
-  @param  Question               Question to be initialized.
-  @param  Cached                 TRUE:  get from Edit copy FALSE: get from original
-                                 Storage
-
-  @retval EFI_SUCCESS            The function completed successfully.
-
-**/
-EFI_STATUS
-GetQuestionValue (
-  IN FORM_BROWSER_FORMSET             *FormSet,
-  IN FORM_BROWSER_FORM                *Form,
-  IN OUT FORM_BROWSER_STATEMENT       *Question,
-  IN BOOLEAN                          Cached
-  )
-{
-  EFI_STATUS          Status;
-  BOOLEAN             Enabled;
-  BOOLEAN             Pending;
-  UINT8               *Dst;
-  UINTN               StorageWidth;
-  EFI_TIME            EfiTime;
-  FORMSET_STORAGE     *Storage;
-  EFI_IFR_TYPE_VALUE  *QuestionValue;
-  CHAR16              *ConfigRequest;
-  CHAR16              *Progress;
-  CHAR16              *Result;
-  CHAR16              *Value;
-  UINTN               Length;
-  BOOLEAN             IsBufferStorage;
-  BOOLEAN             IsString;
-
-  Status = EFI_SUCCESS;
-
-  //
-  // Statement don't have storage, skip them
-  //
-  if (Question->QuestionId == 0) {
-    return Status;
-  }
-
-  //
-  // Question value is provided by an Expression, evaluate it
-  //
-  if (Question->ValueExpression != NULL) {
-    Status = EvaluateExpression (FormSet, Form, Question->ValueExpression);
-    if (!EFI_ERROR (Status)) {
-      CopyMem (&Question->HiiValue, &Question->ValueExpression->Result, sizeof (EFI_HII_VALUE));
-    }
-    return Status;
-  }
-
-  //
-  // Question value is provided by RTC
-  //
-  Storage = Question->Storage;
-  QuestionValue = &Question->HiiValue.Value;
-  if (Storage == NULL) {
-    //
-    // It's a Question without storage, or RTC date/time
-    //
-    if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {
-      //
-      // Date and time define the same Flags bit
-      //
-      switch (Question->Flags & EFI_QF_DATE_STORAGE) {
-      case QF_DATE_STORAGE_TIME:
-        Status = gRT->GetTime (&EfiTime, NULL);
-        break;
-
-      case QF_DATE_STORAGE_WAKEUP:
-        Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);
-        break;
-
-      case QF_DATE_STORAGE_NORMAL:
-      default:
-        //
-        // For date/time without storage
-        //
-        return EFI_SUCCESS;
-      }
-
-      if (EFI_ERROR (Status)) {
-        return Status;
-      }
-
-      if (Question->Operand == EFI_IFR_DATE_OP) {
-        QuestionValue->date.Year  = EfiTime.Year;
-        QuestionValue->date.Month = EfiTime.Month;
-        QuestionValue->date.Day   = EfiTime.Day;
-      } else {
-        QuestionValue->time.Hour   = EfiTime.Hour;
-        QuestionValue->time.Minute = EfiTime.Minute;
-        QuestionValue->time.Second = EfiTime.Second;
-      }
-    }
-
-    return EFI_SUCCESS;
-  }
-
-  //
-  // Question value is provided by EFI variable
-  //
-  StorageWidth = Question->StorageWidth;
-  if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
-    if (Question->BufferValue != NULL) {
-      Dst = Question->BufferValue;
-    } else {
-      Dst = (UINT8 *) QuestionValue;
-    }
-
-    Status = gRT->GetVariable (
-                     Question->VariableName,
-                     &Storage->Guid,
-                     NULL,
-                     &StorageWidth,
-                     Dst
-                     );
-    //
-    // Always return success, even this EFI variable doesn't exist
-    //
-    return EFI_SUCCESS;
-  }
-
-  //
-  // Question Value is provided by Buffer Storage or NameValue Storage
-  //
-  if (Question->BufferValue != NULL) {
-    //
-    // This Question is password or orderedlist
-    //
-    Dst = Question->BufferValue;
-  } else {
-    //
-    // Other type of Questions
-    //
-    Dst = (UINT8 *) &Question->HiiValue.Value;
-  }
-
-  IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);
-  IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ?  TRUE : FALSE);
-  if (Cached) {
-    if (IsBufferStorage) {
-      //
-      // Copy from storage Edit buffer
-      //
-      CopyMem (Dst, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth);
-    } else {
-      Status = GetValueByName (Storage, Question->VariableName, &Value);
-      if (EFI_ERROR (Status)) {
-        return Status;
-      }
-
-      if (IsString) {
-        StrCpy ((CHAR16 *) Dst, Value);
-      } else {
-        Status = R8_HexStringToBuf (Dst, &StorageWidth, Value, NULL);
-      }
-
-      gBS->FreePool (Value);
-    }
-  } else {
-    //
-    // Request current settings from Configuration Driver
-    //
-    if (FormSet->ConfigAccess == NULL) {
-      return EFI_NOT_FOUND;
-    }
-
-    //
-    // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
-    //                   <ConfigHdr> + "&" + <VariableName>
-    //
-    if (IsBufferStorage) {
-      Length = StrLen (Storage->ConfigHdr);
-      Length += StrLen (Question->BlockName);
-    } else {
-      Length = StrLen (Storage->ConfigHdr);
-      Length += StrLen (Question->VariableName) + 1;
-    }
-    ConfigRequest = AllocateZeroPool ((Length + 1) * sizeof (CHAR16));
-    ASSERT (ConfigRequest != NULL);
-
-    StrCpy (ConfigRequest, Storage->ConfigHdr);
-    if (IsBufferStorage) {
-      StrCat (ConfigRequest, Question->BlockName);
-    } else {
-      StrCat (ConfigRequest, L"&");
-      StrCat (ConfigRequest, Question->VariableName);
-    }
-
-    Status = FormSet->ConfigAccess->ExtractConfig (
-                                      FormSet->ConfigAccess,
-                                      ConfigRequest,
-                                      &Progress,
-                                      &Result
-                                      );
-    if (EFI_ERROR (Status)) {
-      return Status;
-    }
-
-    //
-    // Skip <ConfigRequest>
-    //
-    Value = Result + Length;
-    if (IsBufferStorage) {
-      //
-      // Skip "&VALUE"
-      //
-      Value = Value + 6;
-    }
-    if (*Value != '=') {
-      gBS->FreePool (Result);
-      return EFI_NOT_FOUND;
-    }
-    //
-    // Skip '=', point to value
-    //
-    Value = Value + 1;
-    if (!IsBufferStorage && IsString) {
-      StrCpy ((CHAR16 *) Dst, Value);
-    } else {
-      Status = R8_HexStringToBuf (Dst, &StorageWidth, Value, NULL);
-      if (EFI_ERROR (Status)) {
-        gBS->FreePool (Result);
-        return Status;
-      }
-    }
-
-    //
-    // Synchronize Edit Buffer
-    //
-    if (IsBufferStorage) {
-      CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth);
-    } else {
-      SetValueByName (Storage, Question->VariableName, Value);
-    }
-    gBS->FreePool (Result);
-  }
-
-  return Status;
-}
-
-
-/**
-  Save Question Value to edit copy(cached) or Storage(uncached).
-
-  @param  FormSet                FormSet data structure.
-  @param  Form                   Form data structure.
-  @param  Question               Pointer to the Question.
-  @param  Cached                 TRUE:  set to Edit copy FALSE: set to original
-                                 Storage
-
-  @retval EFI_SUCCESS            The function completed successfully.
-
-**/
-EFI_STATUS
-SetQuestionValue (
-  IN FORM_BROWSER_FORMSET             *FormSet,
-  IN FORM_BROWSER_FORM                *Form,
-  IN OUT FORM_BROWSER_STATEMENT       *Question,
-  IN BOOLEAN                          Cached
-  )
-{
-  EFI_STATUS          Status;
-  BOOLEAN             Enabled;
-  BOOLEAN             Pending;
-  UINT8               *Src;
-  EFI_TIME            EfiTime;
-  UINTN               BufferLen;
-  UINTN               StorageWidth;
-  FORMSET_STORAGE     *Storage;
-  EFI_IFR_TYPE_VALUE  *QuestionValue;
-  CHAR16              *ConfigResp;
-  CHAR16              *Progress;
-  CHAR16              *Value;
-  UINTN               Length;
-  BOOLEAN             IsBufferStorage;
-  BOOLEAN             IsString;
-
-  Status = EFI_SUCCESS;
-
-  //
-  // Statement don't have storage, skip them
-  //
-  if (Question->QuestionId == 0) {
-    return Status;
-  }
-
-  //
-  // If Question value is provided by an Expression, then it is read only
-  //
-  if (Question->ValueExpression != NULL) {
-    return Status;
-  }
-
-  //
-  // Question value is provided by RTC
-  //
-  Storage = Question->Storage;
-  QuestionValue = &Question->HiiValue.Value;
-  if (Storage == NULL) {
-    //
-    // It's a Question without storage, or RTC date/time
-    //
-    if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {
-      //
-      // Date and time define the same Flags bit
-      //
-      switch (Question->Flags & EFI_QF_DATE_STORAGE) {
-      case QF_DATE_STORAGE_TIME:
-        Status = gRT->GetTime (&EfiTime, NULL);
-        break;
-
-      case QF_DATE_STORAGE_WAKEUP:
-        Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);
-        break;
-
-      case QF_DATE_STORAGE_NORMAL:
-      default:
-        //
-        // For date/time without storage
-        //
-        return EFI_SUCCESS;
-      }
-
-      if (EFI_ERROR (Status)) {
-        return Status;
-      }
-
-      if (Question->Operand == EFI_IFR_DATE_OP) {
-        EfiTime.Year  = QuestionValue->date.Year;
-        EfiTime.Month = QuestionValue->date.Month;
-        EfiTime.Day   = QuestionValue->date.Day;
-      } else {
-        EfiTime.Hour   = QuestionValue->time.Hour;
-        EfiTime.Minute = QuestionValue->time.Minute;
-        EfiTime.Second = QuestionValue->time.Second;
-      }
-
-      if ((Question->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_TIME) {
-        Status = gRT->SetTime (&EfiTime);
-      } else {
-        Status = gRT->SetWakeupTime (TRUE, &EfiTime);
-      }
-    }
-
-    return Status;
-  }
-
-  //
-  // Question value is provided by EFI variable
-  //
-  StorageWidth = Question->StorageWidth;
-  if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
-    if (Question->BufferValue != NULL) {
-      Src = Question->BufferValue;
-    } else {
-      Src = (UINT8 *) QuestionValue;
-    }
-
-    Status = gRT->SetVariable (
-                     Question->VariableName,
-                     &Storage->Guid,
-                     Storage->Attributes,
-                     StorageWidth,
-                     Src
-                     );
-    return Status;
-  }
-
-  //
-  // Question Value is provided by Buffer Storage or NameValue Storage
-  //
-  if (Question->BufferValue != NULL) {
-    Src = Question->BufferValue;
-  } else {
-    Src = (UINT8 *) &Question->HiiValue.Value;
-  }
-
-  IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);
-  IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ?  TRUE : FALSE);
-  if (IsBufferStorage) {
-    //
-    // Copy to storage edit buffer
-    //
-    CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);
-  } else {
-    if (IsString) {
-      Value = NULL;
-      NewStringCpy (&Value, (CHAR16 *) Src);
-    } else {
-      BufferLen = (StorageWidth * 2 + 1) * sizeof (CHAR16);
-      Value = AllocateZeroPool (BufferLen);
-      ASSERT (Value != NULL);
-      R8_BufToHexString (Value, &BufferLen, Src, StorageWidth);
-    }
-
-    Status = SetValueByName (Storage, Question->VariableName, Value);
-    gBS->FreePool (Value);
-  }
-
-  if (!Cached) {
-    //
-    // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
-    //                <ConfigHdr> + "&" + <VariableName> + "=" + "<HexCh>StorageWidth * 2"
-    //
-    if (IsBufferStorage) {
-      Length = StrLen (Question->BlockName) + 7;
-    } else {
-      Length = StrLen (Question->VariableName) + 2;
-    }
-    if (!IsBufferStorage && IsString) {
-      Length += StrLen ((CHAR16 *) Src);
-    } else {
-      Length += (StorageWidth * 2);
-    }
-    ConfigResp = AllocateZeroPool ((StrLen (Storage->ConfigHdr) + Length + 1) * sizeof (CHAR16));
-    ASSERT (ConfigResp != NULL);
-
-    StrCpy (ConfigResp, Storage->ConfigHdr);
-    if (IsBufferStorage) {
-      StrCat (ConfigResp, Question->BlockName);
-      StrCat (ConfigResp, L"&VALUE=");
-    } else {
-      StrCat (ConfigResp, L"&");
-      StrCat (ConfigResp, Question->VariableName);
-      StrCat (ConfigResp, L"=");
-    }
-
-    Value = ConfigResp + StrLen (ConfigResp);
-    if (!IsBufferStorage && IsString) {
-      StrCpy (Value, (CHAR16 *) Src);
-    } else {
-      BufferLen = (StorageWidth * 2 + 1) * sizeof (CHAR16);
-      R8_BufToHexString (Value, &BufferLen, Src, StorageWidth);
-    }
-
-    //
-    // Submit Question Value to Configuration Driver
-    //
-    if (FormSet->ConfigAccess != NULL) {
-      Status = FormSet->ConfigAccess->RouteConfig (
-                                        FormSet->ConfigAccess,
-                                        ConfigResp,
-                                        &Progress
-                                        );
-      if (EFI_ERROR (Status)) {
-        gBS->FreePool (ConfigResp);
-        return Status;
-      }
-    }
-    gBS->FreePool (ConfigResp);
-
-    //
-    // Synchronize shadow Buffer
-    //
-    SynchronizeStorage (Storage);
-  }
-
-  return Status;
-}
-
-
-/**
-  Perform inconsistent check for a Form.
-
-  @param  FormSet                FormSet data structure.
-  @param  Form                   Form data structure.
-  @param  Question               The Question to be validated.
-  @param  Type                   Validation type: InConsistent or NoSubmit
-
-  @retval EFI_SUCCESS            Form validation pass.
-  @retval other                  Form validation failed.
-
-**/
-EFI_STATUS
-ValidateQuestion (
-  IN  FORM_BROWSER_FORMSET            *FormSet,
-  IN  FORM_BROWSER_FORM               *Form,
-  IN  FORM_BROWSER_STATEMENT          *Question,
-  IN  UINTN                           Type
-  )
-{
-  EFI_STATUS              Status;
-  LIST_ENTRY              *Link;
-  LIST_ENTRY              *ListHead;
-  EFI_STRING              PopUp;
-  EFI_INPUT_KEY           Key;
-  FORM_EXPRESSION         *Expression;
-
-  if (Type == EFI_HII_EXPRESSION_INCONSISTENT_IF) {
-    ListHead = &Question->InconsistentListHead;
-  } else if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {
-    ListHead = &Question->NoSubmitListHead;
-  } else {
-    return EFI_UNSUPPORTED;
-  }
-
-  Link = GetFirstNode (ListHead);
-  while (!IsNull (ListHead, Link)) {
-    Expression = FORM_EXPRESSION_FROM_LINK (Link);
-
-    //
-    // Evaluate the expression
-    //
-    Status = EvaluateExpression (FormSet, Form, Expression);
-    if (EFI_ERROR (Status)) {
-      return Status;
-    }
-
-    if (Expression->Result.Value.b) {
-      //
-      // Condition meet, show up error message
-      //
-      if (Expression->Error != 0) {
-        PopUp = GetToken (Expression->Error, FormSet->HiiHandle);
-        do {
-          CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, PopUp, gPressEnter, gEmptyString);
-        } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
-        gBS->FreePool (PopUp);
-      }
-
-      return EFI_NOT_READY;
-    }
-
-    Link = GetNextNode (ListHead, Link);
-  }
-
-  return EFI_SUCCESS;
-}
-
-
-/**
-  Perform NoSubmit check for a Form.
-
-  @param  FormSet                FormSet data structure.
-  @param  Form                   Form data structure.
-
-  @retval EFI_SUCCESS            Form validation pass.
-  @retval other                  Form validation failed.
-
-**/
-EFI_STATUS
-NoSubmitCheck (
-  IN  FORM_BROWSER_FORMSET            *FormSet,
-  IN  FORM_BROWSER_FORM               *Form
-  )
-{
-  EFI_STATUS              Status;
-  LIST_ENTRY              *Link;
-  FORM_BROWSER_STATEMENT  *Question;
-
-  Link = GetFirstNode (&Form->StatementListHead);
-  while (!IsNull (&Form->StatementListHead, Link)) {
-    Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
-
-    Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_NO_SUBMIT_IF);
-    if (EFI_ERROR (Status)) {
-      return Status;
-    }
-
-    Link = GetNextNode (&Form->StatementListHead, Link);
-  }
-
-  return EFI_SUCCESS;
-}
-
-
-/**
-  Submit a Form.
-
-  @param  FormSet                FormSet data structure.
-  @param  Form                   Form data structure.
-
-  @retval EFI_SUCCESS            The function completed successfully.
-
-**/
-EFI_STATUS
-SubmitForm (
-  IN FORM_BROWSER_FORMSET             *FormSet,
-  IN FORM_BROWSER_FORM                *Form
-  )
-{
-  EFI_STATUS              Status;
-  LIST_ENTRY              *Link;
-  EFI_STRING              ConfigResp;
-  EFI_STRING              Progress;
-  FORMSET_STORAGE         *Storage;
-
-  //
-  // Validate the Form by NoSubmit check
-  //
-  Status = NoSubmitCheck (FormSet, Form);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  //
-  // Submit Buffer storage or Name/Value storage
-  //
-  Link = GetFirstNode (&FormSet->StorageListHead);
-  while (!IsNull (&FormSet->StorageListHead, Link)) {
-    Storage = FORMSET_STORAGE_FROM_LINK (Link);
-    Link = GetNextNode (&FormSet->StorageListHead, Link);
-
-    if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
-      continue;
-    }
-
-    //
-    // Skip if there is no RequestElement
-    //
-    if (Storage->ElementCount == 0) {
-      continue;
-    }
-
-    //
-    // Prepare <ConfigResp>
-    //
-    Status = StorageToConfigResp (Storage, &ConfigResp);
-    if (EFI_ERROR (Status)) {
-      return Status;
-    }
-
-    //
-    // Send <ConfigResp> to Configuration Driver
-    //
-    if (FormSet->ConfigAccess != NULL) {
-      Status = FormSet->ConfigAccess->RouteConfig (
-                                        FormSet->ConfigAccess,
-                                        ConfigResp,
-                                        &Progress
-                                        );
-      if (EFI_ERROR (Status)) {
-        gBS->FreePool (ConfigResp);
-        return Status;
-      }
-    }
-    gBS->FreePool (ConfigResp);
-
-    //
-    // Config success, update storage shadow Buffer
-    //
-    SynchronizeStorage (Storage);
-  }
-
-  gNvUpdateRequired = FALSE;
-
-  return EFI_SUCCESS;
-}
-
-
-/**
-  Reset Question to its default value.
-
-  @param  FormSet                FormSet data structure.
-  @param  DefaultId              The Class of the default.
-
-  @retval EFI_SUCCESS            Question is reset to default value.
-
-**/
-EFI_STATUS
-GetQuestionDefault (
-  IN FORM_BROWSER_FORMSET             *FormSet,
-  IN FORM_BROWSER_FORM                *Form,
-  IN FORM_BROWSER_STATEMENT           *Question,
-  IN UINT16                           DefaultId
-  )
-{
-  EFI_STATUS              Status;
-  LIST_ENTRY              *Link;
-  QUESTION_DEFAULT        *Default;
-  QUESTION_OPTION         *Option;
-  EFI_HII_VALUE           *HiiValue;
-  UINT8                   Index;
-
-  Status = EFI_SUCCESS;
-
-  //
-  // Statement don't have storage, skip them
-  //
-  if (Question->QuestionId == 0) {
-    return Status;
-  }
-
-  //
-  // There are three ways to specify default value for a Question:
-  //  1, use nested EFI_IFR_DEFAULT (highest priority)
-  //  2, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
-  //  3, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
-  //
-  HiiValue = &Question->HiiValue;
-
-  //
-  // EFI_IFR_DEFAULT has highest priority
-  //
-  if (!IsListEmpty (&Question->DefaultListHead)) {
-    Link = GetFirstNode (&Question->DefaultListHead);
-    while (!IsNull (&Question->DefaultListHead, Link)) {
-      Default = QUESTION_DEFAULT_FROM_LINK (Link);
-
-      if (Default->DefaultId == DefaultId) {
-        if (Default->ValueExpression != NULL) {
-          //
-          // Default is provided by an Expression, evaluate it
-          //
-          Status = EvaluateExpression (FormSet, Form, Default->ValueExpression);
-          if (EFI_ERROR (Status)) {
-            return Status;
-          }
-
-          CopyMem (HiiValue, &Default->ValueExpression->Result, sizeof (EFI_HII_VALUE));
-        } else {
-          //
-          // Default value is embedded in EFI_IFR_DEFAULT
-          //
-          CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));
-        }
-
-        return EFI_SUCCESS;
-      }
-
-      Link = GetNextNode (&Question->DefaultListHead, Link);
-    }
-  }
-
-  //
-  // EFI_ONE_OF_OPTION
-  //
-  if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {
-    if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING)  {
-      //
-      // OneOfOption could only provide Standard and Manufacturing default
-      //
-      Link = GetFirstNode (&Question->OptionListHead);
-      while (!IsNull (&Question->OptionListHead, Link)) {
-        Option = QUESTION_OPTION_FROM_LINK (Link);
-
-        if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && (Option->Flags & EFI_IFR_OPTION_DEFAULT)) ||
-            ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && (Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG))
-           ) {
-          CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));
-
-          return EFI_SUCCESS;
-        }
-
-        Link = GetNextNode (&Question->OptionListHead, Link);
-      }
-    }
-  }
-
-  //
-  // EFI_IFR_CHECKBOX - lowest priority
-  //
-  if (Question->Operand == EFI_IFR_CHECKBOX_OP) {
-    if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING)  {
-      //
-      // Checkbox could only provide Standard and Manufacturing default
-      //
-      if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && (Question->Flags & EFI_IFR_CHECKBOX_DEFAULT)) ||
-          ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && (Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG))
-         ) {
-        HiiValue->Value.b = TRUE;
-      } else {
-        HiiValue->Value.b = FALSE;
-      }
-
-      return EFI_SUCCESS;
-    }
-  }
-
-  //
-  // For Questions without default
-  //
-  switch (Question->Operand) {
-  case EFI_IFR_NUMERIC_OP:
-    //
-    // Take minimal value as numeric's default value
-    //
-    HiiValue->Value.u64 = Question->Minimum;
-    break;
-
-  case EFI_IFR_ONE_OF_OP:
-    //
-    // Take first oneof option as oneof's default value
-    //
-    Link = GetFirstNode (&Question->OptionListHead);
-    if (!IsNull (&Question->OptionListHead, Link)) {
-      Option = QUESTION_OPTION_FROM_LINK (Link);
-      CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));
-    }
-    break;
-
-  case EFI_IFR_ORDERED_LIST_OP:
-    //
-    // Take option sequence in IFR as ordered list's default value
-    //
-    Index = 0;
-    Link = GetFirstNode (&Question->OptionListHead);
-    while (!IsNull (&Question->OptionListHead, Link)) {
-      Option = QUESTION_OPTION_FROM_LINK (Link);
-
-      Question->BufferValue[Index] = Option->Value.Value.u8;
-
-      Index++;
-      if (Index >= Question->MaxContainers) {
-        break;
-      }
-
-      Link = GetNextNode (&Question->OptionListHead, Link);
-    }
-    break;
-
-  default:
-    Status = EFI_NOT_FOUND;
-    break;
-  }
-
-  return Status;
-}
-
-
-/**
-  Reset Questions in a Form to their default value.
-
-  @param  FormSet                FormSet data structure.
-  @param  Form                   The Form which to be reset.
-  @param  DefaultId              The Class of the default.
-
-  @retval EFI_SUCCESS            The function completed successfully.
-
-**/
-EFI_STATUS
-ExtractFormDefault (
-  IN FORM_BROWSER_FORMSET             *FormSet,
-  IN FORM_BROWSER_FORM                *Form,
-  IN UINT16                           DefaultId
-  )
-{
-  EFI_STATUS              Status;
-  LIST_ENTRY              *Link;
-  FORM_BROWSER_STATEMENT  *Question;
-
-  Link = GetFirstNode (&Form->StatementListHead);
-  while (!IsNull (&Form->StatementListHead, Link)) {
-    Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
-    Link = GetNextNode (&Form->StatementListHead, Link);
-
-    //
-    // Reset Question to its default value
-    //
-    Status = GetQuestionDefault (FormSet, Form, Question, DefaultId);
-    if (EFI_ERROR (Status)) {
-      continue;
-    }
-
-    //
-    // Synchronize Buffer storage's Edit buffer
-    //
-    if ((Question->Storage != NULL) &&
-        (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) {
-      SetQuestionValue (FormSet, Form, Question, TRUE);
-    }
-  }
-
-  return EFI_SUCCESS;
-}
-
-
-/**
-  Initialize Question's Edit copy from Storage.
-
-  @param  FormSet                FormSet data structure.
-  @param  Form                   Form data structure.
-
-  @retval EFI_SUCCESS            The function completed successfully.
-
-**/
-EFI_STATUS
-LoadFormConfig (
-  IN FORM_BROWSER_FORMSET             *FormSet,
-  IN FORM_BROWSER_FORM                *Form
-  )
-{
-  EFI_STATUS              Status;
-  LIST_ENTRY              *Link;
-  FORM_BROWSER_STATEMENT  *Question;
-
-  Link = GetFirstNode (&Form->StatementListHead);
-  while (!IsNull (&Form->StatementListHead, Link)) {
-    Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
-
-    //
-    // Initialize local copy of Value for each Question
-    //
-    Status = GetQuestionValue (FormSet, Form, Question, TRUE);
-    if (EFI_ERROR (Status)) {
-      return Status;
-    }
-
-    Link = GetNextNode (&Form->StatementListHead, Link);
-  }
-
-  return EFI_SUCCESS;
-}
-
-
-/**
-  Fill storage's edit copy with settings requested from Configuration Driver.
-
-  @param  FormSet                FormSet data structure.
-  @param  Storage                Buffer Storage.
-
-  @retval EFI_SUCCESS            The function completed successfully.
-
-**/
-EFI_STATUS
-LoadStorage (
-  IN FORM_BROWSER_FORMSET    *FormSet,
-  IN FORMSET_STORAGE         *Storage
-  )
-{
-  EFI_STATUS  Status;
-  EFI_STRING  Progress;
-  EFI_STRING  Result;
-  CHAR16      *StrPtr;
-
-  if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
-    return EFI_SUCCESS;
-  }
-
-  if (FormSet->ConfigAccess == NULL) {
-    return EFI_NOT_FOUND;
-  }
-
-  if (Storage->ElementCount == 0) {
-    //
-    // Skip if there is no RequestElement
-    //
-    return EFI_SUCCESS;
-  }
-
-  //
-  // Request current settings from Configuration Driver
-  //
-  Status = FormSet->ConfigAccess->ExtractConfig (
-                                    FormSet->ConfigAccess,
-                                    Storage->ConfigRequest,
-                                    &Progress,
-                                    &Result
-                                    );
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  //
-  // Convert Result from <ConfigAltResp> to <ConfigResp>
-  //
-  StrPtr = StrStr (Result, L"ALTCFG");
-  if (StrPtr != NULL) {
-    *StrPtr = L'\0';
-  }
-
-  Status = ConfigRespToStorage (Storage, Result);
-  gBS->FreePool (Result);
-  return Status;
-}
-
-
-/**
-  Get current setting of Questions.
-
-  @param  FormSet                FormSet data structure.
-
-  @retval EFI_SUCCESS            The function completed successfully.
-
-**/
-EFI_STATUS
-InitializeCurrentSetting (
-  IN OUT FORM_BROWSER_FORMSET             *FormSet
-  )
-{
-  LIST_ENTRY              *Link;
-  FORMSET_STORAGE         *Storage;
-  FORM_BROWSER_FORM       *Form;
-  EFI_STATUS              Status;
-
-  //
-  // Extract default from IFR binary
-  //
-  Link = GetFirstNode (&FormSet->FormListHead);
-  while (!IsNull (&FormSet->FormListHead, Link)) {
-    Form = FORM_BROWSER_FORM_FROM_LINK (Link);
-
-    Status = ExtractFormDefault (FormSet, Form, EFI_HII_DEFAULT_CLASS_STANDARD);
-
-    Link = GetNextNode (&FormSet->FormListHead, Link);
-  }
-
-  //
-  // Request current settings from Configuration Driver
-  //
-  Link = GetFirstNode (&FormSet->StorageListHead);
-  while (!IsNull (&FormSet->StorageListHead, Link)) {
-    Storage = FORMSET_STORAGE_FROM_LINK (Link);
-
-    Status = LoadStorage (FormSet, Storage);
-
-    //
-    // Now Edit Buffer is filled with default values(lower priority) and current
-    // settings(higher priority), sychronize it to shadow Buffer
-    //
-    if (!EFI_ERROR (Status)) {
-      SynchronizeStorage (Storage);
-    }
-
-    Link = GetNextNode (&FormSet->StorageListHead, Link);
-  }
-
-  return EFI_SUCCESS;
-}
-
-
-/**
-  Fetch the Ifr binary data of a FormSet.
-
-  @param  Handle                 PackageList Handle
-  @param  FormSetGuid            GUID of a formset. If not specified (NULL or zero
-                                 GUID), take the first FormSet found in package
-                                 list.
-  @param  BinaryLength           The length of the FormSet IFR binary.
-  @param  BinaryData             The buffer designed to receive the FormSet.
-
-  @retval EFI_SUCCESS            Buffer filled with the requested FormSet.
-                                 BufferLength was updated.
-  @retval EFI_INVALID_PARAMETER  The handle is unknown.
-  @retval EFI_NOT_FOUND          A form or FormSet on the requested handle cannot
-                                 be found with the requested FormId.
-
-**/
-EFI_STATUS
-GetIfrBinaryData (
-  IN  EFI_HII_HANDLE   Handle,
-  IN OUT EFI_GUID      *FormSetGuid,
-  OUT UINTN            *BinaryLength,
-  OUT UINT8            **BinaryData
-  )
-{
-  EFI_STATUS                   Status;
-  EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;
-  UINTN                        BufferSize;
-  UINT8                        *Package;
-  UINT8                        *OpCodeData;
-  UINT32                       Offset;
-  UINT32                       Offset2;
-  BOOLEAN                      ReturnDefault;
-  UINT32                       PackageListLength;
-  EFI_HII_PACKAGE_HEADER       PackageHeader;
-
-  OpCodeData = NULL;
-  Package = NULL;
-  ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));;
-
-  //
-  // if FormSetGuid is NULL or zero GUID, return first FormSet in the package list
-  //
-  if (FormSetGuid == NULL || CompareGuid (FormSetGuid, &gZeroGuid)) {
-    ReturnDefault = TRUE;
-  } else {
-    ReturnDefault = FALSE;
-  }
-
-  //
-  // Get HII PackageList
-  //
-  BufferSize = 0;
-  HiiPackageList = NULL;
-  Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
-  if (Status == EFI_BUFFER_TOO_SMALL) {
-    HiiPackageList = AllocatePool (BufferSize);
-    ASSERT (HiiPackageList != NULL);
-
-    Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
-  }
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  //
-  // Get Form package from this HII package List
-  //
-  Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
-  Offset2 = 0;
-  CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));
-
-  while (Offset < PackageListLength) {
-    Package = ((UINT8 *) HiiPackageList) + Offset;
-    CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
-
-    if (PackageHeader.Type == EFI_HII_PACKAGE_FORM) {
-      //
-      // Search FormSet in this Form Package
-      //
-      Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);
-      while (Offset2 < PackageHeader.Length) {
-        OpCodeData = Package + Offset2;
-
-        if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {
-          //
-          // Check whether return default FormSet
-          //
-          if (ReturnDefault) {
-            break;
-          }
-
-          //
-          // FormSet GUID is specified, check it
-          //
-          if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {
-            break;
-          }
-        }
-
-        Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
-      }
-
-      if (Offset2 < PackageHeader.Length) {
-        //
-        // Target formset found
-        //
-        break;
-      }
-    }
-
-    Offset += PackageHeader.Length;
-  }
-
-  if (Offset >= PackageListLength) {
-    //
-    // Form package not found in this Package List
-    //
-    gBS->FreePool (HiiPackageList);
-    return EFI_NOT_FOUND;
-  }
-
-  if (ReturnDefault && FormSetGuid != NULL) {
-    //
-    // Return the default FormSet GUID
-    //
-    CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));
-  }
-
-  //
-  // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
-  // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
-  // of the Form Package.
-  //
-  *BinaryLength = PackageHeader.Length - Offset2;
-  *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);
-
-  gBS->FreePool (HiiPackageList);
-
-  if (*BinaryData == NULL) {
-    return EFI_OUT_OF_RESOURCES;
-  }
-
-  return EFI_SUCCESS;
-}
-
-
-/**
-  Initialize the internal data structure of a FormSet.
-
-  @param  Handle                 PackageList Handle
-  @param  FormSetGuid            GUID of a formset. If not specified (NULL or zero
-                                 GUID), take the first FormSet found in package
-                                 list.
-  @param  FormSet                FormSet data structure.
-
-  @retval EFI_SUCCESS            The function completed successfully.
-  @retval EFI_NOT_FOUND          The specified FormSet could not be found.
-
-**/
-EFI_STATUS
-InitializeFormSet (
-  IN  EFI_HII_HANDLE                   Handle,
-  IN OUT EFI_GUID                      *FormSetGuid,
-  OUT FORM_BROWSER_FORMSET             *FormSet
-  )
-{
-  EFI_STATUS                Status;
-  EFI_HANDLE                DriverHandle;
-  UINT16                    Index;
-
-  Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  FormSet->HiiHandle = Handle;
-  CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));
-
-  //
-  // Retrieve ConfigAccess Protocol associated with this HiiPackageList
-  //
-  Status = mHiiDatabase->GetPackageListHandle (mHiiDatabase, Handle, &DriverHandle);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-  FormSet->DriverHandle = DriverHandle;
-  Status = gBS->HandleProtocol (
-                  DriverHandle,
-                  &gEfiHiiConfigAccessProtocolGuid,
-                  (VOID **) &FormSet->ConfigAccess
-                  );
-  if (EFI_ERROR (Status)) {
-    //
-    // Configuration Driver don't attach ConfigAccess protocol to its HII package
-    // list, then there will be no configuration action required
-    //
-    FormSet->ConfigAccess = NULL;
-  }
-
-  //
-  // Parse the IFR binary OpCodes
-  //
-  Status = ParseOpCodes (FormSet);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  gClassOfVfr = FormSet->SubClass;
-  if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {
-    FrontPageHandle = FormSet->HiiHandle;
-  }
-
-  //
-  // Match GUID to find out the function key setting. If match fail, use the default setting.
-  //
-  for (Index = 0; Index < sizeof (gFunctionKeySettingTable) / sizeof (FUNCTIION_KEY_SETTING); Index++) {
-    if (CompareGuid (&FormSet->Guid, &(gFunctionKeySettingTable[Index].FormSetGuid))) {
-      //
-      // Update the function key setting.
-      //
-      gFunctionKeySetting = gFunctionKeySettingTable[Index].KeySetting;
-      //
-      // Function key prompt can not be displayed if the function key has been disabled.
-      //
-      if ((gFunctionKeySetting & FUNCTION_ONE) != FUNCTION_ONE) {
-        gFunctionOneString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
-      }
-
-      if ((gFunctionKeySetting & FUNCTION_TWO) != FUNCTION_TWO) {
-        gFunctionTwoString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
-      }
-
-      if ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE) {
-        gFunctionNineString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
-      }
-
-      if ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN) {
-        gFunctionTenString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
-      }
-    }
-  }
-
-  return Status;
-}
+/** @file\r
+Entry and initialization module for the browser.\r
+\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
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "Setup.h"\r
+\r
+SETUP_DRIVER_PRIVATE_DATA  mPrivateData = {\r
+  SETUP_DRIVER_SIGNATURE,\r
+  NULL,\r
+  {\r
+    SendForm,\r
+    BrowserCallback\r
+  },\r
+  {\r
+    SetScope,\r
+    RegisterHotKey,\r
+    RegiserExitHandler,\r
+    SaveReminder\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
+\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
+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
+\r
+FUNCTIION_KEY_SETTING gFunctionKeySettingTable[] = {\r
+  //\r
+  // Boot Manager\r
+  //\r
+  {\r
+    {\r
+      0x847bc3fe,\r
+      0xb974,\r
+      0x446d,\r
+      {\r
+        0x94,\r
+        0x49,\r
+        0x5a,\r
+        0xd5,\r
+        0x41,\r
+        0x2e,\r
+        0x99,\r
+        0x3b\r
+      }\r
+    },\r
+    NONE_FUNCTION_KEY_SETTING\r
+  },\r
+  //\r
+  // Device Manager\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
+  //\r
+  // BMM FormSet.\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
+  //\r
+  // BMM File Explorer FormSet.\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
+\r
+/**\r
+  This is the routine which an external caller uses to direct the browser\r
+  where to obtain it's information.\r
+\r
+\r
+  @param This            The Form Browser protocol instanse.\r
+  @param Handles         A pointer to an array of Handles.  If HandleCount > 1 we\r
+                         display a list of the formsets for the handles specified.\r
+  @param HandleCount     The number of Handles specified in Handle.\r
+  @param FormSetGuid     This field points to the EFI_GUID which must match the Guid\r
+                         field in the EFI_IFR_FORM_SET op-code for the specified\r
+                         forms-based package. If FormSetGuid is NULL, then this\r
+                         function will display the first found forms package.\r
+  @param FormId          This field specifies which EFI_IFR_FORM to render as the first\r
+                         displayable page. If this field has a value of 0x0000, then\r
+                         the forms browser will render the specified forms in their encoded order.\r
+  @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in\r
+                          characters.\r
+  @param ActionRequest   Points to the action recommended by the form.\r
+\r
+  @retval  EFI_SUCCESS            The function completed successfully.\r
+  @retval  EFI_INVALID_PARAMETER  One of the parameters has an invalid value.\r
+  @retval  EFI_NOT_FOUND          No valid forms could be found to display.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SendForm (\r
+  IN  CONST EFI_FORM_BROWSER2_PROTOCOL *This,\r
+  IN  EFI_HII_HANDLE                   *Handles,\r
+  IN  UINTN                            HandleCount,\r
+  IN  EFI_GUID                         *FormSetGuid, OPTIONAL\r
+  IN  UINT16                           FormId, OPTIONAL\r
+  IN  CONST EFI_SCREEN_DESCRIPTOR      *ScreenDimensions, OPTIONAL\r
+  OUT EFI_BROWSER_ACTION_REQUEST       *ActionRequest  OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  UI_MENU_SELECTION             *Selection;\r
+  UINTN                         Index;\r
+  FORM_BROWSER_FORMSET          *FormSet;\r
+  LIST_ENTRY                    *Link;\r
+\r
+  //\r
+  // Calculate total number of Register HotKeys. \r
+  //\r
+  Index = 0;\r
+  Link  = GetFirstNode (&gBrowserHotKeyList);\r
+  while (!IsNull (&gBrowserHotKeyList, Link)) {\r
+    Link = GetNextNode (&gBrowserHotKeyList, Link);\r
+    Index ++;\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
+  //\r
+  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
+\r
+  for (Index = 0; Index < HandleCount; Index++) {\r
+    Selection = AllocateZeroPool (sizeof (UI_MENU_SELECTION));\r
+    ASSERT (Selection != NULL);\r
+\r
+    Selection->Handle = Handles[Index];\r
+    if (FormSetGuid != NULL) {\r
+      CopyMem (&Selection->FormSetGuid, FormSetGuid, sizeof (EFI_GUID));\r
+      Selection->FormId = FormId;\r
+    } else {\r
+      CopyMem (&Selection->FormSetGuid, &gEfiHiiPlatformSetupFormsetGuid, sizeof (EFI_GUID));\r
+    }\r
+\r
+    do {\r
+      FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));\r
+      ASSERT (FormSet != NULL);\r
+\r
+      //\r
+      // Initialize internal data structures of FormSet\r
+      //\r
+      Status = InitializeFormSet (Selection->Handle, &Selection->FormSetGuid, FormSet, TRUE);\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
+      gCurrentSelection = Selection;\r
+\r
+      Status = SetupBrowser (Selection);\r
+\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
+        CleanBrowserStorage(gOldFormSet);\r
+        RemoveEntryList (&gOldFormSet->Link);\r
+        DestroyFormSet (gOldFormSet);\r
+      }\r
+      gOldFormSet = NULL;\r
+    }\r
+\r
+    FreePool (Selection);\r
+  }\r
+\r
+  if (ActionRequest != NULL) {\r
+    *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+    if (gResetRequired) {\r
+      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_RESET;\r
+    }\r
+  }\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
+\r
+Done:\r
+  //\r
+  // Restore globals used by SendForm()\r
+  //\r
+  RestoreBrowserContext ();\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  This function is called by a callback handler to retrieve uncommitted state\r
+  data from the browser.\r
+\r
+  @param  This                   A pointer to the EFI_FORM_BROWSER2_PROTOCOL\r
+                                 instance.\r
+  @param  ResultsDataSize        A pointer to the size of the buffer associated\r
+                                 with ResultsData.\r
+  @param  ResultsData            A string returned from an IFR browser or\r
+                                 equivalent. The results string will have no\r
+                                 routing information in them.\r
+  @param  RetrieveData           A BOOLEAN field which allows an agent to retrieve\r
+                                 (if RetrieveData = TRUE) data from the uncommitted\r
+                                 browser state information or set (if RetrieveData\r
+                                 = FALSE) data in the uncommitted browser state\r
+                                 information.\r
+  @param  VariableGuid           An optional field to indicate the target variable\r
+                                 GUID name to use.\r
+  @param  VariableName           An optional field to indicate the target\r
+                                 human-readable variable name.\r
+\r
+  @retval EFI_SUCCESS            The results have been distributed or are awaiting\r
+                                 distribution.\r
+  @retval EFI_BUFFER_TOO_SMALL   The ResultsDataSize specified was too small to\r
+                                 contain the results data.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BrowserCallback (\r
+  IN CONST EFI_FORM_BROWSER2_PROTOCOL  *This,\r
+  IN OUT UINTN                         *ResultsDataSize,\r
+  IN OUT EFI_STRING                    ResultsData,\r
+  IN BOOLEAN                           RetrieveData,\r
+  IN CONST EFI_GUID                    *VariableGuid, OPTIONAL\r
+  IN CONST CHAR16                      *VariableName  OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS            Status;\r
+  LIST_ENTRY            *Link;\r
+  FORMSET_STORAGE       *Storage;\r
+  FORM_BROWSER_FORMSET  *FormSet;\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
+\r
+  //\r
+  // Find target storage\r
+  //\r
+  Link = GetFirstNode (&FormSet->StorageListHead);\r
+  if (IsNull (&FormSet->StorageListHead, Link)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (VariableGuid != NULL) {\r
+    //\r
+    // Try to find target storage\r
+    //\r
+    Found = FALSE;\r
+    while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+      Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
+      Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+\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
+          if (VariableName == NULL) {\r
+            return EFI_NOT_FOUND;\r
+          }\r
+\r
+          if (StrCmp (Storage->BrowserStorage->Name, (CHAR16 *) VariableName) != 0) {\r
+            continue;\r
+          }\r
+        }\r
+        Found = TRUE;\r
+        break;\r
+      }\r
+    }\r
+\r
+    if (!Found) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+  } else {\r
+    //\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
+    }\r
+\r
+    //\r
+    // Generate <ConfigResp>\r
+    //\r
+    Status = StorageToConfigResp (Storage->BrowserStorage, &ConfigResp, Storage->ConfigRequest);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Skip <ConfigHdr> and '&' to point to <ConfigBody>\r
+    //\r
+    StrPtr = ConfigResp + StrLen (Storage->BrowserStorage->ConfigHdr) + 1;\r
+\r
+    BufferSize = StrSize (StrPtr);\r
+    if (*ResultsDataSize < BufferSize) {\r
+      *ResultsDataSize = BufferSize;\r
+\r
+      FreePool (ConfigResp);\r
+      return EFI_BUFFER_TOO_SMALL;\r
+    }\r
+\r
+    *ResultsDataSize = BufferSize;\r
+    CopyMem (ResultsData, StrPtr, BufferSize);\r
+\r
+    FreePool (ConfigResp);\r
+  } else {\r
+    //\r
+    // Prepare <ConfigResp>\r
+    //\r
+    TmpSize = StrLen (ResultsData);\r
+    BufferSize = (TmpSize + StrLen (Storage->BrowserStorage->ConfigHdr) + 2) * sizeof (CHAR16);\r
+    ConfigResp = AllocateZeroPool (BufferSize);\r
+    ASSERT (ConfigResp != NULL);\r
+\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->BrowserStorage, ConfigResp);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Initialize Setup Browser driver.\r
+\r
+  @param ImageHandle     The image handle.\r
+  @param SystemTable     The system table.\r
+\r
+  @retval EFI_SUCCESS    The Setup Browser module is initialized correctly..\r
+  @return Other value if failed to initialize the Setup Browser module.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeSetup (\r
+  IN EFI_HANDLE           ImageHandle,\r
+  IN EFI_SYSTEM_TABLE     *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  EFI_INPUT_KEY               DefaultHotKey;\r
+  EFI_STRING                  HelpString;\r
+\r
+  //\r
+  // Locate required Hii relative protocols\r
+  //\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiHiiDatabaseProtocolGuid,\r
+                  NULL,\r
+                  (VOID **) &mHiiDatabase\r
+                  );\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
+                  (VOID **) &mHiiConfigRouting\r
+                  );\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
+  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
+  mPrivateData.Handle = NULL;\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &mPrivateData.Handle,\r
+                  &gEfiFormBrowser2ProtocolGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  &mPrivateData.FormBrowser2\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Install 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
+  //\r
+  mPrivateData.Handle = NULL;\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &mPrivateData.Handle,\r
+                  &gEfiFormBrowserExProtocolGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  &mPrivateData.FormBrowserEx\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Create a new string in HII Package List.\r
+\r
+  @param  String                 The String to be added\r
+  @param  HiiHandle              The package list in the HII database to insert the\r
+                                 specified string.\r
+\r
+  @return The output string.\r
+\r
+**/\r
+EFI_STRING_ID\r
+NewString (\r
+  IN  CHAR16                   *String,\r
+  IN  EFI_HII_HANDLE           HiiHandle\r
+  )\r
+{\r
+  EFI_STRING_ID  StringId;\r
+\r
+  StringId = HiiSetString (HiiHandle, 0, String, NULL);\r
+  ASSERT (StringId != 0);\r
+\r
+  return StringId;\r
+}\r
+\r
+\r
+/**\r
+  Delete a string from HII Package List.\r
+\r
+  @param  StringId               Id of the string in HII database.\r
+  @param  HiiHandle              The HII package list handle.\r
+\r
+  @retval EFI_SUCCESS            The string was deleted successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+DeleteString (\r
+  IN  EFI_STRING_ID            StringId,\r
+  IN  EFI_HII_HANDLE           HiiHandle\r
+  )\r
+{\r
+  CHAR16  NullChar;\r
+\r
+  NullChar = CHAR_NULL;\r
+  HiiSetString (HiiHandle, StringId, &NullChar, NULL);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Get the string based on the StringId and HII Package List Handle.\r
+\r
+  @param  Token                  The String's ID.\r
+  @param  HiiHandle              The package list in the HII database to search for\r
+                                 the specified string.\r
+\r
+  @return The output string.\r
+\r
+**/\r
+CHAR16 *\r
+GetToken (\r
+  IN  EFI_STRING_ID                Token,\r
+  IN  EFI_HII_HANDLE               HiiHandle\r
+  )\r
+{\r
+  EFI_STRING  String;\r
+\r
+  if (HiiHandle == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  String = HiiGetString (HiiHandle, Token, NULL);\r
+  if (String == NULL) {\r
+    String = AllocateCopyPool (StrSize (mUnknownString), mUnknownString);\r
+    ASSERT (String != NULL);\r
+  }\r
+  return (CHAR16 *) String;\r
+}\r
+\r
+\r
+/**\r
+  Allocate new memory and then copy the Unicode string Source to Destination.\r
+\r
+  @param  Dest                   Location to copy string\r
+  @param  Src                    String to copy\r
+\r
+**/\r
+VOID\r
+NewStringCpy (\r
+  IN OUT CHAR16       **Dest,\r
+  IN CHAR16           *Src\r
+  )\r
+{\r
+  if (*Dest != NULL) {\r
+    FreePool (*Dest);\r
+  }\r
+  *Dest = AllocateCopyPool (StrSize (Src), Src);\r
+  ASSERT (*Dest != NULL);\r
+}\r
+\r
+\r
+/**\r
+  Allocate new memory and concatinate Source on the end of Destination.\r
+\r
+  @param  Dest                   String to added to the end of.\r
+  @param  Src                    String to concatinate.\r
+\r
+**/\r
+VOID\r
+NewStringCat (\r
+  IN OUT CHAR16       **Dest,\r
+  IN CHAR16           *Src\r
+  )\r
+{\r
+  CHAR16  *NewString;\r
+  UINTN   TmpSize;\r
+\r
+  if (*Dest == NULL) {\r
+    NewStringCpy (Dest, Src);\r
+    return;\r
+  }\r
+\r
+  TmpSize = StrSize (*Dest);\r
+  NewString = AllocateZeroPool (TmpSize + StrSize (Src) - 1);\r
+  ASSERT (NewString != NULL);\r
+\r
+  StrCpy (NewString, *Dest);\r
+  StrCat (NewString, Src);\r
+\r
+  FreePool (*Dest);\r
+  *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 BROWSER_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
+  @param  Storage                The NameValue Storage.\r
+  @param  Name                   The Name.\r
+  @param  Value                  The retured Value.\r
+  @param  GetValueFrom           Where to get source value, from EditValue or Value.\r
+\r
+  @retval EFI_SUCCESS            Value found for given Name.\r
+  @retval EFI_NOT_FOUND          No such Name found in NameValue storage.\r
+\r
+**/\r
+EFI_STATUS\r
+GetValueByName (\r
+  IN BROWSER_STORAGE             *Storage,\r
+  IN CHAR16                      *Name,\r
+  IN OUT CHAR16                  **Value,\r
+  IN GET_SET_QUESTION_VALUE_WITH GetValueFrom\r
+  )\r
+{\r
+  LIST_ENTRY              *Link;\r
+  NAME_VALUE_NODE         *Node;\r
+\r
+  if (GetValueFrom != GetSetValueWithEditBuffer && GetValueFrom != GetSetValueWithBuffer) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  *Value = NULL;\r
+\r
+  Link = GetFirstNode (&Storage->NameValueListHead);\r
+  while (!IsNull (&Storage->NameValueListHead, Link)) {\r
+    Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
+\r
+    if (StrCmp (Name, Node->Name) == 0) {\r
+      if (GetValueFrom == GetSetValueWithEditBuffer) {\r
+        NewStringCpy (Value, Node->EditValue);\r
+      } else {\r
+        NewStringCpy (Value, Node->Value);\r
+      }\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    Link = GetNextNode (&Storage->NameValueListHead, Link);\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+/**\r
+  Set Value of given Name in a NameValue Storage.\r
+\r
+  @param  Storage                The NameValue Storage.\r
+  @param  Name                   The Name.\r
+  @param  Value                  The Value to set.\r
+  @param  SetValueTo             Whether update editValue or Value.\r
+\r
+  @retval EFI_SUCCESS            Value found for given Name.\r
+  @retval EFI_NOT_FOUND          No such Name found in NameValue storage.\r
+\r
+**/\r
+EFI_STATUS\r
+SetValueByName (\r
+  IN BROWSER_STORAGE         *Storage,\r
+  IN CHAR16                  *Name,\r
+  IN CHAR16                  *Value,\r
+  IN GET_SET_QUESTION_VALUE_WITH SetValueTo\r
+  )\r
+{\r
+  LIST_ENTRY              *Link;\r
+  NAME_VALUE_NODE         *Node;\r
+  CHAR16                  *Buffer;\r
+\r
+  if (SetValueTo != GetSetValueWithEditBuffer && SetValueTo != GetSetValueWithBuffer) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Link = GetFirstNode (&Storage->NameValueListHead);\r
+  while (!IsNull (&Storage->NameValueListHead, Link)) {\r
+    Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
+\r
+    if (StrCmp (Name, Node->Name) == 0) {\r
+      if (SetValueTo == GetSetValueWithEditBuffer) {\r
+        Buffer = Node->EditValue;\r
+      } else {\r
+        Buffer = Node->Value;\r
+      }\r
+      if (Buffer != NULL) {\r
+        FreePool (Buffer);\r
+      }\r
+      Buffer = AllocateCopyPool (StrSize (Value), Value);\r
+      ASSERT (Buffer != NULL);\r
+      if (SetValueTo == GetSetValueWithEditBuffer) {\r
+        Node->EditValue = Buffer;\r
+      } else {\r
+        Node->Value = Buffer;\r
+      }\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    Link = GetNextNode (&Storage->NameValueListHead, Link);\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+/**\r
+  Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.\r
+\r
+  @param  Storage                The Storage to be conveted.\r
+  @param  ConfigResp             The returned <ConfigResp>.\r
+  @param  ConfigRequest          The ConfigRequest string.\r
+\r
+  @retval EFI_SUCCESS            Convert success.\r
+  @retval EFI_INVALID_PARAMETER  Incorrect storage type.\r
+\r
+**/\r
+EFI_STATUS\r
+StorageToConfigResp (\r
+  IN BROWSER_STORAGE         *Storage,\r
+  IN CHAR16                  **ConfigResp,\r
+  IN CHAR16                  *ConfigRequest\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  EFI_STRING              Progress;\r
+  LIST_ENTRY              *Link;\r
+  NAME_VALUE_NODE         *Node;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  switch (Storage->Type) {\r
+  case EFI_HII_VARSTORE_BUFFER:\r
+  case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
+    Status = mHiiConfigRouting->BlockToConfig (\r
+                                  mHiiConfigRouting,\r
+                                  ConfigRequest,\r
+                                  Storage->EditBuffer,\r
+                                  Storage->Size,\r
+                                  ConfigResp,\r
+                                  &Progress\r
+                                  );\r
+    break;\r
+\r
+  case EFI_HII_VARSTORE_NAME_VALUE:\r
+    *ConfigResp = NULL;\r
+    NewStringCat (ConfigResp, Storage->ConfigHdr);\r
+\r
+    Link = GetFirstNode (&Storage->NameValueListHead);\r
+    while (!IsNull (&Storage->NameValueListHead, Link)) {\r
+      Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
+\r
+      if (StrStr (ConfigRequest, Node->Name) != NULL) {\r
+        NewStringCat (ConfigResp, L"&");\r
+        NewStringCat (ConfigResp, Node->Name);\r
+        NewStringCat (ConfigResp, L"=");\r
+        NewStringCat (ConfigResp, Node->EditValue);\r
+      }\r
+      Link = GetNextNode (&Storage->NameValueListHead, Link);\r
+    }\r
+    break;\r
+\r
+  case EFI_HII_VARSTORE_EFI_VARIABLE:\r
+  default:\r
+    Status = EFI_INVALID_PARAMETER;\r
+    break;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.\r
+\r
+  @param  Storage                The Storage to receive the settings.\r
+  @param  ConfigResp             The <ConfigResp> to be converted.\r
+\r
+  @retval EFI_SUCCESS            Convert success.\r
+  @retval EFI_INVALID_PARAMETER  Incorrect storage type.\r
+\r
+**/\r
+EFI_STATUS\r
+ConfigRespToStorage (\r
+  IN BROWSER_STORAGE         *Storage,\r
+  IN CHAR16                  *ConfigResp\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  EFI_STRING  Progress;\r
+  UINTN       BufferSize;\r
+  CHAR16      *StrPtr;\r
+  CHAR16      *Name;\r
+  CHAR16      *Value;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  switch (Storage->Type) {\r
+  case EFI_HII_VARSTORE_BUFFER:\r
+  case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
+    BufferSize = Storage->Size;\r
+    Status = mHiiConfigRouting->ConfigToBlock (\r
+                                  mHiiConfigRouting,\r
+                                  ConfigResp,\r
+                                  Storage->EditBuffer,\r
+                                  &BufferSize,\r
+                                  &Progress\r
+                                  );\r
+    break;\r
+\r
+  case EFI_HII_VARSTORE_NAME_VALUE:\r
+    StrPtr = StrStr (ConfigResp, L"PATH");\r
+    if (StrPtr == NULL) {\r
+      break;\r
+    }\r
+    StrPtr = StrStr (ConfigResp, L"&");\r
+    while (StrPtr != NULL) {\r
+      //\r
+      // Skip '&'\r
+      //\r
+      StrPtr = StrPtr + 1;\r
+      Name = StrPtr;\r
+      StrPtr = StrStr (StrPtr, L"=");\r
+      if (StrPtr == NULL) {\r
+        break;\r
+      }\r
+      *StrPtr = 0;\r
+\r
+      //\r
+      // Skip '='\r
+      //\r
+      StrPtr = StrPtr + 1;\r
+      Value = StrPtr;\r
+      StrPtr = StrStr (StrPtr, L"&");\r
+      if (StrPtr != NULL) {\r
+        *StrPtr = 0;\r
+      }\r
+      SetValueByName (Storage, Name, Value, GetSetValueWithEditBuffer);\r
+    }\r
+    break;\r
+\r
+  case EFI_HII_VARSTORE_EFI_VARIABLE:\r
+  default:\r
+    Status = EFI_INVALID_PARAMETER;\r
+    break;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Get Question's current Value.\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 EFI_SUCCESS            The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+GetQuestionValue (\r
+  IN FORM_BROWSER_FORMSET             *FormSet,\r
+  IN FORM_BROWSER_FORM                *Form,\r
+  IN OUT FORM_BROWSER_STATEMENT       *Question,\r
+  IN GET_SET_QUESTION_VALUE_WITH      GetValueFrom\r
+  )\r
+{\r
+  EFI_STATUS          Status;\r
+  BOOLEAN             Enabled;\r
+  BOOLEAN             Pending;\r
+  UINT8               *Dst;\r
+  UINTN               StorageWidth;\r
+  EFI_TIME            EfiTime;\r
+  BROWSER_STORAGE     *Storage;\r
+  EFI_IFR_TYPE_VALUE  *QuestionValue;\r
+  CHAR16              *ConfigRequest;\r
+  CHAR16              *Progress;\r
+  CHAR16              *Result;\r
+  CHAR16              *Value;\r
+  CHAR16              *StringPtr;\r
+  UINTN               Length;\r
+  UINTN               Index;\r
+  UINTN               LengthStr;\r
+  BOOLEAN             IsBufferStorage;\r
+  BOOLEAN             IsString;\r
+  CHAR16              TemStr[5];\r
+  UINT8               DigitUint8;\r
+  UINT8               *TemBuffer;\r
+\r
+  Status = EFI_SUCCESS;\r
+  Value  = NULL;\r
+  Result = NULL;\r
+\r
+  if (GetValueFrom >= GetSetValueWithMax) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Statement don't have storage, skip them\r
+  //\r
+  if (Question->QuestionId == 0) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Question value is provided by an Expression, evaluate it\r
+  //\r
+  if (Question->ValueExpression != NULL) {\r
+    Status = EvaluateExpression (FormSet, Form, Question->ValueExpression);\r
+    if (!EFI_ERROR (Status)) {\r
+      if (Question->ValueExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {\r
+        ASSERT (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER && Question->HiiValue.Buffer != NULL);\r
+        if (Question->StorageWidth > Question->ValueExpression->Result.BufferLen) {\r
+          CopyMem (Question->HiiValue.Buffer, Question->ValueExpression->Result.Buffer, Question->ValueExpression->Result.BufferLen);\r
+          Question->HiiValue.BufferLen = Question->ValueExpression->Result.BufferLen;\r
+        } else {\r
+          CopyMem (Question->HiiValue.Buffer, Question->ValueExpression->Result.Buffer, Question->StorageWidth);\r
+          Question->HiiValue.BufferLen = Question->StorageWidth;\r
+        }\r
+        FreePool (Question->ValueExpression->Result.Buffer);\r
+      }\r
+      Question->HiiValue.Type = Question->ValueExpression->Result.Type;\r
+      CopyMem (&Question->HiiValue.Value, &Question->ValueExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE));      \r
+    }\r
+    return Status;\r
+  }\r
+  \r
+  //\r
+  // Get question value by read expression.\r
+  //\r
+  if (Question->ReadExpression != NULL && Form->FormType == STANDARD_MAP_FORM_TYPE) {\r
+    Status = EvaluateExpression (FormSet, Form, Question->ReadExpression);\r
+    if (!EFI_ERROR (Status) && \r
+      ((Question->ReadExpression->Result.Type < EFI_IFR_TYPE_OTHER) || (Question->ReadExpression->Result.Type == EFI_IFR_TYPE_BUFFER))) {\r
+      //\r
+      // Only update question value to the valid result.\r
+      //\r
+      if (Question->ReadExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {\r
+        ASSERT (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER && Question->HiiValue.Buffer != NULL);\r
+        if (Question->StorageWidth > Question->ReadExpression->Result.BufferLen) {\r
+          CopyMem (Question->HiiValue.Buffer, Question->ReadExpression->Result.Buffer, Question->ReadExpression->Result.BufferLen);\r
+          Question->HiiValue.BufferLen = Question->ReadExpression->Result.BufferLen;\r
+        } else {\r
+          CopyMem (Question->HiiValue.Buffer, Question->ReadExpression->Result.Buffer, Question->StorageWidth);\r
+          Question->HiiValue.BufferLen = Question->StorageWidth;\r
+        }\r
+        FreePool (Question->ReadExpression->Result.Buffer);\r
+      }\r
+      Question->HiiValue.Type = Question->ReadExpression->Result.Type;\r
+      CopyMem (&Question->HiiValue.Value, &Question->ReadExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE));       \r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Question value is provided by RTC\r
+  //\r
+  Storage = Question->Storage;\r
+  QuestionValue = &Question->HiiValue.Value;\r
+  if (Storage == NULL) {\r
+    //\r
+    // It's a Question without storage, or RTC date/time\r
+    //\r
+    if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {\r
+      //\r
+      // Date and time define the same Flags bit\r
+      //\r
+      switch (Question->Flags & EFI_QF_DATE_STORAGE) {\r
+      case QF_DATE_STORAGE_TIME:\r
+        Status = gRT->GetTime (&EfiTime, NULL);\r
+        break;\r
+\r
+      case QF_DATE_STORAGE_WAKEUP:\r
+        Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
+        break;\r
+\r
+      case QF_DATE_STORAGE_NORMAL:\r
+      default:\r
+        //\r
+        // For date/time without storage\r
+        //\r
+        return EFI_SUCCESS;\r
+      }\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      if (Question->Operand == EFI_IFR_DATE_OP) {\r
+        QuestionValue->date.Year  = EfiTime.Year;\r
+        QuestionValue->date.Month = EfiTime.Month;\r
+        QuestionValue->date.Day   = EfiTime.Day;\r
+      } else {\r
+        QuestionValue->time.Hour   = EfiTime.Hour;\r
+        QuestionValue->time.Minute = EfiTime.Minute;\r
+        QuestionValue->time.Second = EfiTime.Second;\r
+      }\r
+    }\r
+\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Question value is provided by EFI variable\r
+  //\r
+  StorageWidth = Question->StorageWidth;\r
+  if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+    if (Question->BufferValue != NULL) {\r
+      Dst = Question->BufferValue;\r
+    } else {\r
+      Dst = (UINT8 *) QuestionValue;\r
+    }\r
+\r
+    Status = gRT->GetVariable (\r
+                     Question->VariableName,\r
+                     &Storage->Guid,\r
+                     NULL,\r
+                     &StorageWidth,\r
+                     Dst\r
+                     );\r
+    //\r
+    // Always return success, even this EFI variable doesn't exist\r
+    //\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Question Value is provided by Buffer Storage or NameValue Storage\r
+  //\r
+  if (Question->BufferValue != NULL) {\r
+    //\r
+    // This Question is password or orderedlist\r
+    //\r
+    Dst = Question->BufferValue;\r
+  } else {\r
+    //\r
+    // Other type of Questions\r
+    //\r
+    Dst = (UINT8 *) &Question->HiiValue.Value;\r
+  }\r
+\r
+  if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
+      Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
+    IsBufferStorage = TRUE;\r
+  } else {\r
+    IsBufferStorage = FALSE;\r
+  }\r
+  IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ?  TRUE : FALSE);\r
+  if (GetValueFrom == GetSetValueWithEditBuffer || GetValueFrom == GetSetValueWithBuffer ) {\r
+    if (IsBufferStorage) {\r
+      if (GetValueFrom == GetSetValueWithEditBuffer) {\r
+        //\r
+        // Copy from storage Edit buffer\r
+        //\r
+        CopyMem (Dst, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth);\r
+      } else {\r
+        //\r
+        // Copy from storage Edit buffer\r
+        //\r
+        CopyMem (Dst, Storage->Buffer + Question->VarStoreInfo.VarOffset, StorageWidth);\r
+      }\r
+    } else {\r
+      Value = NULL;\r
+      Status = GetValueByName (Storage, Question->VariableName, &Value, GetValueFrom);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      ASSERT (Value != NULL);\r
+      LengthStr = StrLen (Value);\r
+      Status    = EFI_SUCCESS;\r
+      if (IsString) {\r
+        //\r
+        // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
+        // Add string tail char L'\0' into Length\r
+        //\r
+        Length    = StorageWidth + sizeof (CHAR16);\r
+        if (Length < ((LengthStr / 4 + 1) * 2)) {\r
+          Status = EFI_BUFFER_TOO_SMALL;\r
+        } else {\r
+          StringPtr = (CHAR16 *) Dst;\r
+          ZeroMem (TemStr, sizeof (TemStr));\r
+          for (Index = 0; Index < LengthStr; Index += 4) {\r
+            StrnCpy (TemStr, Value + Index, 4);\r
+            StringPtr[Index/4] = (CHAR16) StrHexToUint64 (TemStr);\r
+          }\r
+          //\r
+          // Add tailing L'\0' character\r
+          //\r
+          StringPtr[Index/4] = L'\0';\r
+        }\r
+      } else {\r
+        if (StorageWidth < ((LengthStr + 1) / 2)) {\r
+          Status = EFI_BUFFER_TOO_SMALL;\r
+        } else {\r
+          ZeroMem (TemStr, sizeof (TemStr));\r
+          for (Index = 0; Index < LengthStr; Index ++) {\r
+            TemStr[0] = Value[LengthStr - Index - 1];\r
+            DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
+            if ((Index & 1) == 0) {\r
+              Dst [Index/2] = DigitUint8;\r
+            } else {\r
+              Dst [Index/2] = (UINT8) ((DigitUint8 << 4) + Dst [Index/2]);\r
+            }\r
+          }\r
+        }\r
+      }\r
+\r
+      FreePool (Value);\r
+    }\r
+  } else {\r
+    if (Storage->Type == EFI_HII_VARSTORE_BUFFER || Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+      //\r
+      // Request current settings from Configuration Driver\r
+      //\r
+      if (FormSet->ConfigAccess == NULL) {\r
+        return EFI_NOT_FOUND;\r
+      }\r
+\r
+      //\r
+      // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||\r
+      //                   <ConfigHdr> + "&" + <VariableName>\r
+      //\r
+      if (IsBufferStorage) {\r
+        Length = StrLen (Storage->ConfigHdr);\r
+        Length += StrLen (Question->BlockName);\r
+      } else {\r
+        Length = StrLen (Storage->ConfigHdr);\r
+        Length += StrLen (Question->VariableName) + 1;\r
+      }\r
+      ConfigRequest = AllocateZeroPool ((Length + 1) * sizeof (CHAR16));\r
+      ASSERT (ConfigRequest != NULL);\r
+\r
+      StrCpy (ConfigRequest, Storage->ConfigHdr);\r
+      if (IsBufferStorage) {\r
+        StrCat (ConfigRequest, Question->BlockName);\r
+      } else {\r
+        StrCat (ConfigRequest, L"&");\r
+        StrCat (ConfigRequest, Question->VariableName);\r
+      }\r
+\r
+      Status = FormSet->ConfigAccess->ExtractConfig (\r
+                                        FormSet->ConfigAccess,\r
+                                        ConfigRequest,\r
+                                        &Progress,\r
+                                        &Result\r
+                                        );\r
+      FreePool (ConfigRequest);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      //\r
+      // Skip <ConfigRequest>\r
+      //\r
+      if (IsBufferStorage) {\r
+        Value = StrStr (Result, L"&VALUE");\r
+        if (Value == NULL) {\r
+          FreePool (Result);\r
+          return EFI_NOT_FOUND;\r
+        }\r
+        //\r
+        // Skip "&VALUE"\r
+        //\r
+        Value = Value + 6;\r
+      } else {\r
+        Value = Result + Length;\r
+      }\r
+      if (*Value != '=') {\r
+        FreePool (Result);\r
+        return EFI_NOT_FOUND;\r
+      }\r
+      //\r
+      // Skip '=', point to value\r
+      //\r
+      Value = Value + 1;\r
+\r
+      //\r
+      // Suppress <AltResp> if any\r
+      //\r
+      StringPtr = Value;\r
+      while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
+        StringPtr++;\r
+      }\r
+      *StringPtr = L'\0';\r
+\r
+      LengthStr = StrLen (Value);\r
+      Status    = EFI_SUCCESS;\r
+      if (!IsBufferStorage && IsString) {\r
+        //\r
+        // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
+        // Add string tail char L'\0' into Length\r
+        //\r
+        Length    = StorageWidth + sizeof (CHAR16);\r
+        if (Length < ((LengthStr / 4 + 1) * 2)) {\r
+          Status = EFI_BUFFER_TOO_SMALL;\r
+        } else {\r
+          StringPtr = (CHAR16 *) Dst;\r
+          ZeroMem (TemStr, sizeof (TemStr));\r
+          for (Index = 0; Index < LengthStr; Index += 4) {\r
+            StrnCpy (TemStr, Value + Index, 4);\r
+            StringPtr[Index/4] = (CHAR16) StrHexToUint64 (TemStr);\r
+          }\r
+          //\r
+          // Add tailing L'\0' character\r
+          //\r
+          StringPtr[Index/4] = L'\0';\r
+        }\r
+      } else {\r
+        if (StorageWidth < ((LengthStr + 1) / 2)) {\r
+          Status = EFI_BUFFER_TOO_SMALL;\r
+        } else {\r
+          ZeroMem (TemStr, sizeof (TemStr));\r
+          for (Index = 0; Index < LengthStr; Index ++) {\r
+            TemStr[0] = Value[LengthStr - Index - 1];\r
+            DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
+            if ((Index & 1) == 0) {\r
+              Dst [Index/2] = DigitUint8;\r
+            } else {\r
+              Dst [Index/2] = (UINT8) ((DigitUint8 << 4) + Dst [Index/2]);\r
+            }\r
+          }\r
+        }\r
+      }\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        FreePool (Result);\r
+        return Status;\r
+      }\r
+    } else if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
+      TemBuffer = NULL;\r
+      TemBuffer = AllocateZeroPool (Storage->Size);\r
+      if (TemBuffer == NULL) {\r
+        Status = EFI_OUT_OF_RESOURCES;\r
+        return Status;\r
+      }\r
+      Length = Storage->Size;\r
+      Status = gRT->GetVariable (\r
+                       Storage->Name,\r
+                       &Storage->Guid,\r
+                       NULL,\r
+                       &Length,\r
+                       TemBuffer\r
+                       );\r
+      if (EFI_ERROR (Status)) {\r
+        FreePool (TemBuffer);\r
+        return Status;\r
+      }\r
+\r
+      CopyMem (Dst, TemBuffer + Question->VarStoreInfo.VarOffset, StorageWidth);\r
+\r
+      FreePool (TemBuffer);\r
+    }\r
+\r
+    //\r
+    // Synchronize Edit Buffer\r
+    //\r
+    if (IsBufferStorage) {\r
+      CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth);\r
+    } else {\r
+      SetValueByName (Storage, Question->VariableName, Value, GetSetValueWithEditBuffer);\r
+    }\r
+\r
+    if (Result != NULL) {\r
+      FreePool (Result);\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Save Question Value to edit copy(cached) or Storage(uncached).\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   Form data structure.\r
+  @param  Question               Pointer to the Question.\r
+  @param  SetValueTo             Update the question value to editbuffer , buffer or hii driver.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+SetQuestionValue (\r
+  IN FORM_BROWSER_FORMSET             *FormSet,\r
+  IN FORM_BROWSER_FORM                *Form,\r
+  IN OUT FORM_BROWSER_STATEMENT       *Question,\r
+  IN GET_SET_QUESTION_VALUE_WITH      SetValueTo\r
+  )\r
+{\r
+  EFI_STATUS          Status;\r
+  BOOLEAN             Enabled;\r
+  BOOLEAN             Pending;\r
+  UINT8               *Src;\r
+  EFI_TIME            EfiTime;\r
+  UINTN               BufferLen;\r
+  UINTN               StorageWidth;\r
+  BROWSER_STORAGE     *Storage;\r
+  EFI_IFR_TYPE_VALUE  *QuestionValue;\r
+  CHAR16              *ConfigResp;\r
+  CHAR16              *Progress;\r
+  CHAR16              *Value;\r
+  UINTN               Length;\r
+  BOOLEAN             IsBufferStorage;\r
+  BOOLEAN             IsString;\r
+  UINT8               *TemBuffer;\r
+  CHAR16              *TemName;\r
+  CHAR16              *TemString;\r
+  UINTN               Index;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  if (SetValueTo >= GetSetValueWithMax) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Statement don't have storage, skip them\r
+  //\r
+  if (Question->QuestionId == 0) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // If Question value is provided by an Expression, then it is read only\r
+  //\r
+  if (Question->ValueExpression != NULL) {\r
+    return Status;\r
+  }\r
+  \r
+  //\r
+  // Before set question value, evaluate its write expression.\r
+  //\r
+  if (Question->WriteExpression != NULL && Form->FormType == STANDARD_MAP_FORM_TYPE) {\r
+    Status = EvaluateExpression (FormSet, Form, Question->WriteExpression);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Question value is provided by RTC\r
+  //\r
+  Storage = Question->Storage;\r
+  QuestionValue = &Question->HiiValue.Value;\r
+  if (Storage == NULL) {\r
+    //\r
+    // It's a Question without storage, or RTC date/time\r
+    //\r
+    if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {\r
+      //\r
+      // Date and time define the same Flags bit\r
+      //\r
+      switch (Question->Flags & EFI_QF_DATE_STORAGE) {\r
+      case QF_DATE_STORAGE_TIME:\r
+        Status = gRT->GetTime (&EfiTime, NULL);\r
+        break;\r
+\r
+      case QF_DATE_STORAGE_WAKEUP:\r
+        Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
+        break;\r
+\r
+      case QF_DATE_STORAGE_NORMAL:\r
+      default:\r
+        //\r
+        // For date/time without storage\r
+        //\r
+        return EFI_SUCCESS;\r
+      }\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      if (Question->Operand == EFI_IFR_DATE_OP) {\r
+        EfiTime.Year  = QuestionValue->date.Year;\r
+        EfiTime.Month = QuestionValue->date.Month;\r
+        EfiTime.Day   = QuestionValue->date.Day;\r
+      } else {\r
+        EfiTime.Hour   = QuestionValue->time.Hour;\r
+        EfiTime.Minute = QuestionValue->time.Minute;\r
+        EfiTime.Second = QuestionValue->time.Second;\r
+      }\r
+\r
+      if ((Question->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_TIME) {\r
+        Status = gRT->SetTime (&EfiTime);\r
+      } else {\r
+        Status = gRT->SetWakeupTime (TRUE, &EfiTime);\r
+      }\r
+    }\r
+\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Question value is provided by EFI variable\r
+  //\r
+  StorageWidth = Question->StorageWidth;\r
+  if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+    if (Question->BufferValue != NULL) {\r
+      Src = Question->BufferValue;\r
+    } else {\r
+      Src = (UINT8 *) QuestionValue;\r
+    }\r
+\r
+    Status = gRT->SetVariable (\r
+                     Question->VariableName,\r
+                     &Storage->Guid,\r
+                     Storage->Attributes,\r
+                     StorageWidth,\r
+                     Src\r
+                     );\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Question Value is provided by Buffer Storage or NameValue Storage\r
+  //\r
+  if (Question->BufferValue != NULL) {\r
+    Src = Question->BufferValue;\r
+  } else {\r
+    Src = (UINT8 *) &Question->HiiValue.Value;\r
+  }\r
+\r
+  if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
+      Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
+    IsBufferStorage = TRUE;\r
+  } else {\r
+    IsBufferStorage = FALSE;\r
+  }\r
+  IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ?  TRUE : FALSE);\r
+\r
+  if (SetValueTo == GetSetValueWithEditBuffer || SetValueTo == GetSetValueWithBuffer) {\r
+    if (IsBufferStorage) {\r
+      if (SetValueTo == GetSetValueWithEditBuffer) {\r
+        //\r
+        // Copy to storage edit buffer\r
+        //      \r
+        CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
+      } else if (SetValueTo == GetSetValueWithBuffer) {\r
+        //\r
+        // Copy to storage edit buffer\r
+        //     \r
+        CopyMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
+      }\r
+    } else {\r
+      if (IsString) {\r
+        //\r
+        // Allocate enough string buffer.\r
+        //\r
+        Value = NULL;\r
+        BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16);\r
+        Value = AllocateZeroPool (BufferLen);\r
+        ASSERT (Value != NULL);\r
+        //\r
+        // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
+        //\r
+        TemName = (CHAR16 *) Src;\r
+        TemString = Value;\r
+        for (; *TemName != L'\0'; TemName++) {\r
+          TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);\r
+        }\r
+      } else {\r
+        BufferLen = StorageWidth * 2 + 1;\r
+        Value = AllocateZeroPool (BufferLen * sizeof (CHAR16));\r
+        ASSERT (Value != NULL);\r
+        //\r
+        // Convert Buffer to Hex String\r
+        //\r
+        TemBuffer = Src + StorageWidth - 1;\r
+        TemString = Value;\r
+        for (Index = 0; Index < StorageWidth; Index ++, TemBuffer --) {\r
+          TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
+        }\r
+      }\r
+\r
+      Status = SetValueByName (Storage, Question->VariableName, Value, SetValueTo);\r
+      FreePool (Value);\r
+    }\r
+  } else if (SetValueTo == GetSetValueWithHiiDriver) {\r
+    if (Storage->Type == EFI_HII_VARSTORE_BUFFER || Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+      //\r
+      // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||\r
+      //                <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"\r
+      //\r
+      if (IsBufferStorage) {\r
+        Length = StrLen (Question->BlockName) + 7;\r
+      } else {\r
+        Length = StrLen (Question->VariableName) + 2;\r
+      }\r
+      if (!IsBufferStorage && IsString) {\r
+        Length += (StrLen ((CHAR16 *) Src) * 4);\r
+      } else {\r
+        Length += (StorageWidth * 2);\r
+      }\r
+      ConfigResp = AllocateZeroPool ((StrLen (Storage->ConfigHdr) + Length + 1) * sizeof (CHAR16));\r
+      ASSERT (ConfigResp != NULL);\r
+\r
+      StrCpy (ConfigResp, Storage->ConfigHdr);\r
+      if (IsBufferStorage) {\r
+        StrCat (ConfigResp, Question->BlockName);\r
+        StrCat (ConfigResp, L"&VALUE=");\r
+      } else {\r
+        StrCat (ConfigResp, L"&");\r
+        StrCat (ConfigResp, Question->VariableName);\r
+        StrCat (ConfigResp, L"=");\r
+      }\r
+\r
+      Value = ConfigResp + StrLen (ConfigResp);\r
+\r
+      if (!IsBufferStorage && IsString) {\r
+        //\r
+        // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
+        //\r
+        TemName = (CHAR16 *) Src;\r
+        TemString = Value;\r
+        for (; *TemName != L'\0'; TemName++) {\r
+          TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);\r
+        }\r
+      } else {\r
+        //\r
+        // Convert Buffer to Hex String\r
+        //\r
+        TemBuffer = Src + StorageWidth - 1;\r
+        TemString = Value;\r
+        for (Index = 0; Index < StorageWidth; Index ++, TemBuffer --) {\r
+          TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);\r
+        }\r
+      }\r
+\r
+      //\r
+      // Convert to lower char.\r
+      //\r
+      for (TemString = Value; *Value != L'\0'; Value++) {\r
+        if (*Value >= L'A' && *Value <= L'Z') {\r
+          *Value = (CHAR16) (*Value - L'A' + L'a');\r
+        }\r
+      }\r
+\r
+      //\r
+      // Submit Question Value to Configuration Driver\r
+      //\r
+      if (FormSet->ConfigAccess != NULL) {\r
+        Status = FormSet->ConfigAccess->RouteConfig (\r
+                                          FormSet->ConfigAccess,\r
+                                          ConfigResp,\r
+                                          &Progress\r
+                                          );\r
+        if (EFI_ERROR (Status)) {\r
+          FreePool (ConfigResp);\r
+          return Status;\r
+        }\r
+      }\r
+      FreePool (ConfigResp);\r
+      \r
+    } else if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
+      TemBuffer = NULL;\r
+      TemBuffer = AllocateZeroPool(Storage->Size);\r
+      if (TemBuffer == NULL) {\r
+        Status = EFI_OUT_OF_RESOURCES;\r
+        return Status;\r
+      }\r
+      Length = Storage->Size;\r
+      Status = gRT->GetVariable (\r
+                       Storage->Name,\r
+                       &Storage->Guid,\r
+                       NULL,\r
+                       &Length,\r
+                       TemBuffer\r
+                       );\r
+\r
+      CopyMem (TemBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
+      \r
+      Status = gRT->SetVariable (\r
+                       Storage->Name,\r
+                       &Storage->Guid,\r
+                       Storage->Attributes,\r
+                       Storage->Size,\r
+                       TemBuffer\r
+                       );\r
+      FreePool (TemBuffer);\r
+      if (EFI_ERROR (Status)){\r
+        return Status;\r
+      }\r
+    }\r
+    //\r
+    // Sync storage, from editbuffer to buffer.\r
+    //\r
+    CopyMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Perform inconsistent check for a Form.\r
+\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
+\r
+  @retval EFI_SUCCESS            Form validation pass.\r
+  @retval other                  Form validation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+ValidateQuestion (\r
+  IN  FORM_BROWSER_FORMSET            *FormSet,\r
+  IN  FORM_BROWSER_FORM               *Form,\r
+  IN  FORM_BROWSER_STATEMENT          *Question,\r
+  IN  UINTN                           Type\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  LIST_ENTRY              *Link;\r
+  LIST_ENTRY              *ListHead;\r
+  EFI_STRING              PopUp;\r
+  EFI_INPUT_KEY           Key;\r
+  FORM_EXPRESSION         *Expression;\r
+\r
+  if (Type == EFI_HII_EXPRESSION_INCONSISTENT_IF) {\r
+    ListHead = &Question->InconsistentListHead;\r
+  } else if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {\r
+    ListHead = &Question->NoSubmitListHead;\r
+  } else {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Link = GetFirstNode (ListHead);\r
+  while (!IsNull (ListHead, Link)) {\r
+    Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
+\r
+    //\r
+    // Evaluate the expression\r
+    //\r
+    Status = EvaluateExpression (FormSet, Form, Expression);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    if ((Expression->Result.Type == EFI_IFR_TYPE_BOOLEAN) && Expression->Result.Value.b) {\r
+      //\r
+      // Condition meet, show up error message\r
+      //\r
+      if (Expression->Error != 0) {\r
+        PopUp = GetToken (Expression->Error, FormSet->HiiHandle);\r
+        do {\r
+          CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, PopUp, gPressEnter, gEmptyString);\r
+        } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+        FreePool (PopUp);\r
+      }\r
+\r
+      return EFI_NOT_READY;\r
+    }\r
+\r
+    Link = GetNextNode (ListHead, Link);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Perform NoSubmit check for each Form in FormSet.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  CurrentForm            Current input form data structure.\r
+\r
+  @retval EFI_SUCCESS            Form validation pass.\r
+  @retval other                  Form validation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+NoSubmitCheck (\r
+  IN  FORM_BROWSER_FORMSET            *FormSet,\r
+  IN  FORM_BROWSER_FORM               *CurrentForm\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  LIST_ENTRY              *Link;\r
+  FORM_BROWSER_STATEMENT  *Question;\r
+  FORM_BROWSER_FORM       *Form;\r
+  LIST_ENTRY              *LinkForm;\r
+\r
+  LinkForm = GetFirstNode (&FormSet->FormListHead);\r
+  while (!IsNull (&FormSet->FormListHead, LinkForm)) {\r
+    Form = FORM_BROWSER_FORM_FROM_LINK (LinkForm);\r
+    LinkForm = GetNextNode (&FormSet->FormListHead, LinkForm);\r
+\r
+    if (CurrentForm != NULL && CurrentForm != Form) {\r
+      continue;\r
+    }\r
+\r
+    Link = GetFirstNode (&Form->StatementListHead);\r
+    while (!IsNull (&Form->StatementListHead, Link)) {\r
+      Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+\r
+      Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_NO_SUBMIT_IF);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      Link = GetNextNode (&Form->StatementListHead, Link);\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  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  SyncOrRestore          Sync the buffer to editbuffer or Restore  the \r
+                                 editbuffer to buffer\r
+                                 if TRUE, copy the editbuffer to the buffer.\r
+                                 if FALSE, copy the buffer to the editbuffer.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+SynchronizeStorageForForm (\r
+  IN FORM_BROWSER_FORMSET        *FormSet,\r
+  IN FORM_BROWSER_CONFIG_REQUEST *ConfigInfo,\r
+  IN BOOLEAN                     SyncOrRestore\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  EFI_STRING              Progress;\r
+  EFI_STRING              Result;\r
+  UINTN                   BufferSize;\r
+  LIST_ENTRY              *Link;\r
+  NAME_VALUE_NODE         *Node;\r
+  UINT8                   *Src;\r
+  UINT8                   *Dst;\r
+\r
+  Status = EFI_SUCCESS;\r
+  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
+\r
+    if (SyncOrRestore) {\r
+      Src = ConfigInfo->Storage->EditBuffer;\r
+      Dst = ConfigInfo->Storage->Buffer;\r
+    } else {\r
+      Src = ConfigInfo->Storage->Buffer;\r
+      Dst = ConfigInfo->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
+\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 if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+    Link = GetFirstNode (&ConfigInfo->Storage->NameValueListHead);\r
+    while (!IsNull (&ConfigInfo->Storage->NameValueListHead, Link)) {\r
+      Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
+\r
+      if (StrStr (ConfigInfo->ConfigRequest, Node->Name) != NULL) {\r
+        if (SyncOrRestore) {\r
+          NewStringCpy (&Node->Value, Node->EditValue);\r
+        } else {\r
+          NewStringCpy (&Node->EditValue, Node->Value);\r
+        }\r
+      }\r
+\r
+      Link = GetNextNode (&ConfigInfo->Storage->NameValueListHead, Link);\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  When discard the question value, call the callback function with Changed type\r
+  to inform the hii driver.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   Form data structure.\r
+\r
+**/\r
+VOID\r
+SendDiscardInfoToDriver (\r
+  IN FORM_BROWSER_FORMSET             *FormSet,\r
+  IN FORM_BROWSER_FORM                *Form\r
+  )\r
+{\r
+  LIST_ENTRY                  *Link;\r
+  FORM_BROWSER_STATEMENT      *Question;\r
+  EFI_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
+    Link = GetNextNode (&Form->StatementListHead, Link);\r
+\r
+    if (Question->Storage == NULL || Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+      continue;\r
+    }\r
+\r
+    if (Question->Operand == EFI_IFR_PASSWORD_OP) {\r
+      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
+      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
+      TypeValue = &Question->HiiValue.Value;\r
+    }\r
+\r
+    ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+    FormSet->ConfigAccess->Callback (\r
+                             FormSet->ConfigAccess,\r
+                             EFI_BROWSER_ACTION_CHANGED,\r
+                             Question->QuestionId,\r
+                             Question->HiiValue.Type,\r
+                             TypeValue,\r
+                             &ActionRequest\r
+                             );\r
+  }\r
+}\r
+\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
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   Form data structure.\r
+  @param  SettingScope           Setting Scope for Discard action.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+  @retval EFI_UNSUPPORTED        Unsupport SettingScope.\r
+\r
+**/\r
+EFI_STATUS\r
+DiscardForm (\r
+  IN FORM_BROWSER_FORMSET             *FormSet,\r
+  IN FORM_BROWSER_FORM                *Form,\r
+  IN BROWSER_SETTING_SCOPE            SettingScope\r
+  )\r
+{\r
+  LIST_ENTRY                   *Link;\r
+  FORMSET_STORAGE              *Storage;\r
+  FORM_BROWSER_CONFIG_REQUEST  *ConfigInfo;\r
+  FORM_BROWSER_FORMSET    *LocalFormSet;\r
+\r
+  //\r
+  // Check the supported setting level.\r
+  //\r
+  if (SettingScope >= MaxLevel) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (SettingScope == FormLevel && Form->NvUpdateRequired) {\r
+    ConfigInfo = NULL;\r
+    Link = GetFirstNode (&Form->ConfigRequestHead);\r
+    while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
+      ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
+      Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
+\r
+      if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+        continue;\r
+      }\r
+\r
+      //\r
+      // Skip if there is no RequestElement\r
+      //\r
+      if (ConfigInfo->ElementCount == 0) {\r
+        continue;\r
+      }\r
+\r
+      //\r
+      // Prepare <ConfigResp>\r
+      //\r
+      SynchronizeStorageForForm(FormSet, ConfigInfo, FALSE);\r
+\r
+      //\r
+      // Call callback with Changed type to inform the driver.\r
+      //\r
+      SendDiscardInfoToDriver (FormSet, Form);\r
+    }\r
+\r
+    Form->NvUpdateRequired = FALSE;\r
+  } else if (SettingScope == FormSetLevel && IsNvUpdateRequired(FormSet)) {\r
+\r
+    //\r
+    // Discard Buffer storage or Name/Value storage\r
+    //\r
+    Link = GetFirstNode (&FormSet->StorageListHead);\r
+    while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+      Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
+      Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+\r
+      if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+        continue;\r
+      }\r
+\r
+      //\r
+      // Skip if there is no RequestElement\r
+      //\r
+      if (Storage->ElementCount == 0) {\r
+        continue;\r
+      }\r
+\r
+      SynchronizeStorage(Storage->BrowserStorage, FALSE);\r
+    }\r
+\r
+    Link = GetFirstNode (&FormSet->FormListHead);\r
+    while (!IsNull (&FormSet->FormListHead, Link)) {\r
+      Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+      Link = GetNextNode (&FormSet->FormListHead, Link);\r
+      \r
+      //\r
+      // Call callback with Changed type to inform the driver.\r
+      //\r
+      SendDiscardInfoToDriver (FormSet, Form);\r
+    }\r
+\r
+    UpdateNvInfoInForm (FormSet, FALSE);   \r
+  } else if (SettingScope == SystemLevel) {\r
+    //\r
+    // System Level Discard.\r
+    //\r
+    \r
+    //\r
+    // Discard changed value for each FormSet in the maintain list.\r
+    //\r
+    Link = GetFirstNode (&gBrowserFormSetList);\r
+    while (!IsNull (&gBrowserFormSetList, Link)) {\r
+      LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
+      Link = GetNextNode (&gBrowserFormSetList, Link);\r
+      if (!ValidateFormSet(LocalFormSet)) {\r
+        continue;\r
+      }\r
+      DiscardForm (LocalFormSet, NULL, FormSetLevel);\r
+      if (!IsHiiHandleInBrowserContext (LocalFormSet->HiiHandle)) {\r
+        //\r
+        // Remove maintain backup list after discard except for the current using FormSet.\r
+        //\r
+        CleanBrowserStorage(LocalFormSet);\r
+        RemoveEntryList (&LocalFormSet->Link);\r
+        DestroyFormSet (LocalFormSet);\r
+      }\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;  \r
+}\r
+\r
+/**\r
+  Submit data based on the input Setting level (Form, FormSet or System).\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   Form data structure.\r
+  @param  SettingScope           Setting Scope for Submit action.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+  @retval EFI_UNSUPPORTED        Unsupport SettingScope.\r
+\r
+**/\r
+EFI_STATUS\r
+SubmitForm (\r
+  IN FORM_BROWSER_FORMSET             *FormSet,\r
+  IN FORM_BROWSER_FORM                *Form,\r
+  IN BROWSER_SETTING_SCOPE            SettingScope\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  LIST_ENTRY              *Link;\r
+  EFI_STRING              ConfigResp;\r
+  EFI_STRING              Progress;\r
+  BROWSER_STORAGE         *Storage;\r
+  FORMSET_STORAGE         *FormSetStorage;\r
+  UINTN                   BufferSize;\r
+  UINT8                   *TmpBuf;  \r
+  FORM_BROWSER_FORMSET    *LocalFormSet;\r
+  FORM_BROWSER_CONFIG_REQUEST  *ConfigInfo;\r
+\r
+  //\r
+  // Check the supported setting level.\r
+  //\r
+  if (SettingScope >= MaxLevel) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Validate the Form by NoSubmit check\r
+  //\r
+  Status = EFI_SUCCESS;\r
+  if (SettingScope == FormLevel) {\r
+    Status = NoSubmitCheck (FormSet, Form);\r
+  } else if (SettingScope == FormSetLevel) {\r
+    Status = NoSubmitCheck (FormSet, NULL);\r
+  }\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (SettingScope == FormLevel && Form->NvUpdateRequired) {\r
+    ConfigInfo = NULL;\r
+    Link = GetFirstNode (&Form->ConfigRequestHead);\r
+    while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
+      ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
+      Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
+\r
+      Storage = ConfigInfo->Storage;\r
+      if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+        continue;\r
+      }\r
+\r
+      //\r
+      // Skip if there is no RequestElement\r
+      //\r
+      if (ConfigInfo->ElementCount == 0) {\r
+        continue;\r
+      }\r
+\r
+      //\r
+      // 1. Prepare <ConfigResp>\r
+      //\r
+      Status = StorageToConfigResp (ConfigInfo->Storage, &ConfigResp, ConfigInfo->ConfigRequest);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      //\r
+      // 2. Set value to hii driver or efi variable.\r
+      //\r
+      if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
+          Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+        //\r
+        // Send <ConfigResp> to Configuration Driver\r
+        //\r
+        if (FormSet->ConfigAccess != NULL) {\r
+          Status = FormSet->ConfigAccess->RouteConfig (\r
+                                            FormSet->ConfigAccess,\r
+                                            ConfigResp,\r
+                                            &Progress\r
+                                            );\r
+          if (EFI_ERROR (Status)) {\r
+            FreePool (ConfigResp);\r
+            return Status;\r
+          }\r
+        }\r
+      } else if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
+        TmpBuf = NULL;\r
+        TmpBuf = AllocateZeroPool(Storage->Size);\r
+        if (TmpBuf == NULL) {\r
+          Status = EFI_OUT_OF_RESOURCES;\r
+          return Status;\r
+        }\r
+\r
+        BufferSize = Storage->Size;\r
+        Status = gRT->GetVariable (\r
+                         Storage->Name,\r
+                         &Storage->Guid,\r
+                         NULL,\r
+                         &BufferSize,\r
+                         TmpBuf\r
+                         );\r
+        if (EFI_ERROR (Status)) {\r
+          FreePool (TmpBuf);\r
+          FreePool (ConfigResp);\r
+          return Status;\r
+        }\r
+        ASSERT (BufferSize == Storage->Size);      \r
+        Status = mHiiConfigRouting->ConfigToBlock (\r
+                                      mHiiConfigRouting,\r
+                                      ConfigResp,\r
+                                      TmpBuf,\r
+                                      &BufferSize,\r
+                                      &Progress\r
+                                      );\r
+        if (EFI_ERROR (Status)) {\r
+          FreePool (TmpBuf);\r
+          FreePool (ConfigResp);\r
+          return Status;\r
+        }\r
+\r
+        Status = gRT->SetVariable (\r
+                         Storage->Name,\r
+                         &Storage->Guid,\r
+                         Storage->Attributes,\r
+                         Storage->Size,\r
+                         TmpBuf\r
+                         );\r
+        FreePool (TmpBuf);\r
+        if (EFI_ERROR (Status)) {\r
+          FreePool (ConfigResp);\r
+          return Status;\r
+        }\r
+      }\r
+      FreePool (ConfigResp);\r
+      //\r
+      // 3. Config success, update storage shadow Buffer, only update the data belong to this form.\r
+      //\r
+      SynchronizeStorageForForm(FormSet, ConfigInfo, TRUE);\r
+    }\r
+\r
+    //\r
+    // 4. Update the NV flag.\r
+    // \r
+    Form->NvUpdateRequired = FALSE;\r
+  } else if (SettingScope == FormSetLevel && IsNvUpdateRequired(FormSet)) {\r
+    //\r
+    // Submit Buffer storage or Name/Value storage\r
+    //\r
+    Link = GetFirstNode (&FormSet->StorageListHead);\r
+    while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+      FormSetStorage = (FORMSET_STORAGE_FROM_LINK (Link));\r
+      Storage        = FormSetStorage->BrowserStorage;\r
+      Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+\r
+      if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+        continue;\r
+      }\r
+\r
+      //\r
+      // Skip if there is no RequestElement\r
+      //\r
+      if (FormSetStorage->ElementCount == 0) {\r
+        continue;\r
+      }\r
+\r
+      //\r
+      // 1. Prepare <ConfigResp>\r
+      //\r
+      Status = StorageToConfigResp (Storage, &ConfigResp, FormSetStorage->ConfigRequest);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
+          Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+\r
+        //\r
+        // 2. Send <ConfigResp> to Configuration Driver\r
+        //\r
+        if (FormSet->ConfigAccess != NULL) {\r
+          Status = FormSet->ConfigAccess->RouteConfig (\r
+                                            FormSet->ConfigAccess,\r
+                                            ConfigResp,\r
+                                            &Progress\r
+                                            );\r
+          if (EFI_ERROR (Status)) {\r
+            FreePool (ConfigResp);\r
+            return Status;\r
+          }\r
+        }\r
+      } else if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
+        //\r
+        // 1&2. Set the edit data to the variable.\r
+        //\r
+        TmpBuf = NULL;\r
+        TmpBuf = AllocateZeroPool (Storage->Size);\r
+        if (TmpBuf == NULL) {\r
+          Status = EFI_OUT_OF_RESOURCES;\r
+          return Status;\r
+        }        \r
+        BufferSize = Storage->Size;\r
+        Status = gRT->GetVariable (\r
+                       Storage->Name,\r
+                       &Storage->Guid,\r
+                       NULL,\r
+                       &BufferSize,\r
+                       TmpBuf\r
+                       );\r
+        ASSERT (BufferSize == Storage->Size);      \r
+        Status = mHiiConfigRouting->ConfigToBlock (\r
+                                      mHiiConfigRouting,\r
+                                      ConfigResp,\r
+                                      TmpBuf,\r
+                                      &BufferSize,\r
+                                      &Progress\r
+                                      );\r
+        if (EFI_ERROR (Status)) {\r
+          FreePool (TmpBuf);\r
+          FreePool (ConfigResp);\r
+          return Status;\r
+        }\r
+\r
+        Status = gRT->SetVariable (\r
+                         Storage->Name,\r
+                         &Storage->Guid,\r
+                         Storage->Attributes,\r
+                         Storage->Size,\r
+                         TmpBuf\r
+                         );\r
+        if (EFI_ERROR (Status)) {\r
+          FreePool (TmpBuf);\r
+          FreePool (ConfigResp);\r
+          return Status;\r
+        }\r
+        FreePool (TmpBuf);\r
+      }\r
+      FreePool (ConfigResp);\r
+      //\r
+      // 3. Config success, update storage shadow Buffer\r
+      //\r
+      SynchronizeStorage (Storage, TRUE);\r
+    }\r
+\r
+    //\r
+    // 4. Update the NV flag.\r
+    // \r
+    UpdateNvInfoInForm (FormSet, FALSE);\r
+  } else if (SettingScope == SystemLevel) {\r
+    //\r
+    // System Level Save.\r
+    //\r
+\r
+    //\r
+    // Save changed value for each FormSet in the maintain list.\r
+    //\r
+    Link = GetFirstNode (&gBrowserFormSetList);\r
+    while (!IsNull (&gBrowserFormSetList, Link)) {\r
+      LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
+      Link = GetNextNode (&gBrowserFormSetList, Link);\r
+      if (!ValidateFormSet(LocalFormSet)) {\r
+        continue;\r
+      }\r
+      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
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Get Question default value from AltCfg string.\r
+\r
+  @param  FormSet                The form set.\r
+  @param  Question               The question.\r
+  @param  DefaultId              The default Id.\r
+\r
+  @retval EFI_SUCCESS            Question is reset to default value.\r
+\r
+**/\r
+EFI_STATUS\r
+GetDefaultValueFromAltCfg (\r
+  IN     FORM_BROWSER_FORMSET             *FormSet,\r
+  IN OUT FORM_BROWSER_STATEMENT           *Question,\r
+  IN     UINT16                           DefaultId\r
+  )\r
+{\r
+  BOOLEAN             IsBufferStorage;\r
+  BOOLEAN             IsString;  \r
+  UINTN               Length;\r
+  BROWSER_STORAGE     *Storage;\r
+  CHAR16              *ConfigRequest;\r
+  CHAR16              *Progress;\r
+  CHAR16              *Result;\r
+  CHAR16              *ConfigResp;\r
+  CHAR16              *Value;\r
+  CHAR16              *StringPtr;\r
+  UINTN               LengthStr;\r
+  UINT8               *Dst;\r
+  CHAR16              TemStr[5];\r
+  UINTN               Index;\r
+  UINT8               DigitUint8;\r
+  EFI_STATUS          Status;\r
+\r
+  Status        = EFI_NOT_FOUND;\r
+  Length        = 0;\r
+  Dst           = NULL;\r
+  ConfigRequest = NULL;\r
+  Result        = NULL;\r
+  ConfigResp    = NULL;\r
+  Value         = NULL;\r
+  Storage       = Question->Storage;\r
+\r
+  if ((Storage == NULL) || \r
+      (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) || \r
+      (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Question Value is provided by Buffer Storage or NameValue Storage\r
+  //\r
+  if (Question->BufferValue != NULL) {\r
+    //\r
+    // This Question is password or orderedlist\r
+    //\r
+    Dst = Question->BufferValue;\r
+  } else {\r
+    //\r
+    // Other type of Questions\r
+    //\r
+    Dst = (UINT8 *) &Question->HiiValue.Value;\r
+  }\r
+\r
+  IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);\r
+  IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ?  TRUE : FALSE);\r
+\r
+  //\r
+  // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||\r
+  //                   <ConfigHdr> + "&" + <VariableName>\r
+  //\r
+  if (IsBufferStorage) {\r
+    Length  = StrLen (Storage->ConfigHdr);\r
+    Length += StrLen (Question->BlockName);\r
+  } else {\r
+    Length  = StrLen (Storage->ConfigHdr);\r
+    Length += StrLen (Question->VariableName) + 1;\r
+  }\r
+  ConfigRequest = AllocateZeroPool ((Length + 1) * sizeof (CHAR16));\r
+  ASSERT (ConfigRequest != NULL);\r
+\r
+  StrCpy (ConfigRequest, Storage->ConfigHdr);\r
+  if (IsBufferStorage) {\r
+    StrCat (ConfigRequest, Question->BlockName);\r
+  } else {\r
+    StrCat (ConfigRequest, L"&");\r
+    StrCat (ConfigRequest, Question->VariableName);\r
+  }\r
+\r
+  Status = FormSet->ConfigAccess->ExtractConfig (\r
+                                    FormSet->ConfigAccess,\r
+                                    ConfigRequest,\r
+                                    &Progress,\r
+                                    &Result\r
+                                    );\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)\r
+  //    Get the default configuration string according to the default ID.\r
+  //\r
+  Status = mHiiConfigRouting->GetAltConfig (\r
+                                mHiiConfigRouting,\r
+                                Result,\r
+                                &Storage->Guid,\r
+                                Storage->Name,\r
+                                NULL,\r
+                                &DefaultId,  // it can be NULL to get the current setting.\r
+                                &ConfigResp\r
+                              );\r
+  \r
+  //\r
+  // The required setting can't be found. So, it is not required to be validated and set.\r
+  //\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // Skip <ConfigRequest>\r
+  //\r
+  if (IsBufferStorage) {\r
+    Value = StrStr (ConfigResp, L"&VALUE");\r
+    ASSERT (Value != NULL);\r
+    //\r
+    // Skip "&VALUE"\r
+    //\r
+    Value = Value + 6;\r
+  } else {\r
+    Value = StrStr (ConfigResp, Question->VariableName);\r
+    ASSERT (Value != NULL);\r
+\r
+    Value = Value + StrLen (Question->VariableName);\r
+  }\r
+  if (*Value != '=') {\r
+    Status = EFI_NOT_FOUND;\r
+    goto Done;\r
+  }\r
+  //\r
+  // Skip '=', point to value\r
+  //\r
+  Value = Value + 1;\r
+\r
+  //\r
+  // Suppress <AltResp> if any\r
+  //\r
+  StringPtr = Value;\r
+  while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
+    StringPtr++;\r
+  }\r
+  *StringPtr = L'\0';\r
+\r
+  LengthStr = StrLen (Value);\r
+  if (!IsBufferStorage && IsString) {\r
+    StringPtr = (CHAR16 *) Dst;\r
+    ZeroMem (TemStr, sizeof (TemStr));\r
+    for (Index = 0; Index < LengthStr; Index += 4) {\r
+      StrnCpy (TemStr, Value + Index, 4);\r
+      StringPtr[Index/4] = (CHAR16) StrHexToUint64 (TemStr);\r
+    }\r
+    //\r
+    // Add tailing L'\0' character\r
+    //\r
+    StringPtr[Index/4] = L'\0';\r
+  } else {\r
+    ZeroMem (TemStr, sizeof (TemStr));\r
+    for (Index = 0; Index < LengthStr; Index ++) {\r
+      TemStr[0] = Value[LengthStr - Index - 1];\r
+      DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
+      if ((Index & 1) == 0) {\r
+        Dst [Index/2] = DigitUint8;\r
+      } else {\r
+        Dst [Index/2] = (UINT8) ((DigitUint8 << 4) + Dst [Index/2]);\r
+      }\r
+    }\r
+  }\r
+\r
+Done:\r
+  if (ConfigRequest != NULL){\r
+    FreePool (ConfigRequest);\r
+  }\r
+\r
+  if (ConfigResp != NULL) {\r
+    FreePool (ConfigResp);\r
+  }\r
+  \r
+  if (Result != NULL) {\r
+    FreePool (Result);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Get default Id value used for browser.\r
+\r
+  @param  DefaultId              The default id value used by hii.\r
+\r
+  @retval Browser used default value.\r
+\r
+**/\r
+INTN\r
+GetDefaultIdForCallBack (\r
+  UINTN DefaultId\r
+  )\r
+{ \r
+  if (DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) {\r
+    return EFI_BROWSER_ACTION_DEFAULT_STANDARD;\r
+  } else if (DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
+    return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING;\r
+  } else if (DefaultId == EFI_HII_DEFAULT_CLASS_SAFE) {\r
+    return EFI_BROWSER_ACTION_DEFAULT_SAFE;\r
+  } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN + 0x1000) {\r
+    return EFI_BROWSER_ACTION_DEFAULT_PLATFORM + DefaultId - EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN;\r
+  } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN + 0x1000) {\r
+    return EFI_BROWSER_ACTION_DEFAULT_HARDWARE + DefaultId - EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN;\r
+  } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN + 0x1000) {\r
+    return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE + DefaultId - EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN;\r
+  } else {\r
+    return -1;\r
+  }\r
+}\r
+\r
+/**\r
+  Reset Question to its default value.\r
+\r
+  @param  FormSet                The form set.\r
+  @param  Form                   The form.\r
+  @param  Question               The question.\r
+  @param  DefaultId              The Class of the default.\r
+\r
+  @retval EFI_SUCCESS            Question is reset to default value.\r
+\r
+**/\r
+EFI_STATUS\r
+GetQuestionDefault (\r
+  IN FORM_BROWSER_FORMSET             *FormSet,\r
+  IN FORM_BROWSER_FORM                *Form,\r
+  IN FORM_BROWSER_STATEMENT           *Question,\r
+  IN UINT16                           DefaultId\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  LIST_ENTRY              *Link;\r
+  QUESTION_DEFAULT        *Default;\r
+  QUESTION_OPTION         *Option;\r
+  EFI_HII_VALUE           *HiiValue;\r
+  UINT8                   Index;\r
+  EFI_STRING              StrValue;\r
+  EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;\r
+  EFI_BROWSER_ACTION_REQUEST      ActionRequest;\r
+  INTN                            Action;\r
+\r
+  Status   = EFI_NOT_FOUND;\r
+  StrValue = NULL;\r
+\r
+  //\r
+  // Statement don't have storage, skip them\r
+  //\r
+  if (Question->QuestionId == 0) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // There are Five ways to specify default value for a Question:\r
+  //  1, use call back function (highest priority)\r
+  //  2, use ExtractConfig function\r
+  //  3, use nested EFI_IFR_DEFAULT \r
+  //  4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)\r
+  //  5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)\r
+  //\r
+  HiiValue = &Question->HiiValue;\r
+\r
+  //\r
+  // Get Question defaut value from call back function.\r
+  //\r
+  ConfigAccess = FormSet->ConfigAccess;\r
+  Action = GetDefaultIdForCallBack (DefaultId);\r
+  if ((Action > 0) && ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) && (ConfigAccess != NULL)) {\r
+    ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+    Status = ConfigAccess->Callback (\r
+                             ConfigAccess,\r
+                             Action,\r
+                             Question->QuestionId,\r
+                             HiiValue->Type,\r
+                             &HiiValue->Value,\r
+                             &ActionRequest\r
+                             );\r
+    if (!EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Get default value from altcfg string.\r
+  //\r
+  if (ConfigAccess != NULL) {  \r
+    Status = GetDefaultValueFromAltCfg(FormSet, Question, DefaultId);\r
+    if (!EFI_ERROR (Status)) {\r
+        return Status;\r
+    }\r
+  }\r
+\r
+  //\r
+  // EFI_IFR_DEFAULT has highest priority\r
+  //\r
+  if (!IsListEmpty (&Question->DefaultListHead)) {\r
+    Link = GetFirstNode (&Question->DefaultListHead);\r
+    while (!IsNull (&Question->DefaultListHead, Link)) {\r
+      Default = QUESTION_DEFAULT_FROM_LINK (Link);\r
+\r
+      if (Default->DefaultId == DefaultId) {\r
+        if (Default->ValueExpression != NULL) {\r
+          //\r
+          // Default is provided by an Expression, evaluate it\r
+          //\r
+          Status = EvaluateExpression (FormSet, Form, Default->ValueExpression);\r
+          if (EFI_ERROR (Status)) {\r
+            return Status;\r
+          }\r
+\r
+          if (Default->ValueExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {\r
+            ASSERT (HiiValue->Type == EFI_IFR_TYPE_BUFFER && Question->BufferValue != NULL);\r
+            if (Question->StorageWidth > Default->ValueExpression->Result.BufferLen) {\r
+              CopyMem (Question->HiiValue.Buffer, Default->ValueExpression->Result.Buffer, Default->ValueExpression->Result.BufferLen);\r
+              Question->HiiValue.BufferLen = Default->ValueExpression->Result.BufferLen;\r
+            } else {\r
+              CopyMem (Question->HiiValue.Buffer, Default->ValueExpression->Result.Buffer, Question->StorageWidth);\r
+              Question->HiiValue.BufferLen = Question->StorageWidth;\r
+            }\r
+            FreePool (Default->ValueExpression->Result.Buffer);\r
+          }\r
+          HiiValue->Type = Default->ValueExpression->Result.Type;\r
+          CopyMem (&HiiValue->Value, &Default->ValueExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE));       \r
+        } else {\r
+          //\r
+          // Default value is embedded in EFI_IFR_DEFAULT\r
+          //\r
+          CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));\r
+        }\r
+\r
+        if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
+          StrValue = HiiGetString (FormSet->HiiHandle, HiiValue->Value.string, NULL);\r
+          if (StrValue == NULL) {\r
+            return EFI_NOT_FOUND;\r
+          }\r
+          if (Question->StorageWidth > StrSize (StrValue)) {\r
+            CopyMem (Question->BufferValue, StrValue, StrSize (StrValue));\r
+          } else {\r
+            CopyMem (Question->BufferValue, StrValue, Question->StorageWidth);\r
+          }\r
+        }\r
+\r
+        return EFI_SUCCESS;\r
+      }\r
+\r
+      Link = GetNextNode (&Question->DefaultListHead, Link);\r
+    }\r
+  }\r
+\r
+  //\r
+  // EFI_ONE_OF_OPTION\r
+  //\r
+  if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {\r
+    if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING)  {\r
+      //\r
+      // OneOfOption could only provide Standard and Manufacturing default\r
+      //\r
+      Link = GetFirstNode (&Question->OptionListHead);\r
+      while (!IsNull (&Question->OptionListHead, Link)) {\r
+        Option = QUESTION_OPTION_FROM_LINK (Link);\r
+        Link = GetNextNode (&Question->OptionListHead, Link);\r
+\r
+        if ((Option->SuppressExpression != NULL) &&\r
+            EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {\r
+          continue;\r
+        }\r
+\r
+        if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||\r
+            ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))\r
+           ) {\r
+          CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
+\r
+          return EFI_SUCCESS;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // EFI_IFR_CHECKBOX - lowest priority\r
+  //\r
+  if (Question->Operand == EFI_IFR_CHECKBOX_OP) {\r
+    if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING)  {\r
+      //\r
+      // Checkbox could only provide Standard and Manufacturing default\r
+      //\r
+      if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0)) ||\r
+          ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0))\r
+         ) {\r
+        HiiValue->Value.b = TRUE;\r
+      } else {\r
+        HiiValue->Value.b = FALSE;\r
+      }\r
+\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  //\r
+  // For Questions without default\r
+  //\r
+  Status = EFI_NOT_FOUND;\r
+  switch (Question->Operand) {\r
+  case EFI_IFR_NUMERIC_OP:\r
+    //\r
+    // Take minimum value as numeric default value\r
+    //\r
+    if ((HiiValue->Value.u64 < Question->Minimum) || (HiiValue->Value.u64 > Question->Maximum)) {\r
+      HiiValue->Value.u64 = Question->Minimum;\r
+      Status = EFI_SUCCESS;\r
+    }\r
+    break;\r
+\r
+  case EFI_IFR_ONE_OF_OP:\r
+    //\r
+    // Take first oneof option as oneof's default value\r
+    //\r
+    if (ValueToOption (Question, HiiValue) == NULL) {\r
+      Link = GetFirstNode (&Question->OptionListHead);\r
+      while (!IsNull (&Question->OptionListHead, Link)) {\r
+        Option = QUESTION_OPTION_FROM_LINK (Link);\r
+        Link = GetNextNode (&Question->OptionListHead, Link);\r
+\r
+        if ((Option->SuppressExpression != NULL) &&\r
+            EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {\r
+          continue;\r
+        }\r
+\r
+        CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
+        Status = EFI_SUCCESS;\r
+        break;\r
+      }\r
+    }\r
+    break;\r
+\r
+  case EFI_IFR_ORDERED_LIST_OP:\r
+    //\r
+    // Take option sequence in IFR as ordered list's default value\r
+    //\r
+    Index = 0;\r
+    Link = GetFirstNode (&Question->OptionListHead);\r
+    while (!IsNull (&Question->OptionListHead, Link)) {\r
+      Status = EFI_SUCCESS;\r
+      Option = QUESTION_OPTION_FROM_LINK (Link);\r
+      Link = GetNextNode (&Question->OptionListHead, Link);\r
+\r
+      if ((Option->SuppressExpression != NULL) &&\r
+          EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {\r
+        continue;\r
+      }\r
+\r
+      SetArrayData (Question->BufferValue, Question->ValueType, Index, Option->Value.Value.u64);\r
+\r
+      Index++;\r
+      if (Index >= Question->MaxContainers) {\r
+        break;\r
+      }\r
+    }\r
+    break;\r
+\r
+  default:\r
+    break;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Reset Questions to their initial value or default value in a Form, Formset or System.\r
+\r
+  GetDefaultValueScope parameter decides which questions will reset \r
+  to its default value.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   Form data structure.\r
+  @param  DefaultId              The Class of the default.\r
+  @param  SettingScope           Setting Scope for Default action.\r
+  @param  GetDefaultValueScope   Get default value scope.\r
+  @param  Storage                Get default value only for this storage.\r
+  @param  RetrieveValueFirst     Whether call the retrieve call back to\r
+                                 get the initial value before get default\r
+                                 value.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+  @retval EFI_UNSUPPORTED        Unsupport SettingScope.\r
+\r
+**/\r
+EFI_STATUS\r
+ExtractDefault (\r
+  IN FORM_BROWSER_FORMSET             *FormSet,\r
+  IN FORM_BROWSER_FORM                *Form,\r
+  IN UINT16                           DefaultId,\r
+  IN BROWSER_SETTING_SCOPE            SettingScope,\r
+  IN BROWSER_GET_DEFAULT_VALUE        GetDefaultValueScope,\r
+  IN BROWSER_STORAGE                  *Storage OPTIONAL,\r
+  IN BOOLEAN                          RetrieveValueFirst\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  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
+  //\r
+  // Check the supported setting level.\r
+  //\r
+  if (SettingScope >= MaxLevel || GetDefaultValueScope >= GetDefaultForMax) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (GetDefaultValueScope == GetDefaultForStorage && Storage == NULL) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  \r
+  if (SettingScope == FormLevel) {\r
+    //\r
+    // Extract Form default\r
+    //\r
+    Link = GetFirstNode (&Form->StatementListHead);\r
+    while (!IsNull (&Form->StatementListHead, Link)) {\r
+      Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+      Link = GetNextNode (&Form->StatementListHead, Link);\r
+\r
+      //\r
+      // If get default value only for this storage, check the storage first.\r
+      //\r
+      if ((GetDefaultValueScope == GetDefaultForStorage) && (Question->Storage != Storage)) {\r
+        continue;\r
+      }\r
+\r
+      //\r
+      // If get default value only for no storage question, just skip the question which has storage.\r
+      //\r
+      if ((GetDefaultValueScope == GetDefaultForNoStorage) && (Question->Storage != NULL)) {\r
+        continue;\r
+      }\r
+\r
+      //\r
+      // If Question is disabled, don't reset it to default\r
+      //\r
+      if (Question->Expression != NULL) {\r
+        if (EvaluateExpressionList(Question->Expression, TRUE, FormSet, Form) == ExpressDisable) {\r
+          continue;\r
+        }\r
+      }\r
+\r
+      if (RetrieveValueFirst) {\r
+        //\r
+        // Call the Retrieve call back to get the initial question value.\r
+        //\r
+        Status = ProcessRetrieveForQuestion(FormSet->ConfigAccess, Question);\r
+      }\r
+\r
+      //\r
+      // If not request to get the initial value or get initial value fail, then get default value.\r
+      //\r
+      if (!RetrieveValueFirst || EFI_ERROR (Status)) {\r
+        Status = GetQuestionDefault (FormSet, Form, Question, DefaultId);\r
+        if (EFI_ERROR (Status)) {\r
+          continue;\r
+        }\r
+      }\r
+\r
+      //\r
+      // Synchronize Buffer storage's Edit buffer\r
+      //\r
+      if ((Question->Storage != NULL) &&\r
+          (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
+        SetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
+        //\r
+        // Update Form NV flag.\r
+        //\r
+        Form->NvUpdateRequired = TRUE;\r
+      }\r
+    }\r
+  } else if (SettingScope == FormSetLevel) {\r
+    FormLink = GetFirstNode (&FormSet->FormListHead);\r
+    while (!IsNull (&FormSet->FormListHead, FormLink)) {\r
+      Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);\r
+      ExtractDefault (FormSet, Form, DefaultId, FormLevel, GetDefaultValueScope, Storage, RetrieveValueFirst);\r
+      FormLink = GetNextNode (&FormSet->FormListHead, FormLink);\r
+    }\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
+    //\r
+    FreePool (HiiHandles);\r
+    gOldFormSet = BackUpFormSet;\r
+       \r
+    //\r
+    // Set Default Value for each FormSet in the maintain list.\r
+    //\r
+    Link = GetFirstNode (&gBrowserFormSetList);\r
+    while (!IsNull (&gBrowserFormSetList, Link)) {\r
+      LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
+      Link = GetNextNode (&gBrowserFormSetList, Link);\r
+      if (!ValidateFormSet(LocalFormSet)) {\r
+        continue;\r
+      }\r
+      ExtractDefault (LocalFormSet, NULL, DefaultId, FormSetLevel, GetDefaultValueScope, Storage, RetrieveValueFirst);\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Initialize Question's Edit copy from Storage.\r
+\r
+  @param  Selection              Selection contains the information about \r
+                                 the Selection, form and formset to be displayed.\r
+                                 Selection action may be updated in retrieve callback.\r
+                                 If Selection is NULL, only initialize Question value.\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   Form data structure.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+LoadFormConfig (\r
+  IN OUT UI_MENU_SELECTION    *Selection,\r
+  IN FORM_BROWSER_FORMSET     *FormSet,\r
+  IN FORM_BROWSER_FORM        *Form\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  LIST_ENTRY                  *Link;\r
+  FORM_BROWSER_STATEMENT      *Question;\r
+  UINT8                       *BufferValue;\r
+  UINTN                       StorageWidth;\r
+  \r
+  Link = GetFirstNode (&Form->StatementListHead);\r
+  while (!IsNull (&Form->StatementListHead, Link)) {\r
+    Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+\r
+    //\r
+    // Initialize local copy of Value for each Question\r
+    //\r
+    Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    if ((Question->Operand == EFI_IFR_STRING_OP) || (Question->Operand == EFI_IFR_PASSWORD_OP)) {\r
+      HiiSetString (FormSet->HiiHandle, Question->HiiValue.Value.string, (CHAR16*)Question->BufferValue, NULL);\r
+    }\r
+\r
+    //\r
+    // Call the Retrieve call back function for all questions.\r
+    //\r
+    if ((FormSet->ConfigAccess != NULL) && (Selection != NULL) &&\r
+        ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK)) {\r
+      //\r
+      // Check QuestionValue does exist.\r
+      //\r
+      StorageWidth = Question->StorageWidth;\r
+      if (Question->BufferValue != NULL) {\r
+        BufferValue  = Question->BufferValue;\r
+      } else {\r
+        BufferValue = (UINT8 *) &Question->HiiValue.Value;\r
+      }\r
+\r
+      //\r
+      // For efivarstore storage, initial question value first.\r
+      //\r
+      if ((Question->Storage != NULL) && (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
+        Status = gRT->GetVariable (\r
+                         Question->VariableName,\r
+                         &Question->Storage->Guid,\r
+                         NULL,\r
+                         &StorageWidth,\r
+                         BufferValue\r
+                         );\r
+      }\r
+\r
+      Status = ProcessCallBackFunction(Selection, Question, EFI_BROWSER_ACTION_RETRIEVE, TRUE);\r
+    }\r
+\r
+    Link = GetNextNode (&Form->StatementListHead, Link);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Initialize Question's Edit copy from Storage for the whole Formset.\r
+\r
+  @param  Selection              Selection contains the information about \r
+                                 the Selection, form and formset to be displayed.\r
+                                 Selection action may be updated in retrieve callback.\r
+                                 If Selection is NULL, only initialize Question value.\r
+  @param  FormSet                FormSet data structure.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+LoadFormSetConfig (\r
+  IN OUT UI_MENU_SELECTION    *Selection,\r
+  IN     FORM_BROWSER_FORMSET *FormSet\r
+  )\r
+{\r
+  EFI_STATUS            Status;\r
+  LIST_ENTRY            *Link;\r
+  FORM_BROWSER_FORM     *Form;\r
+\r
+  Link = GetFirstNode (&FormSet->FormListHead);\r
+  while (!IsNull (&FormSet->FormListHead, Link)) {\r
+    Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+\r
+    //\r
+    // Initialize local copy of Value for each Form\r
+    //\r
+    Status = LoadFormConfig (Selection, FormSet, Form);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    Link = GetNextNode (&FormSet->FormListHead, Link);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Remove the Request element from the Config Request.\r
+\r
+  @param  Storage                Pointer to the browser storage.\r
+  @param  RequestElement         The pointer to the Request element.\r
+\r
+**/\r
+VOID\r
+RemoveElement (\r
+  IN OUT BROWSER_STORAGE      *Storage,\r
+  IN     CHAR16               *RequestElement\r
+  )\r
+{\r
+  CHAR16   *NewStr;\r
+  CHAR16   *DestStr;\r
+\r
+  ASSERT (Storage->ConfigRequest != NULL && RequestElement != NULL);\r
+\r
+  NewStr = StrStr (Storage->ConfigRequest, RequestElement);\r
+\r
+  if (NewStr == NULL) {\r
+    return;\r
+  }\r
+\r
+  //\r
+  // Remove this element from this ConfigRequest.\r
+  //\r
+  DestStr = NewStr;\r
+  NewStr += StrLen (RequestElement);\r
+  CopyMem (DestStr, NewStr, StrSize (NewStr));\r
+  \r
+  Storage->SpareStrLen += StrLen (RequestElement);  \r
+}\r
+\r
+/**\r
+  Adjust config request in storage, remove the request elements existed in the input ConfigRequest.\r
+\r
+  @param  Storage                Pointer to the 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
+    // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage\r
+    //\r
+    SearchKey = L"&";\r
+  } else {\r
+    //\r
+    // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage\r
+    //\r
+    SearchKey = L"&OFFSET";\r
+  }\r
+\r
+  //\r
+  // Find SearchKey storage\r
+  //\r
+  if (Storage->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
+  // If no request element remain, just remove the ConfigRequest string.\r
+  //\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
+\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
+  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
+  // 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
+    if (*ConfigRequest != NULL) {\r
+      CopyMem (NewStr, *ConfigRequest, StringSize);\r
+      FreePool (*ConfigRequest);\r
+    }\r
+    *ConfigRequest = NewStr;\r
+    *SpareStrLen   = CONFIG_REQUEST_STRING_INCREMENTAL;\r
+  }\r
+\r
+  StrCat (*ConfigRequest, RequestElement);\r
+  *SpareStrLen -= StrLength;\r
+}\r
+\r
+/**\r
+  Adjust the config request info, remove the request elements which already in AllConfigRequest string.\r
+\r
+  @param  Storage                Form set Storage.\r
+  @param  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
+BOOLEAN \r
+ConfigRequestAdjust (\r
+  IN  FORMSET_STORAGE         *Storage,\r
+  OUT CHAR16                  **ConfigRequest\r
+  )\r
+{\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
+  if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+    //\r
+    // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage\r
+    //\r
+    SearchKey = L"&";\r
+  } else {\r
+    //\r
+    // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage\r
+    //\r
+    SearchKey = L"&OFFSET";\r
+  }\r
+\r
+  //\r
+  // Prepare the config header.\r
+  // \r
+  RetBuf = AllocateCopyPool(StrSize (Storage->BrowserStorage->ConfigHdr), Storage->BrowserStorage->ConfigHdr);\r
+  ASSERT (RetBuf != NULL);\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
+    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
+  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
+  @retval EFI_SUCCESS            The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\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
+  CHAR16      *ConfigRequest;\r
+\r
+  if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+    return EFI_SUCCESS;\r
+  }\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
+  Get current setting of Questions.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\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
+\r
+  //\r
+  // Extract default from IFR binary for no storage questions.\r
+  //  \r
+  ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForNoStorage, NULL, TRUE);\r
+\r
+  //\r
+  // Request current settings from Configuration Driver\r
+  //\r
+  Link = GetFirstNode (&FormSet->StorageListHead);\r
+  while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+    Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
+\r
+    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
+    //\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
+      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->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
+        //\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->BrowserStorage, TRUE);\r
+    }\r
+\r
+    Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+  }\r
+\r
+  //\r
+  // If has old formset, get the old nv update status.\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
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Fetch the Ifr binary data of a FormSet.\r
+\r
+  @param  Handle                 PackageList Handle\r
+  @param  FormSetGuid            On input, GUID or class GUID of a formset. If not\r
+                                 specified (NULL or zero GUID), take the first\r
+                                 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
+                                 found in package list.\r
+                                 On output, GUID of the formset found(if not NULL).\r
+  @param  BinaryLength           The length of the FormSet IFR binary.\r
+  @param  BinaryData             The buffer designed to receive the FormSet.\r
+\r
+  @retval EFI_SUCCESS            Buffer filled with the requested FormSet.\r
+                                 BufferLength was updated.\r
+  @retval EFI_INVALID_PARAMETER  The handle is unknown.\r
+  @retval EFI_NOT_FOUND          A form or FormSet on the requested handle cannot\r
+                                 be found with the requested FormId.\r
+\r
+**/\r
+EFI_STATUS\r
+GetIfrBinaryData (\r
+  IN  EFI_HII_HANDLE   Handle,\r
+  IN OUT EFI_GUID      *FormSetGuid,\r
+  OUT UINTN            *BinaryLength,\r
+  OUT UINT8            **BinaryData\r
+  )\r
+{\r
+  EFI_STATUS                   Status;\r
+  EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;\r
+  UINTN                        BufferSize;\r
+  UINT8                        *Package;\r
+  UINT8                        *OpCodeData;\r
+  UINT32                       Offset;\r
+  UINT32                       Offset2;\r
+  UINT32                       PackageListLength;\r
+  EFI_HII_PACKAGE_HEADER       PackageHeader;\r
+  UINT8                        Index;\r
+  UINT8                        NumberOfClassGuid;\r
+  BOOLEAN                      ClassGuidMatch;\r
+  EFI_GUID                     *ClassGuid;\r
+  EFI_GUID                     *ComparingGuid;\r
+\r
+  OpCodeData = NULL;\r
+  Package = NULL;\r
+  ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
+\r
+  //\r
+  // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list\r
+  //\r
+  if (FormSetGuid == NULL) {\r
+    ComparingGuid = &gZeroGuid;\r
+  } else {\r
+    ComparingGuid = FormSetGuid;\r
+  }\r
+\r
+  //\r
+  // Get HII PackageList\r
+  //\r
+  BufferSize = 0;\r
+  HiiPackageList = NULL;\r
+  Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    HiiPackageList = AllocatePool (BufferSize);\r
+    ASSERT (HiiPackageList != NULL);\r
+\r
+    Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
+  }\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  ASSERT (HiiPackageList != NULL);\r
+\r
+  //\r
+  // Get Form package from this HII package List\r
+  //\r
+  Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+  Offset2 = 0;\r
+  CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
+\r
+  ClassGuidMatch = FALSE;\r
+  while (Offset < PackageListLength) {\r
+    Package = ((UINT8 *) HiiPackageList) + Offset;\r
+    CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
+\r
+    if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
+      //\r
+      // Search FormSet in this Form Package\r
+      //\r
+      Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
+      while (Offset2 < PackageHeader.Length) {\r
+        OpCodeData = Package + Offset2;\r
+\r
+        if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
+          //\r
+          // Try to compare against formset GUID\r
+          //\r
+          if (CompareGuid (FormSetGuid, &gZeroGuid) || \r
+              CompareGuid (ComparingGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
+            break;\r
+          }\r
+\r
+          if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) {\r
+            //\r
+            // Try to compare against formset class GUID\r
+            //\r
+            NumberOfClassGuid = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3);\r
+            ClassGuid         = (EFI_GUID *) (OpCodeData + sizeof (EFI_IFR_FORM_SET));\r
+            for (Index = 0; Index < NumberOfClassGuid; Index++) {\r
+              if (CompareGuid (ComparingGuid, ClassGuid + Index)) {\r
+                ClassGuidMatch = TRUE;\r
+                break;\r
+              }\r
+            }\r
+            if (ClassGuidMatch) {\r
+              break;\r
+            }\r
+          } else if (ComparingGuid == &gEfiHiiPlatformSetupFormsetGuid) {\r
+            ClassGuidMatch = TRUE;\r
+            break;\r
+          }\r
+        }\r
+\r
+        Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
+      }\r
+\r
+      if (Offset2 < PackageHeader.Length) {\r
+        //\r
+        // Target formset found\r
+        //\r
+        break;\r
+      }\r
+    }\r
+\r
+    Offset += PackageHeader.Length;\r
+  }\r
+\r
+  if (Offset >= PackageListLength) {\r
+    //\r
+    // Form package not found in this Package List\r
+    //\r
+    FreePool (HiiPackageList);\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  if (FormSetGuid != NULL) {\r
+    //\r
+    // Return the FormSet GUID\r
+    //\r
+    CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
+  }\r
+\r
+  //\r
+  // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes\r
+  // in this FormSet; So, here just simply copy the data from start of a FormSet to the end\r
+  // of the Form Package.\r
+  //\r
+  *BinaryLength = PackageHeader.Length - Offset2;\r
+  *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);\r
+\r
+  FreePool (HiiPackageList);\r
+\r
+  if (*BinaryData == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Initialize the internal data structure of a FormSet.\r
+\r
+  @param  Handle                 PackageList Handle\r
+  @param  FormSetGuid            On input, GUID or class GUID of a formset. If not\r
+                                 specified (NULL or zero GUID), take the first\r
+                                 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
+                                 found in package list.\r
+                                 On output, GUID of the formset found(if not NULL).\r
+  @param  FormSet                FormSet data structure.\r
+  @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
+\r
+**/\r
+EFI_STATUS\r
+InitializeFormSet (\r
+  IN  EFI_HII_HANDLE                   Handle,\r
+  IN OUT EFI_GUID                      *FormSetGuid,\r
+  OUT FORM_BROWSER_FORMSET             *FormSet,\r
+  IN  BOOLEAN                          UpdateGlobalVar                   \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
+    return Status;\r
+  }\r
+\r
+  FormSet->Signature = FORM_BROWSER_FORMSET_SIGNATURE;\r
+  FormSet->HiiHandle = Handle;\r
+  CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));\r
+\r
+  //\r
+  // Retrieve ConfigAccess Protocol associated with this HiiPackageList\r
+  //\r
+  Status = mHiiDatabase->GetPackageListHandle (mHiiDatabase, Handle, &DriverHandle);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  FormSet->DriverHandle = DriverHandle;\r
+  Status = gBS->HandleProtocol (\r
+                  DriverHandle,\r
+                  &gEfiHiiConfigAccessProtocolGuid,\r
+                  (VOID **) &FormSet->ConfigAccess\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // Configuration Driver don't attach ConfigAccess protocol to its HII package\r
+    // list, then there will be no configuration action required\r
+    //\r
+    FormSet->ConfigAccess = NULL;\r
+  }\r
+\r
+  //\r
+  // Parse the IFR binary OpCodes\r
+  //\r
+  Status = ParseOpCodes (FormSet);\r
+  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
+}\r
+\r
+\r
+/**\r
+  Save globals used by previous call to SendForm(). SendForm() may be called from \r
+  HiiConfigAccess.Callback(), this will cause SendForm() be reentried.\r
+  So, save globals of previous call to SendForm() and restore them upon exit.\r
+\r
+**/\r
+VOID\r
+SaveBrowserContext (\r
+  VOID\r
+  )\r
+{\r
+  BROWSER_CONTEXT  *Context;\r
+\r
+  gBrowserContextCount++;\r
+  if (gBrowserContextCount == 1) {\r
+    //\r
+    // This is not reentry of SendForm(), no context to save\r
+    //\r
+    return;\r
+  }\r
+\r
+  Context = AllocatePool (sizeof (BROWSER_CONTEXT));\r
+  ASSERT (Context != NULL);\r
+\r
+  Context->Signature = BROWSER_CONTEXT_SIGNATURE;\r
+\r
+  //\r
+  // Save FormBrowser context\r
+  //\r
+  Context->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
+\r
+  //\r
+  // Insert to FormBrowser context list\r
+  //\r
+  InsertHeadList (&gBrowserContextList, &Context->Link);\r
+}\r
+\r
+\r
+/**\r
+  Restore globals used by previous call to SendForm().\r
+\r
+**/\r
+VOID\r
+RestoreBrowserContext (\r
+  VOID\r
+  )\r
+{\r
+  LIST_ENTRY       *Link;\r
+  BROWSER_CONTEXT  *Context;\r
+\r
+  ASSERT (gBrowserContextCount != 0);\r
+  gBrowserContextCount--;\r
+  if (gBrowserContextCount == 0) {\r
+    //\r
+    // This is not reentry of SendForm(), no context to restore\r
+    //\r
+    return;\r
+  }\r
+\r
+  ASSERT (!IsListEmpty (&gBrowserContextList));\r
+\r
+  Link = GetFirstNode (&gBrowserContextList);\r
+  Context = BROWSER_CONTEXT_FROM_LINK (Link);\r
+\r
+  //\r
+  // Restore FormBrowser context\r
+  //\r
+  gBannerData           = Context->BannerData;\r
+  gClassOfVfr           = Context->ClassOfVfr;\r
+  gFunctionKeySetting   = Context->FunctionKeySetting;\r
+  gResetRequired        = Context->ResetRequired;\r
+  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
+\r
+  //\r
+  // Remove from FormBrowser context list\r
+  //\r
+  RemoveEntryList (&Context->Link);\r
+  gBS->FreePool (Context);\r
+}\r
+\r
+/**\r
+  Find the matched FormSet context in the backup maintain list based on HiiHandle.\r
+  \r
+  @param Handle  The Hii Handle.\r
+  \r
+  @return the found FormSet context. If no found, NULL will return.\r
+\r
+**/\r
+FORM_BROWSER_FORMSET * \r
+GetFormSetFromHiiHandle (\r
+  EFI_HII_HANDLE Handle\r
+  )\r
+{\r
+  LIST_ENTRY           *Link;\r
+  FORM_BROWSER_FORMSET *FormSet;\r
+\r
+  Link = GetFirstNode (&gBrowserFormSetList);\r
+  while (!IsNull (&gBrowserFormSetList, Link)) {\r
+    FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
+    Link = GetNextNode (&gBrowserFormSetList, Link);\r
+    if (!ValidateFormSet(FormSet)) {\r
+      continue;\r
+    }\r
+    if (FormSet->HiiHandle == Handle) {\r
+      return FormSet;\r
+    }\r
+  }\r
+  \r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Check whether the input HII handle is the FormSet that is being used.\r
+  \r
+  @param Handle  The Hii Handle.\r
+  \r
+  @retval TRUE   HII handle is being used.\r
+  @retval FALSE  HII handle is not being used.\r
+\r
+**/\r
+BOOLEAN\r
+IsHiiHandleInBrowserContext (\r
+  EFI_HII_HANDLE Handle\r
+  )\r
+{\r
+  LIST_ENTRY       *Link;\r
+  BROWSER_CONTEXT  *Context;\r
+\r
+  //\r
+  // HiiHandle is Current FormSet.\r
+  //\r
+  if ((gOldFormSet != NULL) && (gOldFormSet->HiiHandle == Handle)) {\r
+    return TRUE;\r
+  }\r
+\r
+  //\r
+  // Check whether HiiHandle is in BrowserContext.\r
+  //\r
+  Link = GetFirstNode (&gBrowserContextList);\r
+  while (!IsNull (&gBrowserContextList, Link)) {\r
+    Context = BROWSER_CONTEXT_FROM_LINK (Link);\r
+    if (Context->OldFormSet->HiiHandle == Handle) {\r
+      //\r
+      // HiiHandle is in BrowserContext\r
+      //\r
+      return TRUE;\r
+    }\r
+    Link = GetNextNode (&gBrowserContextList, Link);\r
+  }\r
+  \r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Find the registered HotKey based on KeyData.\r
+  \r
+  @param[in] KeyData     A pointer to a buffer that describes the keystroke\r
+                         information for the hot key.\r
+\r
+  @return The registered HotKey context. If no found, NULL will return.\r
+**/\r
+BROWSER_HOT_KEY *\r
+GetHotKeyFromRegisterList (\r
+  IN EFI_INPUT_KEY *KeyData\r
+  )\r
+{\r
+  LIST_ENTRY       *Link;\r
+  BROWSER_HOT_KEY  *HotKey;\r
+\r
+  Link = GetFirstNode (&gBrowserHotKeyList);\r
+  while (!IsNull (&gBrowserHotKeyList, Link)) {\r
+    HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);\r
+    if (HotKey->KeyData->ScanCode == KeyData->ScanCode) {\r
+      return HotKey;\r
+    }\r
+    Link = GetNextNode (&gBrowserHotKeyList, Link);\r
+  }\r
+  \r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Configure what scope the hot key will impact.\r
+  All hot keys have the same scope. The mixed hot keys with the different level are not supported.\r
+  If no scope is set, the default scope will be FormSet level.\r
+  After all registered hot keys are removed, previous Scope can reset to another level.\r
+  \r
+  @param[in] Scope               Scope level to be set. \r
+  \r
+  @retval EFI_SUCCESS            Scope is set correctly.\r
+  @retval EFI_INVALID_PARAMETER  Scope is not the valid value specified in BROWSER_SETTING_SCOPE. \r
+  @retval EFI_UNSPPORTED         Scope level is different from current one that the registered hot keys have.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetScope (\r
+  IN BROWSER_SETTING_SCOPE Scope\r
+  )\r
+{\r
+  if (Scope >= MaxLevel) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  \r
+  //\r
+  // When no hot key registered in system or on the first setting,\r
+  // Scope can be set.\r
+  //\r
+  if (mBrowserScopeFirstSet || IsListEmpty (&gBrowserHotKeyList)) {\r
+    gBrowserSettingScope  = Scope;\r
+    mBrowserScopeFirstSet = FALSE;\r
+  } else if (Scope != gBrowserSettingScope) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Register the hot key with its browser action, or unregistered the hot key.\r
+  Only support hot key that is not printable character (control key, function key, etc.).\r
+  If the action value is zero, the hot key will be unregistered if it has been registered.\r
+  If the same hot key has been registered, the new action and help string will override the previous ones.\r
+  \r
+  @param[in] KeyData     A pointer to a buffer that describes the keystroke\r
+                         information for the hot key. Its type is EFI_INPUT_KEY to \r
+                         be supported by all ConsoleIn devices.\r
+  @param[in] Action      Action value that describes what action will be trigged when the hot key is pressed. \r
+  @param[in] DefaultId   Specifies the type of defaults to retrieve, which is only for DEFAULT action.\r
+  @param[in] HelpString  Help string that describes the hot key information.\r
+                         Its value may be NULL for the unregistered hot key.\r
+  \r
+  @retval EFI_SUCCESS            Hot key is registered or unregistered.\r
+  @retval EFI_INVALID_PARAMETER  KeyData is NULL or HelpString is NULL on register.\r
+  @retval EFI_NOT_FOUND          KeyData is not found to be unregistered.\r
+  @retval EFI_UNSUPPORTED        Key represents a printable character. It is conflicted with Browser.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RegisterHotKey (\r
+  IN EFI_INPUT_KEY *KeyData,\r
+  IN UINT32        Action,\r
+  IN UINT16        DefaultId,\r
+  IN EFI_STRING    HelpString OPTIONAL\r
+  )\r
+{\r
+  BROWSER_HOT_KEY  *HotKey;\r
+\r
+  //\r
+  // Check input parameters.\r
+  //\r
+  if (KeyData == NULL || KeyData->UnicodeChar != CHAR_NULL || \r
+     (Action != BROWSER_ACTION_UNREGISTER && HelpString == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Check whether the input KeyData is in BrowserHotKeyList.\r
+  //\r
+  HotKey = GetHotKeyFromRegisterList (KeyData);\r
+  \r
+  //\r
+  // Unregister HotKey\r
+  //\r
+  if (Action == BROWSER_ACTION_UNREGISTER) {\r
+    if (HotKey != NULL) {\r
+      //\r
+      // The registered HotKey is found.  \r
+      // Remove it from List, and free its resource.\r
+      //\r
+      RemoveEntryList (&HotKey->Link);\r
+      FreePool (HotKey->KeyData);\r
+      FreePool (HotKey->HelpString);\r
+      return EFI_SUCCESS;\r
+    } else {\r
+      //\r
+      // The registered HotKey is not found. \r
+      //\r
+      return EFI_NOT_FOUND;\r
+    }\r
+  }\r
+  \r
+  //\r
+  // Register HotKey into List.\r
+  //\r
+  if (HotKey == NULL) {\r
+    //\r
+    // Create new Key, and add it into List.\r
+    //\r
+    HotKey = AllocateZeroPool (sizeof (BROWSER_HOT_KEY));\r
+    ASSERT (HotKey != NULL);\r
+    HotKey->Signature = BROWSER_HOT_KEY_SIGNATURE;\r
+    HotKey->KeyData   = AllocateCopyPool (sizeof (EFI_INPUT_KEY), KeyData);\r
+    InsertTailList (&gBrowserHotKeyList, &HotKey->Link);\r
+  }\r
+\r
+  //\r
+  // Fill HotKey information.\r
+  //\r
+  HotKey->Action     = Action;\r
+  HotKey->DefaultId  = DefaultId;\r
+  if (HotKey->HelpString != NULL) {\r
+    FreePool (HotKey->HelpString);\r
+  }\r
+  HotKey->HelpString = AllocateCopyPool (StrSize (HelpString), HelpString);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Register Exit handler function. \r
+  When more than one handler function is registered, the latter one will override the previous one. \r
+  When NULL handler is specified, the previous Exit handler will be unregistered. \r
+  \r
+  @param[in] Handler      Pointer to handler function. \r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+RegiserExitHandler (\r
+  IN EXIT_HANDLER Handler\r
+  )\r
+{\r
+  ExitHandlerFunction = Handler;\r
+  return;\r
+}\r
+\r
+/**\r
+  Create reminder to let user to choose save or discard the changed browser data.\r
+  Caller can use it to actively check the changed browser data.\r
+\r
+  @retval BROWSER_NO_CHANGES       No browser data is changed.\r
+  @retval BROWSER_SAVE_CHANGES     The changed browser data is saved.\r
+  @retval BROWSER_DISCARD_CHANGES  The changed browser data is discard.\r
+\r
+**/\r
+UINT32\r
+EFIAPI\r
+SaveReminder (\r
+  VOID\r
+  )\r
+{\r
+  LIST_ENTRY              *Link;\r
+  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
+  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
+  }\r
+  \r
+  //\r
+  // No data is changed. No save is required. \r
+  //\r
+  if (!IsDataChanged) {\r
+    return DataSavedAction;\r
+  }\r
+  \r
+  //\r
+  // If data is changed, prompt user\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
+\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
+\r
+  return DataSavedAction;\r
+}\r