]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
HII Library Class interface refine.
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Setup.c
index 4ec9e6ee2aac805ddece6bdff6e5dbe9787061db..f5963ce2fe23f39b9b3019a9597314eb6240d2d9 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 = HiiLibPreparePackageList (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 = HiiLibNewString (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 HiiLibSetString (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 = HiiLibGetString (HiiHandle, Token, String, &BufferLength);
-
-  if (Status == EFI_BUFFER_TOO_SMALL) {
-    gBS->FreePool (String);
-    String = AllocateZeroPool (BufferLength);
-    ASSERT (String != NULL);
-
-    Status = HiiLibGetString (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 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "Setup.h"\r
+#include "Ui.h"\r
+\r
+\r
+SETUP_DRIVER_PRIVATE_DATA  mPrivateData = {\r
+  SETUP_DRIVER_SIGNATURE,\r
+  NULL,\r
+  {\r
+    SendForm,\r
+    BrowserCallback\r
+  }\r
+};\r
+\r
+EFI_HII_DATABASE_PROTOCOL         *mHiiDatabase;\r
+EFI_HII_STRING_PROTOCOL           *mHiiString;\r
+EFI_HII_CONFIG_ROUTING_PROTOCOL   *mHiiConfigRouting;\r
+\r
+BANNER_DATA           *BannerData;\r
+EFI_HII_HANDLE        FrontPageHandle;\r
+UINTN                 gClassOfVfr;\r
+UINTN                 gFunctionKeySetting;\r
+BOOLEAN               gResetRequired;\r
+BOOLEAN               gNvUpdateRequired;\r
+EFI_HII_HANDLE        gHiiHandle;\r
+UINT16                gDirection;\r
+EFI_SCREEN_DESCRIPTOR gScreenDimensions;\r
+BOOLEAN               gUpArrow;\r
+BOOLEAN               gDownArrow;\r
+\r
+//\r
+// Browser Global Strings\r
+//\r
+CHAR16            *gFunctionOneString;\r
+CHAR16            *gFunctionTwoString;\r
+CHAR16            *gFunctionNineString;\r
+CHAR16            *gFunctionTenString;\r
+CHAR16            *gEnterString;\r
+CHAR16            *gEnterCommitString;\r
+CHAR16            *gEnterEscapeString;\r
+CHAR16            *gEscapeString;\r
+CHAR16            *gSaveFailed;\r
+CHAR16            *gMoveHighlight;\r
+CHAR16            *gMakeSelection;\r
+CHAR16            *gDecNumericInput;\r
+CHAR16            *gHexNumericInput;\r
+CHAR16            *gToggleCheckBox;\r
+CHAR16            *gPromptForData;\r
+CHAR16            *gPromptForPassword;\r
+CHAR16            *gPromptForNewPassword;\r
+CHAR16            *gConfirmPassword;\r
+CHAR16            *gConfirmError;\r
+CHAR16            *gPassowordInvalid;\r
+CHAR16            *gPressEnter;\r
+CHAR16            *gEmptyString;\r
+CHAR16            *gAreYouSure;\r
+CHAR16            *gYesResponse;\r
+CHAR16            *gNoResponse;\r
+CHAR16            *gMiniString;\r
+CHAR16            *gPlusString;\r
+CHAR16            *gMinusString;\r
+CHAR16            *gAdjustNumber;\r
+CHAR16            *gSaveChanges;\r
+CHAR16            *gOptionMismatch;\r
+\r
+CHAR16            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
+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
+\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
+      return EFI_INVALID_PARAMETER;\r
+    } else {\r
+      //\r
+      // Local dimension validation.\r
+      //\r
+      if ((ScreenDimensions->RightColumn > ScreenDimensions->LeftColumn) &&\r
+          (ScreenDimensions->BottomRow > ScreenDimensions->TopRow) &&\r
+          ((ScreenDimensions->RightColumn - ScreenDimensions->LeftColumn) > 2) &&\r
+          (\r
+            (ScreenDimensions->BottomRow - ScreenDimensions->TopRow) > STATUS_BAR_HEIGHT +\r
+            SCROLL_ARROW_HEIGHT *\r
+            2 +\r
+            FRONT_PAGE_HEADER_HEIGHT +\r
+            FOOTER_HEIGHT +\r
+            1\r
+          )\r
+        ) {\r
+        CopyMem (&gScreenDimensions, (VOID *) ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
+      } else {\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+    }\r
+  }\r
+\r
+  gOptionBlockWidth = (CHAR16) ((gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3);\r
+  gHelpBlockWidth   = gOptionBlockWidth;\r
+  gPromptBlockWidth = gOptionBlockWidth;\r
+\r
+  //\r
+  // Initialize the strings for the browser, upon exit of the browser, the strings will be freed\r
+  //\r
+  InitializeBrowserStrings ();\r
+\r
+  gFunctionKeySetting = DEFAULT_FUNCTION_KEY_SETTING;\r
+  gClassOfVfr         = EFI_SETUP_APPLICATION_SUBCLASS;\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
+    }\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);\r
+      if (EFI_ERROR (Status) || IsListEmpty (&FormSet->FormListHead)) {\r
+        DestroyFormSet (FormSet);\r
+        break;\r
+      }\r
+      Selection->FormSet = FormSet;\r
+\r
+      //\r
+      // Initialize current settings of Questions in this FormSet\r
+      //\r
+      Status = InitializeCurrentSetting (FormSet);\r
+      if (EFI_ERROR (Status)) {\r
+        DestroyFormSet (FormSet);\r
+        break;\r
+      }\r
+\r
+      //\r
+      // Display this formset\r
+      //\r
+      gCurrentSelection = Selection;\r
+\r
+      Status = SetupBrowser (Selection);\r
+\r
+      gCurrentSelection = NULL;\r
+      DestroyFormSet (FormSet);\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        break;\r
+      }\r
+\r
+    } while (Selection->Action == UI_ACTION_REFRESH_FORMSET);\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
+\r
+  gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
+  gST->ConOut->ClearScreen (gST->ConOut);\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->Guid, (EFI_GUID *) VariableGuid)) {\r
+        if (Storage->Type == EFI_HII_VARSTORE_BUFFER) {\r
+          //\r
+          // Buffer storage require both GUID and Name\r
+          //\r
+          if (VariableName == NULL) {\r
+            return EFI_NOT_FOUND;\r
+          }\r
+\r
+          if (StrCmp (Storage->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, &ConfigResp);\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->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->ConfigHdr) + 2) * sizeof (CHAR16);\r
+    ConfigResp = AllocateZeroPool (BufferSize);\r
+    ASSERT (ConfigResp != NULL);\r
+\r
+    StrCpy (ConfigResp, Storage->ConfigHdr);\r
+    StrCat (ConfigResp, L"&");\r
+    StrCat (ConfigResp, ResultsData);\r
+\r
+    //\r
+    // Update Browser uncommited data\r
+    //\r
+    Status = ConfigRespToStorage (Storage, ConfigResp);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\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
+\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
+  //\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
+  BannerData = AllocateZeroPool (sizeof (BANNER_DATA));\r
+  ASSERT (BannerData != NULL);\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
+  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
+  String = HiiGetString (HiiHandle, Token, NULL);\r
+  ASSERT (String != NULL);\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 Storage's Edit copy to Shadow copy.\r
+\r
+  @param  Storage                The Storage to be synchronized.\r
+\r
+**/\r
+VOID\r
+SynchronizeStorage (\r
+  IN FORMSET_STORAGE         *Storage\r
+  )\r
+{\r
+  LIST_ENTRY              *Link;\r
+  NAME_VALUE_NODE         *Node;\r
+\r
+  switch (Storage->Type) {\r
+  case EFI_HII_VARSTORE_BUFFER:\r
+    CopyMem (Storage->Buffer, Storage->EditBuffer, Storage->Size);\r
+    break;\r
+\r
+  case EFI_HII_VARSTORE_NAME_VALUE:\r
+    Link = GetFirstNode (&Storage->NameValueListHead);\r
+    while (!IsNull (&Storage->NameValueListHead, Link)) {\r
+      Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
+\r
+      NewStringCpy (&Node->Value, Node->EditValue);\r
+\r
+      Link = GetNextNode (&Storage->NameValueListHead, Link);\r
+    }\r
+    break;\r
+\r
+  case EFI_HII_VARSTORE_EFI_VARIABLE:\r
+  default:\r
+    break;\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Get Value for given Name from a NameValue Storage.\r
+\r
+  @param  Storage                The NameValue Storage.\r
+  @param  Name                   The Name.\r
+  @param  Value                  The retured Value.\r
+\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 FORMSET_STORAGE         *Storage,\r
+  IN CHAR16                  *Name,\r
+  IN OUT CHAR16              **Value\r
+  )\r
+{\r
+  LIST_ENTRY              *Link;\r
+  NAME_VALUE_NODE         *Node;\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
+      NewStringCpy (Value, Node->EditValue);\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
+\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 FORMSET_STORAGE         *Storage,\r
+  IN CHAR16                  *Name,\r
+  IN CHAR16                  *Value\r
+  )\r
+{\r
+  LIST_ENTRY              *Link;\r
+  NAME_VALUE_NODE         *Node;\r
+\r
+  Link = GetFirstNode (&Storage->NameValueListHead);\r
+  while (!IsNull (&Storage->NameValueListHead, Link)) {\r
+    Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
+\r
+    if (StrCmp (Name, Node->Name) == 0) {\r
+      if (Node->EditValue != NULL) {\r
+        FreePool (Node->EditValue);\r
+      }\r
+      Node->EditValue = AllocateCopyPool (StrSize (Value), Value);\r
+      ASSERT (Node->EditValue != NULL);\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
+\r
+  @retval EFI_SUCCESS            Convert success.\r
+  @retval EFI_INVALID_PARAMETER  Incorrect storage type.\r
+\r
+**/\r
+EFI_STATUS\r
+StorageToConfigResp (\r
+  IN FORMSET_STORAGE         *Storage,\r
+  IN CHAR16                  **ConfigResp\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
+    Status = mHiiConfigRouting->BlockToConfig (\r
+                                  mHiiConfigRouting,\r
+                                  Storage->ConfigRequest,\r
+                                  Storage->EditBuffer,\r
+                                  Storage->Size,\r
+                                  ConfigResp,\r
+                                  &Progress\r
+                                  );\r
+    break;\r
+\r
+  case EFI_HII_VARSTORE_NAME_VALUE:\r
+    *ConfigResp = NULL;\r
+    NewStringCat (ConfigResp, Storage->ConfigHdr);\r
+\r
+    Link = GetFirstNode (&Storage->NameValueListHead);\r
+    while (!IsNull (&Storage->NameValueListHead, Link)) {\r
+      Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
+\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 FORMSET_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
+    BufferSize = Storage->Size;\r
+    Status = mHiiConfigRouting->ConfigToBlock (\r
+                                  mHiiConfigRouting,\r
+                                  ConfigResp,\r
+                                  Storage->EditBuffer,\r
+                                  &BufferSize,\r
+                                  &Progress\r
+                                  );\r
+    break;\r
+\r
+  case EFI_HII_VARSTORE_NAME_VALUE:\r
+    StrPtr = StrStr (ConfigResp, L"&");\r
+    while (StrPtr != NULL) {\r
+      //\r
+      // Skip '&'\r
+      //\r
+      StrPtr = StrPtr + 1;\r
+      Name = StrPtr;\r
+      StrPtr = StrStr (StrPtr, L"=");\r
+      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);\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  Cached                 TRUE:  get from Edit copy FALSE: get from original\r
+                                 Storage\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+GetQuestionValue (\r
+  IN FORM_BROWSER_FORMSET             *FormSet,\r
+  IN FORM_BROWSER_FORM                *Form,\r
+  IN OUT FORM_BROWSER_STATEMENT       *Question,\r
+  IN BOOLEAN                          Cached\r
+  )\r
+{\r
+  EFI_STATUS          Status;\r
+  BOOLEAN             Enabled;\r
+  BOOLEAN             Pending;\r
+  UINT8               *Dst;\r
+  UINTN               StorageWidth;\r
+  EFI_TIME            EfiTime;\r
+  FORMSET_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
+\r
+  Status = EFI_SUCCESS;\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
+      CopyMem (&Question->HiiValue, &Question->ValueExpression->Result, sizeof (EFI_HII_VALUE));\r
+    }\r
+    return Status;\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
+  IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);\r
+  IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ?  TRUE : FALSE);\r
+  if (Cached) {\r
+    if (IsBufferStorage) {\r
+      //\r
+      // Copy from storage Edit buffer\r
+      //\r
+      CopyMem (Dst, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth);\r
+    } else {\r
+      Status = GetValueByName (Storage, Question->VariableName, &Value);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      \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
+    //\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
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Skip <ConfigRequest>\r
+    //\r
+    Value = Result + Length;\r
+    if (IsBufferStorage) {\r
+      //\r
+      // Skip "&VALUE"\r
+      //\r
+      Value = Value + 6;\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
+\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);\r
+    }\r
+\r
+    FreePool (Result);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Save Question Value to edit copy(cached) or Storage(uncached).\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   Form data structure.\r
+  @param  Question               Pointer to the Question.\r
+  @param  Cached                 TRUE:  set to Edit copy FALSE: set to original\r
+                                 Storage\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+SetQuestionValue (\r
+  IN FORM_BROWSER_FORMSET             *FormSet,\r
+  IN FORM_BROWSER_FORM                *Form,\r
+  IN OUT FORM_BROWSER_STATEMENT       *Question,\r
+  IN BOOLEAN                          Cached\r
+  )\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
+  FORMSET_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
+  //\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
+  // 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
+  IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);\r
+  IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ?  TRUE : FALSE);\r
+  if (IsBufferStorage) {\r
+    //\r
+    // Copy to storage edit buffer\r
+    //\r
+    CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
+  } 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);\r
+    FreePool (Value);\r
+  }\r
+\r
+  if (!Cached) {\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
+    //\r
+    // Synchronize shadow Buffer\r
+    //\r
+    SynchronizeStorage (Storage);\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.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 a Form.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   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               *Form\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  LIST_ENTRY              *Link;\r
+  FORM_BROWSER_STATEMENT  *Question;\r
+\r
+  Link = GetFirstNode (&Form->StatementListHead);\r
+  while (!IsNull (&Form->StatementListHead, Link)) {\r
+    Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+\r
+    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
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Submit a Form.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   Form data structure.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+SubmitForm (\r
+  IN FORM_BROWSER_FORMSET             *FormSet,\r
+  IN FORM_BROWSER_FORM                *Form\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  LIST_ENTRY              *Link;\r
+  EFI_STRING              ConfigResp;\r
+  EFI_STRING              Progress;\r
+  FORMSET_STORAGE         *Storage;\r
+\r
+  //\r
+  // Validate the Form by NoSubmit check\r
+  //\r
+  Status = NoSubmitCheck (FormSet, Form);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Submit Buffer storage or Name/Value storage\r
+  //\r
+  Link = GetFirstNode (&FormSet->StorageListHead);\r
+  while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+    Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
+    Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+\r
+    if (Storage->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
+    //\r
+    // Prepare <ConfigResp>\r
+    //\r
+    Status = StorageToConfigResp (Storage, &ConfigResp);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Send <ConfigResp> to Configuration Driver\r
+    //\r
+    if (FormSet->ConfigAccess != NULL) {\r
+      Status = FormSet->ConfigAccess->RouteConfig (\r
+                                        FormSet->ConfigAccess,\r
+                                        ConfigResp,\r
+                                        &Progress\r
+                                        );\r
+      if (EFI_ERROR (Status)) {\r
+        FreePool (ConfigResp);\r
+        return Status;\r
+      }\r
+    }\r
+    FreePool (ConfigResp);\r
+\r
+    //\r
+    // Config success, update storage shadow Buffer\r
+    //\r
+    SynchronizeStorage (Storage);\r
+  }\r
+\r
+  gNvUpdateRequired = FALSE;\r
+\r
+  return EFI_SUCCESS;\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
+\r
+  Status = EFI_SUCCESS;\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 three ways to specify default value for a Question:\r
+  //  1, use nested EFI_IFR_DEFAULT (highest priority)\r
+  //  2, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)\r
+  //  3, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)\r
+  //\r
+  HiiValue = &Question->HiiValue;\r
+\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
+          CopyMem (HiiValue, &Default->ValueExpression->Result, sizeof (EFI_HII_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
+        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
+\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
+        Link = GetNextNode (&Question->OptionListHead, Link);\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
+  switch (Question->Operand) {\r
+  case EFI_IFR_NUMERIC_OP:\r
+    //\r
+    // Take minimal value as numeric's default value\r
+    //\r
+    HiiValue->Value.u64 = Question->Minimum;\r
+    break;\r
+\r
+  case EFI_IFR_ONE_OF_OP:\r
+    //\r
+    // Take first oneof option as oneof's default value\r
+    //\r
+    Link = GetFirstNode (&Question->OptionListHead);\r
+    if (!IsNull (&Question->OptionListHead, Link)) {\r
+      Option = QUESTION_OPTION_FROM_LINK (Link);\r
+      CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
+    }\r
+    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
+      Option = QUESTION_OPTION_FROM_LINK (Link);\r
+\r
+      Question->BufferValue[Index] = Option->Value.Value.u8;\r
+\r
+      Index++;\r
+      if (Index >= Question->MaxContainers) {\r
+        break;\r
+      }\r
+\r
+      Link = GetNextNode (&Question->OptionListHead, Link);\r
+    }\r
+    break;\r
+\r
+  default:\r
+    Status = EFI_NOT_FOUND;\r
+    break;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Reset Questions in a Form to their default value.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   The Form which to be reset.\r
+  @param  DefaultId              The Class of the default.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+ExtractFormDefault (\r
+  IN FORM_BROWSER_FORMSET             *FormSet,\r
+  IN FORM_BROWSER_FORM                *Form,\r
+  IN UINT16                           DefaultId\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  LIST_ENTRY              *Link;\r
+  FORM_BROWSER_STATEMENT  *Question;\r
+\r
+  Link = GetFirstNode (&Form->StatementListHead);\r
+  while (!IsNull (&Form->StatementListHead, Link)) {\r
+    Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+    Link = GetNextNode (&Form->StatementListHead, Link);\r
+\r
+    //\r
+    // If Question is suppressed, don't reset it to default\r
+    //\r
+    if (Question->SuppressExpression != NULL) {\r
+      Status = EvaluateExpression (FormSet, Form, Question->SuppressExpression);\r
+      if (!EFI_ERROR (Status) && Question->SuppressExpression->Result.Value.b) {\r
+        continue;\r
+      }\r
+    }\r
+\r
+    //\r
+    // Reset Question to its default value\r
+    //\r
+    Status = GetQuestionDefault (FormSet, Form, Question, DefaultId);\r
+    if (EFI_ERROR (Status)) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Synchronize Buffer storage's Edit buffer\r
+    //\r
+    if ((Question->Storage != NULL) &&\r
+        (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
+      SetQuestionValue (FormSet, Form, Question, TRUE);\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Initialize Question's Edit copy from Storage.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   Form data structure.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+LoadFormConfig (\r
+  IN FORM_BROWSER_FORMSET             *FormSet,\r
+  IN FORM_BROWSER_FORM                *Form\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  LIST_ENTRY              *Link;\r
+  FORM_BROWSER_STATEMENT  *Question;\r
+\r
+  Link = GetFirstNode (&Form->StatementListHead);\r
+  while (!IsNull (&Form->StatementListHead, Link)) {\r
+    Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+\r
+    //\r
+    // Initialize local copy of Value for each Question\r
+    //\r
+    Status = GetQuestionValue (FormSet, Form, Question, TRUE);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    Link = GetNextNode (&Form->StatementListHead, Link);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Fill storage's edit copy with settings requested from Configuration Driver.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Storage                Buffer Storage.\r
+\r
+  @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
+\r
+  if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  if (FormSet->ConfigAccess == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  if (Storage->ElementCount == 0) {\r
+    //\r
+    // Skip if there is no RequestElement\r
+    //\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Request current settings from Configuration Driver\r
+  //\r
+  Status = FormSet->ConfigAccess->ExtractConfig (\r
+                                    FormSet->ConfigAccess,\r
+                                    Storage->ConfigRequest,\r
+                                    &Progress,\r
+                                    &Result\r
+                                    );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Convert Result from <ConfigAltResp> to <ConfigResp>\r
+  //\r
+  StrPtr = StrStr (Result, L"ALTCFG");\r
+  if (StrPtr != NULL) {\r
+    *StrPtr = L'\0';\r
+  }\r
+\r
+  Status = ConfigRespToStorage (Storage, Result);\r
+  FreePool (Result);\r
+  return Status;\r
+}\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
+  FORMSET_STORAGE         *Storage;\r
+  FORM_BROWSER_FORM       *Form;\r
+  EFI_STATUS              Status;\r
+\r
+  //\r
+  // Extract default from IFR binary\r
+  //\r
+  Link = GetFirstNode (&FormSet->FormListHead);\r
+  while (!IsNull (&FormSet->FormListHead, Link)) {\r
+    Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+\r
+    Status = ExtractFormDefault (FormSet, Form, EFI_HII_DEFAULT_CLASS_STANDARD);\r
+\r
+    Link = GetNextNode (&FormSet->FormListHead, Link);\r
+  }\r
+\r
+  //\r
+  // Request current settings from Configuration Driver\r
+  //\r
+  Link = GetFirstNode (&FormSet->StorageListHead);\r
+  while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+    Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
+\r
+    Status = LoadStorage (FormSet, Storage);\r
+\r
+    //\r
+    // Now Edit Buffer is filled with default values(lower priority) and current\r
+    // settings(higher priority), sychronize it to shadow Buffer\r
+    //\r
+    if (!EFI_ERROR (Status)) {\r
+      SynchronizeStorage (Storage);\r
+    }\r
+\r
+    Link = GetNextNode (&FormSet->StorageListHead, Link);\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            GUID of a formset. If not specified (NULL or zero\r
+                                 GUID), take the first FormSet found in package\r
+                                 list.\r
+  @param  BinaryLength           The length of the FormSet IFR binary.\r
+  @param  BinaryData             The buffer designed to receive the FormSet.\r
+\r
+  @retval EFI_SUCCESS            Buffer filled with the requested FormSet.\r
+                                 BufferLength was updated.\r
+  @retval EFI_INVALID_PARAMETER  The handle is unknown.\r
+  @retval EFI_NOT_FOUND          A form or FormSet on the requested handle cannot\r
+                                 be found with the requested FormId.\r
+\r
+**/\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
+  BOOLEAN                      ReturnDefault;\r
+  UINT32                       PackageListLength;\r
+  EFI_HII_PACKAGE_HEADER       PackageHeader;\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 FormSet in the package list\r
+  //\r
+  if (FormSetGuid == NULL || CompareGuid (FormSetGuid, &gZeroGuid)) {\r
+    ReturnDefault = TRUE;\r
+  } else {\r
+    ReturnDefault = FALSE;\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
+  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
+          // Check whether return default FormSet\r
+          //\r
+          if (ReturnDefault) {\r
+            break;\r
+          }\r
+\r
+          //\r
+          // FormSet GUID is specified, check it\r
+          //\r
+          if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
+            break;\r
+          }\r
+        }\r
+\r
+        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 (ReturnDefault && FormSetGuid != NULL) {\r
+    //\r
+    // Return the default FormSet GUID\r
+    //\r
+    CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
+  }\r
+\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            GUID of a formset. If not specified (NULL or zero\r
+                                 GUID), take the first FormSet found in package\r
+                                 list.\r
+  @param  FormSet                FormSet data structure.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+  @retval EFI_NOT_FOUND          The specified FormSet could not be found.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeFormSet (\r
+  IN  EFI_HII_HANDLE                   Handle,\r
+  IN OUT EFI_GUID                      *FormSetGuid,\r
+  OUT FORM_BROWSER_FORMSET             *FormSet\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_HANDLE                DriverHandle;\r
+  UINT16                    Index;\r
+\r
+  Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\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
+  gClassOfVfr = FormSet->SubClass;\r
+  if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {\r
+    FrontPageHandle = FormSet->HiiHandle;\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
+      // Function key prompt can not be displayed if the function key has been disabled.\r
+      //\r
+      if ((gFunctionKeySetting & FUNCTION_ONE) != FUNCTION_ONE) {\r
+        gFunctionOneString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
+      }\r
+\r
+      if ((gFunctionKeySetting & FUNCTION_TWO) != FUNCTION_TWO) {\r
+        gFunctionTwoString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
+      }\r
+\r
+      if ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE) {\r
+        gFunctionNineString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
+      }\r
+\r
+      if ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN) {\r
+        gFunctionTenString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
+      }\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r