]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
MdeModulePkg:fix browser not call EFI_BROWSER_ACTION_CHANGED
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Presentation.c
index 631f6413b889f65ab6aa2ad7029959153ef5c85d..b8c5a3919ef1629a11d8127a3143fd1850efba5c 100644 (file)
-/** @file
-Copyright (c) 2004 - 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:
-  Presentation.c
-
-Abstract:
-
-  Some presentation routines.
-
-
-**/
-
-#include "Setup.h"
-#include "Ui.h"
-
-BOOLEAN            mHiiPackageListUpdated;
-UI_MENU_SELECTION  *gCurrentSelection;
-
-
-/**
-  Clear retangle with specified text attribute.
-
-  @param  LeftColumn     Left column of retangle.
-  @param  RightColumn    Right column of retangle.
-  @param  TopRow         Start row of retangle.
-  @param  BottomRow      End row of retangle.
-  @param  TextAttribute  The character foreground and background.
-
-  @return None.
-
-**/
-VOID
-ClearLines (
-  UINTN                                       LeftColumn,
-  UINTN                                       RightColumn,
-  UINTN                                       TopRow,
-  UINTN                                       BottomRow,
-  UINTN                                       TextAttribute
-  )
-{
-  CHAR16  *Buffer;
-  UINTN   Row;
-
-  //
-  // For now, allocate an arbitrarily long buffer
-  //
-  Buffer = AllocateZeroPool (0x10000);
-  ASSERT (Buffer != NULL);
-
-  //
-  // Set foreground and background as defined
-  //
-  gST->ConOut->SetAttribute (gST->ConOut, TextAttribute);
-
-  //
-  // Much faster to buffer the long string instead of print it a character at a time
-  //
-  SetUnicodeMem (Buffer, RightColumn - LeftColumn, L' ');
-
-  //
-  // Clear the desired area with the appropriate foreground/background
-  //
-  for (Row = TopRow; Row <= BottomRow; Row++) {
-    PrintStringAt (LeftColumn, Row, Buffer);
-  }
-
-  gST->ConOut->SetCursorPosition (gST->ConOut, LeftColumn, TopRow);
-
-  gBS->FreePool (Buffer);
-  return ;
-}
-
-VOID
-NewStrCat (
-  CHAR16                                      *Destination,
-  CHAR16                                      *Source
-  )
-{
-  UINTN Length;
-
-  for (Length = 0; Destination[Length] != 0; Length++)
-    ;
-
-  //
-  // We now have the length of the original string
-  // We can safely assume for now that we are concatenating a narrow value to this string.
-  // For instance, the string is "XYZ" and cat'ing ">"
-  // If this assumption changes, we need to make this routine a bit more complex
-  //
-  Destination[Length] = NARROW_CHAR;
-  Length++;
-
-  StrCpy (Destination + Length, Source);
-}
-
-UINTN
-GetStringWidth (
-  CHAR16                                      *String
-  )
-{
-  UINTN Index;
-  UINTN Count;
-  UINTN IncrementValue;
-
-  Index           = 0;
-  Count           = 0;
-  IncrementValue  = 1;
-
-  do {
-    //
-    // Advance to the null-terminator or to the first width directive
-    //
-    for (;
-         (String[Index] != NARROW_CHAR) && (String[Index] != WIDE_CHAR) && (String[Index] != 0);
-         Index++, Count = Count + IncrementValue
-        )
-      ;
-
-    //
-    // We hit the null-terminator, we now have a count
-    //
-    if (String[Index] == 0) {
-      break;
-    }
-    //
-    // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed
-    // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2)
-    //
-    if (String[Index] == NARROW_CHAR) {
-      //
-      // Skip to the next character
-      //
-      Index++;
-      IncrementValue = 1;
-    } else {
-      //
-      // Skip to the next character
-      //
-      Index++;
-      IncrementValue = 2;
-    }
-  } while (String[Index] != 0);
-
-  //
-  // Increment by one to include the null-terminator in the size
-  //
-  Count++;
-
-  return Count * sizeof (CHAR16);
-}
-
-VOID
-DisplayPageFrame (
-  VOID
-  )
-{
-  UINTN                  Index;
-  UINT8                  Line;
-  UINT8                  Alignment;
-  CHAR16                 Character;
-  CHAR16                 *Buffer;
-  CHAR16                 *StrFrontPageBanner;
-  UINTN                  Row;
-  EFI_SCREEN_DESCRIPTOR  LocalScreen;
-
-  ZeroMem (&LocalScreen, sizeof (EFI_SCREEN_DESCRIPTOR));
-  gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &LocalScreen.RightColumn, &LocalScreen.BottomRow);
-  ClearLines (0, LocalScreen.RightColumn, 0, LocalScreen.BottomRow, KEYHELP_BACKGROUND);
-
-  CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
-
-  //
-  // For now, allocate an arbitrarily long buffer
-  //
-  Buffer = AllocateZeroPool (0x10000);
-  ASSERT (Buffer != NULL);
-
-  Character = BOXDRAW_HORIZONTAL;
-
-  for (Index = 0; Index + 2 < (LocalScreen.RightColumn - LocalScreen.LeftColumn); Index++) {
-    Buffer[Index] = Character;
-  }
-
-  if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {
-    //
-    //    ClearLines(0, LocalScreen.RightColumn, 0, BANNER_HEIGHT-1, BANNER_TEXT | BANNER_BACKGROUND);
-    //
-    ClearLines (
-      LocalScreen.LeftColumn,
-      LocalScreen.RightColumn,
-      LocalScreen.TopRow,
-      FRONT_PAGE_HEADER_HEIGHT - 1 + LocalScreen.TopRow,
-      BANNER_TEXT | BANNER_BACKGROUND
-      );
-    //
-    //    for (Line = 0; Line < BANNER_HEIGHT; Line++) {
-    //
-    for (Line = (UINT8) LocalScreen.TopRow; Line < BANNER_HEIGHT + (UINT8) LocalScreen.TopRow; Line++) {
-      //
-      //      for (Alignment = 0; Alignment < BANNER_COLUMNS; Alignment++) {
-      //
-      for (Alignment = (UINT8) LocalScreen.LeftColumn;
-           Alignment < BANNER_COLUMNS + (UINT8) LocalScreen.LeftColumn;
-           Alignment++
-          ) {
-        if (BannerData->Banner[Line - (UINT8) LocalScreen.TopRow][Alignment - (UINT8) LocalScreen.LeftColumn] != 0x0000) {
-          StrFrontPageBanner = GetToken (
-                                BannerData->Banner[Line - (UINT8) LocalScreen.TopRow][Alignment - (UINT8) LocalScreen.LeftColumn],
-                                FrontPageHandle
-                                );
-        } else {
-          continue;
-        }
-
-        switch (Alignment - LocalScreen.LeftColumn) {
-        case 0:
-          //
-          // Handle left column
-          //
-          PrintStringAt (LocalScreen.LeftColumn, Line, StrFrontPageBanner);
-          break;
-
-        case 1:
-          //
-          // Handle center column
-          //
-          PrintStringAt (
-            LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,
-            Line,
-            StrFrontPageBanner
-            );
-          break;
-
-        case 2:
-          //
-          // Handle right column
-          //
-          PrintStringAt (
-            LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3,
-            Line,
-            StrFrontPageBanner
-            );
-          break;
-        }
-
-        gBS->FreePool (StrFrontPageBanner);
-      }
-    }
-  }
-
-  ClearLines (
-    LocalScreen.LeftColumn,
-    LocalScreen.RightColumn,
-    LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT,
-    LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1,
-    KEYHELP_TEXT | KEYHELP_BACKGROUND
-    );
-
-  if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {
-    ClearLines (
-      LocalScreen.LeftColumn,
-      LocalScreen.RightColumn,
-      LocalScreen.TopRow,
-      LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1,
-      TITLE_TEXT | TITLE_BACKGROUND
-      );
-    //
-    // Print Top border line
-    // +------------------------------------------------------------------------------+
-    // ?                                                                             ?
-    // +------------------------------------------------------------------------------+
-    //
-    Character = BOXDRAW_DOWN_RIGHT;
-
-    PrintChar (Character);
-    PrintString (Buffer);
-
-    Character = BOXDRAW_DOWN_LEFT;
-    PrintChar (Character);
-
-    Character = BOXDRAW_VERTICAL;
-    for (Row = LocalScreen.TopRow + 1; Row <= LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 2; Row++) {
-      PrintCharAt (LocalScreen.LeftColumn, Row, Character);
-      PrintCharAt (LocalScreen.RightColumn - 1, Row, Character);
-    }
-
-    Character = BOXDRAW_UP_RIGHT;
-    PrintCharAt (LocalScreen.LeftColumn, LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1, Character);
-    PrintString (Buffer);
-
-    Character = BOXDRAW_UP_LEFT;
-    PrintChar (Character);
-
-    if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {
-      //
-      // Print Bottom border line
-      // +------------------------------------------------------------------------------+
-      // ?                                                                             ?
-      // +------------------------------------------------------------------------------+
-      //
-      Character = BOXDRAW_DOWN_RIGHT;
-      PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT, Character);
-
-      PrintString (Buffer);
-
-      Character = BOXDRAW_DOWN_LEFT;
-      PrintChar (Character);
-      Character = BOXDRAW_VERTICAL;
-      for (Row = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT + 1;
-           Row <= LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 2;
-           Row++
-          ) {
-        PrintCharAt (LocalScreen.LeftColumn, Row, Character);
-        PrintCharAt (LocalScreen.RightColumn - 1, Row, Character);
-      }
-
-      Character = BOXDRAW_UP_RIGHT;
-      PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1, Character);
-
-      PrintString (Buffer);
-
-      Character = BOXDRAW_UP_LEFT;
-      PrintChar (Character);
-    }
-  }
-
-  gBS->FreePool (Buffer);
-
-}
-
-
-/**
-  Evaluate all expressions in a Form.
-
-  @param  FormSet        FormSet this Form belongs to.
-  @param  Form           The Form.
-
-  @retval EFI_SUCCESS    The expression evaluated successfuly
-
-**/
-EFI_STATUS
-EvaluateFormExpressions (
-  IN FORM_BROWSER_FORMSET  *FormSet,
-  IN FORM_BROWSER_FORM     *Form
-  )
-{
-  EFI_STATUS       Status;
-  LIST_ENTRY       *Link;
-  FORM_EXPRESSION  *Expression;
-
-  Link = GetFirstNode (&Form->ExpressionListHead);
-  while (!IsNull (&Form->ExpressionListHead, Link)) {
-    Expression = FORM_EXPRESSION_FROM_LINK (Link);
-    Link = GetNextNode (&Form->ExpressionListHead, Link);
-
-    if (Expression->Type == EFI_HII_EXPRESSION_INCONSISTENT_IF ||
-        Expression->Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {
-      //
-      // Postpone Form validation to Question editing or Form submiting
-      //
-      continue;
-    }
-
-    Status = EvaluateExpression (FormSet, Form, Expression);
-    if (EFI_ERROR (Status)) {
-      return Status;
-    }
-  }
-
-  return EFI_SUCCESS;
-}
-
-/*
-+------------------------------------------------------------------------------+
-?F2=Previous Page                 Setup Page                                  ?
-+------------------------------------------------------------------------------+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-+------------------------------------------------------------------------------+
-?F1=Scroll Help                 F9=Reset to Defaults        F10=Save and Exit ?
-| ^"=Move Highlight          <Spacebar> Toggles Checkbox   Esc=Discard Changes |
-+------------------------------------------------------------------------------+
-*/
-EFI_STATUS
-DisplayForm (
-  IN OUT UI_MENU_SELECTION           *Selection
-  )
-{
-  CHAR16                 *StringPtr;
-  UINT16                 MenuItemCount;
-  EFI_HII_HANDLE         Handle;
-  BOOLEAN                Suppress;
-  EFI_SCREEN_DESCRIPTOR  LocalScreen;
-  UINT16                 Width;
-  UINTN                  ArrayEntry;
-  CHAR16                 *OutputString;
-  LIST_ENTRY             *Link;
-  FORM_BROWSER_STATEMENT *Statement;
-  UINT16                 NumberOfLines;
-  EFI_STATUS             Status;
-
-  Handle        = Selection->Handle;
-  MenuItemCount = 0;
-  ArrayEntry    = 0;
-  OutputString  = NULL;
-
-  UiInitMenu ();
-
-  CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
-
-  StringPtr = GetToken (Selection->FormSet->FormSetTitle, Handle);
-
-  if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {
-    gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | TITLE_BACKGROUND);
-    PrintStringAt (
-      (LocalScreen.RightColumn + LocalScreen.LeftColumn - GetStringWidth (StringPtr) / 2) / 2,
-      LocalScreen.TopRow + 1,
-      StringPtr
-      );
-  }
-
-  if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {
-    gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);
-
-    //
-    // Display the infrastructure strings
-    //
-    if (!IsListEmpty (&gMenuList)) {
-      PrintStringAt (LocalScreen.LeftColumn + 2, LocalScreen.TopRow + 1, gFunctionTwoString);
-    }
-
-    PrintStringAt (LocalScreen.LeftColumn + 2, LocalScreen.BottomRow - 4, gFunctionOneString);
-    PrintStringAt (
-      LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,
-      LocalScreen.BottomRow - 4,
-      gFunctionNineString
-      );
-    PrintStringAt (
-      LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3,
-      LocalScreen.BottomRow - 4,
-      gFunctionTenString
-      );
-    PrintAt (LocalScreen.LeftColumn + 2, LocalScreen.BottomRow - 3, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
-    PrintStringAt (
-      LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,
-      LocalScreen.BottomRow - 3,
-      gEscapeString
-      );
-  }
-  //
-  // Remove Buffer allocated for StringPtr after it has been used.
-  //
-  gBS->FreePool (StringPtr);
-
-  //
-  // Evaluate all the Expressions in this Form
-  //
-  Status = EvaluateFormExpressions (Selection->FormSet, Selection->Form);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  Link = GetFirstNode (&Selection->Form->StatementListHead);
-  while (!IsNull (&Selection->Form->StatementListHead, Link)) {
-    Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
-
-    if (Statement->SuppressExpression != NULL) {
-      Suppress = Statement->SuppressExpression->Result.Value.b;
-    } else {
-      Suppress = FALSE;
-    }
-
-    if (!Suppress) {
-      StringPtr = GetToken (Statement->Prompt, Handle);
-
-      Width     = GetWidth (Statement, Handle);
-
-      NumberOfLines = 1;
-      ArrayEntry = 0;
-      for (; GetLineByWidth (StringPtr, Width, &ArrayEntry, &OutputString) != 0x0000;) {
-        //
-        // If there is more string to process print on the next row and increment the Skip value
-        //
-        if (StrLen (&StringPtr[ArrayEntry])) {
-          NumberOfLines++;
-        }
-
-        gBS->FreePool (OutputString);
-      }
-
-      //
-      // We are NOT!! removing this StringPtr buffer via FreePool since it is being used in the menuoptions, we will do
-      // it in UiFreeMenu.
-      //
-      UiAddMenuOption (StringPtr, Selection->Handle, Statement, NumberOfLines, MenuItemCount);
-      MenuItemCount++;
-    }
-
-    Link = GetNextNode (&Selection->Form->StatementListHead, Link);
-  }
-
-  Status = UiDisplayMenu (Selection);
-
-  UiFreeMenu ();
-
-  return Status;
-}
-
-VOID
-InitializeBrowserStrings (
-  VOID
-  )
-{
-  gFunctionOneString    = GetToken (STRING_TOKEN (FUNCTION_ONE_STRING), gHiiHandle);
-  gFunctionTwoString    = GetToken (STRING_TOKEN (FUNCTION_TWO_STRING), gHiiHandle);
-  gFunctionNineString   = GetToken (STRING_TOKEN (FUNCTION_NINE_STRING), gHiiHandle);
-  gFunctionTenString    = GetToken (STRING_TOKEN (FUNCTION_TEN_STRING), gHiiHandle);
-  gEnterString          = GetToken (STRING_TOKEN (ENTER_STRING), gHiiHandle);
-  gEnterCommitString    = GetToken (STRING_TOKEN (ENTER_COMMIT_STRING), gHiiHandle);
-  gEscapeString         = GetToken (STRING_TOKEN (ESCAPE_STRING), gHiiHandle);
-  gSaveFailed           = GetToken (STRING_TOKEN (SAVE_FAILED), gHiiHandle);
-  gMoveHighlight        = GetToken (STRING_TOKEN (MOVE_HIGHLIGHT), gHiiHandle);
-  gMakeSelection        = GetToken (STRING_TOKEN (MAKE_SELECTION), gHiiHandle);
-  gDecNumericInput      = GetToken (STRING_TOKEN (DEC_NUMERIC_INPUT), gHiiHandle);
-  gHexNumericInput      = GetToken (STRING_TOKEN (HEX_NUMERIC_INPUT), gHiiHandle);
-  gToggleCheckBox       = GetToken (STRING_TOKEN (TOGGLE_CHECK_BOX), gHiiHandle);
-  gPromptForData        = GetToken (STRING_TOKEN (PROMPT_FOR_DATA), gHiiHandle);
-  gPromptForPassword    = GetToken (STRING_TOKEN (PROMPT_FOR_PASSWORD), gHiiHandle);
-  gPromptForNewPassword = GetToken (STRING_TOKEN (PROMPT_FOR_NEW_PASSWORD), gHiiHandle);
-  gConfirmPassword      = GetToken (STRING_TOKEN (CONFIRM_PASSWORD), gHiiHandle);
-  gConfirmError         = GetToken (STRING_TOKEN (CONFIRM_ERROR), gHiiHandle);
-  gPassowordInvalid     = GetToken (STRING_TOKEN (PASSWORD_INVALID), gHiiHandle);
-  gPressEnter           = GetToken (STRING_TOKEN (PRESS_ENTER), gHiiHandle);
-  gEmptyString          = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
-  gAreYouSure           = GetToken (STRING_TOKEN (ARE_YOU_SURE), gHiiHandle);
-  gYesResponse          = GetToken (STRING_TOKEN (ARE_YOU_SURE_YES), gHiiHandle);
-  gNoResponse           = GetToken (STRING_TOKEN (ARE_YOU_SURE_NO), gHiiHandle);
-  gMiniString           = GetToken (STRING_TOKEN (MINI_STRING), gHiiHandle);
-  gPlusString           = GetToken (STRING_TOKEN (PLUS_STRING), gHiiHandle);
-  gMinusString          = GetToken (STRING_TOKEN (MINUS_STRING), gHiiHandle);
-  gAdjustNumber         = GetToken (STRING_TOKEN (ADJUST_NUMBER), gHiiHandle);
-  return ;
-}
-
-VOID
-FreeBrowserStrings (
-  VOID
-  )
-{
-  SafeFreePool (gFunctionOneString);
-  SafeFreePool (gFunctionTwoString);
-  SafeFreePool (gFunctionNineString);
-  SafeFreePool (gFunctionTenString);
-  SafeFreePool (gEnterString);
-  SafeFreePool (gEnterCommitString);
-  SafeFreePool (gEscapeString);
-  SafeFreePool (gMoveHighlight);
-  SafeFreePool (gMakeSelection);
-  SafeFreePool (gDecNumericInput);
-  SafeFreePool (gHexNumericInput);
-  SafeFreePool (gToggleCheckBox);
-  SafeFreePool (gPromptForData);
-  SafeFreePool (gPromptForPassword);
-  SafeFreePool (gPromptForNewPassword);
-  SafeFreePool (gConfirmPassword);
-  SafeFreePool (gPassowordInvalid);
-  SafeFreePool (gConfirmError);
-  SafeFreePool (gPressEnter);
-  SafeFreePool (gEmptyString);
-  SafeFreePool (gAreYouSure);
-  SafeFreePool (gYesResponse);
-  SafeFreePool (gNoResponse);
-  SafeFreePool (gMiniString);
-  SafeFreePool (gPlusString);
-  SafeFreePool (gMinusString);
-  SafeFreePool (gAdjustNumber);
-  return ;
-}
-
-
-/**
-  Update key's help imformation
-
-  @param  MenuOption     The Menu option
-  @param  Selected       Whether or not a tag be selected
-
-  @return None
-
-**/
-VOID
-UpdateKeyHelp (
-  IN  UI_MENU_OPTION              *MenuOption,
-  IN  BOOLEAN                     Selected
-  )
-{
-  UINTN                  SecCol;
-  UINTN                  ThdCol;
-  UINTN                  LeftColumnOfHelp;
-  UINTN                  RightColumnOfHelp;
-  UINTN                  TopRowOfHelp;
-  UINTN                  BottomRowOfHelp;
-  UINTN                  StartColumnOfHelp;
-  EFI_SCREEN_DESCRIPTOR  LocalScreen;
-  FORM_BROWSER_STATEMENT *Statement;
-
-  CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
-
-  SecCol            = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3;
-  ThdCol            = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3;
-
-  StartColumnOfHelp = LocalScreen.LeftColumn + 2;
-  LeftColumnOfHelp  = LocalScreen.LeftColumn + 1;
-  RightColumnOfHelp = LocalScreen.RightColumn - 2;
-  TopRowOfHelp      = LocalScreen.BottomRow - 4;
-  BottomRowOfHelp   = LocalScreen.BottomRow - 3;
-
-  if (gClassOfVfr == EFI_GENERAL_APPLICATION_SUBCLASS) {
-    return ;
-  }
-
-  gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);
-
-  Statement = MenuOption->ThisTag;
-  switch (Statement->Operand) {
-  case EFI_IFR_ORDERED_LIST_OP:
-  case EFI_IFR_ONE_OF_OP:
-  case EFI_IFR_NUMERIC_OP:
-  case EFI_IFR_TIME_OP:
-  case EFI_IFR_DATE_OP:
-    ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);
-
-    if (!Selected) {
-      if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {
-        PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);
-        PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);
-        PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);
-        PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
-      }
-
-      if ((Statement->Operand == EFI_IFR_DATE_OP) ||
-          (Statement->Operand == EFI_IFR_TIME_OP) ||
-          (Statement->Operand == EFI_IFR_NUMERIC_OP && Statement->Step != 0)) {
-        PrintAt (
-          StartColumnOfHelp,
-          BottomRowOfHelp,
-          L"%c%c%c%c%s",
-          ARROW_UP,
-          ARROW_DOWN,
-          ARROW_RIGHT,
-          ARROW_LEFT,
-          gMoveHighlight
-          );
-        PrintStringAt (SecCol, BottomRowOfHelp, gAdjustNumber);
-      } else {
-        PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
-        PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);
-      }
-    } else {
-      PrintStringAt (SecCol, BottomRowOfHelp, gEnterCommitString);
-
-      //
-      // If it is a selected numeric with manual input, display different message
-      //
-      if ((Statement->Operand == EFI_IFR_NUMERIC_OP) && (Statement->Step == 0)) {
-        PrintStringAt (
-          SecCol,
-          TopRowOfHelp,
-          (Statement->Flags & EFI_IFR_DISPLAY_UINT_HEX) ? gHexNumericInput : gDecNumericInput
-          );
-      } else if (Statement->Operand != EFI_IFR_ORDERED_LIST_OP) {
-        PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
-      }
-
-      if (Statement->Operand == EFI_IFR_ORDERED_LIST_OP) {
-        PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gPlusString);
-        PrintStringAt (ThdCol, TopRowOfHelp, gMinusString);
-      }
-
-      PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
-    }
-    break;
-
-  case EFI_IFR_CHECKBOX_OP:
-    ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);
-
-    if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {
-      PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);
-      PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);
-      PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);
-      PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
-    }
-
-    PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
-    PrintStringAt (SecCol, BottomRowOfHelp, gToggleCheckBox);
-    break;
-
-  case EFI_IFR_REF_OP:
-  case EFI_IFR_PASSWORD_OP:
-  case EFI_IFR_STRING_OP:
-  case EFI_IFR_TEXT_OP:
-  case EFI_IFR_ACTION_OP:
-  case EFI_IFR_RESET_BUTTON_OP:
-    ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);
-
-    if (!Selected) {
-      if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {
-        PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);
-        PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);
-        PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);
-        PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
-      }
-
-      PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
-      if (Statement->Operand != EFI_IFR_TEXT_OP) {
-        PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);
-      }
-    } else {
-      if (Statement->Operand != EFI_IFR_REF_OP) {
-        PrintStringAt (
-          (LocalScreen.RightColumn - GetStringWidth (gEnterCommitString) / 2) / 2,
-          BottomRowOfHelp,
-          gEnterCommitString
-          );
-        PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
-      }
-    }
-    break;
-
-  default:
-    break;
-  }
-}
-
-EFI_STATUS
-FormUpdateNotify (
-  IN UINT8                              PackageType,
-  IN CONST EFI_GUID                     *PackageGuid,
-  IN CONST EFI_HII_PACKAGE_HEADER       *Package,
-  IN EFI_HII_HANDLE                     Handle,
-  IN EFI_HII_DATABASE_NOTIFY_TYPE       NotifyType
-  )
-{
-  mHiiPackageListUpdated = TRUE;
-
-  return EFI_SUCCESS;
-}
-
-EFI_STATUS
-SetupBrowser (
-  IN OUT UI_MENU_SELECTION    *Selection
-  )
-{
-  EFI_STATUS                      Status;
-  LIST_ENTRY                      *Link;
-  EFI_BROWSER_ACTION_REQUEST      ActionRequest;
-  EFI_HANDLE                      NotifyHandle;
-  EFI_HII_VALUE                   *HiiValue;
-  FORM_BROWSER_STATEMENT          *Statement;
-  EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;
-
-  gMenuRefreshHead = NULL;
-  gResetRequired = FALSE;
-  gNvUpdateRequired = FALSE;
-
-  UiInitMenuList ();
-
-  //
-  // Register notify for Form package update
-  //
-  Status = mHiiDatabase->RegisterPackageNotify (
-                           mHiiDatabase,
-                           EFI_HII_PACKAGE_FORM,
-                           NULL,
-                           FormUpdateNotify,
-                           EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
-                           &NotifyHandle
-                           );
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  do {
-    //
-    // Displays the Header and Footer borders
-    //
-    DisplayPageFrame ();
-
-    //
-    // Initialize Selection->Form
-    //
-    if (Selection->FormId == 0) {
-      //
-      // Zero FormId indicates display the first Form in a FormSet
-      //
-      Link = GetFirstNode (&Selection->FormSet->FormListHead);
-
-      Selection->Form = FORM_BROWSER_FORM_FROM_LINK (Link);
-      Selection->FormId = Selection->Form->FormId;
-    } else {
-      Selection->Form = IdToForm (Selection->FormSet, Selection->FormId);
-    }
-
-    //
-    // Load Questions' Value for display
-    //
-    Status = LoadFormConfig (Selection->FormSet, Selection->Form);
-    if (EFI_ERROR (Status)) {
-      return Status;
-    }
-
-    //
-    // Display form
-    //
-    Status = DisplayForm (Selection);
-    if (EFI_ERROR (Status)) {
-      return Status;
-    }
-
-    //
-    // Check Selected Statement (if press ESC, Selection->Statement will be NULL)
-    //
-    Statement = Selection->Statement;
-    if (Statement != NULL) {
-      if (Statement->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) {
-        gResetRequired = TRUE;
-      }
-
-      //
-      // Reset FormPackage update flag
-      //
-      mHiiPackageListUpdated = FALSE;
-
-      if (Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK && Statement->Operand != EFI_IFR_PASSWORD_OP) {
-        ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
-
-        HiiValue = &Statement->HiiValue;
-        if (HiiValue->Type == EFI_IFR_TYPE_STRING) {
-          //
-          // Create String in HII database for Configuration Driver to retrieve
-          //
-          HiiValue->Value.string = NewString ((CHAR16 *) Statement->BufferValue, Selection->FormSet->HiiHandle);
-        }
-
-        ConfigAccess = Selection->FormSet->ConfigAccess;
-        if (ConfigAccess == NULL) {
-          return EFI_UNSUPPORTED;
-        }
-        Status = ConfigAccess->Callback (
-                                 ConfigAccess,
-                                 EFI_BROWSER_ACTION_CHANGING,
-                                 Statement->QuestionId,
-                                 HiiValue->Type,
-                                 &HiiValue->Value,
-                                 &ActionRequest
-                                 );
-
-        if (HiiValue->Type == EFI_IFR_TYPE_STRING) {
-          //
-          // Clean the String in HII Database
-          //
-          DeleteString (HiiValue->Value.string, Selection->FormSet->HiiHandle);
-        }
-
-        if (!EFI_ERROR (Status)) {
-          switch (ActionRequest) {
-          case EFI_BROWSER_ACTION_REQUEST_RESET:
-            gResetRequired = TRUE;
-            break;
-
-          case EFI_BROWSER_ACTION_REQUEST_SUBMIT:
-            SubmitForm (Selection->FormSet, Selection->Form);
-            break;
-
-          case EFI_BROWSER_ACTION_REQUEST_EXIT:
-            Selection->Action = UI_ACTION_EXIT;
-            gNvUpdateRequired = FALSE;
-            break;
-
-          default:
-            break;
-          }
-        }
-      }
-
-      //
-      // Check whether Form Package has been updated during Callback
-      //
-      if (mHiiPackageListUpdated && (Selection->Action == UI_ACTION_REFRESH_FORM)) {
-        //
-        // Force to reparse IFR binary of target Formset
-        //
-        Selection->Action = UI_ACTION_REFRESH_FORMSET;
-      }
-    }
-  } while (Selection->Action == UI_ACTION_REFRESH_FORM);
-
-  //
-  // Unregister notify for Form package update
-  //
-  Status = mHiiDatabase->UnregisterPackageNotify (
-                           mHiiDatabase,
-                           NotifyHandle
-                           );
-  return Status;
-}
+/** @file\r
+Utility functions for UI presentation.\r
+\r
+Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "Setup.h"\r
+\r
+BOOLEAN            mHiiPackageListUpdated;\r
+UI_MENU_SELECTION  *gCurrentSelection;\r
+EFI_HII_HANDLE     mCurrentHiiHandle = NULL;\r
+EFI_GUID           mCurrentFormSetGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};\r
+UINT16             mCurrentFormId = 0;\r
+EFI_EVENT          mValueChangedEvent = NULL;\r
+LIST_ENTRY         mRefreshEventList = INITIALIZE_LIST_HEAD_VARIABLE (mRefreshEventList);\r
+UINT16             mCurFakeQestId;\r
+FORM_DISPLAY_ENGINE_FORM gDisplayFormData;\r
+BOOLEAN            mFinishRetrieveCall = FALSE;\r
+\r
+/**\r
+  Evaluate all expressions in a Form.\r
+\r
+  @param  FormSet        FormSet this Form belongs to.\r
+  @param  Form           The Form.\r
+\r
+  @retval EFI_SUCCESS    The expression evaluated successfuly\r
+\r
+**/\r
+EFI_STATUS\r
+EvaluateFormExpressions (\r
+  IN FORM_BROWSER_FORMSET  *FormSet,\r
+  IN FORM_BROWSER_FORM     *Form\r
+  )\r
+{\r
+  EFI_STATUS       Status;\r
+  LIST_ENTRY       *Link;\r
+  FORM_EXPRESSION  *Expression;\r
+\r
+  Link = GetFirstNode (&Form->ExpressionListHead);\r
+  while (!IsNull (&Form->ExpressionListHead, Link)) {\r
+    Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
+    Link = GetNextNode (&Form->ExpressionListHead, Link);\r
+\r
+    if (Expression->Type == EFI_HII_EXPRESSION_INCONSISTENT_IF ||\r
+        Expression->Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF ||\r
+        Expression->Type == EFI_HII_EXPRESSION_WARNING_IF ||\r
+        Expression->Type == EFI_HII_EXPRESSION_WRITE ||\r
+        (Expression->Type == EFI_HII_EXPRESSION_READ && Form->FormType != STANDARD_MAP_FORM_TYPE)) {\r
+      //\r
+      // Postpone Form validation to Question editing or Form submitting or Question Write or Question Read for nonstandard form.\r
+      //\r
+      continue;\r
+    }\r
+\r
+    Status = EvaluateExpression (FormSet, Form, Expression);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Add empty function for event process function.\r
+\r
+  @param Event    The Event need to be process\r
+  @param Context  The context of the event.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+SetupBrowserEmptyFunction (\r
+  IN  EFI_EVENT    Event,\r
+  IN  VOID         *Context\r
+  )\r
+{\r
+}\r
+\r
+/**\r
+  Base on the opcode buffer info to get the display statement.\r
+\r
+  @param OpCode    The input opcode buffer for this statement.\r
+  \r
+  @retval Statement  The statement use this opcode buffer.\r
+\r
+**/\r
+FORM_DISPLAY_ENGINE_STATEMENT *\r
+GetDisplayStatement (\r
+  IN EFI_IFR_OP_HEADER     *OpCode\r
+  )\r
+{\r
+  FORM_DISPLAY_ENGINE_STATEMENT *DisplayStatement;\r
+  LIST_ENTRY                    *Link;\r
+\r
+  Link = GetFirstNode (&gDisplayFormData.StatementListHead);\r
+  while (!IsNull (&gDisplayFormData.StatementListHead, Link)) {\r
+    DisplayStatement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link);\r
+\r
+    if (DisplayStatement->OpCode == OpCode) {\r
+      return DisplayStatement;\r
+    }\r
+    Link = GetNextNode (&gDisplayFormData.StatementListHead, Link);\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Free the refresh event list.\r
+\r
+**/\r
+VOID \r
+FreeRefreshEvent (\r
+  VOID\r
+  )\r
+{\r
+  LIST_ENTRY   *Link;\r
+  FORM_BROWSER_REFRESH_EVENT_NODE *EventNode;\r
+\r
+  while (!IsListEmpty (&mRefreshEventList)) {\r
+    Link = GetFirstNode (&mRefreshEventList);\r
+    EventNode = FORM_BROWSER_REFRESH_EVENT_FROM_LINK (Link);\r
+    RemoveEntryList (&EventNode->Link);\r
+\r
+    gBS->CloseEvent (EventNode->RefreshEvent);\r
+\r
+    FreePool (EventNode);\r
+  }\r
+}\r
+\r
+/**\r
+  Check whether this statement value is changed. If yes, update the statement value and return TRUE; \r
+  else return FALSE.\r
+\r
+  @param Statement           The statement need to check.\r
+\r
+**/\r
+VOID\r
+UpdateStatement (\r
+  IN OUT FORM_BROWSER_STATEMENT        *Statement\r
+  )\r
+{\r
+  GetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithHiiDriver);\r
+\r
+  //\r
+  // Reset FormPackage update flag\r
+  //\r
+  mHiiPackageListUpdated = FALSE;\r
+\r
+  //\r
+  // Question value may be changed, need invoke its Callback()\r
+  //\r
+  ProcessCallBackFunction (gCurrentSelection, gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, EFI_BROWSER_ACTION_RETRIEVE, FALSE);\r
+  \r
+  if (mHiiPackageListUpdated) {\r
+    //\r
+    // Package list is updated, force to reparse IFR binary of target Formset\r
+    //\r
+    mHiiPackageListUpdated = FALSE;\r
+    gCurrentSelection->Action = UI_ACTION_REFRESH_FORMSET;\r
+  }\r
+}\r
+\r
+/**\r
+  Refresh the question which has refresh guid event attribute.\r
+  \r
+  @param Event    The event which has this function related.     \r
+  @param Context  The input context info related to this event or the status code return to the caller.\r
+**/\r
+VOID\r
+EFIAPI\r
+RefreshEventNotifyForStatement(\r
+  IN      EFI_EVENT Event,\r
+  IN      VOID      *Context\r
+  )\r
+{\r
+  FORM_BROWSER_STATEMENT        *Statement;\r
+\r
+  Statement = (FORM_BROWSER_STATEMENT *)Context;\r
+  UpdateStatement(Statement);\r
+  gBS->SignalEvent (mValueChangedEvent);\r
+}\r
+\r
+/**\r
+  Refresh the questions within this form.\r
+  \r
+  @param Event    The event which has this function related.\r
+  @param Context  The input context info related to this event or the status code return to the caller.\r
+**/\r
+VOID\r
+EFIAPI\r
+RefreshEventNotifyForForm(\r
+  IN      EFI_EVENT Event,\r
+  IN      VOID      *Context\r
+  )\r
+{\r
+  gCurrentSelection->Action = UI_ACTION_REFRESH_FORMSET;\r
+\r
+  gBS->SignalEvent (mValueChangedEvent);\r
+}\r
+\r
+/**\r
+  Create refresh hook event for statement which has refresh event or interval.\r
+\r
+  @param Statement           The statement need to check.\r
+\r
+**/\r
+VOID\r
+CreateRefreshEventForStatement (\r
+  IN     FORM_BROWSER_STATEMENT        *Statement\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  EFI_EVENT                       RefreshEvent;\r
+  FORM_BROWSER_REFRESH_EVENT_NODE *EventNode;\r
+\r
+  //\r
+  // If question has refresh guid, create the notify function.\r
+  //\r
+  Status = gBS->CreateEventEx (\r
+                    EVT_NOTIFY_SIGNAL,\r
+                    TPL_CALLBACK,\r
+                    RefreshEventNotifyForStatement,\r
+                    Statement,\r
+                    &Statement->RefreshGuid,\r
+                    &RefreshEvent);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  EventNode = AllocateZeroPool (sizeof (FORM_BROWSER_REFRESH_EVENT_NODE));\r
+  ASSERT (EventNode != NULL);\r
+  EventNode->RefreshEvent = RefreshEvent;\r
+  InsertTailList(&mRefreshEventList, &EventNode->Link);\r
+}\r
+\r
+/**\r
+  Create refresh hook event for form which has refresh event or interval.\r
+\r
+  @param Form           The form need to check.\r
+\r
+**/\r
+VOID\r
+CreateRefreshEventForForm (\r
+  IN     FORM_BROWSER_FORM        *Form\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  EFI_EVENT                       RefreshEvent;\r
+  FORM_BROWSER_REFRESH_EVENT_NODE *EventNode;\r
+\r
+  //\r
+  // If question has refresh guid, create the notify function.\r
+  //\r
+  Status = gBS->CreateEventEx (\r
+                    EVT_NOTIFY_SIGNAL,\r
+                    TPL_CALLBACK,\r
+                    RefreshEventNotifyForForm,\r
+                    Form,\r
+                    &Form->RefreshGuid,\r
+                    &RefreshEvent);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  EventNode = AllocateZeroPool (sizeof (FORM_BROWSER_REFRESH_EVENT_NODE));\r
+  ASSERT (EventNode != NULL);\r
+  EventNode->RefreshEvent = RefreshEvent;\r
+  InsertTailList(&mRefreshEventList, &EventNode->Link);\r
+}\r
+\r
+/**\r
+\r
+  Initialize the Display statement structure data.\r
+\r
+  @param DisplayStatement      Pointer to the display Statement data strucure.\r
+  @param Statement             The statement need to check.\r
+**/\r
+VOID\r
+InitializeDisplayStatement (\r
+  IN OUT FORM_DISPLAY_ENGINE_STATEMENT *DisplayStatement,\r
+  IN     FORM_BROWSER_STATEMENT        *Statement\r
+  )\r
+{\r
+  LIST_ENTRY                 *Link;\r
+  QUESTION_OPTION            *Option;\r
+  DISPLAY_QUESTION_OPTION    *DisplayOption;\r
+  FORM_DISPLAY_ENGINE_STATEMENT *ParentStatement;\r
+\r
+  DisplayStatement->Signature = FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE;\r
+  DisplayStatement->Version   = FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1;\r
+  DisplayStatement->OpCode    = Statement->OpCode;\r
+  InitializeListHead (&DisplayStatement->NestStatementList);\r
+  InitializeListHead (&DisplayStatement->OptionListHead);\r
+\r
+  if ((EvaluateExpressionList(Statement->Expression, FALSE, NULL, NULL) == ExpressGrayOut) || Statement->Locked) {\r
+    DisplayStatement->Attribute |= HII_DISPLAY_GRAYOUT;\r
+  }\r
+  if ((Statement->ValueExpression != NULL) || ((Statement->QuestionFlags & EFI_IFR_FLAG_READ_ONLY) != 0)) {\r
+    DisplayStatement->Attribute |= HII_DISPLAY_READONLY;\r
+  }\r
+\r
+  //\r
+  // Initilize the option list in statement.\r
+  //\r
+  Link = GetFirstNode (&Statement->OptionListHead);\r
+  while (!IsNull (&Statement->OptionListHead, Link)) {\r
+    Option = QUESTION_OPTION_FROM_LINK (Link);\r
+    Link = GetNextNode (&Statement->OptionListHead, Link);\r
+    if ((Option->SuppressExpression != NULL) &&\r
+        ((EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) == ExpressSuppress))) {\r
+      continue;\r
+    }\r
+\r
+    DisplayOption = AllocateZeroPool (sizeof (DISPLAY_QUESTION_OPTION));\r
+    ASSERT (DisplayOption != NULL);\r
+\r
+    DisplayOption->ImageId      = Option->ImageId;\r
+    DisplayOption->Signature    = DISPLAY_QUESTION_OPTION_SIGNATURE;\r
+    DisplayOption->OptionOpCode = Option->OpCode;\r
+    InsertTailList(&DisplayStatement->OptionListHead, &DisplayOption->Link);\r
+  }\r
+\r
+  CopyMem (&DisplayStatement->CurrentValue, &Statement->HiiValue, sizeof (EFI_HII_VALUE));\r
+\r
+  //\r
+  // Some special op code need an extra buffer to save the data.\r
+  // Such as string, password, orderedlist...\r
+  //\r
+  if (Statement->BufferValue != NULL) {\r
+    //\r
+    // Ordered list opcode may not initilized, get default value here.\r
+    //\r
+    if (Statement->OpCode->OpCode == EFI_IFR_ORDERED_LIST_OP && GetArrayData (Statement->BufferValue, Statement->ValueType, 0) == 0) {\r
+      GetQuestionDefault (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, 0);\r
+    }\r
+\r
+    DisplayStatement->CurrentValue.Buffer    = AllocateCopyPool(Statement->StorageWidth,Statement->BufferValue);\r
+    DisplayStatement->CurrentValue.BufferLen = Statement->StorageWidth;\r
+  }\r
+\r
+  DisplayStatement->SettingChangedFlag = Statement->ValueChanged;\r
+\r
+  //\r
+  // Get the highlight statement for current form.\r
+  //\r
+  if (((gCurrentSelection->QuestionId != 0) && (Statement->QuestionId == gCurrentSelection->QuestionId)) ||\r
+      ((mCurFakeQestId != 0) && (Statement->FakeQuestionId == mCurFakeQestId))) {\r
+    gDisplayFormData.HighLightedStatement = DisplayStatement;\r
+  }\r
+\r
+  //\r
+  // Create the refresh event process function.\r
+  //\r
+  if (!CompareGuid (&Statement->RefreshGuid, &gZeroGuid)) {\r
+    CreateRefreshEventForStatement (Statement);\r
+  }\r
+\r
+  //\r
+  // For RTC type of date/time, set default refresh interval to be 1 second.\r
+  //\r
+  if ((Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) && Statement->Storage == NULL) {\r
+    Statement->RefreshInterval = 1;\r
+  }\r
+\r
+  //\r
+  // Create the refresh guid hook event.\r
+  // If the statement in this form has refresh event or refresh interval, browser will create this event for display engine.\r
+  //\r
+  if ((!CompareGuid (&Statement->RefreshGuid, &gZeroGuid)) || (Statement->RefreshInterval != 0)) {\r
+    gDisplayFormData.FormRefreshEvent = mValueChangedEvent;\r
+  }\r
+\r
+  //\r
+  // Save the password check function for later use.\r
+  //\r
+  if (Statement->Operand == EFI_IFR_PASSWORD_OP) {\r
+    DisplayStatement->PasswordCheck = PasswordCheck;\r
+  }\r
+\r
+  //\r
+  // If this statement is nest in the subtitle, insert to the host statement.\r
+  // else insert to the form it belongs to.\r
+  //\r
+  if (Statement->ParentStatement != NULL) {\r
+    ParentStatement = GetDisplayStatement(Statement->ParentStatement->OpCode);\r
+    ASSERT (ParentStatement != NULL);\r
+    InsertTailList(&ParentStatement->NestStatementList, &DisplayStatement->DisplayLink);\r
+  } else {\r
+    InsertTailList(&gDisplayFormData.StatementListHead, &DisplayStatement->DisplayLink);\r
+  }\r
+}\r
+\r
+/**\r
+  Process for the refresh interval statement.\r
+\r
+  @param Event    The Event need to be process\r
+  @param Context  The context of the event.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+RefreshIntervalProcess (\r
+  IN  EFI_EVENT    Event,\r
+  IN  VOID         *Context\r
+  )\r
+{\r
+  FORM_BROWSER_STATEMENT        *Statement;\r
+  LIST_ENTRY                    *Link;\r
+\r
+  Link = GetFirstNode (&gCurrentSelection->Form->StatementListHead);\r
+  while (!IsNull (&gCurrentSelection->Form->StatementListHead, Link)) {\r
+    Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+    Link = GetNextNode (&gCurrentSelection->Form->StatementListHead, Link);\r
+\r
+    if (Statement->RefreshInterval == 0) {\r
+      continue;\r
+    }\r
+\r
+    UpdateStatement(Statement);\r
+  }\r
+\r
+  gBS->SignalEvent (mValueChangedEvent);\r
+}\r
+\r
+/**\r
+\r
+  Make a copy of the global hotkey info.\r
+\r
+**/\r
+VOID\r
+UpdateHotkeyList (\r
+  VOID\r
+  )\r
+{\r
+  BROWSER_HOT_KEY  *HotKey;\r
+  BROWSER_HOT_KEY  *CopyKey;\r
+  LIST_ENTRY       *Link;\r
+\r
+  Link = GetFirstNode (&gBrowserHotKeyList);\r
+  while (!IsNull (&gBrowserHotKeyList, Link)) {\r
+    HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);\r
+\r
+    CopyKey             = AllocateCopyPool(sizeof (BROWSER_HOT_KEY), HotKey);\r
+    ASSERT (CopyKey != NULL);\r
+    CopyKey->KeyData    = AllocateCopyPool(sizeof (EFI_INPUT_KEY), HotKey->KeyData);\r
+    ASSERT (CopyKey->KeyData != NULL);\r
+    CopyKey->HelpString = AllocateCopyPool(StrSize (HotKey->HelpString), HotKey->HelpString);\r
+    ASSERT (CopyKey->HelpString != NULL);\r
+\r
+    InsertTailList(&gDisplayFormData.HotKeyListHead, &CopyKey->Link);\r
+\r
+    Link = GetNextNode (&gBrowserHotKeyList, Link);\r
+  }\r
+}\r
+\r
+/**\r
+\r
+  Get the extra question attribute from override question list.\r
+\r
+  @param    QuestionId    The question id for this request question.\r
+\r
+  @retval   The attribute for this question or NULL if not found this \r
+            question in the list.\r
+\r
+**/\r
+UINT32 \r
+ProcessQuestionExtraAttr (\r
+  IN   EFI_QUESTION_ID  QuestionId\r
+  )\r
+{\r
+  LIST_ENTRY                   *Link;\r
+  QUESTION_ATTRIBUTE_OVERRIDE  *QuestionDesc;\r
+\r
+  //\r
+  // Return HII_DISPLAY_NONE if input a invalid question id.\r
+  //\r
+  if (QuestionId == 0) {\r
+    return HII_DISPLAY_NONE;\r
+  }\r
+\r
+  Link = GetFirstNode (&mPrivateData.FormBrowserEx2.OverrideQestListHead);\r
+  while (!IsNull (&mPrivateData.FormBrowserEx2.OverrideQestListHead, Link)) {\r
+    QuestionDesc = FORM_QUESTION_ATTRIBUTE_OVERRIDE_FROM_LINK (Link);\r
+    Link = GetNextNode (&mPrivateData.FormBrowserEx2.OverrideQestListHead, Link);\r
+\r
+    if ((QuestionDesc->QuestionId == QuestionId) &&\r
+        (QuestionDesc->FormId     == gCurrentSelection->FormId) &&\r
+        (QuestionDesc->HiiHandle  == gCurrentSelection->Handle) &&\r
+        CompareGuid (&QuestionDesc->FormSetGuid, &gCurrentSelection->FormSetGuid)) {\r
+      return QuestionDesc->Attribute;\r
+    }\r
+  }\r
+\r
+  return HII_DISPLAY_NONE;\r
+}\r
+\r
+/**\r
+\r
+  Enum all statement in current form, find all the statement can be display and\r
+  add to the display form.\r
+\r
+**/\r
+VOID\r
+AddStatementToDisplayForm (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  LIST_ENTRY                    *Link;\r
+  FORM_BROWSER_STATEMENT        *Statement;\r
+  FORM_DISPLAY_ENGINE_STATEMENT *DisplayStatement;\r
+  UINT8                         MinRefreshInterval;\r
+  EFI_EVENT                     RefreshIntervalEvent;\r
+  FORM_BROWSER_REFRESH_EVENT_NODE *EventNode;\r
+  BOOLEAN                       FormEditable;\r
+  UINT32                        ExtraAttribute;\r
+\r
+  MinRefreshInterval   = 0;\r
+  FormEditable         = FALSE;\r
+\r
+  //\r
+  // Process the statement outside the form, these statements are not recognized\r
+  // by browser core.\r
+  //\r
+  Link = GetFirstNode (&gCurrentSelection->FormSet->StatementListOSF);\r
+  while (!IsNull (&gCurrentSelection->FormSet->StatementListOSF, Link)) {\r
+    Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+    Link = GetNextNode (&gCurrentSelection->FormSet->StatementListOSF, Link);\r
+\r
+    DisplayStatement = AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT));\r
+    ASSERT (DisplayStatement != NULL);\r
+    DisplayStatement->Signature = FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE;\r
+    DisplayStatement->Version   = FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1;\r
+    DisplayStatement->OpCode = Statement->OpCode;\r
+\r
+    InitializeListHead (&DisplayStatement->NestStatementList);\r
+    InitializeListHead (&DisplayStatement->OptionListHead);\r
+\r
+    InsertTailList(&gDisplayFormData.StatementListOSF, &DisplayStatement->DisplayLink);\r
+  }\r
+\r
+  //\r
+  // Process the statement in this form.\r
+  //\r
+  Link = GetFirstNode (&gCurrentSelection->Form->StatementListHead);\r
+  while (!IsNull (&gCurrentSelection->Form->StatementListHead, Link)) {\r
+    Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+    Link = GetNextNode (&gCurrentSelection->Form->StatementListHead, Link);\r
+\r
+    //\r
+    // This statement can't be show, skip it.\r
+    //\r
+    if (EvaluateExpressionList(Statement->Expression, FALSE, NULL, NULL) > ExpressGrayOut) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Check the extra attribute.\r
+    //\r
+    ExtraAttribute = ProcessQuestionExtraAttr (Statement->QuestionId);\r
+    if ((ExtraAttribute & HII_DISPLAY_SUPPRESS) != 0) {\r
+      continue;\r
+    }\r
+\r
+    DisplayStatement = AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT));\r
+    ASSERT (DisplayStatement != NULL);\r
+\r
+    //\r
+    // Initialize this statement and add it to the display form.\r
+    //\r
+    InitializeDisplayStatement(DisplayStatement, Statement);\r
+\r
+    //\r
+    // Set the extra attribute.\r
+    //\r
+    DisplayStatement->Attribute |= ExtraAttribute;\r
+\r
+    if (Statement->Storage != NULL) {\r
+      FormEditable = TRUE;\r
+    }\r
+\r
+    //\r
+    // Get the minimal refresh interval value for later use.\r
+    //\r
+    if ((Statement->RefreshInterval != 0) && \r
+      (MinRefreshInterval == 0 || Statement->RefreshInterval < MinRefreshInterval)) {\r
+      MinRefreshInterval = Statement->RefreshInterval;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Create the periodic timer for refresh interval statement.\r
+  //\r
+  if (MinRefreshInterval != 0) {\r
+    Status = gBS->CreateEvent (EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK, RefreshIntervalProcess, NULL, &RefreshIntervalEvent);\r
+    ASSERT_EFI_ERROR (Status);\r
+    Status = gBS->SetTimer (RefreshIntervalEvent, TimerPeriodic, MinRefreshInterval * ONE_SECOND);\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    EventNode = AllocateZeroPool (sizeof (FORM_BROWSER_REFRESH_EVENT_NODE));\r
+    ASSERT (EventNode != NULL);\r
+    EventNode->RefreshEvent = RefreshIntervalEvent;\r
+    InsertTailList(&mRefreshEventList, &EventNode->Link);\r
+  }\r
+\r
+  //\r
+  // Create the refresh event process function for Form.\r
+  //\r
+  if (!CompareGuid (&gCurrentSelection->Form->RefreshGuid, &gZeroGuid)) {\r
+    CreateRefreshEventForForm (gCurrentSelection->Form);\r
+    if (gDisplayFormData.FormRefreshEvent == NULL) {\r
+      gDisplayFormData.FormRefreshEvent = mValueChangedEvent;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Update hotkey list field.\r
+  //\r
+  if (gBrowserSettingScope == SystemLevel || FormEditable) {\r
+    UpdateHotkeyList();\r
+  }\r
+}\r
+\r
+/**\r
+\r
+  Initialize the SettingChangedFlag variable in the display form.\r
+\r
+**/\r
+VOID\r
+UpdateDataChangedFlag (\r
+  VOID\r
+  )\r
+{\r
+  LIST_ENTRY           *Link;\r
+  FORM_BROWSER_FORMSET *LocalFormSet;\r
+\r
+  gDisplayFormData.SettingChangedFlag   = FALSE;\r
+\r
+  if (IsNvUpdateRequiredForForm (gCurrentSelection->Form)) {\r
+    gDisplayFormData.SettingChangedFlag = TRUE;\r
+    return;\r
+  }\r
+\r
+  //\r
+  // Base on the system level to check whether need to show the NV flag.\r
+  // \r
+  switch (gBrowserSettingScope) {\r
+  case SystemLevel:\r
+    //\r
+    // Check the maintain list to see whether there is any change.\r
+    //\r
+    Link = GetFirstNode (&gBrowserFormSetList);\r
+    while (!IsNull (&gBrowserFormSetList, Link)) {\r
+      LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
+      if (IsNvUpdateRequiredForFormSet(LocalFormSet)) {\r
+        gDisplayFormData.SettingChangedFlag = TRUE;\r
+        return;\r
+      }\r
+      Link = GetNextNode (&gBrowserFormSetList, Link);\r
+    }\r
+    break;\r
+\r
+  case FormSetLevel:\r
+    if (IsNvUpdateRequiredForFormSet(gCurrentSelection->FormSet)) {\r
+      gDisplayFormData.SettingChangedFlag = TRUE;\r
+      return;\r
+    }\r
+    break;\r
+\r
+  default:\r
+    break;\r
+  }\r
+}\r
+\r
+/**\r
+\r
+  Initialize the Display form structure data.\r
+\r
+**/\r
+VOID\r
+InitializeDisplayFormData (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  gDisplayFormData.Signature   = FORM_DISPLAY_ENGINE_FORM_SIGNATURE;\r
+  gDisplayFormData.Version     = FORM_DISPLAY_ENGINE_VERSION_1;\r
+  gDisplayFormData.ImageId     = 0;\r
+  gDisplayFormData.AnimationId = 0;\r
+\r
+  InitializeListHead (&gDisplayFormData.StatementListHead);\r
+  InitializeListHead (&gDisplayFormData.StatementListOSF);\r
+  InitializeListHead (&gDisplayFormData.HotKeyListHead);\r
+\r
+  Status = gBS->CreateEvent (\r
+        EVT_NOTIFY_WAIT, \r
+        TPL_CALLBACK,\r
+        SetupBrowserEmptyFunction,\r
+        NULL,\r
+        &mValueChangedEvent\r
+        );\r
+  ASSERT_EFI_ERROR (Status); \r
+}\r
+\r
+/**\r
+\r
+  Free the kotkey info saved in form data.\r
+\r
+**/\r
+VOID\r
+FreeHotkeyList (\r
+  VOID\r
+  )\r
+{\r
+  BROWSER_HOT_KEY  *HotKey;\r
+  LIST_ENTRY       *Link;\r
+\r
+  while (!IsListEmpty (&gDisplayFormData.HotKeyListHead)) {\r
+    Link = GetFirstNode (&gDisplayFormData.HotKeyListHead);\r
+    HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);\r
+\r
+    RemoveEntryList (&HotKey->Link);\r
+\r
+    FreePool (HotKey->KeyData);\r
+    FreePool (HotKey->HelpString);\r
+    FreePool (HotKey);\r
+  }\r
+}\r
+\r
+/**\r
+\r
+  Update the Display form structure data.\r
+\r
+**/\r
+VOID\r
+UpdateDisplayFormData (\r
+  VOID\r
+  )\r
+{\r
+  gDisplayFormData.FormTitle        = gCurrentSelection->Form->FormTitle;\r
+  gDisplayFormData.FormId           = gCurrentSelection->FormId;\r
+  gDisplayFormData.HiiHandle        = gCurrentSelection->Handle;\r
+  CopyGuid (&gDisplayFormData.FormSetGuid, &gCurrentSelection->FormSetGuid);\r
+\r
+  gDisplayFormData.Attribute        = 0;\r
+  gDisplayFormData.Attribute       |= gCurrentSelection->Form->ModalForm ? HII_DISPLAY_MODAL : 0;\r
+  gDisplayFormData.Attribute       |= gCurrentSelection->Form->Locked    ? HII_DISPLAY_LOCK  : 0;\r
+\r
+  gDisplayFormData.FormRefreshEvent     = NULL;\r
+  gDisplayFormData.HighLightedStatement = NULL;\r
+\r
+  UpdateDataChangedFlag ();\r
+\r
+  AddStatementToDisplayForm ();\r
+}\r
+\r
+/**\r
+\r
+  Free the Display Statement structure data.\r
+\r
+  @param   StatementList         Point to the statement list which need to be free.\r
+\r
+**/\r
+VOID\r
+FreeStatementData (\r
+  LIST_ENTRY           *StatementList\r
+  )\r
+{\r
+  LIST_ENTRY                    *Link;\r
+  LIST_ENTRY                    *OptionLink;\r
+  FORM_DISPLAY_ENGINE_STATEMENT *Statement;\r
+  DISPLAY_QUESTION_OPTION       *Option;\r
+\r
+  //\r
+  // Free Statements/Questions\r
+  //\r
+  while (!IsListEmpty (StatementList)) {\r
+    Link = GetFirstNode (StatementList);\r
+    Statement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link);\r
+\r
+    //\r
+    // Free Options List\r
+    //\r
+    while (!IsListEmpty (&Statement->OptionListHead)) {\r
+      OptionLink = GetFirstNode (&Statement->OptionListHead);\r
+      Option = DISPLAY_QUESTION_OPTION_FROM_LINK (OptionLink);\r
+      RemoveEntryList (&Option->Link);\r
+      FreePool (Option);\r
+    }\r
+\r
+    //\r
+    // Free nest statement List\r
+    //\r
+    if (!IsListEmpty (&Statement->NestStatementList)) {\r
+      FreeStatementData(&Statement->NestStatementList);\r
+    }\r
+\r
+    RemoveEntryList (&Statement->DisplayLink);\r
+    FreePool (Statement);\r
+  }\r
+}\r
+\r
+/**\r
+\r
+  Free the Display form structure data.\r
+\r
+**/\r
+VOID\r
+FreeDisplayFormData (\r
+  VOID\r
+  )\r
+{\r
+  FreeStatementData (&gDisplayFormData.StatementListHead);\r
+  FreeStatementData (&gDisplayFormData.StatementListOSF);\r
+\r
+  FreeRefreshEvent();\r
+\r
+  FreeHotkeyList();\r
+}\r
+\r
+/**\r
+\r
+  Get FORM_BROWSER_STATEMENT from FORM_DISPLAY_ENGINE_STATEMENT based on the OpCode info.\r
+\r
+  @param DisplayStatement        The input FORM_DISPLAY_ENGINE_STATEMENT.\r
+\r
+  @retval FORM_BROWSER_STATEMENT  The return FORM_BROWSER_STATEMENT info.\r
+\r
+**/\r
+FORM_BROWSER_STATEMENT *\r
+GetBrowserStatement (\r
+  IN FORM_DISPLAY_ENGINE_STATEMENT *DisplayStatement\r
+  )\r
+{\r
+  FORM_BROWSER_STATEMENT *Statement;\r
+  LIST_ENTRY             *Link;\r
+\r
+  Link = GetFirstNode (&gCurrentSelection->Form->StatementListHead);\r
+  while (!IsNull (&gCurrentSelection->Form->StatementListHead, Link)) {\r
+    Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+\r
+    if (Statement->OpCode == DisplayStatement->OpCode) {\r
+      return Statement;\r
+    }\r
+\r
+    Link = GetNextNode (&gCurrentSelection->Form->StatementListHead, Link);\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Update the ValueChanged status for questions in this form.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   Form data structure.\r
+\r
+**/\r
+VOID \r
+UpdateStatementStatusForForm (\r
+  IN FORM_BROWSER_FORMSET             *FormSet,\r
+  IN FORM_BROWSER_FORM                *Form\r
+  )\r
+{\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
+    // For password opcode, not set the the value changed flag.\r
+    //\r
+    if (Question->Operand == EFI_IFR_PASSWORD_OP) {\r
+      continue;\r
+    }\r
+\r
+    IsQuestionValueChanged(FormSet, Form, Question, GetSetValueWithBuffer);\r
+  }\r
+}\r
+\r
+/**\r
+  Update the ValueChanged status for questions in this formset.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+\r
+**/\r
+VOID \r
+UpdateStatementStatusForFormSet (\r
+  IN FORM_BROWSER_FORMSET                *FormSet\r
+  )\r
+{\r
+  LIST_ENTRY                  *Link;\r
+  FORM_BROWSER_FORM           *Form;\r
+\r
+  Link = GetFirstNode (&FormSet->FormListHead);\r
+  while (!IsNull (&FormSet->FormListHead, Link)) {\r
+    Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+    Link = GetNextNode (&FormSet->FormListHead, Link);\r
+\r
+    UpdateStatementStatusForForm (FormSet, Form);\r
+  }\r
+}\r
+\r
+/**\r
+  Update the ValueChanged status for questions.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   Form data structure.\r
+  @param  SettingScope           Setting Scope for Default action.\r
+\r
+**/\r
+VOID \r
+UpdateStatementStatus (\r
+  IN FORM_BROWSER_FORMSET             *FormSet,\r
+  IN FORM_BROWSER_FORM                *Form, \r
+  IN BROWSER_SETTING_SCOPE            SettingScope\r
+  )\r
+{\r
+  LIST_ENTRY                  *Link;\r
+  FORM_BROWSER_FORMSET        *LocalFormSet;\r
+\r
+  switch (SettingScope) {\r
+  case SystemLevel:\r
+    Link = GetFirstNode (&gBrowserFormSetList);\r
+    while (!IsNull (&gBrowserFormSetList, Link)) {\r
+      LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
+      Link = GetNextNode (&gBrowserFormSetList, Link);\r
+      if (!ValidateFormSet(LocalFormSet)) {\r
+        continue;\r
+      }\r
+\r
+      UpdateStatementStatusForFormSet (LocalFormSet);\r
+    }\r
+    break;\r
+\r
+  case FormSetLevel:\r
+    UpdateStatementStatusForFormSet (FormSet);\r
+    break;\r
+\r
+  case FormLevel:\r
+    UpdateStatementStatusForForm (FormSet, Form);\r
+    break;\r
+\r
+  default:\r
+    break;\r
+  }\r
+}\r
+\r
+/**\r
+\r
+  Process the action request in user input.\r
+\r
+  @param Action                  The user input action request info.\r
+  @param DefaultId               The user input default Id info.\r
+\r
+  @retval EFI_SUCESSS            This function always return successfully for now.\r
+\r
+**/\r
+EFI_STATUS \r
+ProcessAction (\r
+  IN UINT32        Action,\r
+  IN UINT16        DefaultId\r
+  )\r
+{\r
+  //\r
+  // This is caused by use press ESC, and it should not combine with other action type.\r
+  //\r
+  if ((Action & BROWSER_ACTION_FORM_EXIT) == BROWSER_ACTION_FORM_EXIT) {\r
+    FindNextMenu (gCurrentSelection, FormLevel);\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Below is normal hotkey trigged action, these action maybe combine with each other.\r
+  //\r
+  if ((Action & BROWSER_ACTION_DISCARD) == BROWSER_ACTION_DISCARD) {\r
+    DiscardForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);\r
+  }\r
+\r
+  if ((Action & BROWSER_ACTION_DEFAULT) == BROWSER_ACTION_DEFAULT) {\r
+    ExtractDefault (gCurrentSelection->FormSet, gCurrentSelection->Form, DefaultId, gBrowserSettingScope, GetDefaultForAll, NULL, FALSE, FALSE);\r
+    UpdateStatementStatus (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);\r
+  }\r
+\r
+  if ((Action & BROWSER_ACTION_SUBMIT) == BROWSER_ACTION_SUBMIT) {\r
+    SubmitForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);\r
+  }\r
+\r
+  if ((Action & BROWSER_ACTION_RESET) == BROWSER_ACTION_RESET) {\r
+    gResetRequired = TRUE;\r
+  }\r
+\r
+  if ((Action & BROWSER_ACTION_EXIT) == BROWSER_ACTION_EXIT) {\r
+    //\r
+    // Form Exit without saving, Similar to ESC Key.\r
+    // FormSet Exit without saving, Exit SendForm.\r
+    // System Exit without saving, CallExitHandler and Exit SendForm.\r
+    //\r
+    DiscardForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);\r
+    if (gBrowserSettingScope == FormLevel || gBrowserSettingScope == FormSetLevel) {\r
+      FindNextMenu (gCurrentSelection, gBrowserSettingScope);\r
+    } else if (gBrowserSettingScope == SystemLevel) {\r
+      if (ExitHandlerFunction != NULL) {\r
+        ExitHandlerFunction ();\r
+      }\r
+      gCurrentSelection->Action = UI_ACTION_EXIT;\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Check whether the formset guid is in this Hii package list.\r
+\r
+  @param  HiiHandle              The HiiHandle for this HII package list.\r
+  @param  FormSetGuid            The formset guid for the request formset.\r
+\r
+  @retval TRUE                   Find the formset guid.\r
+  @retval FALSE                  Not found the formset guid.\r
+\r
+**/\r
+BOOLEAN\r
+GetFormsetGuidFromHiiHandle (\r
+  IN EFI_HII_HANDLE       HiiHandle,\r
+  IN EFI_GUID             *FormSetGuid\r
+  )\r
+{\r
+  EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;\r
+  UINTN                        BufferSize;\r
+  UINT32                       Offset;\r
+  UINT32                       Offset2;\r
+  UINT32                       PackageListLength;\r
+  EFI_HII_PACKAGE_HEADER       PackageHeader;\r
+  UINT8                        *Package;\r
+  UINT8                        *OpCodeData;\r
+  EFI_STATUS                   Status;\r
+  BOOLEAN                      FindGuid;\r
+\r
+  BufferSize     = 0;\r
+  HiiPackageList = NULL;\r
+  FindGuid       = FALSE;\r
+  \r
+  Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    HiiPackageList = AllocatePool (BufferSize);\r
+    ASSERT (HiiPackageList != NULL);\r
+\r
+    Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
+  }\r
+  if (EFI_ERROR (Status) || HiiPackageList == NULL) {\r
+    return FALSE;\r
+  }\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
+    Offset += PackageHeader.Length;\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
+          if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))){\r
+            FindGuid = TRUE;\r
+            break;\r
+          }\r
+        }\r
+\r
+        Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
+      }\r
+    }\r
+    if (FindGuid) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  FreePool (HiiPackageList);\r
+\r
+  return FindGuid;\r
+}\r
+\r
+/**\r
+  Find HII Handle in the HII database associated with given Device Path.\r
+\r
+  If DevicePath is NULL, then ASSERT.\r
+\r
+  @param  DevicePath             Device Path associated with the HII package list\r
+                                 handle.\r
+  @param  FormsetGuid            The formset guid for this formset.\r
+\r
+  @retval Handle                 HII package list Handle associated with the Device\r
+                                        Path.\r
+  @retval NULL                   Hii Package list handle is not found.\r
+\r
+**/\r
+EFI_HII_HANDLE\r
+DevicePathToHiiHandle (\r
+  IN EFI_DEVICE_PATH_PROTOCOL   *DevicePath,\r
+  IN EFI_GUID                   *FormsetGuid\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  EFI_DEVICE_PATH_PROTOCOL    *TmpDevicePath;\r
+  UINTN                       Index;\r
+  EFI_HANDLE                  Handle;\r
+  EFI_HANDLE                  DriverHandle;\r
+  EFI_HII_HANDLE              *HiiHandles;\r
+  EFI_HII_HANDLE              HiiHandle;\r
+\r
+  ASSERT (DevicePath != NULL);\r
+\r
+  TmpDevicePath = DevicePath;\r
+  //\r
+  // Locate Device Path Protocol handle buffer\r
+  //\r
+  Status = gBS->LocateDevicePath (\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  &TmpDevicePath,\r
+                  &DriverHandle\r
+                  );\r
+  if (EFI_ERROR (Status) || !IsDevicePathEnd (TmpDevicePath)) {\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Retrieve all HII Handles from HII database\r
+  //\r
+  HiiHandles = HiiGetHiiHandles (NULL);\r
+  if (HiiHandles == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Search Hii Handle by Driver Handle\r
+  //\r
+  HiiHandle = NULL;\r
+  for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
+    Status = mHiiDatabase->GetPackageListHandle (\r
+                             mHiiDatabase,\r
+                             HiiHandles[Index],\r
+                             &Handle\r
+                             );\r
+    if (!EFI_ERROR (Status) && (Handle == DriverHandle)) {\r
+      if (GetFormsetGuidFromHiiHandle(HiiHandles[Index], FormsetGuid)) {\r
+        HiiHandle = HiiHandles[Index];\r
+        break;\r
+      }\r
+\r
+      if (HiiHandle != NULL) {\r
+        break;\r
+      }\r
+    }\r
+  }\r
+\r
+  FreePool (HiiHandles);\r
+  return HiiHandle;\r
+}\r
+\r
+/**\r
+  Find HII Handle in the HII database associated with given form set guid.\r
+\r
+  If FormSetGuid is NULL, then ASSERT.\r
+\r
+  @param  ComparingGuid          FormSet Guid associated with the HII package list\r
+                                 handle.\r
+\r
+  @retval Handle                 HII package list Handle associated with the Device\r
+                                        Path.\r
+  @retval NULL                   Hii Package list handle is not found.\r
+\r
+**/\r
+EFI_HII_HANDLE\r
+FormSetGuidToHiiHandle (\r
+  EFI_GUID     *ComparingGuid\r
+  )\r
+{\r
+  EFI_HII_HANDLE               *HiiHandles;\r
+  EFI_HII_HANDLE               HiiHandle;\r
+  UINTN                        Index;\r
+\r
+  ASSERT (ComparingGuid != NULL);\r
+\r
+  HiiHandle  = NULL;\r
+  //\r
+  // Get all the Hii handles\r
+  //\r
+  HiiHandles = HiiGetHiiHandles (NULL);\r
+  ASSERT (HiiHandles != NULL);\r
+\r
+  //\r
+  // Search for formset of each class type\r
+  //\r
+  for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
+    if (GetFormsetGuidFromHiiHandle(HiiHandles[Index], ComparingGuid)) {\r
+      HiiHandle = HiiHandles[Index];\r
+      break;\r
+    }\r
+\r
+    if (HiiHandle != NULL) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  FreePool (HiiHandles);\r
+\r
+  return HiiHandle;\r
+}\r
+\r
+/**\r
+  check how to process the changed data in current form or form set.\r
+\r
+  @param Selection       On input, Selection tell setup browser the information\r
+                         about the Selection, form and formset to be displayed.\r
+                         On output, Selection return the screen item that is selected\r
+                         by user.\r
+\r
+  @param Scope           Data save or discard scope, form or formset.\r
+\r
+  @retval                TRUE   Success process the changed data, will return to the parent form.\r
+  @retval                FALSE  Reject to process the changed data, will stay at  current form.\r
+**/\r
+BOOLEAN\r
+ProcessChangedData (\r
+  IN OUT UI_MENU_SELECTION       *Selection,\r
+  IN     BROWSER_SETTING_SCOPE   Scope\r
+  )\r
+{\r
+  BOOLEAN    RetValue;\r
+  EFI_STATUS Status;\r
+\r
+  RetValue = TRUE;\r
+  switch (mFormDisplay->ConfirmDataChange()) {\r
+    case BROWSER_ACTION_DISCARD:\r
+      DiscardForm (Selection->FormSet, Selection->Form, Scope);\r
+      break;\r
+  \r
+    case BROWSER_ACTION_SUBMIT:\r
+      Status = SubmitForm (Selection->FormSet, Selection->Form, Scope);\r
+      if (EFI_ERROR (Status)) {\r
+        RetValue = FALSE;\r
+      }\r
+      break;\r
+\r
+    case BROWSER_ACTION_NONE:\r
+      RetValue = FALSE;\r
+      break;\r
+\r
+    default:\r
+      //\r
+      // if Invalid value return, process same as BROWSER_ACTION_NONE.\r
+      //\r
+      RetValue = FALSE;\r
+      break;\r
+  }\r
+\r
+  return RetValue;\r
+}\r
+\r
+/**\r
+  Find parent formset menu(the first menu which has different formset) for current menu.\r
+  If not find, just return to the first menu.\r
+\r
+  @param Selection    The selection info.\r
+\r
+**/\r
+VOID\r
+FindParentFormSet (\r
+  IN OUT   UI_MENU_SELECTION           *Selection\r
+  )\r
+{\r
+  FORM_ENTRY_INFO            *CurrentMenu;\r
+  FORM_ENTRY_INFO            *ParentMenu;\r
+\r
+  CurrentMenu = Selection->CurrentMenu;\r
+  ParentMenu  = UiFindParentMenu(CurrentMenu, FormSetLevel);\r
+\r
+  if (ParentMenu != NULL) {\r
+    CopyMem (&Selection->FormSetGuid, &ParentMenu->FormSetGuid, sizeof (EFI_GUID));\r
+    Selection->Handle = ParentMenu->HiiHandle;\r
+    Selection->FormId     = ParentMenu->FormId;\r
+    Selection->QuestionId = ParentMenu->QuestionId;\r
+  } else {\r
+    Selection->FormId     = CurrentMenu->FormId;\r
+    Selection->QuestionId = CurrentMenu->QuestionId;\r
+  }\r
+\r
+  Selection->Statement  = NULL;\r
+}\r
+\r
+/**\r
+  Process the goto op code, update the info in the selection structure.\r
+\r
+  @param Statement    The statement belong to goto op code.\r
+  @param Selection    The selection info.\r
+\r
+  @retval EFI_SUCCESS    The menu process successfully.\r
+  @return Other value if the process failed.\r
+**/\r
+EFI_STATUS\r
+ProcessGotoOpCode (\r
+  IN OUT   FORM_BROWSER_STATEMENT      *Statement,\r
+  IN OUT   UI_MENU_SELECTION           *Selection\r
+  )\r
+{\r
+  CHAR16                          *StringPtr;\r
+  EFI_DEVICE_PATH_PROTOCOL        *DevicePath;\r
+  FORM_BROWSER_FORM               *RefForm;\r
+  EFI_STATUS                      Status;\r
+  EFI_HII_HANDLE                  HiiHandle;\r
+  \r
+  Status    = EFI_SUCCESS;\r
+  StringPtr = NULL;\r
+  HiiHandle = NULL;\r
+\r
+  //\r
+  // Prepare the device path check, get the device path info first.\r
+  //\r
+  if (Statement->HiiValue.Value.ref.DevicePath != 0) {\r
+    StringPtr = GetToken (Statement->HiiValue.Value.ref.DevicePath, Selection->FormSet->HiiHandle);\r
+  }\r
+\r
+  //\r
+  // Check whether the device path string is a valid string.\r
+  //\r
+  if (Statement->HiiValue.Value.ref.DevicePath != 0 && StringPtr != NULL && StringPtr[0] != L'\0') {\r
+    if (Selection->Form->ModalForm) {\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Goto another Hii Package list\r
+    //\r
+    if (mPathFromText != NULL) {\r
+      DevicePath = mPathFromText->ConvertTextToDevicePath(StringPtr);\r
+      if (DevicePath != NULL) {\r
+        HiiHandle = DevicePathToHiiHandle (DevicePath, &Statement->HiiValue.Value.ref.FormSetGuid);\r
+        FreePool (DevicePath);\r
+      }\r
+      FreePool (StringPtr);\r
+    } else {\r
+      //\r
+      // Not found the EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL protocol.\r
+      //\r
+      PopupErrorMessage(BROWSER_PROTOCOL_NOT_FOUND, NULL, NULL, NULL);\r
+      FreePool (StringPtr);\r
+      return Status;\r
+    }\r
+\r
+    if (HiiHandle != Selection->Handle) {\r
+      //\r
+      // Goto another Formset, check for uncommitted data\r
+      //\r
+      if ((gBrowserSettingScope == FormLevel || gBrowserSettingScope == FormSetLevel) &&\r
+          IsNvUpdateRequiredForFormSet(Selection->FormSet)) {\r
+        if (!ProcessChangedData(Selection, FormSetLevel)) {\r
+          return EFI_SUCCESS;\r
+        }\r
+      }\r
+    }\r
+\r
+    Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+    Selection->Handle = HiiHandle;\r
+    if (Selection->Handle == NULL) {\r
+      //\r
+      // If target Hii Handle not found, exit current formset.\r
+      //\r
+      FindParentFormSet(Selection);\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    CopyMem (&Selection->FormSetGuid,&Statement->HiiValue.Value.ref.FormSetGuid, sizeof (EFI_GUID));\r
+    Selection->FormId = Statement->HiiValue.Value.ref.FormId;\r
+    Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;\r
+  } else if (!CompareGuid (&Statement->HiiValue.Value.ref.FormSetGuid, &gZeroGuid)) {\r
+    if (Selection->Form->ModalForm) {\r
+      return Status;\r
+    }\r
+    if (!CompareGuid (&Statement->HiiValue.Value.ref.FormSetGuid, &Selection->FormSetGuid)) {\r
+      //\r
+      // Goto another Formset, check for uncommitted data\r
+      //\r
+      if ((gBrowserSettingScope == FormLevel || gBrowserSettingScope == FormSetLevel) &&\r
+         IsNvUpdateRequiredForFormSet(Selection->FormSet)) {\r
+        if (!ProcessChangedData(Selection, FormSetLevel)) {\r
+          return EFI_SUCCESS;\r
+        }\r
+      }\r
+    }\r
+\r
+    Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+    Selection->Handle = FormSetGuidToHiiHandle(&Statement->HiiValue.Value.ref.FormSetGuid);\r
+    if (Selection->Handle == NULL) {\r
+      //\r
+      // If target Hii Handle not found, exit current formset.\r
+      //\r
+      FindParentFormSet(Selection);\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    CopyMem (&Selection->FormSetGuid, &Statement->HiiValue.Value.ref.FormSetGuid, sizeof (EFI_GUID));\r
+    Selection->FormId = Statement->HiiValue.Value.ref.FormId;\r
+    Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;\r
+  } else if (Statement->HiiValue.Value.ref.FormId != 0) {\r
+    //\r
+    // Goto another Form, check for uncommitted data\r
+    //\r
+    if (Statement->HiiValue.Value.ref.FormId != Selection->FormId) {\r
+      if ((gBrowserSettingScope == FormLevel && IsNvUpdateRequiredForForm(Selection->Form))) {\r
+        if (!ProcessChangedData (Selection, FormLevel)) {\r
+          return EFI_SUCCESS;\r
+        }\r
+      }\r
+    }\r
+\r
+    RefForm = IdToForm (Selection->FormSet, Statement->HiiValue.Value.ref.FormId);\r
+    if ((RefForm != NULL) && (RefForm->SuppressExpression != NULL)) {\r
+      if (EvaluateExpressionList(RefForm->SuppressExpression, TRUE, Selection->FormSet, RefForm) != ExpressFalse) {\r
+        //\r
+        // Form is suppressed. \r
+        //\r
+        PopupErrorMessage(BROWSER_FORM_SUPPRESS, NULL, NULL, NULL);\r
+        return EFI_SUCCESS;\r
+      }\r
+    }\r
+\r
+    Selection->FormId = Statement->HiiValue.Value.ref.FormId;\r
+    Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;\r
+  } else if (Statement->HiiValue.Value.ref.QuestionId != 0) {\r
+    Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Process Question Config.\r
+\r
+  @param  Selection              The UI menu selection.\r
+  @param  Question               The Question to be peocessed.\r
+\r
+  @retval EFI_SUCCESS            Question Config process success.\r
+  @retval Other                  Question Config process fail.\r
+\r
+**/\r
+EFI_STATUS\r
+ProcessQuestionConfig (\r
+  IN  UI_MENU_SELECTION       *Selection,\r
+  IN  FORM_BROWSER_STATEMENT  *Question\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  CHAR16                          *ConfigResp;\r
+  CHAR16                          *Progress;\r
+\r
+  if (Question->QuestionConfig == 0) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Get <ConfigResp>\r
+  //\r
+  ConfigResp = GetToken (Question->QuestionConfig, Selection->FormSet->HiiHandle);\r
+  if (ConfigResp == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  } else if (ConfigResp[0] == L'\0') {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Send config to Configuration Driver\r
+  //\r
+  Status = mHiiConfigRouting->RouteConfig (\r
+                           mHiiConfigRouting,\r
+                           ConfigResp,\r
+                           &Progress\r
+                           );\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  Process the user input data.\r
+\r
+  @param UserInput               The user input data.\r
+\r
+  @retval EFI_SUCESSS            This function always return successfully for now.\r
+\r
+**/\r
+EFI_STATUS\r
+ProcessUserInput (\r
+  IN USER_INPUT               *UserInput\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  FORM_BROWSER_STATEMENT        *Statement;\r
+\r
+  Status    = EFI_SUCCESS;\r
+  Statement = NULL;\r
+\r
+  //\r
+  // When Exit from FormDisplay function, one of the below two cases must be true.\r
+  //\r
+  ASSERT (UserInput->Action != 0 || UserInput->SelectedStatement != NULL);\r
+\r
+  //\r
+  // Remove the last highligh question id, this id will update when show next form.\r
+  //\r
+  gCurrentSelection->QuestionId = 0;\r
+  if (UserInput->SelectedStatement != NULL){\r
+    Statement = GetBrowserStatement(UserInput->SelectedStatement);\r
+    ASSERT (Statement != NULL);\r
+\r
+    //\r
+    // This question is the current user select one,record it and later\r
+    // show it as the highlight question.\r
+    //\r
+    gCurrentSelection->CurrentMenu->QuestionId = Statement->QuestionId;\r
+    //\r
+    // For statement like text, actio, it not has question id.\r
+    // So use FakeQuestionId to save the question.\r
+    //\r
+    if (gCurrentSelection->CurrentMenu->QuestionId == 0) {\r
+      mCurFakeQestId = Statement->FakeQuestionId;\r
+    } else {\r
+      mCurFakeQestId = 0;\r
+    }\r
+  }\r
+\r
+  //\r
+  // First process the Action field in USER_INPUT.\r
+  //\r
+  if (UserInput->Action != 0) {\r
+    Status = ProcessAction (UserInput->Action, UserInput->DefaultId);\r
+    gCurrentSelection->Statement = NULL;\r
+  } else {\r
+    ASSERT (Statement != NULL);\r
+    gCurrentSelection->Statement = Statement;\r
+    switch (Statement->Operand) {\r
+    case EFI_IFR_REF_OP:\r
+      Status = ProcessGotoOpCode(Statement, gCurrentSelection);\r
+      break;\r
+    \r
+    case EFI_IFR_ACTION_OP:\r
+      //\r
+      // Process the Config string <ConfigResp>\r
+      //\r
+      Status = ProcessQuestionConfig (gCurrentSelection, Statement);\r
+      break;\r
+    \r
+    case EFI_IFR_RESET_BUTTON_OP:\r
+      //\r
+      // Reset Question to default value specified by DefaultId\r
+      //\r
+      Status = ExtractDefault (gCurrentSelection->FormSet, NULL, Statement->DefaultId, FormSetLevel, GetDefaultForAll, NULL, FALSE, FALSE);\r
+      UpdateStatementStatus (gCurrentSelection->FormSet, NULL, FormSetLevel);\r
+      break;\r
+\r
+    default:\r
+      switch (Statement->Operand) {\r
+      case EFI_IFR_STRING_OP:\r
+        DeleteString(Statement->HiiValue.Value.string, gCurrentSelection->FormSet->HiiHandle);\r
+        Statement->HiiValue.Value.string = UserInput->InputValue.Value.string;\r
+        CopyMem (Statement->BufferValue, UserInput->InputValue.Buffer, (UINTN) UserInput->InputValue.BufferLen);\r
+        FreePool (UserInput->InputValue.Buffer);\r
+        break;\r
+\r
+      case EFI_IFR_PASSWORD_OP:\r
+        if (UserInput->InputValue.Buffer == NULL) {\r
+          //\r
+          // User not input new password, just return.\r
+          //\r
+          break;\r
+        }\r
+\r
+        DeleteString(Statement->HiiValue.Value.string, gCurrentSelection->FormSet->HiiHandle);\r
+        Statement->HiiValue.Value.string = UserInput->InputValue.Value.string;\r
+        CopyMem (Statement->BufferValue, UserInput->InputValue.Buffer, (UINTN) UserInput->InputValue.BufferLen);\r
+        FreePool (UserInput->InputValue.Buffer);\r
+        //\r
+        // Two password match, send it to Configuration Driver\r
+        //\r
+        if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
+          PasswordCheck (NULL, UserInput->SelectedStatement, (CHAR16 *) Statement->BufferValue);\r
+          //\r
+          // Clean the value after saved it.\r
+          //\r
+          ZeroMem (Statement->BufferValue, (UINTN) UserInput->InputValue.BufferLen);\r
+          HiiSetString (gCurrentSelection->FormSet->HiiHandle, Statement->HiiValue.Value.string, (CHAR16*)Statement->BufferValue, NULL);\r
+        } else {\r
+          SetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithHiiDriver);\r
+        }\r
+        break;\r
+\r
+      case EFI_IFR_ORDERED_LIST_OP:\r
+        CopyMem (Statement->BufferValue, UserInput->InputValue.Buffer, UserInput->InputValue.BufferLen);\r
+        break;\r
+\r
+      default:\r
+        CopyMem (&Statement->HiiValue, &UserInput->InputValue, sizeof (EFI_HII_VALUE));\r
+        break;\r
+      }\r
+      break;\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  Display form and wait for user to select one menu option, then return it.\r
+\r
+  @retval EFI_SUCESSS            This function always return successfully for now.\r
+\r
+**/\r
+EFI_STATUS\r
+DisplayForm (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS               Status;\r
+  USER_INPUT               UserInput;\r
+  FORM_ENTRY_INFO          *CurrentMenu;\r
+\r
+  ZeroMem (&UserInput, sizeof (USER_INPUT));\r
+\r
+  //\r
+  // Update the menu history data.\r
+  //\r
+  CurrentMenu = UiFindMenuList (gCurrentSelection->Handle, &gCurrentSelection->FormSetGuid, gCurrentSelection->FormId);\r
+  if (CurrentMenu == NULL) {\r
+    //\r
+    // Current menu not found, add it to the menu tree\r
+    //\r
+    CurrentMenu = UiAddMenuList (gCurrentSelection->Handle, &gCurrentSelection->FormSetGuid,\r
+                                 gCurrentSelection->FormId, gCurrentSelection->QuestionId);\r
+    ASSERT (CurrentMenu != NULL);\r
+  }\r
+\r
+  //\r
+  // Back up the form view history data for this form.\r
+  //\r
+  UiCopyMenuList(&gCurrentSelection->Form->FormViewListHead, &mPrivateData.FormBrowserEx2.FormViewHistoryHead);\r
+\r
+  gCurrentSelection->CurrentMenu = CurrentMenu;\r
+\r
+  if (gCurrentSelection->QuestionId == 0) {\r
+    //\r
+    // Highlight not specified, fetch it from cached menu\r
+    //\r
+    gCurrentSelection->QuestionId = CurrentMenu->QuestionId;\r
+  }\r
+\r
+  Status = EvaluateFormExpressions (gCurrentSelection->FormSet, gCurrentSelection->Form);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  UpdateDisplayFormData ();\r
+\r
+  ASSERT (gDisplayFormData.BrowserStatus == BROWSER_SUCCESS);\r
+  Status = mFormDisplay->FormDisplay (&gDisplayFormData, &UserInput);\r
+  if (EFI_ERROR (Status)) {\r
+    FreeDisplayFormData();\r
+    return Status;\r
+  }\r
+\r
+  Status = ProcessUserInput (&UserInput);\r
+  FreeDisplayFormData();\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Functions which are registered to receive notification of\r
+  database events have this prototype. The actual event is encoded\r
+  in NotifyType. The following table describes how PackageType,\r
+  PackageGuid, Handle, and Package are used for each of the\r
+  notification types.\r
+\r
+  @param PackageType  Package type of the notification.\r
+\r
+  @param PackageGuid  If PackageType is\r
+                      EFI_HII_PACKAGE_TYPE_GUID, then this is\r
+                      the pointer to the GUID from the Guid\r
+                      field of EFI_HII_PACKAGE_GUID_HEADER.\r
+                      Otherwise, it must be NULL.\r
+\r
+  @param Package  Points to the package referred to by the\r
+                  notification Handle The handle of the package\r
+                  list which contains the specified package.\r
+\r
+  @param Handle       The HII handle.\r
+\r
+  @param NotifyType   The type of change concerning the\r
+                      database. See\r
+                      EFI_HII_DATABASE_NOTIFY_TYPE.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FormUpdateNotify (\r
+  IN UINT8                              PackageType,\r
+  IN CONST EFI_GUID                     *PackageGuid,\r
+  IN CONST EFI_HII_PACKAGE_HEADER       *Package,\r
+  IN EFI_HII_HANDLE                     Handle,\r
+  IN EFI_HII_DATABASE_NOTIFY_TYPE       NotifyType\r
+  )\r
+{\r
+  mHiiPackageListUpdated = TRUE;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Update the NV flag info for this form set.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+\r
+**/\r
+BOOLEAN\r
+IsNvUpdateRequiredForFormSet (\r
+  IN FORM_BROWSER_FORMSET  *FormSet\r
+  )\r
+{\r
+  LIST_ENTRY              *Link;\r
+  FORM_BROWSER_FORM       *Form;\r
+  BOOLEAN                 RetVal;\r
+\r
+  //\r
+  // Not finished question initialization, return FALSE.\r
+  //\r
+  if (!FormSet->QuestionInited) {\r
+    return FALSE;\r
+  }\r
+\r
+  RetVal = FALSE;\r
+\r
+  Link = GetFirstNode (&FormSet->FormListHead);\r
+  while (!IsNull (&FormSet->FormListHead, Link)) {\r
+    Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+\r
+    RetVal = IsNvUpdateRequiredForForm(Form);\r
+    if (RetVal) {\r
+      break;\r
+    }\r
+\r
+    Link = GetNextNode (&FormSet->FormListHead, Link);\r
+  }\r
+\r
+  return RetVal;\r
+}\r
+\r
+/**\r
+  Update the NvUpdateRequired flag for a form.\r
+\r
+  @param  Form                Form data structure.\r
+\r
+**/\r
+BOOLEAN\r
+IsNvUpdateRequiredForForm (\r
+  IN FORM_BROWSER_FORM    *Form\r
+  )\r
+{\r
+  LIST_ENTRY              *Link;\r
+  FORM_BROWSER_STATEMENT  *Statement;\r
+\r
+  Link = GetFirstNode (&Form->StatementListHead);\r
+  while (!IsNull (&Form->StatementListHead, Link)) {\r
+    Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+\r
+    if (Statement->ValueChanged) {\r
+      return TRUE;\r
+    }\r
+\r
+    Link = GetNextNode (&Form->StatementListHead, Link);\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Find menu which will show next time.\r
+\r
+  @param Selection       On input, Selection tell setup browser the information\r
+                         about the Selection, form and formset to be displayed.\r
+                         On output, Selection return the screen item that is selected\r
+                         by user.\r
+  @param SettingLevel    Input Settting level, if it is FormLevel, just exit current form. \r
+                         else, we need to exit current formset.\r
+  \r
+  @retval TRUE           Exit current form.\r
+  @retval FALSE          User press ESC and keep in current form.\r
+**/\r
+BOOLEAN\r
+FindNextMenu (\r
+  IN OUT UI_MENU_SELECTION        *Selection,\r
+  IN     BROWSER_SETTING_SCOPE     SettingLevel\r
+  )\r
+{\r
+  FORM_ENTRY_INFO            *CurrentMenu;\r
+  FORM_ENTRY_INFO            *ParentMenu;\r
+  BROWSER_SETTING_SCOPE      Scope;\r
+  \r
+  CurrentMenu = Selection->CurrentMenu;\r
+  Scope       = FormSetLevel;\r
+\r
+  ParentMenu = UiFindParentMenu(CurrentMenu, SettingLevel);\r
+  while (ParentMenu != NULL && !ValidateHiiHandle(ParentMenu->HiiHandle)) {\r
+    ParentMenu = UiFindParentMenu(ParentMenu, SettingLevel);\r
+  }\r
+\r
+  if (ParentMenu != NULL) {\r
+    if (CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) {\r
+      Scope = FormLevel;\r
+    } else {\r
+      Scope = FormSetLevel;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Form Level Check whether the data is changed.\r
+  //\r
+  if ((gBrowserSettingScope == FormLevel && IsNvUpdateRequiredForForm (Selection->Form)) ||\r
+      (gBrowserSettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet(Selection->FormSet) && Scope == FormSetLevel)) {\r
+    if (!ProcessChangedData(Selection, gBrowserSettingScope)) {\r
+      return FALSE;\r
+    }\r
+  }\r
+\r
+  if (ParentMenu != NULL) {\r
+    //\r
+    // ParentMenu is found. Then, go to it.\r
+    //\r
+    if (Scope == FormLevel) {\r
+      Selection->Action = UI_ACTION_REFRESH_FORM;\r
+    } else {\r
+      Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+      CopyMem (&Selection->FormSetGuid, &ParentMenu->FormSetGuid, sizeof (EFI_GUID));\r
+      Selection->Handle = ParentMenu->HiiHandle;\r
+    }\r
+\r
+    Selection->Statement = NULL;\r
+\r
+    Selection->FormId = ParentMenu->FormId;\r
+    Selection->QuestionId = ParentMenu->QuestionId;\r
+\r
+    //\r
+    // Clear highlight record for this menu\r
+    //\r
+    CurrentMenu->QuestionId = 0;\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Current in root page, exit the SendForm\r
+  //\r
+  Selection->Action = UI_ACTION_EXIT;\r
+\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Call the call back function for the question and process the return action.\r
+\r
+  @param Selection             On input, Selection tell setup browser the information\r
+                               about the Selection, form and formset to be displayed.\r
+                               On output, Selection return the screen item that is selected\r
+                               by user.\r
+  @param FormSet               The formset this question belong to.\r
+  @param Form                  The form this question belong to.\r
+  @param Question              The Question which need to call.\r
+  @param Action                The action request.\r
+  @param SkipSaveOrDiscard     Whether skip save or discard action.\r
+\r
+  @retval EFI_SUCCESS          The call back function excutes successfully.\r
+  @return Other value if the call back function failed to excute.  \r
+**/\r
+EFI_STATUS \r
+ProcessCallBackFunction (\r
+  IN OUT UI_MENU_SELECTION               *Selection,\r
+  IN     FORM_BROWSER_FORMSET            *FormSet,\r
+  IN     FORM_BROWSER_FORM               *Form,\r
+  IN     FORM_BROWSER_STATEMENT          *Question,\r
+  IN     EFI_BROWSER_ACTION              Action,\r
+  IN     BOOLEAN                         SkipSaveOrDiscard\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  EFI_STATUS                      InternalStatus;\r
+  EFI_BROWSER_ACTION_REQUEST      ActionRequest;\r
+  EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;\r
+  EFI_HII_VALUE                   *HiiValue;\r
+  EFI_IFR_TYPE_VALUE              *TypeValue;\r
+  FORM_BROWSER_STATEMENT          *Statement;\r
+  BOOLEAN                         SubmitFormIsRequired;\r
+  BOOLEAN                         DiscardFormIsRequired;\r
+  BOOLEAN                         NeedExit;\r
+  LIST_ENTRY                      *Link;\r
+  BROWSER_SETTING_SCOPE           SettingLevel;\r
+  EFI_IFR_TYPE_VALUE              BackUpValue;\r
+  UINT8                           *BackUpBuffer;\r
+  CHAR16                          *NewString;\r
+\r
+  ConfigAccess = FormSet->ConfigAccess;\r
+  SubmitFormIsRequired  = FALSE;\r
+  SettingLevel          = FormSetLevel;\r
+  DiscardFormIsRequired = FALSE;\r
+  NeedExit              = FALSE;\r
+  Status                = EFI_SUCCESS;\r
+  ActionRequest         = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+  BackUpBuffer          = NULL;\r
+\r
+  if (ConfigAccess == NULL) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  Link = GetFirstNode (&Form->StatementListHead);\r
+  while (!IsNull (&Form->StatementListHead, Link)) {\r
+    Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+    Link = GetNextNode (&Form->StatementListHead, Link);\r
+\r
+    //\r
+    // if Question != NULL, only process the question. Else, process all question in this form.\r
+    //\r
+    if ((Question != NULL) && (Statement != Question)) {\r
+      continue;\r
+    }\r
+    \r
+    if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Check whether Statement is disabled.\r
+    //\r
+    if (Statement->Expression != NULL) {\r
+      if (EvaluateExpressionList(Statement->Expression, TRUE, FormSet, Form) == ExpressDisable) {\r
+        continue;\r
+      }\r
+    }\r
+\r
+    HiiValue = &Statement->HiiValue;\r
+    TypeValue = &HiiValue->Value;\r
+    if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
+      //\r
+      // For OrderedList, passing in the value buffer to Callback()\r
+      //\r
+      TypeValue = (EFI_IFR_TYPE_VALUE *) Statement->BufferValue;\r
+    }\r
+\r
+    //\r
+    // If EFI_BROWSER_ACTION_CHANGING type, back up the new question value.\r
+    //\r
+    if (Action == EFI_BROWSER_ACTION_CHANGING) {\r
+      if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
+        BackUpBuffer = AllocateCopyPool(Statement->StorageWidth + sizeof(CHAR16), Statement->BufferValue);\r
+        ASSERT (BackUpBuffer != NULL);\r
+      } else {\r
+        CopyMem (&BackUpValue, &HiiValue->Value, sizeof (EFI_IFR_TYPE_VALUE));\r
+      }\r
+    }\r
+\r
+    ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+    Status = ConfigAccess->Callback (\r
+                             ConfigAccess,\r
+                             Action,\r
+                             Statement->QuestionId,\r
+                             HiiValue->Type,\r
+                             TypeValue,\r
+                             &ActionRequest\r
+                             );\r
+    if (!EFI_ERROR (Status)) {\r
+      //\r
+      // Need to sync the value between Statement->HiiValue->Value and Statement->BufferValue\r
+      //\r
+      if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
+        NewString = GetToken (Statement->HiiValue.Value.string, FormSet->HiiHandle);\r
+        ASSERT (NewString != NULL);\r
+\r
+        ASSERT (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth);\r
+        if (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth) {\r
+          CopyMem (Statement->BufferValue, NewString, StrSize (NewString));\r
+        } else {\r
+          CopyMem (Statement->BufferValue, NewString, Statement->StorageWidth);\r
+        }\r
+        FreePool (NewString);\r
+      }\r
+\r
+      //\r
+      // Only for EFI_BROWSER_ACTION_CHANGED need to handle this ActionRequest.\r
+      //\r
+      switch (Action) {\r
+      case EFI_BROWSER_ACTION_CHANGED:\r
+        switch (ActionRequest) {\r
+        case EFI_BROWSER_ACTION_REQUEST_RESET:\r
+          DiscardFormIsRequired = TRUE;\r
+          gResetRequired = TRUE;\r
+          NeedExit              = TRUE;\r
+          break;\r
+\r
+        case EFI_BROWSER_ACTION_REQUEST_SUBMIT:\r
+          SubmitFormIsRequired = TRUE;\r
+          NeedExit              = TRUE;\r
+          break;\r
+\r
+        case EFI_BROWSER_ACTION_REQUEST_EXIT:\r
+          DiscardFormIsRequired = TRUE;\r
+          NeedExit              = TRUE;\r
+          break;\r
+\r
+        case EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT:\r
+          SubmitFormIsRequired  = TRUE;\r
+          SettingLevel          = FormLevel;\r
+          NeedExit              = TRUE;\r
+          break;\r
+\r
+        case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT:\r
+          DiscardFormIsRequired = TRUE;\r
+          SettingLevel          = FormLevel;\r
+          NeedExit              = TRUE;\r
+          break;\r
+\r
+        case EFI_BROWSER_ACTION_REQUEST_FORM_APPLY:\r
+          SubmitFormIsRequired  = TRUE;\r
+          SettingLevel          = FormLevel;\r
+          break;\r
+\r
+        case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD:\r
+          DiscardFormIsRequired = TRUE;\r
+          SettingLevel          = FormLevel;\r
+          break;\r
+\r
+        default:\r
+          break;\r
+        }\r
+        break;\r
+\r
+      case EFI_BROWSER_ACTION_CHANGING:\r
+        //\r
+        // Do the question validation.\r
+        //\r
+        Status = ValueChangedValidation (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement);\r
+        if (!EFI_ERROR (Status)) {\r
+          //\r
+          //check whether the question value  changed compared with edit buffer before updating edit buffer\r
+          // if changed, set the ValueChanged flag to TRUE,in order to trig the CHANGED callback function\r
+          //\r
+          IsQuestionValueChanged(gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithEditBuffer);\r
+          //\r
+          // According the spec, return value from call back of "changing" and \r
+          // "retrieve" should update to the question's temp buffer.\r
+          //\r
+          SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
+        }\r
+        break;\r
+\r
+      case EFI_BROWSER_ACTION_RETRIEVE:\r
+        //\r
+        // According the spec, return value from call back of "changing" and \r
+        // "retrieve" should update to the question's temp buffer.\r
+        //\r
+        SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
+        break;\r
+\r
+      default:\r
+        break;\r
+      }\r
+    } else {\r
+      //\r
+      // If the callback returns EFI_UNSUPPORTED for EFI_BROWSER_ACTION_CHANGING, \r
+      // then the browser will use the value passed to Callback() and ignore the \r
+      // value returned by Callback(). \r
+      //\r
+      if (Action  == EFI_BROWSER_ACTION_CHANGING && Status == EFI_UNSUPPORTED) {\r
+        if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
+          CopyMem (Statement->BufferValue, BackUpBuffer, Statement->StorageWidth + sizeof(CHAR16));\r
+        } else {\r
+          CopyMem (&HiiValue->Value, &BackUpValue, sizeof (EFI_IFR_TYPE_VALUE));\r
+        }\r
+        \r
+        //\r
+        // Do the question validation.\r
+        //\r
+        InternalStatus = ValueChangedValidation (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement);\r
+        if (!EFI_ERROR (InternalStatus)) {\r
+          //\r
+          //check whether the question value  changed compared with edit buffer before updating edit buffer\r
+          // if changed, set the ValueChanged flag to TRUE,in order to trig the CHANGED callback function\r
+          //\r
+          IsQuestionValueChanged(gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithEditBuffer);\r
+          SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
+        }\r
+      }\r
+\r
+      //\r
+      // According the spec, return fail from call back of "changing" and \r
+      // "retrieve", should restore the question's value.\r
+      //\r
+      if (Action == EFI_BROWSER_ACTION_CHANGING && Status != EFI_UNSUPPORTED) {\r
+        if (Statement->Storage != NULL) {\r
+          GetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
+        } else if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
+          ProcessCallBackFunction (Selection, FormSet, Form, Question, EFI_BROWSER_ACTION_RETRIEVE, FALSE);\r
+        }\r
+      }\r
+\r
+      if (Action == EFI_BROWSER_ACTION_RETRIEVE) {\r
+        GetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);\r
+      }\r
+\r
+      if (Status == EFI_UNSUPPORTED) {\r
+        //\r
+        // If return EFI_UNSUPPORTED, also consider Hii driver suceess deal with it.\r
+        //\r
+        Status = EFI_SUCCESS;\r
+      }\r
+    }\r
+\r
+    if (BackUpBuffer != NULL) {\r
+      FreePool (BackUpBuffer);\r
+    }\r
+\r
+    //\r
+    // If Question != NULL, means just process one question\r
+    // and if code reach here means this question has finished\r
+    // processing, so just break.\r
+    //\r
+    if (Question != NULL) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (SubmitFormIsRequired && !SkipSaveOrDiscard) {\r
+    SubmitForm (FormSet, Form, SettingLevel);\r
+  }\r
+\r
+  if (DiscardFormIsRequired && !SkipSaveOrDiscard) {\r
+    DiscardForm (FormSet, Form, SettingLevel);\r
+  }\r
+\r
+  if (NeedExit) {\r
+    FindNextMenu (Selection, SettingLevel);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Call the retrieve type call back function for one question to get the initialize data.\r
+  \r
+  This function only used when in the initialize stage, because in this stage, the \r
+  Selection->Form is not ready. For other case, use the ProcessCallBackFunction instead.\r
+\r
+  @param ConfigAccess          The config access protocol produced by the hii driver.\r
+  @param Statement             The Question which need to call.\r
+  @param FormSet               The formset this question belong to.\r
+\r
+  @retval EFI_SUCCESS          The call back function excutes successfully.\r
+  @return Other value if the call back function failed to excute.  \r
+**/\r
+EFI_STATUS \r
+ProcessRetrieveForQuestion (\r
+  IN     EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess,\r
+  IN     FORM_BROWSER_STATEMENT          *Statement,\r
+  IN     FORM_BROWSER_FORMSET            *FormSet\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  EFI_BROWSER_ACTION_REQUEST      ActionRequest;\r
+  EFI_HII_VALUE                   *HiiValue;\r
+  EFI_IFR_TYPE_VALUE              *TypeValue;\r
+  CHAR16                          *NewString;\r
+\r
+  Status                = EFI_SUCCESS;\r
+  ActionRequest         = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+\r
+  if (((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) || ConfigAccess == NULL) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  HiiValue  = &Statement->HiiValue;\r
+  TypeValue = &HiiValue->Value;\r
+  if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
+    //\r
+    // For OrderedList, passing in the value buffer to Callback()\r
+    //\r
+    TypeValue = (EFI_IFR_TYPE_VALUE *) Statement->BufferValue;\r
+  }\r
+    \r
+  ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+  Status = ConfigAccess->Callback (\r
+                           ConfigAccess,\r
+                           EFI_BROWSER_ACTION_RETRIEVE,\r
+                           Statement->QuestionId,\r
+                           HiiValue->Type,\r
+                           TypeValue,\r
+                           &ActionRequest\r
+                           );\r
+  if (!EFI_ERROR (Status) && HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
+    NewString = GetToken (Statement->HiiValue.Value.string, FormSet->HiiHandle);\r
+    ASSERT (NewString != NULL);\r
+\r
+    ASSERT (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth);\r
+    if (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth) {\r
+      CopyMem (Statement->BufferValue, NewString, StrSize (NewString));\r
+    } else {\r
+      CopyMem (Statement->BufferValue, NewString, Statement->StorageWidth);\r
+    }\r
+    FreePool (NewString);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  The worker function that send the displays to the screen. On output,\r
+  the selection made by user is returned.\r
+\r
+  @param Selection       On input, Selection tell setup browser the information\r
+                         about the Selection, form and formset to be displayed.\r
+                         On output, Selection return the screen item that is selected\r
+                         by user.\r
+\r
+  @retval EFI_SUCCESS    The page is displayed successfully.\r
+  @return Other value if the page failed to be diplayed.\r
+\r
+**/\r
+EFI_STATUS\r
+SetupBrowser (\r
+  IN OUT UI_MENU_SELECTION    *Selection\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  LIST_ENTRY                      *Link;\r
+  EFI_HANDLE                      NotifyHandle;\r
+  FORM_BROWSER_STATEMENT          *Statement;\r
+  EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;\r
+\r
+  ConfigAccess = Selection->FormSet->ConfigAccess;\r
+\r
+  //\r
+  // Register notify for Form package update\r
+  //\r
+  Status = mHiiDatabase->RegisterPackageNotify (\r
+                           mHiiDatabase,\r
+                           EFI_HII_PACKAGE_FORMS,\r
+                           NULL,\r
+                           FormUpdateNotify,\r
+                           EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
+                           &NotifyHandle\r
+                           );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Initialize current settings of Questions in this FormSet\r
+  //\r
+  InitializeCurrentSetting (Selection->FormSet);\r
+\r
+  //\r
+  // Initilize Action field.\r
+  //\r
+  Selection->Action = UI_ACTION_REFRESH_FORM;\r
+\r
+  //\r
+  // Clean the mCurFakeQestId value is formset refreshed.\r
+  //\r
+  mCurFakeQestId = 0;\r
+\r
+  do {\r
+    //\r
+    // IFR is updated, force to reparse the IFR binary\r
+    // This check is shared by EFI_BROWSER_ACTION_FORM_CLOSE and \r
+    // EFI_BROWSER_ACTION_RETRIEVE, so code place here.\r
+    //\r
+    if (mHiiPackageListUpdated) {\r
+      Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+      mHiiPackageListUpdated = FALSE;\r
+      break;\r
+    }\r
+\r
+    //\r
+    // Initialize Selection->Form\r
+    //\r
+    if (Selection->FormId == 0) {\r
+      //\r
+      // Zero FormId indicates display the first Form in a FormSet\r
+      //\r
+      Link = GetFirstNode (&Selection->FormSet->FormListHead);\r
+\r
+      Selection->Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+      Selection->FormId = Selection->Form->FormId;\r
+    } else {\r
+      Selection->Form = IdToForm (Selection->FormSet, Selection->FormId);\r
+    }\r
+\r
+    if (Selection->Form == NULL) {\r
+      //\r
+      // No Form to display\r
+      //\r
+      Status = EFI_NOT_FOUND;\r
+      goto Done;\r
+    }\r
+\r
+    //\r
+    // Check Form is suppressed.\r
+    //\r
+    if (Selection->Form->SuppressExpression != NULL) {\r
+      if (EvaluateExpressionList(Selection->Form->SuppressExpression, TRUE, Selection->FormSet, Selection->Form) == ExpressSuppress) {\r
+        //\r
+        // Form is suppressed. \r
+        //\r
+        PopupErrorMessage(BROWSER_FORM_SUPPRESS, NULL, NULL, NULL);\r
+        Status = EFI_NOT_FOUND;\r
+        goto Done;\r
+      }\r
+    }\r
+\r
+    //\r
+    // Before display new form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_OPEN\r
+    // for each question with callback flag.\r
+    // New form may be the first form, or the different form after another form close.\r
+    //\r
+    if (((Selection->Handle != mCurrentHiiHandle) ||\r
+        (!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid)) ||\r
+        (Selection->FormId != mCurrentFormId))) {\r
+      //\r
+      // Update Retrieve flag.\r
+      //\r
+      mFinishRetrieveCall = FALSE;\r
+\r
+      //\r
+      // Keep current form information\r
+      //\r
+      mCurrentHiiHandle   = Selection->Handle;\r
+      CopyGuid (&mCurrentFormSetGuid, &Selection->FormSetGuid);\r
+      mCurrentFormId      = Selection->FormId;\r
+\r
+      if (ConfigAccess != NULL) {\r
+        Status = ProcessCallBackFunction (Selection, Selection->FormSet, Selection->Form, NULL, EFI_BROWSER_ACTION_FORM_OPEN, FALSE);\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
+\r
+        //\r
+        // IFR is updated during callback of EFI_BROWSER_ACTION_FORM_OPEN, force to reparse the IFR binary\r
+        //\r
+        if (mHiiPackageListUpdated) {\r
+          Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+          mHiiPackageListUpdated = FALSE;\r
+          break;\r
+        }\r
+      }\r
+    }\r
+\r
+    //\r
+    // Load Questions' Value for display\r
+    //\r
+    Status = LoadFormSetConfig (Selection, Selection->FormSet);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+\r
+    if (!mFinishRetrieveCall) {\r
+      //\r
+      // Finish call RETRIEVE callback for this form.\r
+      //\r
+      mFinishRetrieveCall = TRUE;\r
+\r
+      if (ConfigAccess != NULL) {\r
+        Status = ProcessCallBackFunction (Selection, Selection->FormSet, Selection->Form, NULL, EFI_BROWSER_ACTION_RETRIEVE, FALSE);\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
+\r
+        //\r
+        // IFR is updated during callback of open form, force to reparse the IFR binary\r
+        //\r
+        if (mHiiPackageListUpdated) {\r
+          Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+          mHiiPackageListUpdated = FALSE;\r
+          break;\r
+        }\r
+      }\r
+    }\r
+\r
+    //\r
+    // Display form\r
+    //\r
+    Status = DisplayForm ();\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+\r
+    //\r
+    // Check Selected Statement (if press ESC, Selection->Statement will be NULL)\r
+    //\r
+    Statement = Selection->Statement;\r
+    if (Statement != NULL) {\r
+      if ((ConfigAccess != NULL) && \r
+          ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) && \r
+          (Statement->Operand != EFI_IFR_PASSWORD_OP)) {\r
+        Status = ProcessCallBackFunction(Selection, Selection->FormSet, Selection->Form, Statement, EFI_BROWSER_ACTION_CHANGING, FALSE);\r
+        if (Statement->Operand == EFI_IFR_REF_OP) {\r
+          //\r
+          // Process dynamic update ref opcode.\r
+          //\r
+          if (!EFI_ERROR (Status)) {\r
+            Status = ProcessGotoOpCode(Statement, Selection);\r
+          }\r
+          \r
+          //\r
+          // Callback return error status or status return from process goto opcode.\r
+          //\r
+          if (EFI_ERROR (Status)) {\r
+            //\r
+            // Cross reference will not be taken\r
+            //\r
+            Selection->FormId = Selection->Form->FormId;\r
+            Selection->QuestionId = 0;\r
+          }\r
+        }\r
+\r
+\r
+        if (!EFI_ERROR (Status) && \r
+            (Statement->Operand != EFI_IFR_REF_OP) && \r
+            ((Statement->Storage == NULL) || (Statement->Storage != NULL && Statement->ValueChanged))) {\r
+          //\r
+          // Only question value has been changed, browser will trig CHANGED callback.\r
+          //\r
+          ProcessCallBackFunction(Selection, Selection->FormSet, Selection->Form, Statement, EFI_BROWSER_ACTION_CHANGED, FALSE);\r
+          //\r
+          //check whether the question value changed compared with buffer value\r
+          //if doesn't change ,set the ValueChanged flag to FALSE ,in order not to display the "configuration changed "information on the screen\r
+          //\r
+          IsQuestionValueChanged(gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithBuffer);\r
+        }\r
+      } else {\r
+        //\r
+        // Do the question validation.\r
+        //\r
+        Status = ValueChangedValidation (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement);\r
+        if (!EFI_ERROR (Status) && (Statement->Operand != EFI_IFR_PASSWORD_OP)) {\r
+          SetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithEditBuffer);\r
+          //\r
+          // Verify whether question value has checked, update the ValueChanged flag in Question.\r
+          //\r
+          IsQuestionValueChanged(gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithBuffer);\r
+        }\r
+      }\r
+\r
+      //\r
+      // If question has EFI_IFR_FLAG_RESET_REQUIRED flag and without storage and process question success till here, \r
+      // trig the gResetFlag.\r
+      //\r
+      if ((Status == EFI_SUCCESS) && \r
+          (Statement->Storage == NULL) && \r
+          ((Statement->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) != 0)) {\r
+        gResetRequired = TRUE;\r
+      }\r
+    }\r
+\r
+    //\r
+    // Check whether Exit flag is TRUE.\r
+    //\r
+    if (gExitRequired) {\r
+      switch (gBrowserSettingScope) {\r
+      case SystemLevel:\r
+        Selection->Action = UI_ACTION_EXIT;\r
+        break;\r
+\r
+      case FormSetLevel:\r
+      case FormLevel:\r
+        FindNextMenu (Selection, gBrowserSettingScope);\r
+        break;\r
+\r
+      default:\r
+        break;\r
+      }\r
+\r
+      gExitRequired = FALSE;\r
+    }\r
+\r
+    //\r
+    // Before exit the form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_CLOSE\r
+    // for each question with callback flag.\r
+    //\r
+    if ((ConfigAccess != NULL) && \r
+        ((Selection->Action == UI_ACTION_EXIT) || \r
+         (Selection->Handle != mCurrentHiiHandle) ||\r
+         (!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid)) ||\r
+         (Selection->FormId != mCurrentFormId))) {\r
+\r
+      Status = ProcessCallBackFunction (Selection, Selection->FormSet, Selection->Form, NULL, EFI_BROWSER_ACTION_FORM_CLOSE, FALSE);\r
+      if (EFI_ERROR (Status)) {\r
+        goto Done;\r
+      }\r
+    }\r
+  } while (Selection->Action == UI_ACTION_REFRESH_FORM);\r
+\r
+Done:\r
+  //\r
+  // Reset current form information to the initial setting when error happens or form exit.\r
+  //\r
+  if (EFI_ERROR (Status) || Selection->Action == UI_ACTION_EXIT) {\r
+    mCurrentHiiHandle = NULL;\r
+    CopyGuid (&mCurrentFormSetGuid, &gZeroGuid);\r
+    mCurrentFormId = 0;\r
+  }\r
+\r
+  //\r
+  // Unregister notify for Form package update\r
+  //\r
+  mHiiDatabase->UnregisterPackageNotify (\r
+                   mHiiDatabase,\r
+                   NotifyHandle\r
+                   );\r
+  return Status;\r
+}\r