]> git.proxmox.com Git - mirror_edk2.git/commitdiff
Clean up SetupBrowserDxe for Doxygen comments requirement.
authorqwang12 <qwang12@6f19259b-4bc3-4df7-8a09-765794883524>
Tue, 15 Jul 2008 08:35:54 +0000 (08:35 +0000)
committerqwang12 <qwang12@6f19259b-4bc3-4df7-8a09-765794883524>
Tue, 15 Jul 2008 08:35:54 +0000 (08:35 +0000)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@5472 6f19259b-4bc3-4df7-8a09-765794883524

12 files changed:
MdeModulePkg/Universal/SetupBrowserDxe/Colors.h
MdeModulePkg/Universal/SetupBrowserDxe/Expression.c
MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c
MdeModulePkg/Universal/SetupBrowserDxe/InputHandler.c
MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
MdeModulePkg/Universal/SetupBrowserDxe/Print.c
MdeModulePkg/Universal/SetupBrowserDxe/Print.h
MdeModulePkg/Universal/SetupBrowserDxe/ProcessOptions.c
MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
MdeModulePkg/Universal/SetupBrowserDxe/Setup.h
MdeModulePkg/Universal/SetupBrowserDxe/Ui.c
MdeModulePkg/Universal/SetupBrowserDxe/Ui.h

index 1b355ec5b637349fcbdd82ecf220fd01eba77777..94c3368c3ae427161722e893b33eb30ab0f00b93 100644 (file)
@@ -1,4 +1,5 @@
 /** @file
+MACRO definitions for color used in Setup Browser.
 
 Copyright (c) 2004, Intel Corporation
 All rights reserved. This program and the accompanying materials
@@ -9,20 +10,12 @@ 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:
-
-  Colors.h
-
-Abstract:
-
-
-Revision History
-
-
 **/
+//
+// Unicode collation protocol in
 
-#ifndef _COLORS_H
-#define _COLORS_H
+#ifndef _COLORS_H_
+#define _COLORS_H_
 
 //
 // Screen Color Settings
index a074b92a273ede8390a57c85e7f5f5bc0cd0cba0..25d4e0a678f2fc439de691dacf01465a9be9b774 100644 (file)
-/** @file
-
-Copyright (c) 2007, Intel Corporation
-All rights reserved. This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-Module Name:
-
-  Expression.c
-
-Abstract:
-
-  Expression evaluation.
-
-
-**/
-
-#include "Ui.h"
-#include "Setup.h"
-
-//
-// Global stack used to evaluate boolean expresions
-//
-EFI_HII_VALUE *mOpCodeScopeStack = NULL;
-EFI_HII_VALUE *mOpCodeScopeStackEnd = NULL;
-EFI_HII_VALUE *mOpCodeScopeStackPointer = NULL;
-
-EFI_HII_VALUE *mExpressionEvaluationStack = NULL;
-EFI_HII_VALUE *mExpressionEvaluationStackEnd = NULL;
-EFI_HII_VALUE *mExpressionEvaluationStackPointer = NULL;
-
-//
-// Unicode collation protocol interface
-//
-EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollation = NULL;
-
-
-/**
-  Grow size of the stack
-
-  @param  Stack                  On input: old stack; On output: new stack
-  @param  StackPtr               On input: old stack pointer; On output: new stack
-                                 pointer
-  @param  StackPtr               On input: old stack end; On output: new stack end
-
-  @retval EFI_SUCCESS            Grow stack success.
-  @retval EFI_OUT_OF_RESOURCES   No enough memory for stack space.
-
-**/
-STATIC
-EFI_STATUS
-GrowStack (
-  IN OUT EFI_HII_VALUE  **Stack,
-  IN OUT EFI_HII_VALUE  **StackPtr,
-  IN OUT EFI_HII_VALUE  **StackEnd
-  )
-{
-  UINTN           Size;
-  EFI_HII_VALUE  *NewStack;
-
-  Size = EXPRESSION_STACK_SIZE_INCREMENT;
-  if (*StackPtr != NULL) {
-    Size = Size + (*StackEnd - *Stack);
-  }
-
-  NewStack = AllocatePool (Size * sizeof (EFI_HII_VALUE));
-  if (NewStack == NULL) {
-    return EFI_OUT_OF_RESOURCES;
-  }
-
-  if (*StackPtr != NULL) {
-    //
-    // Copy from Old Stack to the New Stack
-    //
-    CopyMem (
-      NewStack,
-      *Stack,
-      (*StackEnd - *Stack) * sizeof (EFI_HII_VALUE)
-      );
-
-    //
-    // Free The Old Stack
-    //
-    gBS->FreePool (*Stack);
-  }
-
-  //
-  // Make the Stack pointer point to the old data in the new stack
-  //
-  *StackPtr = NewStack + (*StackPtr - *Stack);
-  *Stack    = NewStack;
-  *StackEnd = NewStack + Size;
-
-  return EFI_SUCCESS;
-}
-
-
-/**
-  Push an element onto the Boolean Stack
-
-  @param  Stack                  On input: old stack; On output: new stack
-  @param  StackPtr               On input: old stack pointer; On output: new stack
-                                 pointer
-  @param  StackPtr               On input: old stack end; On output: new stack end
-  @param  Data                   Data to push.
-
-  @retval EFI_SUCCESS            Push stack success.
-
-**/
-EFI_STATUS
-PushStack (
-  IN OUT EFI_HII_VALUE       **Stack,
-  IN OUT EFI_HII_VALUE       **StackPtr,
-  IN OUT EFI_HII_VALUE       **StackEnd,
-  IN EFI_HII_VALUE           *Data
-  )
-{
-  EFI_STATUS  Status;
-
-  //
-  // Check for a stack overflow condition
-  //
-  if (*StackPtr >= *StackEnd) {
-    //
-    // Grow the stack
-    //
-    Status = GrowStack (Stack, StackPtr, StackEnd);
-    if (EFI_ERROR (Status)) {
-      return Status;
-    }
-  }
-
-  //
-  // Push the item onto the stack
-  //
-  CopyMem (*StackPtr, Data, sizeof (EFI_HII_VALUE));
-  *StackPtr = *StackPtr + 1;
-
-  return EFI_SUCCESS;
-}
-
-
-/**
-  Pop an element from the stack.
-
-  @param  Stack                  On input: old stack; On output: new stack
-  @param  StackPtr               On input: old stack pointer; On output: new stack
-                                 pointer
-  @param  StackPtr               On input: old stack end; On output: new stack end
-  @param  Data                   Data to pop.
-
-  @retval EFI_SUCCESS            The value was popped onto the stack.
-  @retval EFI_ACCESS_DENIED      The pop operation underflowed the stack
-
-**/
-EFI_STATUS
-PopStack (
-  IN OUT EFI_HII_VALUE       **Stack,
-  IN OUT EFI_HII_VALUE       **StackPtr,
-  IN OUT EFI_HII_VALUE       **StackEnd,
-  OUT EFI_HII_VALUE          *Data
-  )
-{
-  //
-  // Check for a stack underflow condition
-  //
-  if (*StackPtr == *Stack) {
-    return EFI_ACCESS_DENIED;
-  }
-
-  //
-  // Pop the item off the stack
-  //
-  *StackPtr = *StackPtr - 1;
-  CopyMem (Data, *StackPtr, sizeof (EFI_HII_VALUE));
-  return EFI_SUCCESS;
-}
-
-
-/**
-  Reset stack pointer to begin of the stack.
-
-  None.
-
-  @return None.
-
-**/
-VOID
-ResetScopeStack (
-  VOID
-  )
-{
-  mOpCodeScopeStackPointer = mOpCodeScopeStack;
-}
-
-
-/**
-  Push an Operand onto the Stack
-
-  @param  Operand                Operand to push.
-
-  @retval EFI_SUCCESS            The value was pushed onto the stack.
-  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the
-                                 stack.
-
-**/
-EFI_STATUS
-PushScope (
-  IN UINT8   Operand
-  )
-{
-  EFI_HII_VALUE  Data;
-
-  Data.Type = EFI_IFR_TYPE_NUM_SIZE_8;
-  Data.Value.u8 = Operand;
-
-  return PushStack (
-           &mOpCodeScopeStack,
-           &mOpCodeScopeStackPointer,
-           &mOpCodeScopeStackEnd,
-           &Data
-           );
-}
-
-
-/**
-  Pop an Operand from the Stack
-
-  @param  Operand                Operand to pop.
-
-  @retval EFI_SUCCESS            The value was pushed onto the stack.
-  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the
-                                 stack.
-
-**/
-EFI_STATUS
-PopScope (
-  OUT UINT8     *Operand
-  )
-{
-  EFI_STATUS     Status;
-  EFI_HII_VALUE  Data;
-
-  Status = PopStack (
-             &mOpCodeScopeStack,
-             &mOpCodeScopeStackPointer,
-             &mOpCodeScopeStackEnd,
-             &Data
-             );
-
-  *Operand = Data.Value.u8;
-
-  return Status;
-}
-
-
-/**
-  Reset stack pointer to begin of the stack.
-
-  None.
-
-  @return None.
-
-**/
-VOID
-ResetExpressionStack (
-  VOID
-  )
-{
-  mExpressionEvaluationStackPointer = mExpressionEvaluationStack;
-}
-
-
-/**
-  Push an Expression value onto the Stack
-
-  @param  Value                  Expression value to push.
-
-  @retval EFI_SUCCESS            The value was pushed onto the stack.
-  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the
-                                 stack.
-
-**/
-EFI_STATUS
-PushExpression (
-  IN EFI_HII_VALUE  *Value
-  )
-{
-  return PushStack (
-           &mExpressionEvaluationStack,
-           &mExpressionEvaluationStackPointer,
-           &mExpressionEvaluationStackEnd,
-           Value
-           );
-}
-
-
-/**
-  Pop an Expression value from the stack.
-
-  @param  Value                  Expression value to pop.
-
-  @retval EFI_SUCCESS            The value was popped onto the stack.
-  @retval EFI_ACCESS_DENIED      The pop operation underflowed the stack
-
-**/
-EFI_STATUS
-PopExpression (
-  OUT EFI_HII_VALUE  *Value
-  )
-{
-  return PopStack (
-           &mExpressionEvaluationStack,
-           &mExpressionEvaluationStackPointer,
-           &mExpressionEvaluationStackEnd,
-           Value
-           );
-}
-
-
-/**
-  Get Form given its FormId.
-
-  @param  FormSet                The formset which contains this form.
-  @param  FormId                 Id of this form.
-
-  @retval Pointer                The form.
-  @retval NULL                   Specified Form is not found in the formset.
-
-**/
-FORM_BROWSER_FORM *
-IdToForm (
-  IN FORM_BROWSER_FORMSET  *FormSet,
-  IN UINT16                FormId
-)
-{
-  LIST_ENTRY         *Link;
-  FORM_BROWSER_FORM  *Form;
-
-  Link = GetFirstNode (&FormSet->FormListHead);
-  while (!IsNull (&FormSet->FormListHead, Link)) {
-    Form = FORM_BROWSER_FORM_FROM_LINK (Link);
-
-    if (Form->FormId == FormId) {
-      return Form;
-    }
-
-    Link = GetNextNode (&FormSet->FormListHead, Link);
-  }
-
-  return NULL;
-}
-
-
-/**
-  Search a Question in Form scope using its QuestionId.
-
-  @param  Form                   The form which contains this Question.
-  @param  QuestionId             Id of this Question.
-
-  @retval Pointer                The Question.
-  @retval NULL                   Specified Question not found in the form.
-
-**/
-FORM_BROWSER_STATEMENT *
-IdToQuestion2 (
-  IN FORM_BROWSER_FORM  *Form,
-  IN UINT16             QuestionId
-  )
-{
-  LIST_ENTRY              *Link;
-  FORM_BROWSER_STATEMENT  *Question;
-
-  if (QuestionId == 0) {
-    //
-    // The value of zero is reserved
-    //
-    return NULL;
-  }
-
-  Link = GetFirstNode (&Form->StatementListHead);
-  while (!IsNull (&Form->StatementListHead, Link)) {
-    Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
-
-    if (Question->QuestionId == QuestionId) {
-      return Question;
-    }
-
-    Link = GetNextNode (&Form->StatementListHead, Link);
-  }
-
-  return NULL;
-}
-
-
-/**
-  Search a Question in Formset scope using its QuestionId.
-
-  @param  FormSet                The formset which contains this form.
-  @param  Form                   The form which contains this Question.
-  @param  QuestionId             Id of this Question.
-
-  @retval Pointer                The Question.
-  @retval NULL                   Specified Question not found in the form.
-
-**/
-FORM_BROWSER_STATEMENT *
-IdToQuestion (
-  IN FORM_BROWSER_FORMSET  *FormSet,
-  IN FORM_BROWSER_FORM     *Form,
-  IN UINT16                QuestionId
-  )
-{
-  LIST_ENTRY              *Link;
-  FORM_BROWSER_STATEMENT  *Question;
-
-  //
-  // Search in the form scope first
-  //
-  Question = IdToQuestion2 (Form, QuestionId);
-  if (Question != NULL) {
-    return Question;
-  }
-
-  //
-  // Search in the formset scope
-  //
-  Link = GetFirstNode (&FormSet->FormListHead);
-  while (!IsNull (&FormSet->FormListHead, Link)) {
-    Form = FORM_BROWSER_FORM_FROM_LINK (Link);
-
-    Question = IdToQuestion2 (Form, QuestionId);
-    if (Question != NULL) {
-      return Question;
-    }
-
-    Link = GetNextNode (&FormSet->FormListHead, Link);
-  }
-
-  return NULL;
-}
-
-
-/**
-  Get Expression given its RuleId.
-
-  @param  Form                   The form which contains this Expression.
-  @param  RuleId                 Id of this Expression.
-
-  @retval Pointer                The Expression.
-  @retval NULL                   Specified Expression not found in the form.
-
-**/
-FORM_EXPRESSION *
-RuleIdToExpression (
-  IN FORM_BROWSER_FORM  *Form,
-  IN UINT8              RuleId
-  )
-{
-  LIST_ENTRY       *Link;
-  FORM_EXPRESSION  *Expression;
-
-  Link = GetFirstNode (&Form->ExpressionListHead);
-  while (!IsNull (&Form->ExpressionListHead, Link)) {
-    Expression = FORM_EXPRESSION_FROM_LINK (Link);
-
-    if (Expression->Type == EFI_HII_EXPRESSION_RULE && Expression->RuleId == RuleId) {
-      return Expression;
-    }
-
-    Link = GetNextNode (&Form->ExpressionListHead, Link);
-  }
-
-  return NULL;
-}
-
-
-/**
-  Locate the Unicode Collation Protocol interface for later use.
-
-  None.
-
-  @retval EFI_SUCCESS            Protocol interface initialize success.
-  @retval Other                  Protocol interface initialize failed.
-
-**/
-EFI_STATUS
-InitializeUnicodeCollationProtocol (
-  VOID
-  )
-{
-  EFI_STATUS  Status;
-
-  if (mUnicodeCollation != NULL) {
-    return EFI_SUCCESS;
-  }
-
-  //
-  // BUGBUG: Proper impelmentation is to locate all Unicode Collation Protocol
-  // instances first and then select one which support English language.
-  // Current implementation just pick the first instance.
-  //
-  Status = gBS->LocateProtocol (
-                  &gEfiUnicodeCollation2ProtocolGuid,
-                  NULL,
-                  (VOID **) &mUnicodeCollation
-                  );
-  return Status;
-}
-
-VOID
-IfrStrToUpper (
-  CHAR16                   *String
-  )
-{
-  while (*String != 0) {
-    if ((*String >= 'a') && (*String <= 'z')) {
-      *String = (UINT16) ((*String) & ((UINT16) ~0x20));
-    }
-    String++;
-  }
-}
-
-
-/**
-  Evaluate opcode EFI_IFR_TO_STRING.
-
-  @param  FormSet                Formset which contains this opcode.
-  @param  Format                 String format in EFI_IFR_TO_STRING.
-  @param  Result                 Evaluation result for this opcode.
-
-  @retval EFI_SUCCESS            Opcode evaluation success.
-  @retval Other                  Opcode evaluation failed.
-
-**/
-EFI_STATUS
-IfrToString (
-  IN FORM_BROWSER_FORMSET  *FormSet,
-  IN UINT8                 Format,
-  OUT  EFI_HII_VALUE       *Result
-  )
-{
-  EFI_STATUS     Status;
-  EFI_HII_VALUE  Value;
-  CHAR16         *String;
-  CHAR16         *PrintFormat;
-  CHAR16         Buffer[MAXIMUM_VALUE_CHARACTERS];
-  UINTN          BufferSize;
-
-  Status = PopExpression (&Value);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  switch (Value.Type) {
-  case EFI_IFR_TYPE_NUM_SIZE_8:
-  case EFI_IFR_TYPE_NUM_SIZE_16:
-  case EFI_IFR_TYPE_NUM_SIZE_32:
-  case EFI_IFR_TYPE_NUM_SIZE_64:
-    BufferSize = MAXIMUM_VALUE_CHARACTERS * sizeof (CHAR16);
-    switch (Format) {
-    case EFI_IFR_STRING_UNSIGNED_DEC:
-    case EFI_IFR_STRING_SIGNED_DEC:
-      PrintFormat = L"%ld";
-      break;
-
-    case EFI_IFR_STRING_LOWERCASE_HEX:
-      PrintFormat = L"%lx";
-      break;
-
-    case EFI_IFR_STRING_UPPERCASE_HEX:
-      PrintFormat = L"%lX";
-      break;
-
-    default:
-      return EFI_UNSUPPORTED;
-    }
-    UnicodeSPrint (Buffer, BufferSize, PrintFormat, Value.Value.u64);
-    String = Buffer;
-    break;
-
-  case EFI_IFR_TYPE_STRING:
-    CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));
-    return EFI_SUCCESS;
-
-  case EFI_IFR_TYPE_BOOLEAN:
-    String = (Value.Value.b) ? L"True" : L"False";
-    break;
-
-  default:
-    return EFI_UNSUPPORTED;
-  }
-
-  Result->Type = EFI_IFR_TYPE_STRING;
-  Result->Value.string = NewString (String, FormSet->HiiHandle);
-  return EFI_SUCCESS;
-}
-
-
-/**
-  Evaluate opcode EFI_IFR_TO_UINT.
-
-  @param  FormSet                Formset which contains this opcode.
-  @param  Result                 Evaluation result for this opcode.
-
-  @retval EFI_SUCCESS            Opcode evaluation success.
-  @retval Other                  Opcode evaluation failed.
-
-**/
-EFI_STATUS
-IfrToUint (
-  IN FORM_BROWSER_FORMSET  *FormSet,
-  OUT  EFI_HII_VALUE       *Result
-  )
-{
-  EFI_STATUS     Status;
-  EFI_HII_VALUE  Value;
-  CHAR16         *String;
-  CHAR16         *StringPtr;
-  UINTN          BufferSize;
-
-  Status = PopExpression (&Value);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  if (Value.Type >= EFI_IFR_TYPE_OTHER) {
-    return EFI_UNSUPPORTED;
-  }
-
-  Status = EFI_SUCCESS;
-  if (Value.Type == EFI_IFR_TYPE_STRING) {
-    String = GetToken (Value.Value.string, FormSet->HiiHandle);
-    if (String == NULL) {
-      return EFI_NOT_FOUND;
-    }
-
-    IfrStrToUpper (String);
-    StringPtr = StrStr (String, L"0X");
-    if (StringPtr != NULL) {
-      //
-      // Hex string
-      //
-      BufferSize = sizeof (UINT64);
-      Status = HexStringToBuf ((UINT8 *) &Result->Value.u64, &BufferSize, StringPtr + 2, NULL);
-    } else {
-      //
-      // BUGBUG: Need handle decimal string
-      //
-    }
-    gBS->FreePool (String);
-  } else {
-    CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));
-  }
-
-  Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
-  return Status;
-}
-
-
-/**
-  Evaluate opcode EFI_IFR_CATENATE.
-
-  @param  FormSet                Formset which contains this opcode.
-  @param  Result                 Evaluation result for this opcode.
-
-  @retval EFI_SUCCESS            Opcode evaluation success.
-  @retval Other                  Opcode evaluation failed.
-
-**/
-EFI_STATUS
-IfrCatenate (
-  IN FORM_BROWSER_FORMSET  *FormSet,
-  OUT  EFI_HII_VALUE       *Result
-  )
-{
-  EFI_STATUS     Status;
-  EFI_HII_VALUE  Value;
-  CHAR16         *String[2];
-  UINTN          Index;
-  CHAR16         *StringPtr;
-  UINTN          Size;
-
-  //
-  // String[0] - The second string
-  // String[1] - The first string
-  //
-  String[0] = NULL;
-  String[1] = NULL;
-  StringPtr = NULL;
-  Status = EFI_SUCCESS;
-
-  for (Index = 0; Index < 2; Index++) {
-    Status = PopExpression (&Value);
-    if (EFI_ERROR (Status)) {
-      goto Done;
-    }
-
-    if (Value.Type != EFI_IFR_TYPE_STRING) {
-      Status = EFI_UNSUPPORTED;
-      goto Done;
-    }
-
-    String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);
-    if (String== NULL) {
-      Status = EFI_NOT_FOUND;
-      goto Done;
-    }
-  }
-
-  Size = StrSize (String[0]);
-  StringPtr= AllocatePool (StrSize (String[1]) + Size);
-  ASSERT (StringPtr != NULL);
-  StrCpy (StringPtr, String[1]);
-  StrCat (StringPtr, String[0]);
-
-  Result->Type = EFI_IFR_TYPE_STRING;
-  Result->Value.string = NewString (StringPtr, FormSet->HiiHandle);
-
-Done:
-  SafeFreePool (String[0]);
-  SafeFreePool (String[1]);
-  SafeFreePool (StringPtr);
-
-  return Status;
-}
-
-
-/**
-  Evaluate opcode EFI_IFR_MATCH.
-
-  @param  FormSet                Formset which contains this opcode.
-  @param  Result                 Evaluation result for this opcode.
-
-  @retval EFI_SUCCESS            Opcode evaluation success.
-  @retval Other                  Opcode evaluation failed.
-
-**/
-EFI_STATUS
-IfrMatch (
-  IN FORM_BROWSER_FORMSET  *FormSet,
-  OUT  EFI_HII_VALUE       *Result
-  )
-{
-  EFI_STATUS     Status;
-  EFI_HII_VALUE  Value;
-  CHAR16         *String[2];
-  UINTN          Index;
-
-  //
-  // String[0] - The string to search
-  // String[1] - pattern
-  //
-  String[0] = NULL;
-  String[1] = NULL;
-  Status = EFI_SUCCESS;
-  for (Index = 0; Index < 2; Index++) {
-    Status = PopExpression (&Value);
-    if (EFI_ERROR (Status)) {
-      goto Done;
-    }
-
-    if (Value.Type != EFI_IFR_TYPE_STRING) {
-      Status = EFI_UNSUPPORTED;
-      goto Done;
-    }
-
-    String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);
-    if (String== NULL) {
-      Status = EFI_NOT_FOUND;
-      goto Done;
-    }
-  }
-
-  Result->Type = EFI_IFR_TYPE_BOOLEAN;
-  Result->Value.b = mUnicodeCollation->MetaiMatch (mUnicodeCollation, String[0], String[1]);
-
-Done:
-  SafeFreePool (String[0]);
-  SafeFreePool (String[1]);
-
-  return Status;
-}
-
-
-/**
-  Evaluate opcode EFI_IFR_FIND.
-
-  @param  FormSet                Formset which contains this opcode.
-  @param  Format                 Case sensitive or insensitive.
-  @param  Result                 Evaluation result for this opcode.
-
-  @retval EFI_SUCCESS            Opcode evaluation success.
-  @retval Other                  Opcode evaluation failed.
-
-**/
-EFI_STATUS
-IfrFind (
-  IN FORM_BROWSER_FORMSET  *FormSet,
-  IN UINT8                 Format,
-  OUT  EFI_HII_VALUE       *Result
-  )
-{
-  EFI_STATUS     Status;
-  EFI_HII_VALUE  Value;
-  CHAR16         *String[2];
-  UINTN          Base;
-  CHAR16         *StringPtr;
-  UINTN          Index;
-
-  if (Format > EFI_IFR_FF_CASE_INSENSITIVE) {
-    return EFI_UNSUPPORTED;
-  }
-
-  Status = PopExpression (&Value);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-  if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {
-    return EFI_UNSUPPORTED;
-  }
-  Base = (UINTN) Value.Value.u64;
-
-  //
-  // String[0] - sub-string
-  // String[1] - The string to search
-  //
-  String[0] = NULL;
-  String[1] = NULL;
-  for (Index = 0; Index < 2; Index++) {
-    Status = PopExpression (&Value);
-    if (EFI_ERROR (Status)) {
-      goto Done;
-    }
-
-    if (Value.Type != EFI_IFR_TYPE_STRING) {
-      Status = EFI_UNSUPPORTED;
-      goto Done;
-    }
-
-    String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);
-    if (String== NULL) {
-      Status = EFI_NOT_FOUND;
-      goto Done;
-    }
-
-    if (Format == EFI_IFR_FF_CASE_INSENSITIVE) {
-      //
-      // Case insensitive, convert both string to upper case
-      //
-      IfrStrToUpper (String[Index]);
-    }
-  }
-
-  Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
-  if (Base >= StrLen (String[1])) {
-    Result->Value.u64 = 0xFFFFFFFFFFFFFFFFULL;
-  } else {
-    StringPtr = StrStr (String[1] + Base, String[0]);
-    Result->Value.u64 = (StringPtr == NULL) ? 0xFFFFFFFFFFFFFFFFULL : (StringPtr - String[1]);
-  }
-
-Done:
-  SafeFreePool (String[0]);
-  SafeFreePool (String[1]);
-
-  return Status;
-}
-
-
-/**
-  Evaluate opcode EFI_IFR_MID.
-
-  @param  FormSet                Formset which contains this opcode.
-  @param  Result                 Evaluation result for this opcode.
-
-  @retval EFI_SUCCESS            Opcode evaluation success.
-  @retval Other                  Opcode evaluation failed.
-
-**/
-EFI_STATUS
-IfrMid (
-  IN FORM_BROWSER_FORMSET  *FormSet,
-  OUT  EFI_HII_VALUE       *Result
-  )
-{
-  EFI_STATUS     Status;
-  EFI_HII_VALUE  Value;
-  CHAR16         *String;
-  UINTN          Base;
-  UINTN          Length;
-  CHAR16         *SubString;
-
-  Status = PopExpression (&Value);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-  if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {
-    return EFI_UNSUPPORTED;
-  }
-  Length = (UINTN) Value.Value.u64;
-
-  Status = PopExpression (&Value);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-  if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {
-    return EFI_UNSUPPORTED;
-  }
-  Base = (UINTN) Value.Value.u64;
-
-  Status = PopExpression (&Value);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-  if (Value.Type != EFI_IFR_TYPE_STRING) {
-    return EFI_UNSUPPORTED;
-  }
-  String = GetToken (Value.Value.string, FormSet->HiiHandle);
-  if (String == NULL) {
-    return EFI_NOT_FOUND;
-  }
-
-  if (Length == 0 || Base >= StrLen (String)) {
-    SubString = gEmptyString;
-  } else {
-    SubString = String + Base;
-    if ((Base + Length) < StrLen (String)) {
-      SubString[Length] = L'\0';
-    }
-  }
-
-  Result->Type = EFI_IFR_TYPE_STRING;
-  Result->Value.string = NewString (SubString, FormSet->HiiHandle);
-
-  gBS->FreePool (String);
-
-  return Status;
-}
-
-
-/**
-  Evaluate opcode EFI_IFR_TOKEN.
-
-  @param  FormSet                Formset which contains this opcode.
-  @param  Result                 Evaluation result for this opcode.
-
-  @retval EFI_SUCCESS            Opcode evaluation success.
-  @retval Other                  Opcode evaluation failed.
-
-**/
-EFI_STATUS
-IfrToken (
-  IN FORM_BROWSER_FORMSET  *FormSet,
-  OUT  EFI_HII_VALUE       *Result
-  )
-{
-  EFI_STATUS     Status;
-  EFI_HII_VALUE  Value;
-  CHAR16         *String[2];
-  UINTN          Count;
-  CHAR16         *Delimiter;
-  CHAR16         *SubString;
-  CHAR16         *StringPtr;
-  UINTN          Index;
-
-  Status = PopExpression (&Value);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-  if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {
-    return EFI_UNSUPPORTED;
-  }
-  Count = (UINTN) Value.Value.u64;
-
-  //
-  // String[0] - Delimiter
-  // String[1] - The string to search
-  //
-  String[0] = NULL;
-  String[1] = NULL;
-  for (Index = 0; Index < 2; Index++) {
-    Status = PopExpression (&Value);
-    if (EFI_ERROR (Status)) {
-      goto Done;
-    }
-
-    if (Value.Type != EFI_IFR_TYPE_STRING) {
-      Status = EFI_UNSUPPORTED;
-      goto Done;
-    }
-
-    String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);
-    if (String== NULL) {
-      Status = EFI_NOT_FOUND;
-      goto Done;
-    }
-  }
-
-  Delimiter = String[0];
-  SubString = String[1];
-  while (Count > 0) {
-    SubString = StrStr (SubString, Delimiter);
-    if (SubString != NULL) {
-      //
-      // Skip over the delimiter
-      //
-      SubString = SubString + StrLen (Delimiter);
-    } else {
-      break;
-    }
-    Count--;
-  }
-
-  if (SubString == NULL) {
-    //
-    // nth delimited sub-string not found, push an empty string
-    //
-    SubString = gEmptyString;
-  } else {
-    //
-    // Put a NULL terminator for nth delimited sub-string
-    //
-    StringPtr = StrStr (SubString, Delimiter);
-    if (StringPtr != NULL) {
-      *StringPtr = L'\0';
-    }
-  }
-
-  Result->Type = EFI_IFR_TYPE_STRING;
-  Result->Value.string = NewString (SubString, FormSet->HiiHandle);
-
-Done:
-  SafeFreePool (String[0]);
-  SafeFreePool (String[1]);
-
-  return Status;
-}
-
-
-/**
-  Evaluate opcode EFI_IFR_SPAN.
-
-  @param  FormSet                Formset which contains this opcode.
-  @param  Flags                  FIRST_MATCHING or FIRST_NON_MATCHING.
-  @param  Result                 Evaluation result for this opcode.
-
-  @retval EFI_SUCCESS            Opcode evaluation success.
-  @retval Other                  Opcode evaluation failed.
-
-**/
-EFI_STATUS
-IfrSpan (
-  IN FORM_BROWSER_FORMSET  *FormSet,
-  IN UINT8                 Flags,
-  OUT  EFI_HII_VALUE       *Result
-  )
-{
-  EFI_STATUS     Status;
-  EFI_HII_VALUE  Value;
-  CHAR16         *String[2];
-  CHAR16         *Charset;
-  UINTN          Base;
-  UINTN          Index;
-  CHAR16         *StringPtr;
-  BOOLEAN        Found;
-
-  Status = PopExpression (&Value);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-  if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {
-    return EFI_UNSUPPORTED;
-  }
-  Base = (UINTN) Value.Value.u64;
-
-  //
-  // String[0] - Charset
-  // String[1] - The string to search
-  //
-  String[0] = NULL;
-  String[1] = NULL;
-  for (Index = 0; Index < 2; Index++) {
-    Status = PopExpression (&Value);
-    if (EFI_ERROR (Status)) {
-      goto Done;
-    }
-
-    if (Value.Type != EFI_IFR_TYPE_STRING) {
-      Status = EFI_UNSUPPORTED;
-      goto Done;
-    }
-
-    String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);
-    if (String== NULL) {
-      Status = EFI_NOT_FOUND;
-      goto Done;
-    }
-  }
-
-  if (Base >= StrLen (String[1])) {
-    Status = EFI_UNSUPPORTED;
-    goto Done;
-  }
-
-  Found = FALSE;
-  StringPtr = String[1] + Base;
-  Charset = String[0];
-  while (*StringPtr != 0 && !Found) {
-    Index = 0;
-    while (Charset[Index] != 0) {
-      if (*StringPtr >= Charset[Index] && *StringPtr <= Charset[Index + 1]) {
-        if (Flags == EFI_IFR_FLAGS_FIRST_MATCHING) {
-          Found = TRUE;
-          break;
-        }
-      } else {
-        if (Flags == EFI_IFR_FLAGS_FIRST_NON_MATCHING) {
-          Found = TRUE;
-          break;
-        }
-      }
-      //
-      // Skip characters pair representing low-end of a range and high-end of a range
-      //
-      Index += 2;
-    }
-
-    if (!Found) {
-      StringPtr++;
-    }
-  }
-
-  Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
-  Result->Value.u64 = StringPtr - String[1];
-
-Done:
-  SafeFreePool (String[0]);
-  SafeFreePool (String[1]);
-
-  return Status;
-}
-
-
-/**
-  Zero extend integer/boolean/date/time to UINT64 for comparing.
-
-  @param  Value                  HII Value to be converted.
-
-  @return None.
-
-**/
-VOID
-ExtendValueToU64 (
-  IN  EFI_HII_VALUE   *Value
-  )
-{
-  UINT64  Temp;
-
-  Temp = 0;
-  switch (Value->Type) {
-  case EFI_IFR_TYPE_NUM_SIZE_8:
-    Temp = Value->Value.u8;
-    break;
-
-  case EFI_IFR_TYPE_NUM_SIZE_16:
-    Temp = Value->Value.u16;
-    break;
-
-  case EFI_IFR_TYPE_NUM_SIZE_32:
-    Temp = Value->Value.u32;
-    break;
-
-  case EFI_IFR_TYPE_BOOLEAN:
-    Temp = Value->Value.b;
-    break;
-
-  case EFI_IFR_TYPE_TIME:
-    Temp = Value->Value.u32 & 0xffffff;
-    break;
-
-  case EFI_IFR_TYPE_DATE:
-    Temp = Value->Value.u32;
-    break;
-
-  default:
-    return;
-  }
-
-  Value->Value.u64 = Temp;
-}
-
-
-/**
-  Compare two Hii value.
-
-  @param  Value1                 Expression value to compare on left-hand
-  @param  Value2                 Expression value to compare on right-hand
-  @param  HiiHandle              Only required for string compare
-
-  @retval EFI_INVALID_PARAMETER  Could not perform comparation on two values
-  @retval 0                      Two operators equeal
-  @retval 0                      Value1 is greater than Value2
-  @retval 0                      Value1 is less than Value2
-
-**/
-INTN
-CompareHiiValue (
-  IN  EFI_HII_VALUE   *Value1,
-  IN  EFI_HII_VALUE   *Value2,
-  IN  EFI_HII_HANDLE  HiiHandle OPTIONAL
-  )
-{
-  INTN    Result;
-  INT64   Temp64;
-  CHAR16  *Str1;
-  CHAR16  *Str2;
-
-  if (Value1->Type >= EFI_IFR_TYPE_OTHER || Value2->Type >= EFI_IFR_TYPE_OTHER ) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  if (Value1->Type == EFI_IFR_TYPE_STRING || Value2->Type == EFI_IFR_TYPE_STRING ) {
-    if (Value1->Type != Value2->Type) {
-      //
-      // Both Operator should be type of String
-      //
-      return EFI_INVALID_PARAMETER;
-    }
-
-    if (Value1->Value.string == 0 || Value2->Value.string == 0) {
-      //
-      // StringId 0 is reserved
-      //
-      return EFI_INVALID_PARAMETER;
-    }
-
-    if (Value1->Value.string == Value2->Value.string) {
-      return 0;
-    }
-
-    Str1 = GetToken (Value1->Value.string, HiiHandle);
-    if (Str1 == NULL) {
-      //
-      // String not found
-      //
-      return EFI_INVALID_PARAMETER;
-    }
-
-    Str2 = GetToken (Value2->Value.string, HiiHandle);
-    if (Str2 == NULL) {
-      gBS->FreePool (Str1);
-      return EFI_INVALID_PARAMETER;
-    }
-
-    Result = StrCmp (Str1, Str2);
-
-    gBS->FreePool (Str1);
-    gBS->FreePool (Str2);
-
-    return Result;
-  }
-
-  //
-  // Take remain types(integer, boolean, date/time) as integer
-  //
-  Temp64 = (INT64) (Value1->Value.u64 - Value2->Value.u64);
-  if (Temp64 > 0) {
-    Result = 1;
-  } else if (Temp64 < 0) {
-    Result = -1;
-  } else {
-    Result = 0;
-  }
-
-  return Result;
-}
-
-
-/**
-  Evaluate the result of a HII expression
-
-  @param  FormSet                FormSet associated with this expression.
-  @param  Form                   Form associated with this expression.
-  @param  Expression             Expression to be evaluated.
-
-  @retval EFI_SUCCESS            The expression evaluated successfuly
-  @retval EFI_NOT_FOUND          The Question which referenced by a QuestionId
-                                 could not be found.
-  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the
-                                 stack.
-  @retval EFI_ACCESS_DENIED      The pop operation underflowed the stack
-  @retval EFI_INVALID_PARAMETER  Syntax error with the Expression
-
-**/
-EFI_STATUS
-EvaluateExpression (
-  IN FORM_BROWSER_FORMSET  *FormSet,
-  IN FORM_BROWSER_FORM     *Form,
-  IN OUT FORM_EXPRESSION   *Expression
-  )
-{
-  EFI_STATUS              Status;
-  LIST_ENTRY              *Link;
-  EXPRESSION_OPCODE       *OpCode;
-  FORM_BROWSER_STATEMENT  *Question;
-  FORM_BROWSER_STATEMENT  *Question2;
-  UINT16                  Index;
-  EFI_HII_VALUE           Data1;
-  EFI_HII_VALUE           Data2;
-  EFI_HII_VALUE           Data3;
-  FORM_EXPRESSION         *RuleExpression;
-  EFI_HII_VALUE           *Value;
-  INTN                    Result;
-  CHAR16                  *StrPtr;
-  UINT32                  TempValue;
-
-  //
-  // Always reset the stack before evaluating an Expression
-  //
-  ResetExpressionStack ();
-
-  Expression->Result.Type = EFI_IFR_TYPE_OTHER;
-
-  Link = GetFirstNode (&Expression->OpCodeListHead);
-  while (!IsNull (&Expression->OpCodeListHead, Link)) {
-    OpCode = EXPRESSION_OPCODE_FROM_LINK (Link);
-
-    Link = GetNextNode (&Expression->OpCodeListHead, Link);
-
-    ZeroMem (&Data1, sizeof (EFI_HII_VALUE));
-    ZeroMem (&Data2, sizeof (EFI_HII_VALUE));
-    ZeroMem (&Data3, sizeof (EFI_HII_VALUE));
-
-    Value = &Data3;
-    Value->Type = EFI_IFR_TYPE_BOOLEAN;
-    Status = EFI_SUCCESS;
-
-    switch (OpCode->Operand) {
-    //
-    // Built-in functions
-    //
-    case EFI_IFR_EQ_ID_VAL_OP:
-      Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
-      if (Question == NULL) {
-        return EFI_NOT_FOUND;
-      }
-
-      Result = CompareHiiValue (&Question->HiiValue, &OpCode->Value, NULL);
-      if (Result == EFI_INVALID_PARAMETER) {
-        return EFI_INVALID_PARAMETER;
-      }
-      Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);
-      break;
-
-    case EFI_IFR_EQ_ID_ID_OP:
-      Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
-      if (Question == NULL) {
-        return EFI_NOT_FOUND;
-      }
-
-      Question2 = IdToQuestion (FormSet, Form, OpCode->QuestionId2);
-      if (Question2 == NULL) {
-        return EFI_NOT_FOUND;
-      }
-
-      Result = CompareHiiValue (&Question->HiiValue, &Question2->HiiValue, FormSet->HiiHandle);
-      if (Result == EFI_INVALID_PARAMETER) {
-        return EFI_INVALID_PARAMETER;
-      }
-      Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);
-      break;
-
-    case EFI_IFR_EQ_ID_LIST_OP:
-      Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
-      if (Question == NULL) {
-        return EFI_NOT_FOUND;
-      }
-
-      Value->Value.b = FALSE;
-      for (Index =0; Index < OpCode->ListLength; Index++) {
-        if (Question->HiiValue.Value.u16 == OpCode->ValueList[Index]) {
-          Value->Value.b = TRUE;
-          break;
-        }
-      }
-      break;
-
-    case EFI_IFR_DUP_OP:
-      Status = PopExpression (Value);
-      if (EFI_ERROR (Status)) {
-        return Status;
-      }
-
-      Status = PushExpression (Value);
-      break;
-
-    case EFI_IFR_QUESTION_REF1_OP:
-    case EFI_IFR_THIS_OP:
-      Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
-      if (Question == NULL) {
-        return EFI_NOT_FOUND;
-      }
-
-      Value = &Question->HiiValue;
-      break;
-
-    case EFI_IFR_QUESTION_REF3_OP:
-      if (OpCode->DevicePath == 0) {
-        //
-        // EFI_IFR_QUESTION_REF3
-        // Pop an expression from the expression stack
-        //
-        Status = PopExpression (Value);
-        if (EFI_ERROR (Status)) {
-          return Status;
-        }
-
-        //
-        // Validate the expression value
-        //
-        if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
-          return EFI_NOT_FOUND;
-        }
-
-        Question = IdToQuestion (FormSet, Form, Value->Value.u16);
-        if (Question == NULL) {
-          return EFI_NOT_FOUND;
-        }
-
-        //
-        // push the questions' value on to the expression stack
-        //
-        Value = &Question->HiiValue;
-      } else {
-        //
-        // BUGBUG: push 0 for EFI_IFR_QUESTION_REF3_2 and EFI_IFR_QUESTION_REF3_3,
-        // since it is impractical to evaluate the value of a Question in another
-        // Hii Package list.
-        //
-        ZeroMem (Value, sizeof (EFI_HII_VALUE));
-      }
-      break;
-
-    case EFI_IFR_RULE_REF_OP:
-      //
-      // Find expression for this rule
-      //
-      RuleExpression = RuleIdToExpression (Form, OpCode->RuleId);
-      if (RuleExpression == NULL) {
-        return EFI_NOT_FOUND;
-      }
-
-      //
-      // Evaluate this rule expression
-      //
-      Status = EvaluateExpression (FormSet, Form, RuleExpression);
-      if (EFI_ERROR (Status)) {
-        return Status;
-      }
-
-      Value = &RuleExpression->Result;
-      break;
-
-    case EFI_IFR_STRING_REF1_OP:
-      Value->Type = EFI_IFR_TYPE_STRING;
-      Value->Value.string = OpCode->Value.Value.string;
-      break;
-
-    //
-    // Constant
-    //
-    case EFI_IFR_TRUE_OP:
-    case EFI_IFR_FALSE_OP:
-    case EFI_IFR_ONE_OP:
-    case EFI_IFR_ONES_OP:
-    case EFI_IFR_UINT8_OP:
-    case EFI_IFR_UINT16_OP:
-    case EFI_IFR_UINT32_OP:
-    case EFI_IFR_UINT64_OP:
-    case EFI_IFR_UNDEFINED_OP:
-    case EFI_IFR_VERSION_OP:
-    case EFI_IFR_ZERO_OP:
-      Value = &OpCode->Value;
-      break;
-
-    //
-    // unary-op
-    //
-    case EFI_IFR_LENGTH_OP:
-      Status = PopExpression (Value);
-      if (EFI_ERROR (Status)) {
-        return Status;
-      }
-      if (Value->Type != EFI_IFR_TYPE_STRING) {
-        return EFI_INVALID_PARAMETER;
-      }
-
-      StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);
-      if (StrPtr == NULL) {
-        return EFI_INVALID_PARAMETER;
-      }
-
-      Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
-      Value->Value.u64 = StrLen (StrPtr);
-      gBS->FreePool (StrPtr);
-      break;
-
-    case EFI_IFR_NOT_OP:
-      Status = PopExpression (Value);
-      if (EFI_ERROR (Status)) {
-        return Status;
-      }
-      if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {
-        return EFI_INVALID_PARAMETER;
-      }
-      Value->Value.b = (BOOLEAN) (!Value->Value.b);
-      break;
-
-    case EFI_IFR_QUESTION_REF2_OP:
-      //
-      // Pop an expression from the expression stack
-      //
-      Status = PopExpression (Value);
-      if (EFI_ERROR (Status)) {
-        return Status;
-      }
-
-      //
-      // Validate the expression value
-      //
-      if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
-        return EFI_NOT_FOUND;
-      }
-
-      Question = IdToQuestion (FormSet, Form, Value->Value.u16);
-      if (Question == NULL) {
-        return EFI_NOT_FOUND;
-      }
-
-      Value = &Question->HiiValue;
-      break;
-
-    case EFI_IFR_STRING_REF2_OP:
-      //
-      // Pop an expression from the expression stack
-      //
-      Status = PopExpression (Value);
-      if (EFI_ERROR (Status)) {
-        return Status;
-      }
-
-      //
-      // Validate the expression value
-      //
-      if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
-        return EFI_NOT_FOUND;
-      }
-
-      Value->Type = EFI_IFR_TYPE_STRING;
-      StrPtr = GetToken (Value->Value.u16, FormSet->HiiHandle);
-      if (StrPtr == NULL) {
-        //
-        // If String not exit, push an empty string
-        //
-        Value->Value.string = NewString (gEmptyString, FormSet->HiiHandle);
-      } else {
-        Index = (UINT16) Value->Value.u64;
-        Value->Value.string = Index;
-        gBS->FreePool (StrPtr);
-      }
-      break;
-
-    case EFI_IFR_TO_BOOLEAN_OP:
-      //
-      // Pop an expression from the expression stack
-      //
-      Status = PopExpression (Value);
-      if (EFI_ERROR (Status)) {
-        return Status;
-      }
-
-      //
-      // Convert an expression to a Boolean
-      //
-      if (Value->Type <= EFI_IFR_TYPE_DATE) {
-        //
-        // When converting from an unsigned integer, zero will be converted to
-        // FALSE and any other value will be converted to TRUE.
-        //
-        Value->Value.b = (BOOLEAN) ((Value->Value.u64) ? TRUE : FALSE);
-
-        Value->Type = EFI_IFR_TYPE_BOOLEAN;
-      } else if (Value->Type == EFI_IFR_TYPE_STRING) {
-        //
-        // When converting from a string, if case-insensitive compare
-        // with "true" is True, then push True. If a case-insensitive compare
-        // with "false" is True, then push False.
-        //
-        StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);
-        if (StrPtr == NULL) {
-          return EFI_INVALID_PARAMETER;
-        }
-
-        if ((StrCmp (StrPtr, L"true") == 0) || (StrCmp (StrPtr, L"false") == 0)){
-          Value->Value.b = TRUE;
-        } else {
-          Value->Value.b = FALSE;
-        }
-        gBS->FreePool (StrPtr);
-        Value->Type = EFI_IFR_TYPE_BOOLEAN;
-      }
-      break;
-
-    case EFI_IFR_TO_STRING_OP:
-      Status = IfrToString (FormSet, OpCode->Format, Value);
-      break;
-
-    case EFI_IFR_TO_UINT_OP:
-      Status = IfrToUint (FormSet, Value);
-      break;
-
-    case EFI_IFR_TO_LOWER_OP:
-    case EFI_IFR_TO_UPPER_OP:
-      Status = InitializeUnicodeCollationProtocol ();
-      if (EFI_ERROR (Status)) {
-        return Status;
-      }
-
-      Status = PopExpression (Value);
-      if (EFI_ERROR (Status)) {
-        return Status;
-      }
-
-      if (Value->Type != EFI_IFR_TYPE_STRING) {
-        return EFI_UNSUPPORTED;
-      }
-
-      StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);
-      if (StrPtr == NULL) {
-        return EFI_NOT_FOUND;
-      }
-
-      if (OpCode->Operand == EFI_IFR_TO_LOWER_OP) {
-        mUnicodeCollation->StrLwr (mUnicodeCollation, StrPtr);
-      } else {
-        mUnicodeCollation->StrUpr (mUnicodeCollation, StrPtr);
-      }
-      Value->Value.string = NewString (StrPtr, FormSet->HiiHandle);
-      gBS->FreePool (StrPtr);
-      break;
-
-    case EFI_IFR_BITWISE_NOT_OP:
-      //
-      // Pop an expression from the expression stack
-      //
-      Status = PopExpression (Value);
-      if (EFI_ERROR (Status)) {
-        return Status;
-      }
-      if (Value->Type > EFI_IFR_TYPE_DATE) {
-        return EFI_INVALID_PARAMETER;
-      }
-
-      Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
-      Value->Value.u64 = ~Value->Value.u64;
-      break;
-
-    //
-    // binary-op
-    //
-    case EFI_IFR_ADD_OP:
-    case EFI_IFR_SUBTRACT_OP:
-    case EFI_IFR_MULTIPLY_OP:
-    case EFI_IFR_DIVIDE_OP:
-    case EFI_IFR_MODULO_OP:
-    case EFI_IFR_BITWISE_AND_OP:
-    case EFI_IFR_BITWISE_OR_OP:
-    case EFI_IFR_SHIFT_LEFT_OP:
-    case EFI_IFR_SHIFT_RIGHT_OP:
-      //
-      // Pop an expression from the expression stack
-      //
-      Status = PopExpression (&Data2);
-      if (EFI_ERROR (Status)) {
-        return Status;
-      }
-      if (Data2.Type > EFI_IFR_TYPE_DATE) {
-        return EFI_INVALID_PARAMETER;
-      }
-
-      //
-      // Pop another expression from the expression stack
-      //
-      Status = PopExpression (&Data1);
-      if (EFI_ERROR (Status)) {
-        return Status;
-      }
-      if (Data1.Type > EFI_IFR_TYPE_DATE) {
-        return EFI_INVALID_PARAMETER;
-      }
-
-      Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
-
-      switch (OpCode->Operand) {
-        case EFI_IFR_ADD_OP:
-          Value->Value.u64 = Data1.Value.u64 + Data2.Value.u64;
-          break;
-
-        case EFI_IFR_SUBTRACT_OP:
-          Value->Value.u64 = Data1.Value.u64 - Data2.Value.u64;
-          break;
-
-        case EFI_IFR_MULTIPLY_OP:
-          Value->Value.u64 = MultU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);
-          break;
-
-        case EFI_IFR_DIVIDE_OP:
-          Value->Value.u64 = DivU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);
-          break;
-
-        case EFI_IFR_MODULO_OP:
-          DivU64x32Remainder  (Data1.Value.u64, (UINT32) Data2.Value.u64, &TempValue);
-          Value->Value.u64 = TempValue;
-          break;
-
-        case EFI_IFR_BITWISE_AND_OP:
-          Value->Value.u64 = Data1.Value.u64 & Data2.Value.u64;
-          break;
-
-        case EFI_IFR_BITWISE_OR_OP:
-          Value->Value.u64 = Data1.Value.u64 | Data2.Value.u64;
-          break;
-
-        case EFI_IFR_SHIFT_LEFT_OP:
-          Value->Value.u64 = LShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);
-          break;
-
-        case EFI_IFR_SHIFT_RIGHT_OP:
-          Value->Value.u64 = RShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);
-          break;
-
-        default:
-          break;
-      }
-      break;
-
-    case EFI_IFR_AND_OP:
-    case EFI_IFR_OR_OP:
-      //
-      // Two Boolean operator
-      //
-      Status = PopExpression (&Data2);
-      if (EFI_ERROR (Status)) {
-        return Status;
-      }
-      if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {
-        return EFI_INVALID_PARAMETER;
-      }
-
-      //
-      // Pop another expression from the expression stack
-      //
-      Status = PopExpression (&Data1);
-      if (EFI_ERROR (Status)) {
-        return Status;
-      }
-      if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {
-        return EFI_INVALID_PARAMETER;
-      }
-
-      if (OpCode->Operand == EFI_IFR_AND_OP) {
-        Value->Value.b = (BOOLEAN) (Data1.Value.b && Data2.Value.b);
-      } else {
-        Value->Value.b = (BOOLEAN) (Data1.Value.b || Data2.Value.b);
-      }
-      break;
-
-    case EFI_IFR_EQUAL_OP:
-    case EFI_IFR_NOT_EQUAL_OP:
-    case EFI_IFR_GREATER_EQUAL_OP:
-    case EFI_IFR_GREATER_THAN_OP:
-    case EFI_IFR_LESS_EQUAL_OP:
-    case EFI_IFR_LESS_THAN_OP:
-      //
-      // Compare two integer, string, boolean or date/time
-      //
-      Status = PopExpression (&Data2);
-      if (EFI_ERROR (Status)) {
-        return Status;
-      }
-      if (Data2.Type > EFI_IFR_TYPE_BOOLEAN && Data2.Type != EFI_IFR_TYPE_STRING) {
-        return EFI_INVALID_PARAMETER;
-      }
-
-      //
-      // Pop another expression from the expression stack
-      //
-      Status = PopExpression (&Data1);
-      if (EFI_ERROR (Status)) {
-        return Status;
-      }
-
-      Result = CompareHiiValue (&Data1, &Data2, FormSet->HiiHandle);
-      if (Result == EFI_INVALID_PARAMETER) {
-        return EFI_INVALID_PARAMETER;
-      }
-
-      switch (OpCode->Operand) {
-      case EFI_IFR_EQUAL_OP:
-        Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);
-        break;
-
-      case EFI_IFR_NOT_EQUAL_OP:
-        Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);
-        break;
-
-      case EFI_IFR_GREATER_EQUAL_OP:
-        Value->Value.b = (BOOLEAN) ((Result >= 0) ? TRUE : FALSE);
-        break;
-
-      case EFI_IFR_GREATER_THAN_OP:
-        Value->Value.b = (BOOLEAN) ((Result > 0) ? TRUE : FALSE);
-        break;
-
-      case EFI_IFR_LESS_EQUAL_OP:
-        Value->Value.b = (BOOLEAN) ((Result <= 0) ? TRUE : FALSE);
-        break;
-
-      case EFI_IFR_LESS_THAN_OP:
-        Value->Value.b = (BOOLEAN) ((Result < 0) ? TRUE : FALSE);
-        break;
-
-      default:
-        break;
-      }
-      break;
-
-    case EFI_IFR_MATCH_OP:
-      Status = IfrMatch (FormSet, Value);
-      break;
-
-    case EFI_IFR_CATENATE_OP:
-      Status = IfrCatenate (FormSet, Value);
-      break;
-
-    //
-    // ternary-op
-    //
-    case EFI_IFR_CONDITIONAL_OP:
-      //
-      // Pop third expression from the expression stack
-      //
-      Status = PopExpression (&Data3);
-      if (EFI_ERROR (Status)) {
-        return Status;
-      }
-
-      //
-      // Pop second expression from the expression stack
-      //
-      Status = PopExpression (&Data2);
-      if (EFI_ERROR (Status)) {
-        return Status;
-      }
-
-      //
-      // Pop first expression from the expression stack
-      //
-      Status = PopExpression (&Data1);
-      if (EFI_ERROR (Status)) {
-        return Status;
-      }
-      if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {
-        return EFI_INVALID_PARAMETER;
-      }
-
-      if (Data1.Value.b) {
-        Value = &Data3;
-      } else {
-        Value = &Data2;
-      }
-      break;
-
-    case EFI_IFR_FIND_OP:
-      Status = IfrFind (FormSet, OpCode->Format, Value);
-      break;
-
-    case EFI_IFR_MID_OP:
-      Status = IfrMid (FormSet, Value);
-      break;
-
-    case EFI_IFR_TOKEN_OP:
-      Status = IfrToken (FormSet, Value);
-      break;
-
-    case EFI_IFR_SPAN_OP:
-      Status = IfrSpan (FormSet, OpCode->Flags, Value);
-      break;
-
-    default:
-      break;
-    }
-    if (EFI_ERROR (Status)) {
-      return Status;
-    }
-
-    Status = PushExpression (Value);
-    if (EFI_ERROR (Status)) {
-      return Status;
-    }
-  }
-
-  //
-  // Pop the final result from expression stack
-  //
-  Value = &Data1;
-  Status = PopExpression (Value);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  //
-  // After evaluating an expression, there should be only one value left on the expression stack
-  //
-  if (PopExpression (Value) != EFI_ACCESS_DENIED) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));
-
-  return EFI_SUCCESS;
-}
+/** @file\r
+Utility functions for expression evaluation.\r
+\r
+Copyright (c) 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "Ui.h"\r
+#include "Setup.h"\r
+\r
+//\r
+// Global stack used to evaluate boolean expresions\r
+//\r
+EFI_HII_VALUE *mOpCodeScopeStack = NULL;\r
+EFI_HII_VALUE *mOpCodeScopeStackEnd = NULL;\r
+EFI_HII_VALUE *mOpCodeScopeStackPointer = NULL;\r
+\r
+EFI_HII_VALUE *mExpressionEvaluationStack = NULL;\r
+EFI_HII_VALUE *mExpressionEvaluationStackEnd = NULL;\r
+EFI_HII_VALUE *mExpressionEvaluationStackPointer = NULL;\r
+\r
+//\r
+// Unicode collation protocol interface\r
+//\r
+EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollation = NULL;\r
+\r
+\r
+/**\r
+  Grow size of the stack.\r
+\r
+  This is an internal function.\r
+\r
+  @param  Stack                  On input: old stack; On output: new stack\r
+  @param  StackPtr               On input: old stack pointer; On output: new stack\r
+                                 pointer\r
+  @param  StackEnd               On input: old stack end; On output: new stack end\r
+\r
+  @retval EFI_SUCCESS            Grow stack success.\r
+  @retval EFI_OUT_OF_RESOURCES   No enough memory for stack space.\r
+\r
+**/\r
+EFI_STATUS\r
+GrowStack (\r
+  IN OUT EFI_HII_VALUE  **Stack,\r
+  IN OUT EFI_HII_VALUE  **StackPtr,\r
+  IN OUT EFI_HII_VALUE  **StackEnd\r
+  )\r
+{\r
+  UINTN           Size;\r
+  EFI_HII_VALUE  *NewStack;\r
+\r
+  Size = EXPRESSION_STACK_SIZE_INCREMENT;\r
+  if (*StackPtr != NULL) {\r
+    Size = Size + (*StackEnd - *Stack);\r
+  }\r
+\r
+  NewStack = AllocatePool (Size * sizeof (EFI_HII_VALUE));\r
+  if (NewStack == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  if (*StackPtr != NULL) {\r
+    //\r
+    // Copy from Old Stack to the New Stack\r
+    //\r
+    CopyMem (\r
+      NewStack,\r
+      *Stack,\r
+      (*StackEnd - *Stack) * sizeof (EFI_HII_VALUE)\r
+      );\r
+\r
+    //\r
+    // Free The Old Stack\r
+    //\r
+    gBS->FreePool (*Stack);\r
+  }\r
+\r
+  //\r
+  // Make the Stack pointer point to the old data in the new stack\r
+  //\r
+  *StackPtr = NewStack + (*StackPtr - *Stack);\r
+  *Stack    = NewStack;\r
+  *StackEnd = NewStack + Size;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Push an element onto the Boolean Stack.\r
+\r
+  @param  Stack                  On input: old stack; On output: new stack\r
+  @param  StackPtr               On input: old stack pointer; On output: new stack\r
+                                 pointer\r
+  @param  StackEnd               On input: old stack end; On output: new stack end\r
+  @param  Data                   Data to push.\r
+\r
+  @retval EFI_SUCCESS            Push stack success.\r
+\r
+**/\r
+EFI_STATUS\r
+PushStack (\r
+  IN OUT EFI_HII_VALUE       **Stack,\r
+  IN OUT EFI_HII_VALUE       **StackPtr,\r
+  IN OUT EFI_HII_VALUE       **StackEnd,\r
+  IN EFI_HII_VALUE           *Data\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // Check for a stack overflow condition\r
+  //\r
+  if (*StackPtr >= *StackEnd) {\r
+    //\r
+    // Grow the stack\r
+    //\r
+    Status = GrowStack (Stack, StackPtr, StackEnd);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Push the item onto the stack\r
+  //\r
+  CopyMem (*StackPtr, Data, sizeof (EFI_HII_VALUE));\r
+  *StackPtr = *StackPtr + 1;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Pop an element from the stack.\r
+\r
+  @param  Stack                  On input: old stack; On output: new stack\r
+  @param  StackPtr               On input: old stack pointer; On output: new stack\r
+                                 pointer\r
+  @param  StackEnd               On input: old stack end; On output: new stack end\r
+  @param  Data                   Data to pop.\r
+\r
+  @retval EFI_SUCCESS            The value was popped onto the stack.\r
+  @retval EFI_ACCESS_DENIED      The pop operation underflowed the stack\r
+\r
+**/\r
+EFI_STATUS\r
+PopStack (\r
+  IN OUT EFI_HII_VALUE       **Stack,\r
+  IN OUT EFI_HII_VALUE       **StackPtr,\r
+  IN OUT EFI_HII_VALUE       **StackEnd,\r
+  OUT EFI_HII_VALUE          *Data\r
+  )\r
+{\r
+  //\r
+  // Check for a stack underflow condition\r
+  //\r
+  if (*StackPtr == *Stack) {\r
+    return EFI_ACCESS_DENIED;\r
+  }\r
+\r
+  //\r
+  // Pop the item off the stack\r
+  //\r
+  *StackPtr = *StackPtr - 1;\r
+  CopyMem (Data, *StackPtr, sizeof (EFI_HII_VALUE));\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Reset stack pointer to begin of the stack.\r
+\r
+**/\r
+VOID\r
+ResetScopeStack (\r
+  VOID\r
+  )\r
+{\r
+  mOpCodeScopeStackPointer = mOpCodeScopeStack;\r
+}\r
+\r
+\r
+/**\r
+  Push an Operand onto the Stack\r
+\r
+  @param  Operand                Operand to push.\r
+\r
+  @retval EFI_SUCCESS            The value was pushed onto the stack.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the\r
+                                 stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushScope (\r
+  IN UINT8   Operand\r
+  )\r
+{\r
+  EFI_HII_VALUE  Data;\r
+\r
+  Data.Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
+  Data.Value.u8 = Operand;\r
+\r
+  return PushStack (\r
+           &mOpCodeScopeStack,\r
+           &mOpCodeScopeStackPointer,\r
+           &mOpCodeScopeStackEnd,\r
+           &Data\r
+           );\r
+}\r
+\r
+\r
+/**\r
+  Pop an Operand from the Stack\r
+\r
+  @param  Operand                Operand to pop.\r
+\r
+  @retval EFI_SUCCESS            The value was pushed onto the stack.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the\r
+                                 stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopScope (\r
+  OUT UINT8     *Operand\r
+  )\r
+{\r
+  EFI_STATUS     Status;\r
+  EFI_HII_VALUE  Data;\r
+\r
+  Status = PopStack (\r
+             &mOpCodeScopeStack,\r
+             &mOpCodeScopeStackPointer,\r
+             &mOpCodeScopeStackEnd,\r
+             &Data\r
+             );\r
+\r
+  *Operand = Data.Value.u8;\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Reset stack pointer to begin of the stack.\r
+\r
+**/\r
+VOID\r
+ResetExpressionStack (\r
+  VOID\r
+  )\r
+{\r
+  mExpressionEvaluationStackPointer = mExpressionEvaluationStack;\r
+}\r
+\r
+\r
+/**\r
+  Push an Expression value onto the Stack\r
+\r
+  @param  Value                  Expression value to push.\r
+\r
+  @retval EFI_SUCCESS            The value was pushed onto the stack.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the\r
+                                 stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushExpression (\r
+  IN EFI_HII_VALUE  *Value\r
+  )\r
+{\r
+  return PushStack (\r
+           &mExpressionEvaluationStack,\r
+           &mExpressionEvaluationStackPointer,\r
+           &mExpressionEvaluationStackEnd,\r
+           Value\r
+           );\r
+}\r
+\r
+\r
+/**\r
+  Pop an Expression value from the stack.\r
+\r
+  @param  Value                  Expression value to pop.\r
+\r
+  @retval EFI_SUCCESS            The value was popped onto the stack.\r
+  @retval EFI_ACCESS_DENIED      The pop operation underflowed the stack\r
+\r
+**/\r
+EFI_STATUS\r
+PopExpression (\r
+  OUT EFI_HII_VALUE  *Value\r
+  )\r
+{\r
+  return PopStack (\r
+           &mExpressionEvaluationStack,\r
+           &mExpressionEvaluationStackPointer,\r
+           &mExpressionEvaluationStackEnd,\r
+           Value\r
+           );\r
+}\r
+\r
+\r
+/**\r
+  Get Form given its FormId.\r
+\r
+  @param  FormSet                The formset which contains this form.\r
+  @param  FormId                 Id of this form.\r
+\r
+  @retval Pointer                The form.\r
+  @retval NULL                   Specified Form is not found in the formset.\r
+\r
+**/\r
+FORM_BROWSER_FORM *\r
+IdToForm (\r
+  IN FORM_BROWSER_FORMSET  *FormSet,\r
+  IN UINT16                FormId\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
+\r
+    if (Form->FormId == FormId) {\r
+      return Form;\r
+    }\r
+\r
+    Link = GetNextNode (&FormSet->FormListHead, Link);\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+\r
+/**\r
+  Search a Question in Form scope using its QuestionId.\r
+\r
+  @param  Form                   The form which contains this Question.\r
+  @param  QuestionId             Id of this Question.\r
+\r
+  @retval Pointer                The Question.\r
+  @retval NULL                   Specified Question not found in the form.\r
+\r
+**/\r
+FORM_BROWSER_STATEMENT *\r
+IdToQuestion2 (\r
+  IN FORM_BROWSER_FORM  *Form,\r
+  IN UINT16             QuestionId\r
+  )\r
+{\r
+  LIST_ENTRY              *Link;\r
+  FORM_BROWSER_STATEMENT  *Question;\r
+\r
+  if (QuestionId == 0) {\r
+    //\r
+    // The value of zero is reserved\r
+    //\r
+    return NULL;\r
+  }\r
+\r
+  Link = GetFirstNode (&Form->StatementListHead);\r
+  while (!IsNull (&Form->StatementListHead, Link)) {\r
+    Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+\r
+    if (Question->QuestionId == QuestionId) {\r
+      return Question;\r
+    }\r
+\r
+    Link = GetNextNode (&Form->StatementListHead, Link);\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+\r
+/**\r
+  Search a Question in Formset scope using its QuestionId.\r
+\r
+  @param  FormSet                The formset which contains this form.\r
+  @param  Form                   The form which contains this Question.\r
+  @param  QuestionId             Id of this Question.\r
+\r
+  @retval Pointer                The Question.\r
+  @retval NULL                   Specified Question not found in the form.\r
+\r
+**/\r
+FORM_BROWSER_STATEMENT *\r
+IdToQuestion (\r
+  IN FORM_BROWSER_FORMSET  *FormSet,\r
+  IN FORM_BROWSER_FORM     *Form,\r
+  IN UINT16                QuestionId\r
+  )\r
+{\r
+  LIST_ENTRY              *Link;\r
+  FORM_BROWSER_STATEMENT  *Question;\r
+\r
+  //\r
+  // Search in the form scope first\r
+  //\r
+  Question = IdToQuestion2 (Form, QuestionId);\r
+  if (Question != NULL) {\r
+    return Question;\r
+  }\r
+\r
+  //\r
+  // Search in the formset scope\r
+  //\r
+  Link = GetFirstNode (&FormSet->FormListHead);\r
+  while (!IsNull (&FormSet->FormListHead, Link)) {\r
+    Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+\r
+    Question = IdToQuestion2 (Form, QuestionId);\r
+    if (Question != NULL) {\r
+      return Question;\r
+    }\r
+\r
+    Link = GetNextNode (&FormSet->FormListHead, Link);\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+\r
+/**\r
+  Get Expression given its RuleId.\r
+\r
+  @param  Form                   The form which contains this Expression.\r
+  @param  RuleId                 Id of this Expression.\r
+\r
+  @retval Pointer                The Expression.\r
+  @retval NULL                   Specified Expression not found in the form.\r
+\r
+**/\r
+FORM_EXPRESSION *\r
+RuleIdToExpression (\r
+  IN FORM_BROWSER_FORM  *Form,\r
+  IN UINT8              RuleId\r
+  )\r
+{\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
+\r
+    if (Expression->Type == EFI_HII_EXPRESSION_RULE && Expression->RuleId == RuleId) {\r
+      return Expression;\r
+    }\r
+\r
+    Link = GetNextNode (&Form->ExpressionListHead, Link);\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+\r
+/**\r
+  Locate the Unicode Collation Protocol interface for later use.\r
+\r
+  @retval EFI_SUCCESS            Protocol interface initialize success.\r
+  @retval Other                  Protocol interface initialize failed.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeUnicodeCollationProtocol (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  if (mUnicodeCollation != NULL) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // BUGBUG: Proper impelmentation is to locate all Unicode Collation Protocol\r
+  // instances first and then select one which support English language.\r
+  // Current implementation just pick the first instance.\r
+  //\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiUnicodeCollation2ProtocolGuid,\r
+                  NULL,\r
+                  (VOID **) &mUnicodeCollation\r
+                  );\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Convert the input Unicode character to upper.\r
+\r
+  @param String  Th Unicode character to be converted.\r
+\r
+**/\r
+VOID\r
+IfrStrToUpper (\r
+  CHAR16                   *String\r
+  )\r
+{\r
+  while (*String != 0) {\r
+    if ((*String >= 'a') && (*String <= 'z')) {\r
+      *String = (UINT16) ((*String) & ((UINT16) ~0x20));\r
+    }\r
+    String++;\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Evaluate opcode EFI_IFR_TO_STRING.\r
+\r
+  @param  FormSet                Formset which contains this opcode.\r
+  @param  Format                 String format in EFI_IFR_TO_STRING.\r
+  @param  Result                 Evaluation result for this opcode.\r
+\r
+  @retval EFI_SUCCESS            Opcode evaluation success.\r
+  @retval Other                  Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrToString (\r
+  IN FORM_BROWSER_FORMSET  *FormSet,\r
+  IN UINT8                 Format,\r
+  OUT  EFI_HII_VALUE       *Result\r
+  )\r
+{\r
+  EFI_STATUS     Status;\r
+  EFI_HII_VALUE  Value;\r
+  CHAR16         *String;\r
+  CHAR16         *PrintFormat;\r
+  CHAR16         Buffer[MAXIMUM_VALUE_CHARACTERS];\r
+  UINTN          BufferSize;\r
+\r
+  Status = PopExpression (&Value);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  switch (Value.Type) {\r
+  case EFI_IFR_TYPE_NUM_SIZE_8:\r
+  case EFI_IFR_TYPE_NUM_SIZE_16:\r
+  case EFI_IFR_TYPE_NUM_SIZE_32:\r
+  case EFI_IFR_TYPE_NUM_SIZE_64:\r
+    BufferSize = MAXIMUM_VALUE_CHARACTERS * sizeof (CHAR16);\r
+    switch (Format) {\r
+    case EFI_IFR_STRING_UNSIGNED_DEC:\r
+    case EFI_IFR_STRING_SIGNED_DEC:\r
+      PrintFormat = L"%ld";\r
+      break;\r
+\r
+    case EFI_IFR_STRING_LOWERCASE_HEX:\r
+      PrintFormat = L"%lx";\r
+      break;\r
+\r
+    case EFI_IFR_STRING_UPPERCASE_HEX:\r
+      PrintFormat = L"%lX";\r
+      break;\r
+\r
+    default:\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+    UnicodeSPrint (Buffer, BufferSize, PrintFormat, Value.Value.u64);\r
+    String = Buffer;\r
+    break;\r
+\r
+  case EFI_IFR_TYPE_STRING:\r
+    CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));\r
+    return EFI_SUCCESS;\r
+\r
+  case EFI_IFR_TYPE_BOOLEAN:\r
+    String = (Value.Value.b) ? L"True" : L"False";\r
+    break;\r
+\r
+  default:\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Result->Type = EFI_IFR_TYPE_STRING;\r
+  Result->Value.string = NewString (String, FormSet->HiiHandle);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Evaluate opcode EFI_IFR_TO_UINT.\r
+\r
+  @param  FormSet                Formset which contains this opcode.\r
+  @param  Result                 Evaluation result for this opcode.\r
+\r
+  @retval EFI_SUCCESS            Opcode evaluation success.\r
+  @retval Other                  Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrToUint (\r
+  IN FORM_BROWSER_FORMSET  *FormSet,\r
+  OUT  EFI_HII_VALUE       *Result\r
+  )\r
+{\r
+  EFI_STATUS     Status;\r
+  EFI_HII_VALUE  Value;\r
+  CHAR16         *String;\r
+  CHAR16         *StringPtr;\r
+  UINTN          BufferSize;\r
+\r
+  Status = PopExpression (&Value);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (Value.Type >= EFI_IFR_TYPE_OTHER) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status = EFI_SUCCESS;\r
+  if (Value.Type == EFI_IFR_TYPE_STRING) {\r
+    String = GetToken (Value.Value.string, FormSet->HiiHandle);\r
+    if (String == NULL) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    IfrStrToUpper (String);\r
+    StringPtr = StrStr (String, L"0X");\r
+    if (StringPtr != NULL) {\r
+      //\r
+      // Hex string\r
+      //\r
+      BufferSize = sizeof (UINT64);\r
+      Status = HexStringToBuf ((UINT8 *) &Result->Value.u64, &BufferSize, StringPtr + 2, NULL);\r
+    } else {\r
+      //\r
+      // BUGBUG: Need handle decimal string\r
+      //\r
+    }\r
+    gBS->FreePool (String);\r
+  } else {\r
+    CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));\r
+  }\r
+\r
+  Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Evaluate opcode EFI_IFR_CATENATE.\r
+\r
+  @param  FormSet                Formset which contains this opcode.\r
+  @param  Result                 Evaluation result for this opcode.\r
+\r
+  @retval EFI_SUCCESS            Opcode evaluation success.\r
+  @retval Other                  Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrCatenate (\r
+  IN FORM_BROWSER_FORMSET  *FormSet,\r
+  OUT  EFI_HII_VALUE       *Result\r
+  )\r
+{\r
+  EFI_STATUS     Status;\r
+  EFI_HII_VALUE  Value;\r
+  CHAR16         *String[2];\r
+  UINTN          Index;\r
+  CHAR16         *StringPtr;\r
+  UINTN          Size;\r
+\r
+  //\r
+  // String[0] - The second string\r
+  // String[1] - The first string\r
+  //\r
+  String[0] = NULL;\r
+  String[1] = NULL;\r
+  StringPtr = NULL;\r
+  Status = EFI_SUCCESS;\r
+\r
+  for (Index = 0; Index < 2; Index++) {\r
+    Status = PopExpression (&Value);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+\r
+    if (Value.Type != EFI_IFR_TYPE_STRING) {\r
+      Status = EFI_UNSUPPORTED;\r
+      goto Done;\r
+    }\r
+\r
+    String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
+    if (String== NULL) {\r
+      Status = EFI_NOT_FOUND;\r
+      goto Done;\r
+    }\r
+  }\r
+\r
+  Size = StrSize (String[0]);\r
+  StringPtr= AllocatePool (StrSize (String[1]) + Size);\r
+  ASSERT (StringPtr != NULL);\r
+  StrCpy (StringPtr, String[1]);\r
+  StrCat (StringPtr, String[0]);\r
+\r
+  Result->Type = EFI_IFR_TYPE_STRING;\r
+  Result->Value.string = NewString (StringPtr, FormSet->HiiHandle);\r
+\r
+Done:\r
+  SafeFreePool (String[0]);\r
+  SafeFreePool (String[1]);\r
+  SafeFreePool (StringPtr);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Evaluate opcode EFI_IFR_MATCH.\r
+\r
+  @param  FormSet                Formset which contains this opcode.\r
+  @param  Result                 Evaluation result for this opcode.\r
+\r
+  @retval EFI_SUCCESS            Opcode evaluation success.\r
+  @retval Other                  Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrMatch (\r
+  IN FORM_BROWSER_FORMSET  *FormSet,\r
+  OUT  EFI_HII_VALUE       *Result\r
+  )\r
+{\r
+  EFI_STATUS     Status;\r
+  EFI_HII_VALUE  Value;\r
+  CHAR16         *String[2];\r
+  UINTN          Index;\r
+\r
+  //\r
+  // String[0] - The string to search\r
+  // String[1] - pattern\r
+  //\r
+  String[0] = NULL;\r
+  String[1] = NULL;\r
+  Status = EFI_SUCCESS;\r
+  for (Index = 0; Index < 2; Index++) {\r
+    Status = PopExpression (&Value);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+\r
+    if (Value.Type != EFI_IFR_TYPE_STRING) {\r
+      Status = EFI_UNSUPPORTED;\r
+      goto Done;\r
+    }\r
+\r
+    String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
+    if (String== NULL) {\r
+      Status = EFI_NOT_FOUND;\r
+      goto Done;\r
+    }\r
+  }\r
+\r
+  Result->Type = EFI_IFR_TYPE_BOOLEAN;\r
+  Result->Value.b = mUnicodeCollation->MetaiMatch (mUnicodeCollation, String[0], String[1]);\r
+\r
+Done:\r
+  SafeFreePool (String[0]);\r
+  SafeFreePool (String[1]);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Evaluate opcode EFI_IFR_FIND.\r
+\r
+  @param  FormSet                Formset which contains this opcode.\r
+  @param  Format                 Case sensitive or insensitive.\r
+  @param  Result                 Evaluation result for this opcode.\r
+\r
+  @retval EFI_SUCCESS            Opcode evaluation success.\r
+  @retval Other                  Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrFind (\r
+  IN FORM_BROWSER_FORMSET  *FormSet,\r
+  IN UINT8                 Format,\r
+  OUT  EFI_HII_VALUE       *Result\r
+  )\r
+{\r
+  EFI_STATUS     Status;\r
+  EFI_HII_VALUE  Value;\r
+  CHAR16         *String[2];\r
+  UINTN          Base;\r
+  CHAR16         *StringPtr;\r
+  UINTN          Index;\r
+\r
+  if (Format > EFI_IFR_FF_CASE_INSENSITIVE) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status = PopExpression (&Value);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  Base = (UINTN) Value.Value.u64;\r
+\r
+  //\r
+  // String[0] - sub-string\r
+  // String[1] - The string to search\r
+  //\r
+  String[0] = NULL;\r
+  String[1] = NULL;\r
+  for (Index = 0; Index < 2; Index++) {\r
+    Status = PopExpression (&Value);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+\r
+    if (Value.Type != EFI_IFR_TYPE_STRING) {\r
+      Status = EFI_UNSUPPORTED;\r
+      goto Done;\r
+    }\r
+\r
+    String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
+    if (String== NULL) {\r
+      Status = EFI_NOT_FOUND;\r
+      goto Done;\r
+    }\r
+\r
+    if (Format == EFI_IFR_FF_CASE_INSENSITIVE) {\r
+      //\r
+      // Case insensitive, convert both string to upper case\r
+      //\r
+      IfrStrToUpper (String[Index]);\r
+    }\r
+  }\r
+\r
+  Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+  if (Base >= StrLen (String[1])) {\r
+    Result->Value.u64 = 0xFFFFFFFFFFFFFFFFULL;\r
+  } else {\r
+    StringPtr = StrStr (String[1] + Base, String[0]);\r
+    Result->Value.u64 = (StringPtr == NULL) ? 0xFFFFFFFFFFFFFFFFULL : (StringPtr - String[1]);\r
+  }\r
+\r
+Done:\r
+  SafeFreePool (String[0]);\r
+  SafeFreePool (String[1]);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Evaluate opcode EFI_IFR_MID.\r
+\r
+  @param  FormSet                Formset which contains this opcode.\r
+  @param  Result                 Evaluation result for this opcode.\r
+\r
+  @retval EFI_SUCCESS            Opcode evaluation success.\r
+  @retval Other                  Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrMid (\r
+  IN FORM_BROWSER_FORMSET  *FormSet,\r
+  OUT  EFI_HII_VALUE       *Result\r
+  )\r
+{\r
+  EFI_STATUS     Status;\r
+  EFI_HII_VALUE  Value;\r
+  CHAR16         *String;\r
+  UINTN          Base;\r
+  UINTN          Length;\r
+  CHAR16         *SubString;\r
+\r
+  Status = PopExpression (&Value);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  Length = (UINTN) Value.Value.u64;\r
+\r
+  Status = PopExpression (&Value);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  Base = (UINTN) Value.Value.u64;\r
+\r
+  Status = PopExpression (&Value);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  if (Value.Type != EFI_IFR_TYPE_STRING) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  String = GetToken (Value.Value.string, FormSet->HiiHandle);\r
+  if (String == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  if (Length == 0 || Base >= StrLen (String)) {\r
+    SubString = gEmptyString;\r
+  } else {\r
+    SubString = String + Base;\r
+    if ((Base + Length) < StrLen (String)) {\r
+      SubString[Length] = L'\0';\r
+    }\r
+  }\r
+\r
+  Result->Type = EFI_IFR_TYPE_STRING;\r
+  Result->Value.string = NewString (SubString, FormSet->HiiHandle);\r
+\r
+  gBS->FreePool (String);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Evaluate opcode EFI_IFR_TOKEN.\r
+\r
+  @param  FormSet                Formset which contains this opcode.\r
+  @param  Result                 Evaluation result for this opcode.\r
+\r
+  @retval EFI_SUCCESS            Opcode evaluation success.\r
+  @retval Other                  Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrToken (\r
+  IN FORM_BROWSER_FORMSET  *FormSet,\r
+  OUT  EFI_HII_VALUE       *Result\r
+  )\r
+{\r
+  EFI_STATUS     Status;\r
+  EFI_HII_VALUE  Value;\r
+  CHAR16         *String[2];\r
+  UINTN          Count;\r
+  CHAR16         *Delimiter;\r
+  CHAR16         *SubString;\r
+  CHAR16         *StringPtr;\r
+  UINTN          Index;\r
+\r
+  Status = PopExpression (&Value);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  Count = (UINTN) Value.Value.u64;\r
+\r
+  //\r
+  // String[0] - Delimiter\r
+  // String[1] - The string to search\r
+  //\r
+  String[0] = NULL;\r
+  String[1] = NULL;\r
+  for (Index = 0; Index < 2; Index++) {\r
+    Status = PopExpression (&Value);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+\r
+    if (Value.Type != EFI_IFR_TYPE_STRING) {\r
+      Status = EFI_UNSUPPORTED;\r
+      goto Done;\r
+    }\r
+\r
+    String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
+    if (String== NULL) {\r
+      Status = EFI_NOT_FOUND;\r
+      goto Done;\r
+    }\r
+  }\r
+\r
+  Delimiter = String[0];\r
+  SubString = String[1];\r
+  while (Count > 0) {\r
+    SubString = StrStr (SubString, Delimiter);\r
+    if (SubString != NULL) {\r
+      //\r
+      // Skip over the delimiter\r
+      //\r
+      SubString = SubString + StrLen (Delimiter);\r
+    } else {\r
+      break;\r
+    }\r
+    Count--;\r
+  }\r
+\r
+  if (SubString == NULL) {\r
+    //\r
+    // nth delimited sub-string not found, push an empty string\r
+    //\r
+    SubString = gEmptyString;\r
+  } else {\r
+    //\r
+    // Put a NULL terminator for nth delimited sub-string\r
+    //\r
+    StringPtr = StrStr (SubString, Delimiter);\r
+    if (StringPtr != NULL) {\r
+      *StringPtr = L'\0';\r
+    }\r
+  }\r
+\r
+  Result->Type = EFI_IFR_TYPE_STRING;\r
+  Result->Value.string = NewString (SubString, FormSet->HiiHandle);\r
+\r
+Done:\r
+  SafeFreePool (String[0]);\r
+  SafeFreePool (String[1]);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Evaluate opcode EFI_IFR_SPAN.\r
+\r
+  @param  FormSet                Formset which contains this opcode.\r
+  @param  Flags                  FIRST_MATCHING or FIRST_NON_MATCHING.\r
+  @param  Result                 Evaluation result for this opcode.\r
+\r
+  @retval EFI_SUCCESS            Opcode evaluation success.\r
+  @retval Other                  Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrSpan (\r
+  IN FORM_BROWSER_FORMSET  *FormSet,\r
+  IN UINT8                 Flags,\r
+  OUT  EFI_HII_VALUE       *Result\r
+  )\r
+{\r
+  EFI_STATUS     Status;\r
+  EFI_HII_VALUE  Value;\r
+  CHAR16         *String[2];\r
+  CHAR16         *Charset;\r
+  UINTN          Base;\r
+  UINTN          Index;\r
+  CHAR16         *StringPtr;\r
+  BOOLEAN        Found;\r
+\r
+  Status = PopExpression (&Value);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  Base = (UINTN) Value.Value.u64;\r
+\r
+  //\r
+  // String[0] - Charset\r
+  // String[1] - The string to search\r
+  //\r
+  String[0] = NULL;\r
+  String[1] = NULL;\r
+  for (Index = 0; Index < 2; Index++) {\r
+    Status = PopExpression (&Value);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+\r
+    if (Value.Type != EFI_IFR_TYPE_STRING) {\r
+      Status = EFI_UNSUPPORTED;\r
+      goto Done;\r
+    }\r
+\r
+    String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
+    if (String== NULL) {\r
+      Status = EFI_NOT_FOUND;\r
+      goto Done;\r
+    }\r
+  }\r
+\r
+  if (Base >= StrLen (String[1])) {\r
+    Status = EFI_UNSUPPORTED;\r
+    goto Done;\r
+  }\r
+\r
+  Found = FALSE;\r
+  StringPtr = String[1] + Base;\r
+  Charset = String[0];\r
+  while (*StringPtr != 0 && !Found) {\r
+    Index = 0;\r
+    while (Charset[Index] != 0) {\r
+      if (*StringPtr >= Charset[Index] && *StringPtr <= Charset[Index + 1]) {\r
+        if (Flags == EFI_IFR_FLAGS_FIRST_MATCHING) {\r
+          Found = TRUE;\r
+          break;\r
+        }\r
+      } else {\r
+        if (Flags == EFI_IFR_FLAGS_FIRST_NON_MATCHING) {\r
+          Found = TRUE;\r
+          break;\r
+        }\r
+      }\r
+      //\r
+      // Skip characters pair representing low-end of a range and high-end of a range\r
+      //\r
+      Index += 2;\r
+    }\r
+\r
+    if (!Found) {\r
+      StringPtr++;\r
+    }\r
+  }\r
+\r
+  Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+  Result->Value.u64 = StringPtr - String[1];\r
+\r
+Done:\r
+  SafeFreePool (String[0]);\r
+  SafeFreePool (String[1]);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Zero extend integer/boolean/date/time to UINT64 for comparing.\r
+\r
+  @param  Value                  HII Value to be converted.\r
+\r
+**/\r
+VOID\r
+ExtendValueToU64 (\r
+  IN  EFI_HII_VALUE   *Value\r
+  )\r
+{\r
+  UINT64  Temp;\r
+\r
+  Temp = 0;\r
+  switch (Value->Type) {\r
+  case EFI_IFR_TYPE_NUM_SIZE_8:\r
+    Temp = Value->Value.u8;\r
+    break;\r
+\r
+  case EFI_IFR_TYPE_NUM_SIZE_16:\r
+    Temp = Value->Value.u16;\r
+    break;\r
+\r
+  case EFI_IFR_TYPE_NUM_SIZE_32:\r
+    Temp = Value->Value.u32;\r
+    break;\r
+\r
+  case EFI_IFR_TYPE_BOOLEAN:\r
+    Temp = Value->Value.b;\r
+    break;\r
+\r
+  case EFI_IFR_TYPE_TIME:\r
+    Temp = Value->Value.u32 & 0xffffff;\r
+    break;\r
+\r
+  case EFI_IFR_TYPE_DATE:\r
+    Temp = Value->Value.u32;\r
+    break;\r
+\r
+  default:\r
+    return;\r
+  }\r
+\r
+  Value->Value.u64 = Temp;\r
+}\r
+\r
+\r
+/**\r
+  Compare two Hii value.\r
+\r
+  @param  Value1                 Expression value to compare on left-hand.\r
+  @param  Value2                 Expression value to compare on right-hand.\r
+  @param  HiiHandle              Only required for string compare.\r
+\r
+  @retval EFI_INVALID_PARAMETER  Could not perform comparation on two values.\r
+  @retval 0                      Two operators equeal.\r
+  @return Positive value if Value1 is greater than Value2.\r
+  @retval Negative value if Value1 is less than Value2.\r
+\r
+**/\r
+INTN\r
+CompareHiiValue (\r
+  IN  EFI_HII_VALUE   *Value1,\r
+  IN  EFI_HII_VALUE   *Value2,\r
+  IN  EFI_HII_HANDLE  HiiHandle OPTIONAL\r
+  )\r
+{\r
+  INTN    Result;\r
+  INT64   Temp64;\r
+  CHAR16  *Str1;\r
+  CHAR16  *Str2;\r
+\r
+  if (Value1->Type >= EFI_IFR_TYPE_OTHER || Value2->Type >= EFI_IFR_TYPE_OTHER ) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (Value1->Type == EFI_IFR_TYPE_STRING || Value2->Type == EFI_IFR_TYPE_STRING ) {\r
+    if (Value1->Type != Value2->Type) {\r
+      //\r
+      // Both Operator should be type of String\r
+      //\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    if (Value1->Value.string == 0 || Value2->Value.string == 0) {\r
+      //\r
+      // StringId 0 is reserved\r
+      //\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    if (Value1->Value.string == Value2->Value.string) {\r
+      return 0;\r
+    }\r
+\r
+    Str1 = GetToken (Value1->Value.string, HiiHandle);\r
+    if (Str1 == NULL) {\r
+      //\r
+      // String not found\r
+      //\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    Str2 = GetToken (Value2->Value.string, HiiHandle);\r
+    if (Str2 == NULL) {\r
+      gBS->FreePool (Str1);\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    Result = StrCmp (Str1, Str2);\r
+\r
+    gBS->FreePool (Str1);\r
+    gBS->FreePool (Str2);\r
+\r
+    return Result;\r
+  }\r
+\r
+  //\r
+  // Take remain types(integer, boolean, date/time) as integer\r
+  //\r
+  Temp64 = (INT64) (Value1->Value.u64 - Value2->Value.u64);\r
+  if (Temp64 > 0) {\r
+    Result = 1;\r
+  } else if (Temp64 < 0) {\r
+    Result = -1;\r
+  } else {\r
+    Result = 0;\r
+  }\r
+\r
+  return Result;\r
+}\r
+\r
+\r
+/**\r
+  Evaluate the result of a HII expression\r
+\r
+  @param  FormSet                FormSet associated with this expression.\r
+  @param  Form                   Form associated with this expression.\r
+  @param  Expression             Expression to be evaluated.\r
+\r
+  @retval EFI_SUCCESS            The expression evaluated successfuly\r
+  @retval EFI_NOT_FOUND          The Question which referenced by a QuestionId\r
+                                 could not be found.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the\r
+                                 stack.\r
+  @retval EFI_ACCESS_DENIED      The pop operation underflowed the stack\r
+  @retval EFI_INVALID_PARAMETER  Syntax error with the Expression\r
+\r
+**/\r
+EFI_STATUS\r
+EvaluateExpression (\r
+  IN FORM_BROWSER_FORMSET  *FormSet,\r
+  IN FORM_BROWSER_FORM     *Form,\r
+  IN OUT FORM_EXPRESSION   *Expression\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  LIST_ENTRY              *Link;\r
+  EXPRESSION_OPCODE       *OpCode;\r
+  FORM_BROWSER_STATEMENT  *Question;\r
+  FORM_BROWSER_STATEMENT  *Question2;\r
+  UINT16                  Index;\r
+  EFI_HII_VALUE           Data1;\r
+  EFI_HII_VALUE           Data2;\r
+  EFI_HII_VALUE           Data3;\r
+  FORM_EXPRESSION         *RuleExpression;\r
+  EFI_HII_VALUE           *Value;\r
+  INTN                    Result;\r
+  CHAR16                  *StrPtr;\r
+  UINT32                  TempValue;\r
+\r
+  //\r
+  // Always reset the stack before evaluating an Expression\r
+  //\r
+  ResetExpressionStack ();\r
+\r
+  Expression->Result.Type = EFI_IFR_TYPE_OTHER;\r
+\r
+  Link = GetFirstNode (&Expression->OpCodeListHead);\r
+  while (!IsNull (&Expression->OpCodeListHead, Link)) {\r
+    OpCode = EXPRESSION_OPCODE_FROM_LINK (Link);\r
+\r
+    Link = GetNextNode (&Expression->OpCodeListHead, Link);\r
+\r
+    ZeroMem (&Data1, sizeof (EFI_HII_VALUE));\r
+    ZeroMem (&Data2, sizeof (EFI_HII_VALUE));\r
+    ZeroMem (&Data3, sizeof (EFI_HII_VALUE));\r
+\r
+    Value = &Data3;\r
+    Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
+    Status = EFI_SUCCESS;\r
+\r
+    switch (OpCode->Operand) {\r
+    //\r
+    // Built-in functions\r
+    //\r
+    case EFI_IFR_EQ_ID_VAL_OP:\r
+      Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
+      if (Question == NULL) {\r
+        return EFI_NOT_FOUND;\r
+      }\r
+\r
+      Result = CompareHiiValue (&Question->HiiValue, &OpCode->Value, NULL);\r
+      if (Result == EFI_INVALID_PARAMETER) {\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+      Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
+      break;\r
+\r
+    case EFI_IFR_EQ_ID_ID_OP:\r
+      Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
+      if (Question == NULL) {\r
+        return EFI_NOT_FOUND;\r
+      }\r
+\r
+      Question2 = IdToQuestion (FormSet, Form, OpCode->QuestionId2);\r
+      if (Question2 == NULL) {\r
+        return EFI_NOT_FOUND;\r
+      }\r
+\r
+      Result = CompareHiiValue (&Question->HiiValue, &Question2->HiiValue, FormSet->HiiHandle);\r
+      if (Result == EFI_INVALID_PARAMETER) {\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+      Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
+      break;\r
+\r
+    case EFI_IFR_EQ_ID_LIST_OP:\r
+      Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
+      if (Question == NULL) {\r
+        return EFI_NOT_FOUND;\r
+      }\r
+\r
+      Value->Value.b = FALSE;\r
+      for (Index =0; Index < OpCode->ListLength; Index++) {\r
+        if (Question->HiiValue.Value.u16 == OpCode->ValueList[Index]) {\r
+          Value->Value.b = TRUE;\r
+          break;\r
+        }\r
+      }\r
+      break;\r
+\r
+    case EFI_IFR_DUP_OP:\r
+      Status = PopExpression (Value);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      Status = PushExpression (Value);\r
+      break;\r
+\r
+    case EFI_IFR_QUESTION_REF1_OP:\r
+    case EFI_IFR_THIS_OP:\r
+      Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
+      if (Question == NULL) {\r
+        return EFI_NOT_FOUND;\r
+      }\r
+\r
+      Value = &Question->HiiValue;\r
+      break;\r
+\r
+    case EFI_IFR_QUESTION_REF3_OP:\r
+      if (OpCode->DevicePath == 0) {\r
+        //\r
+        // EFI_IFR_QUESTION_REF3\r
+        // Pop an expression from the expression stack\r
+        //\r
+        Status = PopExpression (Value);\r
+        if (EFI_ERROR (Status)) {\r
+          return Status;\r
+        }\r
+\r
+        //\r
+        // Validate the expression value\r
+        //\r
+        if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
+          return EFI_NOT_FOUND;\r
+        }\r
+\r
+        Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
+        if (Question == NULL) {\r
+          return EFI_NOT_FOUND;\r
+        }\r
+\r
+        //\r
+        // push the questions' value on to the expression stack\r
+        //\r
+        Value = &Question->HiiValue;\r
+      } else {\r
+        //\r
+        // BUGBUG: push 0 for EFI_IFR_QUESTION_REF3_2 and EFI_IFR_QUESTION_REF3_3,\r
+        // since it is impractical to evaluate the value of a Question in another\r
+        // Hii Package list.\r
+        //\r
+        ZeroMem (Value, sizeof (EFI_HII_VALUE));\r
+      }\r
+      break;\r
+\r
+    case EFI_IFR_RULE_REF_OP:\r
+      //\r
+      // Find expression for this rule\r
+      //\r
+      RuleExpression = RuleIdToExpression (Form, OpCode->RuleId);\r
+      if (RuleExpression == NULL) {\r
+        return EFI_NOT_FOUND;\r
+      }\r
+\r
+      //\r
+      // Evaluate this rule expression\r
+      //\r
+      Status = EvaluateExpression (FormSet, Form, RuleExpression);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      Value = &RuleExpression->Result;\r
+      break;\r
+\r
+    case EFI_IFR_STRING_REF1_OP:\r
+      Value->Type = EFI_IFR_TYPE_STRING;\r
+      Value->Value.string = OpCode->Value.Value.string;\r
+      break;\r
+\r
+    //\r
+    // Constant\r
+    //\r
+    case EFI_IFR_TRUE_OP:\r
+    case EFI_IFR_FALSE_OP:\r
+    case EFI_IFR_ONE_OP:\r
+    case EFI_IFR_ONES_OP:\r
+    case EFI_IFR_UINT8_OP:\r
+    case EFI_IFR_UINT16_OP:\r
+    case EFI_IFR_UINT32_OP:\r
+    case EFI_IFR_UINT64_OP:\r
+    case EFI_IFR_UNDEFINED_OP:\r
+    case EFI_IFR_VERSION_OP:\r
+    case EFI_IFR_ZERO_OP:\r
+      Value = &OpCode->Value;\r
+      break;\r
+\r
+    //\r
+    // unary-op\r
+    //\r
+    case EFI_IFR_LENGTH_OP:\r
+      Status = PopExpression (Value);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      if (Value->Type != EFI_IFR_TYPE_STRING) {\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+\r
+      StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
+      if (StrPtr == NULL) {\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+\r
+      Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+      Value->Value.u64 = StrLen (StrPtr);\r
+      gBS->FreePool (StrPtr);\r
+      break;\r
+\r
+    case EFI_IFR_NOT_OP:\r
+      Status = PopExpression (Value);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+      Value->Value.b = (BOOLEAN) (!Value->Value.b);\r
+      break;\r
+\r
+    case EFI_IFR_QUESTION_REF2_OP:\r
+      //\r
+      // Pop an expression from the expression stack\r
+      //\r
+      Status = PopExpression (Value);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      //\r
+      // Validate the expression value\r
+      //\r
+      if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
+        return EFI_NOT_FOUND;\r
+      }\r
+\r
+      Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
+      if (Question == NULL) {\r
+        return EFI_NOT_FOUND;\r
+      }\r
+\r
+      Value = &Question->HiiValue;\r
+      break;\r
+\r
+    case EFI_IFR_STRING_REF2_OP:\r
+      //\r
+      // Pop an expression from the expression stack\r
+      //\r
+      Status = PopExpression (Value);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      //\r
+      // Validate the expression value\r
+      //\r
+      if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
+        return EFI_NOT_FOUND;\r
+      }\r
+\r
+      Value->Type = EFI_IFR_TYPE_STRING;\r
+      StrPtr = GetToken (Value->Value.u16, FormSet->HiiHandle);\r
+      if (StrPtr == NULL) {\r
+        //\r
+        // If String not exit, push an empty string\r
+        //\r
+        Value->Value.string = NewString (gEmptyString, FormSet->HiiHandle);\r
+      } else {\r
+        Index = (UINT16) Value->Value.u64;\r
+        Value->Value.string = Index;\r
+        gBS->FreePool (StrPtr);\r
+      }\r
+      break;\r
+\r
+    case EFI_IFR_TO_BOOLEAN_OP:\r
+      //\r
+      // Pop an expression from the expression stack\r
+      //\r
+      Status = PopExpression (Value);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      //\r
+      // Convert an expression to a Boolean\r
+      //\r
+      if (Value->Type <= EFI_IFR_TYPE_DATE) {\r
+        //\r
+        // When converting from an unsigned integer, zero will be converted to\r
+        // FALSE and any other value will be converted to TRUE.\r
+        //\r
+        Value->Value.b = (BOOLEAN) ((Value->Value.u64) ? TRUE : FALSE);\r
+\r
+        Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
+      } else if (Value->Type == EFI_IFR_TYPE_STRING) {\r
+        //\r
+        // When converting from a string, if case-insensitive compare\r
+        // with "true" is True, then push True. If a case-insensitive compare\r
+        // with "false" is True, then push False.\r
+        //\r
+        StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
+        if (StrPtr == NULL) {\r
+          return EFI_INVALID_PARAMETER;\r
+        }\r
+\r
+        if ((StrCmp (StrPtr, L"true") == 0) || (StrCmp (StrPtr, L"false") == 0)){\r
+          Value->Value.b = TRUE;\r
+        } else {\r
+          Value->Value.b = FALSE;\r
+        }\r
+        gBS->FreePool (StrPtr);\r
+        Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
+      }\r
+      break;\r
+\r
+    case EFI_IFR_TO_STRING_OP:\r
+      Status = IfrToString (FormSet, OpCode->Format, Value);\r
+      break;\r
+\r
+    case EFI_IFR_TO_UINT_OP:\r
+      Status = IfrToUint (FormSet, Value);\r
+      break;\r
+\r
+    case EFI_IFR_TO_LOWER_OP:\r
+    case EFI_IFR_TO_UPPER_OP:\r
+      Status = InitializeUnicodeCollationProtocol ();\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      Status = PopExpression (Value);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      if (Value->Type != EFI_IFR_TYPE_STRING) {\r
+        return EFI_UNSUPPORTED;\r
+      }\r
+\r
+      StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
+      if (StrPtr == NULL) {\r
+        return EFI_NOT_FOUND;\r
+      }\r
+\r
+      if (OpCode->Operand == EFI_IFR_TO_LOWER_OP) {\r
+        mUnicodeCollation->StrLwr (mUnicodeCollation, StrPtr);\r
+      } else {\r
+        mUnicodeCollation->StrUpr (mUnicodeCollation, StrPtr);\r
+      }\r
+      Value->Value.string = NewString (StrPtr, FormSet->HiiHandle);\r
+      gBS->FreePool (StrPtr);\r
+      break;\r
+\r
+    case EFI_IFR_BITWISE_NOT_OP:\r
+      //\r
+      // Pop an expression from the expression stack\r
+      //\r
+      Status = PopExpression (Value);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      if (Value->Type > EFI_IFR_TYPE_DATE) {\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+\r
+      Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+      Value->Value.u64 = ~Value->Value.u64;\r
+      break;\r
+\r
+    //\r
+    // binary-op\r
+    //\r
+    case EFI_IFR_ADD_OP:\r
+    case EFI_IFR_SUBTRACT_OP:\r
+    case EFI_IFR_MULTIPLY_OP:\r
+    case EFI_IFR_DIVIDE_OP:\r
+    case EFI_IFR_MODULO_OP:\r
+    case EFI_IFR_BITWISE_AND_OP:\r
+    case EFI_IFR_BITWISE_OR_OP:\r
+    case EFI_IFR_SHIFT_LEFT_OP:\r
+    case EFI_IFR_SHIFT_RIGHT_OP:\r
+      //\r
+      // Pop an expression from the expression stack\r
+      //\r
+      Status = PopExpression (&Data2);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      if (Data2.Type > EFI_IFR_TYPE_DATE) {\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+\r
+      //\r
+      // Pop another expression from the expression stack\r
+      //\r
+      Status = PopExpression (&Data1);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      if (Data1.Type > EFI_IFR_TYPE_DATE) {\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+\r
+      Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+\r
+      switch (OpCode->Operand) {\r
+        case EFI_IFR_ADD_OP:\r
+          Value->Value.u64 = Data1.Value.u64 + Data2.Value.u64;\r
+          break;\r
+\r
+        case EFI_IFR_SUBTRACT_OP:\r
+          Value->Value.u64 = Data1.Value.u64 - Data2.Value.u64;\r
+          break;\r
+\r
+        case EFI_IFR_MULTIPLY_OP:\r
+          Value->Value.u64 = MultU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);\r
+          break;\r
+\r
+        case EFI_IFR_DIVIDE_OP:\r
+          Value->Value.u64 = DivU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);\r
+          break;\r
+\r
+        case EFI_IFR_MODULO_OP:\r
+          DivU64x32Remainder  (Data1.Value.u64, (UINT32) Data2.Value.u64, &TempValue);\r
+          Value->Value.u64 = TempValue;\r
+          break;\r
+\r
+        case EFI_IFR_BITWISE_AND_OP:\r
+          Value->Value.u64 = Data1.Value.u64 & Data2.Value.u64;\r
+          break;\r
+\r
+        case EFI_IFR_BITWISE_OR_OP:\r
+          Value->Value.u64 = Data1.Value.u64 | Data2.Value.u64;\r
+          break;\r
+\r
+        case EFI_IFR_SHIFT_LEFT_OP:\r
+          Value->Value.u64 = LShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);\r
+          break;\r
+\r
+        case EFI_IFR_SHIFT_RIGHT_OP:\r
+          Value->Value.u64 = RShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);\r
+          break;\r
+\r
+        default:\r
+          break;\r
+      }\r
+      break;\r
+\r
+    case EFI_IFR_AND_OP:\r
+    case EFI_IFR_OR_OP:\r
+      //\r
+      // Two Boolean operator\r
+      //\r
+      Status = PopExpression (&Data2);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+\r
+      //\r
+      // Pop another expression from the expression stack\r
+      //\r
+      Status = PopExpression (&Data1);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+\r
+      if (OpCode->Operand == EFI_IFR_AND_OP) {\r
+        Value->Value.b = (BOOLEAN) (Data1.Value.b && Data2.Value.b);\r
+      } else {\r
+        Value->Value.b = (BOOLEAN) (Data1.Value.b || Data2.Value.b);\r
+      }\r
+      break;\r
+\r
+    case EFI_IFR_EQUAL_OP:\r
+    case EFI_IFR_NOT_EQUAL_OP:\r
+    case EFI_IFR_GREATER_EQUAL_OP:\r
+    case EFI_IFR_GREATER_THAN_OP:\r
+    case EFI_IFR_LESS_EQUAL_OP:\r
+    case EFI_IFR_LESS_THAN_OP:\r
+      //\r
+      // Compare two integer, string, boolean or date/time\r
+      //\r
+      Status = PopExpression (&Data2);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      if (Data2.Type > EFI_IFR_TYPE_BOOLEAN && Data2.Type != EFI_IFR_TYPE_STRING) {\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+\r
+      //\r
+      // Pop another expression from the expression stack\r
+      //\r
+      Status = PopExpression (&Data1);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      Result = CompareHiiValue (&Data1, &Data2, FormSet->HiiHandle);\r
+      if (Result == EFI_INVALID_PARAMETER) {\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+\r
+      switch (OpCode->Operand) {\r
+      case EFI_IFR_EQUAL_OP:\r
+        Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
+        break;\r
+\r
+      case EFI_IFR_NOT_EQUAL_OP:\r
+        Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
+        break;\r
+\r
+      case EFI_IFR_GREATER_EQUAL_OP:\r
+        Value->Value.b = (BOOLEAN) ((Result >= 0) ? TRUE : FALSE);\r
+        break;\r
+\r
+      case EFI_IFR_GREATER_THAN_OP:\r
+        Value->Value.b = (BOOLEAN) ((Result > 0) ? TRUE : FALSE);\r
+        break;\r
+\r
+      case EFI_IFR_LESS_EQUAL_OP:\r
+        Value->Value.b = (BOOLEAN) ((Result <= 0) ? TRUE : FALSE);\r
+        break;\r
+\r
+      case EFI_IFR_LESS_THAN_OP:\r
+        Value->Value.b = (BOOLEAN) ((Result < 0) ? TRUE : FALSE);\r
+        break;\r
+\r
+      default:\r
+        break;\r
+      }\r
+      break;\r
+\r
+    case EFI_IFR_MATCH_OP:\r
+      Status = IfrMatch (FormSet, Value);\r
+      break;\r
+\r
+    case EFI_IFR_CATENATE_OP:\r
+      Status = IfrCatenate (FormSet, Value);\r
+      break;\r
+\r
+    //\r
+    // ternary-op\r
+    //\r
+    case EFI_IFR_CONDITIONAL_OP:\r
+      //\r
+      // Pop third expression from the expression stack\r
+      //\r
+      Status = PopExpression (&Data3);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      //\r
+      // Pop second expression from the expression stack\r
+      //\r
+      Status = PopExpression (&Data2);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      //\r
+      // Pop first expression from the expression stack\r
+      //\r
+      Status = PopExpression (&Data1);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+\r
+      if (Data1.Value.b) {\r
+        Value = &Data3;\r
+      } else {\r
+        Value = &Data2;\r
+      }\r
+      break;\r
+\r
+    case EFI_IFR_FIND_OP:\r
+      Status = IfrFind (FormSet, OpCode->Format, Value);\r
+      break;\r
+\r
+    case EFI_IFR_MID_OP:\r
+      Status = IfrMid (FormSet, Value);\r
+      break;\r
+\r
+    case EFI_IFR_TOKEN_OP:\r
+      Status = IfrToken (FormSet, Value);\r
+      break;\r
+\r
+    case EFI_IFR_SPAN_OP:\r
+      Status = IfrSpan (FormSet, OpCode->Flags, Value);\r
+      break;\r
+\r
+    default:\r
+      break;\r
+    }\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    Status = PushExpression (Value);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Pop the final result from expression stack\r
+  //\r
+  Value = &Data1;\r
+  Status = PopExpression (Value);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // After evaluating an expression, there should be only one value left on the expression stack\r
+  //\r
+  if (PopExpression (Value) != EFI_ACCESS_DENIED) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));\r
+\r
+  return EFI_SUCCESS;\r
+}\r
index 9108acb473ea6ded418216d2e23f1675ea62ee8d..7e5f6684ce39dce2c821d74635282a746b0a6edd 100644 (file)
@@ -1,4 +1,6 @@
 /** @file
+Parser for IFR binary encoding.
+
 Copyright (c) 2007 - 2008, 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
@@ -8,15 +10,6 @@ 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:
-
-  IfrParse.c
-
-Abstract:
-
-  Parser for IFR binary encoding.
-
-
 **/
 
 #include "Setup.h"
@@ -337,7 +330,7 @@ InitializeRequestElement (
     StrLen = UnicodeSPrint (RequestElement, 30 * sizeof (CHAR16), L"&%s", Question->VariableName);
   }
 
-  if ((Question->Operand == EFI_IFR_PASSWORD_OP) && (Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK)) {
+  if ((Question->Operand == EFI_IFR_PASSWORD_OP) && ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK)) {
     //
     // Password with CALLBACK flag is stored in encoded format,
     // so don't need to append it to <ConfigRequest>
@@ -371,12 +364,10 @@ InitializeRequestElement (
 
 
 /**
-  Free resources of a Expression
+  Free resources of a Expression.
 
   @param  FormSet                Pointer of the Expression
 
-  @return None.
-
 **/
 VOID
 DestroyExpression (
@@ -402,12 +393,10 @@ DestroyExpression (
 
 
 /**
-  Free resources of a storage
+  Free resources of a storage.
 
   @param  Storage                Pointer of the storage
 
-  @return None.
-
 **/
 VOID
 DestroyStorage (
@@ -444,12 +433,10 @@ DestroyStorage (
 
 
 /**
-  Free resources of a Statement
+  Free resources of a Statement.
 
   @param  Statement              Pointer of the Statement
 
-  @return None.
-
 **/
 VOID
 DestroyStatement (
@@ -511,11 +498,9 @@ DestroyStatement (
 
 
 /**
-  Free resources of a Form
+  Free resources of a Form.
 
-  @param  Form                   Pointer of the Form
-
-  @return None.
+  @param  Form                   Pointer of the Form.
 
 **/
 VOID
@@ -557,12 +542,10 @@ DestroyForm (
 
 
 /**
-  Free resources allocated for a FormSet
+  Free resources allocated for a FormSet.
 
   @param  FormSet                Pointer of the FormSet
 
-  @return None.
-
 **/
 VOID
 DestroyFormSet (
@@ -657,8 +640,6 @@ IsExpressionOpCode (
   @param  NumberOfStatement      Number of Statemens(Questions)
   @param  NumberOfExpression     Number of Expression OpCodes
 
-  @return None.
-
 **/
 VOID
 CountOpCodes (
@@ -791,7 +772,7 @@ ParseOpCodes (
     //
     // If scope bit set, push onto scope stack
     //
-    if (Scope) {
+    if (Scope != 0) {
       PushScope (Operand);
     }
 
@@ -1091,7 +1072,7 @@ ParseOpCodes (
       CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
       CurrentStatement->Flags = ((EFI_IFR_SUBTITLE *) OpCodeData)->Flags;
 
-      if (Scope) {
+      if (Scope != 0) {
         mInScopeSubtitle = TRUE;
       }
       break;
@@ -1187,7 +1168,7 @@ ParseOpCodes (
 
       InitializeRequestElement (FormSet, CurrentStatement);
 
-      if ((Operand == EFI_IFR_ONE_OF_OP) && Scope) {
+      if ((Operand == EFI_IFR_ONE_OF_OP) && Scope != 0) {
         SuppressForOption = TRUE;
       }
       break;
@@ -1208,7 +1189,7 @@ ParseOpCodes (
       CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_OTHER;
       CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth);
 
-      if (Scope) {
+      if (Scope != 0) {
         SuppressForOption = TRUE;
       }
       break;
@@ -1320,7 +1301,7 @@ ParseOpCodes (
       //
       InsertTailList (&CurrentStatement->DefaultListHead, &CurrentDefault->Link);
 
-      if (Scope) {
+      if (Scope != 0) {
         InScopeDefault = TRUE;
       }
       break;
index cc580b81c748aba02200007aea79a8e1ff7b3f73..b958f4fdc7a635fc0c83a32ab7290fdca3d3ae64 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:
-
-  InputHandler.c
-
-Abstract:
-
-  Implementation for handling user input from the User Interface
-
-Revision History
-
-
-**/
-
-#include "Ui.h"
-#include "Setup.h"
-
-
-/**
-  Get string or password input from user.
-
-  @param  MenuOption        Pointer to the current input menu.
-  @param  Prompt            The prompt string shown on popup window.
-  @param  StringPtr         Destination for use input string.
-
-  @retval EFI_SUCCESS       If string input is read successfully
-  @retval EFI_DEVICE_ERROR  If operation fails
-
-**/
-EFI_STATUS
-ReadString (
-  IN  UI_MENU_OPTION              *MenuOption,
-  IN  CHAR16                      *Prompt,
-  OUT CHAR16                      *StringPtr
-  )
-{
-  EFI_STATUS              Status;
-  EFI_INPUT_KEY           Key;
-  CHAR16                  NullCharacter;
-  UINTN                   ScreenSize;
-  CHAR16                  Space[2];
-  CHAR16                  KeyPad[2];
-  CHAR16                  *TempString;
-  CHAR16                  *BufferedString;
-  UINTN                   Index;
-  UINTN                   Count;
-  UINTN                   Start;
-  UINTN                   Top;
-  UINTN                   DimensionsWidth;
-  UINTN                   DimensionsHeight;
-  BOOLEAN                 CursorVisible;
-  UINTN                   Minimum;
-  UINTN                   Maximum;
-  FORM_BROWSER_STATEMENT  *Question;
-  BOOLEAN                 IsPassword;
-
-  DimensionsWidth  = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
-  DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;
-
-  NullCharacter    = CHAR_NULL;
-  ScreenSize       = GetStringWidth (Prompt) / sizeof (CHAR16);
-  Space[0]         = L' ';
-  Space[1]         = CHAR_NULL;
-
-  Question         = MenuOption->ThisTag;
-  Minimum          = (UINTN) Question->Minimum;
-  Maximum          = (UINTN) Question->Maximum;
-
-  if (Question->Operand == EFI_IFR_PASSWORD_OP) {
-    IsPassword = TRUE;
-  } else {
-    IsPassword = FALSE;
-  }
-
-  TempString = AllocateZeroPool ((Maximum + 1)* sizeof (CHAR16));
-  ASSERT (TempString);
-
-  if (ScreenSize < (Maximum + 1)) {
-    ScreenSize = Maximum + 1;
-  }
-
-  if ((ScreenSize + 2) > DimensionsWidth) {
-    ScreenSize = DimensionsWidth - 2;
-  }
-
-  BufferedString = AllocateZeroPool (ScreenSize * 2);
-  ASSERT (BufferedString);
-
-  Start = (DimensionsWidth - ScreenSize - 2) / 2 + gScreenDimensions.LeftColumn + 1;
-  Top   = ((DimensionsHeight - 6) / 2) + gScreenDimensions.TopRow - 1;
-
-  //
-  // Display prompt for string
-  //
-  CreatePopUp (ScreenSize, 4, &NullCharacter, Prompt, Space, &NullCharacter);
-
-  gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_BLACK, EFI_LIGHTGRAY));
-
-  CursorVisible = gST->ConOut->Mode->CursorVisible;
-  gST->ConOut->EnableCursor (gST->ConOut, TRUE);
-
-  do {
-    Status = WaitForKeyStroke (&Key);
-    ASSERT_EFI_ERROR (Status);
-
-    gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_BLACK, EFI_LIGHTGRAY));
-    switch (Key.UnicodeChar) {
-    case CHAR_NULL:
-      switch (Key.ScanCode) {
-      case SCAN_LEFT:
-        break;
-
-      case SCAN_RIGHT:
-        break;
-
-      case SCAN_ESC:
-        gBS->FreePool (TempString);
-        gBS->FreePool (BufferedString);
-        gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
-        gST->ConOut->EnableCursor (gST->ConOut, CursorVisible);
-        return EFI_DEVICE_ERROR;
-
-      default:
-        break;
-      }
-
-      break;
-
-    case CHAR_CARRIAGE_RETURN:
-      if (GetStringWidth (StringPtr) >= ((Minimum + 1) * sizeof (CHAR16))) {
-
-        gBS->FreePool (TempString);
-        gBS->FreePool (BufferedString);
-        gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
-        gST->ConOut->EnableCursor (gST->ConOut, CursorVisible);
-        return EFI_SUCCESS;
-      } else {
-        //
-        // Simply create a popup to tell the user that they had typed in too few characters.
-        // To save code space, we can then treat this as an error and return back to the menu.
-        //
-        do {
-          CreateDialog (4, TRUE, 0, NULL, &Key, &NullCharacter, gMiniString, gPressEnter, &NullCharacter);
-        } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
-
-        gBS->FreePool (TempString);
-        gBS->FreePool (BufferedString);
-        gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
-        gST->ConOut->EnableCursor (gST->ConOut, CursorVisible);
-        return EFI_DEVICE_ERROR;
-      }
-
-      break;
-
-    case CHAR_BACKSPACE:
-      if (StringPtr[0] != CHAR_NULL) {
-        for (Index = 0; StringPtr[Index] != CHAR_NULL; Index++) {
-          TempString[Index] = StringPtr[Index];
-        }
-        //
-        // Effectively truncate string by 1 character
-        //
-        TempString[Index - 1] = CHAR_NULL;
-        StrCpy (StringPtr, TempString);
-      }
-
-    default:
-      //
-      // If it is the beginning of the string, don't worry about checking maximum limits
-      //
-      if ((StringPtr[0] == CHAR_NULL) && (Key.UnicodeChar != CHAR_BACKSPACE)) {
-        StrnCpy (StringPtr, &Key.UnicodeChar, 1);
-        StrnCpy (TempString, &Key.UnicodeChar, 1);
-      } else if ((GetStringWidth (StringPtr) < ((Maximum + 1) * sizeof (CHAR16))) && (Key.UnicodeChar != CHAR_BACKSPACE)) {
-        KeyPad[0] = Key.UnicodeChar;
-        KeyPad[1] = CHAR_NULL;
-        StrCat (StringPtr, KeyPad);
-        StrCat (TempString, KeyPad);
-      }
-
-      //
-      // If the width of the input string is now larger than the screen, we nee to
-      // adjust the index to start printing portions of the string
-      //
-      SetUnicodeMem (BufferedString, ScreenSize - 1, L' ');
-      PrintStringAt (Start + 1, Top + 3, BufferedString);
-
-      if ((GetStringWidth (StringPtr) / 2) > (DimensionsWidth - 2)) {
-        Index = (GetStringWidth (StringPtr) / 2) - DimensionsWidth + 2;
-      } else {
-        Index = 0;
-      }
-
-      if (IsPassword) {
-        gST->ConOut->SetCursorPosition (gST->ConOut, Start + 1, Top + 3);
-      }
-
-      for (Count = 0; Index + 1 < GetStringWidth (StringPtr) / 2; Index++, Count++) {
-        BufferedString[Count] = StringPtr[Index];
-
-        if (IsPassword) {
-          PrintChar (L'*');
-        }
-      }
-
-      if (!IsPassword) {
-        PrintStringAt (Start + 1, Top + 3, BufferedString);
-      }
-      break;
-    }
-
-    gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
-    gST->ConOut->SetCursorPosition (gST->ConOut, Start + GetStringWidth (StringPtr) / 2, Top + 3);
-  } while (TRUE);
-
-}
-
-
-/**
-  This routine reads a numeric value from the user input.
-
-  @param  Selection         Pointer to current selection.
-  @param  MenuOption        Pointer to the current input menu.
-
-  @retval EFI_SUCCESS       If numerical input is read successfully
-  @retval EFI_DEVICE_ERROR  If operation fails
-
-**/
-EFI_STATUS
-GetNumericInput (
-  IN  UI_MENU_SELECTION           *Selection,
-  IN  UI_MENU_OPTION              *MenuOption
-  )
-{
-  EFI_STATUS              Status;
-  UINTN                   Column;
-  UINTN                   Row;
-  CHAR16                  InputText[23];
-  CHAR16                  FormattedNumber[22];
-  UINT64                  PreviousNumber[20];
-  UINTN                   Count;
-  UINTN                   Loop;
-  BOOLEAN                 ManualInput;
-  BOOLEAN                 HexInput;
-  BOOLEAN                 DateOrTime;
-  UINTN                   InputWidth;
-  UINT64                  EditValue;
-  UINT64                  Step;
-  UINT64                  Minimum;
-  UINT64                  Maximum;
-  UINTN                   EraseLen;
-  UINT8                   Digital;
-  EFI_INPUT_KEY           Key;
-  EFI_HII_VALUE           *QuestionValue;
-  FORM_BROWSER_FORM       *Form;
-  FORM_BROWSER_FORMSET    *FormSet;
-  FORM_BROWSER_STATEMENT  *Question;
-
-  Column            = MenuOption->OptCol;
-  Row               = MenuOption->Row;
-  PreviousNumber[0] = 0;
-  Count             = 0;
-  InputWidth        = 0;
-  Digital           = 0;
-
-  FormSet       = Selection->FormSet;
-  Form          = Selection->Form;
-  Question      = MenuOption->ThisTag;
-  QuestionValue = &Question->HiiValue;
-  Step          = Question->Step;
-  Minimum       = Question->Minimum;
-  Maximum       = Question->Maximum;
-
-  if ((Question->Operand == EFI_IFR_DATE_OP) || (Question->Operand == EFI_IFR_TIME_OP)) {
-    DateOrTime = TRUE;
-  } else {
-    DateOrTime = FALSE;
-  }
-
-  //
-  // Prepare Value to be edit
-  //
-  EraseLen = 0;
-  EditValue = 0;
-  if (Question->Operand == EFI_IFR_DATE_OP) {
-    Step = 1;
-    Minimum = 1;
-
-    switch (MenuOption->Sequence) {
-    case 0:
-      Maximum = 12;
-      EraseLen = 4;
-      EditValue = QuestionValue->Value.date.Month;
-      break;
-
-    case 1:
-      Maximum = 31;
-      EraseLen = 3;
-      EditValue = QuestionValue->Value.date.Day;
-      break;
-
-    case 2:
-      Maximum = 0xffff;
-      EraseLen = 5;
-      EditValue = QuestionValue->Value.date.Year;
-      break;
-
-    default:
-      break;
-    }
-  } else if (Question->Operand == EFI_IFR_TIME_OP) {
-    Step = 1;
-    Minimum = 0;
-
-    switch (MenuOption->Sequence) {
-    case 0:
-      Maximum = 23;
-      EraseLen = 4;
-      EditValue = QuestionValue->Value.time.Hour;
-      break;
-
-    case 1:
-      Maximum = 59;
-      EraseLen = 3;
-      EditValue = QuestionValue->Value.time.Minute;
-      break;
-
-    case 2:
-      Maximum = 59;
-      EraseLen = 3;
-      EditValue = QuestionValue->Value.time.Second;
-      break;
-
-    default:
-      break;
-    }
-  } else {
-    //
-    // Numeric
-    //
-    EraseLen = gOptionBlockWidth;
-    EditValue = QuestionValue->Value.u64;
-    if (Maximum == 0) {
-      Maximum = (UINT64) -1;
-    }
-  }
-
-  if (Step == 0) {
-    ManualInput = TRUE;
-  } else {
-    ManualInput = FALSE;
-  }
-
-  if ((Question->Operand == EFI_IFR_NUMERIC_OP) &&
-      ((Question->Flags & EFI_IFR_DISPLAY) == EFI_IFR_DISPLAY_UINT_HEX)) {
-    HexInput = TRUE;
-  } else {
-    HexInput = FALSE;
-  }
-
-  if (ManualInput) {
-    if (HexInput) {
-      InputWidth = Question->StorageWidth * 2;
-    } else {
-      switch (Question->StorageWidth) {
-      case 1:
-        InputWidth = 3;
-        break;
-
-      case 2:
-        InputWidth = 5;
-        break;
-
-      case 4:
-        InputWidth = 10;
-        break;
-
-      case 8:
-        InputWidth = 20;
-        break;
-
-      default:
-        InputWidth = 0;
-        break;
-      }
-    }
-
-    InputText[0] = LEFT_NUMERIC_DELIMITER;
-    SetUnicodeMem (InputText + 1, InputWidth, L' ');
-    InputText[InputWidth + 1] = RIGHT_NUMERIC_DELIMITER;
-    InputText[InputWidth + 2] = L'\0';
-
-    PrintAt (Column, Row, InputText);
-    Column++;
-  }
-
-  //
-  // First time we enter this handler, we need to check to see if
-  // we were passed an increment or decrement directive
-  //
-  do {
-    Key.UnicodeChar = CHAR_NULL;
-    if (gDirection != 0) {
-      Key.ScanCode  = gDirection;
-      gDirection    = 0;
-      goto TheKey2;
-    }
-
-    Status = WaitForKeyStroke (&Key);
-
-TheKey2:
-    switch (Key.UnicodeChar) {
-
-    case '+':
-    case '-':
-      if (Key.UnicodeChar == '+') {
-        Key.ScanCode = SCAN_RIGHT;
-      } else {
-        Key.ScanCode = SCAN_LEFT;
-      }
-      Key.UnicodeChar = CHAR_NULL;
-      goto TheKey2;
-
-    case CHAR_NULL:
-      switch (Key.ScanCode) {
-      case SCAN_LEFT:
-      case SCAN_RIGHT:
-        if (DateOrTime) {
-          //
-          // By setting this value, we will return back to the caller.
-          // We need to do this since an auto-refresh will destroy the adjustment
-          // based on what the real-time-clock is showing.  So we always commit
-          // upon changing the value.
-          //
-          gDirection = SCAN_DOWN;
-        }
-
-        if (!ManualInput) {
-          if (Key.ScanCode == SCAN_LEFT) {
-            if (EditValue > Step) {
-              EditValue = EditValue - Step;
-            } else {
-              EditValue = Minimum;
-            }
-          } else if (Key.ScanCode == SCAN_RIGHT) {
-            EditValue = EditValue + Step;
-            if (EditValue > Maximum) {
-              EditValue = Maximum;
-            }
-          }
-
-          ZeroMem (FormattedNumber, 21 * sizeof (CHAR16));
-          if (Question->Operand == EFI_IFR_DATE_OP) {
-            if (MenuOption->Sequence == 2) {
-              //
-              // Year
-              //
-              UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%04d", EditValue);
-            } else {
-              //
-              // Month/Day
-              //
-              UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%02d", EditValue);
-            }
-
-            if (MenuOption->Sequence == 0) {
-              FormattedNumber[EraseLen - 2] = DATE_SEPARATOR;
-            } else if (MenuOption->Sequence == 1) {
-              FormattedNumber[EraseLen - 1] = DATE_SEPARATOR;
-            }
-          } else if (Question->Operand == EFI_IFR_TIME_OP) {
-            UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%02d", EditValue);
-
-            if (MenuOption->Sequence == 0) {
-              FormattedNumber[EraseLen - 2] = TIME_SEPARATOR;
-            } else if (MenuOption->Sequence == 1) {
-              FormattedNumber[EraseLen - 1] = TIME_SEPARATOR;
-            }
-          } else {
-            QuestionValue->Value.u64 = EditValue;
-            PrintFormattedNumber (Question, FormattedNumber, 21 * sizeof (CHAR16));
-          }
-
-          gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
-          for (Loop = 0; Loop < EraseLen; Loop++) {
-            PrintAt (MenuOption->OptCol + Loop, MenuOption->Row, L" ");
-          }
-          gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT);
-
-          if (MenuOption->Sequence == 0) {
-            PrintCharAt (MenuOption->OptCol, Row, LEFT_NUMERIC_DELIMITER);
-            Column = MenuOption->OptCol + 1;
-          }
-
-          PrintStringAt (Column, Row, FormattedNumber);
-
-          if (!DateOrTime || MenuOption->Sequence == 2) {
-            PrintChar (RIGHT_NUMERIC_DELIMITER);
-          }
-        }
-        break;
-
-      case SCAN_UP:
-      case SCAN_DOWN:
-        goto EnterCarriageReturn;
-
-      case SCAN_ESC:
-        return EFI_DEVICE_ERROR;
-
-      default:
-        break;
-      }
-
-      break;
-
-EnterCarriageReturn:
-
-    case CHAR_CARRIAGE_RETURN:
-      //
-      // Store Edit value back to Question
-      //
-      if (Question->Operand == EFI_IFR_DATE_OP) {
-        switch (MenuOption->Sequence) {
-        case 0:
-          QuestionValue->Value.date.Month = (UINT8) EditValue;
-          break;
-
-        case 1:
-          QuestionValue->Value.date.Day = (UINT8) EditValue;
-          break;
-
-        case 2:
-          QuestionValue->Value.date.Year = (UINT16) EditValue;
-          break;
-
-        default:
-          break;
-        }
-      } else if (Question->Operand == EFI_IFR_TIME_OP) {
-        switch (MenuOption->Sequence) {
-        case 0:
-          QuestionValue->Value.time.Hour = (UINT8) EditValue;
-          break;
-
-        case 1:
-          QuestionValue->Value.time.Minute = (UINT8) EditValue;
-          break;
-
-        case 2:
-          QuestionValue->Value.time.Second = (UINT8) EditValue;
-          break;
-
-        default:
-          break;
-        }
-      } else {
-        //
-        // Numeric
-        //
-        QuestionValue->Value.u64 = EditValue;
-      }
-
-      //
-      // Check to see if the Value is something reasonable against consistency limitations.
-      // If not, let's kick the error specified.
-      //
-      Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);
-      if (EFI_ERROR (Status)) {
-        //
-        // Input value is not valid, restore Question Value
-        //
-        GetQuestionValue (FormSet, Form, Question, TRUE);
-      } else {
-        SetQuestionValue (FormSet, Form, Question, TRUE);
-        if (!DateOrTime || (Question->Storage != NULL)) {
-          //
-          // NV flag is unnecessary for RTC type of Date/Time
-          //
-          UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);
-        }
-      }
-
-      return Status;
-      break;
-
-    case CHAR_BACKSPACE:
-      if (ManualInput) {
-        if (Count == 0) {
-          break;
-        }
-        //
-        // Remove a character
-        //
-        EditValue = PreviousNumber[Count - 1];
-        UpdateStatusBar (INPUT_ERROR, Question->QuestionFlags, FALSE);
-        Count--;
-        Column--;
-        PrintAt (Column, Row, L" ");
-      }
-      break;
-
-    default:
-      if (ManualInput) {
-        if (HexInput) {
-          if (!IsHexDigit (&Digital, Key.UnicodeChar)) {
-            UpdateStatusBar (INPUT_ERROR, Question->QuestionFlags, TRUE);
-            break;
-          }
-        } else {
-          if (Key.UnicodeChar > L'9' || Key.UnicodeChar < L'0') {
-            UpdateStatusBar (INPUT_ERROR, Question->QuestionFlags, TRUE);
-            break;
-          }
-        }
-
-        //
-        // If Count exceed input width, there is no way more is valid
-        //
-        if (Count >= InputWidth) {
-          break;
-        }
-        //
-        // Someone typed something valid!
-        //
-        if (Count != 0) {
-          if (HexInput) {
-            EditValue = LShiftU64 (EditValue, 4) + Digital;
-          } else {
-            EditValue = MultU64x32 (EditValue, 10) + (Key.UnicodeChar - L'0');
-          }
-        } else {
-          if (HexInput) {
-            EditValue = Digital;
-          } else {
-            EditValue = Key.UnicodeChar - L'0';
-          }
-        }
-
-        if (EditValue > Maximum) {
-          UpdateStatusBar (INPUT_ERROR, Question->QuestionFlags, TRUE);
-          EditValue = PreviousNumber[Count];
-          break;
-        } else {
-          UpdateStatusBar (INPUT_ERROR, Question->QuestionFlags, FALSE);
-        }
-
-        Count++;
-        PreviousNumber[Count] = EditValue;
-
-        PrintCharAt (Column, Row, Key.UnicodeChar);
-        Column++;
-      }
-      break;
-    }
-  } while (TRUE);
-
-}
-
-
-/**
-  Get selection for OneOf and OrderedList (Left/Right will be ignored).
-
-  @param  Selection         Pointer to current selection.
-  @param  MenuOption        Pointer to the current input menu.
-
-  @retval EFI_SUCCESS       If Option input is processed successfully
-  @retval EFI_DEVICE_ERROR  If operation fails
-
-**/
-EFI_STATUS
-GetSelectionInputPopUp (
-  IN  UI_MENU_SELECTION           *Selection,
-  IN  UI_MENU_OPTION              *MenuOption
-  )
-{
-  EFI_STATUS              Status;
-  EFI_INPUT_KEY           Key;
-  UINTN                   Index;
-  CHAR16                  *StringPtr;
-  CHAR16                  *TempStringPtr;
-  UINTN                   Index2;
-  UINTN                   TopOptionIndex;
-  UINTN                   HighlightOptionIndex;
-  UINTN                   Start;
-  UINTN                   End;
-  UINTN                   Top;
-  UINTN                   Bottom;
-  UINTN                   PopUpMenuLines;
-  UINTN                   MenuLinesInView;
-  UINTN                   PopUpWidth;
-  CHAR16                  Character;
-  INT32                   SavedAttribute;
-  BOOLEAN                 ShowDownArrow;
-  BOOLEAN                 ShowUpArrow;
-  UINTN                   DimensionsWidth;
-  LIST_ENTRY              *Link;
-  BOOLEAN                 OrderedList;
-  UINT8                   *ValueArray;
-  EFI_HII_VALUE           HiiValue;
-  EFI_HII_VALUE           *HiiValueArray;
-  UINTN                   OptionCount;
-  QUESTION_OPTION         *OneOfOption;
-  QUESTION_OPTION         *CurrentOption;
-  FORM_BROWSER_STATEMENT  *Question;
-
-  DimensionsWidth   = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
-
-  ValueArray        = NULL;
-  CurrentOption     = NULL;
-  ShowDownArrow     = FALSE;
-  ShowUpArrow       = FALSE;
-
-  StringPtr = AllocateZeroPool ((gOptionBlockWidth + 1) * 2);
-  ASSERT (StringPtr);
-
-  Question = MenuOption->ThisTag;
-  if (Question->Operand == EFI_IFR_ORDERED_LIST_OP) {
-    ValueArray = Question->BufferValue;
-    OrderedList = TRUE;
-  } else {
-    OrderedList = FALSE;
-  }
-
-  //
-  // Calculate Option count
-  //
-  if (OrderedList) {
-    for (Index = 0; Index < Question->MaxContainers; Index++) {
-      if (ValueArray[Index] == 0) {
-        break;
-      }
-    }
-
-    OptionCount = Index;
-  } else {
-    OptionCount = 0;
-    Link = GetFirstNode (&Question->OptionListHead);
-    while (!IsNull (&Question->OptionListHead, Link)) {
-      OneOfOption = QUESTION_OPTION_FROM_LINK (Link);
-
-      OptionCount++;
-
-      Link = GetNextNode (&Question->OptionListHead, Link);
-    }
-  }
-
-  //
-  // Prepare HiiValue array
-  //
-  HiiValueArray = AllocateZeroPool (OptionCount * sizeof (EFI_HII_VALUE));
-  ASSERT (HiiValueArray != NULL);
-  Link = GetFirstNode (&Question->OptionListHead);
-  for (Index = 0; Index < OptionCount; Index++) {
-    if (OrderedList) {
-      HiiValueArray[Index].Type = EFI_IFR_TYPE_NUM_SIZE_8;
-      HiiValueArray[Index].Value.u8 = ValueArray[Index];
-    } else {
-      OneOfOption = QUESTION_OPTION_FROM_LINK (Link);
-      CopyMem (&HiiValueArray[Index], &OneOfOption->Value, sizeof (EFI_HII_VALUE));
-      Link = GetNextNode (&Question->OptionListHead, Link);
-    }
-  }
-
-  //
-  // Move Suppressed Option to list tail
-  //
-  PopUpMenuLines = 0;
-  for (Index = 0; Index < OptionCount; Index++) {
-    OneOfOption = ValueToOption (Question, &HiiValueArray[OptionCount - Index - 1]);
-    if (OneOfOption == NULL) {
-      return EFI_NOT_FOUND;
-    }
-
-    RemoveEntryList (&OneOfOption->Link);
-
-    if ((OneOfOption->SuppressExpression != NULL) &&
-        (OneOfOption->SuppressExpression->Result.Value.b)) {
-      //
-      // This option is suppressed, insert to tail
-      //
-      InsertTailList (&Question->OptionListHead, &OneOfOption->Link);
-    } else {
-      //
-      // Insert to head
-      //
-      InsertHeadList (&Question->OptionListHead, &OneOfOption->Link);
-
-      PopUpMenuLines++;
-    }
-  }
-
-  //
-  // Get the number of one of options present and its size
-  //
-  PopUpWidth = 0;
-  HighlightOptionIndex = 0;
-  Link = GetFirstNode (&Question->OptionListHead);
-  for (Index = 0; Index < PopUpMenuLines; Index++) {
-    OneOfOption = QUESTION_OPTION_FROM_LINK (Link);
-
-    StringPtr = GetToken (OneOfOption->Text, MenuOption->Handle);
-    if (StrLen (StringPtr) > PopUpWidth) {
-      PopUpWidth = StrLen (StringPtr);
-    }
-    gBS->FreePool (StringPtr);
-
-    if (!OrderedList && CompareHiiValue (&Question->HiiValue, &OneOfOption->Value, NULL) == 0) {
-      //
-      // Find current selected Option for OneOf
-      //
-      HighlightOptionIndex = Index;
-    }
-
-    Link = GetNextNode (&Question->OptionListHead, Link);
-  }
-
-  //
-  // Perform popup menu initialization.
-  //
-  PopUpWidth = PopUpWidth + POPUP_PAD_SPACE_COUNT;
-
-  SavedAttribute = gST->ConOut->Mode->Attribute;
-  gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
-
-  if ((PopUpWidth + POPUP_FRAME_WIDTH) > DimensionsWidth) {
-    PopUpWidth = DimensionsWidth - POPUP_FRAME_WIDTH;
-  }
-
-  Start  = (DimensionsWidth - PopUpWidth - POPUP_FRAME_WIDTH) / 2 + gScreenDimensions.LeftColumn;
-  End    = Start + PopUpWidth + POPUP_FRAME_WIDTH;
-  Top    = gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT;
-  Bottom = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT - 1;
-
-  MenuLinesInView = Bottom - Top - 1;
-  if (MenuLinesInView >= PopUpMenuLines) {
-    Top     = Top + (MenuLinesInView - PopUpMenuLines) / 2;
-    Bottom  = Top + PopUpMenuLines + 1;
-  } else {
-    ShowDownArrow = TRUE;
-  }
-
-  if (HighlightOptionIndex > (MenuLinesInView - 1)) {
-    TopOptionIndex = HighlightOptionIndex - MenuLinesInView + 1;
-  } else {
-    TopOptionIndex = 0;
-  }
-
-  do {
-    //
-    // Clear that portion of the screen
-    //
-    ClearLines (Start, End, Top, Bottom, POPUP_TEXT | POPUP_BACKGROUND);
-
-    //
-    // Draw "One of" pop-up menu
-    //
-    Character = BOXDRAW_DOWN_RIGHT;
-    PrintCharAt (Start, Top, Character);
-    for (Index = Start; Index + 2 < End; Index++) {
-      if ((ShowUpArrow) && ((Index + 1) == (Start + End) / 2)) {
-        Character = GEOMETRICSHAPE_UP_TRIANGLE;
-      } else {
-        Character = BOXDRAW_HORIZONTAL;
-      }
-
-      PrintChar (Character);
-    }
-
-    Character = BOXDRAW_DOWN_LEFT;
-    PrintChar (Character);
-    Character = BOXDRAW_VERTICAL;
-    for (Index = Top + 1; Index < Bottom; Index++) {
-      PrintCharAt (Start, Index, Character);
-      PrintCharAt (End - 1, Index, Character);
-    }
-
-    //
-    // Move to top Option
-    //
-    Link = GetFirstNode (&Question->OptionListHead);
-    for (Index = 0; Index < TopOptionIndex; Index++) {
-      Link = GetNextNode (&Question->OptionListHead, Link);
-    }
-
-    //
-    // Display the One of options
-    //
-    Index2 = Top + 1;
-    for (Index = TopOptionIndex; (Index < PopUpMenuLines) && (Index2 < Bottom); Index++) {
-      OneOfOption = QUESTION_OPTION_FROM_LINK (Link);
-      Link = GetNextNode (&Question->OptionListHead, Link);
-
-      StringPtr = GetToken (OneOfOption->Text, MenuOption->Handle);
-      //
-      // If the string occupies multiple lines, truncate it to fit in one line,
-      // and append a "..." for indication.
-      //
-      if (StrLen (StringPtr) > (PopUpWidth - 1)) {
-        TempStringPtr = AllocateZeroPool (sizeof (CHAR16) * (PopUpWidth - 1));
-        ASSERT ( TempStringPtr != NULL );
-        CopyMem (TempStringPtr, StringPtr, (sizeof (CHAR16) * (PopUpWidth - 5)));
-        gBS->FreePool (StringPtr);
-        StringPtr = TempStringPtr;
-        StrCat (StringPtr, L"...");
-      }
-
-      if (Index == HighlightOptionIndex) {
-          //
-          // Highlight the selected one
-          //
-          CurrentOption = OneOfOption;
-
-          gST->ConOut->SetAttribute (gST->ConOut, PICKLIST_HIGHLIGHT_TEXT | PICKLIST_HIGHLIGHT_BACKGROUND);
-          PrintStringAt (Start + 2, Index2, StringPtr);
-          gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
-        } else {
-          gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
-          PrintStringAt (Start + 2, Index2, StringPtr);
-        }
-
-      Index2++;
-      gBS->FreePool (StringPtr);
-    }
-
-    Character = BOXDRAW_UP_RIGHT;
-    PrintCharAt (Start, Bottom, Character);
-    for (Index = Start; Index + 2 < End; Index++) {
-      if ((ShowDownArrow) && ((Index + 1) == (Start + End) / 2)) {
-        Character = GEOMETRICSHAPE_DOWN_TRIANGLE;
-      } else {
-        Character = BOXDRAW_HORIZONTAL;
-      }
-
-      PrintChar (Character);
-    }
-
-    Character = BOXDRAW_UP_LEFT;
-    PrintChar (Character);
-
-    //
-    // Get User selection
-    //
-    Key.UnicodeChar = CHAR_NULL;
-    if ((gDirection == SCAN_UP) || (gDirection == SCAN_DOWN)) {
-      Key.ScanCode  = gDirection;
-      gDirection    = 0;
-      goto TheKey;
-    }
-
-    Status = WaitForKeyStroke (&Key);
-
-TheKey:
-    switch (Key.UnicodeChar) {
-    case '+':
-      if (OrderedList) {
-        if ((TopOptionIndex > 0) && (TopOptionIndex == HighlightOptionIndex)) {
-          //
-          // Highlight reaches the top of the popup window, scroll one menu item.
-          //
-          TopOptionIndex--;
-          ShowDownArrow = TRUE;
-        }
-
-        if (TopOptionIndex == 0) {
-          ShowUpArrow = FALSE;
-        }
-
-        if (HighlightOptionIndex > 0) {
-          HighlightOptionIndex--;
-
-          SwapListEntries (CurrentOption->Link.BackLink, &CurrentOption->Link);
-        }
-      }
-      break;
-
-    case '-':
-      //
-      // If an ordered list op-code, we will allow for a popup of +/- keys
-      // to create an ordered list of items
-      //
-      if (OrderedList) {
-        if (((TopOptionIndex + MenuLinesInView) < PopUpMenuLines) &&
-            (HighlightOptionIndex == (TopOptionIndex + MenuLinesInView - 1))) {
-          //
-          // Highlight reaches the bottom of the popup window, scroll one menu item.
-          //
-          TopOptionIndex++;
-          ShowUpArrow = TRUE;
-        }
-
-        if ((TopOptionIndex + MenuLinesInView) == PopUpMenuLines) {
-          ShowDownArrow = FALSE;
-        }
-
-        if (HighlightOptionIndex < (PopUpMenuLines - 1)) {
-          HighlightOptionIndex++;
-
-          SwapListEntries (&CurrentOption->Link, CurrentOption->Link.ForwardLink);
-        }
-      }
-      break;
-
-    case CHAR_NULL:
-      switch (Key.ScanCode) {
-      case SCAN_UP:
-      case SCAN_DOWN:
-        if (Key.ScanCode == SCAN_UP) {
-          if ((TopOptionIndex > 0) && (TopOptionIndex == HighlightOptionIndex)) {
-            //
-            // Highlight reaches the top of the popup window, scroll one menu item.
-            //
-            TopOptionIndex--;
-            ShowDownArrow = TRUE;
-          }
-
-          if (TopOptionIndex == 0) {
-            ShowUpArrow = FALSE;
-          }
-
-          if (HighlightOptionIndex > 0) {
-            HighlightOptionIndex--;
-          }
-        } else {
-          if (((TopOptionIndex + MenuLinesInView) < PopUpMenuLines) &&
-              (HighlightOptionIndex == (TopOptionIndex + MenuLinesInView - 1))) {
-            //
-            // Highlight reaches the bottom of the popup window, scroll one menu item.
-            //
-            TopOptionIndex++;
-            ShowUpArrow = TRUE;
-          }
-
-          if ((TopOptionIndex + MenuLinesInView) == PopUpMenuLines) {
-            ShowDownArrow = FALSE;
-          }
-
-          if (HighlightOptionIndex < (PopUpMenuLines - 1)) {
-            HighlightOptionIndex++;
-          }
-        }
-        break;
-
-      case SCAN_ESC:
-        gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);
-
-        //
-        // Restore link list order for orderedlist
-        //
-        if (OrderedList) {
-          HiiValue.Type = EFI_IFR_TYPE_NUM_SIZE_8;
-          HiiValue.Value.u64 = 0;
-          for (Index = 0; Index < Question->MaxContainers; Index++) {
-            HiiValue.Value.u8 = ValueArray[Index];
-            if (HiiValue.Value.u8) {
-              break;
-            }
-
-            OneOfOption = ValueToOption (Question, &HiiValue);
-            if (OneOfOption == NULL) {
-              return EFI_NOT_FOUND;
-            }
-
-            RemoveEntryList (&OneOfOption->Link);
-            InsertTailList (&Question->OptionListHead, &OneOfOption->Link);
-          }
-        }
-
-        gBS->FreePool (HiiValueArray);
-        return EFI_DEVICE_ERROR;
-
-      default:
-        break;
-      }
-
-      break;
-
-    case CHAR_CARRIAGE_RETURN:
-      //
-      // return the current selection
-      //
-      if (OrderedList) {
-        Index = 0;
-        Link = GetFirstNode (&Question->OptionListHead);
-        while (!IsNull (&Question->OptionListHead, Link)) {
-          OneOfOption = QUESTION_OPTION_FROM_LINK (Link);
-
-          Question->BufferValue[Index] = OneOfOption->Value.Value.u8;
-
-          Index++;
-          if (Index > Question->MaxContainers) {
-            break;
-          }
-
-          Link = GetNextNode (&Question->OptionListHead, Link);
-        }
-      } else {
-        CopyMem (&Question->HiiValue, &CurrentOption->Value, sizeof (EFI_HII_VALUE));
-      }
-
-      gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);
-      gBS->FreePool (HiiValueArray);
-
-      Status = ValidateQuestion (Selection->FormSet, Selection->Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);
-      if (EFI_ERROR (Status)) {
-        //
-        // Input value is not valid, restore Question Value
-        //
-        GetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE);
-      } else {
-        SetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE);
-        UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);
-      }
-
-      return Status;
-
-    default:
-      break;
-    }
-  } while (TRUE);
-
-}
-
-EFI_STATUS
-WaitForKeyStroke (
-  OUT  EFI_INPUT_KEY           *Key
-  )
-{
-  EFI_STATUS  Status;
-
-  do {
-    UiWaitForSingleEvent (gST->ConIn->WaitForKey, 0, 0);
-    Status = gST->ConIn->ReadKeyStroke (gST->ConIn, Key);
-  } while (EFI_ERROR(Status));
-
-  return Status;
-}
+/** @file\r
+Implementation for handling user input from the User Interfaces.\r
+\r
+Copyright (c) 2004 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "Ui.h"\r
+#include "Setup.h"\r
+\r
+\r
+/**\r
+  Get string or password input from user.\r
+\r
+  @param  MenuOption        Pointer to the current input menu.\r
+  @param  Prompt            The prompt string shown on popup window.\r
+  @param  StringPtr         Destination for use input string.\r
+\r
+  @retval EFI_SUCCESS       If string input is read successfully\r
+  @retval EFI_DEVICE_ERROR  If operation fails\r
+\r
+**/\r
+EFI_STATUS\r
+ReadString (\r
+  IN  UI_MENU_OPTION              *MenuOption,\r
+  IN  CHAR16                      *Prompt,\r
+  OUT CHAR16                      *StringPtr\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  EFI_INPUT_KEY           Key;\r
+  CHAR16                  NullCharacter;\r
+  UINTN                   ScreenSize;\r
+  CHAR16                  Space[2];\r
+  CHAR16                  KeyPad[2];\r
+  CHAR16                  *TempString;\r
+  CHAR16                  *BufferedString;\r
+  UINTN                   Index;\r
+  UINTN                   Count;\r
+  UINTN                   Start;\r
+  UINTN                   Top;\r
+  UINTN                   DimensionsWidth;\r
+  UINTN                   DimensionsHeight;\r
+  BOOLEAN                 CursorVisible;\r
+  UINTN                   Minimum;\r
+  UINTN                   Maximum;\r
+  FORM_BROWSER_STATEMENT  *Question;\r
+  BOOLEAN                 IsPassword;\r
+\r
+  DimensionsWidth  = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;\r
+  DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;\r
+\r
+  NullCharacter    = CHAR_NULL;\r
+  ScreenSize       = GetStringWidth (Prompt) / sizeof (CHAR16);\r
+  Space[0]         = L' ';\r
+  Space[1]         = CHAR_NULL;\r
+\r
+  Question         = MenuOption->ThisTag;\r
+  Minimum          = (UINTN) Question->Minimum;\r
+  Maximum          = (UINTN) Question->Maximum;\r
+\r
+  if (Question->Operand == EFI_IFR_PASSWORD_OP) {\r
+    IsPassword = TRUE;\r
+  } else {\r
+    IsPassword = FALSE;\r
+  }\r
+\r
+  TempString = AllocateZeroPool ((Maximum + 1)* sizeof (CHAR16));\r
+  ASSERT (TempString);\r
+\r
+  if (ScreenSize < (Maximum + 1)) {\r
+    ScreenSize = Maximum + 1;\r
+  }\r
+\r
+  if ((ScreenSize + 2) > DimensionsWidth) {\r
+    ScreenSize = DimensionsWidth - 2;\r
+  }\r
+\r
+  BufferedString = AllocateZeroPool (ScreenSize * 2);\r
+  ASSERT (BufferedString);\r
+\r
+  Start = (DimensionsWidth - ScreenSize - 2) / 2 + gScreenDimensions.LeftColumn + 1;\r
+  Top   = ((DimensionsHeight - 6) / 2) + gScreenDimensions.TopRow - 1;\r
+\r
+  //\r
+  // Display prompt for string\r
+  //\r
+  CreatePopUp (ScreenSize, 4, &NullCharacter, Prompt, Space, &NullCharacter);\r
+\r
+  gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_BLACK, EFI_LIGHTGRAY));\r
+\r
+  CursorVisible = gST->ConOut->Mode->CursorVisible;\r
+  gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
+\r
+  do {\r
+    Status = WaitForKeyStroke (&Key);\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_BLACK, EFI_LIGHTGRAY));\r
+    switch (Key.UnicodeChar) {\r
+    case CHAR_NULL:\r
+      switch (Key.ScanCode) {\r
+      case SCAN_LEFT:\r
+        break;\r
+\r
+      case SCAN_RIGHT:\r
+        break;\r
+\r
+      case SCAN_ESC:\r
+        gBS->FreePool (TempString);\r
+        gBS->FreePool (BufferedString);\r
+        gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
+        gST->ConOut->EnableCursor (gST->ConOut, CursorVisible);\r
+        return EFI_DEVICE_ERROR;\r
+\r
+      default:\r
+        break;\r
+      }\r
+\r
+      break;\r
+\r
+    case CHAR_CARRIAGE_RETURN:\r
+      if (GetStringWidth (StringPtr) >= ((Minimum + 1) * sizeof (CHAR16))) {\r
+\r
+        gBS->FreePool (TempString);\r
+        gBS->FreePool (BufferedString);\r
+        gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
+        gST->ConOut->EnableCursor (gST->ConOut, CursorVisible);\r
+        return EFI_SUCCESS;\r
+      } else {\r
+        //\r
+        // Simply create a popup to tell the user that they had typed in too few characters.\r
+        // To save code space, we can then treat this as an error and return back to the menu.\r
+        //\r
+        do {\r
+          CreateDialog (4, TRUE, 0, NULL, &Key, &NullCharacter, gMiniString, gPressEnter, &NullCharacter);\r
+        } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+\r
+        gBS->FreePool (TempString);\r
+        gBS->FreePool (BufferedString);\r
+        gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
+        gST->ConOut->EnableCursor (gST->ConOut, CursorVisible);\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+\r
+      break;\r
+\r
+    case CHAR_BACKSPACE:\r
+      if (StringPtr[0] != CHAR_NULL) {\r
+        for (Index = 0; StringPtr[Index] != CHAR_NULL; Index++) {\r
+          TempString[Index] = StringPtr[Index];\r
+        }\r
+        //\r
+        // Effectively truncate string by 1 character\r
+        //\r
+        TempString[Index - 1] = CHAR_NULL;\r
+        StrCpy (StringPtr, TempString);\r
+      }\r
+\r
+    default:\r
+      //\r
+      // If it is the beginning of the string, don't worry about checking maximum limits\r
+      //\r
+      if ((StringPtr[0] == CHAR_NULL) && (Key.UnicodeChar != CHAR_BACKSPACE)) {\r
+        StrnCpy (StringPtr, &Key.UnicodeChar, 1);\r
+        StrnCpy (TempString, &Key.UnicodeChar, 1);\r
+      } else if ((GetStringWidth (StringPtr) < ((Maximum + 1) * sizeof (CHAR16))) && (Key.UnicodeChar != CHAR_BACKSPACE)) {\r
+        KeyPad[0] = Key.UnicodeChar;\r
+        KeyPad[1] = CHAR_NULL;\r
+        StrCat (StringPtr, KeyPad);\r
+        StrCat (TempString, KeyPad);\r
+      }\r
+\r
+      //\r
+      // If the width of the input string is now larger than the screen, we nee to\r
+      // adjust the index to start printing portions of the string\r
+      //\r
+      SetUnicodeMem (BufferedString, ScreenSize - 1, L' ');\r
+      PrintStringAt (Start + 1, Top + 3, BufferedString);\r
+\r
+      if ((GetStringWidth (StringPtr) / 2) > (DimensionsWidth - 2)) {\r
+        Index = (GetStringWidth (StringPtr) / 2) - DimensionsWidth + 2;\r
+      } else {\r
+        Index = 0;\r
+      }\r
+\r
+      if (IsPassword) {\r
+        gST->ConOut->SetCursorPosition (gST->ConOut, Start + 1, Top + 3);\r
+      }\r
+\r
+      for (Count = 0; Index + 1 < GetStringWidth (StringPtr) / 2; Index++, Count++) {\r
+        BufferedString[Count] = StringPtr[Index];\r
+\r
+        if (IsPassword) {\r
+          PrintChar (L'*');\r
+        }\r
+      }\r
+\r
+      if (!IsPassword) {\r
+        PrintStringAt (Start + 1, Top + 3, BufferedString);\r
+      }\r
+      break;\r
+    }\r
+\r
+    gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
+    gST->ConOut->SetCursorPosition (gST->ConOut, Start + GetStringWidth (StringPtr) / 2, Top + 3);\r
+  } while (TRUE);\r
+\r
+}\r
+\r
+\r
+/**\r
+  This routine reads a numeric value from the user input.\r
+\r
+  @param  Selection         Pointer to current selection.\r
+  @param  MenuOption        Pointer to the current input menu.\r
+\r
+  @retval EFI_SUCCESS       If numerical input is read successfully\r
+  @retval EFI_DEVICE_ERROR  If operation fails\r
+\r
+**/\r
+EFI_STATUS\r
+GetNumericInput (\r
+  IN  UI_MENU_SELECTION           *Selection,\r
+  IN  UI_MENU_OPTION              *MenuOption\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  UINTN                   Column;\r
+  UINTN                   Row;\r
+  CHAR16                  InputText[23];\r
+  CHAR16                  FormattedNumber[22];\r
+  UINT64                  PreviousNumber[20];\r
+  UINTN                   Count;\r
+  UINTN                   Loop;\r
+  BOOLEAN                 ManualInput;\r
+  BOOLEAN                 HexInput;\r
+  BOOLEAN                 DateOrTime;\r
+  UINTN                   InputWidth;\r
+  UINT64                  EditValue;\r
+  UINT64                  Step;\r
+  UINT64                  Minimum;\r
+  UINT64                  Maximum;\r
+  UINTN                   EraseLen;\r
+  UINT8                   Digital;\r
+  EFI_INPUT_KEY           Key;\r
+  EFI_HII_VALUE           *QuestionValue;\r
+  FORM_BROWSER_FORM       *Form;\r
+  FORM_BROWSER_FORMSET    *FormSet;\r
+  FORM_BROWSER_STATEMENT  *Question;\r
+\r
+  Column            = MenuOption->OptCol;\r
+  Row               = MenuOption->Row;\r
+  PreviousNumber[0] = 0;\r
+  Count             = 0;\r
+  InputWidth        = 0;\r
+  Digital           = 0;\r
+\r
+  FormSet       = Selection->FormSet;\r
+  Form          = Selection->Form;\r
+  Question      = MenuOption->ThisTag;\r
+  QuestionValue = &Question->HiiValue;\r
+  Step          = Question->Step;\r
+  Minimum       = Question->Minimum;\r
+  Maximum       = Question->Maximum;\r
+\r
+  if ((Question->Operand == EFI_IFR_DATE_OP) || (Question->Operand == EFI_IFR_TIME_OP)) {\r
+    DateOrTime = TRUE;\r
+  } else {\r
+    DateOrTime = FALSE;\r
+  }\r
+\r
+  //\r
+  // Prepare Value to be edit\r
+  //\r
+  EraseLen = 0;\r
+  EditValue = 0;\r
+  if (Question->Operand == EFI_IFR_DATE_OP) {\r
+    Step = 1;\r
+    Minimum = 1;\r
+\r
+    switch (MenuOption->Sequence) {\r
+    case 0:\r
+      Maximum = 12;\r
+      EraseLen = 4;\r
+      EditValue = QuestionValue->Value.date.Month;\r
+      break;\r
+\r
+    case 1:\r
+      Maximum = 31;\r
+      EraseLen = 3;\r
+      EditValue = QuestionValue->Value.date.Day;\r
+      break;\r
+\r
+    case 2:\r
+      Maximum = 0xffff;\r
+      EraseLen = 5;\r
+      EditValue = QuestionValue->Value.date.Year;\r
+      break;\r
+\r
+    default:\r
+      break;\r
+    }\r
+  } else if (Question->Operand == EFI_IFR_TIME_OP) {\r
+    Step = 1;\r
+    Minimum = 0;\r
+\r
+    switch (MenuOption->Sequence) {\r
+    case 0:\r
+      Maximum = 23;\r
+      EraseLen = 4;\r
+      EditValue = QuestionValue->Value.time.Hour;\r
+      break;\r
+\r
+    case 1:\r
+      Maximum = 59;\r
+      EraseLen = 3;\r
+      EditValue = QuestionValue->Value.time.Minute;\r
+      break;\r
+\r
+    case 2:\r
+      Maximum = 59;\r
+      EraseLen = 3;\r
+      EditValue = QuestionValue->Value.time.Second;\r
+      break;\r
+\r
+    default:\r
+      break;\r
+    }\r
+  } else {\r
+    //\r
+    // Numeric\r
+    //\r
+    EraseLen = gOptionBlockWidth;\r
+    EditValue = QuestionValue->Value.u64;\r
+    if (Maximum == 0) {\r
+      Maximum = (UINT64) -1;\r
+    }\r
+  }\r
+\r
+  if (Step == 0) {\r
+    ManualInput = TRUE;\r
+  } else {\r
+    ManualInput = FALSE;\r
+  }\r
+\r
+  if ((Question->Operand == EFI_IFR_NUMERIC_OP) &&\r
+      ((Question->Flags & EFI_IFR_DISPLAY) == EFI_IFR_DISPLAY_UINT_HEX)) {\r
+    HexInput = TRUE;\r
+  } else {\r
+    HexInput = FALSE;\r
+  }\r
+\r
+  if (ManualInput) {\r
+    if (HexInput) {\r
+      InputWidth = Question->StorageWidth * 2;\r
+    } else {\r
+      switch (Question->StorageWidth) {\r
+      case 1:\r
+        InputWidth = 3;\r
+        break;\r
+\r
+      case 2:\r
+        InputWidth = 5;\r
+        break;\r
+\r
+      case 4:\r
+        InputWidth = 10;\r
+        break;\r
+\r
+      case 8:\r
+        InputWidth = 20;\r
+        break;\r
+\r
+      default:\r
+        InputWidth = 0;\r
+        break;\r
+      }\r
+    }\r
+\r
+    InputText[0] = LEFT_NUMERIC_DELIMITER;\r
+    SetUnicodeMem (InputText + 1, InputWidth, L' ');\r
+    InputText[InputWidth + 1] = RIGHT_NUMERIC_DELIMITER;\r
+    InputText[InputWidth + 2] = L'\0';\r
+\r
+    PrintAt (Column, Row, InputText);\r
+    Column++;\r
+  }\r
+\r
+  //\r
+  // First time we enter this handler, we need to check to see if\r
+  // we were passed an increment or decrement directive\r
+  //\r
+  do {\r
+    Key.UnicodeChar = CHAR_NULL;\r
+    if (gDirection != 0) {\r
+      Key.ScanCode  = gDirection;\r
+      gDirection    = 0;\r
+      goto TheKey2;\r
+    }\r
+\r
+    Status = WaitForKeyStroke (&Key);\r
+\r
+TheKey2:\r
+    switch (Key.UnicodeChar) {\r
+\r
+    case '+':\r
+    case '-':\r
+      if (Key.UnicodeChar == '+') {\r
+        Key.ScanCode = SCAN_RIGHT;\r
+      } else {\r
+        Key.ScanCode = SCAN_LEFT;\r
+      }\r
+      Key.UnicodeChar = CHAR_NULL;\r
+      goto TheKey2;\r
+\r
+    case CHAR_NULL:\r
+      switch (Key.ScanCode) {\r
+      case SCAN_LEFT:\r
+      case SCAN_RIGHT:\r
+        if (DateOrTime) {\r
+          //\r
+          // By setting this value, we will return back to the caller.\r
+          // We need to do this since an auto-refresh will destroy the adjustment\r
+          // based on what the real-time-clock is showing.  So we always commit\r
+          // upon changing the value.\r
+          //\r
+          gDirection = SCAN_DOWN;\r
+        }\r
+\r
+        if (!ManualInput) {\r
+          if (Key.ScanCode == SCAN_LEFT) {\r
+            if (EditValue > Step) {\r
+              EditValue = EditValue - Step;\r
+            } else {\r
+              EditValue = Minimum;\r
+            }\r
+          } else if (Key.ScanCode == SCAN_RIGHT) {\r
+            EditValue = EditValue + Step;\r
+            if (EditValue > Maximum) {\r
+              EditValue = Maximum;\r
+            }\r
+          }\r
+\r
+          ZeroMem (FormattedNumber, 21 * sizeof (CHAR16));\r
+          if (Question->Operand == EFI_IFR_DATE_OP) {\r
+            if (MenuOption->Sequence == 2) {\r
+              //\r
+              // Year\r
+              //\r
+              UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%04d", EditValue);\r
+            } else {\r
+              //\r
+              // Month/Day\r
+              //\r
+              UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%02d", EditValue);\r
+            }\r
+\r
+            if (MenuOption->Sequence == 0) {\r
+              FormattedNumber[EraseLen - 2] = DATE_SEPARATOR;\r
+            } else if (MenuOption->Sequence == 1) {\r
+              FormattedNumber[EraseLen - 1] = DATE_SEPARATOR;\r
+            }\r
+          } else if (Question->Operand == EFI_IFR_TIME_OP) {\r
+            UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%02d", EditValue);\r
+\r
+            if (MenuOption->Sequence == 0) {\r
+              FormattedNumber[EraseLen - 2] = TIME_SEPARATOR;\r
+            } else if (MenuOption->Sequence == 1) {\r
+              FormattedNumber[EraseLen - 1] = TIME_SEPARATOR;\r
+            }\r
+          } else {\r
+            QuestionValue->Value.u64 = EditValue;\r
+            PrintFormattedNumber (Question, FormattedNumber, 21 * sizeof (CHAR16));\r
+          }\r
+\r
+          gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);\r
+          for (Loop = 0; Loop < EraseLen; Loop++) {\r
+            PrintAt (MenuOption->OptCol + Loop, MenuOption->Row, L" ");\r
+          }\r
+          gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT);\r
+\r
+          if (MenuOption->Sequence == 0) {\r
+            PrintCharAt (MenuOption->OptCol, Row, LEFT_NUMERIC_DELIMITER);\r
+            Column = MenuOption->OptCol + 1;\r
+          }\r
+\r
+          PrintStringAt (Column, Row, FormattedNumber);\r
+\r
+          if (!DateOrTime || MenuOption->Sequence == 2) {\r
+            PrintChar (RIGHT_NUMERIC_DELIMITER);\r
+          }\r
+        }\r
+        break;\r
+\r
+      case SCAN_UP:\r
+      case SCAN_DOWN:\r
+        goto EnterCarriageReturn;\r
+\r
+      case SCAN_ESC:\r
+        return EFI_DEVICE_ERROR;\r
+\r
+      default:\r
+        break;\r
+      }\r
+\r
+      break;\r
+\r
+EnterCarriageReturn:\r
+\r
+    case CHAR_CARRIAGE_RETURN:\r
+      //\r
+      // Store Edit value back to Question\r
+      //\r
+      if (Question->Operand == EFI_IFR_DATE_OP) {\r
+        switch (MenuOption->Sequence) {\r
+        case 0:\r
+          QuestionValue->Value.date.Month = (UINT8) EditValue;\r
+          break;\r
+\r
+        case 1:\r
+          QuestionValue->Value.date.Day = (UINT8) EditValue;\r
+          break;\r
+\r
+        case 2:\r
+          QuestionValue->Value.date.Year = (UINT16) EditValue;\r
+          break;\r
+\r
+        default:\r
+          break;\r
+        }\r
+      } else if (Question->Operand == EFI_IFR_TIME_OP) {\r
+        switch (MenuOption->Sequence) {\r
+        case 0:\r
+          QuestionValue->Value.time.Hour = (UINT8) EditValue;\r
+          break;\r
+\r
+        case 1:\r
+          QuestionValue->Value.time.Minute = (UINT8) EditValue;\r
+          break;\r
+\r
+        case 2:\r
+          QuestionValue->Value.time.Second = (UINT8) EditValue;\r
+          break;\r
+\r
+        default:\r
+          break;\r
+        }\r
+      } else {\r
+        //\r
+        // Numeric\r
+        //\r
+        QuestionValue->Value.u64 = EditValue;\r
+      }\r
+\r
+      //\r
+      // Check to see if the Value is something reasonable against consistency limitations.\r
+      // If not, let's kick the error specified.\r
+      //\r
+      Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);\r
+      if (EFI_ERROR (Status)) {\r
+        //\r
+        // Input value is not valid, restore Question Value\r
+        //\r
+        GetQuestionValue (FormSet, Form, Question, TRUE);\r
+      } else {\r
+        SetQuestionValue (FormSet, Form, Question, TRUE);\r
+        if (!DateOrTime || (Question->Storage != NULL)) {\r
+          //\r
+          // NV flag is unnecessary for RTC type of Date/Time\r
+          //\r
+          UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
+        }\r
+      }\r
+\r
+      return Status;\r
+      break;\r
+\r
+    case CHAR_BACKSPACE:\r
+      if (ManualInput) {\r
+        if (Count == 0) {\r
+          break;\r
+        }\r
+        //\r
+        // Remove a character\r
+        //\r
+        EditValue = PreviousNumber[Count - 1];\r
+        UpdateStatusBar (INPUT_ERROR, Question->QuestionFlags, FALSE);\r
+        Count--;\r
+        Column--;\r
+        PrintAt (Column, Row, L" ");\r
+      }\r
+      break;\r
+\r
+    default:\r
+      if (ManualInput) {\r
+        if (HexInput) {\r
+          if (!IsHexDigit (&Digital, Key.UnicodeChar)) {\r
+            UpdateStatusBar (INPUT_ERROR, Question->QuestionFlags, TRUE);\r
+            break;\r
+          }\r
+        } else {\r
+          if (Key.UnicodeChar > L'9' || Key.UnicodeChar < L'0') {\r
+            UpdateStatusBar (INPUT_ERROR, Question->QuestionFlags, TRUE);\r
+            break;\r
+          }\r
+        }\r
+\r
+        //\r
+        // If Count exceed input width, there is no way more is valid\r
+        //\r
+        if (Count >= InputWidth) {\r
+          break;\r
+        }\r
+        //\r
+        // Someone typed something valid!\r
+        //\r
+        if (Count != 0) {\r
+          if (HexInput) {\r
+            EditValue = LShiftU64 (EditValue, 4) + Digital;\r
+          } else {\r
+            EditValue = MultU64x32 (EditValue, 10) + (Key.UnicodeChar - L'0');\r
+          }\r
+        } else {\r
+          if (HexInput) {\r
+            EditValue = Digital;\r
+          } else {\r
+            EditValue = Key.UnicodeChar - L'0';\r
+          }\r
+        }\r
+\r
+        if (EditValue > Maximum) {\r
+          UpdateStatusBar (INPUT_ERROR, Question->QuestionFlags, TRUE);\r
+          EditValue = PreviousNumber[Count];\r
+          break;\r
+        } else {\r
+          UpdateStatusBar (INPUT_ERROR, Question->QuestionFlags, FALSE);\r
+        }\r
+\r
+        Count++;\r
+        PreviousNumber[Count] = EditValue;\r
+\r
+        PrintCharAt (Column, Row, Key.UnicodeChar);\r
+        Column++;\r
+      }\r
+      break;\r
+    }\r
+  } while (TRUE);\r
+\r
+}\r
+\r
+\r
+/**\r
+  Get selection for OneOf and OrderedList (Left/Right will be ignored).\r
+\r
+  @param  Selection         Pointer to current selection.\r
+  @param  MenuOption        Pointer to the current input menu.\r
+\r
+  @retval EFI_SUCCESS       If Option input is processed successfully\r
+  @retval EFI_DEVICE_ERROR  If operation fails\r
+\r
+**/\r
+EFI_STATUS\r
+GetSelectionInputPopUp (\r
+  IN  UI_MENU_SELECTION           *Selection,\r
+  IN  UI_MENU_OPTION              *MenuOption\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  EFI_INPUT_KEY           Key;\r
+  UINTN                   Index;\r
+  CHAR16                  *StringPtr;\r
+  CHAR16                  *TempStringPtr;\r
+  UINTN                   Index2;\r
+  UINTN                   TopOptionIndex;\r
+  UINTN                   HighlightOptionIndex;\r
+  UINTN                   Start;\r
+  UINTN                   End;\r
+  UINTN                   Top;\r
+  UINTN                   Bottom;\r
+  UINTN                   PopUpMenuLines;\r
+  UINTN                   MenuLinesInView;\r
+  UINTN                   PopUpWidth;\r
+  CHAR16                  Character;\r
+  INT32                   SavedAttribute;\r
+  BOOLEAN                 ShowDownArrow;\r
+  BOOLEAN                 ShowUpArrow;\r
+  UINTN                   DimensionsWidth;\r
+  LIST_ENTRY              *Link;\r
+  BOOLEAN                 OrderedList;\r
+  UINT8                   *ValueArray;\r
+  EFI_HII_VALUE           HiiValue;\r
+  EFI_HII_VALUE           *HiiValueArray;\r
+  UINTN                   OptionCount;\r
+  QUESTION_OPTION         *OneOfOption;\r
+  QUESTION_OPTION         *CurrentOption;\r
+  FORM_BROWSER_STATEMENT  *Question;\r
+\r
+  DimensionsWidth   = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;\r
+\r
+  ValueArray        = NULL;\r
+  CurrentOption     = NULL;\r
+  ShowDownArrow     = FALSE;\r
+  ShowUpArrow       = FALSE;\r
+\r
+  StringPtr = AllocateZeroPool ((gOptionBlockWidth + 1) * 2);\r
+  ASSERT (StringPtr);\r
+\r
+  Question = MenuOption->ThisTag;\r
+  if (Question->Operand == EFI_IFR_ORDERED_LIST_OP) {\r
+    ValueArray = Question->BufferValue;\r
+    OrderedList = TRUE;\r
+  } else {\r
+    OrderedList = FALSE;\r
+  }\r
+\r
+  //\r
+  // Calculate Option count\r
+  //\r
+  if (OrderedList) {\r
+    for (Index = 0; Index < Question->MaxContainers; Index++) {\r
+      if (ValueArray[Index] == 0) {\r
+        break;\r
+      }\r
+    }\r
+\r
+    OptionCount = Index;\r
+  } else {\r
+    OptionCount = 0;\r
+    Link = GetFirstNode (&Question->OptionListHead);\r
+    while (!IsNull (&Question->OptionListHead, Link)) {\r
+      OneOfOption = QUESTION_OPTION_FROM_LINK (Link);\r
+\r
+      OptionCount++;\r
+\r
+      Link = GetNextNode (&Question->OptionListHead, Link);\r
+    }\r
+  }\r
+\r
+  //\r
+  // Prepare HiiValue array\r
+  //\r
+  HiiValueArray = AllocateZeroPool (OptionCount * sizeof (EFI_HII_VALUE));\r
+  ASSERT (HiiValueArray != NULL);\r
+  Link = GetFirstNode (&Question->OptionListHead);\r
+  for (Index = 0; Index < OptionCount; Index++) {\r
+    if (OrderedList) {\r
+      HiiValueArray[Index].Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
+      HiiValueArray[Index].Value.u8 = ValueArray[Index];\r
+    } else {\r
+      OneOfOption = QUESTION_OPTION_FROM_LINK (Link);\r
+      CopyMem (&HiiValueArray[Index], &OneOfOption->Value, sizeof (EFI_HII_VALUE));\r
+      Link = GetNextNode (&Question->OptionListHead, Link);\r
+    }\r
+  }\r
+\r
+  //\r
+  // Move Suppressed Option to list tail\r
+  //\r
+  PopUpMenuLines = 0;\r
+  for (Index = 0; Index < OptionCount; Index++) {\r
+    OneOfOption = ValueToOption (Question, &HiiValueArray[OptionCount - Index - 1]);\r
+    if (OneOfOption == NULL) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    RemoveEntryList (&OneOfOption->Link);\r
+\r
+    if ((OneOfOption->SuppressExpression != NULL) &&\r
+        (OneOfOption->SuppressExpression->Result.Value.b)) {\r
+      //\r
+      // This option is suppressed, insert to tail\r
+      //\r
+      InsertTailList (&Question->OptionListHead, &OneOfOption->Link);\r
+    } else {\r
+      //\r
+      // Insert to head\r
+      //\r
+      InsertHeadList (&Question->OptionListHead, &OneOfOption->Link);\r
+\r
+      PopUpMenuLines++;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Get the number of one of options present and its size\r
+  //\r
+  PopUpWidth = 0;\r
+  HighlightOptionIndex = 0;\r
+  Link = GetFirstNode (&Question->OptionListHead);\r
+  for (Index = 0; Index < PopUpMenuLines; Index++) {\r
+    OneOfOption = QUESTION_OPTION_FROM_LINK (Link);\r
+\r
+    StringPtr = GetToken (OneOfOption->Text, MenuOption->Handle);\r
+    if (StrLen (StringPtr) > PopUpWidth) {\r
+      PopUpWidth = StrLen (StringPtr);\r
+    }\r
+    gBS->FreePool (StringPtr);\r
+\r
+    if (!OrderedList && CompareHiiValue (&Question->HiiValue, &OneOfOption->Value, NULL) == 0) {\r
+      //\r
+      // Find current selected Option for OneOf\r
+      //\r
+      HighlightOptionIndex = Index;\r
+    }\r
+\r
+    Link = GetNextNode (&Question->OptionListHead, Link);\r
+  }\r
+\r
+  //\r
+  // Perform popup menu initialization.\r
+  //\r
+  PopUpWidth = PopUpWidth + POPUP_PAD_SPACE_COUNT;\r
+\r
+  SavedAttribute = gST->ConOut->Mode->Attribute;\r
+  gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);\r
+\r
+  if ((PopUpWidth + POPUP_FRAME_WIDTH) > DimensionsWidth) {\r
+    PopUpWidth = DimensionsWidth - POPUP_FRAME_WIDTH;\r
+  }\r
+\r
+  Start  = (DimensionsWidth - PopUpWidth - POPUP_FRAME_WIDTH) / 2 + gScreenDimensions.LeftColumn;\r
+  End    = Start + PopUpWidth + POPUP_FRAME_WIDTH;\r
+  Top    = gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT;\r
+  Bottom = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT - 1;\r
+\r
+  MenuLinesInView = Bottom - Top - 1;\r
+  if (MenuLinesInView >= PopUpMenuLines) {\r
+    Top     = Top + (MenuLinesInView - PopUpMenuLines) / 2;\r
+    Bottom  = Top + PopUpMenuLines + 1;\r
+  } else {\r
+    ShowDownArrow = TRUE;\r
+  }\r
+\r
+  if (HighlightOptionIndex > (MenuLinesInView - 1)) {\r
+    TopOptionIndex = HighlightOptionIndex - MenuLinesInView + 1;\r
+  } else {\r
+    TopOptionIndex = 0;\r
+  }\r
+\r
+  do {\r
+    //\r
+    // Clear that portion of the screen\r
+    //\r
+    ClearLines (Start, End, Top, Bottom, POPUP_TEXT | POPUP_BACKGROUND);\r
+\r
+    //\r
+    // Draw "One of" pop-up menu\r
+    //\r
+    Character = BOXDRAW_DOWN_RIGHT;\r
+    PrintCharAt (Start, Top, Character);\r
+    for (Index = Start; Index + 2 < End; Index++) {\r
+      if ((ShowUpArrow) && ((Index + 1) == (Start + End) / 2)) {\r
+        Character = GEOMETRICSHAPE_UP_TRIANGLE;\r
+      } else {\r
+        Character = BOXDRAW_HORIZONTAL;\r
+      }\r
+\r
+      PrintChar (Character);\r
+    }\r
+\r
+    Character = BOXDRAW_DOWN_LEFT;\r
+    PrintChar (Character);\r
+    Character = BOXDRAW_VERTICAL;\r
+    for (Index = Top + 1; Index < Bottom; Index++) {\r
+      PrintCharAt (Start, Index, Character);\r
+      PrintCharAt (End - 1, Index, Character);\r
+    }\r
+\r
+    //\r
+    // Move to top Option\r
+    //\r
+    Link = GetFirstNode (&Question->OptionListHead);\r
+    for (Index = 0; Index < TopOptionIndex; Index++) {\r
+      Link = GetNextNode (&Question->OptionListHead, Link);\r
+    }\r
+\r
+    //\r
+    // Display the One of options\r
+    //\r
+    Index2 = Top + 1;\r
+    for (Index = TopOptionIndex; (Index < PopUpMenuLines) && (Index2 < Bottom); Index++) {\r
+      OneOfOption = QUESTION_OPTION_FROM_LINK (Link);\r
+      Link = GetNextNode (&Question->OptionListHead, Link);\r
+\r
+      StringPtr = GetToken (OneOfOption->Text, MenuOption->Handle);\r
+      //\r
+      // If the string occupies multiple lines, truncate it to fit in one line,\r
+      // and append a "..." for indication.\r
+      //\r
+      if (StrLen (StringPtr) > (PopUpWidth - 1)) {\r
+        TempStringPtr = AllocateZeroPool (sizeof (CHAR16) * (PopUpWidth - 1));\r
+        ASSERT ( TempStringPtr != NULL );\r
+        CopyMem (TempStringPtr, StringPtr, (sizeof (CHAR16) * (PopUpWidth - 5)));\r
+        gBS->FreePool (StringPtr);\r
+        StringPtr = TempStringPtr;\r
+        StrCat (StringPtr, L"...");\r
+      }\r
+\r
+      if (Index == HighlightOptionIndex) {\r
+          //\r
+          // Highlight the selected one\r
+          //\r
+          CurrentOption = OneOfOption;\r
+\r
+          gST->ConOut->SetAttribute (gST->ConOut, PICKLIST_HIGHLIGHT_TEXT | PICKLIST_HIGHLIGHT_BACKGROUND);\r
+          PrintStringAt (Start + 2, Index2, StringPtr);\r
+          gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);\r
+        } else {\r
+          gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);\r
+          PrintStringAt (Start + 2, Index2, StringPtr);\r
+        }\r
+\r
+      Index2++;\r
+      gBS->FreePool (StringPtr);\r
+    }\r
+\r
+    Character = BOXDRAW_UP_RIGHT;\r
+    PrintCharAt (Start, Bottom, Character);\r
+    for (Index = Start; Index + 2 < End; Index++) {\r
+      if ((ShowDownArrow) && ((Index + 1) == (Start + End) / 2)) {\r
+        Character = GEOMETRICSHAPE_DOWN_TRIANGLE;\r
+      } else {\r
+        Character = BOXDRAW_HORIZONTAL;\r
+      }\r
+\r
+      PrintChar (Character);\r
+    }\r
+\r
+    Character = BOXDRAW_UP_LEFT;\r
+    PrintChar (Character);\r
+\r
+    //\r
+    // Get User selection\r
+    //\r
+    Key.UnicodeChar = CHAR_NULL;\r
+    if ((gDirection == SCAN_UP) || (gDirection == SCAN_DOWN)) {\r
+      Key.ScanCode  = gDirection;\r
+      gDirection    = 0;\r
+      goto TheKey;\r
+    }\r
+\r
+    Status = WaitForKeyStroke (&Key);\r
+\r
+TheKey:\r
+    switch (Key.UnicodeChar) {\r
+    case '+':\r
+      if (OrderedList) {\r
+        if ((TopOptionIndex > 0) && (TopOptionIndex == HighlightOptionIndex)) {\r
+          //\r
+          // Highlight reaches the top of the popup window, scroll one menu item.\r
+          //\r
+          TopOptionIndex--;\r
+          ShowDownArrow = TRUE;\r
+        }\r
+\r
+        if (TopOptionIndex == 0) {\r
+          ShowUpArrow = FALSE;\r
+        }\r
+\r
+        if (HighlightOptionIndex > 0) {\r
+          HighlightOptionIndex--;\r
+\r
+          SwapListEntries (CurrentOption->Link.BackLink, &CurrentOption->Link);\r
+        }\r
+      }\r
+      break;\r
+\r
+    case '-':\r
+      //\r
+      // If an ordered list op-code, we will allow for a popup of +/- keys\r
+      // to create an ordered list of items\r
+      //\r
+      if (OrderedList) {\r
+        if (((TopOptionIndex + MenuLinesInView) < PopUpMenuLines) &&\r
+            (HighlightOptionIndex == (TopOptionIndex + MenuLinesInView - 1))) {\r
+          //\r
+          // Highlight reaches the bottom of the popup window, scroll one menu item.\r
+          //\r
+          TopOptionIndex++;\r
+          ShowUpArrow = TRUE;\r
+        }\r
+\r
+        if ((TopOptionIndex + MenuLinesInView) == PopUpMenuLines) {\r
+          ShowDownArrow = FALSE;\r
+        }\r
+\r
+        if (HighlightOptionIndex < (PopUpMenuLines - 1)) {\r
+          HighlightOptionIndex++;\r
+\r
+          SwapListEntries (&CurrentOption->Link, CurrentOption->Link.ForwardLink);\r
+        }\r
+      }\r
+      break;\r
+\r
+    case CHAR_NULL:\r
+      switch (Key.ScanCode) {\r
+      case SCAN_UP:\r
+      case SCAN_DOWN:\r
+        if (Key.ScanCode == SCAN_UP) {\r
+          if ((TopOptionIndex > 0) && (TopOptionIndex == HighlightOptionIndex)) {\r
+            //\r
+            // Highlight reaches the top of the popup window, scroll one menu item.\r
+            //\r
+            TopOptionIndex--;\r
+            ShowDownArrow = TRUE;\r
+          }\r
+\r
+          if (TopOptionIndex == 0) {\r
+            ShowUpArrow = FALSE;\r
+          }\r
+\r
+          if (HighlightOptionIndex > 0) {\r
+            HighlightOptionIndex--;\r
+          }\r
+        } else {\r
+          if (((TopOptionIndex + MenuLinesInView) < PopUpMenuLines) &&\r
+              (HighlightOptionIndex == (TopOptionIndex + MenuLinesInView - 1))) {\r
+            //\r
+            // Highlight reaches the bottom of the popup window, scroll one menu item.\r
+            //\r
+            TopOptionIndex++;\r
+            ShowUpArrow = TRUE;\r
+          }\r
+\r
+          if ((TopOptionIndex + MenuLinesInView) == PopUpMenuLines) {\r
+            ShowDownArrow = FALSE;\r
+          }\r
+\r
+          if (HighlightOptionIndex < (PopUpMenuLines - 1)) {\r
+            HighlightOptionIndex++;\r
+          }\r
+        }\r
+        break;\r
+\r
+      case SCAN_ESC:\r
+        gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);\r
+\r
+        //\r
+        // Restore link list order for orderedlist\r
+        //\r
+        if (OrderedList) {\r
+          HiiValue.Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
+          HiiValue.Value.u64 = 0;\r
+          for (Index = 0; Index < Question->MaxContainers; Index++) {\r
+            HiiValue.Value.u8 = ValueArray[Index];\r
+            if (HiiValue.Value.u8) {\r
+              break;\r
+            }\r
+\r
+            OneOfOption = ValueToOption (Question, &HiiValue);\r
+            if (OneOfOption == NULL) {\r
+              return EFI_NOT_FOUND;\r
+            }\r
+\r
+            RemoveEntryList (&OneOfOption->Link);\r
+            InsertTailList (&Question->OptionListHead, &OneOfOption->Link);\r
+          }\r
+        }\r
+\r
+        gBS->FreePool (HiiValueArray);\r
+        return EFI_DEVICE_ERROR;\r
+\r
+      default:\r
+        break;\r
+      }\r
+\r
+      break;\r
+\r
+    case CHAR_CARRIAGE_RETURN:\r
+      //\r
+      // return the current selection\r
+      //\r
+      if (OrderedList) {\r
+        Index = 0;\r
+        Link = GetFirstNode (&Question->OptionListHead);\r
+        while (!IsNull (&Question->OptionListHead, Link)) {\r
+          OneOfOption = QUESTION_OPTION_FROM_LINK (Link);\r
+\r
+          Question->BufferValue[Index] = OneOfOption->Value.Value.u8;\r
+\r
+          Index++;\r
+          if (Index > Question->MaxContainers) {\r
+            break;\r
+          }\r
+\r
+          Link = GetNextNode (&Question->OptionListHead, Link);\r
+        }\r
+      } else {\r
+        CopyMem (&Question->HiiValue, &CurrentOption->Value, sizeof (EFI_HII_VALUE));\r
+      }\r
+\r
+      gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);\r
+      gBS->FreePool (HiiValueArray);\r
+\r
+      Status = ValidateQuestion (Selection->FormSet, Selection->Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);\r
+      if (EFI_ERROR (Status)) {\r
+        //\r
+        // Input value is not valid, restore Question Value\r
+        //\r
+        GetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE);\r
+      } else {\r
+        SetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE);\r
+        UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
+      }\r
+\r
+      return Status;\r
+\r
+    default:\r
+      break;\r
+    }\r
+  } while (TRUE);\r
+\r
+}\r
+\r
+/**\r
+  Wait for a key to be pressed by user.\r
+\r
+  @param Key         The key which is pressed by user.\r
+\r
+  @retval EFI_SUCCESS The function always completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+WaitForKeyStroke (\r
+  OUT  EFI_INPUT_KEY           *Key\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  do {\r
+    UiWaitForSingleEvent (gST->ConIn->WaitForKey, 0, 0);\r
+    Status = gST->ConIn->ReadKeyStroke (gST->ConIn, Key);\r
+  } while (EFI_ERROR(Status));\r
+\r
+  return Status;\r
+}\r
index 631f6413b889f65ab6aa2ad7029959153ef5c85d..47f99f5b8dda4d0f4a87163cd3fc389032575432 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 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "Setup.h"\r
+#include "Ui.h"\r
+\r
+BOOLEAN            mHiiPackageListUpdated;\r
+UI_MENU_SELECTION  *gCurrentSelection;\r
+\r
+\r
+/**\r
+  Clear retangle with specified text attribute.\r
+\r
+  @param  LeftColumn     Left column of retangle.\r
+  @param  RightColumn    Right column of retangle.\r
+  @param  TopRow         Start row of retangle.\r
+  @param  BottomRow      End row of retangle.\r
+  @param  TextAttribute  The character foreground and background.\r
+\r
+**/\r
+VOID\r
+ClearLines (\r
+  UINTN                                       LeftColumn,\r
+  UINTN                                       RightColumn,\r
+  UINTN                                       TopRow,\r
+  UINTN                                       BottomRow,\r
+  UINTN                                       TextAttribute\r
+  )\r
+{\r
+  CHAR16  *Buffer;\r
+  UINTN   Row;\r
+\r
+  //\r
+  // For now, allocate an arbitrarily long buffer\r
+  //\r
+  Buffer = AllocateZeroPool (0x10000);\r
+  ASSERT (Buffer != NULL);\r
+\r
+  //\r
+  // Set foreground and background as defined\r
+  //\r
+  gST->ConOut->SetAttribute (gST->ConOut, TextAttribute);\r
+\r
+  //\r
+  // Much faster to buffer the long string instead of print it a character at a time\r
+  //\r
+  SetUnicodeMem (Buffer, RightColumn - LeftColumn, L' ');\r
+\r
+  //\r
+  // Clear the desired area with the appropriate foreground/background\r
+  //\r
+  for (Row = TopRow; Row <= BottomRow; Row++) {\r
+    PrintStringAt (LeftColumn, Row, Buffer);\r
+  }\r
+\r
+  gST->ConOut->SetCursorPosition (gST->ConOut, LeftColumn, TopRow);\r
+\r
+  gBS->FreePool (Buffer);\r
+  return ;\r
+}\r
+\r
+/**\r
+  Concatenate a narrow string to another string.\r
+\r
+  @param Destination The destination string.\r
+  @param Source      The source string. The string to be concatenated.\r
+                     to the end of Destination.\r
+\r
+**/\r
+VOID\r
+NewStrCat (\r
+  CHAR16                                      *Destination,\r
+  CHAR16                                      *Source\r
+  )\r
+{\r
+  UINTN Length;\r
+\r
+  for (Length = 0; Destination[Length] != 0; Length++)\r
+    ;\r
+\r
+  //\r
+  // We now have the length of the original string\r
+  // We can safely assume for now that we are concatenating a narrow value to this string.\r
+  // For instance, the string is "XYZ" and cat'ing ">"\r
+  // If this assumption changes, we need to make this routine a bit more complex\r
+  //\r
+  Destination[Length] = NARROW_CHAR;\r
+  Length++;\r
+\r
+  StrCpy (Destination + Length, Source);\r
+}\r
+\r
+/**\r
+  Count the storage space of a Unicode string.\r
+\r
+  This function handles the Unicode string with NARROW_CHAR\r
+  and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR\r
+  does not count in the resultant output. If a WIDE_CHAR is \r
+  hit, then 2 Unicode character will consume an output storage\r
+  space with size of CHAR16 till a NARROW_CHAR is hit.\r
+\r
+  @param String          The input string to be counted.\r
+\r
+  @return Storage space for the input string.\r
+\r
+**/\r
+UINTN\r
+GetStringWidth (\r
+  CHAR16                                      *String\r
+  )\r
+{\r
+  UINTN Index;\r
+  UINTN Count;\r
+  UINTN IncrementValue;\r
+\r
+  Index           = 0;\r
+  Count           = 0;\r
+  IncrementValue  = 1;\r
+\r
+  do {\r
+    //\r
+    // Advance to the null-terminator or to the first width directive\r
+    //\r
+    for (;\r
+         (String[Index] != NARROW_CHAR) && (String[Index] != WIDE_CHAR) && (String[Index] != 0);\r
+         Index++, Count = Count + IncrementValue\r
+        )\r
+      ;\r
+\r
+    //\r
+    // We hit the null-terminator, we now have a count\r
+    //\r
+    if (String[Index] == 0) {\r
+      break;\r
+    }\r
+    //\r
+    // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed\r
+    // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2)\r
+    //\r
+    if (String[Index] == NARROW_CHAR) {\r
+      //\r
+      // Skip to the next character\r
+      //\r
+      Index++;\r
+      IncrementValue = 1;\r
+    } else {\r
+      //\r
+      // Skip to the next character\r
+      //\r
+      Index++;\r
+      IncrementValue = 2;\r
+    }\r
+  } while (String[Index] != 0);\r
+\r
+  //\r
+  // Increment by one to include the null-terminator in the size\r
+  //\r
+  Count++;\r
+\r
+  return Count * sizeof (CHAR16);\r
+}\r
+\r
+/**\r
+  This function displays the page frame.\r
+\r
+**/\r
+VOID\r
+DisplayPageFrame (\r
+  VOID\r
+  )\r
+{\r
+  UINTN                  Index;\r
+  UINT8                  Line;\r
+  UINT8                  Alignment;\r
+  CHAR16                 Character;\r
+  CHAR16                 *Buffer;\r
+  CHAR16                 *StrFrontPageBanner;\r
+  UINTN                  Row;\r
+  EFI_SCREEN_DESCRIPTOR  LocalScreen;\r
+\r
+  ZeroMem (&LocalScreen, sizeof (EFI_SCREEN_DESCRIPTOR));\r
+  gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &LocalScreen.RightColumn, &LocalScreen.BottomRow);\r
+  ClearLines (0, LocalScreen.RightColumn, 0, LocalScreen.BottomRow, KEYHELP_BACKGROUND);\r
+\r
+  CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
+\r
+  //\r
+  // For now, allocate an arbitrarily long buffer\r
+  //\r
+  Buffer = AllocateZeroPool (0x10000);\r
+  ASSERT (Buffer != NULL);\r
+\r
+  Character = BOXDRAW_HORIZONTAL;\r
+\r
+  for (Index = 0; Index + 2 < (LocalScreen.RightColumn - LocalScreen.LeftColumn); Index++) {\r
+    Buffer[Index] = Character;\r
+  }\r
+\r
+  if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {\r
+    //\r
+    //    ClearLines(0, LocalScreen.RightColumn, 0, BANNER_HEIGHT-1, BANNER_TEXT | BANNER_BACKGROUND);\r
+    //\r
+    ClearLines (\r
+      LocalScreen.LeftColumn,\r
+      LocalScreen.RightColumn,\r
+      LocalScreen.TopRow,\r
+      FRONT_PAGE_HEADER_HEIGHT - 1 + LocalScreen.TopRow,\r
+      BANNER_TEXT | BANNER_BACKGROUND\r
+      );\r
+    //\r
+    //    for (Line = 0; Line < BANNER_HEIGHT; Line++) {\r
+    //\r
+    for (Line = (UINT8) LocalScreen.TopRow; Line < BANNER_HEIGHT + (UINT8) LocalScreen.TopRow; Line++) {\r
+      //\r
+      //      for (Alignment = 0; Alignment < BANNER_COLUMNS; Alignment++) {\r
+      //\r
+      for (Alignment = (UINT8) LocalScreen.LeftColumn;\r
+           Alignment < BANNER_COLUMNS + (UINT8) LocalScreen.LeftColumn;\r
+           Alignment++\r
+          ) {\r
+        if (BannerData->Banner[Line - (UINT8) LocalScreen.TopRow][Alignment - (UINT8) LocalScreen.LeftColumn] != 0x0000) {\r
+          StrFrontPageBanner = GetToken (\r
+                                BannerData->Banner[Line - (UINT8) LocalScreen.TopRow][Alignment - (UINT8) LocalScreen.LeftColumn],\r
+                                FrontPageHandle\r
+                                );\r
+        } else {\r
+          continue;\r
+        }\r
+\r
+        switch (Alignment - LocalScreen.LeftColumn) {\r
+        case 0:\r
+          //\r
+          // Handle left column\r
+          //\r
+          PrintStringAt (LocalScreen.LeftColumn, Line, StrFrontPageBanner);\r
+          break;\r
+\r
+        case 1:\r
+          //\r
+          // Handle center column\r
+          //\r
+          PrintStringAt (\r
+            LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,\r
+            Line,\r
+            StrFrontPageBanner\r
+            );\r
+          break;\r
+\r
+        case 2:\r
+          //\r
+          // Handle right column\r
+          //\r
+          PrintStringAt (\r
+            LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3,\r
+            Line,\r
+            StrFrontPageBanner\r
+            );\r
+          break;\r
+        }\r
+\r
+        gBS->FreePool (StrFrontPageBanner);\r
+      }\r
+    }\r
+  }\r
+\r
+  ClearLines (\r
+    LocalScreen.LeftColumn,\r
+    LocalScreen.RightColumn,\r
+    LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT,\r
+    LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1,\r
+    KEYHELP_TEXT | KEYHELP_BACKGROUND\r
+    );\r
+\r
+  if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {\r
+    ClearLines (\r
+      LocalScreen.LeftColumn,\r
+      LocalScreen.RightColumn,\r
+      LocalScreen.TopRow,\r
+      LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1,\r
+      TITLE_TEXT | TITLE_BACKGROUND\r
+      );\r
+    //\r
+    // Print Top border line\r
+    // +------------------------------------------------------------------------------+\r
+    // ?                                                                             ?\r
+    // +------------------------------------------------------------------------------+\r
+    //\r
+    Character = BOXDRAW_DOWN_RIGHT;\r
+\r
+    PrintChar (Character);\r
+    PrintString (Buffer);\r
+\r
+    Character = BOXDRAW_DOWN_LEFT;\r
+    PrintChar (Character);\r
+\r
+    Character = BOXDRAW_VERTICAL;\r
+    for (Row = LocalScreen.TopRow + 1; Row <= LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 2; Row++) {\r
+      PrintCharAt (LocalScreen.LeftColumn, Row, Character);\r
+      PrintCharAt (LocalScreen.RightColumn - 1, Row, Character);\r
+    }\r
+\r
+    Character = BOXDRAW_UP_RIGHT;\r
+    PrintCharAt (LocalScreen.LeftColumn, LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1, Character);\r
+    PrintString (Buffer);\r
+\r
+    Character = BOXDRAW_UP_LEFT;\r
+    PrintChar (Character);\r
+\r
+    if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {\r
+      //\r
+      // Print Bottom border line\r
+      // +------------------------------------------------------------------------------+\r
+      // ?                                                                             ?\r
+      // +------------------------------------------------------------------------------+\r
+      //\r
+      Character = BOXDRAW_DOWN_RIGHT;\r
+      PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT, Character);\r
+\r
+      PrintString (Buffer);\r
+\r
+      Character = BOXDRAW_DOWN_LEFT;\r
+      PrintChar (Character);\r
+      Character = BOXDRAW_VERTICAL;\r
+      for (Row = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT + 1;\r
+           Row <= LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 2;\r
+           Row++\r
+          ) {\r
+        PrintCharAt (LocalScreen.LeftColumn, Row, Character);\r
+        PrintCharAt (LocalScreen.RightColumn - 1, Row, Character);\r
+      }\r
+\r
+      Character = BOXDRAW_UP_RIGHT;\r
+      PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1, Character);\r
+\r
+      PrintString (Buffer);\r
+\r
+      Character = BOXDRAW_UP_LEFT;\r
+      PrintChar (Character);\r
+    }\r
+  }\r
+\r
+  gBS->FreePool (Buffer);\r
+\r
+}\r
+\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
+      //\r
+      // Postpone Form validation to Question editing or Form submiting\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
++------------------------------------------------------------------------------+\r
+?F2=Previous Page                 Setup Page                                  ?\r
++------------------------------------------------------------------------------+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
++------------------------------------------------------------------------------+\r
+?F1=Scroll Help                 F9=Reset to Defaults        F10=Save and Exit ?\r
+| ^"=Move Highlight          <Spacebar> Toggles Checkbox   Esc=Discard Changes |\r
++------------------------------------------------------------------------------+\r
+*/\r
+\r
+/**\r
+\r
+  \r
+  Display form and wait for user to select one menu option, then return it.\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
+  @retval EFI_SUCESSS            This function always return successfully for now.\r
+\r
+**/\r
+EFI_STATUS\r
+DisplayForm (\r
+  IN OUT UI_MENU_SELECTION           *Selection\r
+  )\r
+{\r
+  CHAR16                 *StringPtr;\r
+  UINT16                 MenuItemCount;\r
+  EFI_HII_HANDLE         Handle;\r
+  BOOLEAN                Suppress;\r
+  EFI_SCREEN_DESCRIPTOR  LocalScreen;\r
+  UINT16                 Width;\r
+  UINTN                  ArrayEntry;\r
+  CHAR16                 *OutputString;\r
+  LIST_ENTRY             *Link;\r
+  FORM_BROWSER_STATEMENT *Statement;\r
+  UINT16                 NumberOfLines;\r
+  EFI_STATUS             Status;\r
+\r
+  Handle        = Selection->Handle;\r
+  MenuItemCount = 0;\r
+  ArrayEntry    = 0;\r
+  OutputString  = NULL;\r
+\r
+  UiInitMenu ();\r
+\r
+  CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
+\r
+  StringPtr = GetToken (Selection->FormSet->FormSetTitle, Handle);\r
+\r
+  if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {\r
+    gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | TITLE_BACKGROUND);\r
+    PrintStringAt (\r
+      (LocalScreen.RightColumn + LocalScreen.LeftColumn - GetStringWidth (StringPtr) / 2) / 2,\r
+      LocalScreen.TopRow + 1,\r
+      StringPtr\r
+      );\r
+  }\r
+\r
+  if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {\r
+    gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
+\r
+    //\r
+    // Display the infrastructure strings\r
+    //\r
+    if (!IsListEmpty (&gMenuList)) {\r
+      PrintStringAt (LocalScreen.LeftColumn + 2, LocalScreen.TopRow + 1, gFunctionTwoString);\r
+    }\r
+\r
+    PrintStringAt (LocalScreen.LeftColumn + 2, LocalScreen.BottomRow - 4, gFunctionOneString);\r
+    PrintStringAt (\r
+      LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,\r
+      LocalScreen.BottomRow - 4,\r
+      gFunctionNineString\r
+      );\r
+    PrintStringAt (\r
+      LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3,\r
+      LocalScreen.BottomRow - 4,\r
+      gFunctionTenString\r
+      );\r
+    PrintAt (LocalScreen.LeftColumn + 2, LocalScreen.BottomRow - 3, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
+    PrintStringAt (\r
+      LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,\r
+      LocalScreen.BottomRow - 3,\r
+      gEscapeString\r
+      );\r
+  }\r
+  //\r
+  // Remove Buffer allocated for StringPtr after it has been used.\r
+  //\r
+  gBS->FreePool (StringPtr);\r
+\r
+  //\r
+  // Evaluate all the Expressions in this Form\r
+  //\r
+  Status = EvaluateFormExpressions (Selection->FormSet, Selection->Form);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Link = GetFirstNode (&Selection->Form->StatementListHead);\r
+  while (!IsNull (&Selection->Form->StatementListHead, Link)) {\r
+    Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+\r
+    if (Statement->SuppressExpression != NULL) {\r
+      Suppress = Statement->SuppressExpression->Result.Value.b;\r
+    } else {\r
+      Suppress = FALSE;\r
+    }\r
+\r
+    if (!Suppress) {\r
+      StringPtr = GetToken (Statement->Prompt, Handle);\r
+\r
+      Width     = GetWidth (Statement, Handle);\r
+\r
+      NumberOfLines = 1;\r
+      ArrayEntry = 0;\r
+      for (; GetLineByWidth (StringPtr, Width, &ArrayEntry, &OutputString) != 0x0000;) {\r
+        //\r
+        // If there is more string to process print on the next row and increment the Skip value\r
+        //\r
+        if (StrLen (&StringPtr[ArrayEntry])) {\r
+          NumberOfLines++;\r
+        }\r
+\r
+        gBS->FreePool (OutputString);\r
+      }\r
+\r
+      //\r
+      // We are NOT!! removing this StringPtr buffer via FreePool since it is being used in the menuoptions, we will do\r
+      // it in UiFreeMenu.\r
+      //\r
+      UiAddMenuOption (StringPtr, Selection->Handle, Statement, NumberOfLines, MenuItemCount);\r
+      MenuItemCount++;\r
+    }\r
+\r
+    Link = GetNextNode (&Selection->Form->StatementListHead, Link);\r
+  }\r
+\r
+  Status = UiDisplayMenu (Selection);\r
+\r
+  UiFreeMenu ();\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Initialize the HII String Token to the correct values.\r
+\r
+**/\r
+VOID\r
+InitializeBrowserStrings (\r
+  VOID\r
+  )\r
+{\r
+  gFunctionOneString    = GetToken (STRING_TOKEN (FUNCTION_ONE_STRING), gHiiHandle);\r
+  gFunctionTwoString    = GetToken (STRING_TOKEN (FUNCTION_TWO_STRING), gHiiHandle);\r
+  gFunctionNineString   = GetToken (STRING_TOKEN (FUNCTION_NINE_STRING), gHiiHandle);\r
+  gFunctionTenString    = GetToken (STRING_TOKEN (FUNCTION_TEN_STRING), gHiiHandle);\r
+  gEnterString          = GetToken (STRING_TOKEN (ENTER_STRING), gHiiHandle);\r
+  gEnterCommitString    = GetToken (STRING_TOKEN (ENTER_COMMIT_STRING), gHiiHandle);\r
+  gEscapeString         = GetToken (STRING_TOKEN (ESCAPE_STRING), gHiiHandle);\r
+  gSaveFailed           = GetToken (STRING_TOKEN (SAVE_FAILED), gHiiHandle);\r
+  gMoveHighlight        = GetToken (STRING_TOKEN (MOVE_HIGHLIGHT), gHiiHandle);\r
+  gMakeSelection        = GetToken (STRING_TOKEN (MAKE_SELECTION), gHiiHandle);\r
+  gDecNumericInput      = GetToken (STRING_TOKEN (DEC_NUMERIC_INPUT), gHiiHandle);\r
+  gHexNumericInput      = GetToken (STRING_TOKEN (HEX_NUMERIC_INPUT), gHiiHandle);\r
+  gToggleCheckBox       = GetToken (STRING_TOKEN (TOGGLE_CHECK_BOX), gHiiHandle);\r
+  gPromptForData        = GetToken (STRING_TOKEN (PROMPT_FOR_DATA), gHiiHandle);\r
+  gPromptForPassword    = GetToken (STRING_TOKEN (PROMPT_FOR_PASSWORD), gHiiHandle);\r
+  gPromptForNewPassword = GetToken (STRING_TOKEN (PROMPT_FOR_NEW_PASSWORD), gHiiHandle);\r
+  gConfirmPassword      = GetToken (STRING_TOKEN (CONFIRM_PASSWORD), gHiiHandle);\r
+  gConfirmError         = GetToken (STRING_TOKEN (CONFIRM_ERROR), gHiiHandle);\r
+  gPassowordInvalid     = GetToken (STRING_TOKEN (PASSWORD_INVALID), gHiiHandle);\r
+  gPressEnter           = GetToken (STRING_TOKEN (PRESS_ENTER), gHiiHandle);\r
+  gEmptyString          = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
+  gAreYouSure           = GetToken (STRING_TOKEN (ARE_YOU_SURE), gHiiHandle);\r
+  gYesResponse          = GetToken (STRING_TOKEN (ARE_YOU_SURE_YES), gHiiHandle);\r
+  gNoResponse           = GetToken (STRING_TOKEN (ARE_YOU_SURE_NO), gHiiHandle);\r
+  gMiniString           = GetToken (STRING_TOKEN (MINI_STRING), gHiiHandle);\r
+  gPlusString           = GetToken (STRING_TOKEN (PLUS_STRING), gHiiHandle);\r
+  gMinusString          = GetToken (STRING_TOKEN (MINUS_STRING), gHiiHandle);\r
+  gAdjustNumber         = GetToken (STRING_TOKEN (ADJUST_NUMBER), gHiiHandle);\r
+  return ;\r
+}\r
+\r
+/**\r
+  Free up the resource allocated for all strings required\r
+  by Setup Browser.\r
+\r
+**/\r
+VOID\r
+FreeBrowserStrings (\r
+  VOID\r
+  )\r
+{\r
+  SafeFreePool (gFunctionOneString);\r
+  SafeFreePool (gFunctionTwoString);\r
+  SafeFreePool (gFunctionNineString);\r
+  SafeFreePool (gFunctionTenString);\r
+  SafeFreePool (gEnterString);\r
+  SafeFreePool (gEnterCommitString);\r
+  SafeFreePool (gEscapeString);\r
+  SafeFreePool (gMoveHighlight);\r
+  SafeFreePool (gMakeSelection);\r
+  SafeFreePool (gDecNumericInput);\r
+  SafeFreePool (gHexNumericInput);\r
+  SafeFreePool (gToggleCheckBox);\r
+  SafeFreePool (gPromptForData);\r
+  SafeFreePool (gPromptForPassword);\r
+  SafeFreePool (gPromptForNewPassword);\r
+  SafeFreePool (gConfirmPassword);\r
+  SafeFreePool (gPassowordInvalid);\r
+  SafeFreePool (gConfirmError);\r
+  SafeFreePool (gPressEnter);\r
+  SafeFreePool (gEmptyString);\r
+  SafeFreePool (gAreYouSure);\r
+  SafeFreePool (gYesResponse);\r
+  SafeFreePool (gNoResponse);\r
+  SafeFreePool (gMiniString);\r
+  SafeFreePool (gPlusString);\r
+  SafeFreePool (gMinusString);\r
+  SafeFreePool (gAdjustNumber);\r
+  return ;\r
+}\r
+\r
+\r
+/**\r
+  Update key's help imformation.\r
+\r
+  @param  MenuOption     The Menu option\r
+  @param  Selected       Whether or not a tag be selected\r
+\r
+**/\r
+VOID\r
+UpdateKeyHelp (\r
+  IN  UI_MENU_OPTION              *MenuOption,\r
+  IN  BOOLEAN                     Selected\r
+  )\r
+{\r
+  UINTN                  SecCol;\r
+  UINTN                  ThdCol;\r
+  UINTN                  LeftColumnOfHelp;\r
+  UINTN                  RightColumnOfHelp;\r
+  UINTN                  TopRowOfHelp;\r
+  UINTN                  BottomRowOfHelp;\r
+  UINTN                  StartColumnOfHelp;\r
+  EFI_SCREEN_DESCRIPTOR  LocalScreen;\r
+  FORM_BROWSER_STATEMENT *Statement;\r
+\r
+  CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
+\r
+  SecCol            = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3;\r
+  ThdCol            = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3;\r
+\r
+  StartColumnOfHelp = LocalScreen.LeftColumn + 2;\r
+  LeftColumnOfHelp  = LocalScreen.LeftColumn + 1;\r
+  RightColumnOfHelp = LocalScreen.RightColumn - 2;\r
+  TopRowOfHelp      = LocalScreen.BottomRow - 4;\r
+  BottomRowOfHelp   = LocalScreen.BottomRow - 3;\r
+\r
+  if (gClassOfVfr == EFI_GENERAL_APPLICATION_SUBCLASS) {\r
+    return ;\r
+  }\r
+\r
+  gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
+\r
+  Statement = MenuOption->ThisTag;\r
+  switch (Statement->Operand) {\r
+  case EFI_IFR_ORDERED_LIST_OP:\r
+  case EFI_IFR_ONE_OF_OP:\r
+  case EFI_IFR_NUMERIC_OP:\r
+  case EFI_IFR_TIME_OP:\r
+  case EFI_IFR_DATE_OP:\r
+    ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
+\r
+    if (!Selected) {\r
+      if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {\r
+        PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);\r
+        PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);\r
+        PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);\r
+        PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
+      }\r
+\r
+      if ((Statement->Operand == EFI_IFR_DATE_OP) ||\r
+          (Statement->Operand == EFI_IFR_TIME_OP) ||\r
+          (Statement->Operand == EFI_IFR_NUMERIC_OP && Statement->Step != 0)) {\r
+        PrintAt (\r
+          StartColumnOfHelp,\r
+          BottomRowOfHelp,\r
+          L"%c%c%c%c%s",\r
+          ARROW_UP,\r
+          ARROW_DOWN,\r
+          ARROW_RIGHT,\r
+          ARROW_LEFT,\r
+          gMoveHighlight\r
+          );\r
+        PrintStringAt (SecCol, BottomRowOfHelp, gAdjustNumber);\r
+      } else {\r
+        PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
+        PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);\r
+      }\r
+    } else {\r
+      PrintStringAt (SecCol, BottomRowOfHelp, gEnterCommitString);\r
+\r
+      //\r
+      // If it is a selected numeric with manual input, display different message\r
+      //\r
+      if ((Statement->Operand == EFI_IFR_NUMERIC_OP) && (Statement->Step == 0)) {\r
+        PrintStringAt (\r
+          SecCol,\r
+          TopRowOfHelp,\r
+          ((Statement->Flags & EFI_IFR_DISPLAY_UINT_HEX) == EFI_IFR_DISPLAY_UINT_HEX) ? gHexNumericInput : gDecNumericInput\r
+          );\r
+      } else if (Statement->Operand != EFI_IFR_ORDERED_LIST_OP) {\r
+        PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
+      }\r
+\r
+      if (Statement->Operand == EFI_IFR_ORDERED_LIST_OP) {\r
+        PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gPlusString);\r
+        PrintStringAt (ThdCol, TopRowOfHelp, gMinusString);\r
+      }\r
+\r
+      PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
+    }\r
+    break;\r
+\r
+  case EFI_IFR_CHECKBOX_OP:\r
+    ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
+\r
+    if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {\r
+      PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);\r
+      PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);\r
+      PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);\r
+      PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
+    }\r
+\r
+    PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
+    PrintStringAt (SecCol, BottomRowOfHelp, gToggleCheckBox);\r
+    break;\r
+\r
+  case EFI_IFR_REF_OP:\r
+  case EFI_IFR_PASSWORD_OP:\r
+  case EFI_IFR_STRING_OP:\r
+  case EFI_IFR_TEXT_OP:\r
+  case EFI_IFR_ACTION_OP:\r
+  case EFI_IFR_RESET_BUTTON_OP:\r
+    ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
+\r
+    if (!Selected) {\r
+      if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {\r
+        PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);\r
+        PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);\r
+        PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);\r
+        PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
+      }\r
+\r
+      PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
+      if (Statement->Operand != EFI_IFR_TEXT_OP) {\r
+        PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);\r
+      }\r
+    } else {\r
+      if (Statement->Operand != EFI_IFR_REF_OP) {\r
+        PrintStringAt (\r
+          (LocalScreen.RightColumn - GetStringWidth (gEnterCommitString) / 2) / 2,\r
+          BottomRowOfHelp,\r
+          gEnterCommitString\r
+          );\r
+        PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
+      }\r
+    }\r
+    break;\r
+\r
+  default:\r
+    break;\r
+  }\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
+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
+  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_BROWSER_ACTION_REQUEST      ActionRequest;\r
+  EFI_HANDLE                      NotifyHandle;\r
+  EFI_HII_VALUE                   *HiiValue;\r
+  FORM_BROWSER_STATEMENT          *Statement;\r
+  EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;\r
+\r
+  gMenuRefreshHead = NULL;\r
+  gResetRequired = FALSE;\r
+  gNvUpdateRequired = FALSE;\r
+\r
+  UiInitMenuList ();\r
+\r
+  //\r
+  // Register notify for Form package update\r
+  //\r
+  Status = mHiiDatabase->RegisterPackageNotify (\r
+                           mHiiDatabase,\r
+                           EFI_HII_PACKAGE_FORM,\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
+  do {\r
+    //\r
+    // Displays the Header and Footer borders\r
+    //\r
+    DisplayPageFrame ();\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
+    //\r
+    // Load Questions' Value for display\r
+    //\r
+    Status = LoadFormConfig (Selection->FormSet, Selection->Form);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Display form\r
+    //\r
+    Status = DisplayForm (Selection);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\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 ((Statement->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) == EFI_IFR_FLAG_RESET_REQUIRED) {\r
+        gResetRequired = TRUE;\r
+      }\r
+\r
+      //\r
+      // Reset FormPackage update flag\r
+      //\r
+      mHiiPackageListUpdated = FALSE;\r
+\r
+      if (((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) && (Statement->Operand != EFI_IFR_PASSWORD_OP)) {\r
+        ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+\r
+        HiiValue = &Statement->HiiValue;\r
+        if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
+          //\r
+          // Create String in HII database for Configuration Driver to retrieve\r
+          //\r
+          HiiValue->Value.string = NewString ((CHAR16 *) Statement->BufferValue, Selection->FormSet->HiiHandle);\r
+        }\r
+\r
+        ConfigAccess = Selection->FormSet->ConfigAccess;\r
+        if (ConfigAccess == NULL) {\r
+          return EFI_UNSUPPORTED;\r
+        }\r
+        Status = ConfigAccess->Callback (\r
+                                 ConfigAccess,\r
+                                 EFI_BROWSER_ACTION_CHANGING,\r
+                                 Statement->QuestionId,\r
+                                 HiiValue->Type,\r
+                                 &HiiValue->Value,\r
+                                 &ActionRequest\r
+                                 );\r
+\r
+        if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
+          //\r
+          // Clean the String in HII Database\r
+          //\r
+          DeleteString (HiiValue->Value.string, Selection->FormSet->HiiHandle);\r
+        }\r
+\r
+        if (!EFI_ERROR (Status)) {\r
+          switch (ActionRequest) {\r
+          case EFI_BROWSER_ACTION_REQUEST_RESET:\r
+            gResetRequired = TRUE;\r
+            break;\r
+\r
+          case EFI_BROWSER_ACTION_REQUEST_SUBMIT:\r
+            SubmitForm (Selection->FormSet, Selection->Form);\r
+            break;\r
+\r
+          case EFI_BROWSER_ACTION_REQUEST_EXIT:\r
+            Selection->Action = UI_ACTION_EXIT;\r
+            gNvUpdateRequired = FALSE;\r
+            break;\r
+\r
+          default:\r
+            break;\r
+          }\r
+        }\r
+      }\r
+\r
+      //\r
+      // Check whether Form Package has been updated during Callback\r
+      //\r
+      if (mHiiPackageListUpdated && (Selection->Action == UI_ACTION_REFRESH_FORM)) {\r
+        //\r
+        // Force to reparse IFR binary of target Formset\r
+        //\r
+        Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+      }\r
+    }\r
+  } while (Selection->Action == UI_ACTION_REFRESH_FORM);\r
+\r
+  //\r
+  // Unregister notify for Form package update\r
+  //\r
+  Status = mHiiDatabase->UnregisterPackageNotify (\r
+                           mHiiDatabase,\r
+                           NotifyHandle\r
+                           );\r
+  return Status;\r
+}\r
index 235ee45d2da78bab4acb0e14b8e23c89c49e9783..d8b42f8973713caf87913917db8ef317fd51dc65 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:
-
-  Print.c
-
-Abstract:
-
-  Basic Ascii AvSPrintf() function named VSPrint(). VSPrint() enables very
-  simple implemenation of SPrint() and Print() to support debug.
-
-  You can not Print more than EFI_DRIVER_LIB_MAX_PRINT_BUFFER characters at a
-  time. This makes the implementation very simple.
-
-  VSPrint, Print, SPrint format specification has the follwoing form
-
-  %type
-
-  type:
-    'S','s' - argument is an Unicode string
-    'c' - argument is an ascii character
-    '%' - Print a %
-
-
-**/
-
-#include "Setup.h"
-
-UINTN
-ValueToString (
-  IN  OUT CHAR16  *Buffer,
-  IN  BOOLEAN     Flags,
-  IN  INT64       Value
-  );
-
-UINTN
-PrintInternal (
-  IN UINTN                            Column,
-  IN UINTN                            Row,
-  IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL     *Out,
-  IN CHAR16                           *fmt,
-  IN VA_LIST                          args
-  )
-//
-// Display string worker for: Print, PrintAt, IPrint, IPrintAt
-//
-{
-  CHAR16  *Buffer;
-  CHAR16  *BackupBuffer;
-  UINTN   Index;
-  UINTN   PreviousIndex;
-
-  //
-  // For now, allocate an arbitrarily long buffer
-  //
-  Buffer        = AllocateZeroPool (0x10000);
-  BackupBuffer  = AllocateZeroPool (0x10000);
-  ASSERT (Buffer);
-  ASSERT (BackupBuffer);
-
-  if (Column != (UINTN) -1) {
-    Out->SetCursorPosition (Out, Column, Row);
-  }
-
-  UnicodeVSPrint (Buffer, 0x10000, fmt, args);
-
-  Out->Mode->Attribute = Out->Mode->Attribute & 0x7f;
-
-  Out->SetAttribute (Out, Out->Mode->Attribute);
-
-  Index         = 0;
-  PreviousIndex = 0;
-
-  do {
-    for (; (Buffer[Index] != NARROW_CHAR) && (Buffer[Index] != WIDE_CHAR) && (Buffer[Index] != 0); Index++) {
-      BackupBuffer[Index] = Buffer[Index];
-    }
-
-    if (Buffer[Index] == 0) {
-      break;
-    }
-    //
-    // Null-terminate the temporary string
-    //
-    BackupBuffer[Index] = 0;
-
-    //
-    // Print this out, we are about to switch widths
-    //
-    Out->OutputString (Out, &BackupBuffer[PreviousIndex]);
-
-    //
-    // Preserve the current index + 1, since this is where we will start printing from next
-    //
-    PreviousIndex = Index + 1;
-
-    //
-    // We are at a narrow or wide character directive.  Set attributes and strip it and print it
-    //
-    if (Buffer[Index] == NARROW_CHAR) {
-      //
-      // Preserve bits 0 - 6 and zero out the rest
-      //
-      Out->Mode->Attribute = Out->Mode->Attribute & 0x7f;
-      Out->SetAttribute (Out, Out->Mode->Attribute);
-    } else {
-      //
-      // Must be wide, set bit 7 ON
-      //
-      Out->Mode->Attribute = Out->Mode->Attribute | EFI_WIDE_ATTRIBUTE;
-      Out->SetAttribute (Out, Out->Mode->Attribute);
-    }
-
-    Index++;
-
-  } while (Buffer[Index] != 0);
-
-  //
-  // We hit the end of the string - print it
-  //
-  Out->OutputString (Out, &BackupBuffer[PreviousIndex]);
-
-  gBS->FreePool (Buffer);
-  gBS->FreePool (BackupBuffer);
-  return EFI_SUCCESS;
-}
-
-
-/**
-  Prints a formatted unicode string to the default console
-
-  @param  fmt        Format string
-
-  @return Length of string printed to the console
-
-**/
-UINTN
-ConsolePrint (
-  IN CHAR16   *fmt,
-  ...
-  )
-{
-  VA_LIST args;
-
-  VA_START (args, fmt);
-  return PrintInternal ((UINTN) -1, (UINTN) -1, gST->ConOut, fmt, args);
-}
-
-
-/**
-  Prints a unicode string to the default console,
-  using L"%s" format.
-
-  @param  String     String pointer.
-
-  @return Length of string printed to the console
-
-**/
-UINTN
-PrintString (
-  CHAR16       *String
-  )
-{
-  return ConsolePrint (L"%s", String);
-}
-
-
-/**
-  Prints a chracter to the default console,
-  using L"%c" format.
-
-  @param  Character  Character to print.
-
-  @return Length of string printed to the console.
-
-**/
-UINTN
-PrintChar (
-  CHAR16       Character
-  )
-{
-  return ConsolePrint (L"%c", Character);
-}
-
-
-/**
-  Prints a formatted unicode string to the default console, at
-  the supplied cursor position
-
-  @param  Row        The cursor position to print the string at
-  @param  fmt        Format string
-
-  @return Length of string printed to the console
-
-**/
-UINTN
-PrintAt (
-  IN UINTN     Column,
-  IN UINTN     Row,
-  IN CHAR16    *fmt,
-  ...
-  )
-{
-  VA_LIST args;
-
-  VA_START (args, fmt);
-  return PrintInternal (Column, Row, gST->ConOut, fmt, args);
-}
-
-
-/**
-  Prints a unicode string to the default console, at
-  the supplied cursor position, using L"%s" format.
-
-  @param  Row        The cursor position to print the string at
-  @param  String     String pointer.
-
-  @return Length of string printed to the console
-
-**/
-UINTN
-PrintStringAt (
-  IN UINTN     Column,
-  IN UINTN     Row,
-  CHAR16       *String
-  )
-{
-  return PrintAt (Column, Row, L"%s", String);
-}
-
-
-/**
-  Prints a chracter to the default console, at
-  the supplied cursor position, using L"%c" format.
-
-  @param  Row        The cursor position to print the string at
-  @param  Character  Character to print.
-
-  @return Length of string printed to the console.
-
-**/
-UINTN
-PrintCharAt (
-  IN UINTN     Column,
-  IN UINTN     Row,
-  CHAR16       Character
-  )
-{
-  return PrintAt (Column, Row, L"%c", Character);
-}
-
-
-/**
-  VSPrint worker function that prints a Value as a decimal number in Buffer
-
-  @param  Buffer     Location to place ascii decimal number string of Value.
-  @param  Value      Decimal value to convert to a string in Buffer.
-  @param  Flags      Flags to use in printing decimal string, see file header for
-                     details.
-
-  @return Number of characters printed.
-
-**/
-UINTN
-ValueToString (
-  IN  OUT CHAR16  *Buffer,
-  IN  BOOLEAN     Flags,
-  IN  INT64       Value
-  )
-{
-  CHAR16  TempBuffer[30];
-  CHAR16  *TempStr;
-  CHAR16  *BufferPtr;
-  UINTN   Count;
-  UINTN   NumberCount;
-  UINT32  Remainder;
-  BOOLEAN Negative;
-
-  Negative    = FALSE;
-  TempStr     = TempBuffer;
-  BufferPtr   = Buffer;
-  Count       = 0;
-  NumberCount = 0;
-
-  if (Value < 0) {
-    Negative = TRUE;
-    Value    = -Value;
-  }
-
-  do {
-    Value         = (INT64) DivU64x32Remainder  ((UINT64) Value, 10, &Remainder);
-    *(TempStr++)  = (CHAR16) (Remainder + '0');
-    Count++;
-    NumberCount++;
-    if ((Flags & COMMA_TYPE) == COMMA_TYPE) {
-      if (NumberCount % 3 == 0 && Value != 0) {
-        *(TempStr++) = ',';
-        Count++;
-      }
-    }
-  } while (Value != 0);
-
-  if (Negative) {
-    *(BufferPtr++) = '-';
-    Count++;
-  }
-
-  //
-  // Reverse temp string into Buffer.
-  //
-  while (TempStr != TempBuffer) {
-    *(BufferPtr++) = *(--TempStr);
-  }
-
-  *BufferPtr = 0;
-  return Count;
-}
+/** @file\r
+Basic Ascii AvSPrintf() function named VSPrint(). VSPrint() enables very\r
+simple implemenation of SPrint() and Print() to support debug.\r
+\r
+You can not Print more than EFI_DRIVER_LIB_MAX_PRINT_BUFFER characters at a\r
+time. This makes the implementation very simple.\r
+\r
+VSPrint, Print, SPrint format specification has the follwoing form\r
+\r
+%type\r
+\r
+type:\r
+  'S','s' - argument is an Unicode string\r
+  'c' - argument is an ascii character\r
+  '%' - Print a %\r
+\r
+\r
+Copyright (c) 2004 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "Setup.h"\r
+\r
+/**\r
+  VSPrint worker function that prints a Value as a decimal number in Buffer.\r
+\r
+  @param  Buffer     Location to place ascii decimal number string of Value.\r
+  @param  Flags      Flags to use in printing decimal string, see file header for\r
+                     details.\r
+  @param  Value      Decimal value to convert to a string in Buffer.\r
+\r
+  @return Number of characters printed.\r
+\r
+**/\r
+UINTN\r
+ValueToString (\r
+  IN  OUT CHAR16  *Buffer,\r
+  IN  BOOLEAN     Flags,\r
+  IN  INT64       Value\r
+  );\r
+\r
+/**\r
+  The internal function prints to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL\r
+  protocol instance.\r
+\r
+  @param Column          The position of the output string.\r
+  @param Row             The position of the output string.\r
+  @param Out             The EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance.\r
+  @param Fmt             The format string.\r
+  @param Args            The additional argument for the variables in the format string.\r
+\r
+  @return Number of Unicode character printed.\r
+\r
+**/\r
+UINTN\r
+PrintInternal (\r
+  IN UINTN                            Column,\r
+  IN UINTN                            Row,\r
+  IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *Out,\r
+  IN CHAR16                           *Fmt,\r
+  IN VA_LIST                          Args\r
+  )\r
+{\r
+  CHAR16  *Buffer;\r
+  CHAR16  *BackupBuffer;\r
+  UINTN   Index;\r
+  UINTN   PreviousIndex;\r
+  UINTN   Count;\r
+\r
+  //\r
+  // For now, allocate an arbitrarily long buffer\r
+  //\r
+  Buffer        = AllocateZeroPool (0x10000);\r
+  BackupBuffer  = AllocateZeroPool (0x10000);\r
+  ASSERT (Buffer);\r
+  ASSERT (BackupBuffer);\r
+\r
+  if (Column != (UINTN) -1) {\r
+    Out->SetCursorPosition (Out, Column, Row);\r
+  }\r
+\r
+  UnicodeVSPrint (Buffer, 0x10000, Fmt, Args);\r
+\r
+  Out->Mode->Attribute = Out->Mode->Attribute & 0x7f;\r
+\r
+  Out->SetAttribute (Out, Out->Mode->Attribute);\r
+\r
+  Index         = 0;\r
+  PreviousIndex = 0;\r
+  Count         = 0;\r
+\r
+  do {\r
+    for (; (Buffer[Index] != NARROW_CHAR) && (Buffer[Index] != WIDE_CHAR) && (Buffer[Index] != 0); Index++) {\r
+      BackupBuffer[Index] = Buffer[Index];\r
+    }\r
+\r
+    if (Buffer[Index] == 0) {\r
+      break;\r
+    }\r
+    //\r
+    // Null-terminate the temporary string\r
+    //\r
+    BackupBuffer[Index] = 0;\r
+\r
+    //\r
+    // Print this out, we are about to switch widths\r
+    //\r
+    Out->OutputString (Out, &BackupBuffer[PreviousIndex]);\r
+    Count += StrLen (&BackupBuffer[PreviousIndex]);\r
+\r
+    //\r
+    // Preserve the current index + 1, since this is where we will start printing from next\r
+    //\r
+    PreviousIndex = Index + 1;\r
+\r
+    //\r
+    // We are at a narrow or wide character directive.  Set attributes and strip it and print it\r
+    //\r
+    if (Buffer[Index] == NARROW_CHAR) {\r
+      //\r
+      // Preserve bits 0 - 6 and zero out the rest\r
+      //\r
+      Out->Mode->Attribute = Out->Mode->Attribute & 0x7f;\r
+      Out->SetAttribute (Out, Out->Mode->Attribute);\r
+    } else {\r
+      //\r
+      // Must be wide, set bit 7 ON\r
+      //\r
+      Out->Mode->Attribute = Out->Mode->Attribute | EFI_WIDE_ATTRIBUTE;\r
+      Out->SetAttribute (Out, Out->Mode->Attribute);\r
+    }\r
+\r
+    Index++;\r
+\r
+  } while (Buffer[Index] != 0);\r
+\r
+  //\r
+  // We hit the end of the string - print it\r
+  //\r
+  Out->OutputString (Out, &BackupBuffer[PreviousIndex]);\r
+  Count += StrLen (&BackupBuffer[PreviousIndex]);\r
+\r
+  gBS->FreePool (Buffer);\r
+  gBS->FreePool (BackupBuffer);\r
+  return Count;\r
+}\r
+\r
+\r
+/**\r
+  Prints a formatted unicode string to the default console.\r
+\r
+  @param  Fmt        Format string\r
+  @param  ...        Variable argument list for format string.\r
+\r
+  @return Length of string printed to the console.\r
+\r
+**/\r
+UINTN\r
+ConsolePrint (\r
+  IN CHAR16   *Fmt,\r
+  IN ...\r
+  )\r
+{\r
+  VA_LIST Args;\r
+\r
+  VA_START (Args, Fmt);\r
+  return PrintInternal ((UINTN) -1, (UINTN) -1, gST->ConOut, Fmt, Args);\r
+}\r
+\r
+\r
+/**\r
+  Prints a unicode string to the default console,\r
+  using L"%s" format.\r
+\r
+  @param  String     String pointer.\r
+\r
+  @return Length of string printed to the console\r
+\r
+**/\r
+UINTN\r
+PrintString (\r
+  IN CHAR16       *String\r
+  )\r
+{\r
+  return ConsolePrint (L"%s", String);\r
+}\r
+\r
+\r
+/**\r
+  Prints a chracter to the default console,\r
+  using L"%c" format.\r
+\r
+  @param  Character  Character to print.\r
+\r
+  @return Length of string printed to the console.\r
+\r
+**/\r
+UINTN\r
+PrintChar (\r
+  CHAR16       Character\r
+  )\r
+{\r
+  return ConsolePrint (L"%c", Character);\r
+}\r
+\r
+\r
+/**\r
+  Prints a formatted unicode string to the default console, at\r
+  the supplied cursor position.\r
+\r
+  @param  Column     The cursor position to print the string at.\r
+  @param  Row        The cursor position to print the string at.\r
+  @param  Fmt        Format string.\r
+  @param  ...        Variable argument list for format string.\r
+\r
+  @return Length of string printed to the console\r
+\r
+**/\r
+UINTN\r
+PrintAt (\r
+  IN UINTN     Column,\r
+  IN UINTN     Row,\r
+  IN CHAR16    *Fmt,\r
+  ...\r
+  )\r
+{\r
+  VA_LIST Args;\r
+\r
+  VA_START (Args, Fmt);\r
+  return PrintInternal (Column, Row, gST->ConOut, Fmt, Args);\r
+}\r
+\r
+\r
+/**\r
+  Prints a unicode string to the default console, at\r
+  the supplied cursor position, using L"%s" format.\r
+\r
+  @param  Column     The cursor position to print the string at.\r
+  @param  Row        The cursor position to print the string at\r
+  @param  String     String pointer.\r
+\r
+  @return Length of string printed to the console\r
+\r
+**/\r
+UINTN\r
+PrintStringAt (\r
+  IN UINTN     Column,\r
+  IN UINTN     Row,\r
+  CHAR16       *String\r
+  )\r
+{\r
+  return PrintAt (Column, Row, L"%s", String);\r
+}\r
+\r
+\r
+/**\r
+  Prints a chracter to the default console, at\r
+  the supplied cursor position, using L"%c" format.\r
+\r
+  @param  Column     The cursor position to print the string at.\r
+  @param  Row        The cursor position to print the string at.\r
+  @param  Character  Character to print.\r
+\r
+  @return Length of string printed to the console.\r
+\r
+**/\r
+UINTN\r
+PrintCharAt (\r
+  IN UINTN     Column,\r
+  IN UINTN     Row,\r
+  CHAR16       Character\r
+  )\r
+{\r
+  return PrintAt (Column, Row, L"%c", Character);\r
+}\r
+\r
+\r
+/**\r
+  VSPrint worker function that prints a Value as a decimal number in Buffer.\r
+\r
+  @param  Buffer     Location to place ascii decimal number string of Value.\r
+  @param  Flags      Flags to use in printing decimal string, see file header for\r
+                     details.\r
+  @param  Value      Decimal value to convert to a string in Buffer.\r
+\r
+  @return Number of characters printed.\r
+\r
+**/\r
+UINTN\r
+ValueToString (\r
+  IN  OUT CHAR16  *Buffer,\r
+  IN  BOOLEAN     Flags,\r
+  IN  INT64       Value\r
+  )\r
+{\r
+  CHAR16  TempBuffer[30];\r
+  CHAR16  *TempStr;\r
+  CHAR16  *BufferPtr;\r
+  UINTN   Count;\r
+  UINTN   NumberCount;\r
+  UINT32  Remainder;\r
+  BOOLEAN Negative;\r
+\r
+  Negative    = FALSE;\r
+  TempStr     = TempBuffer;\r
+  BufferPtr   = Buffer;\r
+  Count       = 0;\r
+  NumberCount = 0;\r
+\r
+  if (Value < 0) {\r
+    Negative = TRUE;\r
+    Value    = -Value;\r
+  }\r
+\r
+  do {\r
+    Value         = (INT64) DivU64x32Remainder  ((UINT64) Value, 10, &Remainder);\r
+    *(TempStr++)  = (CHAR16) (Remainder + '0');\r
+    Count++;\r
+    NumberCount++;\r
+    if ((Flags & COMMA_TYPE) == COMMA_TYPE) {\r
+      if (NumberCount % 3 == 0 && Value != 0) {\r
+        *(TempStr++) = ',';\r
+        Count++;\r
+      }\r
+    }\r
+  } while (Value != 0);\r
+\r
+  if (Negative) {\r
+    *(BufferPtr++) = '-';\r
+    Count++;\r
+  }\r
+\r
+  //\r
+  // Reverse temp string into Buffer.\r
+  //\r
+  while (TempStr != TempBuffer) {\r
+    *(BufferPtr++) = *(--TempStr);\r
+  }\r
+\r
+  *BufferPtr = 0;\r
+  return Count;\r
+}\r
index c473a26cfa7e4e3b910ca7abdf8966b58288b4d1..b75e0ffbc55adf77a6a5807149265c3352f7be69 100644 (file)
@@ -1,4 +1,5 @@
 /** @file
+Micro definitions data for Print.c
 
 Copyright (c) 2004, Intel Corporation
 All rights reserved. This program and the accompanying materials
@@ -9,15 +10,6 @@ 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:
-
-  Print.h
-
-Abstract:
-
-  Private data for Print.c
-
-
 **/
 
 #ifndef _PRINT_H_
index ac9eeda777e81c6bb2ead0bbde5c197b974027cd..3e2cd180f65746afc84bbf9eea760a41e7e4caa1 100644 (file)
@@ -1,4 +1,6 @@
 /** @file
+Implementation for handling the User Interface option processing.
+
 
 Copyright (c) 2004 - 2007, Intel Corporation
 All rights reserved. This program and the accompanying materials
@@ -9,17 +11,6 @@ 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:
-
-  ProcessOptions.c
-
-Abstract:
-
-  Implementation for handling the User Interface option processing.
-
-Revision History
-
-
 **/
 
 #include "Ui.h"
@@ -113,7 +104,7 @@ ValueToOption (
 /**
   Print Question Value according to it's storage width and display attributes.
 
-  @param  Event                  The event to wait for
+  @param  Question               The Question to be printed.
   @param  FormattedNumber        Buffer for output string.
   @param  BufferSize             The FormattedNumber buffer size in bytes.
 
@@ -265,10 +256,6 @@ PasswordCallback (
 /**
   Display error message for invalid password.
 
-  None.
-
-  @return None.
-
 **/
 VOID
 PasswordInvalid (
@@ -624,7 +611,7 @@ ProcessOptions (
       //
       // For interactive passwords, old password is validated by callback
       //
-      if (Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) {
+      if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK)  != 0) {
         //
         // Use a NULL password to test whether old password is required
         //
@@ -707,7 +694,7 @@ ProcessOptions (
         //
         // Reset state machine for interactive password
         //
-        if (Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) {
+        if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {
           PasswordCallback (Selection, MenuOption, NULL);
         }
 
@@ -725,7 +712,7 @@ ProcessOptions (
         //
         // Reset state machine for interactive password
         //
-        if (Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) {
+        if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {
           PasswordCallback (Selection, MenuOption, NULL);
         }
 
@@ -741,7 +728,7 @@ ProcessOptions (
         //
         // Two password match, send it to Configuration Driver
         //
-        if (Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) {
+        if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {
           PasswordCallback (Selection, MenuOption, StringPtr);
         } else {
           CopyMem (Question->BufferValue, StringPtr, Maximum * sizeof (CHAR16));
@@ -751,7 +738,7 @@ ProcessOptions (
         //
         // Reset state machine for interactive password
         //
-        if (Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) {
+        if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {
           PasswordCallback (Selection, MenuOption, NULL);
         }
 
@@ -781,11 +768,8 @@ ProcessOptions (
   FormattedString and the glyph width of each line cannot exceed gHelpBlockWidth.
 
   @param  StringPtr              The entire help string.
-  @param  MenuOption             The MenuOption for this Question.
+  @param  FormattedString        The oupput formatted string.
   @param  RowCount               TRUE: if Question is selected.
-  @param  OptionString           Pointer of the Option String to be displayed.
-
-  @return None.
 
 **/
 VOID
index ff857750efdcd140e4389d60bfdfb5456f9bc246..40c2544bdd604687978f4482114efa66b9e6ba13 100644 (file)
-/** @file
-Copyright (c) 2007 - 2008, Intel Corporation
-All rights reserved. This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-Module Name:
-
-  Setup.c
-
-Abstract:
-
-  Entry and initialization module for the browser.
-
-
-**/
-
-#include "Setup.h"
-#include "Ui.h"
-
-
-SETUP_DRIVER_PRIVATE_DATA  mPrivateData = {
-  SETUP_DRIVER_SIGNATURE,
-  NULL,
-  {
-    SendForm,
-    BrowserCallback
-  },
-  {
-    UnicodeVSPrint
-  }
-};
-
-EFI_HII_DATABASE_PROTOCOL         *mHiiDatabase;
-EFI_HII_STRING_PROTOCOL           *mHiiString;
-EFI_HII_CONFIG_ROUTING_PROTOCOL   *mHiiConfigRouting;
-
-BANNER_DATA           *BannerData;
-EFI_HII_HANDLE        FrontPageHandle;
-UINTN                 gClassOfVfr;
-UINTN                 gFunctionKeySetting;
-BOOLEAN               gResetRequired;
-BOOLEAN               gNvUpdateRequired;
-EFI_HII_HANDLE        gHiiHandle;
-BOOLEAN               gFirstIn;
-UINT16                gDirection;
-EFI_SCREEN_DESCRIPTOR gScreenDimensions;
-BOOLEAN               gUpArrow;
-BOOLEAN               gDownArrow;
-
-//
-// Browser Global Strings
-//
-CHAR16            *gFunctionOneString;
-CHAR16            *gFunctionTwoString;
-CHAR16            *gFunctionNineString;
-CHAR16            *gFunctionTenString;
-CHAR16            *gEnterString;
-CHAR16            *gEnterCommitString;
-CHAR16            *gEscapeString;
-CHAR16            *gSaveFailed;
-CHAR16            *gMoveHighlight;
-CHAR16            *gMakeSelection;
-CHAR16            *gDecNumericInput;
-CHAR16            *gHexNumericInput;
-CHAR16            *gToggleCheckBox;
-CHAR16            *gPromptForData;
-CHAR16            *gPromptForPassword;
-CHAR16            *gPromptForNewPassword;
-CHAR16            *gConfirmPassword;
-CHAR16            *gConfirmError;
-CHAR16            *gPassowordInvalid;
-CHAR16            *gPressEnter;
-CHAR16            *gEmptyString;
-CHAR16            *gAreYouSure;
-CHAR16            *gYesResponse;
-CHAR16            *gNoResponse;
-CHAR16            *gMiniString;
-CHAR16            *gPlusString;
-CHAR16            *gMinusString;
-CHAR16            *gAdjustNumber;
-
-CHAR16            gPromptBlockWidth;
-CHAR16            gOptionBlockWidth;
-CHAR16            gHelpBlockWidth;
-
-EFI_GUID  gZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
-EFI_GUID  gSetupBrowserGuid = {
-  0xab368524, 0xb60c, 0x495b, {0xa0, 0x9, 0x12, 0xe8, 0x5b, 0x1a, 0xea, 0x32}
-};
-
-FUNCTIION_KEY_SETTING gFunctionKeySettingTable[] = {
-  //
-  // Boot Manager
-  //
-  {
-    {
-      0x847bc3fe,
-      0xb974,
-      0x446d,
-      {
-        0x94,
-        0x49,
-        0x5a,
-        0xd5,
-        0x41,
-        0x2e,
-        0x99,
-        0x3b
-      }
-    },
-    NONE_FUNCTION_KEY_SETTING
-  },
-  //
-  // Device Manager
-  //
-  {
-    {
-      0x3ebfa8e6,
-      0x511d,
-      0x4b5b,
-      {
-        0xa9,
-        0x5f,
-        0xfb,
-        0x38,
-        0x26,
-        0xf,
-        0x1c,
-        0x27
-      }
-    },
-    NONE_FUNCTION_KEY_SETTING
-  },
-  //
-  // BMM FormSet.
-  //
-  {
-    {
-      0x642237c7,
-      0x35d4,
-      0x472d,
-      {
-        0x83,
-        0x65,
-        0x12,
-        0xe0,
-        0xcc,
-        0xf2,
-        0x7a,
-        0x22
-      }
-    },
-    NONE_FUNCTION_KEY_SETTING
-  },
-  //
-  // BMM File Explorer FormSet.
-  //
-  {
-    {
-      0x1f2d63e1,
-      0xfebd,
-      0x4dc7,
-      {
-        0x9c,
-        0xc5,
-        0xba,
-        0x2b,
-        0x1c,
-        0xef,
-        0x9c,
-        0x5b
-      }
-    },
-    NONE_FUNCTION_KEY_SETTING
-  },
-};
-
-EFI_STATUS
-EFIAPI
-SendForm (
-  IN  CONST EFI_FORM_BROWSER2_PROTOCOL *This,
-  IN  EFI_HII_HANDLE                   *Handles,
-  IN  UINTN                            HandleCount,
-  IN  EFI_GUID                         *FormSetGuid, OPTIONAL
-  IN  UINT16                           FormId, OPTIONAL
-  IN  CONST EFI_SCREEN_DESCRIPTOR      *ScreenDimensions, OPTIONAL
-  OUT EFI_BROWSER_ACTION_REQUEST       *ActionRequest  OPTIONAL
-  )
-/*++
-
-Routine Description:
-  This is the routine which an external caller uses to direct the browser
-  where to obtain it's information.
-
-Arguments:
-  This            - The Form Browser protocol instanse.
-  Handles         - A pointer to an array of Handles.  If HandleCount > 1 we
-                    display a list of the formsets for the handles specified.
-  HandleCount     - The number of Handles specified in Handle.
-  FormSetGuid     - This field points to the EFI_GUID which must match the Guid
-                    field in the EFI_IFR_FORM_SET op-code for the specified
-                    forms-based package. If FormSetGuid is NULL, then this
-                    function will display the first found forms package.
-  FormId          - This field specifies which EFI_IFR_FORM to render as the first
-                    displayable page. If this field has a value of 0x0000, then
-                    the forms browser will render the specified forms in their encoded order.
-  ScreenDimenions - This allows the browser to be called so that it occupies a
-                    portion of the physical screen instead of dynamically determining the screen dimensions.
-  ActionRequest   - Points to the action recommended by the form.
-
-Returns:
-  EFI_SUCCESS           -  The function completed successfully.
-  EFI_INVALID_PARAMETER -  One of the parameters has an invalid value.
-  EFI_NOT_FOUND         -  No valid forms could be found to display.
-
---*/
-{
-  EFI_STATUS            Status;
-  UI_MENU_SELECTION     *Selection;
-  UINTN                 Index;
-  FORM_BROWSER_FORMSET  *FormSet;
-
-  Status = EFI_SUCCESS;
-  ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
-
-  //
-  // Seed the dimensions in the global
-  //
-  gST->ConOut->QueryMode (
-                 gST->ConOut,
-                 gST->ConOut->Mode->Mode,
-                 &gScreenDimensions.RightColumn,
-                 &gScreenDimensions.BottomRow
-                 );
-
-  if (ScreenDimensions != NULL) {
-    //
-    // Check local dimension vs. global dimension.
-    //
-    if ((gScreenDimensions.RightColumn < ScreenDimensions->RightColumn) ||
-        (gScreenDimensions.BottomRow < ScreenDimensions->BottomRow)
-        ) {
-      return EFI_INVALID_PARAMETER;
-    } else {
-      //
-      // Local dimension validation.
-      //
-      if ((ScreenDimensions->RightColumn > ScreenDimensions->LeftColumn) &&
-          (ScreenDimensions->BottomRow > ScreenDimensions->TopRow) &&
-          ((ScreenDimensions->RightColumn - ScreenDimensions->LeftColumn) > 2) &&
-          (
-            (ScreenDimensions->BottomRow - ScreenDimensions->TopRow) > STATUS_BAR_HEIGHT +
-            SCROLL_ARROW_HEIGHT *
-            2 +
-            FRONT_PAGE_HEADER_HEIGHT +
-            FOOTER_HEIGHT +
-            1
-          )
-        ) {
-        CopyMem (&gScreenDimensions, (VOID *) ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
-      } else {
-        return EFI_INVALID_PARAMETER;
-      }
-    }
-  }
-
-  gOptionBlockWidth = (CHAR16) ((gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3);
-  gHelpBlockWidth   = gOptionBlockWidth;
-  gPromptBlockWidth = gOptionBlockWidth;
-
-  //
-  // Initialize the strings for the browser, upon exit of the browser, the strings will be freed
-  //
-  InitializeBrowserStrings ();
-
-  gFunctionKeySetting = DEFAULT_FUNCTION_KEY_SETTING;
-  gClassOfVfr         = EFI_SETUP_APPLICATION_SUBCLASS;
-
-  //
-  // Ensure we are in Text mode
-  //
-  if (gFirstIn) {
-    gFirstIn = FALSE;
-    gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
-    DisableQuietBoot ();
-  }
-
-  for (Index = 0; Index < HandleCount; Index++) {
-    Selection = AllocateZeroPool (sizeof (UI_MENU_SELECTION));
-    ASSERT (Selection != NULL);
-
-    Selection->Handle = Handles[Index];
-    if (FormSetGuid != NULL) {
-      CopyMem (&Selection->FormSetGuid, FormSetGuid, sizeof (EFI_GUID));
-      Selection->FormId = FormId;
-    }
-
-    do {
-      FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));
-      ASSERT (FormSet != NULL);
-
-      //
-      // Initialize internal data structures of FormSet
-      //
-      Status = InitializeFormSet (Selection->Handle, &Selection->FormSetGuid, FormSet);
-      if (EFI_ERROR (Status)) {
-        DestroyFormSet (FormSet);
-        break;
-      }
-      Selection->FormSet = FormSet;
-
-      //
-      // Initialize current settings of Questions in this FormSet
-      //
-      Status = InitializeCurrentSetting (FormSet);
-      if (EFI_ERROR (Status)) {
-        DestroyFormSet (FormSet);
-        break;
-      }
-
-      //
-      // Display this formset
-      //
-      gCurrentSelection = Selection;
-
-      Status = SetupBrowser (Selection);
-
-      gCurrentSelection = NULL;
-      DestroyFormSet (FormSet);
-
-      if (EFI_ERROR (Status)) {
-        break;
-      }
-
-    } while (Selection->Action == UI_ACTION_REFRESH_FORMSET);
-
-    gBS->FreePool (Selection);
-  }
-
-  if (ActionRequest != NULL) {
-    *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
-    if (gResetRequired) {
-      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_RESET;
-    }
-  }
-
-  FreeBrowserStrings ();
-
-  gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
-  gST->ConOut->ClearScreen (gST->ConOut);
-
-  return Status;
-}
-
-
-/**
-  This function is called by a callback handler to retrieve uncommitted state
-  data from the browser.
-
-  @param  This                   A pointer to the EFI_FORM_BROWSER2_PROTOCOL
-                                 instance.
-  @param  ResultsDataSize        A pointer to the size of the buffer associated
-                                 with ResultsData.
-  @param  ResultsData            A string returned from an IFR browser or
-                                 equivalent. The results string will have no
-                                 routing information in them.
-  @param  RetrieveData           A BOOLEAN field which allows an agent to retrieve
-                                 (if RetrieveData = TRUE) data from the uncommitted
-                                 browser state information or set (if RetrieveData
-                                 = FALSE) data in the uncommitted browser state
-                                 information.
-  @param  VariableGuid           An optional field to indicate the target variable
-                                 GUID name to use.
-  @param  VariableName           An optional field to indicate the target
-                                 human-readable variable name.
-
-  @retval EFI_SUCCESS            The results have been distributed or are awaiting
-                                 distribution.
-  @retval EFI_BUFFER_TOO_SMALL   The ResultsDataSize specified was too small to
-                                 contain the results data.
-
-**/
-EFI_STATUS
-EFIAPI
-BrowserCallback (
-  IN CONST EFI_FORM_BROWSER2_PROTOCOL  *This,
-  IN OUT UINTN                         *ResultsDataSize,
-  IN OUT EFI_STRING                    ResultsData,
-  IN BOOLEAN                           RetrieveData,
-  IN CONST EFI_GUID                    *VariableGuid, OPTIONAL
-  IN CONST CHAR16                      *VariableName  OPTIONAL
-  )
-{
-  EFI_STATUS            Status;
-  LIST_ENTRY            *Link;
-  FORMSET_STORAGE       *Storage;
-  FORM_BROWSER_FORMSET  *FormSet;
-  BOOLEAN               Found;
-  CHAR16                *ConfigResp;
-  CHAR16                *StrPtr;
-  UINTN                 BufferSize;
-  UINTN                 TmpSize;
-
-  if (ResultsDataSize == NULL || ResultsData == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  if (gCurrentSelection == NULL) {
-    return EFI_NOT_READY;
-  }
-
-  Storage = NULL;
-  ConfigResp = NULL;
-  FormSet = gCurrentSelection->FormSet;
-
-  //
-  // Find target storage
-  //
-  Link = GetFirstNode (&FormSet->StorageListHead);
-  if (IsNull (&FormSet->StorageListHead, Link)) {
-    return EFI_UNSUPPORTED;
-  }
-
-  if (VariableGuid != NULL) {
-    //
-    // Try to find target storage
-    //
-    Found = FALSE;
-    while (!IsNull (&FormSet->StorageListHead, Link)) {
-      Storage = FORMSET_STORAGE_FROM_LINK (Link);
-      Link = GetNextNode (&FormSet->StorageListHead, Link);
-
-      if (CompareGuid (&Storage->Guid, (EFI_GUID *) VariableGuid)) {
-        if (Storage->Type == EFI_HII_VARSTORE_BUFFER) {
-          //
-          // Buffer storage require both GUID and Name
-          //
-          if (VariableName == NULL) {
-            return EFI_NOT_FOUND;
-          }
-
-          if (StrCmp (Storage->Name, (CHAR16 *) VariableName) != 0) {
-            continue;
-          }
-        }
-        Found = TRUE;
-        break;
-      }
-    }
-
-    if (!Found) {
-      return EFI_NOT_FOUND;
-    }
-  } else {
-    //
-    // GUID/Name is not specified, take the first storage in FormSet
-    //
-    Storage = FORMSET_STORAGE_FROM_LINK (Link);
-  }
-
-  if (RetrieveData) {
-    //
-    // Skip if there is no RequestElement
-    //
-    if (Storage->ElementCount == 0) {
-      return EFI_SUCCESS;
-    }
-
-    //
-    // Generate <ConfigResp>
-    //
-    Status = StorageToConfigResp (Storage, &ConfigResp);
-    if (EFI_ERROR (Status)) {
-      return Status;
-    }
-
-    //
-    // Skip <ConfigHdr> and '&' to point to <ConfigBody>
-    //
-    StrPtr = ConfigResp + StrLen (Storage->ConfigHdr) + 1;
-
-    BufferSize = StrSize (StrPtr);
-    if (*ResultsDataSize < BufferSize) {
-      *ResultsDataSize = BufferSize;
-
-      gBS->FreePool (ConfigResp);
-      return EFI_BUFFER_TOO_SMALL;
-    }
-
-    *ResultsDataSize = BufferSize;
-    CopyMem (ResultsData, StrPtr, BufferSize);
-
-    gBS->FreePool (ConfigResp);
-  } else {
-    //
-    // Prepare <ConfigResp>
-    //
-    TmpSize = StrLen (ResultsData);
-    BufferSize = (TmpSize + StrLen (Storage->ConfigHdr) + 2) * sizeof (CHAR16);
-    ConfigResp = AllocateZeroPool (BufferSize);
-    ASSERT (ConfigResp != NULL);
-
-    StrCpy (ConfigResp, Storage->ConfigHdr);
-    StrCat (ConfigResp, L"&");
-    StrCat (ConfigResp, ResultsData);
-
-    //
-    // Update Browser uncommited data
-    //
-    Status = ConfigRespToStorage (Storage, ConfigResp);
-    if (EFI_ERROR (Status)) {
-      return Status;
-    }
-  }
-
-  return EFI_SUCCESS;
-}
-
-
-/**
-  Initialize Setup
-
-  @param  entry                  EFI_IMAGE_ENTRY_POINT)
-
-  @retval EFI_SUCCESS            Setup loaded.
-  @retval other                  Setup Error
-
-**/
-EFI_STATUS
-EFIAPI
-InitializeSetup (
-  IN EFI_HANDLE           ImageHandle,
-  IN EFI_SYSTEM_TABLE     *SystemTable
-  )
-{
-  EFI_STATUS                  Status;
-  EFI_HANDLE                  HiiDriverHandle;
-  EFI_HII_PACKAGE_LIST_HEADER *PackageList;
-
-  //
-  // Locate required Hii relative protocols
-  //
-  Status = gBS->LocateProtocol (
-                  &gEfiHiiDatabaseProtocolGuid,
-                  NULL,
-                  (VOID **) &mHiiDatabase
-                  );
-  ASSERT_EFI_ERROR (Status);
-
-  Status = gBS->LocateProtocol (
-                  &gEfiHiiStringProtocolGuid,
-                  NULL,
-                  (VOID **) &mHiiString
-                  );
-  ASSERT_EFI_ERROR (Status);
-
-  Status = gBS->LocateProtocol (
-                  &gEfiHiiConfigRoutingProtocolGuid,
-                  NULL,
-                  (VOID **) &mHiiConfigRouting
-                  );
-  ASSERT_EFI_ERROR (Status);
-
-  //
-  // Publish our HII data
-  //
-  Status = HiiLibCreateHiiDriverHandle (&HiiDriverHandle);
-  ASSERT_EFI_ERROR (Status);
-
-  PackageList = HiiLibPreparePackageList (1, &gSetupBrowserGuid, SetupBrowserStrings);
-  ASSERT (PackageList != NULL);
-  Status = mHiiDatabase->NewPackageList (
-                           mHiiDatabase,
-                           PackageList,
-                           HiiDriverHandle,
-                           &gHiiHandle
-                           );
-  ASSERT_EFI_ERROR (Status);
-
-  //
-  // Initialize Driver private data
-  //
-  gFirstIn = TRUE;
-  BannerData = AllocateZeroPool (sizeof (BANNER_DATA));
-  ASSERT (BannerData != NULL);
-
-  //
-  // Install FormBrowser2 protocol
-  //
-  mPrivateData.Handle = NULL;
-  Status = gBS->InstallProtocolInterface (
-                  &mPrivateData.Handle,
-                  &gEfiFormBrowser2ProtocolGuid,
-                  EFI_NATIVE_INTERFACE,
-                  &mPrivateData.FormBrowser2
-                  );
-  ASSERT_EFI_ERROR (Status);
-
-  //
-  // Install Print protocol
-  //
-  Status = gBS->InstallProtocolInterface (
-                  &mPrivateData.Handle,
-                  &gEfiPrintProtocolGuid,
-                  EFI_NATIVE_INTERFACE,
-                  &mPrivateData.Print
-                  );
-
-  return Status;
-}
-
-
-/**
-  Create a new string in HII Package List.
-
-  @param  String                 The String to be added
-  @param  HiiHandle              The package list in the HII database to insert the
-                                 specified string.
-
-  @return The output string.
-
-**/
-EFI_STRING_ID
-NewString (
-  IN  CHAR16                   *String,
-  IN  EFI_HII_HANDLE           HiiHandle
-  )
-{
-  EFI_STRING_ID  StringId;
-  EFI_STATUS     Status;
-
-  StringId = 0;
-  Status = HiiLibNewString (HiiHandle, &StringId, String);
-  ASSERT_EFI_ERROR (Status);
-
-  return StringId;
-}
-
-
-/**
-  Delete a string from HII Package List.
-
-  @param  StringId               Id of the string in HII database.
-  @param  HiiHandle              The HII package list handle.
-
-  @retval EFI_SUCCESS            The string was deleted successfully.
-
-**/
-EFI_STATUS
-DeleteString (
-  IN  EFI_STRING_ID            StringId,
-  IN  EFI_HII_HANDLE           HiiHandle
-  )
-{
-  CHAR16  NullChar;
-
-  NullChar = CHAR_NULL;
-  return HiiLibSetString (HiiHandle, StringId, &NullChar);
-}
-
-
-/**
-  Get the string based on the StringId and HII Package List Handle.
-
-  @param  Token                  The String's ID.
-  @param  HiiHandle              The package list in the HII database to search for
-                                 the specified string.
-
-  @return The output string.
-
-**/
-CHAR16 *
-GetToken (
-  IN  EFI_STRING_ID                Token,
-  IN  EFI_HII_HANDLE               HiiHandle
-  )
-{
-  EFI_STATUS  Status;
-  CHAR16      *String;
-  UINTN       BufferLength;
-
-  //
-  // Set default string size assumption at no more than 256 bytes
-  //
-  BufferLength = 0x100;
-  String = AllocateZeroPool (BufferLength);
-  ASSERT (String != NULL);
-
-  Status = HiiLibGetString (HiiHandle, Token, String, &BufferLength);
-
-  if (Status == EFI_BUFFER_TOO_SMALL) {
-    gBS->FreePool (String);
-    String = AllocateZeroPool (BufferLength);
-    ASSERT (String != NULL);
-
-    Status = HiiLibGetString (HiiHandle, Token, String, &BufferLength);
-  }
-  ASSERT_EFI_ERROR (Status);
-
-  return String;
-}
-
-
-/**
-  Allocate new memory and then copy the Unicode string Source to Destination.
-
-  @param  Dest                   Location to copy string
-  @param  Src                    String to copy
-
-  @return NONE
-
-**/
-VOID
-NewStringCpy (
-  IN OUT CHAR16       **Dest,
-  IN CHAR16           *Src
-  )
-{
-  SafeFreePool (*Dest);
-  *Dest = AllocateCopyPool (StrSize (Src), Src);
-  ASSERT (*Dest != NULL);
-}
-
-
-/**
-  Allocate new memory and concatinate Source on the end of Destination.
-
-  @param  Dest                   String to added to the end of.
-  @param  Src                    String to concatinate.
-
-  @return NONE
-
-**/
-VOID
-NewStringCat (
-  IN OUT CHAR16       **Dest,
-  IN CHAR16           *Src
-  )
-{
-  CHAR16  *NewString;
-  UINTN   TmpSize;
-
-  if (*Dest == NULL) {
-    NewStringCpy (Dest, Src);
-    return;
-  }
-
-  TmpSize = StrSize (*Dest);
-  NewString = AllocateZeroPool (TmpSize + StrSize (Src) - 1);
-  ASSERT (NewString != NULL);
-
-  StrCpy (NewString, *Dest);
-  StrCat (NewString, Src);
-
-  gBS->FreePool (*Dest);
-  *Dest = NewString;
-}
-
-
-/**
-  Synchronize Storage's Edit copy to Shadow copy.
-
-  @param  Storage                The Storage to be synchronized.
-
-  @return NONE
-
-**/
-VOID
-SynchronizeStorage (
-  IN FORMSET_STORAGE         *Storage
-  )
-{
-  LIST_ENTRY              *Link;
-  NAME_VALUE_NODE         *Node;
-
-  switch (Storage->Type) {
-  case EFI_HII_VARSTORE_BUFFER:
-    CopyMem (Storage->Buffer, Storage->EditBuffer, Storage->Size);
-    break;
-
-  case EFI_HII_VARSTORE_NAME_VALUE:
-    Link = GetFirstNode (&Storage->NameValueListHead);
-    while (!IsNull (&Storage->NameValueListHead, Link)) {
-      Node = NAME_VALUE_NODE_FROM_LINK (Link);
-
-      NewStringCpy (&Node->Value, Node->EditValue);
-
-      Link = GetNextNode (&Storage->NameValueListHead, Link);
-    }
-    break;
-
-  case EFI_HII_VARSTORE_EFI_VARIABLE:
-  default:
-    break;
-  }
-}
-
-
-/**
-  Get Value for given Name from a NameValue Storage.
-
-  @param  Storage                The NameValue Storage.
-  @param  Name                   The Name.
-  @param  Value                  The retured Value.
-
-  @retval EFI_SUCCESS            Value found for given Name.
-  @retval EFI_NOT_FOUND          No such Name found in NameValue storage.
-
-**/
-EFI_STATUS
-GetValueByName (
-  IN FORMSET_STORAGE         *Storage,
-  IN CHAR16                  *Name,
-  IN OUT CHAR16              **Value
-  )
-{
-  LIST_ENTRY              *Link;
-  NAME_VALUE_NODE         *Node;
-
-  *Value = NULL;
-
-  Link = GetFirstNode (&Storage->NameValueListHead);
-  while (!IsNull (&Storage->NameValueListHead, Link)) {
-    Node = NAME_VALUE_NODE_FROM_LINK (Link);
-
-    if (StrCmp (Name, Node->Name) == 0) {
-      NewStringCpy (Value, Node->EditValue);
-      return EFI_SUCCESS;
-    }
-
-    Link = GetNextNode (&Storage->NameValueListHead, Link);
-  }
-
-  return EFI_NOT_FOUND;
-}
-
-
-/**
-  Set Value of given Name in a NameValue Storage.
-
-  @param  Storage                The NameValue Storage.
-  @param  Name                   The Name.
-  @param  Value                  The Value to set.
-
-  @retval EFI_SUCCESS            Value found for given Name.
-  @retval EFI_NOT_FOUND          No such Name found in NameValue storage.
-
-**/
-EFI_STATUS
-SetValueByName (
-  IN FORMSET_STORAGE         *Storage,
-  IN CHAR16                  *Name,
-  IN CHAR16                  *Value
-  )
-{
-  LIST_ENTRY              *Link;
-  NAME_VALUE_NODE         *Node;
-
-  Link = GetFirstNode (&Storage->NameValueListHead);
-  while (!IsNull (&Storage->NameValueListHead, Link)) {
-    Node = NAME_VALUE_NODE_FROM_LINK (Link);
-
-    if (StrCmp (Name, Node->Name) == 0) {
-      SafeFreePool (Node->EditValue);
-      Node->EditValue = AllocateCopyPool (StrSize (Value), Value);
-      ASSERT (Node->EditValue != NULL);
-      return EFI_SUCCESS;
-    }
-
-    Link = GetNextNode (&Storage->NameValueListHead, Link);
-  }
-
-  return EFI_NOT_FOUND;
-}
-
-
-/**
-  Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
-
-  @param  Storage                The Storage to be conveted.
-  @param  ConfigResp             The returned <ConfigResp>.
-
-  @retval EFI_SUCCESS            Convert success.
-  @retval EFI_INVALID_PARAMETER  Incorrect storage type.
-
-**/
-EFI_STATUS
-StorageToConfigResp (
-  IN FORMSET_STORAGE         *Storage,
-  IN CHAR16                  **ConfigResp
-  )
-{
-  EFI_STATUS  Status;
-  EFI_STRING  Progress;
-  LIST_ENTRY              *Link;
-  NAME_VALUE_NODE         *Node;
-
-  Status = EFI_SUCCESS;
-
-  switch (Storage->Type) {
-  case EFI_HII_VARSTORE_BUFFER:
-    Status = mHiiConfigRouting->BlockToConfig (
-                                  mHiiConfigRouting,
-                                  Storage->ConfigRequest,
-                                  Storage->EditBuffer,
-                                  Storage->Size,
-                                  ConfigResp,
-                                  &Progress
-                                  );
-    break;
-
-  case EFI_HII_VARSTORE_NAME_VALUE:
-    *ConfigResp = NULL;
-    NewStringCat (ConfigResp, Storage->ConfigHdr);
-
-    Link = GetFirstNode (&Storage->NameValueListHead);
-    while (!IsNull (&Storage->NameValueListHead, Link)) {
-      Node = NAME_VALUE_NODE_FROM_LINK (Link);
-
-      NewStringCat (ConfigResp, L"&");
-      NewStringCat (ConfigResp, Node->Name);
-      NewStringCat (ConfigResp, L"=");
-      NewStringCat (ConfigResp, Node->EditValue);
-
-      Link = GetNextNode (&Storage->NameValueListHead, Link);
-    }
-    break;
-
-  case EFI_HII_VARSTORE_EFI_VARIABLE:
-  default:
-    Status = EFI_INVALID_PARAMETER;
-    break;
-  }
-
-  return Status;
-}
-
-
-/**
-  Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
-
-  @param  Storage                The Storage to receive the settings.
-  @param  ConfigResp             The <ConfigResp> to be converted.
-
-  @retval EFI_SUCCESS            Convert success.
-  @retval EFI_INVALID_PARAMETER  Incorrect storage type.
-
-**/
-EFI_STATUS
-ConfigRespToStorage (
-  IN FORMSET_STORAGE         *Storage,
-  IN CHAR16                  *ConfigResp
-  )
-{
-  EFI_STATUS  Status;
-  EFI_STRING  Progress;
-  UINTN       BufferSize;
-  CHAR16      *StrPtr;
-  CHAR16      *Name;
-  CHAR16      *Value;
-
-  Status = EFI_SUCCESS;
-
-  switch (Storage->Type) {
-  case EFI_HII_VARSTORE_BUFFER:
-    BufferSize = Storage->Size;
-    Status = mHiiConfigRouting->ConfigToBlock (
-                                  mHiiConfigRouting,
-                                  ConfigResp,
-                                  Storage->EditBuffer,
-                                  &BufferSize,
-                                  &Progress
-                                  );
-    break;
-
-  case EFI_HII_VARSTORE_NAME_VALUE:
-    StrPtr = StrStr (ConfigResp, L"&");
-    while (StrPtr != NULL) {
-      //
-      // Skip '&'
-      //
-      StrPtr = StrPtr + 1;
-      Name = StrPtr;
-      StrPtr = StrStr (StrPtr, L"=");
-      if (StrPtr == NULL) {
-        break;
-      }
-      *StrPtr = 0;
-
-      //
-      // Skip '='
-      //
-      StrPtr = StrPtr + 1;
-      Value = StrPtr;
-      StrPtr = StrStr (StrPtr, L"&");
-      if (StrPtr != NULL) {
-        *StrPtr = 0;
-      }
-      SetValueByName (Storage, Name, Value);
-    }
-    break;
-
-  case EFI_HII_VARSTORE_EFI_VARIABLE:
-  default:
-    Status = EFI_INVALID_PARAMETER;
-    break;
-  }
-
-  return Status;
-}
-
-
-/**
-  Get Question's current Value.
-
-  @param  FormSet                FormSet data structure.
-  @param  Form                   Form data structure.
-  @param  Question               Question to be initialized.
-  @param  Cached                 TRUE:  get from Edit copy FALSE: get from original
-                                 Storage
-
-  @retval EFI_SUCCESS            The function completed successfully.
-
-**/
-EFI_STATUS
-GetQuestionValue (
-  IN FORM_BROWSER_FORMSET             *FormSet,
-  IN FORM_BROWSER_FORM                *Form,
-  IN OUT FORM_BROWSER_STATEMENT       *Question,
-  IN BOOLEAN                          Cached
-  )
-{
-  EFI_STATUS          Status;
-  BOOLEAN             Enabled;
-  BOOLEAN             Pending;
-  UINT8               *Dst;
-  UINTN               StorageWidth;
-  EFI_TIME            EfiTime;
-  FORMSET_STORAGE     *Storage;
-  EFI_IFR_TYPE_VALUE  *QuestionValue;
-  CHAR16              *ConfigRequest;
-  CHAR16              *Progress;
-  CHAR16              *Result;
-  CHAR16              *Value;
-  UINTN               Length;
-  BOOLEAN             IsBufferStorage;
-  BOOLEAN             IsString;
-
-  Status = EFI_SUCCESS;
-
-  //
-  // Statement don't have storage, skip them
-  //
-  if (Question->QuestionId == 0) {
-    return Status;
-  }
-
-  //
-  // Question value is provided by an Expression, evaluate it
-  //
-  if (Question->ValueExpression != NULL) {
-    Status = EvaluateExpression (FormSet, Form, Question->ValueExpression);
-    if (!EFI_ERROR (Status)) {
-      CopyMem (&Question->HiiValue, &Question->ValueExpression->Result, sizeof (EFI_HII_VALUE));
-    }
-    return Status;
-  }
-
-  //
-  // Question value is provided by RTC
-  //
-  Storage = Question->Storage;
-  QuestionValue = &Question->HiiValue.Value;
-  if (Storage == NULL) {
-    //
-    // It's a Question without storage, or RTC date/time
-    //
-    if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {
-      //
-      // Date and time define the same Flags bit
-      //
-      switch (Question->Flags & EFI_QF_DATE_STORAGE) {
-      case QF_DATE_STORAGE_TIME:
-        Status = gRT->GetTime (&EfiTime, NULL);
-        break;
-
-      case QF_DATE_STORAGE_WAKEUP:
-        Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);
-        break;
-
-      case QF_DATE_STORAGE_NORMAL:
-      default:
-        //
-        // For date/time without storage
-        //
-        return EFI_SUCCESS;
-      }
-
-      if (EFI_ERROR (Status)) {
-        return Status;
-      }
-
-      if (Question->Operand == EFI_IFR_DATE_OP) {
-        QuestionValue->date.Year  = EfiTime.Year;
-        QuestionValue->date.Month = EfiTime.Month;
-        QuestionValue->date.Day   = EfiTime.Day;
-      } else {
-        QuestionValue->time.Hour   = EfiTime.Hour;
-        QuestionValue->time.Minute = EfiTime.Minute;
-        QuestionValue->time.Second = EfiTime.Second;
-      }
-    }
-
-    return EFI_SUCCESS;
-  }
-
-  //
-  // Question value is provided by EFI variable
-  //
-  StorageWidth = Question->StorageWidth;
-  if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
-    if (Question->BufferValue != NULL) {
-      Dst = Question->BufferValue;
-    } else {
-      Dst = (UINT8 *) QuestionValue;
-    }
-
-    Status = gRT->GetVariable (
-                     Question->VariableName,
-                     &Storage->Guid,
-                     NULL,
-                     &StorageWidth,
-                     Dst
-                     );
-    //
-    // Always return success, even this EFI variable doesn't exist
-    //
-    return EFI_SUCCESS;
-  }
-
-  //
-  // Question Value is provided by Buffer Storage or NameValue Storage
-  //
-  if (Question->BufferValue != NULL) {
-    //
-    // This Question is password or orderedlist
-    //
-    Dst = Question->BufferValue;
-  } else {
-    //
-    // Other type of Questions
-    //
-    Dst = (UINT8 *) &Question->HiiValue.Value;
-  }
-
-  IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);
-  IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ?  TRUE : FALSE);
-  if (Cached) {
-    if (IsBufferStorage) {
-      //
-      // Copy from storage Edit buffer
-      //
-      CopyMem (Dst, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth);
-    } else {
-      Status = GetValueByName (Storage, Question->VariableName, &Value);
-      if (EFI_ERROR (Status)) {
-        return Status;
-      }
-
-      if (IsString) {
-        //
-        // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
-        //
-        Length = StorageWidth + sizeof (CHAR16);
-        Status = ConfigStringToUnicode ((CHAR16 *) Dst, &Length, Value);
-      } else {
-        Status = HexStringToBuf (Dst, &StorageWidth, Value, NULL);
-      }
-
-      gBS->FreePool (Value);
-    }
-  } else {
-    //
-    // Request current settings from Configuration Driver
-    //
-    if (FormSet->ConfigAccess == NULL) {
-      return EFI_NOT_FOUND;
-    }
-
-    //
-    // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
-    //                   <ConfigHdr> + "&" + <VariableName>
-    //
-    if (IsBufferStorage) {
-      Length = StrLen (Storage->ConfigHdr);
-      Length += StrLen (Question->BlockName);
-    } else {
-      Length = StrLen (Storage->ConfigHdr);
-      Length += StrLen (Question->VariableName) + 1;
-    }
-    ConfigRequest = AllocateZeroPool ((Length + 1) * sizeof (CHAR16));
-    ASSERT (ConfigRequest != NULL);
-
-    StrCpy (ConfigRequest, Storage->ConfigHdr);
-    if (IsBufferStorage) {
-      StrCat (ConfigRequest, Question->BlockName);
-    } else {
-      StrCat (ConfigRequest, L"&");
-      StrCat (ConfigRequest, Question->VariableName);
-    }
-
-    Status = FormSet->ConfigAccess->ExtractConfig (
-                                      FormSet->ConfigAccess,
-                                      ConfigRequest,
-                                      &Progress,
-                                      &Result
-                                      );
-    if (EFI_ERROR (Status)) {
-      return Status;
-    }
-
-    //
-    // Skip <ConfigRequest>
-    //
-    Value = Result + Length;
-    if (IsBufferStorage) {
-      //
-      // Skip "&VALUE"
-      //
-      Value = Value + 6;
-    }
-    if (*Value != '=') {
-      gBS->FreePool (Result);
-      return EFI_NOT_FOUND;
-    }
-    //
-    // Skip '=', point to value
-    //
-    Value = Value + 1;
-    if (!IsBufferStorage && IsString) {
-      //
-      // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
-      //
-      Length = StorageWidth + sizeof (CHAR16);
-      Status = ConfigStringToUnicode ((CHAR16 *) Dst, &Length, Value);
-    } else {
-      Status = HexStringToBuf (Dst, &StorageWidth, Value, NULL);
-      if (EFI_ERROR (Status)) {
-        gBS->FreePool (Result);
-        return Status;
-      }
-    }
-
-    //
-    // Synchronize Edit Buffer
-    //
-    if (IsBufferStorage) {
-      CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth);
-    } else {
-      SetValueByName (Storage, Question->VariableName, Value);
-    }
-    gBS->FreePool (Result);
-  }
-
-  return Status;
-}
-
-
-/**
-  Save Question Value to edit copy(cached) or Storage(uncached).
-
-  @param  FormSet                FormSet data structure.
-  @param  Form                   Form data structure.
-  @param  Question               Pointer to the Question.
-  @param  Cached                 TRUE:  set to Edit copy FALSE: set to original
-                                 Storage
-
-  @retval EFI_SUCCESS            The function completed successfully.
-
-**/
-EFI_STATUS
-SetQuestionValue (
-  IN FORM_BROWSER_FORMSET             *FormSet,
-  IN FORM_BROWSER_FORM                *Form,
-  IN OUT FORM_BROWSER_STATEMENT       *Question,
-  IN BOOLEAN                          Cached
-  )
-{
-  EFI_STATUS          Status;
-  BOOLEAN             Enabled;
-  BOOLEAN             Pending;
-  UINT8               *Src;
-  EFI_TIME            EfiTime;
-  UINTN               BufferLen;
-  UINTN               StorageWidth;
-  FORMSET_STORAGE     *Storage;
-  EFI_IFR_TYPE_VALUE  *QuestionValue;
-  CHAR16              *ConfigResp;
-  CHAR16              *Progress;
-  CHAR16              *Value;
-  UINTN               Length;
-  BOOLEAN             IsBufferStorage;
-  BOOLEAN             IsString;
-
-  Status = EFI_SUCCESS;
-
-  //
-  // Statement don't have storage, skip them
-  //
-  if (Question->QuestionId == 0) {
-    return Status;
-  }
-
-  //
-  // If Question value is provided by an Expression, then it is read only
-  //
-  if (Question->ValueExpression != NULL) {
-    return Status;
-  }
-
-  //
-  // Question value is provided by RTC
-  //
-  Storage = Question->Storage;
-  QuestionValue = &Question->HiiValue.Value;
-  if (Storage == NULL) {
-    //
-    // It's a Question without storage, or RTC date/time
-    //
-    if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {
-      //
-      // Date and time define the same Flags bit
-      //
-      switch (Question->Flags & EFI_QF_DATE_STORAGE) {
-      case QF_DATE_STORAGE_TIME:
-        Status = gRT->GetTime (&EfiTime, NULL);
-        break;
-
-      case QF_DATE_STORAGE_WAKEUP:
-        Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);
-        break;
-
-      case QF_DATE_STORAGE_NORMAL:
-      default:
-        //
-        // For date/time without storage
-        //
-        return EFI_SUCCESS;
-      }
-
-      if (EFI_ERROR (Status)) {
-        return Status;
-      }
-
-      if (Question->Operand == EFI_IFR_DATE_OP) {
-        EfiTime.Year  = QuestionValue->date.Year;
-        EfiTime.Month = QuestionValue->date.Month;
-        EfiTime.Day   = QuestionValue->date.Day;
-      } else {
-        EfiTime.Hour   = QuestionValue->time.Hour;
-        EfiTime.Minute = QuestionValue->time.Minute;
-        EfiTime.Second = QuestionValue->time.Second;
-      }
-
-      if ((Question->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_TIME) {
-        Status = gRT->SetTime (&EfiTime);
-      } else {
-        Status = gRT->SetWakeupTime (TRUE, &EfiTime);
-      }
-    }
-
-    return Status;
-  }
-
-  //
-  // Question value is provided by EFI variable
-  //
-  StorageWidth = Question->StorageWidth;
-  if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
-    if (Question->BufferValue != NULL) {
-      Src = Question->BufferValue;
-    } else {
-      Src = (UINT8 *) QuestionValue;
-    }
-
-    Status = gRT->SetVariable (
-                     Question->VariableName,
-                     &Storage->Guid,
-                     Storage->Attributes,
-                     StorageWidth,
-                     Src
-                     );
-    return Status;
-  }
-
-  //
-  // Question Value is provided by Buffer Storage or NameValue Storage
-  //
-  if (Question->BufferValue != NULL) {
-    Src = Question->BufferValue;
-  } else {
-    Src = (UINT8 *) &Question->HiiValue.Value;
-  }
-
-  IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);
-  IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ?  TRUE : FALSE);
-  if (IsBufferStorage) {
-    //
-    // Copy to storage edit buffer
-    //
-    CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);
-  } else {
-    if (IsString) {
-      //
-      // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
-      //
-      Value = NULL;
-      BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16);
-      Value = AllocateZeroPool (BufferLen);
-      ASSERT (Value != NULL);
-      Status = UnicodeToConfigString (Value, &BufferLen, (CHAR16 *) Src);
-      ASSERT_EFI_ERROR (Status);
-    } else {
-      BufferLen = StorageWidth * 2 + 1;
-      Value = AllocateZeroPool (BufferLen * sizeof (CHAR16));
-      ASSERT (Value != NULL);
-      BufToHexString (Value, &BufferLen, Src, StorageWidth);
-      ToLower (Value);
-    }
-
-    Status = SetValueByName (Storage, Question->VariableName, Value);
-    gBS->FreePool (Value);
-  }
-
-  if (!Cached) {
-    //
-    // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
-    //                <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
-    //
-    if (IsBufferStorage) {
-      Length = StrLen (Question->BlockName) + 7;
-    } else {
-      Length = StrLen (Question->VariableName) + 2;
-    }
-    if (!IsBufferStorage && IsString) {
-      Length += (StrLen ((CHAR16 *) Src) * 4);
-    } else {
-      Length += (StorageWidth * 2);
-    }
-    ConfigResp = AllocateZeroPool ((StrLen (Storage->ConfigHdr) + Length + 1) * sizeof (CHAR16));
-    ASSERT (ConfigResp != NULL);
-
-    StrCpy (ConfigResp, Storage->ConfigHdr);
-    if (IsBufferStorage) {
-      StrCat (ConfigResp, Question->BlockName);
-      StrCat (ConfigResp, L"&VALUE=");
-    } else {
-      StrCat (ConfigResp, L"&");
-      StrCat (ConfigResp, Question->VariableName);
-      StrCat (ConfigResp, L"=");
-    }
-
-    Value = ConfigResp + StrLen (ConfigResp);
-    if (!IsBufferStorage && IsString) {
-      //
-      // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
-      //
-      BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16);
-      Status = UnicodeToConfigString (Value, &BufferLen, (CHAR16 *) Src);
-      ASSERT_EFI_ERROR (Status);
-    } else {
-      BufferLen = StorageWidth * 2 + 1;
-      BufToHexString (Value, &BufferLen, Src, StorageWidth);
-      ToLower (Value);
-    }
-
-    //
-    // Submit Question Value to Configuration Driver
-    //
-    if (FormSet->ConfigAccess != NULL) {
-      Status = FormSet->ConfigAccess->RouteConfig (
-                                        FormSet->ConfigAccess,
-                                        ConfigResp,
-                                        &Progress
-                                        );
-      if (EFI_ERROR (Status)) {
-        gBS->FreePool (ConfigResp);
-        return Status;
-      }
-    }
-    gBS->FreePool (ConfigResp);
-
-    //
-    // Synchronize shadow Buffer
-    //
-    SynchronizeStorage (Storage);
-  }
-
-  return Status;
-}
-
-
-/**
-  Perform inconsistent check for a Form.
-
-  @param  FormSet                FormSet data structure.
-  @param  Form                   Form data structure.
-  @param  Question               The Question to be validated.
-  @param  Type                   Validation type: InConsistent or NoSubmit
-
-  @retval EFI_SUCCESS            Form validation pass.
-  @retval other                  Form validation failed.
-
-**/
-EFI_STATUS
-ValidateQuestion (
-  IN  FORM_BROWSER_FORMSET            *FormSet,
-  IN  FORM_BROWSER_FORM               *Form,
-  IN  FORM_BROWSER_STATEMENT          *Question,
-  IN  UINTN                           Type
-  )
-{
-  EFI_STATUS              Status;
-  LIST_ENTRY              *Link;
-  LIST_ENTRY              *ListHead;
-  EFI_STRING              PopUp;
-  EFI_INPUT_KEY           Key;
-  FORM_EXPRESSION         *Expression;
-
-  if (Type == EFI_HII_EXPRESSION_INCONSISTENT_IF) {
-    ListHead = &Question->InconsistentListHead;
-  } else if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {
-    ListHead = &Question->NoSubmitListHead;
-  } else {
-    return EFI_UNSUPPORTED;
-  }
-
-  Link = GetFirstNode (ListHead);
-  while (!IsNull (ListHead, Link)) {
-    Expression = FORM_EXPRESSION_FROM_LINK (Link);
-
-    //
-    // Evaluate the expression
-    //
-    Status = EvaluateExpression (FormSet, Form, Expression);
-    if (EFI_ERROR (Status)) {
-      return Status;
-    }
-
-    if (Expression->Result.Value.b) {
-      //
-      // Condition meet, show up error message
-      //
-      if (Expression->Error != 0) {
-        PopUp = GetToken (Expression->Error, FormSet->HiiHandle);
-        do {
-          CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, PopUp, gPressEnter, gEmptyString);
-        } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
-        gBS->FreePool (PopUp);
-      }
-
-      return EFI_NOT_READY;
-    }
-
-    Link = GetNextNode (ListHead, Link);
-  }
-
-  return EFI_SUCCESS;
-}
-
-
-/**
-  Perform NoSubmit check for a Form.
-
-  @param  FormSet                FormSet data structure.
-  @param  Form                   Form data structure.
-
-  @retval EFI_SUCCESS            Form validation pass.
-  @retval other                  Form validation failed.
-
-**/
-EFI_STATUS
-NoSubmitCheck (
-  IN  FORM_BROWSER_FORMSET            *FormSet,
-  IN  FORM_BROWSER_FORM               *Form
-  )
-{
-  EFI_STATUS              Status;
-  LIST_ENTRY              *Link;
-  FORM_BROWSER_STATEMENT  *Question;
-
-  Link = GetFirstNode (&Form->StatementListHead);
-  while (!IsNull (&Form->StatementListHead, Link)) {
-    Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
-
-    Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_NO_SUBMIT_IF);
-    if (EFI_ERROR (Status)) {
-      return Status;
-    }
-
-    Link = GetNextNode (&Form->StatementListHead, Link);
-  }
-
-  return EFI_SUCCESS;
-}
-
-
-/**
-  Submit a Form.
-
-  @param  FormSet                FormSet data structure.
-  @param  Form                   Form data structure.
-
-  @retval EFI_SUCCESS            The function completed successfully.
-
-**/
-EFI_STATUS
-SubmitForm (
-  IN FORM_BROWSER_FORMSET             *FormSet,
-  IN FORM_BROWSER_FORM                *Form
-  )
-{
-  EFI_STATUS              Status;
-  LIST_ENTRY              *Link;
-  EFI_STRING              ConfigResp;
-  EFI_STRING              Progress;
-  FORMSET_STORAGE         *Storage;
-
-  //
-  // Validate the Form by NoSubmit check
-  //
-  Status = NoSubmitCheck (FormSet, Form);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  //
-  // Submit Buffer storage or Name/Value storage
-  //
-  Link = GetFirstNode (&FormSet->StorageListHead);
-  while (!IsNull (&FormSet->StorageListHead, Link)) {
-    Storage = FORMSET_STORAGE_FROM_LINK (Link);
-    Link = GetNextNode (&FormSet->StorageListHead, Link);
-
-    if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
-      continue;
-    }
-
-    //
-    // Skip if there is no RequestElement
-    //
-    if (Storage->ElementCount == 0) {
-      continue;
-    }
-
-    //
-    // Prepare <ConfigResp>
-    //
-    Status = StorageToConfigResp (Storage, &ConfigResp);
-    if (EFI_ERROR (Status)) {
-      return Status;
-    }
-
-    //
-    // Send <ConfigResp> to Configuration Driver
-    //
-    if (FormSet->ConfigAccess != NULL) {
-      Status = FormSet->ConfigAccess->RouteConfig (
-                                        FormSet->ConfigAccess,
-                                        ConfigResp,
-                                        &Progress
-                                        );
-      if (EFI_ERROR (Status)) {
-        gBS->FreePool (ConfigResp);
-        return Status;
-      }
-    }
-    gBS->FreePool (ConfigResp);
-
-    //
-    // Config success, update storage shadow Buffer
-    //
-    SynchronizeStorage (Storage);
-  }
-
-  gNvUpdateRequired = FALSE;
-
-  return EFI_SUCCESS;
-}
-
-
-/**
-  Reset Question to its default value.
-
-  @param  FormSet                FormSet data structure.
-  @param  DefaultId              The Class of the default.
-
-  @retval EFI_SUCCESS            Question is reset to default value.
-
-**/
-EFI_STATUS
-GetQuestionDefault (
-  IN FORM_BROWSER_FORMSET             *FormSet,
-  IN FORM_BROWSER_FORM                *Form,
-  IN FORM_BROWSER_STATEMENT           *Question,
-  IN UINT16                           DefaultId
-  )
-{
-  EFI_STATUS              Status;
-  LIST_ENTRY              *Link;
-  QUESTION_DEFAULT        *Default;
-  QUESTION_OPTION         *Option;
-  EFI_HII_VALUE           *HiiValue;
-  UINT8                   Index;
-
-  Status = EFI_SUCCESS;
-
-  //
-  // Statement don't have storage, skip them
-  //
-  if (Question->QuestionId == 0) {
-    return Status;
-  }
-
-  //
-  // There are three ways to specify default value for a Question:
-  //  1, use nested EFI_IFR_DEFAULT (highest priority)
-  //  2, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
-  //  3, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
-  //
-  HiiValue = &Question->HiiValue;
-
-  //
-  // EFI_IFR_DEFAULT has highest priority
-  //
-  if (!IsListEmpty (&Question->DefaultListHead)) {
-    Link = GetFirstNode (&Question->DefaultListHead);
-    while (!IsNull (&Question->DefaultListHead, Link)) {
-      Default = QUESTION_DEFAULT_FROM_LINK (Link);
-
-      if (Default->DefaultId == DefaultId) {
-        if (Default->ValueExpression != NULL) {
-          //
-          // Default is provided by an Expression, evaluate it
-          //
-          Status = EvaluateExpression (FormSet, Form, Default->ValueExpression);
-          if (EFI_ERROR (Status)) {
-            return Status;
-          }
-
-          CopyMem (HiiValue, &Default->ValueExpression->Result, sizeof (EFI_HII_VALUE));
-        } else {
-          //
-          // Default value is embedded in EFI_IFR_DEFAULT
-          //
-          CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));
-        }
-
-        return EFI_SUCCESS;
-      }
-
-      Link = GetNextNode (&Question->DefaultListHead, Link);
-    }
-  }
-
-  //
-  // EFI_ONE_OF_OPTION
-  //
-  if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {
-    if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING)  {
-      //
-      // OneOfOption could only provide Standard and Manufacturing default
-      //
-      Link = GetFirstNode (&Question->OptionListHead);
-      while (!IsNull (&Question->OptionListHead, Link)) {
-        Option = QUESTION_OPTION_FROM_LINK (Link);
-
-        if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && (Option->Flags & EFI_IFR_OPTION_DEFAULT)) ||
-            ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && (Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG))
-           ) {
-          CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));
-
-          return EFI_SUCCESS;
-        }
-
-        Link = GetNextNode (&Question->OptionListHead, Link);
-      }
-    }
-  }
-
-  //
-  // EFI_IFR_CHECKBOX - lowest priority
-  //
-  if (Question->Operand == EFI_IFR_CHECKBOX_OP) {
-    if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING)  {
-      //
-      // Checkbox could only provide Standard and Manufacturing default
-      //
-      if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && (Question->Flags & EFI_IFR_CHECKBOX_DEFAULT)) ||
-          ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && (Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG))
-         ) {
-        HiiValue->Value.b = TRUE;
-      } else {
-        HiiValue->Value.b = FALSE;
-      }
-
-      return EFI_SUCCESS;
-    }
-  }
-
-  //
-  // For Questions without default
-  //
-  switch (Question->Operand) {
-  case EFI_IFR_NUMERIC_OP:
-    //
-    // Take minimal value as numeric's default value
-    //
-    HiiValue->Value.u64 = Question->Minimum;
-    break;
-
-  case EFI_IFR_ONE_OF_OP:
-    //
-    // Take first oneof option as oneof's default value
-    //
-    Link = GetFirstNode (&Question->OptionListHead);
-    if (!IsNull (&Question->OptionListHead, Link)) {
-      Option = QUESTION_OPTION_FROM_LINK (Link);
-      CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));
-    }
-    break;
-
-  case EFI_IFR_ORDERED_LIST_OP:
-    //
-    // Take option sequence in IFR as ordered list's default value
-    //
-    Index = 0;
-    Link = GetFirstNode (&Question->OptionListHead);
-    while (!IsNull (&Question->OptionListHead, Link)) {
-      Option = QUESTION_OPTION_FROM_LINK (Link);
-
-      Question->BufferValue[Index] = Option->Value.Value.u8;
-
-      Index++;
-      if (Index >= Question->MaxContainers) {
-        break;
-      }
-
-      Link = GetNextNode (&Question->OptionListHead, Link);
-    }
-    break;
-
-  default:
-    Status = EFI_NOT_FOUND;
-    break;
-  }
-
-  return Status;
-}
-
-
-/**
-  Reset Questions in a Form to their default value.
-
-  @param  FormSet                FormSet data structure.
-  @param  Form                   The Form which to be reset.
-  @param  DefaultId              The Class of the default.
-
-  @retval EFI_SUCCESS            The function completed successfully.
-
-**/
-EFI_STATUS
-ExtractFormDefault (
-  IN FORM_BROWSER_FORMSET             *FormSet,
-  IN FORM_BROWSER_FORM                *Form,
-  IN UINT16                           DefaultId
-  )
-{
-  EFI_STATUS              Status;
-  LIST_ENTRY              *Link;
-  FORM_BROWSER_STATEMENT  *Question;
-
-  Link = GetFirstNode (&Form->StatementListHead);
-  while (!IsNull (&Form->StatementListHead, Link)) {
-    Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
-    Link = GetNextNode (&Form->StatementListHead, Link);
-
-    //
-    // Reset Question to its default value
-    //
-    Status = GetQuestionDefault (FormSet, Form, Question, DefaultId);
-    if (EFI_ERROR (Status)) {
-      continue;
-    }
-
-    //
-    // Synchronize Buffer storage's Edit buffer
-    //
-    if ((Question->Storage != NULL) &&
-        (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) {
-      SetQuestionValue (FormSet, Form, Question, TRUE);
-    }
-  }
-
-  return EFI_SUCCESS;
-}
-
-
-/**
-  Initialize Question's Edit copy from Storage.
-
-  @param  FormSet                FormSet data structure.
-  @param  Form                   Form data structure.
-
-  @retval EFI_SUCCESS            The function completed successfully.
-
-**/
-EFI_STATUS
-LoadFormConfig (
-  IN FORM_BROWSER_FORMSET             *FormSet,
-  IN FORM_BROWSER_FORM                *Form
-  )
-{
-  EFI_STATUS              Status;
-  LIST_ENTRY              *Link;
-  FORM_BROWSER_STATEMENT  *Question;
-
-  Link = GetFirstNode (&Form->StatementListHead);
-  while (!IsNull (&Form->StatementListHead, Link)) {
-    Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
-
-    //
-    // Initialize local copy of Value for each Question
-    //
-    Status = GetQuestionValue (FormSet, Form, Question, TRUE);
-    if (EFI_ERROR (Status)) {
-      return Status;
-    }
-
-    Link = GetNextNode (&Form->StatementListHead, Link);
-  }
-
-  return EFI_SUCCESS;
-}
-
-
-/**
-  Fill storage's edit copy with settings requested from Configuration Driver.
-
-  @param  FormSet                FormSet data structure.
-  @param  Storage                Buffer Storage.
-
-  @retval EFI_SUCCESS            The function completed successfully.
-
-**/
-EFI_STATUS
-LoadStorage (
-  IN FORM_BROWSER_FORMSET    *FormSet,
-  IN FORMSET_STORAGE         *Storage
-  )
-{
-  EFI_STATUS  Status;
-  EFI_STRING  Progress;
-  EFI_STRING  Result;
-  CHAR16      *StrPtr;
-
-  if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
-    return EFI_SUCCESS;
-  }
-
-  if (FormSet->ConfigAccess == NULL) {
-    return EFI_NOT_FOUND;
-  }
-
-  if (Storage->ElementCount == 0) {
-    //
-    // Skip if there is no RequestElement
-    //
-    return EFI_SUCCESS;
-  }
-
-  //
-  // Request current settings from Configuration Driver
-  //
-  Status = FormSet->ConfigAccess->ExtractConfig (
-                                    FormSet->ConfigAccess,
-                                    Storage->ConfigRequest,
-                                    &Progress,
-                                    &Result
-                                    );
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  //
-  // Convert Result from <ConfigAltResp> to <ConfigResp>
-  //
-  StrPtr = StrStr (Result, L"ALTCFG");
-  if (StrPtr != NULL) {
-    *StrPtr = L'\0';
-  }
-
-  Status = ConfigRespToStorage (Storage, Result);
-  gBS->FreePool (Result);
-  return Status;
-}
-
-
-/**
-  Get current setting of Questions.
-
-  @param  FormSet                FormSet data structure.
-
-  @retval EFI_SUCCESS            The function completed successfully.
-
-**/
-EFI_STATUS
-InitializeCurrentSetting (
-  IN OUT FORM_BROWSER_FORMSET             *FormSet
-  )
-{
-  LIST_ENTRY              *Link;
-  FORMSET_STORAGE         *Storage;
-  FORM_BROWSER_FORM       *Form;
-  EFI_STATUS              Status;
-
-  //
-  // Extract default from IFR binary
-  //
-  Link = GetFirstNode (&FormSet->FormListHead);
-  while (!IsNull (&FormSet->FormListHead, Link)) {
-    Form = FORM_BROWSER_FORM_FROM_LINK (Link);
-
-    Status = ExtractFormDefault (FormSet, Form, EFI_HII_DEFAULT_CLASS_STANDARD);
-
-    Link = GetNextNode (&FormSet->FormListHead, Link);
-  }
-
-  //
-  // Request current settings from Configuration Driver
-  //
-  Link = GetFirstNode (&FormSet->StorageListHead);
-  while (!IsNull (&FormSet->StorageListHead, Link)) {
-    Storage = FORMSET_STORAGE_FROM_LINK (Link);
-
-    Status = LoadStorage (FormSet, Storage);
-
-    //
-    // Now Edit Buffer is filled with default values(lower priority) and current
-    // settings(higher priority), sychronize it to shadow Buffer
-    //
-    if (!EFI_ERROR (Status)) {
-      SynchronizeStorage (Storage);
-    }
-
-    Link = GetNextNode (&FormSet->StorageListHead, Link);
-  }
-
-  return EFI_SUCCESS;
-}
-
-
-/**
-  Fetch the Ifr binary data of a FormSet.
-
-  @param  Handle                 PackageList Handle
-  @param  FormSetGuid            GUID of a formset. If not specified (NULL or zero
-                                 GUID), take the first FormSet found in package
-                                 list.
-  @param  BinaryLength           The length of the FormSet IFR binary.
-  @param  BinaryData             The buffer designed to receive the FormSet.
-
-  @retval EFI_SUCCESS            Buffer filled with the requested FormSet.
-                                 BufferLength was updated.
-  @retval EFI_INVALID_PARAMETER  The handle is unknown.
-  @retval EFI_NOT_FOUND          A form or FormSet on the requested handle cannot
-                                 be found with the requested FormId.
-
-**/
-EFI_STATUS
-GetIfrBinaryData (
-  IN  EFI_HII_HANDLE   Handle,
-  IN OUT EFI_GUID      *FormSetGuid,
-  OUT UINTN            *BinaryLength,
-  OUT UINT8            **BinaryData
-  )
-{
-  EFI_STATUS                   Status;
-  EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;
-  UINTN                        BufferSize;
-  UINT8                        *Package;
-  UINT8                        *OpCodeData;
-  UINT32                       Offset;
-  UINT32                       Offset2;
-  BOOLEAN                      ReturnDefault;
-  UINT32                       PackageListLength;
-  EFI_HII_PACKAGE_HEADER       PackageHeader;
-
-  OpCodeData = NULL;
-  Package = NULL;
-  ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));;
-
-  //
-  // if FormSetGuid is NULL or zero GUID, return first FormSet in the package list
-  //
-  if (FormSetGuid == NULL || CompareGuid (FormSetGuid, &gZeroGuid)) {
-    ReturnDefault = TRUE;
-  } else {
-    ReturnDefault = FALSE;
-  }
-
-  //
-  // Get HII PackageList
-  //
-  BufferSize = 0;
-  HiiPackageList = NULL;
-  Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
-  if (Status == EFI_BUFFER_TOO_SMALL) {
-    HiiPackageList = AllocatePool (BufferSize);
-    ASSERT (HiiPackageList != NULL);
-
-    Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
-  }
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  //
-  // Get Form package from this HII package List
-  //
-  Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
-  Offset2 = 0;
-  CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));
-
-  while (Offset < PackageListLength) {
-    Package = ((UINT8 *) HiiPackageList) + Offset;
-    CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
-
-    if (PackageHeader.Type == EFI_HII_PACKAGE_FORM) {
-      //
-      // Search FormSet in this Form Package
-      //
-      Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);
-      while (Offset2 < PackageHeader.Length) {
-        OpCodeData = Package + Offset2;
-
-        if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {
-          //
-          // Check whether return default FormSet
-          //
-          if (ReturnDefault) {
-            break;
-          }
-
-          //
-          // FormSet GUID is specified, check it
-          //
-          if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {
-            break;
-          }
-        }
-
-        Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
-      }
-
-      if (Offset2 < PackageHeader.Length) {
-        //
-        // Target formset found
-        //
-        break;
-      }
-    }
-
-    Offset += PackageHeader.Length;
-  }
-
-  if (Offset >= PackageListLength) {
-    //
-    // Form package not found in this Package List
-    //
-    gBS->FreePool (HiiPackageList);
-    return EFI_NOT_FOUND;
-  }
-
-  if (ReturnDefault && FormSetGuid != NULL) {
-    //
-    // Return the default FormSet GUID
-    //
-    CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));
-  }
-
-  //
-  // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
-  // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
-  // of the Form Package.
-  //
-  *BinaryLength = PackageHeader.Length - Offset2;
-  *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);
-
-  gBS->FreePool (HiiPackageList);
-
-  if (*BinaryData == NULL) {
-    return EFI_OUT_OF_RESOURCES;
-  }
-
-  return EFI_SUCCESS;
-}
-
-
-/**
-  Initialize the internal data structure of a FormSet.
-
-  @param  Handle                 PackageList Handle
-  @param  FormSetGuid            GUID of a formset. If not specified (NULL or zero
-                                 GUID), take the first FormSet found in package
-                                 list.
-  @param  FormSet                FormSet data structure.
-
-  @retval EFI_SUCCESS            The function completed successfully.
-  @retval EFI_NOT_FOUND          The specified FormSet could not be found.
-
-**/
-EFI_STATUS
-InitializeFormSet (
-  IN  EFI_HII_HANDLE                   Handle,
-  IN OUT EFI_GUID                      *FormSetGuid,
-  OUT FORM_BROWSER_FORMSET             *FormSet
-  )
-{
-  EFI_STATUS                Status;
-  EFI_HANDLE                DriverHandle;
-  UINT16                    Index;
-
-  Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  FormSet->HiiHandle = Handle;
-  CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));
-
-  //
-  // Retrieve ConfigAccess Protocol associated with this HiiPackageList
-  //
-  Status = mHiiDatabase->GetPackageListHandle (mHiiDatabase, Handle, &DriverHandle);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-  FormSet->DriverHandle = DriverHandle;
-  Status = gBS->HandleProtocol (
-                  DriverHandle,
-                  &gEfiHiiConfigAccessProtocolGuid,
-                  (VOID **) &FormSet->ConfigAccess
-                  );
-  if (EFI_ERROR (Status)) {
-    //
-    // Configuration Driver don't attach ConfigAccess protocol to its HII package
-    // list, then there will be no configuration action required
-    //
-    FormSet->ConfigAccess = NULL;
-  }
-
-  //
-  // Parse the IFR binary OpCodes
-  //
-  Status = ParseOpCodes (FormSet);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  gClassOfVfr = FormSet->SubClass;
-  if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {
-    FrontPageHandle = FormSet->HiiHandle;
-  }
-
-  //
-  // Match GUID to find out the function key setting. If match fail, use the default setting.
-  //
-  for (Index = 0; Index < sizeof (gFunctionKeySettingTable) / sizeof (FUNCTIION_KEY_SETTING); Index++) {
-    if (CompareGuid (&FormSet->Guid, &(gFunctionKeySettingTable[Index].FormSetGuid))) {
-      //
-      // Update the function key setting.
-      //
-      gFunctionKeySetting = gFunctionKeySettingTable[Index].KeySetting;
-      //
-      // Function key prompt can not be displayed if the function key has been disabled.
-      //
-      if ((gFunctionKeySetting & FUNCTION_ONE) != FUNCTION_ONE) {
-        gFunctionOneString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
-      }
-
-      if ((gFunctionKeySetting & FUNCTION_TWO) != FUNCTION_TWO) {
-        gFunctionTwoString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
-      }
-
-      if ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE) {
-        gFunctionNineString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
-      }
-
-      if ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN) {
-        gFunctionTenString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
-      }
-    }
-  }
-
-  return Status;
-}
+/** @file\r
+Entry and initialization module for the browser.\r
+\r
+Copyright (c) 2007 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "Setup.h"\r
+#include "Ui.h"\r
+\r
+\r
+SETUP_DRIVER_PRIVATE_DATA  mPrivateData = {\r
+  SETUP_DRIVER_SIGNATURE,\r
+  NULL,\r
+  {\r
+    SendForm,\r
+    BrowserCallback\r
+  },\r
+  {\r
+    UnicodeVSPrint\r
+  }\r
+};\r
+\r
+EFI_HII_DATABASE_PROTOCOL         *mHiiDatabase;\r
+EFI_HII_STRING_PROTOCOL           *mHiiString;\r
+EFI_HII_CONFIG_ROUTING_PROTOCOL   *mHiiConfigRouting;\r
+\r
+BANNER_DATA           *BannerData;\r
+EFI_HII_HANDLE        FrontPageHandle;\r
+UINTN                 gClassOfVfr;\r
+UINTN                 gFunctionKeySetting;\r
+BOOLEAN               gResetRequired;\r
+BOOLEAN               gNvUpdateRequired;\r
+EFI_HII_HANDLE        gHiiHandle;\r
+BOOLEAN               gFirstIn;\r
+UINT16                gDirection;\r
+EFI_SCREEN_DESCRIPTOR gScreenDimensions;\r
+BOOLEAN               gUpArrow;\r
+BOOLEAN               gDownArrow;\r
+\r
+//\r
+// Browser Global Strings\r
+//\r
+CHAR16            *gFunctionOneString;\r
+CHAR16            *gFunctionTwoString;\r
+CHAR16            *gFunctionNineString;\r
+CHAR16            *gFunctionTenString;\r
+CHAR16            *gEnterString;\r
+CHAR16            *gEnterCommitString;\r
+CHAR16            *gEscapeString;\r
+CHAR16            *gSaveFailed;\r
+CHAR16            *gMoveHighlight;\r
+CHAR16            *gMakeSelection;\r
+CHAR16            *gDecNumericInput;\r
+CHAR16            *gHexNumericInput;\r
+CHAR16            *gToggleCheckBox;\r
+CHAR16            *gPromptForData;\r
+CHAR16            *gPromptForPassword;\r
+CHAR16            *gPromptForNewPassword;\r
+CHAR16            *gConfirmPassword;\r
+CHAR16            *gConfirmError;\r
+CHAR16            *gPassowordInvalid;\r
+CHAR16            *gPressEnter;\r
+CHAR16            *gEmptyString;\r
+CHAR16            *gAreYouSure;\r
+CHAR16            *gYesResponse;\r
+CHAR16            *gNoResponse;\r
+CHAR16            *gMiniString;\r
+CHAR16            *gPlusString;\r
+CHAR16            *gMinusString;\r
+CHAR16            *gAdjustNumber;\r
+\r
+CHAR16            gPromptBlockWidth;\r
+CHAR16            gOptionBlockWidth;\r
+CHAR16            gHelpBlockWidth;\r
+\r
+EFI_GUID  gZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};\r
+EFI_GUID  gSetupBrowserGuid = {\r
+  0xab368524, 0xb60c, 0x495b, {0xa0, 0x9, 0x12, 0xe8, 0x5b, 0x1a, 0xea, 0x32}\r
+};\r
+\r
+FUNCTIION_KEY_SETTING gFunctionKeySettingTable[] = {\r
+  //\r
+  // Boot Manager\r
+  //\r
+  {\r
+    {\r
+      0x847bc3fe,\r
+      0xb974,\r
+      0x446d,\r
+      {\r
+        0x94,\r
+        0x49,\r
+        0x5a,\r
+        0xd5,\r
+        0x41,\r
+        0x2e,\r
+        0x99,\r
+        0x3b\r
+      }\r
+    },\r
+    NONE_FUNCTION_KEY_SETTING\r
+  },\r
+  //\r
+  // Device Manager\r
+  //\r
+  {\r
+    {\r
+      0x3ebfa8e6,\r
+      0x511d,\r
+      0x4b5b,\r
+      {\r
+        0xa9,\r
+        0x5f,\r
+        0xfb,\r
+        0x38,\r
+        0x26,\r
+        0xf,\r
+        0x1c,\r
+        0x27\r
+      }\r
+    },\r
+    NONE_FUNCTION_KEY_SETTING\r
+  },\r
+  //\r
+  // BMM FormSet.\r
+  //\r
+  {\r
+    {\r
+      0x642237c7,\r
+      0x35d4,\r
+      0x472d,\r
+      {\r
+        0x83,\r
+        0x65,\r
+        0x12,\r
+        0xe0,\r
+        0xcc,\r
+        0xf2,\r
+        0x7a,\r
+        0x22\r
+      }\r
+    },\r
+    NONE_FUNCTION_KEY_SETTING\r
+  },\r
+  //\r
+  // BMM File Explorer FormSet.\r
+  //\r
+  {\r
+    {\r
+      0x1f2d63e1,\r
+      0xfebd,\r
+      0x4dc7,\r
+      {\r
+        0x9c,\r
+        0xc5,\r
+        0xba,\r
+        0x2b,\r
+        0x1c,\r
+        0xef,\r
+        0x9c,\r
+        0x5b\r
+      }\r
+    },\r
+    NONE_FUNCTION_KEY_SETTING\r
+  },\r
+};\r
+\r
+/**\r
+  This is the routine which an external caller uses to direct the browser\r
+  where to obtain it's information.\r
+\r
+\r
+  @param This            The Form Browser protocol instanse.\r
+  @param Handles         A pointer to an array of Handles.  If HandleCount > 1 we\r
+                         display a list of the formsets for the handles specified.\r
+  @param HandleCount     The number of Handles specified in Handle.\r
+  @param FormSetGuid     This field points to the EFI_GUID which must match the Guid\r
+                         field in the EFI_IFR_FORM_SET op-code for the specified\r
+                         forms-based package. If FormSetGuid is NULL, then this\r
+                         function will display the first found forms package.\r
+  @param FormId          This field specifies which EFI_IFR_FORM to render as the first\r
+                         displayable page. If this field has a value of 0x0000, then\r
+                         the forms browser will render the specified forms in their encoded order.\r
+                         ScreenDimenions - This allows the browser to be called so that it occupies a\r
+                         portion of the physical screen instead of dynamically determining the screen dimensions.\r
+                         ActionRequest   - Points to the action recommended by the form.\r
+  @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in \r
+                          characters.\r
+  @param ActionRequest       Points to the action recommended by the form.\r
+\r
+  @retval  EFI_SUCCESS            The function completed successfully.\r
+  @retval  EFI_INVALID_PARAMETER  One of the parameters has an invalid value.\r
+  @retval  EFI_NOT_FOUND          No valid forms could be found to display.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SendForm (\r
+  IN  CONST EFI_FORM_BROWSER2_PROTOCOL *This,\r
+  IN  EFI_HII_HANDLE                   *Handles,\r
+  IN  UINTN                            HandleCount,\r
+  IN  EFI_GUID                         *FormSetGuid, OPTIONAL\r
+  IN  UINT16                           FormId, OPTIONAL\r
+  IN  CONST EFI_SCREEN_DESCRIPTOR      *ScreenDimensions, OPTIONAL\r
+  OUT EFI_BROWSER_ACTION_REQUEST       *ActionRequest  OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS            Status;\r
+  UI_MENU_SELECTION     *Selection;\r
+  UINTN                 Index;\r
+  FORM_BROWSER_FORMSET  *FormSet;\r
+\r
+  Status = EFI_SUCCESS;\r
+  ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
+\r
+  //\r
+  // Seed the dimensions in the global\r
+  //\r
+  gST->ConOut->QueryMode (\r
+                 gST->ConOut,\r
+                 gST->ConOut->Mode->Mode,\r
+                 &gScreenDimensions.RightColumn,\r
+                 &gScreenDimensions.BottomRow\r
+                 );\r
+\r
+  if (ScreenDimensions != NULL) {\r
+    //\r
+    // Check local dimension vs. global dimension.\r
+    //\r
+    if ((gScreenDimensions.RightColumn < ScreenDimensions->RightColumn) ||\r
+        (gScreenDimensions.BottomRow < ScreenDimensions->BottomRow)\r
+        ) {\r
+      return EFI_INVALID_PARAMETER;\r
+    } else {\r
+      //\r
+      // Local dimension validation.\r
+      //\r
+      if ((ScreenDimensions->RightColumn > ScreenDimensions->LeftColumn) &&\r
+          (ScreenDimensions->BottomRow > ScreenDimensions->TopRow) &&\r
+          ((ScreenDimensions->RightColumn - ScreenDimensions->LeftColumn) > 2) &&\r
+          (\r
+            (ScreenDimensions->BottomRow - ScreenDimensions->TopRow) > STATUS_BAR_HEIGHT +\r
+            SCROLL_ARROW_HEIGHT *\r
+            2 +\r
+            FRONT_PAGE_HEADER_HEIGHT +\r
+            FOOTER_HEIGHT +\r
+            1\r
+          )\r
+        ) {\r
+        CopyMem (&gScreenDimensions, (VOID *) ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
+      } else {\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+    }\r
+  }\r
+\r
+  gOptionBlockWidth = (CHAR16) ((gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3);\r
+  gHelpBlockWidth   = gOptionBlockWidth;\r
+  gPromptBlockWidth = gOptionBlockWidth;\r
+\r
+  //\r
+  // Initialize the strings for the browser, upon exit of the browser, the strings will be freed\r
+  //\r
+  InitializeBrowserStrings ();\r
+\r
+  gFunctionKeySetting = DEFAULT_FUNCTION_KEY_SETTING;\r
+  gClassOfVfr         = EFI_SETUP_APPLICATION_SUBCLASS;\r
+\r
+  //\r
+  // Ensure we are in Text mode\r
+  //\r
+  if (gFirstIn) {\r
+    gFirstIn = FALSE;\r
+    gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
+    DisableQuietBoot ();\r
+  }\r
+\r
+  for (Index = 0; Index < HandleCount; Index++) {\r
+    Selection = AllocateZeroPool (sizeof (UI_MENU_SELECTION));\r
+    ASSERT (Selection != NULL);\r
+\r
+    Selection->Handle = Handles[Index];\r
+    if (FormSetGuid != NULL) {\r
+      CopyMem (&Selection->FormSetGuid, FormSetGuid, sizeof (EFI_GUID));\r
+      Selection->FormId = FormId;\r
+    }\r
+\r
+    do {\r
+      FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));\r
+      ASSERT (FormSet != NULL);\r
+\r
+      //\r
+      // Initialize internal data structures of FormSet\r
+      //\r
+      Status = InitializeFormSet (Selection->Handle, &Selection->FormSetGuid, FormSet);\r
+      if (EFI_ERROR (Status)) {\r
+        DestroyFormSet (FormSet);\r
+        break;\r
+      }\r
+      Selection->FormSet = FormSet;\r
+\r
+      //\r
+      // Initialize current settings of Questions in this FormSet\r
+      //\r
+      Status = InitializeCurrentSetting (FormSet);\r
+      if (EFI_ERROR (Status)) {\r
+        DestroyFormSet (FormSet);\r
+        break;\r
+      }\r
+\r
+      //\r
+      // Display this formset\r
+      //\r
+      gCurrentSelection = Selection;\r
+\r
+      Status = SetupBrowser (Selection);\r
+\r
+      gCurrentSelection = NULL;\r
+      DestroyFormSet (FormSet);\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        break;\r
+      }\r
+\r
+    } while (Selection->Action == UI_ACTION_REFRESH_FORMSET);\r
+\r
+    gBS->FreePool (Selection);\r
+  }\r
+\r
+  if (ActionRequest != NULL) {\r
+    *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+    if (gResetRequired) {\r
+      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_RESET;\r
+    }\r
+  }\r
+\r
+  FreeBrowserStrings ();\r
+\r
+  gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
+  gST->ConOut->ClearScreen (gST->ConOut);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  This function is called by a callback handler to retrieve uncommitted state\r
+  data from the browser.\r
+\r
+  @param  This                   A pointer to the EFI_FORM_BROWSER2_PROTOCOL\r
+                                 instance.\r
+  @param  ResultsDataSize        A pointer to the size of the buffer associated\r
+                                 with ResultsData.\r
+  @param  ResultsData            A string returned from an IFR browser or\r
+                                 equivalent. The results string will have no\r
+                                 routing information in them.\r
+  @param  RetrieveData           A BOOLEAN field which allows an agent to retrieve\r
+                                 (if RetrieveData = TRUE) data from the uncommitted\r
+                                 browser state information or set (if RetrieveData\r
+                                 = FALSE) data in the uncommitted browser state\r
+                                 information.\r
+  @param  VariableGuid           An optional field to indicate the target variable\r
+                                 GUID name to use.\r
+  @param  VariableName           An optional field to indicate the target\r
+                                 human-readable variable name.\r
+\r
+  @retval EFI_SUCCESS            The results have been distributed or are awaiting\r
+                                 distribution.\r
+  @retval EFI_BUFFER_TOO_SMALL   The ResultsDataSize specified was too small to\r
+                                 contain the results data.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BrowserCallback (\r
+  IN CONST EFI_FORM_BROWSER2_PROTOCOL  *This,\r
+  IN OUT UINTN                         *ResultsDataSize,\r
+  IN OUT EFI_STRING                    ResultsData,\r
+  IN BOOLEAN                           RetrieveData,\r
+  IN CONST EFI_GUID                    *VariableGuid, OPTIONAL\r
+  IN CONST CHAR16                      *VariableName  OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS            Status;\r
+  LIST_ENTRY            *Link;\r
+  FORMSET_STORAGE       *Storage;\r
+  FORM_BROWSER_FORMSET  *FormSet;\r
+  BOOLEAN               Found;\r
+  CHAR16                *ConfigResp;\r
+  CHAR16                *StrPtr;\r
+  UINTN                 BufferSize;\r
+  UINTN                 TmpSize;\r
+\r
+  if (ResultsDataSize == NULL || ResultsData == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (gCurrentSelection == NULL) {\r
+    return EFI_NOT_READY;\r
+  }\r
+\r
+  Storage = NULL;\r
+  ConfigResp = NULL;\r
+  FormSet = gCurrentSelection->FormSet;\r
+\r
+  //\r
+  // Find target storage\r
+  //\r
+  Link = GetFirstNode (&FormSet->StorageListHead);\r
+  if (IsNull (&FormSet->StorageListHead, Link)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (VariableGuid != NULL) {\r
+    //\r
+    // Try to find target storage\r
+    //\r
+    Found = FALSE;\r
+    while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+      Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
+      Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+\r
+      if (CompareGuid (&Storage->Guid, (EFI_GUID *) VariableGuid)) {\r
+        if (Storage->Type == EFI_HII_VARSTORE_BUFFER) {\r
+          //\r
+          // Buffer storage require both GUID and Name\r
+          //\r
+          if (VariableName == NULL) {\r
+            return EFI_NOT_FOUND;\r
+          }\r
+\r
+          if (StrCmp (Storage->Name, (CHAR16 *) VariableName) != 0) {\r
+            continue;\r
+          }\r
+        }\r
+        Found = TRUE;\r
+        break;\r
+      }\r
+    }\r
+\r
+    if (!Found) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+  } else {\r
+    //\r
+    // GUID/Name is not specified, take the first storage in FormSet\r
+    //\r
+    Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
+  }\r
+\r
+  if (RetrieveData) {\r
+    //\r
+    // Skip if there is no RequestElement\r
+    //\r
+    if (Storage->ElementCount == 0) {\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    //\r
+    // Generate <ConfigResp>\r
+    //\r
+    Status = StorageToConfigResp (Storage, &ConfigResp);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Skip <ConfigHdr> and '&' to point to <ConfigBody>\r
+    //\r
+    StrPtr = ConfigResp + StrLen (Storage->ConfigHdr) + 1;\r
+\r
+    BufferSize = StrSize (StrPtr);\r
+    if (*ResultsDataSize < BufferSize) {\r
+      *ResultsDataSize = BufferSize;\r
+\r
+      gBS->FreePool (ConfigResp);\r
+      return EFI_BUFFER_TOO_SMALL;\r
+    }\r
+\r
+    *ResultsDataSize = BufferSize;\r
+    CopyMem (ResultsData, StrPtr, BufferSize);\r
+\r
+    gBS->FreePool (ConfigResp);\r
+  } else {\r
+    //\r
+    // Prepare <ConfigResp>\r
+    //\r
+    TmpSize = StrLen (ResultsData);\r
+    BufferSize = (TmpSize + StrLen (Storage->ConfigHdr) + 2) * sizeof (CHAR16);\r
+    ConfigResp = AllocateZeroPool (BufferSize);\r
+    ASSERT (ConfigResp != NULL);\r
+\r
+    StrCpy (ConfigResp, Storage->ConfigHdr);\r
+    StrCat (ConfigResp, L"&");\r
+    StrCat (ConfigResp, ResultsData);\r
+\r
+    //\r
+    // Update Browser uncommited data\r
+    //\r
+    Status = ConfigRespToStorage (Storage, ConfigResp);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Initialize Setup Browser driver.\r
+\r
+  @param ImageHandle     The image handle.\r
+  @param SystemTable     The system table.\r
+\r
+  @retval EFI_SUCCESS    The Setup Browser module is initialized correctly..\r
+  @return Other value if failed to initialize the Setup Browser module.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeSetup (\r
+  IN EFI_HANDLE           ImageHandle,\r
+  IN EFI_SYSTEM_TABLE     *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  EFI_HANDLE                  HiiDriverHandle;\r
+  EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
+\r
+  //\r
+  // Locate required Hii relative protocols\r
+  //\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiHiiDatabaseProtocolGuid,\r
+                  NULL,\r
+                  (VOID **) &mHiiDatabase\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiHiiStringProtocolGuid,\r
+                  NULL,\r
+                  (VOID **) &mHiiString\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiHiiConfigRoutingProtocolGuid,\r
+                  NULL,\r
+                  (VOID **) &mHiiConfigRouting\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Publish our HII data\r
+  //\r
+  Status = HiiLibCreateHiiDriverHandle (&HiiDriverHandle);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  PackageList = HiiLibPreparePackageList (1, &gSetupBrowserGuid, SetupBrowserStrings);\r
+  ASSERT (PackageList != NULL);\r
+  Status = mHiiDatabase->NewPackageList (\r
+                           mHiiDatabase,\r
+                           PackageList,\r
+                           HiiDriverHandle,\r
+                           &gHiiHandle\r
+                           );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Initialize Driver private data\r
+  //\r
+  gFirstIn = TRUE;\r
+  BannerData = AllocateZeroPool (sizeof (BANNER_DATA));\r
+  ASSERT (BannerData != NULL);\r
+\r
+  //\r
+  // Install FormBrowser2 protocol\r
+  //\r
+  mPrivateData.Handle = NULL;\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &mPrivateData.Handle,\r
+                  &gEfiFormBrowser2ProtocolGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  &mPrivateData.FormBrowser2\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Install Print protocol\r
+  //\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &mPrivateData.Handle,\r
+                  &gEfiPrintProtocolGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  &mPrivateData.Print\r
+                  );\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Create a new string in HII Package List.\r
+\r
+  @param  String                 The String to be added\r
+  @param  HiiHandle              The package list in the HII database to insert the\r
+                                 specified string.\r
+\r
+  @return The output string.\r
+\r
+**/\r
+EFI_STRING_ID\r
+NewString (\r
+  IN  CHAR16                   *String,\r
+  IN  EFI_HII_HANDLE           HiiHandle\r
+  )\r
+{\r
+  EFI_STRING_ID  StringId;\r
+  EFI_STATUS     Status;\r
+\r
+  StringId = 0;\r
+  Status = HiiLibNewString (HiiHandle, &StringId, String);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  return StringId;\r
+}\r
+\r
+\r
+/**\r
+  Delete a string from HII Package List.\r
+\r
+  @param  StringId               Id of the string in HII database.\r
+  @param  HiiHandle              The HII package list handle.\r
+\r
+  @retval EFI_SUCCESS            The string was deleted successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+DeleteString (\r
+  IN  EFI_STRING_ID            StringId,\r
+  IN  EFI_HII_HANDLE           HiiHandle\r
+  )\r
+{\r
+  CHAR16  NullChar;\r
+\r
+  NullChar = CHAR_NULL;\r
+  return HiiLibSetString (HiiHandle, StringId, &NullChar);\r
+}\r
+\r
+\r
+/**\r
+  Get the string based on the StringId and HII Package List Handle.\r
+\r
+  @param  Token                  The String's ID.\r
+  @param  HiiHandle              The package list in the HII database to search for\r
+                                 the specified string.\r
+\r
+  @return The output string.\r
+\r
+**/\r
+CHAR16 *\r
+GetToken (\r
+  IN  EFI_STRING_ID                Token,\r
+  IN  EFI_HII_HANDLE               HiiHandle\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  CHAR16      *String;\r
+  UINTN       BufferLength;\r
+\r
+  //\r
+  // Set default string size assumption at no more than 256 bytes\r
+  //\r
+  BufferLength = 0x100;\r
+  String = AllocateZeroPool (BufferLength);\r
+  ASSERT (String != NULL);\r
+\r
+  Status = HiiLibGetString (HiiHandle, Token, String, &BufferLength);\r
+\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    gBS->FreePool (String);\r
+    String = AllocateZeroPool (BufferLength);\r
+    ASSERT (String != NULL);\r
+\r
+    Status = HiiLibGetString (HiiHandle, Token, String, &BufferLength);\r
+  }\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  return String;\r
+}\r
+\r
+\r
+/**\r
+  Allocate new memory and then copy the Unicode string Source to Destination.\r
+\r
+  @param  Dest                   Location to copy string\r
+  @param  Src                    String to copy\r
+\r
+**/\r
+VOID\r
+NewStringCpy (\r
+  IN OUT CHAR16       **Dest,\r
+  IN CHAR16           *Src\r
+  )\r
+{\r
+  SafeFreePool (*Dest);\r
+  *Dest = AllocateCopyPool (StrSize (Src), Src);\r
+  ASSERT (*Dest != NULL);\r
+}\r
+\r
+\r
+/**\r
+  Allocate new memory and concatinate Source on the end of Destination.\r
+\r
+  @param  Dest                   String to added to the end of.\r
+  @param  Src                    String to concatinate.\r
+\r
+**/\r
+VOID\r
+NewStringCat (\r
+  IN OUT CHAR16       **Dest,\r
+  IN CHAR16           *Src\r
+  )\r
+{\r
+  CHAR16  *NewString;\r
+  UINTN   TmpSize;\r
+\r
+  if (*Dest == NULL) {\r
+    NewStringCpy (Dest, Src);\r
+    return;\r
+  }\r
+\r
+  TmpSize = StrSize (*Dest);\r
+  NewString = AllocateZeroPool (TmpSize + StrSize (Src) - 1);\r
+  ASSERT (NewString != NULL);\r
+\r
+  StrCpy (NewString, *Dest);\r
+  StrCat (NewString, Src);\r
+\r
+  gBS->FreePool (*Dest);\r
+  *Dest = NewString;\r
+}\r
+\r
+\r
+/**\r
+  Synchronize Storage's Edit copy to Shadow copy.\r
+\r
+  @param  Storage                The Storage to be synchronized.\r
+\r
+**/\r
+VOID\r
+SynchronizeStorage (\r
+  IN FORMSET_STORAGE         *Storage\r
+  )\r
+{\r
+  LIST_ENTRY              *Link;\r
+  NAME_VALUE_NODE         *Node;\r
+\r
+  switch (Storage->Type) {\r
+  case EFI_HII_VARSTORE_BUFFER:\r
+    CopyMem (Storage->Buffer, Storage->EditBuffer, Storage->Size);\r
+    break;\r
+\r
+  case EFI_HII_VARSTORE_NAME_VALUE:\r
+    Link = GetFirstNode (&Storage->NameValueListHead);\r
+    while (!IsNull (&Storage->NameValueListHead, Link)) {\r
+      Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
+\r
+      NewStringCpy (&Node->Value, Node->EditValue);\r
+\r
+      Link = GetNextNode (&Storage->NameValueListHead, Link);\r
+    }\r
+    break;\r
+\r
+  case EFI_HII_VARSTORE_EFI_VARIABLE:\r
+  default:\r
+    break;\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Get Value for given Name from a NameValue Storage.\r
+\r
+  @param  Storage                The NameValue Storage.\r
+  @param  Name                   The Name.\r
+  @param  Value                  The retured Value.\r
+\r
+  @retval EFI_SUCCESS            Value found for given Name.\r
+  @retval EFI_NOT_FOUND          No such Name found in NameValue storage.\r
+\r
+**/\r
+EFI_STATUS\r
+GetValueByName (\r
+  IN FORMSET_STORAGE         *Storage,\r
+  IN CHAR16                  *Name,\r
+  IN OUT CHAR16              **Value\r
+  )\r
+{\r
+  LIST_ENTRY              *Link;\r
+  NAME_VALUE_NODE         *Node;\r
+\r
+  *Value = NULL;\r
+\r
+  Link = GetFirstNode (&Storage->NameValueListHead);\r
+  while (!IsNull (&Storage->NameValueListHead, Link)) {\r
+    Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
+\r
+    if (StrCmp (Name, Node->Name) == 0) {\r
+      NewStringCpy (Value, Node->EditValue);\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    Link = GetNextNode (&Storage->NameValueListHead, Link);\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+/**\r
+  Set Value of given Name in a NameValue Storage.\r
+\r
+  @param  Storage                The NameValue Storage.\r
+  @param  Name                   The Name.\r
+  @param  Value                  The Value to set.\r
+\r
+  @retval EFI_SUCCESS            Value found for given Name.\r
+  @retval EFI_NOT_FOUND          No such Name found in NameValue storage.\r
+\r
+**/\r
+EFI_STATUS\r
+SetValueByName (\r
+  IN FORMSET_STORAGE         *Storage,\r
+  IN CHAR16                  *Name,\r
+  IN CHAR16                  *Value\r
+  )\r
+{\r
+  LIST_ENTRY              *Link;\r
+  NAME_VALUE_NODE         *Node;\r
+\r
+  Link = GetFirstNode (&Storage->NameValueListHead);\r
+  while (!IsNull (&Storage->NameValueListHead, Link)) {\r
+    Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
+\r
+    if (StrCmp (Name, Node->Name) == 0) {\r
+      SafeFreePool (Node->EditValue);\r
+      Node->EditValue = AllocateCopyPool (StrSize (Value), Value);\r
+      ASSERT (Node->EditValue != NULL);\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    Link = GetNextNode (&Storage->NameValueListHead, Link);\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+/**\r
+  Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.\r
+\r
+  @param  Storage                The Storage to be conveted.\r
+  @param  ConfigResp             The returned <ConfigResp>.\r
+\r
+  @retval EFI_SUCCESS            Convert success.\r
+  @retval EFI_INVALID_PARAMETER  Incorrect storage type.\r
+\r
+**/\r
+EFI_STATUS\r
+StorageToConfigResp (\r
+  IN FORMSET_STORAGE         *Storage,\r
+  IN CHAR16                  **ConfigResp\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  EFI_STRING  Progress;\r
+  LIST_ENTRY              *Link;\r
+  NAME_VALUE_NODE         *Node;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  switch (Storage->Type) {\r
+  case EFI_HII_VARSTORE_BUFFER:\r
+    Status = mHiiConfigRouting->BlockToConfig (\r
+                                  mHiiConfigRouting,\r
+                                  Storage->ConfigRequest,\r
+                                  Storage->EditBuffer,\r
+                                  Storage->Size,\r
+                                  ConfigResp,\r
+                                  &Progress\r
+                                  );\r
+    break;\r
+\r
+  case EFI_HII_VARSTORE_NAME_VALUE:\r
+    *ConfigResp = NULL;\r
+    NewStringCat (ConfigResp, Storage->ConfigHdr);\r
+\r
+    Link = GetFirstNode (&Storage->NameValueListHead);\r
+    while (!IsNull (&Storage->NameValueListHead, Link)) {\r
+      Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
+\r
+      NewStringCat (ConfigResp, L"&");\r
+      NewStringCat (ConfigResp, Node->Name);\r
+      NewStringCat (ConfigResp, L"=");\r
+      NewStringCat (ConfigResp, Node->EditValue);\r
+\r
+      Link = GetNextNode (&Storage->NameValueListHead, Link);\r
+    }\r
+    break;\r
+\r
+  case EFI_HII_VARSTORE_EFI_VARIABLE:\r
+  default:\r
+    Status = EFI_INVALID_PARAMETER;\r
+    break;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.\r
+\r
+  @param  Storage                The Storage to receive the settings.\r
+  @param  ConfigResp             The <ConfigResp> to be converted.\r
+\r
+  @retval EFI_SUCCESS            Convert success.\r
+  @retval EFI_INVALID_PARAMETER  Incorrect storage type.\r
+\r
+**/\r
+EFI_STATUS\r
+ConfigRespToStorage (\r
+  IN FORMSET_STORAGE         *Storage,\r
+  IN CHAR16                  *ConfigResp\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  EFI_STRING  Progress;\r
+  UINTN       BufferSize;\r
+  CHAR16      *StrPtr;\r
+  CHAR16      *Name;\r
+  CHAR16      *Value;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  switch (Storage->Type) {\r
+  case EFI_HII_VARSTORE_BUFFER:\r
+    BufferSize = Storage->Size;\r
+    Status = mHiiConfigRouting->ConfigToBlock (\r
+                                  mHiiConfigRouting,\r
+                                  ConfigResp,\r
+                                  Storage->EditBuffer,\r
+                                  &BufferSize,\r
+                                  &Progress\r
+                                  );\r
+    break;\r
+\r
+  case EFI_HII_VARSTORE_NAME_VALUE:\r
+    StrPtr = StrStr (ConfigResp, L"&");\r
+    while (StrPtr != NULL) {\r
+      //\r
+      // Skip '&'\r
+      //\r
+      StrPtr = StrPtr + 1;\r
+      Name = StrPtr;\r
+      StrPtr = StrStr (StrPtr, L"=");\r
+      if (StrPtr == NULL) {\r
+        break;\r
+      }\r
+      *StrPtr = 0;\r
+\r
+      //\r
+      // Skip '='\r
+      //\r
+      StrPtr = StrPtr + 1;\r
+      Value = StrPtr;\r
+      StrPtr = StrStr (StrPtr, L"&");\r
+      if (StrPtr != NULL) {\r
+        *StrPtr = 0;\r
+      }\r
+      SetValueByName (Storage, Name, Value);\r
+    }\r
+    break;\r
+\r
+  case EFI_HII_VARSTORE_EFI_VARIABLE:\r
+  default:\r
+    Status = EFI_INVALID_PARAMETER;\r
+    break;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Get Question's current Value.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   Form data structure.\r
+  @param  Question               Question to be initialized.\r
+  @param  Cached                 TRUE:  get from Edit copy FALSE: get from original\r
+                                 Storage\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+GetQuestionValue (\r
+  IN FORM_BROWSER_FORMSET             *FormSet,\r
+  IN FORM_BROWSER_FORM                *Form,\r
+  IN OUT FORM_BROWSER_STATEMENT       *Question,\r
+  IN BOOLEAN                          Cached\r
+  )\r
+{\r
+  EFI_STATUS          Status;\r
+  BOOLEAN             Enabled;\r
+  BOOLEAN             Pending;\r
+  UINT8               *Dst;\r
+  UINTN               StorageWidth;\r
+  EFI_TIME            EfiTime;\r
+  FORMSET_STORAGE     *Storage;\r
+  EFI_IFR_TYPE_VALUE  *QuestionValue;\r
+  CHAR16              *ConfigRequest;\r
+  CHAR16              *Progress;\r
+  CHAR16              *Result;\r
+  CHAR16              *Value;\r
+  UINTN               Length;\r
+  BOOLEAN             IsBufferStorage;\r
+  BOOLEAN             IsString;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  // Statement don't have storage, skip them\r
+  //\r
+  if (Question->QuestionId == 0) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Question value is provided by an Expression, evaluate it\r
+  //\r
+  if (Question->ValueExpression != NULL) {\r
+    Status = EvaluateExpression (FormSet, Form, Question->ValueExpression);\r
+    if (!EFI_ERROR (Status)) {\r
+      CopyMem (&Question->HiiValue, &Question->ValueExpression->Result, sizeof (EFI_HII_VALUE));\r
+    }\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Question value is provided by RTC\r
+  //\r
+  Storage = Question->Storage;\r
+  QuestionValue = &Question->HiiValue.Value;\r
+  if (Storage == NULL) {\r
+    //\r
+    // It's a Question without storage, or RTC date/time\r
+    //\r
+    if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {\r
+      //\r
+      // Date and time define the same Flags bit\r
+      //\r
+      switch (Question->Flags & EFI_QF_DATE_STORAGE) {\r
+      case QF_DATE_STORAGE_TIME:\r
+        Status = gRT->GetTime (&EfiTime, NULL);\r
+        break;\r
+\r
+      case QF_DATE_STORAGE_WAKEUP:\r
+        Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
+        break;\r
+\r
+      case QF_DATE_STORAGE_NORMAL:\r
+      default:\r
+        //\r
+        // For date/time without storage\r
+        //\r
+        return EFI_SUCCESS;\r
+      }\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      if (Question->Operand == EFI_IFR_DATE_OP) {\r
+        QuestionValue->date.Year  = EfiTime.Year;\r
+        QuestionValue->date.Month = EfiTime.Month;\r
+        QuestionValue->date.Day   = EfiTime.Day;\r
+      } else {\r
+        QuestionValue->time.Hour   = EfiTime.Hour;\r
+        QuestionValue->time.Minute = EfiTime.Minute;\r
+        QuestionValue->time.Second = EfiTime.Second;\r
+      }\r
+    }\r
+\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Question value is provided by EFI variable\r
+  //\r
+  StorageWidth = Question->StorageWidth;\r
+  if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+    if (Question->BufferValue != NULL) {\r
+      Dst = Question->BufferValue;\r
+    } else {\r
+      Dst = (UINT8 *) QuestionValue;\r
+    }\r
+\r
+    Status = gRT->GetVariable (\r
+                     Question->VariableName,\r
+                     &Storage->Guid,\r
+                     NULL,\r
+                     &StorageWidth,\r
+                     Dst\r
+                     );\r
+    //\r
+    // Always return success, even this EFI variable doesn't exist\r
+    //\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Question Value is provided by Buffer Storage or NameValue Storage\r
+  //\r
+  if (Question->BufferValue != NULL) {\r
+    //\r
+    // This Question is password or orderedlist\r
+    //\r
+    Dst = Question->BufferValue;\r
+  } else {\r
+    //\r
+    // Other type of Questions\r
+    //\r
+    Dst = (UINT8 *) &Question->HiiValue.Value;\r
+  }\r
+\r
+  IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);\r
+  IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ?  TRUE : FALSE);\r
+  if (Cached) {\r
+    if (IsBufferStorage) {\r
+      //\r
+      // Copy from storage Edit buffer\r
+      //\r
+      CopyMem (Dst, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth);\r
+    } else {\r
+      Status = GetValueByName (Storage, Question->VariableName, &Value);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      if (IsString) {\r
+        //\r
+        // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
+        //\r
+        Length = StorageWidth + sizeof (CHAR16);\r
+        Status = ConfigStringToUnicode ((CHAR16 *) Dst, &Length, Value);\r
+      } else {\r
+        Status = HexStringToBuf (Dst, &StorageWidth, Value, NULL);\r
+      }\r
+\r
+      gBS->FreePool (Value);\r
+    }\r
+  } else {\r
+    //\r
+    // Request current settings from Configuration Driver\r
+    //\r
+    if (FormSet->ConfigAccess == NULL) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    //\r
+    // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||\r
+    //                   <ConfigHdr> + "&" + <VariableName>\r
+    //\r
+    if (IsBufferStorage) {\r
+      Length = StrLen (Storage->ConfigHdr);\r
+      Length += StrLen (Question->BlockName);\r
+    } else {\r
+      Length = StrLen (Storage->ConfigHdr);\r
+      Length += StrLen (Question->VariableName) + 1;\r
+    }\r
+    ConfigRequest = AllocateZeroPool ((Length + 1) * sizeof (CHAR16));\r
+    ASSERT (ConfigRequest != NULL);\r
+\r
+    StrCpy (ConfigRequest, Storage->ConfigHdr);\r
+    if (IsBufferStorage) {\r
+      StrCat (ConfigRequest, Question->BlockName);\r
+    } else {\r
+      StrCat (ConfigRequest, L"&");\r
+      StrCat (ConfigRequest, Question->VariableName);\r
+    }\r
+\r
+    Status = FormSet->ConfigAccess->ExtractConfig (\r
+                                      FormSet->ConfigAccess,\r
+                                      ConfigRequest,\r
+                                      &Progress,\r
+                                      &Result\r
+                                      );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Skip <ConfigRequest>\r
+    //\r
+    Value = Result + Length;\r
+    if (IsBufferStorage) {\r
+      //\r
+      // Skip "&VALUE"\r
+      //\r
+      Value = Value + 6;\r
+    }\r
+    if (*Value != '=') {\r
+      gBS->FreePool (Result);\r
+      return EFI_NOT_FOUND;\r
+    }\r
+    //\r
+    // Skip '=', point to value\r
+    //\r
+    Value = Value + 1;\r
+    if (!IsBufferStorage && IsString) {\r
+      //\r
+      // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
+      //\r
+      Length = StorageWidth + sizeof (CHAR16);\r
+      Status = ConfigStringToUnicode ((CHAR16 *) Dst, &Length, Value);\r
+    } else {\r
+      Status = HexStringToBuf (Dst, &StorageWidth, Value, NULL);\r
+      if (EFI_ERROR (Status)) {\r
+        gBS->FreePool (Result);\r
+        return Status;\r
+      }\r
+    }\r
+\r
+    //\r
+    // Synchronize Edit Buffer\r
+    //\r
+    if (IsBufferStorage) {\r
+      CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth);\r
+    } else {\r
+      SetValueByName (Storage, Question->VariableName, Value);\r
+    }\r
+    gBS->FreePool (Result);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Save Question Value to edit copy(cached) or Storage(uncached).\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   Form data structure.\r
+  @param  Question               Pointer to the Question.\r
+  @param  Cached                 TRUE:  set to Edit copy FALSE: set to original\r
+                                 Storage\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+SetQuestionValue (\r
+  IN FORM_BROWSER_FORMSET             *FormSet,\r
+  IN FORM_BROWSER_FORM                *Form,\r
+  IN OUT FORM_BROWSER_STATEMENT       *Question,\r
+  IN BOOLEAN                          Cached\r
+  )\r
+{\r
+  EFI_STATUS          Status;\r
+  BOOLEAN             Enabled;\r
+  BOOLEAN             Pending;\r
+  UINT8               *Src;\r
+  EFI_TIME            EfiTime;\r
+  UINTN               BufferLen;\r
+  UINTN               StorageWidth;\r
+  FORMSET_STORAGE     *Storage;\r
+  EFI_IFR_TYPE_VALUE  *QuestionValue;\r
+  CHAR16              *ConfigResp;\r
+  CHAR16              *Progress;\r
+  CHAR16              *Value;\r
+  UINTN               Length;\r
+  BOOLEAN             IsBufferStorage;\r
+  BOOLEAN             IsString;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  // Statement don't have storage, skip them\r
+  //\r
+  if (Question->QuestionId == 0) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // If Question value is provided by an Expression, then it is read only\r
+  //\r
+  if (Question->ValueExpression != NULL) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Question value is provided by RTC\r
+  //\r
+  Storage = Question->Storage;\r
+  QuestionValue = &Question->HiiValue.Value;\r
+  if (Storage == NULL) {\r
+    //\r
+    // It's a Question without storage, or RTC date/time\r
+    //\r
+    if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {\r
+      //\r
+      // Date and time define the same Flags bit\r
+      //\r
+      switch (Question->Flags & EFI_QF_DATE_STORAGE) {\r
+      case QF_DATE_STORAGE_TIME:\r
+        Status = gRT->GetTime (&EfiTime, NULL);\r
+        break;\r
+\r
+      case QF_DATE_STORAGE_WAKEUP:\r
+        Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
+        break;\r
+\r
+      case QF_DATE_STORAGE_NORMAL:\r
+      default:\r
+        //\r
+        // For date/time without storage\r
+        //\r
+        return EFI_SUCCESS;\r
+      }\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      if (Question->Operand == EFI_IFR_DATE_OP) {\r
+        EfiTime.Year  = QuestionValue->date.Year;\r
+        EfiTime.Month = QuestionValue->date.Month;\r
+        EfiTime.Day   = QuestionValue->date.Day;\r
+      } else {\r
+        EfiTime.Hour   = QuestionValue->time.Hour;\r
+        EfiTime.Minute = QuestionValue->time.Minute;\r
+        EfiTime.Second = QuestionValue->time.Second;\r
+      }\r
+\r
+      if ((Question->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_TIME) {\r
+        Status = gRT->SetTime (&EfiTime);\r
+      } else {\r
+        Status = gRT->SetWakeupTime (TRUE, &EfiTime);\r
+      }\r
+    }\r
+\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Question value is provided by EFI variable\r
+  //\r
+  StorageWidth = Question->StorageWidth;\r
+  if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+    if (Question->BufferValue != NULL) {\r
+      Src = Question->BufferValue;\r
+    } else {\r
+      Src = (UINT8 *) QuestionValue;\r
+    }\r
+\r
+    Status = gRT->SetVariable (\r
+                     Question->VariableName,\r
+                     &Storage->Guid,\r
+                     Storage->Attributes,\r
+                     StorageWidth,\r
+                     Src\r
+                     );\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Question Value is provided by Buffer Storage or NameValue Storage\r
+  //\r
+  if (Question->BufferValue != NULL) {\r
+    Src = Question->BufferValue;\r
+  } else {\r
+    Src = (UINT8 *) &Question->HiiValue.Value;\r
+  }\r
+\r
+  IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);\r
+  IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ?  TRUE : FALSE);\r
+  if (IsBufferStorage) {\r
+    //\r
+    // Copy to storage edit buffer\r
+    //\r
+    CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
+  } else {\r
+    if (IsString) {\r
+      //\r
+      // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
+      //\r
+      Value = NULL;\r
+      BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16);\r
+      Value = AllocateZeroPool (BufferLen);\r
+      ASSERT (Value != NULL);\r
+      Status = UnicodeToConfigString (Value, &BufferLen, (CHAR16 *) Src);\r
+      ASSERT_EFI_ERROR (Status);\r
+    } else {\r
+      BufferLen = StorageWidth * 2 + 1;\r
+      Value = AllocateZeroPool (BufferLen * sizeof (CHAR16));\r
+      ASSERT (Value != NULL);\r
+      BufToHexString (Value, &BufferLen, Src, StorageWidth);\r
+      ToLower (Value);\r
+    }\r
+\r
+    Status = SetValueByName (Storage, Question->VariableName, Value);\r
+    gBS->FreePool (Value);\r
+  }\r
+\r
+  if (!Cached) {\r
+    //\r
+    // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||\r
+    //                <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"\r
+    //\r
+    if (IsBufferStorage) {\r
+      Length = StrLen (Question->BlockName) + 7;\r
+    } else {\r
+      Length = StrLen (Question->VariableName) + 2;\r
+    }\r
+    if (!IsBufferStorage && IsString) {\r
+      Length += (StrLen ((CHAR16 *) Src) * 4);\r
+    } else {\r
+      Length += (StorageWidth * 2);\r
+    }\r
+    ConfigResp = AllocateZeroPool ((StrLen (Storage->ConfigHdr) + Length + 1) * sizeof (CHAR16));\r
+    ASSERT (ConfigResp != NULL);\r
+\r
+    StrCpy (ConfigResp, Storage->ConfigHdr);\r
+    if (IsBufferStorage) {\r
+      StrCat (ConfigResp, Question->BlockName);\r
+      StrCat (ConfigResp, L"&VALUE=");\r
+    } else {\r
+      StrCat (ConfigResp, L"&");\r
+      StrCat (ConfigResp, Question->VariableName);\r
+      StrCat (ConfigResp, L"=");\r
+    }\r
+\r
+    Value = ConfigResp + StrLen (ConfigResp);\r
+    if (!IsBufferStorage && IsString) {\r
+      //\r
+      // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
+      //\r
+      BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16);\r
+      Status = UnicodeToConfigString (Value, &BufferLen, (CHAR16 *) Src);\r
+      ASSERT_EFI_ERROR (Status);\r
+    } else {\r
+      BufferLen = StorageWidth * 2 + 1;\r
+      BufToHexString (Value, &BufferLen, Src, StorageWidth);\r
+      ToLower (Value);\r
+    }\r
+\r
+    //\r
+    // Submit Question Value to Configuration Driver\r
+    //\r
+    if (FormSet->ConfigAccess != NULL) {\r
+      Status = FormSet->ConfigAccess->RouteConfig (\r
+                                        FormSet->ConfigAccess,\r
+                                        ConfigResp,\r
+                                        &Progress\r
+                                        );\r
+      if (EFI_ERROR (Status)) {\r
+        gBS->FreePool (ConfigResp);\r
+        return Status;\r
+      }\r
+    }\r
+    gBS->FreePool (ConfigResp);\r
+\r
+    //\r
+    // Synchronize shadow Buffer\r
+    //\r
+    SynchronizeStorage (Storage);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Perform inconsistent check for a Form.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   Form data structure.\r
+  @param  Question               The Question to be validated.\r
+  @param  Type                   Validation type: InConsistent or NoSubmit\r
+\r
+  @retval EFI_SUCCESS            Form validation pass.\r
+  @retval other                  Form validation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+ValidateQuestion (\r
+  IN  FORM_BROWSER_FORMSET            *FormSet,\r
+  IN  FORM_BROWSER_FORM               *Form,\r
+  IN  FORM_BROWSER_STATEMENT          *Question,\r
+  IN  UINTN                           Type\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  LIST_ENTRY              *Link;\r
+  LIST_ENTRY              *ListHead;\r
+  EFI_STRING              PopUp;\r
+  EFI_INPUT_KEY           Key;\r
+  FORM_EXPRESSION         *Expression;\r
+\r
+  if (Type == EFI_HII_EXPRESSION_INCONSISTENT_IF) {\r
+    ListHead = &Question->InconsistentListHead;\r
+  } else if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {\r
+    ListHead = &Question->NoSubmitListHead;\r
+  } else {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Link = GetFirstNode (ListHead);\r
+  while (!IsNull (ListHead, Link)) {\r
+    Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
+\r
+    //\r
+    // Evaluate the expression\r
+    //\r
+    Status = EvaluateExpression (FormSet, Form, Expression);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    if (Expression->Result.Value.b) {\r
+      //\r
+      // Condition meet, show up error message\r
+      //\r
+      if (Expression->Error != 0) {\r
+        PopUp = GetToken (Expression->Error, FormSet->HiiHandle);\r
+        do {\r
+          CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, PopUp, gPressEnter, gEmptyString);\r
+        } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+        gBS->FreePool (PopUp);\r
+      }\r
+\r
+      return EFI_NOT_READY;\r
+    }\r
+\r
+    Link = GetNextNode (ListHead, Link);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Perform NoSubmit check for a Form.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   Form data structure.\r
+\r
+  @retval EFI_SUCCESS            Form validation pass.\r
+  @retval other                  Form validation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+NoSubmitCheck (\r
+  IN  FORM_BROWSER_FORMSET            *FormSet,\r
+  IN  FORM_BROWSER_FORM               *Form\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  LIST_ENTRY              *Link;\r
+  FORM_BROWSER_STATEMENT  *Question;\r
+\r
+  Link = GetFirstNode (&Form->StatementListHead);\r
+  while (!IsNull (&Form->StatementListHead, Link)) {\r
+    Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+\r
+    Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_NO_SUBMIT_IF);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    Link = GetNextNode (&Form->StatementListHead, Link);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Submit a Form.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   Form data structure.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+SubmitForm (\r
+  IN FORM_BROWSER_FORMSET             *FormSet,\r
+  IN FORM_BROWSER_FORM                *Form\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  LIST_ENTRY              *Link;\r
+  EFI_STRING              ConfigResp;\r
+  EFI_STRING              Progress;\r
+  FORMSET_STORAGE         *Storage;\r
+\r
+  //\r
+  // Validate the Form by NoSubmit check\r
+  //\r
+  Status = NoSubmitCheck (FormSet, Form);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Submit Buffer storage or Name/Value storage\r
+  //\r
+  Link = GetFirstNode (&FormSet->StorageListHead);\r
+  while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+    Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
+    Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+\r
+    if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Skip if there is no RequestElement\r
+    //\r
+    if (Storage->ElementCount == 0) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Prepare <ConfigResp>\r
+    //\r
+    Status = StorageToConfigResp (Storage, &ConfigResp);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Send <ConfigResp> to Configuration Driver\r
+    //\r
+    if (FormSet->ConfigAccess != NULL) {\r
+      Status = FormSet->ConfigAccess->RouteConfig (\r
+                                        FormSet->ConfigAccess,\r
+                                        ConfigResp,\r
+                                        &Progress\r
+                                        );\r
+      if (EFI_ERROR (Status)) {\r
+        gBS->FreePool (ConfigResp);\r
+        return Status;\r
+      }\r
+    }\r
+    gBS->FreePool (ConfigResp);\r
+\r
+    //\r
+    // Config success, update storage shadow Buffer\r
+    //\r
+    SynchronizeStorage (Storage);\r
+  }\r
+\r
+  gNvUpdateRequired = FALSE;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Reset Question to its default value.\r
+\r
+  @param  FormSet                The form set.\r
+  @param  Form                   The form.\r
+  @param  Question               The question.\r
+  @param  DefaultId              The Class of the default.\r
+\r
+  @retval EFI_SUCCESS            Question is reset to default value.\r
+\r
+**/\r
+EFI_STATUS\r
+GetQuestionDefault (\r
+  IN FORM_BROWSER_FORMSET             *FormSet,\r
+  IN FORM_BROWSER_FORM                *Form,\r
+  IN FORM_BROWSER_STATEMENT           *Question,\r
+  IN UINT16                           DefaultId\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  LIST_ENTRY              *Link;\r
+  QUESTION_DEFAULT        *Default;\r
+  QUESTION_OPTION         *Option;\r
+  EFI_HII_VALUE           *HiiValue;\r
+  UINT8                   Index;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  // Statement don't have storage, skip them\r
+  //\r
+  if (Question->QuestionId == 0) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // There are three ways to specify default value for a Question:\r
+  //  1, use nested EFI_IFR_DEFAULT (highest priority)\r
+  //  2, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)\r
+  //  3, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)\r
+  //\r
+  HiiValue = &Question->HiiValue;\r
+\r
+  //\r
+  // EFI_IFR_DEFAULT has highest priority\r
+  //\r
+  if (!IsListEmpty (&Question->DefaultListHead)) {\r
+    Link = GetFirstNode (&Question->DefaultListHead);\r
+    while (!IsNull (&Question->DefaultListHead, Link)) {\r
+      Default = QUESTION_DEFAULT_FROM_LINK (Link);\r
+\r
+      if (Default->DefaultId == DefaultId) {\r
+        if (Default->ValueExpression != NULL) {\r
+          //\r
+          // Default is provided by an Expression, evaluate it\r
+          //\r
+          Status = EvaluateExpression (FormSet, Form, Default->ValueExpression);\r
+          if (EFI_ERROR (Status)) {\r
+            return Status;\r
+          }\r
+\r
+          CopyMem (HiiValue, &Default->ValueExpression->Result, sizeof (EFI_HII_VALUE));\r
+        } else {\r
+          //\r
+          // Default value is embedded in EFI_IFR_DEFAULT\r
+          //\r
+          CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));\r
+        }\r
+\r
+        return EFI_SUCCESS;\r
+      }\r
+\r
+      Link = GetNextNode (&Question->DefaultListHead, Link);\r
+    }\r
+  }\r
+\r
+  //\r
+  // EFI_ONE_OF_OPTION\r
+  //\r
+  if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {\r
+    if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING)  {\r
+      //\r
+      // OneOfOption could only provide Standard and Manufacturing default\r
+      //\r
+      Link = GetFirstNode (&Question->OptionListHead);\r
+      while (!IsNull (&Question->OptionListHead, Link)) {\r
+        Option = QUESTION_OPTION_FROM_LINK (Link);\r
+\r
+        if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||\r
+            ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))\r
+           ) {\r
+          CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
+\r
+          return EFI_SUCCESS;\r
+        }\r
+\r
+        Link = GetNextNode (&Question->OptionListHead, Link);\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // EFI_IFR_CHECKBOX - lowest priority\r
+  //\r
+  if (Question->Operand == EFI_IFR_CHECKBOX_OP) {\r
+    if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING)  {\r
+      //\r
+      // Checkbox could only provide Standard and Manufacturing default\r
+      //\r
+      if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0)) ||\r
+          ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0))\r
+         ) {\r
+        HiiValue->Value.b = TRUE;\r
+      } else {\r
+        HiiValue->Value.b = FALSE;\r
+      }\r
+\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  //\r
+  // For Questions without default\r
+  //\r
+  switch (Question->Operand) {\r
+  case EFI_IFR_NUMERIC_OP:\r
+    //\r
+    // Take minimal value as numeric's default value\r
+    //\r
+    HiiValue->Value.u64 = Question->Minimum;\r
+    break;\r
+\r
+  case EFI_IFR_ONE_OF_OP:\r
+    //\r
+    // Take first oneof option as oneof's default value\r
+    //\r
+    Link = GetFirstNode (&Question->OptionListHead);\r
+    if (!IsNull (&Question->OptionListHead, Link)) {\r
+      Option = QUESTION_OPTION_FROM_LINK (Link);\r
+      CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
+    }\r
+    break;\r
+\r
+  case EFI_IFR_ORDERED_LIST_OP:\r
+    //\r
+    // Take option sequence in IFR as ordered list's default value\r
+    //\r
+    Index = 0;\r
+    Link = GetFirstNode (&Question->OptionListHead);\r
+    while (!IsNull (&Question->OptionListHead, Link)) {\r
+      Option = QUESTION_OPTION_FROM_LINK (Link);\r
+\r
+      Question->BufferValue[Index] = Option->Value.Value.u8;\r
+\r
+      Index++;\r
+      if (Index >= Question->MaxContainers) {\r
+        break;\r
+      }\r
+\r
+      Link = GetNextNode (&Question->OptionListHead, Link);\r
+    }\r
+    break;\r
+\r
+  default:\r
+    Status = EFI_NOT_FOUND;\r
+    break;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Reset Questions in a Form to their default value.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   The Form which to be reset.\r
+  @param  DefaultId              The Class of the default.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+ExtractFormDefault (\r
+  IN FORM_BROWSER_FORMSET             *FormSet,\r
+  IN FORM_BROWSER_FORM                *Form,\r
+  IN UINT16                           DefaultId\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  LIST_ENTRY              *Link;\r
+  FORM_BROWSER_STATEMENT  *Question;\r
+\r
+  Link = GetFirstNode (&Form->StatementListHead);\r
+  while (!IsNull (&Form->StatementListHead, Link)) {\r
+    Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+    Link = GetNextNode (&Form->StatementListHead, Link);\r
+\r
+    //\r
+    // Reset Question to its default value\r
+    //\r
+    Status = GetQuestionDefault (FormSet, Form, Question, DefaultId);\r
+    if (EFI_ERROR (Status)) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Synchronize Buffer storage's Edit buffer\r
+    //\r
+    if ((Question->Storage != NULL) &&\r
+        (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
+      SetQuestionValue (FormSet, Form, Question, TRUE);\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Initialize Question's Edit copy from Storage.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   Form data structure.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+LoadFormConfig (\r
+  IN FORM_BROWSER_FORMSET             *FormSet,\r
+  IN FORM_BROWSER_FORM                *Form\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  LIST_ENTRY              *Link;\r
+  FORM_BROWSER_STATEMENT  *Question;\r
+\r
+  Link = GetFirstNode (&Form->StatementListHead);\r
+  while (!IsNull (&Form->StatementListHead, Link)) {\r
+    Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+\r
+    //\r
+    // Initialize local copy of Value for each Question\r
+    //\r
+    Status = GetQuestionValue (FormSet, Form, Question, TRUE);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    Link = GetNextNode (&Form->StatementListHead, Link);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Fill storage's edit copy with settings requested from Configuration Driver.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Storage                Buffer Storage.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+LoadStorage (\r
+  IN FORM_BROWSER_FORMSET    *FormSet,\r
+  IN FORMSET_STORAGE         *Storage\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  EFI_STRING  Progress;\r
+  EFI_STRING  Result;\r
+  CHAR16      *StrPtr;\r
+\r
+  if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  if (FormSet->ConfigAccess == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  if (Storage->ElementCount == 0) {\r
+    //\r
+    // Skip if there is no RequestElement\r
+    //\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Request current settings from Configuration Driver\r
+  //\r
+  Status = FormSet->ConfigAccess->ExtractConfig (\r
+                                    FormSet->ConfigAccess,\r
+                                    Storage->ConfigRequest,\r
+                                    &Progress,\r
+                                    &Result\r
+                                    );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Convert Result from <ConfigAltResp> to <ConfigResp>\r
+  //\r
+  StrPtr = StrStr (Result, L"ALTCFG");\r
+  if (StrPtr != NULL) {\r
+    *StrPtr = L'\0';\r
+  }\r
+\r
+  Status = ConfigRespToStorage (Storage, Result);\r
+  gBS->FreePool (Result);\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Get current setting of Questions.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeCurrentSetting (\r
+  IN OUT FORM_BROWSER_FORMSET             *FormSet\r
+  )\r
+{\r
+  LIST_ENTRY              *Link;\r
+  FORMSET_STORAGE         *Storage;\r
+  FORM_BROWSER_FORM       *Form;\r
+  EFI_STATUS              Status;\r
+\r
+  //\r
+  // Extract default from IFR binary\r
+  //\r
+  Link = GetFirstNode (&FormSet->FormListHead);\r
+  while (!IsNull (&FormSet->FormListHead, Link)) {\r
+    Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+\r
+    Status = ExtractFormDefault (FormSet, Form, EFI_HII_DEFAULT_CLASS_STANDARD);\r
+\r
+    Link = GetNextNode (&FormSet->FormListHead, Link);\r
+  }\r
+\r
+  //\r
+  // Request current settings from Configuration Driver\r
+  //\r
+  Link = GetFirstNode (&FormSet->StorageListHead);\r
+  while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+    Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
+\r
+    Status = LoadStorage (FormSet, Storage);\r
+\r
+    //\r
+    // Now Edit Buffer is filled with default values(lower priority) and current\r
+    // settings(higher priority), sychronize it to shadow Buffer\r
+    //\r
+    if (!EFI_ERROR (Status)) {\r
+      SynchronizeStorage (Storage);\r
+    }\r
+\r
+    Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Fetch the Ifr binary data of a FormSet.\r
+\r
+  @param  Handle                 PackageList Handle\r
+  @param  FormSetGuid            GUID of a formset. If not specified (NULL or zero\r
+                                 GUID), take the first FormSet found in package\r
+                                 list.\r
+  @param  BinaryLength           The length of the FormSet IFR binary.\r
+  @param  BinaryData             The buffer designed to receive the FormSet.\r
+\r
+  @retval EFI_SUCCESS            Buffer filled with the requested FormSet.\r
+                                 BufferLength was updated.\r
+  @retval EFI_INVALID_PARAMETER  The handle is unknown.\r
+  @retval EFI_NOT_FOUND          A form or FormSet on the requested handle cannot\r
+                                 be found with the requested FormId.\r
+\r
+**/\r
+EFI_STATUS\r
+GetIfrBinaryData (\r
+  IN  EFI_HII_HANDLE   Handle,\r
+  IN OUT EFI_GUID      *FormSetGuid,\r
+  OUT UINTN            *BinaryLength,\r
+  OUT UINT8            **BinaryData\r
+  )\r
+{\r
+  EFI_STATUS                   Status;\r
+  EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;\r
+  UINTN                        BufferSize;\r
+  UINT8                        *Package;\r
+  UINT8                        *OpCodeData;\r
+  UINT32                       Offset;\r
+  UINT32                       Offset2;\r
+  BOOLEAN                      ReturnDefault;\r
+  UINT32                       PackageListLength;\r
+  EFI_HII_PACKAGE_HEADER       PackageHeader;\r
+\r
+  OpCodeData = NULL;\r
+  Package = NULL;\r
+  ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));;\r
+\r
+  //\r
+  // if FormSetGuid is NULL or zero GUID, return first FormSet in the package list\r
+  //\r
+  if (FormSetGuid == NULL || CompareGuid (FormSetGuid, &gZeroGuid)) {\r
+    ReturnDefault = TRUE;\r
+  } else {\r
+    ReturnDefault = FALSE;\r
+  }\r
+\r
+  //\r
+  // Get HII PackageList\r
+  //\r
+  BufferSize = 0;\r
+  HiiPackageList = NULL;\r
+  Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    HiiPackageList = AllocatePool (BufferSize);\r
+    ASSERT (HiiPackageList != NULL);\r
+\r
+    Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
+  }\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Get Form package from this HII package List\r
+  //\r
+  Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+  Offset2 = 0;\r
+  CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
+\r
+  while (Offset < PackageListLength) {\r
+    Package = ((UINT8 *) HiiPackageList) + Offset;\r
+    CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
+\r
+    if (PackageHeader.Type == EFI_HII_PACKAGE_FORM) {\r
+      //\r
+      // Search FormSet in this Form Package\r
+      //\r
+      Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
+      while (Offset2 < PackageHeader.Length) {\r
+        OpCodeData = Package + Offset2;\r
+\r
+        if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
+          //\r
+          // Check whether return default FormSet\r
+          //\r
+          if (ReturnDefault) {\r
+            break;\r
+          }\r
+\r
+          //\r
+          // FormSet GUID is specified, check it\r
+          //\r
+          if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
+            break;\r
+          }\r
+        }\r
+\r
+        Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
+      }\r
+\r
+      if (Offset2 < PackageHeader.Length) {\r
+        //\r
+        // Target formset found\r
+        //\r
+        break;\r
+      }\r
+    }\r
+\r
+    Offset += PackageHeader.Length;\r
+  }\r
+\r
+  if (Offset >= PackageListLength) {\r
+    //\r
+    // Form package not found in this Package List\r
+    //\r
+    gBS->FreePool (HiiPackageList);\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  if (ReturnDefault && FormSetGuid != NULL) {\r
+    //\r
+    // Return the default FormSet GUID\r
+    //\r
+    CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
+  }\r
+\r
+  //\r
+  // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes\r
+  // in this FormSet; So, here just simply copy the data from start of a FormSet to the end\r
+  // of the Form Package.\r
+  //\r
+  *BinaryLength = PackageHeader.Length - Offset2;\r
+  *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);\r
+\r
+  gBS->FreePool (HiiPackageList);\r
+\r
+  if (*BinaryData == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Initialize the internal data structure of a FormSet.\r
+\r
+  @param  Handle                 PackageList Handle\r
+  @param  FormSetGuid            GUID of a formset. If not specified (NULL or zero\r
+                                 GUID), take the first FormSet found in package\r
+                                 list.\r
+  @param  FormSet                FormSet data structure.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+  @retval EFI_NOT_FOUND          The specified FormSet could not be found.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeFormSet (\r
+  IN  EFI_HII_HANDLE                   Handle,\r
+  IN OUT EFI_GUID                      *FormSetGuid,\r
+  OUT FORM_BROWSER_FORMSET             *FormSet\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_HANDLE                DriverHandle;\r
+  UINT16                    Index;\r
+\r
+  Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  FormSet->HiiHandle = Handle;\r
+  CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));\r
+\r
+  //\r
+  // Retrieve ConfigAccess Protocol associated with this HiiPackageList\r
+  //\r
+  Status = mHiiDatabase->GetPackageListHandle (mHiiDatabase, Handle, &DriverHandle);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  FormSet->DriverHandle = DriverHandle;\r
+  Status = gBS->HandleProtocol (\r
+                  DriverHandle,\r
+                  &gEfiHiiConfigAccessProtocolGuid,\r
+                  (VOID **) &FormSet->ConfigAccess\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // Configuration Driver don't attach ConfigAccess protocol to its HII package\r
+    // list, then there will be no configuration action required\r
+    //\r
+    FormSet->ConfigAccess = NULL;\r
+  }\r
+\r
+  //\r
+  // Parse the IFR binary OpCodes\r
+  //\r
+  Status = ParseOpCodes (FormSet);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  gClassOfVfr = FormSet->SubClass;\r
+  if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {\r
+    FrontPageHandle = FormSet->HiiHandle;\r
+  }\r
+\r
+  //\r
+  // Match GUID to find out the function key setting. If match fail, use the default setting.\r
+  //\r
+  for (Index = 0; Index < sizeof (gFunctionKeySettingTable) / sizeof (FUNCTIION_KEY_SETTING); Index++) {\r
+    if (CompareGuid (&FormSet->Guid, &(gFunctionKeySettingTable[Index].FormSetGuid))) {\r
+      //\r
+      // Update the function key setting.\r
+      //\r
+      gFunctionKeySetting = gFunctionKeySettingTable[Index].KeySetting;\r
+      //\r
+      // Function key prompt can not be displayed if the function key has been disabled.\r
+      //\r
+      if ((gFunctionKeySetting & FUNCTION_ONE) != FUNCTION_ONE) {\r
+        gFunctionOneString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
+      }\r
+\r
+      if ((gFunctionKeySetting & FUNCTION_TWO) != FUNCTION_TWO) {\r
+        gFunctionTwoString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
+      }\r
+\r
+      if ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE) {\r
+        gFunctionNineString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
+      }\r
+\r
+      if ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN) {\r
+        gFunctionTenString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
+      }\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
index 80a9d299a35ea3b2d5593ae99124919b9894009d..2a4eb9e80ebe67f892c20cadf7324363a571431f 100644 (file)
-/** @file
-
-Copyright (c) 2007, Intel Corporation
-All rights reserved. This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-Module Name:
-
-  Setup.h
-
-Abstract:
-
-
-Revision History
-
-
-**/
-
-#ifndef _SETUP_H
-#define _SETUP_H
-
-
-#include <PiDxe.h>
-
-#include <Protocol/Print.h>
-#include <Protocol/SimpleTextOut.h>
-#include <Protocol/SimpleTextIn.h>
-#include <Protocol/FormBrowser2.h>
-#include <Protocol/DevicePath.h>
-#include <Protocol/UnicodeCollation.h>
-#include <Protocol/HiiConfigAccess.h>
-#include <Protocol/HiiConfigRouting.h>
-#include <Protocol/HiiDatabase.h>
-#include <Protocol/HiiString.h>
-
-#include <MdeModuleHii.h>
-
-#include <Library/GraphicsLib.h>
-#include <Library/PrintLib.h>
-#include <Library/DebugLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/UefiRuntimeServicesTableLib.h>
-#include <Library/UefiDriverEntryPoint.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/BaseLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/IfrSupportLib.h>
-#include <Library/ExtendedIfrSupportLib.h>
-#include <Library/HiiLib.h>
-#include <Library/ExtendedHiiLib.h>
-
-#include "Colors.h"
-
-//
-// This is the generated header file which includes whatever needs to be exported (strings + IFR)
-//
-
-extern UINT8  SetupBrowserStrings[];
-
-//
-// Screen definitions
-//
-#define BANNER_HEIGHT                 6
-#define BANNER_COLUMNS                3
-
-#define FRONT_PAGE_HEADER_HEIGHT      6
-#define NONE_FRONT_PAGE_HEADER_HEIGHT 3
-#define LEFT_SKIPPED_COLUMNS          4
-#define FOOTER_HEIGHT                 4
-#define STATUS_BAR_HEIGHT             1
-#define SCROLL_ARROW_HEIGHT           1
-#define POPUP_PAD_SPACE_COUNT         5
-#define POPUP_FRAME_WIDTH             2
-
-//
-// Definition for function key setting
-//
-#define NONE_FUNCTION_KEY_SETTING     0
-#define DEFAULT_FUNCTION_KEY_SETTING  (FUNCTION_ONE | FUNCTION_TWO | FUNCTION_NINE | FUNCTION_TEN)
-
-#define FUNCTION_ONE                  (1 << 0)
-#define FUNCTION_TWO                  (1 << 1)
-#define FUNCTION_NINE                 (1 << 2)
-#define FUNCTION_TEN                  (1 << 3)
-
-typedef struct {
-  EFI_GUID  FormSetGuid;
-  UINTN     KeySetting;
-} FUNCTIION_KEY_SETTING;
-
-//
-// Character definitions
-//
-#define CHAR_SPACE              0x0020
-#define UPPER_LOWER_CASE_OFFSET 0x20
-
-//
-// Time definitions
-//
-#define ONE_SECOND  10000000
-
-//
-// Display definitions
-//
-#define LEFT_HYPER_DELIMITER      L'<'
-#define RIGHT_HYPER_DELIMITER     L'>'
-
-#define LEFT_ONEOF_DELIMITER      L'<'
-#define RIGHT_ONEOF_DELIMITER     L'>'
-
-#define LEFT_NUMERIC_DELIMITER    L'['
-#define RIGHT_NUMERIC_DELIMITER   L']'
-
-#define LEFT_CHECKBOX_DELIMITER   L'['
-#define RIGHT_CHECKBOX_DELIMITER  L']'
-
-#define CHECK_ON                  L'X'
-#define CHECK_OFF                 L' '
-
-#define TIME_SEPARATOR            L':'
-#define DATE_SEPARATOR            L'/'
-
-#define YES_ANSWER                L'Y'
-#define NO_ANSWER                 L'N'
-
-//
-// This is the Input Error Message
-//
-#define INPUT_ERROR 1
-
-//
-// This is the NV RAM update required Message
-//
-#define NV_UPDATE_REQUIRED  2
-
-//
-// Refresh the Status Bar with flags
-//
-#define REFRESH_STATUS_BAR  0xff
-
-//
-// Incremental string lenght of ConfigRequest
-//
-#define CONFIG_REQUEST_STRING_INCREMENTAL  1024
-
-//
-// HII value compare result
-//
-#define HII_VALUE_UNDEFINED     0
-#define HII_VALUE_EQUAL         1
-#define HII_VALUE_LESS_THAN     2
-#define HII_VALUE_GREATER_THAN  3
-
-//
-// Incremental size of stack for expression
-//
-#define EXPRESSION_STACK_SIZE_INCREMENT    0x100
-
-
-#define EFI_SPECIFICATION_ERRATA_VERSION   0
-
-#define EFI_IFR_SPECIFICATION_VERSION  \
-        ((((EFI_SPECIFICATION_VERSION) >> 8) & 0xff00) | \
-         (((EFI_SPECIFICATION_VERSION) & 0xf) << 4) | \
-         ((EFI_SPECIFICATION_ERRATA_VERSION) & 0xf))
-
-#define SETUP_DRIVER_SIGNATURE EFI_SIGNATURE_32 ('F', 'B', 'D', 'V')
-typedef struct {
-  UINT32                             Signature;
-
-  EFI_HANDLE                         Handle;
-
-  //
-  // Produced protocol
-  //
-  EFI_FORM_BROWSER2_PROTOCOL         FormBrowser2;
-  EFI_PRINT_PROTOCOL                 Print;
-
-} SETUP_DRIVER_PRIVATE_DATA;
-
-typedef struct {
-  EFI_STRING_ID  Banner[BANNER_HEIGHT][BANNER_COLUMNS];
-} BANNER_DATA;
-
-//
-// IFR relative definition
-//
-#define EFI_HII_EXPRESSION_INCONSISTENT_IF   0
-#define EFI_HII_EXPRESSION_NO_SUBMIT_IF      1
-#define EFI_HII_EXPRESSION_GRAY_OUT_IF       2
-#define EFI_HII_EXPRESSION_SUPPRESS_IF       3
-#define EFI_HII_EXPRESSION_DISABLE_IF        4
-#define EFI_HII_EXPRESSION_VALUE             5
-#define EFI_HII_EXPRESSION_RULE              6
-
-#define EFI_HII_VARSTORE_BUFFER              0
-#define EFI_HII_VARSTORE_NAME_VALUE          1
-#define EFI_HII_VARSTORE_EFI_VARIABLE        2
-
-#define FORM_INCONSISTENT_VALIDATION         0
-#define FORM_NO_SUBMIT_VALIDATION            1
-
-typedef struct {
-  UINT8               Type;
-  EFI_IFR_TYPE_VALUE  Value;
-} EFI_HII_VALUE;
-
-#define NAME_VALUE_NODE_SIGNATURE  EFI_SIGNATURE_32 ('N', 'V', 'S', 'T')
-
-typedef struct {
-  UINTN            Signature;
-  LIST_ENTRY       Link;
-  CHAR16           *Name;
-  CHAR16           *Value;
-  CHAR16           *EditValue;
-} NAME_VALUE_NODE;
-
-#define NAME_VALUE_NODE_FROM_LINK(a)  CR (a, NAME_VALUE_NODE, Link, NAME_VALUE_NODE_SIGNATURE)
-
-#define FORMSET_STORAGE_SIGNATURE  EFI_SIGNATURE_32 ('F', 'S', 'T', 'G')
-
-typedef struct {
-  UINTN            Signature;
-  LIST_ENTRY       Link;
-
-  UINT8            Type;           // Storage type
-
-  UINT16           VarStoreId;
-  EFI_GUID         Guid;
-
-  CHAR16           *Name;          // For EFI_IFR_VARSTORE
-  UINT16           Size;
-  UINT8            *Buffer;
-  UINT8            *EditBuffer;    // Edit copy for Buffer Storage
-
-  LIST_ENTRY       NameValueListHead; // List of NAME_VALUE_NODE
-
-  UINT32           Attributes;     // For EFI_IFR_VARSTORE_EFI: EFI Variable attribute
-
-  CHAR16           *ConfigHdr;     // <ConfigHdr>
-  CHAR16           *ConfigRequest; // <ConfigRequest> = <ConfigHdr> + <RequestElement>
-  UINTN            ElementCount;   // Number of <RequestElement> in the <ConfigRequest>
-  UINTN            SpareStrLen;    // Spare length of ConfigRequest string buffer
-} FORMSET_STORAGE;
-
-#define FORMSET_STORAGE_FROM_LINK(a)  CR (a, FORMSET_STORAGE, Link, FORMSET_STORAGE_SIGNATURE)
-
-#define EXPRESSION_OPCODE_SIGNATURE  EFI_SIGNATURE_32 ('E', 'X', 'O', 'P')
-
-typedef struct {
-  UINTN             Signature;
-  LIST_ENTRY        Link;
-
-  UINT8             Operand;
-
-  UINT8             Format;      // For EFI_IFR_TO_STRING, EFI_IFR_FIND
-  UINT8             Flags;       // For EFI_IFR_SPAN
-  UINT8             RuleId;      // For EFI_IFR_RULE_REF
-
-  EFI_HII_VALUE     Value;       // For EFI_IFR_EQ_ID_VAL, EFI_IFR_UINT64, EFI_IFR_UINT32, EFI_IFR_UINT16, EFI_IFR_UINT8, EFI_IFR_STRING_REF1
-
-  EFI_QUESTION_ID   QuestionId;  // For EFI_IFR_EQ_ID_ID, EFI_IFR_EQ_ID_LIST, EFI_IFR_QUESTION_REF1
-  EFI_QUESTION_ID   QuestionId2;
-
-  UINT16            ListLength;  // For EFI_IFR_EQ_ID_LIST
-  UINT16            *ValueList;
-
-  EFI_STRING_ID     DevicePath;  // For EFI_IFR_QUESTION_REF3_2, EFI_IFR_QUESTION_REF3_3
-  EFI_GUID          Guid;
-} EXPRESSION_OPCODE;
-
-#define EXPRESSION_OPCODE_FROM_LINK(a)  CR (a, EXPRESSION_OPCODE, Link, EXPRESSION_OPCODE_SIGNATURE)
-
-#define FORM_EXPRESSION_SIGNATURE  EFI_SIGNATURE_32 ('F', 'E', 'X', 'P')
-
-typedef struct {
-  UINTN             Signature;
-  LIST_ENTRY        Link;
-
-  UINT8             Type;            // Type for this expression
-
-  UINT8             RuleId;          // For EFI_IFR_RULE only
-  EFI_STRING_ID     Error;           // For EFI_IFR_NO_SUBMIT_IF, EFI_IFR_INCONSISTENT_IF only
-
-  EFI_HII_VALUE     Result;          // Expression evaluation result
-
-  LIST_ENTRY        OpCodeListHead;  // OpCodes consist of this expression (EXPRESSION_OPCODE)
-} FORM_EXPRESSION;
-
-#define FORM_EXPRESSION_FROM_LINK(a)  CR (a, FORM_EXPRESSION, Link, FORM_EXPRESSION_SIGNATURE)
-
-#define QUESTION_DEFAULT_SIGNATURE  EFI_SIGNATURE_32 ('Q', 'D', 'F', 'T')
-
-typedef struct {
-  UINTN               Signature;
-  LIST_ENTRY          Link;
-
-  UINT16              DefaultId;
-  EFI_HII_VALUE       Value;              // Default value
-
-  FORM_EXPRESSION     *ValueExpression;   // Not-NULL indicates default value is provided by EFI_IFR_VALUE
-} QUESTION_DEFAULT;
-
-#define QUESTION_DEFAULT_FROM_LINK(a)  CR (a, QUESTION_DEFAULT, Link, QUESTION_DEFAULT_SIGNATURE)
-
-#define QUESTION_OPTION_SIGNATURE  EFI_SIGNATURE_32 ('Q', 'O', 'P', 'T')
-
-typedef struct {
-  UINTN               Signature;
-  LIST_ENTRY          Link;
-
-  EFI_STRING_ID       Text;
-  UINT8               Flags;
-  EFI_HII_VALUE       Value;
-  EFI_IMAGE_ID        ImageId;
-
-  FORM_EXPRESSION     *SuppressExpression; // Non-NULL indicates nested inside of SuppressIf
-} QUESTION_OPTION;
-
-#define QUESTION_OPTION_FROM_LINK(a)  CR (a, QUESTION_OPTION, Link, QUESTION_OPTION_SIGNATURE)
-
-#define FORM_BROWSER_STATEMENT_SIGNATURE  EFI_SIGNATURE_32 ('F', 'S', 'T', 'A')
-typedef struct {
-  UINTN                 Signature;
-  LIST_ENTRY            Link;
-
-  UINT8                 Operand;          // The operand (first byte) of this Statement or Question
-
-  //
-  // Statement Header
-  //
-  EFI_STRING_ID         Prompt;
-  EFI_STRING_ID         Help;
-  EFI_STRING_ID         TextTwo;          // For EFI_IFR_TEXT
-
-  //
-  // Question Header
-  //
-  EFI_QUESTION_ID       QuestionId;       // The value of zero is reserved
-  EFI_VARSTORE_ID       VarStoreId;       // A value of zero indicates no variable storage
-  FORMSET_STORAGE       *Storage;
-  union {
-    EFI_STRING_ID       VarName;
-    UINT16              VarOffset;
-  }  VarStoreInfo;
-  UINT16                StorageWidth;
-  UINT8                 QuestionFlags;
-  CHAR16                *VariableName;    // Name/Value or EFI Variable name
-  CHAR16                *BlockName;       // Buffer storage block name: "OFFSET=...WIDTH=..."
-
-  EFI_HII_VALUE         HiiValue;         // Edit copy for checkbox, numberic, oneof
-  UINT8                 *BufferValue;     // Edit copy for string, password, orderedlist
-
-  //
-  // OpCode specific members
-  //
-  UINT8                 Flags;            // for EFI_IFR_CHECKBOX, EFI_IFR_DATE, EFI_IFR_NUMERIC, EFI_IFR_ONE_OF,
-                                          // EFI_IFR_ORDERED_LIST, EFI_IFR_STRING,EFI_IFR_SUBTITLE,EFI_IFR_TIME, EFI_IFR_BANNER
-  UINT8                 MaxContainers;    // for EFI_IFR_ORDERED_LIST
-
-  UINT16                BannerLineNumber; // for EFI_IFR_BANNER, 1-based line number
-  EFI_STRING_ID         QuestionConfig;   // for EFI_IFR_ACTION, if 0 then no configuration string will be processed
-
-  UINT64                Minimum;          // for EFI_IFR_ONE_OF/EFI_IFR_NUMERIC, it's Min/Max value
-  UINT64                Maximum;          // for EFI_IFR_STRING/EFI_IFR_PASSWORD, it's Min/Max length
-  UINT64                Step;
-
-  EFI_DEFAULT_ID        DefaultId;        // for EFI_IFR_RESET_BUTTON
-  EFI_FORM_ID           RefFormId;        // for EFI_IFR_REF
-  EFI_QUESTION_ID       RefQuestionId;    // for EFI_IFR_REF2
-  EFI_GUID              RefFormSetId;     // for EFI_IFR_REF3
-  EFI_STRING_ID         RefDevicePath;    // for EFI_IFR_REF4
-
-  //
-  // Get from IFR parsing
-  //
-  FORM_EXPRESSION       *ValueExpression;    // nested EFI_IFR_VALUE, provide Question value and indicate Question is ReadOnly
-  LIST_ENTRY            DefaultListHead;     // nested EFI_IFR_DEFAULT list (QUESTION_DEFAULT), provide default values
-  LIST_ENTRY            OptionListHead;      // nested EFI_IFR_ONE_OF_OPTION list (QUESTION_OPTION)
-
-  EFI_IMAGE_ID          ImageId;             // nested EFI_IFR_IMAGE
-  UINT8                 RefreshInterval;     // nested EFI_IFR_REFRESH, refresh interval(in seconds) for Question value, 0 means no refresh
-  BOOLEAN               InSubtitle;          // nesting inside of EFI_IFR_SUBTITLE
-
-  LIST_ENTRY            InconsistentListHead;// nested inconsistent expression list (FORM_EXPRESSION)
-  LIST_ENTRY            NoSubmitListHead;    // nested nosubmit expression list (FORM_EXPRESSION)
-  FORM_EXPRESSION       *GrayOutExpression;  // nesting inside of GrayOutIf
-  FORM_EXPRESSION       *SuppressExpression; // nesting inside of SuppressIf
-
-} FORM_BROWSER_STATEMENT;
-
-#define FORM_BROWSER_STATEMENT_FROM_LINK(a)  CR (a, FORM_BROWSER_STATEMENT, Link, FORM_BROWSER_STATEMENT_SIGNATURE)
-
-#define FORM_BROWSER_FORM_SIGNATURE  EFI_SIGNATURE_32 ('F', 'F', 'R', 'M')
-
-typedef struct {
-  UINTN             Signature;
-  LIST_ENTRY        Link;
-
-  UINT16            FormId;
-  EFI_STRING_ID     FormTitle;
-
-  EFI_IMAGE_ID      ImageId;
-
-  LIST_ENTRY        ExpressionListHead;   // List of Expressions (FORM_EXPRESSION)
-  LIST_ENTRY        StatementListHead;    // List of Statements and Questions (FORM_BROWSER_STATEMENT)
-} FORM_BROWSER_FORM;
-
-#define FORM_BROWSER_FORM_FROM_LINK(a)  CR (a, FORM_BROWSER_FORM, Link, FORM_BROWSER_FORM_SIGNATURE)
-
-#define FORMSET_DEFAULTSTORE_SIGNATURE  EFI_SIGNATURE_32 ('F', 'D', 'F', 'S')
-
-typedef struct {
-  UINTN            Signature;
-  LIST_ENTRY       Link;
-
-  UINT16           DefaultId;
-  EFI_STRING_ID    DefaultName;
-} FORMSET_DEFAULTSTORE;
-
-#define FORMSET_DEFAULTSTORE_FROM_LINK(a)  CR (a, FORMSET_DEFAULTSTORE, Link, FORMSET_DEFAULTSTORE_SIGNATURE)
-
-typedef struct {
-  EFI_HII_HANDLE                  HiiHandle;
-  EFI_HANDLE                      DriverHandle;
-  EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;
-  EFI_DEVICE_PATH_PROTOCOL        *DevicePath;
-
-  UINTN                           IfrBinaryLength;
-  UINT8                           *IfrBinaryData;
-
-  EFI_GUID                        Guid;
-  EFI_STRING_ID                   FormSetTitle;
-  EFI_STRING_ID                   Help;
-  UINT16                          Class;
-  UINT16                          SubClass;
-  EFI_IMAGE_ID                    ImageId;
-
-  FORM_BROWSER_STATEMENT          *StatementBuffer;     // Buffer for all Statements and Questions
-  EXPRESSION_OPCODE               *ExpressionBuffer;    // Buffer for all Expression OpCode
-
-  LIST_ENTRY                      StorageListHead;      // Storage list (FORMSET_STORAGE)
-  LIST_ENTRY                      DefaultStoreListHead; // DefaultStore list (FORMSET_DEFAULTSTORE)
-  LIST_ENTRY                      FormListHead;         // Form list (FORM_BROWSER_FORM)
-} FORM_BROWSER_FORMSET;
-
-
-extern EFI_HII_DATABASE_PROTOCOL         *mHiiDatabase;
-extern EFI_HII_STRING_PROTOCOL           *mHiiString;
-extern EFI_HII_CONFIG_ROUTING_PROTOCOL   *mHiiConfigRouting;
-
-extern BANNER_DATA           *BannerData;
-extern EFI_HII_HANDLE        FrontPageHandle;
-extern UINTN                 gClassOfVfr;
-extern UINTN                 gFunctionKeySetting;
-extern BOOLEAN               gResetRequired;
-extern BOOLEAN               gNvUpdateRequired;
-extern EFI_HII_HANDLE        gHiiHandle;
-extern BOOLEAN               gFirstIn;
-extern UINT16                gDirection;
-extern EFI_SCREEN_DESCRIPTOR gScreenDimensions;
-extern BOOLEAN               gUpArrow;
-extern BOOLEAN               gDownArrow;
-
-//
-// Browser Global Strings
-//
-extern CHAR16            *gFunctionOneString;
-extern CHAR16            *gFunctionTwoString;
-extern CHAR16            *gFunctionNineString;
-extern CHAR16            *gFunctionTenString;
-extern CHAR16            *gEnterString;
-extern CHAR16            *gEnterCommitString;
-extern CHAR16            *gEscapeString;
-extern CHAR16            *gSaveFailed;
-extern CHAR16            *gMoveHighlight;
-extern CHAR16            *gMakeSelection;
-extern CHAR16            *gDecNumericInput;
-extern CHAR16            *gHexNumericInput;
-extern CHAR16            *gToggleCheckBox;
-extern CHAR16            *gPromptForData;
-extern CHAR16            *gPromptForPassword;
-extern CHAR16            *gPromptForNewPassword;
-extern CHAR16            *gConfirmPassword;
-extern CHAR16            *gConfirmError;
-extern CHAR16            *gPassowordInvalid;
-extern CHAR16            *gPressEnter;
-extern CHAR16            *gEmptyString;
-extern CHAR16            *gAreYouSure;
-extern CHAR16            *gYesResponse;
-extern CHAR16            *gNoResponse;
-extern CHAR16            *gMiniString;
-extern CHAR16            *gPlusString;
-extern CHAR16            *gMinusString;
-extern CHAR16            *gAdjustNumber;
-
-extern CHAR16            gPromptBlockWidth;
-extern CHAR16            gOptionBlockWidth;
-extern CHAR16            gHelpBlockWidth;
-
-extern EFI_GUID          gZeroGuid;
-extern EFI_GUID          gTianoHiiIfrGuid;
-
-//
-// Global Procedure Defines
-//
-VOID
-InitializeBrowserStrings (
-  VOID
-  )
-;
-
-UINTN
-_Print (
-  IN CHAR16                         *fmt,
-  ...
-  )
-;
-
-UINTN
-PrintString (
-  CHAR16       *String
-  )
-;
-
-UINTN
-PrintChar (
-  CHAR16       Character
-  )
-;
-
-UINTN
-PrintAt (
-  IN UINTN     Column,
-  IN UINTN     Row,
-  IN CHAR16    *fmt,
-  ...
-  )
-;
-
-UINTN
-PrintStringAt (
-  IN UINTN     Column,
-  IN UINTN     Row,
-  CHAR16       *String
-  )
-;
-
-UINTN
-PrintCharAt (
-  IN UINTN     Column,
-  IN UINTN     Row,
-  CHAR16       Character
-  )
-;
-
-EFI_STATUS
-ParseOpCodes (
-  IN FORM_BROWSER_FORMSET              *FormSet
-  )
-;
-
-VOID
-DestroyFormSet (
-  IN OUT FORM_BROWSER_FORMSET  *FormSet
-  )
-;
-
-VOID
-DisplayPageFrame (
-  VOID
-  )
-;
-
-EFI_STRING_ID
-NewString (
-  IN  CHAR16                   *String,
-  IN  EFI_HII_HANDLE           HiiHandle
-  )
-;
-
-EFI_STATUS
-DeleteString (
-  IN  EFI_STRING_ID            StringId,
-  IN  EFI_HII_HANDLE           HiiHandle
-  )
-;
-CHAR16 *
-GetToken (
-  IN  EFI_STRING_ID                Token,
-  IN  EFI_HII_HANDLE               HiiHandle
-  )
-;
-
-VOID
-CreateSharedPopUp (
-  IN  UINTN                       RequestedWidth,
-  IN  UINTN                       NumberOfLines,
-  IN  CHAR16                      **ArrayOfStrings
-  )
-;
-
-EFI_STATUS
-CreateDialog (
-  IN  UINTN                       NumberOfLines,
-  IN  BOOLEAN                     HotKey,
-  IN  UINTN                       MaximumStringSize,
-  OUT CHAR16                      *StringBuffer,
-  OUT EFI_INPUT_KEY               *KeyValue,
-  IN  CHAR16                      *String,
-  ...
-  )
-;
-
-EFI_STATUS
-GetQuestionValue (
-  IN FORM_BROWSER_FORMSET             *FormSet,
-  IN FORM_BROWSER_FORM                *Form,
-  IN OUT FORM_BROWSER_STATEMENT       *Question,
-  IN BOOLEAN                          Cached
-  )
-;
-
-EFI_STATUS
-SetQuestionValue (
-  IN FORM_BROWSER_FORMSET             *FormSet,
-  IN FORM_BROWSER_FORM                *Form,
-  IN OUT FORM_BROWSER_STATEMENT       *Question,
-  IN BOOLEAN                          Cached
-  )
-;
-
-EFI_STATUS
-ValidateQuestion (
-  IN  FORM_BROWSER_FORMSET            *FormSet,
-  IN  FORM_BROWSER_FORM               *Form,
-  IN  FORM_BROWSER_STATEMENT          *Question,
-  IN  UINTN                           Type
-  )
-;
-
-EFI_STATUS
-SubmitForm (
-  IN FORM_BROWSER_FORMSET             *FormSet,
-  IN FORM_BROWSER_FORM                *Form
-  )
-;
-
-EFI_STATUS
-GetQuestionDefault (
-  IN FORM_BROWSER_FORMSET             *FormSet,
-  IN FORM_BROWSER_FORM                *Form,
-  IN FORM_BROWSER_STATEMENT           *Question,
-  IN UINT16                           DefaultId
-  )
-;
-
-EFI_STATUS
-InitializeCurrentSetting (
-  IN OUT FORM_BROWSER_FORMSET             *FormSet
-  )
-;
-
-EFI_STATUS
-InitializeFormSet (
-  IN  EFI_HII_HANDLE                   Handle,
-  IN OUT EFI_GUID                      *FormSetGuid,
-  OUT FORM_BROWSER_FORMSET             *FormSet
-  )
-;
-
-EFI_STATUS
-ExtractFormDefault (
-  IN FORM_BROWSER_FORMSET             *FormSet,
-  IN  FORM_BROWSER_FORM               *Form,
-  IN UINT16                           DefaultId
-  )
-;
-
-EFI_STATUS
-LoadFormConfig (
-  IN FORM_BROWSER_FORMSET             *FormSet,
-  IN FORM_BROWSER_FORM                *Form
-  )
-;
-
-EFI_STATUS
-StorageToConfigResp (
-  IN FORMSET_STORAGE         *Storage,
-  IN CHAR16                  **ConfigResp
-  )
-;
-
-EFI_STATUS
-ConfigRespToStorage (
-  IN FORMSET_STORAGE         *Storage,
-  IN CHAR16                  *ConfigResp
-  )
-;
-
-EFI_STATUS
-LoadStorage (
-  IN FORM_BROWSER_FORMSET    *FormSet,
-  IN FORMSET_STORAGE         *Storage
-  )
-;
-
-EFI_STATUS
-GetIfrBinaryData (
-  IN  EFI_HII_HANDLE   Handle,
-  IN OUT EFI_GUID      *FormSetGuid,
-  OUT UINTN            *BinaryLength,
-  OUT UINT8            **BinaryData
-  )
-;
-
-EFI_STATUS
-EFIAPI
-SendForm (
-  IN  CONST EFI_FORM_BROWSER2_PROTOCOL *This,
-  IN  EFI_HII_HANDLE                   *Handles,
-  IN  UINTN                            HandleCount,
-  IN  EFI_GUID                         *FormSetGuid, OPTIONAL
-  IN  UINT16                           FormId, OPTIONAL
-  IN  CONST EFI_SCREEN_DESCRIPTOR      *ScreenDimensions, OPTIONAL
-  OUT EFI_BROWSER_ACTION_REQUEST       *ActionRequest  OPTIONAL
-  )
-;
-
-EFI_STATUS
-EFIAPI
-BrowserCallback (
-  IN CONST EFI_FORM_BROWSER2_PROTOCOL  *This,
-  IN OUT UINTN                         *ResultsDataSize,
-  IN OUT EFI_STRING                    ResultsData,
-  IN BOOLEAN                           RetrieveData,
-  IN CONST EFI_GUID                    *VariableGuid, OPTIONAL
-  IN CONST CHAR16                      *VariableName  OPTIONAL
-  )
-;
-
-#endif
+/** @file\r
+Private MACRO, structure and function definitions for Setup Browser module. \r
+\r
+Copyright (c) 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+\r
+**/\r
+\r
+#ifndef _SETUP_H_\r
+#define _SETUP_H_\r
+\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <Protocol/Print.h>\r
+#include <Protocol/SimpleTextOut.h>\r
+#include <Protocol/SimpleTextIn.h>\r
+#include <Protocol/FormBrowser2.h>\r
+#include <Protocol/DevicePath.h>\r
+#include <Protocol/UnicodeCollation.h>\r
+#include <Protocol/HiiConfigAccess.h>\r
+#include <Protocol/HiiConfigRouting.h>\r
+#include <Protocol/HiiDatabase.h>\r
+#include <Protocol/HiiString.h>\r
+\r
+#include <MdeModuleHii.h>\r
+\r
+#include <Library/GraphicsLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/IfrSupportLib.h>\r
+#include <Library/ExtendedIfrSupportLib.h>\r
+#include <Library/HiiLib.h>\r
+#include <Library/ExtendedHiiLib.h>\r
+\r
+#include "Colors.h"\r
+\r
+//\r
+// This is the generated header file which includes whatever needs to be exported (strings + IFR)\r
+//\r
+\r
+extern UINT8  SetupBrowserStrings[];\r
+\r
+//\r
+// Screen definitions\r
+//\r
+#define BANNER_HEIGHT                 6\r
+#define BANNER_COLUMNS                3\r
+\r
+#define FRONT_PAGE_HEADER_HEIGHT      6\r
+#define NONE_FRONT_PAGE_HEADER_HEIGHT 3\r
+#define LEFT_SKIPPED_COLUMNS          4\r
+#define FOOTER_HEIGHT                 4\r
+#define STATUS_BAR_HEIGHT             1\r
+#define SCROLL_ARROW_HEIGHT           1\r
+#define POPUP_PAD_SPACE_COUNT         5\r
+#define POPUP_FRAME_WIDTH             2\r
+\r
+//\r
+// Definition for function key setting\r
+//\r
+#define NONE_FUNCTION_KEY_SETTING     0\r
+#define DEFAULT_FUNCTION_KEY_SETTING  (FUNCTION_ONE | FUNCTION_TWO | FUNCTION_NINE | FUNCTION_TEN)\r
+\r
+#define FUNCTION_ONE                  (1 << 0)\r
+#define FUNCTION_TWO                  (1 << 1)\r
+#define FUNCTION_NINE                 (1 << 2)\r
+#define FUNCTION_TEN                  (1 << 3)\r
+\r
+typedef struct {\r
+  EFI_GUID  FormSetGuid;\r
+  UINTN     KeySetting;\r
+} FUNCTIION_KEY_SETTING;\r
+\r
+//\r
+// Character definitions\r
+//\r
+#define CHAR_SPACE              0x0020\r
+#define UPPER_LOWER_CASE_OFFSET 0x20\r
+\r
+//\r
+// Time definitions\r
+//\r
+#define ONE_SECOND  10000000\r
+\r
+//\r
+// Display definitions\r
+//\r
+#define LEFT_HYPER_DELIMITER      L'<'\r
+#define RIGHT_HYPER_DELIMITER     L'>'\r
+\r
+#define LEFT_ONEOF_DELIMITER      L'<'\r
+#define RIGHT_ONEOF_DELIMITER     L'>'\r
+\r
+#define LEFT_NUMERIC_DELIMITER    L'['\r
+#define RIGHT_NUMERIC_DELIMITER   L']'\r
+\r
+#define LEFT_CHECKBOX_DELIMITER   L'['\r
+#define RIGHT_CHECKBOX_DELIMITER  L']'\r
+\r
+#define CHECK_ON                  L'X'\r
+#define CHECK_OFF                 L' '\r
+\r
+#define TIME_SEPARATOR            L':'\r
+#define DATE_SEPARATOR            L'/'\r
+\r
+#define YES_ANSWER                L'Y'\r
+#define NO_ANSWER                 L'N'\r
+\r
+//\r
+// This is the Input Error Message\r
+//\r
+#define INPUT_ERROR 1\r
+\r
+//\r
+// This is the NV RAM update required Message\r
+//\r
+#define NV_UPDATE_REQUIRED  2\r
+\r
+//\r
+// Refresh the Status Bar with flags\r
+//\r
+#define REFRESH_STATUS_BAR  0xff\r
+\r
+//\r
+// Incremental string lenght of ConfigRequest\r
+//\r
+#define CONFIG_REQUEST_STRING_INCREMENTAL  1024\r
+\r
+//\r
+// HII value compare result\r
+//\r
+#define HII_VALUE_UNDEFINED     0\r
+#define HII_VALUE_EQUAL         1\r
+#define HII_VALUE_LESS_THAN     2\r
+#define HII_VALUE_GREATER_THAN  3\r
+\r
+//\r
+// Incremental size of stack for expression\r
+//\r
+#define EXPRESSION_STACK_SIZE_INCREMENT    0x100\r
+\r
+\r
+#define EFI_SPECIFICATION_ERRATA_VERSION   0\r
+\r
+#define EFI_IFR_SPECIFICATION_VERSION  \\r
+        ((((EFI_SPECIFICATION_VERSION) >> 8) & 0xff00) | \\r
+         (((EFI_SPECIFICATION_VERSION) & 0xf) << 4) | \\r
+         ((EFI_SPECIFICATION_ERRATA_VERSION) & 0xf))\r
+\r
+#define SETUP_DRIVER_SIGNATURE EFI_SIGNATURE_32 ('F', 'B', 'D', 'V')\r
+typedef struct {\r
+  UINT32                             Signature;\r
+\r
+  EFI_HANDLE                         Handle;\r
+\r
+  //\r
+  // Produced protocol\r
+  //\r
+  EFI_FORM_BROWSER2_PROTOCOL         FormBrowser2;\r
+  EFI_PRINT_PROTOCOL                 Print;\r
+\r
+} SETUP_DRIVER_PRIVATE_DATA;\r
+\r
+typedef struct {\r
+  EFI_STRING_ID  Banner[BANNER_HEIGHT][BANNER_COLUMNS];\r
+} BANNER_DATA;\r
+\r
+//\r
+// IFR relative definition\r
+//\r
+#define EFI_HII_EXPRESSION_INCONSISTENT_IF   0\r
+#define EFI_HII_EXPRESSION_NO_SUBMIT_IF      1\r
+#define EFI_HII_EXPRESSION_GRAY_OUT_IF       2\r
+#define EFI_HII_EXPRESSION_SUPPRESS_IF       3\r
+#define EFI_HII_EXPRESSION_DISABLE_IF        4\r
+#define EFI_HII_EXPRESSION_VALUE             5\r
+#define EFI_HII_EXPRESSION_RULE              6\r
+\r
+#define EFI_HII_VARSTORE_BUFFER              0\r
+#define EFI_HII_VARSTORE_NAME_VALUE          1\r
+#define EFI_HII_VARSTORE_EFI_VARIABLE        2\r
+\r
+#define FORM_INCONSISTENT_VALIDATION         0\r
+#define FORM_NO_SUBMIT_VALIDATION            1\r
+\r
+typedef struct {\r
+  UINT8               Type;\r
+  EFI_IFR_TYPE_VALUE  Value;\r
+} EFI_HII_VALUE;\r
+\r
+#define NAME_VALUE_NODE_SIGNATURE  EFI_SIGNATURE_32 ('N', 'V', 'S', 'T')\r
+\r
+typedef struct {\r
+  UINTN            Signature;\r
+  LIST_ENTRY       Link;\r
+  CHAR16           *Name;\r
+  CHAR16           *Value;\r
+  CHAR16           *EditValue;\r
+} NAME_VALUE_NODE;\r
+\r
+#define NAME_VALUE_NODE_FROM_LINK(a)  CR (a, NAME_VALUE_NODE, Link, NAME_VALUE_NODE_SIGNATURE)\r
+\r
+#define FORMSET_STORAGE_SIGNATURE  EFI_SIGNATURE_32 ('F', 'S', 'T', 'G')\r
+\r
+typedef struct {\r
+  UINTN            Signature;\r
+  LIST_ENTRY       Link;\r
+\r
+  UINT8            Type;           // Storage type\r
+\r
+  UINT16           VarStoreId;\r
+  EFI_GUID         Guid;\r
+\r
+  CHAR16           *Name;          // For EFI_IFR_VARSTORE\r
+  UINT16           Size;\r
+  UINT8            *Buffer;\r
+  UINT8            *EditBuffer;    // Edit copy for Buffer Storage\r
+\r
+  LIST_ENTRY       NameValueListHead; // List of NAME_VALUE_NODE\r
+\r
+  UINT32           Attributes;     // For EFI_IFR_VARSTORE_EFI: EFI Variable attribute\r
+\r
+  CHAR16           *ConfigHdr;     // <ConfigHdr>\r
+  CHAR16           *ConfigRequest; // <ConfigRequest> = <ConfigHdr> + <RequestElement>\r
+  UINTN            ElementCount;   // Number of <RequestElement> in the <ConfigRequest>\r
+  UINTN            SpareStrLen;    // Spare length of ConfigRequest string buffer\r
+} FORMSET_STORAGE;\r
+\r
+#define FORMSET_STORAGE_FROM_LINK(a)  CR (a, FORMSET_STORAGE, Link, FORMSET_STORAGE_SIGNATURE)\r
+\r
+#define EXPRESSION_OPCODE_SIGNATURE  EFI_SIGNATURE_32 ('E', 'X', 'O', 'P')\r
+\r
+typedef struct {\r
+  UINTN             Signature;\r
+  LIST_ENTRY        Link;\r
+\r
+  UINT8             Operand;\r
+\r
+  UINT8             Format;      // For EFI_IFR_TO_STRING, EFI_IFR_FIND\r
+  UINT8             Flags;       // For EFI_IFR_SPAN\r
+  UINT8             RuleId;      // For EFI_IFR_RULE_REF\r
+\r
+  EFI_HII_VALUE     Value;       // For EFI_IFR_EQ_ID_VAL, EFI_IFR_UINT64, EFI_IFR_UINT32, EFI_IFR_UINT16, EFI_IFR_UINT8, EFI_IFR_STRING_REF1\r
+\r
+  EFI_QUESTION_ID   QuestionId;  // For EFI_IFR_EQ_ID_ID, EFI_IFR_EQ_ID_LIST, EFI_IFR_QUESTION_REF1\r
+  EFI_QUESTION_ID   QuestionId2;\r
+\r
+  UINT16            ListLength;  // For EFI_IFR_EQ_ID_LIST\r
+  UINT16            *ValueList;\r
+\r
+  EFI_STRING_ID     DevicePath;  // For EFI_IFR_QUESTION_REF3_2, EFI_IFR_QUESTION_REF3_3\r
+  EFI_GUID          Guid;\r
+} EXPRESSION_OPCODE;\r
+\r
+#define EXPRESSION_OPCODE_FROM_LINK(a)  CR (a, EXPRESSION_OPCODE, Link, EXPRESSION_OPCODE_SIGNATURE)\r
+\r
+#define FORM_EXPRESSION_SIGNATURE  EFI_SIGNATURE_32 ('F', 'E', 'X', 'P')\r
+\r
+typedef struct {\r
+  UINTN             Signature;\r
+  LIST_ENTRY        Link;\r
+\r
+  UINT8             Type;            // Type for this expression\r
+\r
+  UINT8             RuleId;          // For EFI_IFR_RULE only\r
+  EFI_STRING_ID     Error;           // For EFI_IFR_NO_SUBMIT_IF, EFI_IFR_INCONSISTENT_IF only\r
+\r
+  EFI_HII_VALUE     Result;          // Expression evaluation result\r
+\r
+  LIST_ENTRY        OpCodeListHead;  // OpCodes consist of this expression (EXPRESSION_OPCODE)\r
+} FORM_EXPRESSION;\r
+\r
+#define FORM_EXPRESSION_FROM_LINK(a)  CR (a, FORM_EXPRESSION, Link, FORM_EXPRESSION_SIGNATURE)\r
+\r
+#define QUESTION_DEFAULT_SIGNATURE  EFI_SIGNATURE_32 ('Q', 'D', 'F', 'T')\r
+\r
+typedef struct {\r
+  UINTN               Signature;\r
+  LIST_ENTRY          Link;\r
+\r
+  UINT16              DefaultId;\r
+  EFI_HII_VALUE       Value;              // Default value\r
+\r
+  FORM_EXPRESSION     *ValueExpression;   // Not-NULL indicates default value is provided by EFI_IFR_VALUE\r
+} QUESTION_DEFAULT;\r
+\r
+#define QUESTION_DEFAULT_FROM_LINK(a)  CR (a, QUESTION_DEFAULT, Link, QUESTION_DEFAULT_SIGNATURE)\r
+\r
+#define QUESTION_OPTION_SIGNATURE  EFI_SIGNATURE_32 ('Q', 'O', 'P', 'T')\r
+\r
+typedef struct {\r
+  UINTN               Signature;\r
+  LIST_ENTRY          Link;\r
+\r
+  EFI_STRING_ID       Text;\r
+  UINT8               Flags;\r
+  EFI_HII_VALUE       Value;\r
+  EFI_IMAGE_ID        ImageId;\r
+\r
+  FORM_EXPRESSION     *SuppressExpression; // Non-NULL indicates nested inside of SuppressIf\r
+} QUESTION_OPTION;\r
+\r
+#define QUESTION_OPTION_FROM_LINK(a)  CR (a, QUESTION_OPTION, Link, QUESTION_OPTION_SIGNATURE)\r
+\r
+#define FORM_BROWSER_STATEMENT_SIGNATURE  EFI_SIGNATURE_32 ('F', 'S', 'T', 'A')\r
+typedef struct {\r
+  UINTN                 Signature;\r
+  LIST_ENTRY            Link;\r
+\r
+  UINT8                 Operand;          // The operand (first byte) of this Statement or Question\r
+\r
+  //\r
+  // Statement Header\r
+  //\r
+  EFI_STRING_ID         Prompt;\r
+  EFI_STRING_ID         Help;\r
+  EFI_STRING_ID         TextTwo;          // For EFI_IFR_TEXT\r
+\r
+  //\r
+  // Question Header\r
+  //\r
+  EFI_QUESTION_ID       QuestionId;       // The value of zero is reserved\r
+  EFI_VARSTORE_ID       VarStoreId;       // A value of zero indicates no variable storage\r
+  FORMSET_STORAGE       *Storage;\r
+  union {\r
+    EFI_STRING_ID       VarName;\r
+    UINT16              VarOffset;\r
+  }  VarStoreInfo;\r
+  UINT16                StorageWidth;\r
+  UINT8                 QuestionFlags;\r
+  CHAR16                *VariableName;    // Name/Value or EFI Variable name\r
+  CHAR16                *BlockName;       // Buffer storage block name: "OFFSET=...WIDTH=..."\r
+\r
+  EFI_HII_VALUE         HiiValue;         // Edit copy for checkbox, numberic, oneof\r
+  UINT8                 *BufferValue;     // Edit copy for string, password, orderedlist\r
+\r
+  //\r
+  // OpCode specific members\r
+  //\r
+  UINT8                 Flags;            // for EFI_IFR_CHECKBOX, EFI_IFR_DATE, EFI_IFR_NUMERIC, EFI_IFR_ONE_OF,\r
+                                          // EFI_IFR_ORDERED_LIST, EFI_IFR_STRING,EFI_IFR_SUBTITLE,EFI_IFR_TIME, EFI_IFR_BANNER\r
+  UINT8                 MaxContainers;    // for EFI_IFR_ORDERED_LIST\r
+\r
+  UINT16                BannerLineNumber; // for EFI_IFR_BANNER, 1-based line number\r
+  EFI_STRING_ID         QuestionConfig;   // for EFI_IFR_ACTION, if 0 then no configuration string will be processed\r
+\r
+  UINT64                Minimum;          // for EFI_IFR_ONE_OF/EFI_IFR_NUMERIC, it's Min/Max value\r
+  UINT64                Maximum;          // for EFI_IFR_STRING/EFI_IFR_PASSWORD, it's Min/Max length\r
+  UINT64                Step;\r
+\r
+  EFI_DEFAULT_ID        DefaultId;        // for EFI_IFR_RESET_BUTTON\r
+  EFI_FORM_ID           RefFormId;        // for EFI_IFR_REF\r
+  EFI_QUESTION_ID       RefQuestionId;    // for EFI_IFR_REF2\r
+  EFI_GUID              RefFormSetId;     // for EFI_IFR_REF3\r
+  EFI_STRING_ID         RefDevicePath;    // for EFI_IFR_REF4\r
+\r
+  //\r
+  // Get from IFR parsing\r
+  //\r
+  FORM_EXPRESSION       *ValueExpression;    // nested EFI_IFR_VALUE, provide Question value and indicate Question is ReadOnly\r
+  LIST_ENTRY            DefaultListHead;     // nested EFI_IFR_DEFAULT list (QUESTION_DEFAULT), provide default values\r
+  LIST_ENTRY            OptionListHead;      // nested EFI_IFR_ONE_OF_OPTION list (QUESTION_OPTION)\r
+\r
+  EFI_IMAGE_ID          ImageId;             // nested EFI_IFR_IMAGE\r
+  UINT8                 RefreshInterval;     // nested EFI_IFR_REFRESH, refresh interval(in seconds) for Question value, 0 means no refresh\r
+  BOOLEAN               InSubtitle;          // nesting inside of EFI_IFR_SUBTITLE\r
+\r
+  LIST_ENTRY            InconsistentListHead;// nested inconsistent expression list (FORM_EXPRESSION)\r
+  LIST_ENTRY            NoSubmitListHead;    // nested nosubmit expression list (FORM_EXPRESSION)\r
+  FORM_EXPRESSION       *GrayOutExpression;  // nesting inside of GrayOutIf\r
+  FORM_EXPRESSION       *SuppressExpression; // nesting inside of SuppressIf\r
+\r
+} FORM_BROWSER_STATEMENT;\r
+\r
+#define FORM_BROWSER_STATEMENT_FROM_LINK(a)  CR (a, FORM_BROWSER_STATEMENT, Link, FORM_BROWSER_STATEMENT_SIGNATURE)\r
+\r
+#define FORM_BROWSER_FORM_SIGNATURE  EFI_SIGNATURE_32 ('F', 'F', 'R', 'M')\r
+\r
+typedef struct {\r
+  UINTN             Signature;\r
+  LIST_ENTRY        Link;\r
+\r
+  UINT16            FormId;\r
+  EFI_STRING_ID     FormTitle;\r
+\r
+  EFI_IMAGE_ID      ImageId;\r
+\r
+  LIST_ENTRY        ExpressionListHead;   // List of Expressions (FORM_EXPRESSION)\r
+  LIST_ENTRY        StatementListHead;    // List of Statements and Questions (FORM_BROWSER_STATEMENT)\r
+} FORM_BROWSER_FORM;\r
+\r
+#define FORM_BROWSER_FORM_FROM_LINK(a)  CR (a, FORM_BROWSER_FORM, Link, FORM_BROWSER_FORM_SIGNATURE)\r
+\r
+#define FORMSET_DEFAULTSTORE_SIGNATURE  EFI_SIGNATURE_32 ('F', 'D', 'F', 'S')\r
+\r
+typedef struct {\r
+  UINTN            Signature;\r
+  LIST_ENTRY       Link;\r
+\r
+  UINT16           DefaultId;\r
+  EFI_STRING_ID    DefaultName;\r
+} FORMSET_DEFAULTSTORE;\r
+\r
+#define FORMSET_DEFAULTSTORE_FROM_LINK(a)  CR (a, FORMSET_DEFAULTSTORE, Link, FORMSET_DEFAULTSTORE_SIGNATURE)\r
+\r
+typedef struct {\r
+  EFI_HII_HANDLE                  HiiHandle;\r
+  EFI_HANDLE                      DriverHandle;\r
+  EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;\r
+  EFI_DEVICE_PATH_PROTOCOL        *DevicePath;\r
+\r
+  UINTN                           IfrBinaryLength;\r
+  UINT8                           *IfrBinaryData;\r
+\r
+  EFI_GUID                        Guid;\r
+  EFI_STRING_ID                   FormSetTitle;\r
+  EFI_STRING_ID                   Help;\r
+  UINT16                          Class;\r
+  UINT16                          SubClass;\r
+  EFI_IMAGE_ID                    ImageId;\r
+\r
+  FORM_BROWSER_STATEMENT          *StatementBuffer;     // Buffer for all Statements and Questions\r
+  EXPRESSION_OPCODE               *ExpressionBuffer;    // Buffer for all Expression OpCode\r
+\r
+  LIST_ENTRY                      StorageListHead;      // Storage list (FORMSET_STORAGE)\r
+  LIST_ENTRY                      DefaultStoreListHead; // DefaultStore list (FORMSET_DEFAULTSTORE)\r
+  LIST_ENTRY                      FormListHead;         // Form list (FORM_BROWSER_FORM)\r
+} FORM_BROWSER_FORMSET;\r
+\r
+\r
+extern EFI_HII_DATABASE_PROTOCOL         *mHiiDatabase;\r
+extern EFI_HII_STRING_PROTOCOL           *mHiiString;\r
+extern EFI_HII_CONFIG_ROUTING_PROTOCOL   *mHiiConfigRouting;\r
+\r
+extern BANNER_DATA           *BannerData;\r
+extern EFI_HII_HANDLE        FrontPageHandle;\r
+extern UINTN                 gClassOfVfr;\r
+extern UINTN                 gFunctionKeySetting;\r
+extern BOOLEAN               gResetRequired;\r
+extern BOOLEAN               gNvUpdateRequired;\r
+extern EFI_HII_HANDLE        gHiiHandle;\r
+extern BOOLEAN               gFirstIn;\r
+extern UINT16                gDirection;\r
+extern EFI_SCREEN_DESCRIPTOR gScreenDimensions;\r
+extern BOOLEAN               gUpArrow;\r
+extern BOOLEAN               gDownArrow;\r
+\r
+//\r
+// Browser Global Strings\r
+//\r
+extern CHAR16            *gFunctionOneString;\r
+extern CHAR16            *gFunctionTwoString;\r
+extern CHAR16            *gFunctionNineString;\r
+extern CHAR16            *gFunctionTenString;\r
+extern CHAR16            *gEnterString;\r
+extern CHAR16            *gEnterCommitString;\r
+extern CHAR16            *gEscapeString;\r
+extern CHAR16            *gSaveFailed;\r
+extern CHAR16            *gMoveHighlight;\r
+extern CHAR16            *gMakeSelection;\r
+extern CHAR16            *gDecNumericInput;\r
+extern CHAR16            *gHexNumericInput;\r
+extern CHAR16            *gToggleCheckBox;\r
+extern CHAR16            *gPromptForData;\r
+extern CHAR16            *gPromptForPassword;\r
+extern CHAR16            *gPromptForNewPassword;\r
+extern CHAR16            *gConfirmPassword;\r
+extern CHAR16            *gConfirmError;\r
+extern CHAR16            *gPassowordInvalid;\r
+extern CHAR16            *gPressEnter;\r
+extern CHAR16            *gEmptyString;\r
+extern CHAR16            *gAreYouSure;\r
+extern CHAR16            *gYesResponse;\r
+extern CHAR16            *gNoResponse;\r
+extern CHAR16            *gMiniString;\r
+extern CHAR16            *gPlusString;\r
+extern CHAR16            *gMinusString;\r
+extern CHAR16            *gAdjustNumber;\r
+\r
+extern CHAR16            gPromptBlockWidth;\r
+extern CHAR16            gOptionBlockWidth;\r
+extern CHAR16            gHelpBlockWidth;\r
+\r
+extern EFI_GUID          gZeroGuid;\r
+extern EFI_GUID          gTianoHiiIfrGuid;\r
+\r
+//\r
+// Global Procedure Defines\r
+//\r
+\r
+/**\r
+  Initialize the HII String Token to the correct values.\r
+\r
+**/\r
+VOID\r
+InitializeBrowserStrings (\r
+  VOID\r
+  )\r
+;\r
+\r
+/**\r
+  Prints a unicode string to the default console,\r
+  using L"%s" format.\r
+\r
+  @param  String     String pointer.\r
+\r
+  @return Length of string printed to the console\r
+\r
+**/\r
+UINTN\r
+PrintString (\r
+  IN CHAR16       *String\r
+  )\r
+;\r
+\r
+/**\r
+  Prints a chracter to the default console,\r
+  using L"%c" format.\r
+\r
+  @param  Character  Character to print.\r
+\r
+  @return Length of string printed to the console.\r
+\r
+**/\r
+UINTN\r
+PrintChar (\r
+  CHAR16       Character\r
+  )\r
+;\r
+\r
+/**\r
+  Prints a formatted unicode string to the default console, at\r
+  the supplied cursor position.\r
+\r
+  @param  Column     The cursor position to print the string at.\r
+  @param  Row        The cursor position to print the string at\r
+  @param  Fmt        Format string\r
+  @param  ...        Variable argument list for formating string.\r
+\r
+  @return Length of string printed to the console\r
+\r
+**/\r
+UINTN\r
+PrintAt (\r
+  IN UINTN     Column,\r
+  IN UINTN     Row,\r
+  IN CHAR16    *Fmt,\r
+  ...\r
+  )\r
+;\r
+\r
+/**\r
+  Prints a unicode string to the default console, at\r
+  the supplied cursor position, using L"%s" format.\r
+\r
+  @param  Column     The cursor position to print the string at.\r
+  @param  Row        The cursor position to print the string at\r
+  @param  String     String pointer.\r
+\r
+  @return Length of string printed to the console\r
+\r
+**/\r
+UINTN\r
+PrintStringAt (\r
+  IN UINTN     Column,\r
+  IN UINTN     Row,\r
+  IN CHAR16    *String\r
+  )\r
+;\r
+\r
+/**\r
+  Prints a chracter to the default console, at\r
+  the supplied cursor position, using L"%c" format.\r
+\r
+  @param  Column     The cursor position to print the string at.\r
+  @param  Row        The cursor position to print the string at.\r
+  @param  Character  Character to print.\r
+\r
+  @return Length of string printed to the console.\r
+\r
+**/\r
+UINTN\r
+PrintCharAt (\r
+  IN UINTN     Column,\r
+  IN UINTN     Row,\r
+  CHAR16       Character\r
+  )\r
+;\r
+\r
+/**\r
+  Parse opcodes in the formset IFR binary.\r
+\r
+  @param  FormSet                Pointer of the FormSet data structure.\r
+\r
+  @retval EFI_SUCCESS            Opcode parse success.\r
+  @retval Other                  Opcode parse fail.\r
+\r
+**/\r
+EFI_STATUS\r
+ParseOpCodes (\r
+  IN FORM_BROWSER_FORMSET              *FormSet\r
+  )\r
+;\r
+\r
+/**\r
+  Free resources allocated for a FormSet.\r
+\r
+  @param  FormSet                Pointer of the FormSet\r
+\r
+**/\r
+VOID\r
+DestroyFormSet (\r
+  IN OUT FORM_BROWSER_FORMSET  *FormSet\r
+  )\r
+;\r
+\r
+/**\r
+  This function displays the page frame.\r
+\r
+**/\r
+VOID\r
+DisplayPageFrame (\r
+  VOID\r
+  )\r
+;\r
+\r
+/**\r
+  Create a new string in HII Package List.\r
+\r
+  @param  String                 The String to be added\r
+  @param  HiiHandle              The package list in the HII database to insert the\r
+                                 specified string.\r
+\r
+  @return The output string.\r
+\r
+**/\r
+EFI_STRING_ID\r
+NewString (\r
+  IN  CHAR16                   *String,\r
+  IN  EFI_HII_HANDLE           HiiHandle\r
+  )\r
+;\r
+\r
+/**\r
+  Delete a string from HII Package List.\r
+\r
+  @param  StringId               Id of the string in HII database.\r
+  @param  HiiHandle              The HII package list handle.\r
+\r
+  @retval EFI_SUCCESS            The string was deleted successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+DeleteString (\r
+  IN  EFI_STRING_ID            StringId,\r
+  IN  EFI_HII_HANDLE           HiiHandle\r
+  )\r
+;\r
+\r
+/**\r
+  Get the string based on the StringId and HII Package List Handle.\r
+\r
+  @param  Token                  The String's ID.\r
+  @param  HiiHandle              The package list in the HII database to search for\r
+                                 the specified string.\r
+\r
+  @return The output string.\r
+\r
+**/\r
+CHAR16 *\r
+GetToken (\r
+  IN  EFI_STRING_ID                Token,\r
+  IN  EFI_HII_HANDLE               HiiHandle\r
+  )\r
+;\r
+\r
+/**\r
+  Draw a pop up windows based on the dimension, number of lines and\r
+  strings specified.\r
+\r
+  @param RequestedWidth  The width of the pop-up.\r
+  @param NumberOfLines   The number of lines.\r
+  @param ArrayOfStrings  The array of string to be printed.\r
+\r
+**/\r
+VOID\r
+CreateSharedPopUp (\r
+  IN  UINTN                       RequestedWidth,\r
+  IN  UINTN                       NumberOfLines,\r
+  IN  CHAR16                      **ArrayOfStrings\r
+  )\r
+;\r
+\r
+/**\r
+  Routine used to abstract a generic dialog interface and return the selected key or string\r
+\r
+  @param  NumberOfLines          The number of lines for the dialog box\r
+  @param  HotKey                 Defines whether a single character is parsed\r
+                                 (TRUE) and returned in KeyValue or a string is\r
+                                 returned in StringBuffer.  Two special characters\r
+                                 are considered when entering a string, a SCAN_ESC\r
+                                 and an CHAR_CARRIAGE_RETURN.  SCAN_ESC terminates\r
+                                 string input and returns\r
+  @param  MaximumStringSize      The maximum size in bytes of a typed in string\r
+                                 (each character is a CHAR16) and the minimum\r
+                                 string returned is two bytes\r
+  @param  StringBuffer           The passed in pointer to the buffer which will\r
+                                 hold the typed in string if HotKey is FALSE\r
+  @param  KeyValue               The EFI_KEY value returned if HotKey is TRUE..\r
+  @param  String                 Pointer to the first string in the list\r
+  @param  ...                    A series of (quantity == NumberOfLines) text\r
+                                 strings which will be used to construct the dialog\r
+                                 box\r
+\r
+  @retval EFI_SUCCESS            Displayed dialog and received user interaction\r
+  @retval EFI_INVALID_PARAMETER  One of the parameters was invalid (e.g.\r
+                                 (StringBuffer == NULL) && (HotKey == FALSE))\r
+  @retval EFI_DEVICE_ERROR       User typed in an ESC character to exit the routine\r
+\r
+**/\r
+EFI_STATUS\r
+CreateDialog (\r
+  IN  UINTN                       NumberOfLines,\r
+  IN  BOOLEAN                     HotKey,\r
+  IN  UINTN                       MaximumStringSize,\r
+  OUT CHAR16                      *StringBuffer,\r
+  OUT EFI_INPUT_KEY               *KeyValue,\r
+  IN  CHAR16                      *String,\r
+  ...\r
+  )\r
+;\r
+\r
+/**\r
+  Get Question's current Value.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   Form data structure.\r
+  @param  Question               Question to be initialized.\r
+  @param  Cached                 TRUE:  get from Edit copy FALSE: get from original\r
+                                 Storage\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+GetQuestionValue (\r
+  IN FORM_BROWSER_FORMSET             *FormSet,\r
+  IN FORM_BROWSER_FORM                *Form,\r
+  IN OUT FORM_BROWSER_STATEMENT       *Question,\r
+  IN BOOLEAN                          Cached\r
+  )\r
+;\r
+\r
+/**\r
+  Save Question Value to edit copy(cached) or Storage(uncached).\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   Form data structure.\r
+  @param  Question               Pointer to the Question.\r
+  @param  Cached                 TRUE:  set to Edit copy FALSE: set to original\r
+                                 Storage\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+SetQuestionValue (\r
+  IN FORM_BROWSER_FORMSET             *FormSet,\r
+  IN FORM_BROWSER_FORM                *Form,\r
+  IN OUT FORM_BROWSER_STATEMENT       *Question,\r
+  IN BOOLEAN                          Cached\r
+  )\r
+;\r
+\r
+/**\r
+  Perform inconsistent check for a Form.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   Form data structure.\r
+  @param  Question               The Question to be validated.\r
+  @param  Type                   Validation type: InConsistent or NoSubmit\r
+\r
+  @retval EFI_SUCCESS            Form validation pass.\r
+  @retval other                  Form validation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+ValidateQuestion (\r
+  IN  FORM_BROWSER_FORMSET            *FormSet,\r
+  IN  FORM_BROWSER_FORM               *Form,\r
+  IN  FORM_BROWSER_STATEMENT          *Question,\r
+  IN  UINTN                           Type\r
+  )\r
+;\r
+\r
+/**\r
+  Submit a Form.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   Form data structure.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+SubmitForm (\r
+  IN FORM_BROWSER_FORMSET             *FormSet,\r
+  IN FORM_BROWSER_FORM                *Form\r
+  )\r
+;\r
+\r
+/**\r
+  Reset Question to its default value.\r
+\r
+  @param  FormSet                The form set.\r
+  @param  Form                   The form.\r
+  @param  Question               The question.\r
+  @param  DefaultId              The Class of the default.\r
+\r
+  @retval EFI_SUCCESS            Question is reset to default value.\r
+\r
+**/\r
+EFI_STATUS\r
+GetQuestionDefault (\r
+  IN FORM_BROWSER_FORMSET             *FormSet,\r
+  IN FORM_BROWSER_FORM                *Form,\r
+  IN FORM_BROWSER_STATEMENT           *Question,\r
+  IN UINT16                           DefaultId\r
+  )\r
+;\r
+\r
+/**\r
+  Get current setting of Questions.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeCurrentSetting (\r
+  IN OUT FORM_BROWSER_FORMSET             *FormSet\r
+  )\r
+;\r
+\r
+/**\r
+  Initialize the internal data structure of a FormSet.\r
+\r
+  @param  Handle                 PackageList Handle\r
+  @param  FormSetGuid            GUID of a formset. If not specified (NULL or zero\r
+                                 GUID), take the first FormSet found in package\r
+                                 list.\r
+  @param  FormSet                FormSet data structure.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+  @retval EFI_NOT_FOUND          The specified FormSet could not be found.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeFormSet (\r
+  IN  EFI_HII_HANDLE                   Handle,\r
+  IN OUT EFI_GUID                      *FormSetGuid,\r
+  OUT FORM_BROWSER_FORMSET             *FormSet\r
+  )\r
+;\r
+\r
+/**\r
+  Reset Questions in a Form to their default value.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   The Form which to be reset.\r
+  @param  DefaultId              The Class of the default.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+ExtractFormDefault (\r
+  IN FORM_BROWSER_FORMSET             *FormSet,\r
+  IN  FORM_BROWSER_FORM               *Form,\r
+  IN UINT16                           DefaultId\r
+  )\r
+;\r
+\r
+/**\r
+  Initialize Question's Edit copy from Storage.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Form                   Form data structure.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+LoadFormConfig (\r
+  IN FORM_BROWSER_FORMSET             *FormSet,\r
+  IN FORM_BROWSER_FORM                *Form\r
+  )\r
+;\r
+\r
+/**\r
+  Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.\r
+\r
+  @param  Storage                The Storage to be conveted.\r
+  @param  ConfigResp             The returned <ConfigResp>.\r
+\r
+  @retval EFI_SUCCESS            Convert success.\r
+  @retval EFI_INVALID_PARAMETER  Incorrect storage type.\r
+\r
+**/\r
+EFI_STATUS\r
+StorageToConfigResp (\r
+  IN FORMSET_STORAGE         *Storage,\r
+  IN CHAR16                  **ConfigResp\r
+  )\r
+;\r
+\r
+/**\r
+  Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.\r
+\r
+  @param  Storage                The Storage to receive the settings.\r
+  @param  ConfigResp             The <ConfigResp> to be converted.\r
+\r
+  @retval EFI_SUCCESS            Convert success.\r
+  @retval EFI_INVALID_PARAMETER  Incorrect storage type.\r
+\r
+**/\r
+EFI_STATUS\r
+ConfigRespToStorage (\r
+  IN FORMSET_STORAGE         *Storage,\r
+  IN CHAR16                  *ConfigResp\r
+  )\r
+;\r
+\r
+/**\r
+  Fill storage's edit copy with settings requested from Configuration Driver.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+  @param  Storage                Buffer Storage.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+LoadStorage (\r
+  IN FORM_BROWSER_FORMSET    *FormSet,\r
+  IN FORMSET_STORAGE         *Storage\r
+  )\r
+;\r
+\r
+/**\r
+  Fetch the Ifr binary data of a FormSet.\r
+\r
+  @param  Handle                 PackageList Handle\r
+  @param  FormSetGuid            GUID of a formset. If not specified (NULL or zero\r
+                                 GUID), take the first FormSet found in package\r
+                                 list.\r
+  @param  BinaryLength           The length of the FormSet IFR binary.\r
+  @param  BinaryData             The buffer designed to receive the FormSet.\r
+\r
+  @retval EFI_SUCCESS            Buffer filled with the requested FormSet.\r
+                                 BufferLength was updated.\r
+  @retval EFI_INVALID_PARAMETER  The handle is unknown.\r
+  @retval EFI_NOT_FOUND          A form or FormSet on the requested handle cannot\r
+                                 be found with the requested FormId.\r
+\r
+**/\r
+EFI_STATUS\r
+GetIfrBinaryData (\r
+  IN  EFI_HII_HANDLE   Handle,\r
+  IN OUT EFI_GUID      *FormSetGuid,\r
+  OUT UINTN            *BinaryLength,\r
+  OUT UINT8            **BinaryData\r
+  )\r
+;\r
+\r
+/**\r
+  This is the routine which an external caller uses to direct the browser\r
+  where to obtain it's information.\r
+\r
+\r
+  @param This            The Form Browser protocol instanse.\r
+  @param Handles         A pointer to an array of Handles.  If HandleCount > 1 we\r
+                         display a list of the formsets for the handles specified.\r
+  @param HandleCount     The number of Handles specified in Handle.\r
+  @param FormSetGuid     This field points to the EFI_GUID which must match the Guid\r
+                         field in the EFI_IFR_FORM_SET op-code for the specified\r
+                         forms-based package. If FormSetGuid is NULL, then this\r
+                         function will display the first found forms package.\r
+  @param FormId          This field specifies which EFI_IFR_FORM to render as the first\r
+                         displayable page. If this field has a value of 0x0000, then\r
+                         the forms browser will render the specified forms in their encoded order.\r
+                         ScreenDimenions - This allows the browser to be called so that it occupies a\r
+                         portion of the physical screen instead of dynamically determining the screen dimensions.\r
+                         ActionRequest   - Points to the action recommended by the form.\r
+  @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in \r
+                          characters.\r
+  @param ActionRequest       Points to the action recommended by the form.\r
+\r
+  @retval  EFI_SUCCESS            The function completed successfully.\r
+  @retval  EFI_INVALID_PARAMETER  One of the parameters has an invalid value.\r
+  @retval  EFI_NOT_FOUND          No valid forms could be found to display.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SendForm (\r
+  IN  CONST EFI_FORM_BROWSER2_PROTOCOL *This,\r
+  IN  EFI_HII_HANDLE                   *Handles,\r
+  IN  UINTN                            HandleCount,\r
+  IN  EFI_GUID                         *FormSetGuid, OPTIONAL\r
+  IN  UINT16                           FormId, OPTIONAL\r
+  IN  CONST EFI_SCREEN_DESCRIPTOR      *ScreenDimensions, OPTIONAL\r
+  OUT EFI_BROWSER_ACTION_REQUEST       *ActionRequest  OPTIONAL\r
+  )\r
+;\r
+\r
+/**\r
+  This function is called by a callback handler to retrieve uncommitted state\r
+  data from the browser.\r
+\r
+  @param  This                   A pointer to the EFI_FORM_BROWSER2_PROTOCOL\r
+                                 instance.\r
+  @param  ResultsDataSize        A pointer to the size of the buffer associated\r
+                                 with ResultsData.\r
+  @param  ResultsData            A string returned from an IFR browser or\r
+                                 equivalent. The results string will have no\r
+                                 routing information in them.\r
+  @param  RetrieveData           A BOOLEAN field which allows an agent to retrieve\r
+                                 (if RetrieveData = TRUE) data from the uncommitted\r
+                                 browser state information or set (if RetrieveData\r
+                                 = FALSE) data in the uncommitted browser state\r
+                                 information.\r
+  @param  VariableGuid           An optional field to indicate the target variable\r
+                                 GUID name to use.\r
+  @param  VariableName           An optional field to indicate the target\r
+                                 human-readable variable name.\r
+\r
+  @retval EFI_SUCCESS            The results have been distributed or are awaiting\r
+                                 distribution.\r
+  @retval EFI_BUFFER_TOO_SMALL   The ResultsDataSize specified was too small to\r
+                                 contain the results data.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BrowserCallback (\r
+  IN CONST EFI_FORM_BROWSER2_PROTOCOL  *This,\r
+  IN OUT UINTN                         *ResultsDataSize,\r
+  IN OUT EFI_STRING                    ResultsData,\r
+  IN BOOLEAN                           RetrieveData,\r
+  IN CONST EFI_GUID                    *VariableGuid, OPTIONAL\r
+  IN CONST CHAR16                      *VariableName  OPTIONAL\r
+  )\r
+;\r
+\r
+#endif\r
index 04b9f693031f0161329fa2d9030ab2a157c794ad..a66e94647503d9abae3e2b00c677d4eefbba163e 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:
-
-  Ui.c
-
-Abstract:
-
-  Implementation for UI.
-
-Revision History
-
-
-**/
-
-#include "Ui.h"
-#include "Setup.h"
-
-LIST_ENTRY          Menu;
-LIST_ENTRY          gMenuList;
-MENU_REFRESH_ENTRY  *gMenuRefreshHead;
-
-//
-// Search table for UiDisplayMenu()
-//
-SCAN_CODE_TO_SCREEN_OPERATION     gScanCodeToOperation[] = {
-  {
-    SCAN_UP,
-    UiUp,
-  },
-  {
-    SCAN_DOWN,
-    UiDown,
-  },
-  {
-    SCAN_PAGE_UP,
-    UiPageUp,
-  },
-  {
-    SCAN_PAGE_DOWN,
-    UiPageDown,
-  },
-  {
-    SCAN_ESC,
-    UiReset,
-  },
-  {
-    SCAN_F2,
-    UiPrevious,
-  },
-  {
-    SCAN_LEFT,
-    UiLeft,
-  },
-  {
-    SCAN_RIGHT,
-    UiRight,
-  },
-  {
-    SCAN_F9,
-    UiDefault,
-  },
-  {
-    SCAN_F10,
-    UiSave
-  }
-};
-
-SCREEN_OPERATION_T0_CONTROL_FLAG  gScreenOperationToControlFlag[] = {
-  {
-    UiNoOperation,
-    CfUiNoOperation,
-  },
-  {
-    UiDefault,
-    CfUiDefault,
-  },
-  {
-    UiSelect,
-    CfUiSelect,
-  },
-  {
-    UiUp,
-    CfUiUp,
-  },
-  {
-    UiDown,
-    CfUiDown,
-  },
-  {
-    UiLeft,
-    CfUiLeft,
-  },
-  {
-    UiRight,
-    CfUiRight,
-  },
-  {
-    UiReset,
-    CfUiReset,
-  },
-  {
-    UiSave,
-    CfUiSave,
-  },
-  {
-    UiPrevious,
-    CfUiPrevious,
-  },
-  {
-    UiPageUp,
-    CfUiPageUp,
-  },
-  {
-    UiPageDown,
-    CfUiPageDown
-  }
-};
-
-
-/**
-  Set Buffer to Value for Size bytes.
-
-  @param  Buffer                 Memory to set.
-  @param  Size                   Number of bytes to set
-  @param  Value                  Value of the set operation.
-
-  @return None
-
-**/
-VOID
-SetUnicodeMem (
-  IN VOID   *Buffer,
-  IN UINTN  Size,
-  IN CHAR16 Value
-  )
-{
-  CHAR16  *Ptr;
-
-  Ptr = Buffer;
-  while (Size--) {
-    *(Ptr++) = Value;
-  }
-}
-
-
-/**
-  Initialize Menu option list.
-
-  None.
-
-  @return None.
-
-**/
-VOID
-UiInitMenu (
-  VOID
-  )
-{
-  InitializeListHead (&Menu);
-}
-
-
-/**
-  Initialize Menu option list.
-
-  None.
-
-  @return None.
-
-**/
-VOID
-UiInitMenuList (
-  VOID
-  )
-{
-  InitializeListHead (&gMenuList);
-}
-
-
-/**
-  Remove a Menu in list, and return FormId/QuestionId for previous Menu.
-
-  @param  Selection              Menu selection.
-
-  @return None.
-
-**/
-VOID
-UiRemoveMenuListEntry (
-  IN OUT UI_MENU_SELECTION  *Selection
-  )
-{
-  UI_MENU_LIST  *UiMenuList;
-
-  if (!IsListEmpty (&gMenuList)) {
-    UiMenuList = CR (gMenuList.ForwardLink, UI_MENU_LIST, MenuLink, UI_MENU_LIST_SIGNATURE);
-
-    Selection->FormId = UiMenuList->FormId;
-    Selection->QuestionId = UiMenuList->QuestionId;
-    RemoveEntryList (&UiMenuList->MenuLink);
-    gBS->FreePool (UiMenuList);
-  }
-}
-
-
-/**
-  Free Menu option linked list.
-
-  None.
-
-  @return None.
-
-**/
-VOID
-UiFreeMenuList (
-  VOID
-  )
-{
-  UI_MENU_LIST  *UiMenuList;
-
-  while (!IsListEmpty (&gMenuList)) {
-    UiMenuList = CR (gMenuList.ForwardLink, UI_MENU_LIST, MenuLink, UI_MENU_LIST_SIGNATURE);
-    RemoveEntryList (&UiMenuList->MenuLink);
-    gBS->FreePool (UiMenuList);
-  }
-}
-
-
-/**
-  Add one menu entry to the linked lst
-
-  @param  Selection              Menu selection.
-
-  @return None.
-
-**/
-VOID
-UiAddMenuListEntry (
-  IN UI_MENU_SELECTION            *Selection
-  )
-{
-  UI_MENU_LIST  *UiMenuList;
-
-  UiMenuList = AllocateZeroPool (sizeof (UI_MENU_LIST));
-  ASSERT (UiMenuList != NULL);
-
-  UiMenuList->Signature = UI_MENU_LIST_SIGNATURE;
-  UiMenuList->FormId = Selection->FormId;
-  UiMenuList->QuestionId = Selection->QuestionId;
-
-  InsertHeadList (&gMenuList, &UiMenuList->MenuLink);
-}
-
-
-/**
-  Free Menu option linked list.
-
-  None.
-
-  @return None.
-
-**/
-VOID
-UiFreeMenu (
-  VOID
-  )
-{
-  UI_MENU_OPTION  *MenuOption;
-
-  while (!IsListEmpty (&Menu)) {
-    MenuOption = MENU_OPTION_FROM_LINK (Menu.ForwardLink);
-    RemoveEntryList (&MenuOption->Link);
-
-    //
-    // We allocated space for this description when we did a GetToken, free it here
-    //
-    if (MenuOption->Skip != 0) {
-      //
-      // For date/time, MenuOption->Description is shared by three Menu Options
-      // Data format :      [01/02/2004]      [11:22:33]
-      // Line number :        0  0    1         0  0  1
-      //
-      gBS->FreePool (MenuOption->Description);
-    }
-    gBS->FreePool (MenuOption);
-  }
-}
-
-
-/**
-  Free Menu option linked list.
-
-  None.
-
-  @return None.
-
-**/
-VOID
-UiFreeRefreshList (
-  VOID
-  )
-{
-  MENU_REFRESH_ENTRY  *OldMenuRefreshEntry;
-
-  while (gMenuRefreshHead != NULL) {
-    OldMenuRefreshEntry = gMenuRefreshHead->Next;
-    gBS->FreePool (gMenuRefreshHead);
-    gMenuRefreshHead = OldMenuRefreshEntry;
-  }
-
-  gMenuRefreshHead = NULL;
-}
-
-
-
-/**
-  Refresh screen.
-
-  None.
-
-  @return None.
-
-**/
-VOID
-RefreshForm (
-  VOID
-  )
-{
-  CHAR16                  *OptionString;
-  MENU_REFRESH_ENTRY      *MenuRefreshEntry;
-  UINTN                   Index;
-  UINTN                   Loop;
-  EFI_STATUS              Status;
-  UI_MENU_SELECTION       *Selection;
-  FORM_BROWSER_STATEMENT  *Question;
-
-  OptionString = NULL;
-
-  if (gMenuRefreshHead != NULL) {
-
-    MenuRefreshEntry = gMenuRefreshHead;
-
-    do {
-      gST->ConOut->SetAttribute (gST->ConOut, MenuRefreshEntry->CurrentAttribute);
-
-      Selection = MenuRefreshEntry->Selection;
-      Question = MenuRefreshEntry->MenuOption->ThisTag;
-
-      //
-      // Don't update Question being edited
-      //
-      if (Question != MenuRefreshEntry->Selection->Statement) {
-
-        Status = GetQuestionValue (Selection->FormSet, Selection->Form, Question, FALSE);
-        if (EFI_ERROR (Status)) {
-          return;
-        }
-
-        ProcessOptions (Selection, MenuRefreshEntry->MenuOption, FALSE, &OptionString);
-
-        if (OptionString != NULL) {
-          //
-          // If leading spaces on OptionString - remove the spaces
-          //
-          for (Index = 0; OptionString[Index] == L' '; Index++)
-            ;
-
-          for (Loop = 0; OptionString[Index] != CHAR_NULL; Index++) {
-            OptionString[Loop] = OptionString[Index];
-            Loop++;
-          }
-
-          OptionString[Loop] = CHAR_NULL;
-
-          PrintStringAt (MenuRefreshEntry->CurrentColumn, MenuRefreshEntry->CurrentRow, OptionString);
-          gBS->FreePool (OptionString);
-        }
-      }
-
-      MenuRefreshEntry = MenuRefreshEntry->Next;
-
-    } while (MenuRefreshEntry != NULL);
-  }
-}
-
-
-/**
-  Wait for a given event to fire, or for an optional timeout to expire.
-
-  @param  Event                  The event to wait for
-  @param  Timeout                An optional timeout value in 100 ns units.
-  @param  RefreshInterval        Menu refresh interval (in seconds).
-
-  @retval EFI_SUCCESS            Event fired before Timeout expired.
-  @retval EFI_TIME_OUT           Timout expired before Event fired.
-
-**/
-EFI_STATUS
-UiWaitForSingleEvent (
-  IN EFI_EVENT                Event,
-  IN UINT64                   Timeout, OPTIONAL
-  IN UINT8                    RefreshInterval OPTIONAL
-  )
-{
-  EFI_STATUS  Status;
-  UINTN       Index;
-  EFI_EVENT   TimerEvent;
-  EFI_EVENT   WaitList[2];
-
-  if (Timeout) {
-    //
-    // Create a timer event
-    //
-    Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
-    if (!EFI_ERROR (Status)) {
-      //
-      // Set the timer event
-      //
-      gBS->SetTimer (
-            TimerEvent,
-            TimerRelative,
-            Timeout
-            );
-
-      //
-      // Wait for the original event or the timer
-      //
-      WaitList[0] = Event;
-      WaitList[1] = TimerEvent;
-      Status      = gBS->WaitForEvent (2, WaitList, &Index);
-      gBS->CloseEvent (TimerEvent);
-
-      //
-      // If the timer expired, change the return to timed out
-      //
-      if (!EFI_ERROR (Status) && Index == 1) {
-        Status = EFI_TIMEOUT;
-      }
-    }
-  } else {
-    //
-    // Update screen every second
-    //
-    if (RefreshInterval == 0) {
-      Timeout = ONE_SECOND;
-    } else {
-      Timeout = RefreshInterval * ONE_SECOND;
-    }
-
-    do {
-      Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
-
-      //
-      // Set the timer event
-      //
-      gBS->SetTimer (
-            TimerEvent,
-            TimerRelative,
-            Timeout
-            );
-
-      //
-      // Wait for the original event or the timer
-      //
-      WaitList[0] = Event;
-      WaitList[1] = TimerEvent;
-      Status      = gBS->WaitForEvent (2, WaitList, &Index);
-
-      //
-      // If the timer expired, update anything that needs a refresh and keep waiting
-      //
-      if (!EFI_ERROR (Status) && Index == 1) {
-        Status = EFI_TIMEOUT;
-        if (RefreshInterval != 0) {
-          RefreshForm ();
-        }
-      }
-
-      gBS->CloseEvent (TimerEvent);
-    } while (Status == EFI_TIMEOUT);
-  }
-
-  return Status;
-}
-
-
-/**
-  Add one menu option by specified description and context.
-
-  @param  String                 String description for this option.
-  @param  Handle                 Hii handle for the package list.
-  @param  Statement              Statement of this Menu Option.
-  @param  NumberOfLines          Display lines for this Menu Option.
-  @param  MenuItemCount          The index for this Option in the Menu.
-
-  @return None.
-
-**/
-VOID
-UiAddMenuOption (
-  IN CHAR16                  *String,
-  IN EFI_HII_HANDLE          Handle,
-  IN FORM_BROWSER_STATEMENT  *Statement,
-  IN UINT16                  NumberOfLines,
-  IN UINT16                  MenuItemCount
-  )
-{
-  UI_MENU_OPTION  *MenuOption;
-  UINTN           Index;
-  UINTN           Count;
-
-  Count = 1;
-
-  if (Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) {
-    //
-    // Add three MenuOptions for Date/Time
-    // Data format :      [01/02/2004]      [11:22:33]
-    // Line number :        0  0    1         0  0  1
-    //
-    NumberOfLines = 0;
-    Count = 3;
-
-    if (Statement->Storage == NULL) {
-      //
-      // For RTC type of date/time, set default refresh interval to be 1 second
-      //
-      if (Statement->RefreshInterval == 0) {
-        Statement->RefreshInterval = 1;
-      }
-    }
-  }
-
-  for (Index = 0; Index < Count; Index++) {
-    MenuOption = AllocateZeroPool (sizeof (UI_MENU_OPTION));
-    ASSERT (MenuOption);
-
-    MenuOption->Signature   = UI_MENU_OPTION_SIGNATURE;
-    MenuOption->Description = String;
-    MenuOption->Handle      = Handle;
-    MenuOption->ThisTag     = Statement;
-    MenuOption->EntryNumber = MenuItemCount;
-
-    if (Index == 2) {
-      //
-      // Override LineNumber for the MenuOption in Date/Time sequence
-      //
-      MenuOption->Skip = 1;
-    } else {
-      MenuOption->Skip = NumberOfLines;
-    }
-    MenuOption->Sequence = Index;
-
-    if (Statement->GrayOutExpression != NULL) {
-      MenuOption->GrayOut = Statement->GrayOutExpression->Result.Value.b;
-    }
-
-    if ((Statement->ValueExpression != NULL) ||
-        (Statement->QuestionFlags & EFI_IFR_FLAG_READ_ONLY)) {
-      MenuOption->ReadOnly = TRUE;
-    }
-
-    InsertTailList (&Menu, &MenuOption->Link);
-  }
-}
-
-
-/**
-  Routine used to abstract a generic dialog interface and return the selected key or string
-
-  @param  NumberOfLines          The number of lines for the dialog box
-  @param  HotKey                 Defines whether a single character is parsed
-                                 (TRUE) and returned in KeyValue or a string is
-                                 returned in StringBuffer.  Two special characters
-                                 are considered when entering a string, a SCAN_ESC
-                                 and an CHAR_CARRIAGE_RETURN.  SCAN_ESC terminates
-                                 string input and returns
-  @param  MaximumStringSize      The maximum size in bytes of a typed in string
-                                 (each character is a CHAR16) and the minimum
-                                 string returned is two bytes
-  @param  StringBuffer           The passed in pointer to the buffer which will
-                                 hold the typed in string if HotKey is FALSE
-  @param  KeyValue               The EFI_KEY value returned if HotKey is TRUE..
-  @param  String                 Pointer to the first string in the list
-  @param  ...                    A series of (quantity == NumberOfLines) text
-                                 strings which will be used to construct the dialog
-                                 box
-
-  @retval EFI_SUCCESS            Displayed dialog and received user interaction
-  @retval EFI_INVALID_PARAMETER  One of the parameters was invalid (e.g.
-                                 (StringBuffer == NULL) && (HotKey == FALSE))
-  @retval EFI_DEVICE_ERROR       User typed in an ESC character to exit the routine
-
-**/
-EFI_STATUS
-CreateDialog (
-  IN  UINTN                       NumberOfLines,
-  IN  BOOLEAN                     HotKey,
-  IN  UINTN                       MaximumStringSize,
-  OUT CHAR16                      *StringBuffer,
-  OUT EFI_INPUT_KEY               *KeyValue,
-  IN  CHAR16                      *String,
-  ...
-  )
-{
-  VA_LIST       Marker;
-  UINTN         Count;
-  EFI_INPUT_KEY Key;
-  UINTN         LargestString;
-  CHAR16        *TempString;
-  CHAR16        *BufferedString;
-  CHAR16        *StackString;
-  CHAR16        KeyPad[2];
-  UINTN         Start;
-  UINTN         Top;
-  UINTN         Index;
-  EFI_STATUS    Status;
-  BOOLEAN       SelectionComplete;
-  UINTN         InputOffset;
-  UINTN         CurrentAttribute;
-  UINTN         DimensionsWidth;
-  UINTN         DimensionsHeight;
-
-  DimensionsWidth   = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
-  DimensionsHeight  = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;
-
-  SelectionComplete = FALSE;
-  InputOffset       = 0;
-  TempString        = AllocateZeroPool (MaximumStringSize * 2);
-  BufferedString    = AllocateZeroPool (MaximumStringSize * 2);
-  CurrentAttribute  = gST->ConOut->Mode->Attribute;
-
-  ASSERT (TempString);
-  ASSERT (BufferedString);
-
-  VA_START (Marker, String);
-
-  //
-  // Zero the outgoing buffer
-  //
-  ZeroMem (StringBuffer, MaximumStringSize);
-
-  if (HotKey) {
-    if (KeyValue == NULL) {
-      return EFI_INVALID_PARAMETER;
-    }
-  } else {
-    if (StringBuffer == NULL) {
-      return EFI_INVALID_PARAMETER;
-    }
-  }
-  //
-  // Disable cursor
-  //
-  gST->ConOut->EnableCursor (gST->ConOut, FALSE);
-
-  LargestString = (GetStringWidth (String) / 2);
-
-  if (*String == L' ') {
-    InputOffset = 1;
-  }
-  //
-  // Determine the largest string in the dialog box
-  // Notice we are starting with 1 since String is the first string
-  //
-  for (Count = 1; Count < NumberOfLines; Count++) {
-    StackString = VA_ARG (Marker, CHAR16 *);
-
-    if (StackString[0] == L' ') {
-      InputOffset = Count + 1;
-    }
-
-    if ((GetStringWidth (StackString) / 2) > LargestString) {
-      //
-      // Size of the string visually and subtract the width by one for the null-terminator
-      //
-      LargestString = (GetStringWidth (StackString) / 2);
-    }
-  }
-
-  Start = (DimensionsWidth - LargestString - 2) / 2 + gScreenDimensions.LeftColumn + 1;
-  Top   = ((DimensionsHeight - NumberOfLines - 2) / 2) + gScreenDimensions.TopRow - 1;
-
-  Count = 0;
-
-  //
-  // Display the Popup
-  //
-  CreateSharedPopUp (LargestString, NumberOfLines, &String);
-
-  //
-  // Take the first key typed and report it back?
-  //
-  if (HotKey) {
-    Status = WaitForKeyStroke (&Key);
-    ASSERT_EFI_ERROR (Status);
-    CopyMem (KeyValue, &Key, sizeof (EFI_INPUT_KEY));
-
-  } else {
-    do {
-      Status = WaitForKeyStroke (&Key);
-
-      switch (Key.UnicodeChar) {
-      case CHAR_NULL:
-        switch (Key.ScanCode) {
-        case SCAN_ESC:
-          gBS->FreePool (TempString);
-          gBS->FreePool (BufferedString);
-          gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);
-          gST->ConOut->EnableCursor (gST->ConOut, TRUE);
-          return EFI_DEVICE_ERROR;
-
-        default:
-          break;
-        }
-
-        break;
-
-      case CHAR_CARRIAGE_RETURN:
-        SelectionComplete = TRUE;
-        gBS->FreePool (TempString);
-        gBS->FreePool (BufferedString);
-        gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);
-        gST->ConOut->EnableCursor (gST->ConOut, TRUE);
-        return EFI_SUCCESS;
-        break;
-
-      case CHAR_BACKSPACE:
-        if (StringBuffer[0] != CHAR_NULL) {
-          for (Index = 0; StringBuffer[Index] != CHAR_NULL; Index++) {
-            TempString[Index] = StringBuffer[Index];
-          }
-          //
-          // Effectively truncate string by 1 character
-          //
-          TempString[Index - 1] = CHAR_NULL;
-          StrCpy (StringBuffer, TempString);
-        }
-
-      default:
-        //
-        // If it is the beginning of the string, don't worry about checking maximum limits
-        //
-        if ((StringBuffer[0] == CHAR_NULL) && (Key.UnicodeChar != CHAR_BACKSPACE)) {
-          StrnCpy (StringBuffer, &Key.UnicodeChar, 1);
-          StrnCpy (TempString, &Key.UnicodeChar, 1);
-        } else if ((GetStringWidth (StringBuffer) < MaximumStringSize) && (Key.UnicodeChar != CHAR_BACKSPACE)) {
-          KeyPad[0] = Key.UnicodeChar;
-          KeyPad[1] = CHAR_NULL;
-          StrCat (StringBuffer, KeyPad);
-          StrCat (TempString, KeyPad);
-        }
-        //
-        // If the width of the input string is now larger than the screen, we nee to
-        // adjust the index to start printing portions of the string
-        //
-        SetUnicodeMem (BufferedString, LargestString, L' ');
-
-        PrintStringAt (Start + 1, Top + InputOffset, BufferedString);
-
-        if ((GetStringWidth (StringBuffer) / 2) > (DimensionsWidth - 2)) {
-          Index = (GetStringWidth (StringBuffer) / 2) - DimensionsWidth + 2;
-        } else {
-          Index = 0;
-        }
-
-        for (Count = 0; Index + 1 < GetStringWidth (StringBuffer) / 2; Index++, Count++) {
-          BufferedString[Count] = StringBuffer[Index];
-        }
-
-        PrintStringAt (Start + 1, Top + InputOffset, BufferedString);
-        break;
-      }
-    } while (!SelectionComplete);
-  }
-
-  gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);
-  gST->ConOut->EnableCursor (gST->ConOut, TRUE);
-  return EFI_SUCCESS;
-}
-
-VOID
-CreateSharedPopUp (
-  IN  UINTN                       RequestedWidth,
-  IN  UINTN                       NumberOfLines,
-  IN  CHAR16                      **ArrayOfStrings
-  )
-{
-  UINTN   Index;
-  UINTN   Count;
-  CHAR16  Character;
-  UINTN   Start;
-  UINTN   End;
-  UINTN   Top;
-  UINTN   Bottom;
-  CHAR16  *String;
-  UINTN   DimensionsWidth;
-  UINTN   DimensionsHeight;
-
-  DimensionsWidth   = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
-  DimensionsHeight  = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;
-
-  Count = 0;
-
-  gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
-
-  if ((RequestedWidth + 2) > DimensionsWidth) {
-    RequestedWidth = DimensionsWidth - 2;
-  }
-
-  //
-  // Subtract the PopUp width from total Columns, allow for one space extra on
-  // each end plus a border.
-  //
-  Start     = (DimensionsWidth - RequestedWidth - 2) / 2 + gScreenDimensions.LeftColumn + 1;
-  End       = Start + RequestedWidth + 1;
-
-  Top       = ((DimensionsHeight - NumberOfLines - 2) / 2) + gScreenDimensions.TopRow - 1;
-  Bottom    = Top + NumberOfLines + 2;
-
-  Character = BOXDRAW_DOWN_RIGHT;
-  PrintCharAt (Start, Top, Character);
-  Character = BOXDRAW_HORIZONTAL;
-  for (Index = Start; Index + 2 < End; Index++) {
-    PrintChar (Character);
-  }
-
-  Character = BOXDRAW_DOWN_LEFT;
-  PrintChar (Character);
-  Character = BOXDRAW_VERTICAL;
-  for (Index = Top; Index + 2 < Bottom; Index++) {
-    String = ArrayOfStrings[Count];
-    Count++;
-
-    //
-    // This will clear the background of the line - we never know who might have been
-    // here before us.  This differs from the next clear in that it used the non-reverse
-    // video for normal printing.
-    //
-    if (GetStringWidth (String) / 2 > 1) {
-      ClearLines (Start, End, Index + 1, Index + 1, POPUP_TEXT | POPUP_BACKGROUND);
-    }
-
-    //
-    // Passing in a space results in the assumption that this is where typing will occur
-    //
-    if (String[0] == L' ') {
-      ClearLines (Start + 1, End - 1, Index + 1, Index + 1, POPUP_INVERSE_TEXT | POPUP_INVERSE_BACKGROUND);
-    }
-
-    //
-    // Passing in a NULL results in a blank space
-    //
-    if (String[0] == CHAR_NULL) {
-      ClearLines (Start, End, Index + 1, Index + 1, POPUP_TEXT | POPUP_BACKGROUND);
-    }
-
-    PrintStringAt (
-      ((DimensionsWidth - GetStringWidth (String) / 2) / 2) + gScreenDimensions.LeftColumn + 1,
-      Index + 1,
-      String
-      );
-    gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
-    PrintCharAt (Start, Index + 1, Character);
-    PrintCharAt (End - 1, Index + 1, Character);
-  }
-
-  Character = BOXDRAW_UP_RIGHT;
-  PrintCharAt (Start, Bottom - 1, Character);
-  Character = BOXDRAW_HORIZONTAL;
-  for (Index = Start; Index + 2 < End; Index++) {
-    PrintChar (Character);
-  }
-
-  Character = BOXDRAW_UP_LEFT;
-  PrintChar (Character);
-}
-
-VOID
-CreatePopUp (
-  IN  UINTN                       RequestedWidth,
-  IN  UINTN                       NumberOfLines,
-  IN  CHAR16                      *ArrayOfStrings,
-  ...
-  )
-{
-  CreateSharedPopUp (RequestedWidth, NumberOfLines, &ArrayOfStrings);
-}
-
-
-/**
-  Update status bar on the bottom of menu.
-
-  @param  MessageType            The type of message to be shown.
-  @param  Flags                  The flags in Question header.
-  @param  State                  Set or clear.
-
-  @return None.
-
-**/
-VOID
-UpdateStatusBar (
-  IN  UINTN                       MessageType,
-  IN  UINT8                       Flags,
-  IN  BOOLEAN                     State
-  )
-{
-  UINTN           Index;
-  STATIC BOOLEAN  InputError;
-  CHAR16          *NvUpdateMessage;
-  CHAR16          *InputErrorMessage;
-
-  NvUpdateMessage   = GetToken (STRING_TOKEN (NV_UPDATE_MESSAGE), gHiiHandle);
-  InputErrorMessage = GetToken (STRING_TOKEN (INPUT_ERROR_MESSAGE), gHiiHandle);
-
-  switch (MessageType) {
-  case INPUT_ERROR:
-    if (State) {
-      gST->ConOut->SetAttribute (gST->ConOut, ERROR_TEXT);
-      PrintStringAt (
-        gScreenDimensions.LeftColumn + gPromptBlockWidth,
-        gScreenDimensions.BottomRow - 1,
-        InputErrorMessage
-        );
-      InputError = TRUE;
-    } else {
-      gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT);
-      for (Index = 0; Index < (GetStringWidth (InputErrorMessage) - 2) / 2; Index++) {
-        PrintAt (gScreenDimensions.LeftColumn + gPromptBlockWidth + Index, gScreenDimensions.BottomRow - 1, L"  ");
-      }
-
-      InputError = FALSE;
-    }
-    break;
-
-  case NV_UPDATE_REQUIRED:
-    if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {
-      if (State) {
-        gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT);
-        PrintStringAt (
-          gScreenDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth,
-          gScreenDimensions.BottomRow - 1,
-          NvUpdateMessage
-          );
-        gResetRequired    = (BOOLEAN) (gResetRequired | ((Flags & EFI_IFR_FLAG_RESET_REQUIRED) == EFI_IFR_FLAG_RESET_REQUIRED));
-
-        gNvUpdateRequired = TRUE;
-      } else {
-        gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT);
-        for (Index = 0; Index < (GetStringWidth (NvUpdateMessage) - 2) / 2; Index++) {
-          PrintAt (
-            (gScreenDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + Index),
-            gScreenDimensions.BottomRow - 1,
-            L"  "
-            );
-        }
-
-        gNvUpdateRequired = FALSE;
-      }
-    }
-    break;
-
-  case REFRESH_STATUS_BAR:
-    if (InputError) {
-      UpdateStatusBar (INPUT_ERROR, Flags, TRUE);
-    }
-
-    if (gNvUpdateRequired) {
-      UpdateStatusBar (NV_UPDATE_REQUIRED, Flags, TRUE);
-    }
-    break;
-
-  default:
-    break;
-  }
-
-  gBS->FreePool (InputErrorMessage);
-  gBS->FreePool (NvUpdateMessage);
-  return ;
-}
-
-
-/**
-  Get the supported width for a particular op-code
-
-  @param  Statement              The FORM_BROWSER_STATEMENT structure passed in.
-  @param  Handle                 The handle in the HII database being used
-
-  @return Returns the number of CHAR16 characters that is support.
-
-**/
-UINT16
-GetWidth (
-  IN FORM_BROWSER_STATEMENT        *Statement,
-  IN EFI_HII_HANDLE                 Handle
-  )
-{
-  CHAR16  *String;
-  UINTN   Size;
-  UINT16  Width;
-
-  Size = 0;
-
-  //
-  // See if the second text parameter is really NULL
-  //
-  if ((Statement->Operand == EFI_IFR_TEXT_OP) && (Statement->TextTwo != 0)) {
-    String = GetToken (Statement->TextTwo, Handle);
-    Size   = StrLen (String);
-    gBS->FreePool (String);
-  }
-
-  if ((Statement->Operand == EFI_IFR_SUBTITLE_OP) ||
-      (Statement->Operand == EFI_IFR_REF_OP) ||
-      (Statement->Operand == EFI_IFR_PASSWORD_OP) ||
-      (Statement->Operand == EFI_IFR_ACTION_OP) ||
-      (Statement->Operand == EFI_IFR_RESET_BUTTON_OP) ||
-      //
-      // Allow a wide display if text op-code and no secondary text op-code
-      //
-      ((Statement->Operand == EFI_IFR_TEXT_OP) && (Size == 0))
-      ) {
-    Width = (UINT16) (gPromptBlockWidth + gOptionBlockWidth);
-  } else {
-    Width = (UINT16) gPromptBlockWidth;
-  }
-
-  if (Statement->InSubtitle) {
-    Width -= SUBTITLE_INDENT;
-  }
-
-  return Width;
-}
-
-
-/**
-  Will copy LineWidth amount of a string in the OutputString buffer and return the
-  number of CHAR16 characters that were copied into the OutputString buffer.
-
-  @param  InputString            String description for this option.
-  @param  LineWidth              Width of the desired string to extract in CHAR16
-                                 characters
-  @param  Index                  Where in InputString to start the copy process
-  @param  OutputString           Buffer to copy the string into
-
-  @return Returns the number of CHAR16 characters that were copied into the OutputString buffer.
-
-**/
-UINT16
-GetLineByWidth (
-  IN      CHAR16                      *InputString,
-  IN      UINT16                      LineWidth,
-  IN OUT  UINTN                       *Index,
-  OUT     CHAR16                      **OutputString
-  )
-{
-  static BOOLEAN  Finished;
-  UINT16          Count;
-  UINT16          Count2;
-
-  if (Finished) {
-    Finished = FALSE;
-    return (UINT16) 0;
-  }
-
-  Count         = LineWidth;
-  Count2        = 0;
-
-  *OutputString = AllocateZeroPool (((UINTN) (LineWidth + 1) * 2));
-
-  //
-  // Ensure we have got a valid buffer
-  //
-  if (*OutputString != NULL) {
-
-    //
-    //NARROW_CHAR can not be printed in screen, so if a line only contain  the two CHARs: 'NARROW_CHAR + CHAR_CARRIAGE_RETURN' , it is a empty line  in Screen.
-    //To avoid displaying this  empty line in screen,  just skip  the two CHARs here.
-    //
-   if ((InputString[*Index] == NARROW_CHAR) && (InputString[*Index + 1] == CHAR_CARRIAGE_RETURN)) {
-     *Index = *Index + 2;
-   }
-
-    //
-    // Fast-forward the string and see if there is a carriage-return in the string
-    //
-    for (; (InputString[*Index + Count2] != CHAR_CARRIAGE_RETURN) && (Count2 != LineWidth); Count2++)
-      ;
-
-    //
-    // Copy the desired LineWidth of data to the output buffer.
-    // Also make sure that we don't copy more than the string.
-    // Also make sure that if there are linefeeds, we account for them.
-    //
-    if ((StrSize (&InputString[*Index]) <= ((UINTN) (LineWidth + 1) * 2)) &&
-        (StrSize (&InputString[*Index]) <= ((UINTN) (Count2 + 1) * 2))
-        ) {
-      //
-      // Convert to CHAR16 value and show that we are done with this operation
-      //
-      LineWidth = (UINT16) ((StrSize (&InputString[*Index]) - 2) / 2);
-      if (LineWidth != 0) {
-        Finished = TRUE;
-      }
-    } else {
-      if (Count2 == LineWidth) {
-        //
-        // Rewind the string from the maximum size until we see a space to break the line
-        //
-        for (; (InputString[*Index + LineWidth] != CHAR_SPACE) && (LineWidth != 0); LineWidth--)
-          ;
-        if (LineWidth == 0) {
-          LineWidth = Count;
-        }
-      } else {
-        LineWidth = Count2;
-      }
-    }
-
-    CopyMem (*OutputString, &InputString[*Index], LineWidth * 2);
-
-    //
-    // If currently pointing to a space, increment the index to the first non-space character
-    //
-    for (;
-         (InputString[*Index + LineWidth] == CHAR_SPACE) || (InputString[*Index + LineWidth] == CHAR_CARRIAGE_RETURN);
-         (*Index)++
-        )
-      ;
-    *Index = (UINT16) (*Index + LineWidth);
-    return LineWidth;
-  } else {
-    return (UINT16) 0;
-  }
-}
-
-
-/**
-  Update display lines for a Menu Option.
-
-  @param  MenuOption             The MenuOption to be checked.
-
-  @retval TRUE                   This Menu Option is selectable.
-  @retval FALSE                  This Menu Option could not be selected.
-
-**/
-VOID
-UpdateOptionSkipLines (
-  IN UI_MENU_SELECTION            *Selection,
-  IN UI_MENU_OPTION               *MenuOption,
-  IN CHAR16                       **OptionalString,
-  IN UINTN                        SkipValue
-  )
-{
-  UINTN   Index;
-  UINT16  Width;
-  UINTN   Row;
-  UINTN   OriginalRow;
-  CHAR16  *OutputString;
-  CHAR16  *OptionString;
-
-  Row           = 0;
-  OptionString  = *OptionalString;
-  OutputString  = NULL;
-
-  ProcessOptions (Selection, MenuOption, FALSE, &OptionString);
-
-  if (OptionString != NULL) {
-    Width               = (UINT16) gOptionBlockWidth;
-
-    OriginalRow         = Row;
-
-    for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {
-      //
-      // If there is more string to process print on the next row and increment the Skip value
-      //
-      if (StrLen (&OptionString[Index])) {
-        if (SkipValue == 0) {
-          Row++;
-          //
-          // Since the Number of lines for this menu entry may or may not be reflected accurately
-          // since the prompt might be 1 lines and option might be many, and vice versa, we need to do
-          // some testing to ensure we are keeping this in-sync.
-          //
-          // If the difference in rows is greater than or equal to the skip value, increase the skip value
-          //
-          if ((Row - OriginalRow) >= MenuOption->Skip) {
-            MenuOption->Skip++;
-          }
-        }
-      }
-
-      gBS->FreePool (OutputString);
-      if (SkipValue != 0) {
-        SkipValue--;
-      }
-    }
-
-    Row = OriginalRow;
-  }
-
-  *OptionalString = OptionString;
-}
-
-
-/**
-  Check whether this Menu Option could be highlighted.
-
-  @param  MenuOption             The MenuOption to be checked.
-
-  @retval TRUE                   This Menu Option is selectable.
-  @retval FALSE                  This Menu Option could not be selected.
-
-**/
-STATIC
-BOOLEAN
-IsSelectable (
-  UI_MENU_OPTION   *MenuOption
-  )
-{
-  if ((MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP) ||
-      MenuOption->GrayOut || MenuOption->ReadOnly) {
-    return FALSE;
-  } else {
-    return TRUE;
-  }
-}
-
-
-/**
-  Determine if the menu is the last menu that can be selected.
-
-  @param  Direction              the scroll direction. False is down. True is up.
-
-  @return FALSE -- the menu isn't the last menu that can be selected.
-  @return TRUE  -- the menu is the last menu that can be selected.
-
-**/
-STATIC
-BOOLEAN
-ValueIsScroll (
-  IN  BOOLEAN                     Direction,
-  IN  LIST_ENTRY                  *CurrentPos
-  )
-{
-  LIST_ENTRY      *Temp;
-  UI_MENU_OPTION  *MenuOption;
-
-  Temp = Direction ? CurrentPos->BackLink : CurrentPos->ForwardLink;
-
-  if (Temp == &Menu) {
-    return TRUE;
-  }
-
-  for (; Temp != &Menu; Temp = Direction ? Temp->BackLink : Temp->ForwardLink) {
-    MenuOption = MENU_OPTION_FROM_LINK (Temp);
-    if (IsSelectable (MenuOption)) {
-      return FALSE;
-    }
-  }
-
-  return TRUE;
-}
-
-
-/**
-  Move to next selectable statement.
-
-  @param  GoUp                   The navigation direction. TRUE: up, FALSE: down.
-  @param  CurrentPosition        Current position.
-
-  @return The row distance from current MenuOption to next selectable MenuOption.
-
-**/
-STATIC
-INTN
-MoveToNextStatement (
-  IN     BOOLEAN                   GoUp,
-  IN OUT LIST_ENTRY                **CurrentPosition
-  )
-{
-  INTN             Distance;
-  LIST_ENTRY       *Pos;
-  BOOLEAN          HitEnd;
-  UI_MENU_OPTION   *NextMenuOption;
-
-  Distance = 0;
-  Pos      = *CurrentPosition;
-  HitEnd   = FALSE;
-
-  while (TRUE) {
-    NextMenuOption = MENU_OPTION_FROM_LINK (Pos);
-    if (IsSelectable (NextMenuOption)) {
-      break;
-    }
-    if ((GoUp ? Pos->BackLink : Pos->ForwardLink) == &Menu) {
-      HitEnd = TRUE;
-      break;
-    }
-    Distance += NextMenuOption->Skip;
-    Pos = (GoUp ? Pos->BackLink : Pos->ForwardLink);
-  }
-
-  if (HitEnd) {
-    //
-    // If we hit end there is still no statement can be focused,
-    // we go backwards to find the statement can be focused.
-    //
-    Distance = 0;
-    Pos = *CurrentPosition;
-
-    while (TRUE) {
-      NextMenuOption = MENU_OPTION_FROM_LINK (Pos);
-      if (IsSelectable (NextMenuOption)) {
-        break;
-      }
-      if ((!GoUp ? Pos->BackLink : Pos->ForwardLink) == &Menu) {
-        ASSERT (FALSE);
-        break;
-      }
-      Distance -= NextMenuOption->Skip;
-      Pos = (!GoUp ? Pos->BackLink : Pos->ForwardLink);
-    }
-  }
-
-  *CurrentPosition = &NextMenuOption->Link;
-  return Distance;
-}
-
-
-/**
-  Adjust Data and Time position accordingly.
-  Data format :      [01/02/2004]      [11:22:33]
-  Line number :        0  0    1         0  0  1
-
-  @param  DirectionUp            the up or down direction. False is down. True is
-                                 up.
-  @param  CurrentPosition        Current position. On return: Point to the last
-                                 Option (Year or Second) if up; Point to the first
-                                 Option (Month or Hour) if down.
-
-  @return Return line number to pad. It is possible that we stand on a zero-advance
-  @return data or time opcode, so pad one line when we judge if we are going to scroll outside.
-
-**/
-STATIC
-UINTN
-AdjustDateAndTimePosition (
-  IN     BOOLEAN                     DirectionUp,
-  IN OUT LIST_ENTRY                  **CurrentPosition
-  )
-{
-  UINTN           Count;
-  LIST_ENTRY      *NewPosition;
-  UI_MENU_OPTION  *MenuOption;
-  UINTN           PadLineNumber;
-
-  PadLineNumber = 0;
-  NewPosition   = *CurrentPosition;
-  MenuOption    = MENU_OPTION_FROM_LINK (NewPosition);
-
-  if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) ||
-      (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {
-    //
-    // Calculate the distance from current position to the last Date/Time MenuOption
-    //
-    Count = 0;
-    while (MenuOption->Skip == 0) {
-      Count++;
-      NewPosition   = NewPosition->ForwardLink;
-      MenuOption    = MENU_OPTION_FROM_LINK (NewPosition);
-      PadLineNumber = 1;
-    }
-
-    NewPosition = *CurrentPosition;
-    if (DirectionUp) {
-      //
-      // Since the behavior of hitting the up arrow on a Date/Time MenuOption is intended
-      // to be one that back to the previous set of MenuOptions, we need to advance to the first
-      // Date/Time MenuOption and leave the remaining logic in CfUiUp intact so the appropriate
-      // checking can be done.
-      //
-      while (Count++ < 2) {
-        NewPosition = NewPosition->BackLink;
-      }
-    } else {
-      //
-      // Since the behavior of hitting the down arrow on a Date/Time MenuOption is intended
-      // to be one that progresses to the next set of MenuOptions, we need to advance to the last
-      // Date/Time MenuOption and leave the remaining logic in CfUiDown intact so the appropriate
-      // checking can be done.
-      //
-      while (Count-- > 0) {
-        NewPosition = NewPosition->ForwardLink;
-      }
-    }
-
-    *CurrentPosition = NewPosition;
-  }
-
-  return PadLineNumber;
-}
-
-
-/**
-  Display menu and wait for user to select one menu option, then return it.
-  If AutoBoot is enabled, then if user doesn't select any option,
-  after period of time, it will automatically return the first menu option.
-
-
-  @return Return the pointer of the menu which selected,
-  @return otherwise return NULL.
-
-**/
-EFI_STATUS
-UiDisplayMenu (
-  IN OUT UI_MENU_SELECTION           *Selection
-  )
-{
-  INTN                            SkipValue;
-  INTN                            Difference;
-  INTN                            OldSkipValue;
-  UINTN                           DistanceValue;
-  UINTN                           Row;
-  UINTN                           Col;
-  UINTN                           Temp;
-  UINTN                           Temp2;
-  UINTN                           TopRow;
-  UINTN                           BottomRow;
-  UINTN                           OriginalRow;
-  UINTN                           Index;
-  UINT32                          Count;
-  UINT16                          Width;
-  CHAR16                          *StringPtr;
-  CHAR16                          *OptionString;
-  CHAR16                          *OutputString;
-  CHAR16                          *FormattedString;
-  CHAR16                          YesResponse;
-  CHAR16                          NoResponse;
-  BOOLEAN                         NewLine;
-  BOOLEAN                         Repaint;
-  BOOLEAN                         SavedValue;
-  EFI_STATUS                      Status;
-  EFI_INPUT_KEY                   Key;
-  LIST_ENTRY                      *Link;
-  LIST_ENTRY                      *NewPos;
-  LIST_ENTRY                      *TopOfScreen;
-  LIST_ENTRY                      *SavedListEntry;
-  UI_MENU_OPTION                  *MenuOption;
-  UI_MENU_OPTION                  *NextMenuOption;
-  UI_MENU_OPTION                  *SavedMenuOption;
-  UI_MENU_OPTION                  *PreviousMenuOption;
-  UI_CONTROL_FLAG                 ControlFlag;
-  EFI_SCREEN_DESCRIPTOR           LocalScreen;
-  MENU_REFRESH_ENTRY              *MenuRefreshEntry;
-  UI_SCREEN_OPERATION             ScreenOperation;
-  UINT8                           MinRefreshInterval;
-  UINTN                           BufferSize;
-  UINT16                          DefaultId;
-  EFI_DEVICE_PATH_PROTOCOL        *DevicePath;
-  FORM_BROWSER_STATEMENT          *Statement;
-
-  CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
-
-  Status              = EFI_SUCCESS;
-  FormattedString     = NULL;
-  OptionString        = NULL;
-  ScreenOperation     = UiNoOperation;
-  NewLine             = TRUE;
-  MinRefreshInterval  = 0;
-  DefaultId           = 0;
-
-  OutputString        = NULL;
-  gUpArrow            = FALSE;
-  gDownArrow          = FALSE;
-  SkipValue           = 0;
-  OldSkipValue        = 0;
-  MenuRefreshEntry    = gMenuRefreshHead;
-
-  NextMenuOption      = NULL;
-  PreviousMenuOption  = NULL;
-  SavedMenuOption     = NULL;
-
-  ZeroMem (&Key, sizeof (EFI_INPUT_KEY));
-
-  if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {
-    TopRow  = LocalScreen.TopRow + FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;
-    Row     = LocalScreen.TopRow + FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;
-  } else {
-    TopRow  = LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;
-    Row     = LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;
-  }
-
-  Col = LocalScreen.LeftColumn;
-  BottomRow = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT - SCROLL_ARROW_HEIGHT - 1;
-
-  Selection->TopRow = TopRow;
-  Selection->BottomRow = BottomRow;
-  Selection->PromptCol = Col;
-  Selection->OptionCol = gPromptBlockWidth + 1 + LocalScreen.LeftColumn;
-  Selection->Statement = NULL;
-
-  TopOfScreen = Menu.ForwardLink;
-  Repaint     = TRUE;
-  MenuOption  = NULL;
-
-  //
-  // Get user's selection
-  //
-  NewPos = Menu.ForwardLink;
-
-  gST->ConOut->EnableCursor (gST->ConOut, FALSE);
-  UpdateStatusBar (REFRESH_STATUS_BAR, (UINT8) 0, TRUE);
-
-  ControlFlag = CfInitialization;
-  Selection->Action = UI_ACTION_NONE;
-  while (TRUE) {
-    switch (ControlFlag) {
-    case CfInitialization:
-      if (IsListEmpty (&Menu)) {
-        ControlFlag = CfReadKey;
-      } else {
-        ControlFlag = CfCheckSelection;
-      }
-      break;
-
-    case CfCheckSelection:
-      if (Selection->Action != UI_ACTION_NONE) {
-        ControlFlag = CfExit;
-      } else {
-        ControlFlag = CfRepaint;
-      }
-      break;
-
-    case CfRepaint:
-      ControlFlag = CfRefreshHighLight;
-
-      if (Repaint) {
-        //
-        // Display menu
-        //
-        gDownArrow      = FALSE;
-        gUpArrow        = FALSE;
-        Row             = TopRow;
-
-        Temp            = SkipValue;
-        Temp2           = SkipValue;
-
-        ClearLines (
-          LocalScreen.LeftColumn,
-          LocalScreen.RightColumn,
-          TopRow - SCROLL_ARROW_HEIGHT,
-          BottomRow + SCROLL_ARROW_HEIGHT,
-          FIELD_TEXT | FIELD_BACKGROUND
-          );
-
-        UiFreeRefreshList ();
-        MinRefreshInterval = 0;
-
-        for (Link = TopOfScreen; Link != &Menu; Link = Link->ForwardLink) {
-          MenuOption          = MENU_OPTION_FROM_LINK (Link);
-          MenuOption->Row     = Row;
-          MenuOption->Col     = Col;
-          MenuOption->OptCol  = gPromptBlockWidth + 1 + LocalScreen.LeftColumn;
-
-          Statement = MenuOption->ThisTag;
-          if (Statement->InSubtitle) {
-            MenuOption->Col += SUBTITLE_INDENT;
-          }
-
-          if (MenuOption->GrayOut) {
-            gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_GRAYED | FIELD_BACKGROUND);
-          } else {
-            if (Statement->Operand == EFI_IFR_SUBTITLE_OP) {
-              gST->ConOut->SetAttribute (gST->ConOut, SUBTITLE_TEXT | FIELD_BACKGROUND);
-            }
-          }
-
-          Width       = GetWidth (Statement, MenuOption->Handle);
-          OriginalRow = Row;
-
-          for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {
-            if ((Temp == 0) && (Row <= BottomRow)) {
-              PrintStringAt (MenuOption->Col, Row, OutputString);
-            }
-            //
-            // If there is more string to process print on the next row and increment the Skip value
-            //
-            if (StrLen (&MenuOption->Description[Index])) {
-              if (Temp == 0) {
-                Row++;
-              }
-            }
-
-            gBS->FreePool (OutputString);
-            if (Temp != 0) {
-              Temp--;
-            }
-          }
-
-          Temp  = 0;
-          Row   = OriginalRow;
-
-          gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
-          ProcessOptions (Selection, MenuOption, FALSE, &OptionString);
-
-          if (OptionString != NULL) {
-            if (Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) {
-              //
-              // If leading spaces on OptionString - remove the spaces
-              //
-              for (Index = 0; OptionString[Index] == L' '; Index++) {
-                MenuOption->OptCol++;
-              }
-
-              for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {
-                OptionString[Count] = OptionString[Index];
-                Count++;
-              }
-
-              OptionString[Count] = CHAR_NULL;
-            }
-
-            //
-            // If Question request refresh, register the op-code
-            //
-            if (Statement->RefreshInterval != 0) {
-              //
-              // Menu will be refreshed at minimal interval of all Questions
-              // which have refresh request
-              //
-              if (MinRefreshInterval == 0 || Statement->RefreshInterval < MinRefreshInterval) {
-                MinRefreshInterval = Statement->RefreshInterval;
-              }
-
-              if (gMenuRefreshHead == NULL) {
-                MenuRefreshEntry = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));
-                ASSERT (MenuRefreshEntry != NULL);
-                MenuRefreshEntry->MenuOption        = MenuOption;
-                MenuRefreshEntry->Selection         = Selection;
-                MenuRefreshEntry->CurrentColumn     = MenuOption->OptCol;
-                MenuRefreshEntry->CurrentRow        = MenuOption->Row;
-                MenuRefreshEntry->CurrentAttribute  = FIELD_TEXT | FIELD_BACKGROUND;
-                gMenuRefreshHead                    = MenuRefreshEntry;
-              } else {
-                //
-                // Advance to the last entry
-                //
-                for (MenuRefreshEntry = gMenuRefreshHead;
-                     MenuRefreshEntry->Next != NULL;
-                     MenuRefreshEntry = MenuRefreshEntry->Next
-                    )
-                  ;
-                MenuRefreshEntry->Next = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));
-                ASSERT (MenuRefreshEntry->Next != NULL);
-                MenuRefreshEntry                    = MenuRefreshEntry->Next;
-                MenuRefreshEntry->MenuOption        = MenuOption;
-                MenuRefreshEntry->Selection         = Selection;
-                MenuRefreshEntry->CurrentColumn     = MenuOption->OptCol;
-                MenuRefreshEntry->CurrentRow        = MenuOption->Row;
-                MenuRefreshEntry->CurrentAttribute  = FIELD_TEXT | FIELD_BACKGROUND;
-              }
-            }
-
-            Width       = (UINT16) gOptionBlockWidth;
-            OriginalRow = Row;
-
-            for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {
-              if ((Temp2 == 0) && (Row <= BottomRow)) {
-                PrintStringAt (MenuOption->OptCol, Row, OutputString);
-              }
-              //
-              // If there is more string to process print on the next row and increment the Skip value
-              //
-              if (StrLen (&OptionString[Index])) {
-                if (Temp2 == 0) {
-                  Row++;
-                  //
-                  // Since the Number of lines for this menu entry may or may not be reflected accurately
-                  // since the prompt might be 1 lines and option might be many, and vice versa, we need to do
-                  // some testing to ensure we are keeping this in-sync.
-                  //
-                  // If the difference in rows is greater than or equal to the skip value, increase the skip value
-                  //
-                  if ((Row - OriginalRow) >= MenuOption->Skip) {
-                    MenuOption->Skip++;
-                  }
-                }
-              }
-
-              gBS->FreePool (OutputString);
-              if (Temp2 != 0) {
-                Temp2--;
-              }
-            }
-
-            Temp2 = 0;
-            Row   = OriginalRow;
-
-            gBS->FreePool (OptionString);
-          }
-          //
-          // If this is a text op with secondary text information
-          //
-          if ((Statement->Operand == EFI_IFR_TEXT_OP) && (Statement->TextTwo != 0)) {
-            StringPtr   = GetToken (Statement->TextTwo, MenuOption->Handle);
-
-            Width       = (UINT16) gOptionBlockWidth;
-            OriginalRow = Row;
-
-            for (Index = 0; GetLineByWidth (StringPtr, Width, &Index, &OutputString) != 0x0000;) {
-              if ((Temp == 0) && (Row <= BottomRow)) {
-                PrintStringAt (MenuOption->OptCol, Row, OutputString);
-              }
-              //
-              // If there is more string to process print on the next row and increment the Skip value
-              //
-              if (StrLen (&StringPtr[Index])) {
-                if (Temp2 == 0) {
-                  Row++;
-                  //
-                  // Since the Number of lines for this menu entry may or may not be reflected accurately
-                  // since the prompt might be 1 lines and option might be many, and vice versa, we need to do
-                  // some testing to ensure we are keeping this in-sync.
-                  //
-                  // If the difference in rows is greater than or equal to the skip value, increase the skip value
-                  //
-                  if ((Row - OriginalRow) >= MenuOption->Skip) {
-                    MenuOption->Skip++;
-                  }
-                }
-              }
-
-              gBS->FreePool (OutputString);
-              if (Temp2 != 0) {
-                Temp2--;
-              }
-            }
-
-            Row = OriginalRow;
-            gBS->FreePool (StringPtr);
-          }
-
-          //
-          // Need to handle the bottom of the display
-          //
-          if (MenuOption->Skip > 1) {
-            Row += MenuOption->Skip - SkipValue;
-            SkipValue = 0;
-          } else {
-            Row += MenuOption->Skip;
-          }
-
-          if (Row > BottomRow) {
-            if (!ValueIsScroll (FALSE, Link)) {
-              gDownArrow = TRUE;
-            }
-
-            Row = BottomRow + 1;
-            break;
-          }
-        }
-
-        if (!ValueIsScroll (TRUE, TopOfScreen)) {
-          gUpArrow = TRUE;
-        }
-
-        if (gUpArrow) {
-          gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND);
-          PrintAt (
-            LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,
-            TopRow - SCROLL_ARROW_HEIGHT,
-            L"%c",
-            ARROW_UP
-            );
-          gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
-        }
-
-        if (gDownArrow) {
-          gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND);
-          PrintAt (
-            LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,
-            BottomRow + SCROLL_ARROW_HEIGHT,
-            L"%c",
-            ARROW_DOWN
-            );
-          gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
-        }
-
-        MenuOption = NULL;
-      }
-      break;
-
-    case CfRefreshHighLight:
-      //
-      // MenuOption: Last menu option that need to remove hilight
-      //             MenuOption is set to NULL in Repaint
-      // NewPos:     Current menu option that need to hilight
-      //
-      ControlFlag = CfUpdateHelpString;
-
-      //
-      // Repaint flag is normally reset when finish processing CfUpdateHelpString. Temporarily
-      // reset Repaint flag because we may break halfway and skip CfUpdateHelpString processing.
-      //
-      SavedValue  = Repaint;
-      Repaint     = FALSE;
-
-      if (Selection->QuestionId != 0) {
-        NewPos = Menu.ForwardLink;
-        SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);
-
-        while (SavedMenuOption->ThisTag->QuestionId != Selection->QuestionId && NewPos->ForwardLink != &Menu) {
-          NewPos     = NewPos->ForwardLink;
-          SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);
-        }
-        if (SavedMenuOption->ThisTag->QuestionId == Selection->QuestionId) {
-          //
-          // Target Question found, find its MenuOption
-          //
-          Link = TopOfScreen;
-
-          for (Index = TopRow; Index <= BottomRow && Link != NewPos;) {
-            SavedMenuOption = MENU_OPTION_FROM_LINK (Link);
-            Index += SavedMenuOption->Skip;
-            Link = Link->ForwardLink;
-          }
-
-          if (Link != NewPos || Index > BottomRow) {
-            //
-            // NewPos is not in the current page, simply scroll page so that NewPos is in the end of the page
-            //
-            Link    = NewPos;
-            for (Index = TopRow; Index <= BottomRow; ) {
-              Link = Link->BackLink;
-              SavedMenuOption = MENU_OPTION_FROM_LINK (Link);
-              Index     += SavedMenuOption->Skip;
-            }
-            TopOfScreen     = Link->ForwardLink;
-
-            Repaint = TRUE;
-            NewLine = TRUE;
-            ControlFlag = CfRepaint;
-            break;
-          }
-        } else {
-          //
-          // Target Question not found, highlight the default menu option
-          //
-          NewPos = TopOfScreen;
-        }
-
-        Selection->QuestionId = 0;
-      }
-
-      if (NewPos != NULL && (MenuOption == NULL || NewPos != &MenuOption->Link)) {
-        if (MenuOption != NULL) {
-          //
-          // Remove highlight on last Menu Option
-          //
-          gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);
-          ProcessOptions (Selection, MenuOption, FALSE, &OptionString);
-          gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
-          if (OptionString != NULL) {
-            if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) ||
-                (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)
-               ) {
-              //
-              // If leading spaces on OptionString - remove the spaces
-              //
-              for (Index = 0; OptionString[Index] == L' '; Index++)
-                ;
-
-              for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {
-                OptionString[Count] = OptionString[Index];
-                Count++;
-              }
-
-              OptionString[Count] = CHAR_NULL;
-            }
-
-            Width               = (UINT16) gOptionBlockWidth;
-            OriginalRow         = MenuOption->Row;
-
-            for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {
-              if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {
-                PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);
-              }
-              //
-              // If there is more string to process print on the next row and increment the Skip value
-              //
-              if (StrLen (&OptionString[Index])) {
-                MenuOption->Row++;
-              }
-
-              gBS->FreePool (OutputString);
-            }
-
-            MenuOption->Row = OriginalRow;
-
-            gBS->FreePool (OptionString);
-          } else {
-            if (NewLine) {
-              if (MenuOption->GrayOut) {
-                gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_GRAYED | FIELD_BACKGROUND);
-              } else if (MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP) {
-                gST->ConOut->SetAttribute (gST->ConOut, SUBTITLE_TEXT | FIELD_BACKGROUND);
-              }
-
-              OriginalRow = MenuOption->Row;
-              Width       = GetWidth (MenuOption->ThisTag, MenuOption->Handle);
-
-              for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {
-                if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {
-                  PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString);
-                }
-                //
-                // If there is more string to process print on the next row and increment the Skip value
-                //
-                if (StrLen (&MenuOption->Description[Index])) {
-                  MenuOption->Row++;
-                }
-
-                gBS->FreePool (OutputString);
-              }
-
-              MenuOption->Row = OriginalRow;
-              gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
-            }
-          }
-        }
-
-        //
-        // This is only possible if we entered this page and the first menu option is
-        // a "non-menu" item.  In that case, force it UiDown
-        //
-        MenuOption = MENU_OPTION_FROM_LINK (NewPos);
-        if (!IsSelectable (MenuOption)) {
-          ASSERT (ScreenOperation == UiNoOperation);
-          ScreenOperation = UiDown;
-          ControlFlag     = CfScreenOperation;
-          break;
-        }
-
-        //
-        // This is the current selected statement
-        //
-        Statement = MenuOption->ThisTag;
-        Selection->Statement = Statement;
-
-        //
-        // Set reverse attribute
-        //
-        gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT);
-        gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);
-
-        //
-        // Assuming that we have a refresh linked-list created, lets annotate the
-        // appropriate entry that we are highlighting with its new attribute.  Just prior to this
-        // lets reset all of the entries' attribute so we do not get multiple highlights in he refresh
-        //
-        if (gMenuRefreshHead != NULL) {
-          for (MenuRefreshEntry = gMenuRefreshHead; MenuRefreshEntry != NULL; MenuRefreshEntry = MenuRefreshEntry->Next) {
-            MenuRefreshEntry->CurrentAttribute = FIELD_TEXT | FIELD_BACKGROUND;
-            if (MenuRefreshEntry->MenuOption == MenuOption) {
-              MenuRefreshEntry->CurrentAttribute = FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT;
-            }
-          }
-        }
-
-        ProcessOptions (Selection, MenuOption, FALSE, &OptionString);
-        if (OptionString != NULL) {
-          if (Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) {
-            //
-            // If leading spaces on OptionString - remove the spaces
-            //
-            for (Index = 0; OptionString[Index] == L' '; Index++)
-              ;
-
-            for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {
-              OptionString[Count] = OptionString[Index];
-              Count++;
-            }
-
-            OptionString[Count] = CHAR_NULL;
-          }
-          Width               = (UINT16) gOptionBlockWidth;
-
-          OriginalRow         = MenuOption->Row;
-
-          for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {
-            if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {
-              PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);
-            }
-            //
-            // If there is more string to process print on the next row and increment the Skip value
-            //
-            if (StrLen (&OptionString[Index])) {
-              MenuOption->Row++;
-            }
-
-            gBS->FreePool (OutputString);
-          }
-
-          MenuOption->Row = OriginalRow;
-
-          gBS->FreePool (OptionString);
-        } else {
-          if (NewLine) {
-            OriginalRow = MenuOption->Row;
-
-            Width       = GetWidth (Statement, MenuOption->Handle);
-
-            for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {
-              if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {
-                PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString);
-              }
-              //
-              // If there is more string to process print on the next row and increment the Skip value
-              //
-              if (StrLen (&MenuOption->Description[Index])) {
-                MenuOption->Row++;
-              }
-
-              gBS->FreePool (OutputString);
-            }
-
-            MenuOption->Row = OriginalRow;
-
-          }
-        }
-
-        if (((NewPos->ForwardLink != &Menu) && (ScreenOperation == UiDown)) ||
-            ((NewPos->BackLink != &Menu) && (ScreenOperation == UiUp)) ||
-            (ScreenOperation == UiNoOperation)
-            ) {
-          UpdateKeyHelp (MenuOption, FALSE);
-        }
-        //
-        // Clear reverse attribute
-        //
-        gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
-      }
-      //
-      // Repaint flag will be used when process CfUpdateHelpString, so restore its value
-      // if we didn't break halfway when process CfRefreshHighLight.
-      //
-      Repaint = SavedValue;
-      break;
-
-    case CfUpdateHelpString:
-      ControlFlag = CfPrepareToReadKey;
-
-        if ((Repaint || NewLine) && (gClassOfVfr != EFI_GENERAL_APPLICATION_SUBCLASS)) {
-        //
-        // Don't print anything if it is a NULL help token
-        //
-        if (MenuOption->ThisTag->Help == 0) {
-          StringPtr = L"\0";
-        } else {
-          StringPtr = GetToken (MenuOption->ThisTag->Help, MenuOption->Handle);
-        }
-
-        ProcessHelpString (StringPtr, &FormattedString, BottomRow - TopRow);
-
-        gST->ConOut->SetAttribute (gST->ConOut, HELP_TEXT | FIELD_BACKGROUND);
-
-        for (Index = 0; Index < BottomRow - TopRow; Index++) {
-          //
-          // Pad String with spaces to simulate a clearing of the previous line
-          //
-          for (; GetStringWidth (&FormattedString[Index * gHelpBlockWidth * 2]) / 2 < gHelpBlockWidth;) {
-            StrCat (&FormattedString[Index * gHelpBlockWidth * 2], L" ");
-          }
-
-          PrintStringAt (
-            LocalScreen.RightColumn - gHelpBlockWidth,
-            Index + TopRow,
-            &FormattedString[Index * gHelpBlockWidth * 2]
-            );
-        }
-      }
-      //
-      // Reset this flag every time we finish using it.
-      //
-      Repaint = FALSE;
-      NewLine = FALSE;
-      break;
-
-    case CfPrepareToReadKey:
-      ControlFlag = CfReadKey;
-      ScreenOperation = UiNoOperation;
-      break;
-
-    case CfReadKey:
-      ControlFlag = CfScreenOperation;
-
-      //
-      // Wait for user's selection
-      //
-      do {
-        Status = UiWaitForSingleEvent (gST->ConIn->WaitForKey, 0, MinRefreshInterval);
-      } while (Status == EFI_TIMEOUT);
-
-      if (Status == EFI_TIMEOUT) {
-        Key.UnicodeChar = CHAR_CARRIAGE_RETURN;
-      } else {
-        Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
-        //
-        // if we encounter error, continue to read another key in.
-        //
-        if (EFI_ERROR (Status)) {
-          ControlFlag = CfReadKey;
-          continue;
-        }
-      }
-
-      if (IsListEmpty (&Menu) && Key.UnicodeChar != CHAR_NULL) {
-        //
-        // If the screen has no menu items, and the user didn't select UiPrevious, or UiReset
-        //
-        break;
-      }
-
-      switch (Key.UnicodeChar) {
-      case CHAR_CARRIAGE_RETURN:
-        ScreenOperation = UiSelect;
-        gDirection      = 0;
-        break;
-
-      //
-      // We will push the adjustment of these numeric values directly to the input handler
-      //  NOTE: we won't handle manual input numeric
-      //
-      case '+':
-      case '-':
-        Statement = MenuOption->ThisTag;
-        if ((Statement->Operand == EFI_IFR_DATE_OP)
-          || (Statement->Operand == EFI_IFR_TIME_OP)
-          || ((Statement->Operand == EFI_IFR_NUMERIC_OP) && (Statement->Step != 0))
-        ){
-          if (Key.UnicodeChar == '+') {
-            gDirection = SCAN_RIGHT;
-          } else {
-            gDirection = SCAN_LEFT;
-          }
-          Status = ProcessOptions (Selection, MenuOption, TRUE, &OptionString);
-          SafeFreePool (OptionString);
-        }
-        break;
-
-      case '^':
-        ScreenOperation = UiUp;
-        break;
-
-      case 'V':
-      case 'v':
-        ScreenOperation = UiDown;
-        break;
-
-      case ' ':
-        if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {
-          if (MenuOption->ThisTag->Operand == EFI_IFR_CHECKBOX_OP && !MenuOption->GrayOut) {
-            ScreenOperation = UiSelect;
-          }
-        }
-        break;
-
-      case CHAR_NULL:
-        if (((Key.ScanCode == SCAN_F1) && ((gFunctionKeySetting & FUNCTION_ONE) != FUNCTION_ONE)) ||
-            ((Key.ScanCode == SCAN_F2) && ((gFunctionKeySetting & FUNCTION_TWO) != FUNCTION_TWO)) ||
-            ((Key.ScanCode == SCAN_F9) && ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE)) ||
-            ((Key.ScanCode == SCAN_F10) && ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN))
-            ) {
-          //
-          // If the function key has been disabled, just ignore the key.
-          //
-        } else {
-          for (Index = 0; Index < sizeof (gScanCodeToOperation) / sizeof (gScanCodeToOperation[0]); Index++) {
-            if (Key.ScanCode == gScanCodeToOperation[Index].ScanCode) {
-              if (Key.ScanCode == SCAN_F9) {
-                //
-                // Reset to standard default
-                //
-                DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
-              }
-              ScreenOperation = gScanCodeToOperation[Index].ScreenOperation;
-              break;
-            }
-          }
-        }
-        break;
-      }
-      break;
-
-    case CfScreenOperation:
-      if (ScreenOperation != UiPrevious && ScreenOperation != UiReset) {
-        //
-        // If the screen has no menu items, and the user didn't select UiPrevious, or UiReset
-        // ignore the selection and go back to reading keys.
-        //
-        if (IsListEmpty (&Menu)) {
-          ControlFlag = CfReadKey;
-          break;
-        }
-        //
-        // if there is nothing logical to place a cursor on, just move on to wait for a key.
-        //
-        for (Link = Menu.ForwardLink; Link != &Menu; Link = Link->ForwardLink) {
-          NextMenuOption = MENU_OPTION_FROM_LINK (Link);
-          if (IsSelectable (NextMenuOption)) {
-            break;
-          }
-        }
-
-        if (Link == &Menu) {
-          ControlFlag = CfPrepareToReadKey;
-          break;
-        }
-      } else if (ScreenOperation == UiReset) {
-        //
-        // Press ESC to exit FormSet
-        //
-        Selection->Action = UI_ACTION_EXIT;
-        Selection->Statement = NULL;
-      }
-
-      for (Index = 0;
-           Index < sizeof (gScreenOperationToControlFlag) / sizeof (gScreenOperationToControlFlag[0]);
-           Index++
-          ) {
-        if (ScreenOperation == gScreenOperationToControlFlag[Index].ScreenOperation) {
-          ControlFlag = gScreenOperationToControlFlag[Index].ControlFlag;
-          break;
-        }
-      }
-      break;
-
-    case CfUiPrevious:
-      ControlFlag = CfCheckSelection;
-
-      if (IsListEmpty (&gMenuList)) {
-        Selection->Action = UI_ACTION_NONE;
-        if (IsListEmpty (&Menu)) {
-          ControlFlag = CfReadKey;
-        }
-        break;
-      }
-
-      //
-      // Remove the Cached page entry
-      //
-      UiRemoveMenuListEntry (Selection);
-
-      Selection->Action = UI_ACTION_REFRESH_FORM;
-      Selection->Statement = NULL;
-      break;
-
-    case CfUiSelect:
-      ControlFlag = CfCheckSelection;
-
-      Statement = MenuOption->ThisTag;
-      if ((Statement->Operand == EFI_IFR_TEXT_OP) ||
-          (Statement->Operand == EFI_IFR_DATE_OP) ||
-          (Statement->Operand == EFI_IFR_TIME_OP) ||
-          (Statement->Operand == EFI_IFR_NUMERIC_OP && Statement->Step != 0)) {
-        break;
-      }
-
-      //
-      // Keep highlight on current MenuOption
-      //
-      Selection->QuestionId = Statement->QuestionId;
-
-      switch (Statement->Operand) {
-      case EFI_IFR_REF_OP:
-        if (Statement->RefDevicePath != 0) {
-          //
-          // Goto another Hii Package list
-          //
-          ControlFlag = CfUiReset;
-          Selection->Action = UI_ACTION_REFRESH_FORMSET;
-
-          StringPtr = GetToken (Statement->RefDevicePath, Selection->FormSet->HiiHandle);
-          if (StringPtr == NULL) {
-            //
-            // No device path string not found, exit
-            //
-            Selection->Action = UI_ACTION_EXIT;
-            Selection->Statement = NULL;
-            break;
-          }
-          BufferSize = StrLen (StringPtr) / 2;
-          DevicePath = AllocatePool (BufferSize);
-
-          HexStringToBuffer ((UINT8 *) DevicePath, &BufferSize, StringPtr);
-          Selection->Handle = HiiLibDevicePathToHiiHandle (DevicePath);
-          if (Selection->Handle == NULL) {
-            //
-            // If target Hii Handle not found, exit
-            //
-            Selection->Action = UI_ACTION_EXIT;
-            Selection->Statement = NULL;
-            break;
-          }
-
-          gBS->FreePool (StringPtr);
-          gBS->FreePool (DevicePath);
-
-          CopyMem (&Selection->FormSetGuid, &Statement->RefFormSetId, sizeof (EFI_GUID));
-          Selection->FormId = Statement->RefFormId;
-          Selection->QuestionId = Statement->RefQuestionId;
-        } else if (!CompareGuid (&Statement->RefFormSetId, &gZeroGuid)) {
-          //
-          // Goto another Formset, check for uncommitted data
-          //
-          ControlFlag = CfUiReset;
-          Selection->Action = UI_ACTION_REFRESH_FORMSET;
-
-          CopyMem (&Selection->FormSetGuid, &Statement->RefFormSetId, sizeof (EFI_GUID));
-          Selection->FormId = Statement->RefFormId;
-          Selection->QuestionId = Statement->RefQuestionId;
-        } else if (Statement->RefFormId != 0) {
-          //
-          // Goto another form inside this formset,
-          //
-          Selection->Action = UI_ACTION_REFRESH_FORM;
-
-          //
-          // Link current form so that we can always go back when someone hits the UiPrevious
-          //
-          UiAddMenuListEntry (Selection);
-
-          Selection->FormId = Statement->RefFormId;
-          Selection->QuestionId = Statement->RefQuestionId;
-        } else if (Statement->RefQuestionId != 0) {
-          //
-          // Goto another Question
-          //
-          Selection->QuestionId = Statement->RefQuestionId;
-
-          if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK)) {
-            Selection->Action = UI_ACTION_REFRESH_FORM;
-          } else {
-            Repaint = TRUE;
-            NewLine = TRUE;
-            break;
-          }
-        }
-        break;
-
-      case EFI_IFR_ACTION_OP:
-        //
-        // Process the Config string <ConfigResp>
-        //
-        Status = ProcessQuestionConfig (Selection, Statement);
-
-        if (EFI_ERROR (Status)) {
-          break;
-        }
-
-        //
-        // The action button may change some Question value, so refresh the form
-        //
-        Selection->Action = UI_ACTION_REFRESH_FORM;
-        break;
-
-      case EFI_IFR_RESET_BUTTON_OP:
-        //
-        // Reset Question to default value specified by DefaultId
-        //
-        ControlFlag = CfUiDefault;
-        DefaultId = Statement->DefaultId;
-        break;
-
-      default:
-        //
-        // Editable Questions: oneof, ordered list, checkbox, numeric, string, password
-        //
-        UpdateKeyHelp (MenuOption, TRUE);
-        Status = ProcessOptions (Selection, MenuOption, TRUE, &OptionString);
-
-        if (EFI_ERROR (Status)) {
-          Repaint = TRUE;
-          NewLine = TRUE;
-          break;
-        }
-
-        if (OptionString != NULL) {
-          PrintStringAt (LocalScreen.LeftColumn + gPromptBlockWidth + 1, MenuOption->Row, OptionString);
-          gBS->FreePool (OptionString);
-        }
-
-        Selection->Action = UI_ACTION_REFRESH_FORM;
-        break;
-      }
-      break;
-
-    case CfUiReset:
-      //
-      // We are going to leave current FormSet, so check uncommited data in this FormSet
-      //
-      ControlFlag = CfCheckSelection;
-
-      if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {
-        //
-        // There is no parent menu for FrontPage
-        //
-        Selection->Action = UI_ACTION_NONE;
-        Selection->Statement = MenuOption->ThisTag;
-        break;
-      }
-
-      //
-      // If NV flag is up, prompt user
-      //
-      if (gNvUpdateRequired) {
-        Status      = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
-
-        YesResponse = gYesResponse[0];
-        NoResponse  = gNoResponse[0];
-
-        do {
-          CreateDialog (3, TRUE, 0, NULL, &Key, gEmptyString, gAreYouSure, gEmptyString);
-        } while
-        (
-          (Key.ScanCode != SCAN_ESC) &&
-          ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (NoResponse | UPPER_LOWER_CASE_OFFSET)) &&
-          ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (YesResponse | UPPER_LOWER_CASE_OFFSET))
-        );
-
-        //
-        // If the user hits the YesResponse key
-        //
-        if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse | UPPER_LOWER_CASE_OFFSET)) {
-        } else {
-          Repaint = TRUE;
-          NewLine = TRUE;
-
-          Selection->Action = UI_ACTION_NONE;
-          break;
-        }
-      }
-
-      gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
-      gST->ConOut->EnableCursor (gST->ConOut, TRUE);
-
-      UiFreeMenuList ();
-      gST->ConOut->ClearScreen (gST->ConOut);
-      return EFI_SUCCESS;
-
-    case CfUiLeft:
-      ControlFlag = CfCheckSelection;
-      if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {
-        if (MenuOption->Sequence != 0) {
-          //
-          // In the middle or tail of the Date/Time op-code set, go left.
-          //
-          NewPos = NewPos->BackLink;
-        }
-      }
-      break;
-
-    case CfUiRight:
-      ControlFlag = CfCheckSelection;
-      if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {
-        if (MenuOption->Sequence != 2) {
-          //
-          // In the middle or tail of the Date/Time op-code set, go left.
-          //
-          NewPos = NewPos->ForwardLink;
-        }
-      }
-      break;
-
-    case CfUiUp:
-      ControlFlag = CfCheckSelection;
-
-      SavedListEntry = TopOfScreen;
-
-      if (NewPos->BackLink != &Menu) {
-        NewLine = TRUE;
-        //
-        // Adjust Date/Time position before we advance forward.
-        //
-        AdjustDateAndTimePosition (TRUE, &NewPos);
-
-        //
-        // Caution that we have already rewind to the top, don't go backward in this situation.
-        //
-        if (NewPos->BackLink != &Menu) {
-          NewPos = NewPos->BackLink;
-        }
-
-        PreviousMenuOption = MENU_OPTION_FROM_LINK (NewPos);
-        DistanceValue = PreviousMenuOption->Skip;
-
-        //
-        // Since the behavior of hitting the up arrow on a Date/Time op-code is intended
-        // to be one that back to the previous set of op-codes, we need to advance to the sencond
-        // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate
-        // checking can be done.
-        //
-        DistanceValue += AdjustDateAndTimePosition (TRUE, &NewPos);
-
-        //
-        // Check the previous menu entry to see if it was a zero-length advance.  If it was,
-        // don't worry about a redraw.
-        //
-        if ((INTN) MenuOption->Row - (INTN) DistanceValue < (INTN) TopRow) {
-          Repaint     = TRUE;
-          TopOfScreen = NewPos;
-        }
-
-        Difference = MoveToNextStatement (TRUE, &NewPos);
-        if ((INTN) MenuOption->Row - (INTN) DistanceValue < (INTN) TopRow) {
-          if (Difference > 0) {
-            //
-            // Previous focus MenuOption is above the TopOfScreen, so we need to scroll
-            //
-            TopOfScreen = NewPos;
-            Repaint     = TRUE;
-          }
-        }
-        if (Difference < 0) {
-          //
-          // We want to goto previous MenuOption, but finally we go down.
-          // it means that we hit the begining MenuOption that can be focused
-          // so we simply scroll to the top
-          //
-          if (SavedListEntry != Menu.ForwardLink) {
-            TopOfScreen = Menu.ForwardLink;
-            Repaint     = TRUE;
-          }
-        }
-
-        //
-        // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
-        //
-        AdjustDateAndTimePosition (TRUE, &TopOfScreen);
-
-        UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);
-      } else {
-        SavedMenuOption = MenuOption;
-        MenuOption      = MENU_OPTION_FROM_LINK (NewPos);
-        if (!IsSelectable (MenuOption)) {
-          //
-          // If we are at the end of the list and sitting on a text op, we need to more forward
-          //
-          ScreenOperation = UiDown;
-          ControlFlag     = CfScreenOperation;
-          break;
-        }
-
-        MenuOption = SavedMenuOption;
-      }
-      break;
-
-    case CfUiPageUp:
-      ControlFlag     = CfCheckSelection;
-
-      if (NewPos->BackLink == &Menu) {
-        NewLine = FALSE;
-        Repaint = FALSE;
-        break;
-      }
-
-      NewLine   = TRUE;
-      Repaint   = TRUE;
-      Link      = TopOfScreen;
-      PreviousMenuOption = MENU_OPTION_FROM_LINK (Link);
-      Index = BottomRow;
-      while ((Index >= TopRow) && (Link->BackLink != &Menu)) {
-        Index = Index - PreviousMenuOption->Skip;
-        Link = Link->BackLink;
-        PreviousMenuOption = MENU_OPTION_FROM_LINK (Link);
-      }
-
-      TopOfScreen = Link;
-      Difference = MoveToNextStatement (TRUE, &Link);
-      if (Difference > 0) {
-        //
-        // The focus MenuOption is above the TopOfScreen
-        //
-        TopOfScreen = Link;
-      } else if (Difference < 0) {
-        //
-        // This happens when there is no MenuOption can be focused from
-        // Current MenuOption to the first MenuOption
-        //
-        TopOfScreen = Menu.ForwardLink;
-      }
-      Index += Difference;
-      if (Index < TopRow) {
-        MenuOption = NULL;
-      }
-
-      if (NewPos == Link) {
-        Repaint = FALSE;
-        NewLine = FALSE;
-      } else {
-        NewPos = Link;
-      }
-
-      //
-      // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
-      // Don't do this when we are already in the first page.
-      //
-      AdjustDateAndTimePosition (TRUE, &TopOfScreen);
-      AdjustDateAndTimePosition (TRUE, &NewPos);
-      break;
-
-    case CfUiPageDown:
-      ControlFlag     = CfCheckSelection;
-
-      if (NewPos->ForwardLink == &Menu) {
-        NewLine = FALSE;
-        Repaint = FALSE;
-        break;
-      }
-
-      NewLine = TRUE;
-      Repaint = TRUE;
-      Link    = TopOfScreen;
-      NextMenuOption = MENU_OPTION_FROM_LINK (Link);
-      Index = TopRow;
-      while ((Index <= BottomRow) && (Link->ForwardLink != &Menu)) {
-        Index = Index + NextMenuOption->Skip;
-        Link           = Link->ForwardLink;
-        NextMenuOption = MENU_OPTION_FROM_LINK (Link);
-      }
-
-      Index += MoveToNextStatement (FALSE, &Link);
-      if (Index > BottomRow) {
-        //
-        // There are more MenuOption needing scrolling
-        //
-        TopOfScreen = Link;
-        MenuOption = NULL;
-      }
-      if (NewPos == Link && Index <= BottomRow) {
-        //
-        // Finally we know that NewPos is the last MenuOption can be focused.
-        //
-        NewLine = FALSE;
-        Repaint = FALSE;
-      } else {
-        NewPos  = Link;
-      }
-
-      //
-      // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
-      // Don't do this when we are already in the last page.
-      //
-      AdjustDateAndTimePosition (TRUE, &TopOfScreen);
-      AdjustDateAndTimePosition (TRUE, &NewPos);
-      break;
-
-    case CfUiDown:
-      ControlFlag = CfCheckSelection;
-      //
-      // Since the behavior of hitting the down arrow on a Date/Time op-code is intended
-      // to be one that progresses to the next set of op-codes, we need to advance to the last
-      // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate
-      // checking can be done.  The only other logic we need to introduce is that if a Date/Time
-      // op-code is the last entry in the menu, we need to rewind back to the first op-code of
-      // the Date/Time op-code.
-      //
-      SavedListEntry = NewPos;
-      DistanceValue  = AdjustDateAndTimePosition (FALSE, &NewPos);
-
-      if (NewPos->ForwardLink != &Menu) {
-        MenuOption      = MENU_OPTION_FROM_LINK (NewPos);
-        NewLine         = TRUE;
-        NewPos          = NewPos->ForwardLink;
-        NextMenuOption  = MENU_OPTION_FROM_LINK (NewPos);
-
-        DistanceValue  += NextMenuOption->Skip;
-        DistanceValue  += MoveToNextStatement (FALSE, &NewPos);
-        //
-        // An option might be multi-line, so we need to reflect that data in the overall skip value
-        //
-        UpdateOptionSkipLines (Selection, NextMenuOption, &OptionString, SkipValue);
-
-        Temp = MenuOption->Row + MenuOption->Skip + DistanceValue - 1;
-        if ((MenuOption->Row + MenuOption->Skip == BottomRow + 1) &&
-            (NextMenuOption->ThisTag->Operand == EFI_IFR_DATE_OP ||
-             NextMenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)
-            ) {
-          Temp ++;
-        }
-
-        //
-        // If we are going to scroll, update TopOfScreen
-        //
-        if (Temp > BottomRow) {
-          do {
-            //
-            // Is the current top of screen a zero-advance op-code?
-            // If so, keep moving forward till we hit a >0 advance op-code
-            //
-            SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);
-
-            //
-            // If bottom op-code is more than one line or top op-code is more than one line
-            //
-            if ((DistanceValue > 1) || (MenuOption->Skip > 1)) {
-              //
-              // Is the bottom op-code greater than or equal in size to the top op-code?
-              //
-              if ((Temp - BottomRow) >= (SavedMenuOption->Skip - OldSkipValue)) {
-                //
-                // Skip the top op-code
-                //
-                TopOfScreen     = TopOfScreen->ForwardLink;
-                Difference      = (Temp - BottomRow) - (SavedMenuOption->Skip - OldSkipValue);
-
-                OldSkipValue    = Difference;
-
-                SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);
-
-                //
-                // If we have a remainder, skip that many more op-codes until we drain the remainder
-                //
-                for (;
-                     Difference >= (INTN) SavedMenuOption->Skip;
-                     Difference = Difference - (INTN) SavedMenuOption->Skip
-                    ) {
-                  //
-                  // Since the Difference is greater than or equal to this op-code's skip value, skip it
-                  //
-                  TopOfScreen     = TopOfScreen->ForwardLink;
-                  SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);
-                  if (Difference < (INTN) SavedMenuOption->Skip) {
-                    Difference = SavedMenuOption->Skip - Difference - 1;
-                    break;
-                  } else {
-                    if (Difference == (INTN) SavedMenuOption->Skip) {
-                      TopOfScreen     = TopOfScreen->ForwardLink;
-                      SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);
-                      Difference      = SavedMenuOption->Skip - Difference;
-                      break;
-                    }
-                  }
-                }
-                //
-                // Since we will act on this op-code in the next routine, and increment the
-                // SkipValue, set the skips to one less than what is required.
-                //
-                SkipValue = Difference - 1;
-
-              } else {
-                //
-                // Since we will act on this op-code in the next routine, and increment the
-                // SkipValue, set the skips to one less than what is required.
-                //
-                SkipValue = OldSkipValue + (Temp - BottomRow) - 1;
-              }
-            } else {
-              if ((OldSkipValue + 1) == (INTN) SavedMenuOption->Skip) {
-                TopOfScreen = TopOfScreen->ForwardLink;
-                break;
-              } else {
-                SkipValue = OldSkipValue;
-              }
-            }
-            //
-            // If the op-code at the top of the screen is more than one line, let's not skip it yet
-            // Let's set a skip flag to smoothly scroll the top of the screen.
-            //
-            if (SavedMenuOption->Skip > 1) {
-              if (SavedMenuOption == NextMenuOption) {
-                SkipValue = 0;
-              } else {
-                SkipValue++;
-              }
-            } else {
-              SkipValue   = 0;
-              TopOfScreen = TopOfScreen->ForwardLink;
-            }
-          } while (SavedMenuOption->Skip == 0);
-
-          Repaint       = TRUE;
-          OldSkipValue  = SkipValue;
-        }
-
-        MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);
-
-        UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);
-
-      } else {
-        SavedMenuOption = MenuOption;
-        MenuOption      = MENU_OPTION_FROM_LINK (NewPos);
-        if (!IsSelectable (MenuOption)) {
-          //
-          // If we are at the end of the list and sitting on a text op, we need to more forward
-          //
-          ScreenOperation = UiUp;
-          ControlFlag     = CfScreenOperation;
-          break;
-        }
-
-        MenuOption = SavedMenuOption;
-        //
-        // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.
-        //
-        AdjustDateAndTimePosition (TRUE, &NewPos);
-      }
-      break;
-
-    case CfUiSave:
-      ControlFlag = CfCheckSelection;
-
-      //
-      // Submit the form
-      //
-      Status = SubmitForm (Selection->FormSet, Selection->Form);
-
-      if (!EFI_ERROR (Status)) {
-        UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);
-        UpdateStatusBar (NV_UPDATE_REQUIRED, MenuOption->ThisTag->QuestionFlags, FALSE);
-      } else {
-        do {
-          CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gSaveFailed, gPressEnter, gEmptyString);
-        } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
-
-        Repaint = TRUE;
-        NewLine = TRUE;
-      }
-      break;
-
-    case CfUiDefault:
-      ControlFlag = CfCheckSelection;
-
-      Status = ExtractFormDefault (Selection->FormSet, Selection->Form, DefaultId);
-
-      if (!EFI_ERROR (Status)) {
-        Selection->Action = UI_ACTION_REFRESH_FORM;
-
-        //
-        // Show NV update flag on status bar
-        //
-        gNvUpdateRequired = TRUE;
-      }
-      break;
-
-    case CfUiNoOperation:
-      ControlFlag = CfCheckSelection;
-      break;
-
-    case CfExit:
-      UiFreeRefreshList ();
-
-      gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
-      gST->ConOut->SetCursorPosition (gST->ConOut, 0, Row + 4);
-      gST->ConOut->EnableCursor (gST->ConOut, TRUE);
-      gST->ConOut->OutputString (gST->ConOut, L"\n");
-
-      return EFI_SUCCESS;
-
-    default:
-      break;
-    }
-  }
-}
+/** @file\r
+Utility functions for User Interface functions.\r
+\r
+Copyright (c) 2004 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "Ui.h"\r
+#include "Setup.h"\r
+\r
+LIST_ENTRY          Menu;\r
+LIST_ENTRY          gMenuList;\r
+MENU_REFRESH_ENTRY  *gMenuRefreshHead;\r
+\r
+//\r
+// Search table for UiDisplayMenu()\r
+//\r
+SCAN_CODE_TO_SCREEN_OPERATION     gScanCodeToOperation[] = {\r
+  {\r
+    SCAN_UP,\r
+    UiUp,\r
+  },\r
+  {\r
+    SCAN_DOWN,\r
+    UiDown,\r
+  },\r
+  {\r
+    SCAN_PAGE_UP,\r
+    UiPageUp,\r
+  },\r
+  {\r
+    SCAN_PAGE_DOWN,\r
+    UiPageDown,\r
+  },\r
+  {\r
+    SCAN_ESC,\r
+    UiReset,\r
+  },\r
+  {\r
+    SCAN_F2,\r
+    UiPrevious,\r
+  },\r
+  {\r
+    SCAN_LEFT,\r
+    UiLeft,\r
+  },\r
+  {\r
+    SCAN_RIGHT,\r
+    UiRight,\r
+  },\r
+  {\r
+    SCAN_F9,\r
+    UiDefault,\r
+  },\r
+  {\r
+    SCAN_F10,\r
+    UiSave\r
+  }\r
+};\r
+\r
+SCREEN_OPERATION_T0_CONTROL_FLAG  gScreenOperationToControlFlag[] = {\r
+  {\r
+    UiNoOperation,\r
+    CfUiNoOperation,\r
+  },\r
+  {\r
+    UiDefault,\r
+    CfUiDefault,\r
+  },\r
+  {\r
+    UiSelect,\r
+    CfUiSelect,\r
+  },\r
+  {\r
+    UiUp,\r
+    CfUiUp,\r
+  },\r
+  {\r
+    UiDown,\r
+    CfUiDown,\r
+  },\r
+  {\r
+    UiLeft,\r
+    CfUiLeft,\r
+  },\r
+  {\r
+    UiRight,\r
+    CfUiRight,\r
+  },\r
+  {\r
+    UiReset,\r
+    CfUiReset,\r
+  },\r
+  {\r
+    UiSave,\r
+    CfUiSave,\r
+  },\r
+  {\r
+    UiPrevious,\r
+    CfUiPrevious,\r
+  },\r
+  {\r
+    UiPageUp,\r
+    CfUiPageUp,\r
+  },\r
+  {\r
+    UiPageDown,\r
+    CfUiPageDown\r
+  }\r
+};\r
+\r
+\r
+/**\r
+  Set Buffer to Value for Size bytes.\r
+\r
+  @param  Buffer                 Memory to set.\r
+  @param  Size                   Number of bytes to set\r
+  @param  Value                  Value of the set operation.\r
+\r
+**/\r
+VOID\r
+SetUnicodeMem (\r
+  IN VOID   *Buffer,\r
+  IN UINTN  Size,\r
+  IN CHAR16 Value\r
+  )\r
+{\r
+  CHAR16  *Ptr;\r
+\r
+  Ptr = Buffer;\r
+  while ((Size--)  != 0) {\r
+    *(Ptr++) = Value;\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Initialize Menu option list.\r
+\r
+**/\r
+VOID\r
+UiInitMenu (\r
+  VOID\r
+  )\r
+{\r
+  InitializeListHead (&Menu);\r
+}\r
+\r
+\r
+/**\r
+  Initialize Menu option list.\r
+\r
+**/\r
+VOID\r
+UiInitMenuList (\r
+  VOID\r
+  )\r
+{\r
+  InitializeListHead (&gMenuList);\r
+}\r
+\r
+\r
+/**\r
+  Remove a Menu in list, and return FormId/QuestionId for previous Menu.\r
+\r
+  @param  Selection              Menu selection.\r
+\r
+**/\r
+VOID\r
+UiRemoveMenuListEntry (\r
+  OUT UI_MENU_SELECTION  *Selection\r
+  )\r
+{\r
+  UI_MENU_LIST  *UiMenuList;\r
+\r
+  if (!IsListEmpty (&gMenuList)) {\r
+    UiMenuList = CR (gMenuList.ForwardLink, UI_MENU_LIST, MenuLink, UI_MENU_LIST_SIGNATURE);\r
+\r
+    Selection->FormId = UiMenuList->FormId;\r
+    Selection->QuestionId = UiMenuList->QuestionId;\r
+    RemoveEntryList (&UiMenuList->MenuLink);\r
+    gBS->FreePool (UiMenuList);\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Free Menu option linked list.\r
+\r
+**/\r
+VOID\r
+UiFreeMenuList (\r
+  VOID\r
+  )\r
+{\r
+  UI_MENU_LIST  *UiMenuList;\r
+\r
+  while (!IsListEmpty (&gMenuList)) {\r
+    UiMenuList = CR (gMenuList.ForwardLink, UI_MENU_LIST, MenuLink, UI_MENU_LIST_SIGNATURE);\r
+    RemoveEntryList (&UiMenuList->MenuLink);\r
+    gBS->FreePool (UiMenuList);\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Add one menu entry to the linked lst\r
+\r
+  @param  Selection              Menu selection.\r
+\r
+**/\r
+VOID\r
+UiAddMenuListEntry (\r
+  IN UI_MENU_SELECTION            *Selection\r
+  )\r
+{\r
+  UI_MENU_LIST  *UiMenuList;\r
+\r
+  UiMenuList = AllocateZeroPool (sizeof (UI_MENU_LIST));\r
+  ASSERT (UiMenuList != NULL);\r
+\r
+  UiMenuList->Signature = UI_MENU_LIST_SIGNATURE;\r
+  UiMenuList->FormId = Selection->FormId;\r
+  UiMenuList->QuestionId = Selection->QuestionId;\r
+\r
+  InsertHeadList (&gMenuList, &UiMenuList->MenuLink);\r
+}\r
+\r
+\r
+/**\r
+  Free Menu option linked list.\r
+\r
+**/\r
+VOID\r
+UiFreeMenu (\r
+  VOID\r
+  )\r
+{\r
+  UI_MENU_OPTION  *MenuOption;\r
+\r
+  while (!IsListEmpty (&Menu)) {\r
+    MenuOption = MENU_OPTION_FROM_LINK (Menu.ForwardLink);\r
+    RemoveEntryList (&MenuOption->Link);\r
+\r
+    //\r
+    // We allocated space for this description when we did a GetToken, free it here\r
+    //\r
+    if (MenuOption->Skip != 0) {\r
+      //\r
+      // For date/time, MenuOption->Description is shared by three Menu Options\r
+      // Data format :      [01/02/2004]      [11:22:33]\r
+      // Line number :        0  0    1         0  0  1\r
+      //\r
+      gBS->FreePool (MenuOption->Description);\r
+    }\r
+    gBS->FreePool (MenuOption);\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Free Menu option linked list.\r
+\r
+**/\r
+VOID\r
+UiFreeRefreshList (\r
+  VOID\r
+  )\r
+{\r
+  MENU_REFRESH_ENTRY  *OldMenuRefreshEntry;\r
+\r
+  while (gMenuRefreshHead != NULL) {\r
+    OldMenuRefreshEntry = gMenuRefreshHead->Next;\r
+    gBS->FreePool (gMenuRefreshHead);\r
+    gMenuRefreshHead = OldMenuRefreshEntry;\r
+  }\r
+\r
+  gMenuRefreshHead = NULL;\r
+}\r
+\r
+\r
+\r
+/**\r
+  Refresh screen.\r
+\r
+**/\r
+VOID\r
+RefreshForm (\r
+  VOID\r
+  )\r
+{\r
+  CHAR16                  *OptionString;\r
+  MENU_REFRESH_ENTRY      *MenuRefreshEntry;\r
+  UINTN                   Index;\r
+  UINTN                   Loop;\r
+  EFI_STATUS              Status;\r
+  UI_MENU_SELECTION       *Selection;\r
+  FORM_BROWSER_STATEMENT  *Question;\r
+\r
+  OptionString = NULL;\r
+\r
+  if (gMenuRefreshHead != NULL) {\r
+\r
+    MenuRefreshEntry = gMenuRefreshHead;\r
+\r
+    do {\r
+      gST->ConOut->SetAttribute (gST->ConOut, MenuRefreshEntry->CurrentAttribute);\r
+\r
+      Selection = MenuRefreshEntry->Selection;\r
+      Question = MenuRefreshEntry->MenuOption->ThisTag;\r
+\r
+      //\r
+      // Don't update Question being edited\r
+      //\r
+      if (Question != MenuRefreshEntry->Selection->Statement) {\r
+\r
+        Status = GetQuestionValue (Selection->FormSet, Selection->Form, Question, FALSE);\r
+        if (EFI_ERROR (Status)) {\r
+          return;\r
+        }\r
+\r
+        ProcessOptions (Selection, MenuRefreshEntry->MenuOption, FALSE, &OptionString);\r
+\r
+        if (OptionString != NULL) {\r
+          //\r
+          // If leading spaces on OptionString - remove the spaces\r
+          //\r
+          for (Index = 0; OptionString[Index] == L' '; Index++)\r
+            ;\r
+\r
+          for (Loop = 0; OptionString[Index] != CHAR_NULL; Index++) {\r
+            OptionString[Loop] = OptionString[Index];\r
+            Loop++;\r
+          }\r
+\r
+          OptionString[Loop] = CHAR_NULL;\r
+\r
+          PrintStringAt (MenuRefreshEntry->CurrentColumn, MenuRefreshEntry->CurrentRow, OptionString);\r
+          gBS->FreePool (OptionString);\r
+        }\r
+      }\r
+\r
+      MenuRefreshEntry = MenuRefreshEntry->Next;\r
+\r
+    } while (MenuRefreshEntry != NULL);\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Wait for a given event to fire, or for an optional timeout to expire.\r
+\r
+  @param  Event                  The event to wait for\r
+  @param  Timeout                An optional timeout value in 100 ns units.\r
+  @param  RefreshInterval        Menu refresh interval (in seconds).\r
+\r
+  @retval EFI_SUCCESS            Event fired before Timeout expired.\r
+  @retval EFI_TIME_OUT           Timout expired before Event fired.\r
+\r
+**/\r
+EFI_STATUS\r
+UiWaitForSingleEvent (\r
+  IN EFI_EVENT                Event,\r
+  IN UINT64                   Timeout, OPTIONAL\r
+  IN UINT8                    RefreshInterval OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINTN       Index;\r
+  EFI_EVENT   TimerEvent;\r
+  EFI_EVENT   WaitList[2];\r
+\r
+  if (Timeout != 0) {\r
+    //\r
+    // Create a timer event\r
+    //\r
+    Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);\r
+    if (!EFI_ERROR (Status)) {\r
+      //\r
+      // Set the timer event\r
+      //\r
+      gBS->SetTimer (\r
+            TimerEvent,\r
+            TimerRelative,\r
+            Timeout\r
+            );\r
+\r
+      //\r
+      // Wait for the original event or the timer\r
+      //\r
+      WaitList[0] = Event;\r
+      WaitList[1] = TimerEvent;\r
+      Status      = gBS->WaitForEvent (2, WaitList, &Index);\r
+      gBS->CloseEvent (TimerEvent);\r
+\r
+      //\r
+      // If the timer expired, change the return to timed out\r
+      //\r
+      if (!EFI_ERROR (Status) && Index == 1) {\r
+        Status = EFI_TIMEOUT;\r
+      }\r
+    }\r
+  } else {\r
+    //\r
+    // Update screen every second\r
+    //\r
+    if (RefreshInterval == 0) {\r
+      Timeout = ONE_SECOND;\r
+    } else {\r
+      Timeout = RefreshInterval * ONE_SECOND;\r
+    }\r
+\r
+    do {\r
+      Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);\r
+\r
+      //\r
+      // Set the timer event\r
+      //\r
+      gBS->SetTimer (\r
+            TimerEvent,\r
+            TimerRelative,\r
+            Timeout\r
+            );\r
+\r
+      //\r
+      // Wait for the original event or the timer\r
+      //\r
+      WaitList[0] = Event;\r
+      WaitList[1] = TimerEvent;\r
+      Status      = gBS->WaitForEvent (2, WaitList, &Index);\r
+\r
+      //\r
+      // If the timer expired, update anything that needs a refresh and keep waiting\r
+      //\r
+      if (!EFI_ERROR (Status) && Index == 1) {\r
+        Status = EFI_TIMEOUT;\r
+        if (RefreshInterval != 0) {\r
+          RefreshForm ();\r
+        }\r
+      }\r
+\r
+      gBS->CloseEvent (TimerEvent);\r
+    } while (Status == EFI_TIMEOUT);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Add one menu option by specified description and context.\r
+\r
+  @param  String                 String description for this option.\r
+  @param  Handle                 Hii handle for the package list.\r
+  @param  Statement              Statement of this Menu Option.\r
+  @param  NumberOfLines          Display lines for this Menu Option.\r
+  @param  MenuItemCount          The index for this Option in the Menu.\r
+\r
+**/\r
+VOID\r
+UiAddMenuOption (\r
+  IN CHAR16                  *String,\r
+  IN EFI_HII_HANDLE          Handle,\r
+  IN FORM_BROWSER_STATEMENT  *Statement,\r
+  IN UINT16                  NumberOfLines,\r
+  IN UINT16                  MenuItemCount\r
+  )\r
+{\r
+  UI_MENU_OPTION  *MenuOption;\r
+  UINTN           Index;\r
+  UINTN           Count;\r
+\r
+  Count = 1;\r
+\r
+  if (Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) {\r
+    //\r
+    // Add three MenuOptions for Date/Time\r
+    // Data format :      [01/02/2004]      [11:22:33]\r
+    // Line number :        0  0    1         0  0  1\r
+    //\r
+    NumberOfLines = 0;\r
+    Count = 3;\r
+\r
+    if (Statement->Storage == NULL) {\r
+      //\r
+      // For RTC type of date/time, set default refresh interval to be 1 second\r
+      //\r
+      if (Statement->RefreshInterval == 0) {\r
+        Statement->RefreshInterval = 1;\r
+      }\r
+    }\r
+  }\r
+\r
+  for (Index = 0; Index < Count; Index++) {\r
+    MenuOption = AllocateZeroPool (sizeof (UI_MENU_OPTION));\r
+    ASSERT (MenuOption);\r
+\r
+    MenuOption->Signature   = UI_MENU_OPTION_SIGNATURE;\r
+    MenuOption->Description = String;\r
+    MenuOption->Handle      = Handle;\r
+    MenuOption->ThisTag     = Statement;\r
+    MenuOption->EntryNumber = MenuItemCount;\r
+\r
+    if (Index == 2) {\r
+      //\r
+      // Override LineNumber for the MenuOption in Date/Time sequence\r
+      //\r
+      MenuOption->Skip = 1;\r
+    } else {\r
+      MenuOption->Skip = NumberOfLines;\r
+    }\r
+    MenuOption->Sequence = Index;\r
+\r
+    if (Statement->GrayOutExpression != NULL) {\r
+      MenuOption->GrayOut = Statement->GrayOutExpression->Result.Value.b;\r
+    }\r
+\r
+    if ((Statement->ValueExpression != NULL) ||\r
+        ((Statement->QuestionFlags & EFI_IFR_FLAG_READ_ONLY) != 0)) {\r
+      MenuOption->ReadOnly = TRUE;\r
+    }\r
+\r
+    InsertTailList (&Menu, &MenuOption->Link);\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Routine used to abstract a generic dialog interface and return the selected key or string\r
+\r
+  @param  NumberOfLines          The number of lines for the dialog box\r
+  @param  HotKey                 Defines whether a single character is parsed\r
+                                 (TRUE) and returned in KeyValue or a string is\r
+                                 returned in StringBuffer.  Two special characters\r
+                                 are considered when entering a string, a SCAN_ESC\r
+                                 and an CHAR_CARRIAGE_RETURN.  SCAN_ESC terminates\r
+                                 string input and returns\r
+  @param  MaximumStringSize      The maximum size in bytes of a typed in string\r
+                                 (each character is a CHAR16) and the minimum\r
+                                 string returned is two bytes\r
+  @param  StringBuffer           The passed in pointer to the buffer which will\r
+                                 hold the typed in string if HotKey is FALSE\r
+  @param  KeyValue               The EFI_KEY value returned if HotKey is TRUE..\r
+  @param  String                 Pointer to the first string in the list\r
+  @param  ...                    A series of (quantity == NumberOfLines) text\r
+                                 strings which will be used to construct the dialog\r
+                                 box\r
+\r
+  @retval EFI_SUCCESS            Displayed dialog and received user interaction\r
+  @retval EFI_INVALID_PARAMETER  One of the parameters was invalid (e.g.\r
+                                 (StringBuffer == NULL) && (HotKey == FALSE))\r
+  @retval EFI_DEVICE_ERROR       User typed in an ESC character to exit the routine\r
+\r
+**/\r
+EFI_STATUS\r
+CreateDialog (\r
+  IN  UINTN                       NumberOfLines,\r
+  IN  BOOLEAN                     HotKey,\r
+  IN  UINTN                       MaximumStringSize,\r
+  OUT CHAR16                      *StringBuffer,\r
+  OUT EFI_INPUT_KEY               *KeyValue,\r
+  IN  CHAR16                      *String,\r
+  ...\r
+  )\r
+{\r
+  VA_LIST       Marker;\r
+  UINTN         Count;\r
+  EFI_INPUT_KEY Key;\r
+  UINTN         LargestString;\r
+  CHAR16        *TempString;\r
+  CHAR16        *BufferedString;\r
+  CHAR16        *StackString;\r
+  CHAR16        KeyPad[2];\r
+  UINTN         Start;\r
+  UINTN         Top;\r
+  UINTN         Index;\r
+  EFI_STATUS    Status;\r
+  BOOLEAN       SelectionComplete;\r
+  UINTN         InputOffset;\r
+  UINTN         CurrentAttribute;\r
+  UINTN         DimensionsWidth;\r
+  UINTN         DimensionsHeight;\r
+\r
+  DimensionsWidth   = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;\r
+  DimensionsHeight  = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;\r
+\r
+  SelectionComplete = FALSE;\r
+  InputOffset       = 0;\r
+  TempString        = AllocateZeroPool (MaximumStringSize * 2);\r
+  BufferedString    = AllocateZeroPool (MaximumStringSize * 2);\r
+  CurrentAttribute  = gST->ConOut->Mode->Attribute;\r
+\r
+  ASSERT (TempString);\r
+  ASSERT (BufferedString);\r
+\r
+  VA_START (Marker, String);\r
+\r
+  //\r
+  // Zero the outgoing buffer\r
+  //\r
+  ZeroMem (StringBuffer, MaximumStringSize);\r
+\r
+  if (HotKey) {\r
+    if (KeyValue == NULL) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  } else {\r
+    if (StringBuffer == NULL) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  }\r
+  //\r
+  // Disable cursor\r
+  //\r
+  gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
+\r
+  LargestString = (GetStringWidth (String) / 2);\r
+\r
+  if (*String == L' ') {\r
+    InputOffset = 1;\r
+  }\r
+  //\r
+  // Determine the largest string in the dialog box\r
+  // Notice we are starting with 1 since String is the first string\r
+  //\r
+  for (Count = 1; Count < NumberOfLines; Count++) {\r
+    StackString = VA_ARG (Marker, CHAR16 *);\r
+\r
+    if (StackString[0] == L' ') {\r
+      InputOffset = Count + 1;\r
+    }\r
+\r
+    if ((GetStringWidth (StackString) / 2) > LargestString) {\r
+      //\r
+      // Size of the string visually and subtract the width by one for the null-terminator\r
+      //\r
+      LargestString = (GetStringWidth (StackString) / 2);\r
+    }\r
+  }\r
+\r
+  Start = (DimensionsWidth - LargestString - 2) / 2 + gScreenDimensions.LeftColumn + 1;\r
+  Top   = ((DimensionsHeight - NumberOfLines - 2) / 2) + gScreenDimensions.TopRow - 1;\r
+\r
+  Count = 0;\r
+\r
+  //\r
+  // Display the Popup\r
+  //\r
+  CreateSharedPopUp (LargestString, NumberOfLines, &String);\r
+\r
+  //\r
+  // Take the first key typed and report it back?\r
+  //\r
+  if (HotKey) {\r
+    Status = WaitForKeyStroke (&Key);\r
+    ASSERT_EFI_ERROR (Status);\r
+    CopyMem (KeyValue, &Key, sizeof (EFI_INPUT_KEY));\r
+\r
+  } else {\r
+    do {\r
+      Status = WaitForKeyStroke (&Key);\r
+\r
+      switch (Key.UnicodeChar) {\r
+      case CHAR_NULL:\r
+        switch (Key.ScanCode) {\r
+        case SCAN_ESC:\r
+          gBS->FreePool (TempString);\r
+          gBS->FreePool (BufferedString);\r
+          gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);\r
+          gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
+          return EFI_DEVICE_ERROR;\r
+\r
+        default:\r
+          break;\r
+        }\r
+\r
+        break;\r
+\r
+      case CHAR_CARRIAGE_RETURN:\r
+        SelectionComplete = TRUE;\r
+        gBS->FreePool (TempString);\r
+        gBS->FreePool (BufferedString);\r
+        gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);\r
+        gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
+        return EFI_SUCCESS;\r
+        break;\r
+\r
+      case CHAR_BACKSPACE:\r
+        if (StringBuffer[0] != CHAR_NULL) {\r
+          for (Index = 0; StringBuffer[Index] != CHAR_NULL; Index++) {\r
+            TempString[Index] = StringBuffer[Index];\r
+          }\r
+          //\r
+          // Effectively truncate string by 1 character\r
+          //\r
+          TempString[Index - 1] = CHAR_NULL;\r
+          StrCpy (StringBuffer, TempString);\r
+        }\r
+\r
+      default:\r
+        //\r
+        // If it is the beginning of the string, don't worry about checking maximum limits\r
+        //\r
+        if ((StringBuffer[0] == CHAR_NULL) && (Key.UnicodeChar != CHAR_BACKSPACE)) {\r
+          StrnCpy (StringBuffer, &Key.UnicodeChar, 1);\r
+          StrnCpy (TempString, &Key.UnicodeChar, 1);\r
+        } else if ((GetStringWidth (StringBuffer) < MaximumStringSize) && (Key.UnicodeChar != CHAR_BACKSPACE)) {\r
+          KeyPad[0] = Key.UnicodeChar;\r
+          KeyPad[1] = CHAR_NULL;\r
+          StrCat (StringBuffer, KeyPad);\r
+          StrCat (TempString, KeyPad);\r
+        }\r
+        //\r
+        // If the width of the input string is now larger than the screen, we nee to\r
+        // adjust the index to start printing portions of the string\r
+        //\r
+        SetUnicodeMem (BufferedString, LargestString, L' ');\r
+\r
+        PrintStringAt (Start + 1, Top + InputOffset, BufferedString);\r
+\r
+        if ((GetStringWidth (StringBuffer) / 2) > (DimensionsWidth - 2)) {\r
+          Index = (GetStringWidth (StringBuffer) / 2) - DimensionsWidth + 2;\r
+        } else {\r
+          Index = 0;\r
+        }\r
+\r
+        for (Count = 0; Index + 1 < GetStringWidth (StringBuffer) / 2; Index++, Count++) {\r
+          BufferedString[Count] = StringBuffer[Index];\r
+        }\r
+\r
+        PrintStringAt (Start + 1, Top + InputOffset, BufferedString);\r
+        break;\r
+      }\r
+    } while (!SelectionComplete);\r
+  }\r
+\r
+  gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);\r
+  gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Draw a pop up windows based on the dimension, number of lines and\r
+  strings specified.\r
+\r
+  @param RequestedWidth  The width of the pop-up.\r
+  @param NumberOfLines   The number of lines.\r
+  @param ArrayOfStrings  The array of string to be printed.\r
+\r
+**/\r
+VOID\r
+CreateSharedPopUp (\r
+  IN  UINTN                       RequestedWidth,\r
+  IN  UINTN                       NumberOfLines,\r
+  IN  CHAR16                      **ArrayOfStrings\r
+  )\r
+{\r
+  UINTN   Index;\r
+  UINTN   Count;\r
+  CHAR16  Character;\r
+  UINTN   Start;\r
+  UINTN   End;\r
+  UINTN   Top;\r
+  UINTN   Bottom;\r
+  CHAR16  *String;\r
+  UINTN   DimensionsWidth;\r
+  UINTN   DimensionsHeight;\r
+\r
+  DimensionsWidth   = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;\r
+  DimensionsHeight  = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;\r
+\r
+  Count = 0;\r
+\r
+  gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);\r
+\r
+  if ((RequestedWidth + 2) > DimensionsWidth) {\r
+    RequestedWidth = DimensionsWidth - 2;\r
+  }\r
+\r
+  //\r
+  // Subtract the PopUp width from total Columns, allow for one space extra on\r
+  // each end plus a border.\r
+  //\r
+  Start     = (DimensionsWidth - RequestedWidth - 2) / 2 + gScreenDimensions.LeftColumn + 1;\r
+  End       = Start + RequestedWidth + 1;\r
+\r
+  Top       = ((DimensionsHeight - NumberOfLines - 2) / 2) + gScreenDimensions.TopRow - 1;\r
+  Bottom    = Top + NumberOfLines + 2;\r
+\r
+  Character = BOXDRAW_DOWN_RIGHT;\r
+  PrintCharAt (Start, Top, Character);\r
+  Character = BOXDRAW_HORIZONTAL;\r
+  for (Index = Start; Index + 2 < End; Index++) {\r
+    PrintChar (Character);\r
+  }\r
+\r
+  Character = BOXDRAW_DOWN_LEFT;\r
+  PrintChar (Character);\r
+  Character = BOXDRAW_VERTICAL;\r
+  for (Index = Top; Index + 2 < Bottom; Index++) {\r
+    String = ArrayOfStrings[Count];\r
+    Count++;\r
+\r
+    //\r
+    // This will clear the background of the line - we never know who might have been\r
+    // here before us.  This differs from the next clear in that it used the non-reverse\r
+    // video for normal printing.\r
+    //\r
+    if (GetStringWidth (String) / 2 > 1) {\r
+      ClearLines (Start, End, Index + 1, Index + 1, POPUP_TEXT | POPUP_BACKGROUND);\r
+    }\r
+\r
+    //\r
+    // Passing in a space results in the assumption that this is where typing will occur\r
+    //\r
+    if (String[0] == L' ') {\r
+      ClearLines (Start + 1, End - 1, Index + 1, Index + 1, POPUP_INVERSE_TEXT | POPUP_INVERSE_BACKGROUND);\r
+    }\r
+\r
+    //\r
+    // Passing in a NULL results in a blank space\r
+    //\r
+    if (String[0] == CHAR_NULL) {\r
+      ClearLines (Start, End, Index + 1, Index + 1, POPUP_TEXT | POPUP_BACKGROUND);\r
+    }\r
+\r
+    PrintStringAt (\r
+      ((DimensionsWidth - GetStringWidth (String) / 2) / 2) + gScreenDimensions.LeftColumn + 1,\r
+      Index + 1,\r
+      String\r
+      );\r
+    gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);\r
+    PrintCharAt (Start, Index + 1, Character);\r
+    PrintCharAt (End - 1, Index + 1, Character);\r
+  }\r
+\r
+  Character = BOXDRAW_UP_RIGHT;\r
+  PrintCharAt (Start, Bottom - 1, Character);\r
+  Character = BOXDRAW_HORIZONTAL;\r
+  for (Index = Start; Index + 2 < End; Index++) {\r
+    PrintChar (Character);\r
+  }\r
+\r
+  Character = BOXDRAW_UP_LEFT;\r
+  PrintChar (Character);\r
+}\r
+\r
+/**\r
+  Draw a pop up windows based on the dimension, number of lines and\r
+  strings specified.\r
+\r
+  @param RequestedWidth  The width of the pop-up.\r
+  @param NumberOfLines   The number of lines.\r
+  @param ArrayOfStrings  The array of string to be printed.\r
+  @param ...             A series of text strings that displayed in the pop-up.\r
+\r
+**/\r
+VOID\r
+CreatePopUp (\r
+  IN  UINTN                       RequestedWidth,\r
+  IN  UINTN                       NumberOfLines,\r
+  IN  CHAR16                      *ArrayOfStrings,\r
+  ...\r
+  )\r
+{\r
+  CreateSharedPopUp (RequestedWidth, NumberOfLines, &ArrayOfStrings);\r
+}\r
+\r
+\r
+/**\r
+  Update status bar on the bottom of menu.\r
+\r
+  @param  MessageType            The type of message to be shown.\r
+  @param  Flags                  The flags in Question header.\r
+  @param  State                  Set or clear.\r
+\r
+**/\r
+VOID\r
+UpdateStatusBar (\r
+  IN  UINTN                       MessageType,\r
+  IN  UINT8                       Flags,\r
+  IN  BOOLEAN                     State\r
+  )\r
+{\r
+  UINTN           Index;\r
+  STATIC BOOLEAN  InputError;\r
+  CHAR16          *NvUpdateMessage;\r
+  CHAR16          *InputErrorMessage;\r
+\r
+  NvUpdateMessage   = GetToken (STRING_TOKEN (NV_UPDATE_MESSAGE), gHiiHandle);\r
+  InputErrorMessage = GetToken (STRING_TOKEN (INPUT_ERROR_MESSAGE), gHiiHandle);\r
+\r
+  switch (MessageType) {\r
+  case INPUT_ERROR:\r
+    if (State) {\r
+      gST->ConOut->SetAttribute (gST->ConOut, ERROR_TEXT);\r
+      PrintStringAt (\r
+        gScreenDimensions.LeftColumn + gPromptBlockWidth,\r
+        gScreenDimensions.BottomRow - 1,\r
+        InputErrorMessage\r
+        );\r
+      InputError = TRUE;\r
+    } else {\r
+      gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT);\r
+      for (Index = 0; Index < (GetStringWidth (InputErrorMessage) - 2) / 2; Index++) {\r
+        PrintAt (gScreenDimensions.LeftColumn + gPromptBlockWidth + Index, gScreenDimensions.BottomRow - 1, L"  ");\r
+      }\r
+\r
+      InputError = FALSE;\r
+    }\r
+    break;\r
+\r
+  case NV_UPDATE_REQUIRED:\r
+    if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {\r
+      if (State) {\r
+        gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT);\r
+        PrintStringAt (\r
+          gScreenDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth,\r
+          gScreenDimensions.BottomRow - 1,\r
+          NvUpdateMessage\r
+          );\r
+        gResetRequired    = (BOOLEAN) (gResetRequired | ((Flags & EFI_IFR_FLAG_RESET_REQUIRED) == EFI_IFR_FLAG_RESET_REQUIRED));\r
+\r
+        gNvUpdateRequired = TRUE;\r
+      } else {\r
+        gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT);\r
+        for (Index = 0; Index < (GetStringWidth (NvUpdateMessage) - 2) / 2; Index++) {\r
+          PrintAt (\r
+            (gScreenDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + Index),\r
+            gScreenDimensions.BottomRow - 1,\r
+            L"  "\r
+            );\r
+        }\r
+\r
+        gNvUpdateRequired = FALSE;\r
+      }\r
+    }\r
+    break;\r
+\r
+  case REFRESH_STATUS_BAR:\r
+    if (InputError) {\r
+      UpdateStatusBar (INPUT_ERROR, Flags, TRUE);\r
+    }\r
+\r
+    if (gNvUpdateRequired) {\r
+      UpdateStatusBar (NV_UPDATE_REQUIRED, Flags, TRUE);\r
+    }\r
+    break;\r
+\r
+  default:\r
+    break;\r
+  }\r
+\r
+  gBS->FreePool (InputErrorMessage);\r
+  gBS->FreePool (NvUpdateMessage);\r
+  return ;\r
+}\r
+\r
+\r
+/**\r
+  Get the supported width for a particular op-code\r
+\r
+  @param  Statement              The FORM_BROWSER_STATEMENT structure passed in.\r
+  @param  Handle                 The handle in the HII database being used\r
+\r
+  @return Returns the number of CHAR16 characters that is support.\r
+\r
+**/\r
+UINT16\r
+GetWidth (\r
+  IN FORM_BROWSER_STATEMENT        *Statement,\r
+  IN EFI_HII_HANDLE                 Handle\r
+  )\r
+{\r
+  CHAR16  *String;\r
+  UINTN   Size;\r
+  UINT16  Width;\r
+\r
+  Size = 0;\r
+\r
+  //\r
+  // See if the second text parameter is really NULL\r
+  //\r
+  if ((Statement->Operand == EFI_IFR_TEXT_OP) && (Statement->TextTwo != 0)) {\r
+    String = GetToken (Statement->TextTwo, Handle);\r
+    Size   = StrLen (String);\r
+    gBS->FreePool (String);\r
+  }\r
+\r
+  if ((Statement->Operand == EFI_IFR_SUBTITLE_OP) ||\r
+      (Statement->Operand == EFI_IFR_REF_OP) ||\r
+      (Statement->Operand == EFI_IFR_PASSWORD_OP) ||\r
+      (Statement->Operand == EFI_IFR_ACTION_OP) ||\r
+      (Statement->Operand == EFI_IFR_RESET_BUTTON_OP) ||\r
+      //\r
+      // Allow a wide display if text op-code and no secondary text op-code\r
+      //\r
+      ((Statement->Operand == EFI_IFR_TEXT_OP) && (Size == 0))\r
+      ) {\r
+    Width = (UINT16) (gPromptBlockWidth + gOptionBlockWidth);\r
+  } else {\r
+    Width = (UINT16) gPromptBlockWidth;\r
+  }\r
+\r
+  if (Statement->InSubtitle) {\r
+    Width -= SUBTITLE_INDENT;\r
+  }\r
+\r
+  return Width;\r
+}\r
+\r
+\r
+STATIC BOOLEAN GetLineByWidthFinished = FALSE;\r
+\r
+/**\r
+  Will copy LineWidth amount of a string in the OutputString buffer and return the\r
+  number of CHAR16 characters that were copied into the OutputString buffer.\r
+\r
+  @param  InputString            String description for this option.\r
+  @param  LineWidth              Width of the desired string to extract in CHAR16\r
+                                 characters\r
+  @param  Index                  Where in InputString to start the copy process\r
+  @param  OutputString           Buffer to copy the string into\r
+\r
+  @return Returns the number of CHAR16 characters that were copied into the OutputString buffer.\r
+\r
+**/\r
+UINT16\r
+GetLineByWidth (\r
+  IN      CHAR16                      *InputString,\r
+  IN      UINT16                      LineWidth,\r
+  IN OUT  UINTN                       *Index,\r
+  OUT     CHAR16                      **OutputString\r
+  )\r
+{\r
+  UINT16          Count;\r
+  UINT16          Count2;\r
+\r
+  if (GetLineByWidthFinished) {\r
+    GetLineByWidthFinished = FALSE;\r
+    return (UINT16) 0;\r
+  }\r
+\r
+  Count         = LineWidth;\r
+  Count2        = 0;\r
+\r
+  *OutputString = AllocateZeroPool (((UINTN) (LineWidth + 1) * 2));\r
+\r
+  //\r
+  // Ensure we have got a valid buffer\r
+  //\r
+  if (*OutputString != NULL) {\r
+\r
+    //\r
+    //NARROW_CHAR can not be printed in screen, so if a line only contain  the two CHARs: 'NARROW_CHAR + CHAR_CARRIAGE_RETURN' , it is a empty line  in Screen.\r
+    //To avoid displaying this  empty line in screen,  just skip  the two CHARs here.\r
+    //\r
+   if ((InputString[*Index] == NARROW_CHAR) && (InputString[*Index + 1] == CHAR_CARRIAGE_RETURN)) {\r
+     *Index = *Index + 2;\r
+   }\r
+\r
+    //\r
+    // Fast-forward the string and see if there is a carriage-return in the string\r
+    //\r
+    for (; (InputString[*Index + Count2] != CHAR_CARRIAGE_RETURN) && (Count2 != LineWidth); Count2++)\r
+      ;\r
+\r
+    //\r
+    // Copy the desired LineWidth of data to the output buffer.\r
+    // Also make sure that we don't copy more than the string.\r
+    // Also make sure that if there are linefeeds, we account for them.\r
+    //\r
+    if ((StrSize (&InputString[*Index]) <= ((UINTN) (LineWidth + 1) * 2)) &&\r
+        (StrSize (&InputString[*Index]) <= ((UINTN) (Count2 + 1) * 2))\r
+        ) {\r
+      //\r
+      // Convert to CHAR16 value and show that we are done with this operation\r
+      //\r
+      LineWidth = (UINT16) ((StrSize (&InputString[*Index]) - 2) / 2);\r
+      if (LineWidth != 0) {\r
+        GetLineByWidthFinished = TRUE;\r
+      }\r
+    } else {\r
+      if (Count2 == LineWidth) {\r
+        //\r
+        // Rewind the string from the maximum size until we see a space to break the line\r
+        //\r
+        for (; (InputString[*Index + LineWidth] != CHAR_SPACE) && (LineWidth != 0); LineWidth--)\r
+          ;\r
+        if (LineWidth == 0) {\r
+          LineWidth = Count;\r
+        }\r
+      } else {\r
+        LineWidth = Count2;\r
+      }\r
+    }\r
+\r
+    CopyMem (*OutputString, &InputString[*Index], LineWidth * 2);\r
+\r
+    //\r
+    // If currently pointing to a space, increment the index to the first non-space character\r
+    //\r
+    for (;\r
+         (InputString[*Index + LineWidth] == CHAR_SPACE) || (InputString[*Index + LineWidth] == CHAR_CARRIAGE_RETURN);\r
+         (*Index)++\r
+        )\r
+      ;\r
+    *Index = (UINT16) (*Index + LineWidth);\r
+    return LineWidth;\r
+  } else {\r
+    return (UINT16) 0;\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Update display lines for a Menu Option.\r
+\r
+  @param  Selection              The user's selection.\r
+  @param  MenuOption             The MenuOption to be checked.\r
+  @param  OptionalString         The option string.\r
+  @param  SkipValue              The number of lins to skip.\r
+\r
+  @retval TRUE                   This Menu Option is selectable.\r
+  @retval FALSE                  This Menu Option could not be selected.\r
+\r
+**/\r
+VOID\r
+UpdateOptionSkipLines (\r
+  IN UI_MENU_SELECTION            *Selection,\r
+  IN UI_MENU_OPTION               *MenuOption,\r
+  OUT CHAR16                       **OptionalString,\r
+  IN UINTN                        SkipValue\r
+  )\r
+{\r
+  UINTN   Index;\r
+  UINT16  Width;\r
+  UINTN   Row;\r
+  UINTN   OriginalRow;\r
+  CHAR16  *OutputString;\r
+  CHAR16  *OptionString;\r
+\r
+  Row           = 0;\r
+  OptionString  = *OptionalString;\r
+  OutputString  = NULL;\r
+\r
+  ProcessOptions (Selection, MenuOption, FALSE, &OptionString);\r
+\r
+  if (OptionString != NULL) {\r
+    Width               = (UINT16) gOptionBlockWidth;\r
+\r
+    OriginalRow         = Row;\r
+\r
+    for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {\r
+      //\r
+      // If there is more string to process print on the next row and increment the Skip value\r
+      //\r
+      if (StrLen (&OptionString[Index])) {\r
+        if (SkipValue == 0) {\r
+          Row++;\r
+          //\r
+          // Since the Number of lines for this menu entry may or may not be reflected accurately\r
+          // since the prompt might be 1 lines and option might be many, and vice versa, we need to do\r
+          // some testing to ensure we are keeping this in-sync.\r
+          //\r
+          // If the difference in rows is greater than or equal to the skip value, increase the skip value\r
+          //\r
+          if ((Row - OriginalRow) >= MenuOption->Skip) {\r
+            MenuOption->Skip++;\r
+          }\r
+        }\r
+      }\r
+\r
+      gBS->FreePool (OutputString);\r
+      if (SkipValue != 0) {\r
+        SkipValue--;\r
+      }\r
+    }\r
+\r
+    Row = OriginalRow;\r
+  }\r
+\r
+  *OptionalString = OptionString;\r
+}\r
+\r
+\r
+/**\r
+  Check whether this Menu Option could be highlighted.\r
+\r
+  This is an internal function.\r
+\r
+  @param  MenuOption             The MenuOption to be checked.\r
+\r
+  @retval TRUE                   This Menu Option is selectable.\r
+  @retval FALSE                  This Menu Option could not be selected.\r
+\r
+**/\r
+BOOLEAN\r
+IsSelectable (\r
+  UI_MENU_OPTION   *MenuOption\r
+  )\r
+{\r
+  if ((MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP) ||\r
+      MenuOption->GrayOut || MenuOption->ReadOnly) {\r
+    return FALSE;\r
+  } else {\r
+    return TRUE;\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Determine if the menu is the last menu that can be selected.\r
+\r
+  This is an internal function.\r
+  \r
+  @param  Direction              The scroll direction. False is down. True is up.\r
+  @param  CurrentPos             The current focus.\r
+\r
+  @return FALSE -- the menu isn't the last menu that can be selected.\r
+  @return TRUE  -- the menu is the last menu that can be selected.\r
+\r
+**/\r
+BOOLEAN\r
+ValueIsScroll (\r
+  IN  BOOLEAN                     Direction,\r
+  IN  LIST_ENTRY                  *CurrentPos\r
+  )\r
+{\r
+  LIST_ENTRY      *Temp;\r
+  UI_MENU_OPTION  *MenuOption;\r
+\r
+  Temp = Direction ? CurrentPos->BackLink : CurrentPos->ForwardLink;\r
+\r
+  if (Temp == &Menu) {\r
+    return TRUE;\r
+  }\r
+\r
+  for (; Temp != &Menu; Temp = Direction ? Temp->BackLink : Temp->ForwardLink) {\r
+    MenuOption = MENU_OPTION_FROM_LINK (Temp);\r
+    if (IsSelectable (MenuOption)) {\r
+      return FALSE;\r
+    }\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
+\r
+/**\r
+  Move to next selectable statement.\r
+  \r
+  This is an internal function.\r
+  \r
+  @param  GoUp                   The navigation direction. TRUE: up, FALSE: down.\r
+  @param  CurrentPosition        Current position.\r
+\r
+  @return The row distance from current MenuOption to next selectable MenuOption.\r
+\r
+**/\r
+INTN\r
+MoveToNextStatement (\r
+  IN     BOOLEAN                   GoUp,\r
+  IN OUT LIST_ENTRY                **CurrentPosition\r
+  )\r
+{\r
+  INTN             Distance;\r
+  LIST_ENTRY       *Pos;\r
+  BOOLEAN          HitEnd;\r
+  UI_MENU_OPTION   *NextMenuOption;\r
+\r
+  Distance = 0;\r
+  Pos      = *CurrentPosition;\r
+  HitEnd   = FALSE;\r
+\r
+  while (TRUE) {\r
+    NextMenuOption = MENU_OPTION_FROM_LINK (Pos);\r
+    if (IsSelectable (NextMenuOption)) {\r
+      break;\r
+    }\r
+    if ((GoUp ? Pos->BackLink : Pos->ForwardLink) == &Menu) {\r
+      HitEnd = TRUE;\r
+      break;\r
+    }\r
+    Distance += NextMenuOption->Skip;\r
+    Pos = (GoUp ? Pos->BackLink : Pos->ForwardLink);\r
+  }\r
+\r
+  if (HitEnd) {\r
+    //\r
+    // If we hit end there is still no statement can be focused,\r
+    // we go backwards to find the statement can be focused.\r
+    //\r
+    Distance = 0;\r
+    Pos = *CurrentPosition;\r
+\r
+    while (TRUE) {\r
+      NextMenuOption = MENU_OPTION_FROM_LINK (Pos);\r
+      if (IsSelectable (NextMenuOption)) {\r
+        break;\r
+      }\r
+      if ((!GoUp ? Pos->BackLink : Pos->ForwardLink) == &Menu) {\r
+        ASSERT (FALSE);\r
+        break;\r
+      }\r
+      Distance -= NextMenuOption->Skip;\r
+      Pos = (!GoUp ? Pos->BackLink : Pos->ForwardLink);\r
+    }\r
+  }\r
+\r
+  *CurrentPosition = &NextMenuOption->Link;\r
+  return Distance;\r
+}\r
+\r
+\r
+/**\r
+  Adjust Data and Time position accordingly.\r
+  Data format :      [01/02/2004]      [11:22:33]\r
+  Line number :        0  0    1         0  0  1\r
+  \r
+  This is an internal function.\r
+\r
+  @param  DirectionUp            the up or down direction. False is down. True is\r
+                                 up.\r
+  @param  CurrentPosition        Current position. On return: Point to the last\r
+                                 Option (Year or Second) if up; Point to the first\r
+                                 Option (Month or Hour) if down.\r
+\r
+  @return Return line number to pad. It is possible that we stand on a zero-advance\r
+  @return data or time opcode, so pad one line when we judge if we are going to scroll outside.\r
+\r
+**/\r
+UINTN\r
+AdjustDateAndTimePosition (\r
+  IN     BOOLEAN                     DirectionUp,\r
+  IN OUT LIST_ENTRY                  **CurrentPosition\r
+  )\r
+{\r
+  UINTN           Count;\r
+  LIST_ENTRY      *NewPosition;\r
+  UI_MENU_OPTION  *MenuOption;\r
+  UINTN           PadLineNumber;\r
+\r
+  PadLineNumber = 0;\r
+  NewPosition   = *CurrentPosition;\r
+  MenuOption    = MENU_OPTION_FROM_LINK (NewPosition);\r
+\r
+  if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) ||\r
+      (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {\r
+    //\r
+    // Calculate the distance from current position to the last Date/Time MenuOption\r
+    //\r
+    Count = 0;\r
+    while (MenuOption->Skip == 0) {\r
+      Count++;\r
+      NewPosition   = NewPosition->ForwardLink;\r
+      MenuOption    = MENU_OPTION_FROM_LINK (NewPosition);\r
+      PadLineNumber = 1;\r
+    }\r
+\r
+    NewPosition = *CurrentPosition;\r
+    if (DirectionUp) {\r
+      //\r
+      // Since the behavior of hitting the up arrow on a Date/Time MenuOption is intended\r
+      // to be one that back to the previous set of MenuOptions, we need to advance to the first\r
+      // Date/Time MenuOption and leave the remaining logic in CfUiUp intact so the appropriate\r
+      // checking can be done.\r
+      //\r
+      while (Count++ < 2) {\r
+        NewPosition = NewPosition->BackLink;\r
+      }\r
+    } else {\r
+      //\r
+      // Since the behavior of hitting the down arrow on a Date/Time MenuOption is intended\r
+      // to be one that progresses to the next set of MenuOptions, we need to advance to the last\r
+      // Date/Time MenuOption and leave the remaining logic in CfUiDown intact so the appropriate\r
+      // checking can be done.\r
+      //\r
+      while (Count-- > 0) {\r
+        NewPosition = NewPosition->ForwardLink;\r
+      }\r
+    }\r
+\r
+    *CurrentPosition = NewPosition;\r
+  }\r
+\r
+  return PadLineNumber;\r
+}\r
+\r
+\r
+/**\r
+  Display menu and wait for user to select one menu option, then return it.\r
+  If AutoBoot is enabled, then if user doesn't select any option,\r
+  after period of time, it will automatically return the first menu option.\r
+\r
+  @param  Selection              Menu selection.\r
+\r
+  @retval EFI_SUCESSS            This function always return successfully for now.\r
+\r
+**/\r
+EFI_STATUS\r
+UiDisplayMenu (\r
+  IN OUT UI_MENU_SELECTION           *Selection\r
+  )\r
+{\r
+  INTN                            SkipValue;\r
+  INTN                            Difference;\r
+  INTN                            OldSkipValue;\r
+  UINTN                           DistanceValue;\r
+  UINTN                           Row;\r
+  UINTN                           Col;\r
+  UINTN                           Temp;\r
+  UINTN                           Temp2;\r
+  UINTN                           TopRow;\r
+  UINTN                           BottomRow;\r
+  UINTN                           OriginalRow;\r
+  UINTN                           Index;\r
+  UINT32                          Count;\r
+  UINT16                          Width;\r
+  CHAR16                          *StringPtr;\r
+  CHAR16                          *OptionString;\r
+  CHAR16                          *OutputString;\r
+  CHAR16                          *FormattedString;\r
+  CHAR16                          YesResponse;\r
+  CHAR16                          NoResponse;\r
+  BOOLEAN                         NewLine;\r
+  BOOLEAN                         Repaint;\r
+  BOOLEAN                         SavedValue;\r
+  EFI_STATUS                      Status;\r
+  EFI_INPUT_KEY                   Key;\r
+  LIST_ENTRY                      *Link;\r
+  LIST_ENTRY                      *NewPos;\r
+  LIST_ENTRY                      *TopOfScreen;\r
+  LIST_ENTRY                      *SavedListEntry;\r
+  UI_MENU_OPTION                  *MenuOption;\r
+  UI_MENU_OPTION                  *NextMenuOption;\r
+  UI_MENU_OPTION                  *SavedMenuOption;\r
+  UI_MENU_OPTION                  *PreviousMenuOption;\r
+  UI_CONTROL_FLAG                 ControlFlag;\r
+  EFI_SCREEN_DESCRIPTOR           LocalScreen;\r
+  MENU_REFRESH_ENTRY              *MenuRefreshEntry;\r
+  UI_SCREEN_OPERATION             ScreenOperation;\r
+  UINT8                           MinRefreshInterval;\r
+  UINTN                           BufferSize;\r
+  UINT16                          DefaultId;\r
+  EFI_DEVICE_PATH_PROTOCOL        *DevicePath;\r
+  FORM_BROWSER_STATEMENT          *Statement;\r
+\r
+  CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
+\r
+  Status              = EFI_SUCCESS;\r
+  FormattedString     = NULL;\r
+  OptionString        = NULL;\r
+  ScreenOperation     = UiNoOperation;\r
+  NewLine             = TRUE;\r
+  MinRefreshInterval  = 0;\r
+  DefaultId           = 0;\r
+\r
+  OutputString        = NULL;\r
+  gUpArrow            = FALSE;\r
+  gDownArrow          = FALSE;\r
+  SkipValue           = 0;\r
+  OldSkipValue        = 0;\r
+  MenuRefreshEntry    = gMenuRefreshHead;\r
+\r
+  NextMenuOption      = NULL;\r
+  PreviousMenuOption  = NULL;\r
+  SavedMenuOption     = NULL;\r
+\r
+  ZeroMem (&Key, sizeof (EFI_INPUT_KEY));\r
+\r
+  if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {\r
+    TopRow  = LocalScreen.TopRow + FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;\r
+    Row     = LocalScreen.TopRow + FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;\r
+  } else {\r
+    TopRow  = LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;\r
+    Row     = LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;\r
+  }\r
+\r
+  Col = LocalScreen.LeftColumn;\r
+  BottomRow = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT - SCROLL_ARROW_HEIGHT - 1;\r
+\r
+  Selection->TopRow = TopRow;\r
+  Selection->BottomRow = BottomRow;\r
+  Selection->PromptCol = Col;\r
+  Selection->OptionCol = gPromptBlockWidth + 1 + LocalScreen.LeftColumn;\r
+  Selection->Statement = NULL;\r
+\r
+  TopOfScreen = Menu.ForwardLink;\r
+  Repaint     = TRUE;\r
+  MenuOption  = NULL;\r
+\r
+  //\r
+  // Get user's selection\r
+  //\r
+  NewPos = Menu.ForwardLink;\r
+\r
+  gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
+  UpdateStatusBar (REFRESH_STATUS_BAR, (UINT8) 0, TRUE);\r
+\r
+  ControlFlag = CfInitialization;\r
+  Selection->Action = UI_ACTION_NONE;\r
+  while (TRUE) {\r
+    switch (ControlFlag) {\r
+    case CfInitialization:\r
+      if (IsListEmpty (&Menu)) {\r
+        ControlFlag = CfReadKey;\r
+      } else {\r
+        ControlFlag = CfCheckSelection;\r
+      }\r
+      break;\r
+\r
+    case CfCheckSelection:\r
+      if (Selection->Action != UI_ACTION_NONE) {\r
+        ControlFlag = CfExit;\r
+      } else {\r
+        ControlFlag = CfRepaint;\r
+      }\r
+      break;\r
+\r
+    case CfRepaint:\r
+      ControlFlag = CfRefreshHighLight;\r
+\r
+      if (Repaint) {\r
+        //\r
+        // Display menu\r
+        //\r
+        gDownArrow      = FALSE;\r
+        gUpArrow        = FALSE;\r
+        Row             = TopRow;\r
+\r
+        Temp            = SkipValue;\r
+        Temp2           = SkipValue;\r
+\r
+        ClearLines (\r
+          LocalScreen.LeftColumn,\r
+          LocalScreen.RightColumn,\r
+          TopRow - SCROLL_ARROW_HEIGHT,\r
+          BottomRow + SCROLL_ARROW_HEIGHT,\r
+          FIELD_TEXT | FIELD_BACKGROUND\r
+          );\r
+\r
+        UiFreeRefreshList ();\r
+        MinRefreshInterval = 0;\r
+\r
+        for (Link = TopOfScreen; Link != &Menu; Link = Link->ForwardLink) {\r
+          MenuOption          = MENU_OPTION_FROM_LINK (Link);\r
+          MenuOption->Row     = Row;\r
+          MenuOption->Col     = Col;\r
+          MenuOption->OptCol  = gPromptBlockWidth + 1 + LocalScreen.LeftColumn;\r
+\r
+          Statement = MenuOption->ThisTag;\r
+          if (Statement->InSubtitle) {\r
+            MenuOption->Col += SUBTITLE_INDENT;\r
+          }\r
+\r
+          if (MenuOption->GrayOut) {\r
+            gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_GRAYED | FIELD_BACKGROUND);\r
+          } else {\r
+            if (Statement->Operand == EFI_IFR_SUBTITLE_OP) {\r
+              gST->ConOut->SetAttribute (gST->ConOut, SUBTITLE_TEXT | FIELD_BACKGROUND);\r
+            }\r
+          }\r
+\r
+          Width       = GetWidth (Statement, MenuOption->Handle);\r
+          OriginalRow = Row;\r
+\r
+          for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {\r
+            if ((Temp == 0) && (Row <= BottomRow)) {\r
+              PrintStringAt (MenuOption->Col, Row, OutputString);\r
+            }\r
+            //\r
+            // If there is more string to process print on the next row and increment the Skip value\r
+            //\r
+            if (StrLen (&MenuOption->Description[Index])) {\r
+              if (Temp == 0) {\r
+                Row++;\r
+              }\r
+            }\r
+\r
+            gBS->FreePool (OutputString);\r
+            if (Temp != 0) {\r
+              Temp--;\r
+            }\r
+          }\r
+\r
+          Temp  = 0;\r
+          Row   = OriginalRow;\r
+\r
+          gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);\r
+          ProcessOptions (Selection, MenuOption, FALSE, &OptionString);\r
+\r
+          if (OptionString != NULL) {\r
+            if (Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) {\r
+              //\r
+              // If leading spaces on OptionString - remove the spaces\r
+              //\r
+              for (Index = 0; OptionString[Index] == L' '; Index++) {\r
+                MenuOption->OptCol++;\r
+              }\r
+\r
+              for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {\r
+                OptionString[Count] = OptionString[Index];\r
+                Count++;\r
+              }\r
+\r
+              OptionString[Count] = CHAR_NULL;\r
+            }\r
+\r
+            //\r
+            // If Question request refresh, register the op-code\r
+            //\r
+            if (Statement->RefreshInterval != 0) {\r
+              //\r
+              // Menu will be refreshed at minimal interval of all Questions\r
+              // which have refresh request\r
+              //\r
+              if (MinRefreshInterval == 0 || Statement->RefreshInterval < MinRefreshInterval) {\r
+                MinRefreshInterval = Statement->RefreshInterval;\r
+              }\r
+\r
+              if (gMenuRefreshHead == NULL) {\r
+                MenuRefreshEntry = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));\r
+                ASSERT (MenuRefreshEntry != NULL);\r
+                MenuRefreshEntry->MenuOption        = MenuOption;\r
+                MenuRefreshEntry->Selection         = Selection;\r
+                MenuRefreshEntry->CurrentColumn     = MenuOption->OptCol;\r
+                MenuRefreshEntry->CurrentRow        = MenuOption->Row;\r
+                MenuRefreshEntry->CurrentAttribute  = FIELD_TEXT | FIELD_BACKGROUND;\r
+                gMenuRefreshHead                    = MenuRefreshEntry;\r
+              } else {\r
+                //\r
+                // Advance to the last entry\r
+                //\r
+                for (MenuRefreshEntry = gMenuRefreshHead;\r
+                     MenuRefreshEntry->Next != NULL;\r
+                     MenuRefreshEntry = MenuRefreshEntry->Next\r
+                    )\r
+                  ;\r
+                MenuRefreshEntry->Next = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));\r
+                ASSERT (MenuRefreshEntry->Next != NULL);\r
+                MenuRefreshEntry                    = MenuRefreshEntry->Next;\r
+                MenuRefreshEntry->MenuOption        = MenuOption;\r
+                MenuRefreshEntry->Selection         = Selection;\r
+                MenuRefreshEntry->CurrentColumn     = MenuOption->OptCol;\r
+                MenuRefreshEntry->CurrentRow        = MenuOption->Row;\r
+                MenuRefreshEntry->CurrentAttribute  = FIELD_TEXT | FIELD_BACKGROUND;\r
+              }\r
+            }\r
+\r
+            Width       = (UINT16) gOptionBlockWidth;\r
+            OriginalRow = Row;\r
+\r
+            for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {\r
+              if ((Temp2 == 0) && (Row <= BottomRow)) {\r
+                PrintStringAt (MenuOption->OptCol, Row, OutputString);\r
+              }\r
+              //\r
+              // If there is more string to process print on the next row and increment the Skip value\r
+              //\r
+              if (StrLen (&OptionString[Index])) {\r
+                if (Temp2 == 0) {\r
+                  Row++;\r
+                  //\r
+                  // Since the Number of lines for this menu entry may or may not be reflected accurately\r
+                  // since the prompt might be 1 lines and option might be many, and vice versa, we need to do\r
+                  // some testing to ensure we are keeping this in-sync.\r
+                  //\r
+                  // If the difference in rows is greater than or equal to the skip value, increase the skip value\r
+                  //\r
+                  if ((Row - OriginalRow) >= MenuOption->Skip) {\r
+                    MenuOption->Skip++;\r
+                  }\r
+                }\r
+              }\r
+\r
+              gBS->FreePool (OutputString);\r
+              if (Temp2 != 0) {\r
+                Temp2--;\r
+              }\r
+            }\r
+\r
+            Temp2 = 0;\r
+            Row   = OriginalRow;\r
+\r
+            gBS->FreePool (OptionString);\r
+          }\r
+          //\r
+          // If this is a text op with secondary text information\r
+          //\r
+          if ((Statement->Operand == EFI_IFR_TEXT_OP) && (Statement->TextTwo != 0)) {\r
+            StringPtr   = GetToken (Statement->TextTwo, MenuOption->Handle);\r
+\r
+            Width       = (UINT16) gOptionBlockWidth;\r
+            OriginalRow = Row;\r
+\r
+            for (Index = 0; GetLineByWidth (StringPtr, Width, &Index, &OutputString) != 0x0000;) {\r
+              if ((Temp == 0) && (Row <= BottomRow)) {\r
+                PrintStringAt (MenuOption->OptCol, Row, OutputString);\r
+              }\r
+              //\r
+              // If there is more string to process print on the next row and increment the Skip value\r
+              //\r
+              if (StrLen (&StringPtr[Index])) {\r
+                if (Temp2 == 0) {\r
+                  Row++;\r
+                  //\r
+                  // Since the Number of lines for this menu entry may or may not be reflected accurately\r
+                  // since the prompt might be 1 lines and option might be many, and vice versa, we need to do\r
+                  // some testing to ensure we are keeping this in-sync.\r
+                  //\r
+                  // If the difference in rows is greater than or equal to the skip value, increase the skip value\r
+                  //\r
+                  if ((Row - OriginalRow) >= MenuOption->Skip) {\r
+                    MenuOption->Skip++;\r
+                  }\r
+                }\r
+              }\r
+\r
+              gBS->FreePool (OutputString);\r
+              if (Temp2 != 0) {\r
+                Temp2--;\r
+              }\r
+            }\r
+\r
+            Row = OriginalRow;\r
+            gBS->FreePool (StringPtr);\r
+          }\r
+\r
+          //\r
+          // Need to handle the bottom of the display\r
+          //\r
+          if (MenuOption->Skip > 1) {\r
+            Row += MenuOption->Skip - SkipValue;\r
+            SkipValue = 0;\r
+          } else {\r
+            Row += MenuOption->Skip;\r
+          }\r
+\r
+          if (Row > BottomRow) {\r
+            if (!ValueIsScroll (FALSE, Link)) {\r
+              gDownArrow = TRUE;\r
+            }\r
+\r
+            Row = BottomRow + 1;\r
+            break;\r
+          }\r
+        }\r
+\r
+        if (!ValueIsScroll (TRUE, TopOfScreen)) {\r
+          gUpArrow = TRUE;\r
+        }\r
+\r
+        if (gUpArrow) {\r
+          gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND);\r
+          PrintAt (\r
+            LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,\r
+            TopRow - SCROLL_ARROW_HEIGHT,\r
+            L"%c",\r
+            ARROW_UP\r
+            );\r
+          gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);\r
+        }\r
+\r
+        if (gDownArrow) {\r
+          gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND);\r
+          PrintAt (\r
+            LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,\r
+            BottomRow + SCROLL_ARROW_HEIGHT,\r
+            L"%c",\r
+            ARROW_DOWN\r
+            );\r
+          gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);\r
+        }\r
+\r
+        MenuOption = NULL;\r
+      }\r
+      break;\r
+\r
+    case CfRefreshHighLight:\r
+      //\r
+      // MenuOption: Last menu option that need to remove hilight\r
+      //             MenuOption is set to NULL in Repaint\r
+      // NewPos:     Current menu option that need to hilight\r
+      //\r
+      ControlFlag = CfUpdateHelpString;\r
+\r
+      //\r
+      // Repaint flag is normally reset when finish processing CfUpdateHelpString. Temporarily\r
+      // reset Repaint flag because we may break halfway and skip CfUpdateHelpString processing.\r
+      //\r
+      SavedValue  = Repaint;\r
+      Repaint     = FALSE;\r
+\r
+      if (Selection->QuestionId != 0) {\r
+        NewPos = Menu.ForwardLink;\r
+        SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+\r
+        while (SavedMenuOption->ThisTag->QuestionId != Selection->QuestionId && NewPos->ForwardLink != &Menu) {\r
+          NewPos     = NewPos->ForwardLink;\r
+          SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+        }\r
+        if (SavedMenuOption->ThisTag->QuestionId == Selection->QuestionId) {\r
+          //\r
+          // Target Question found, find its MenuOption\r
+          //\r
+          Link = TopOfScreen;\r
+\r
+          for (Index = TopRow; Index <= BottomRow && Link != NewPos;) {\r
+            SavedMenuOption = MENU_OPTION_FROM_LINK (Link);\r
+            Index += SavedMenuOption->Skip;\r
+            Link = Link->ForwardLink;\r
+          }\r
+\r
+          if (Link != NewPos || Index > BottomRow) {\r
+            //\r
+            // NewPos is not in the current page, simply scroll page so that NewPos is in the end of the page\r
+            //\r
+            Link    = NewPos;\r
+            for (Index = TopRow; Index <= BottomRow; ) {\r
+              Link = Link->BackLink;\r
+              SavedMenuOption = MENU_OPTION_FROM_LINK (Link);\r
+              Index     += SavedMenuOption->Skip;\r
+            }\r
+            TopOfScreen     = Link->ForwardLink;\r
+\r
+            Repaint = TRUE;\r
+            NewLine = TRUE;\r
+            ControlFlag = CfRepaint;\r
+            break;\r
+          }\r
+        } else {\r
+          //\r
+          // Target Question not found, highlight the default menu option\r
+          //\r
+          NewPos = TopOfScreen;\r
+        }\r
+\r
+        Selection->QuestionId = 0;\r
+      }\r
+\r
+      if (NewPos != NULL && (MenuOption == NULL || NewPos != &MenuOption->Link)) {\r
+        if (MenuOption != NULL) {\r
+          //\r
+          // Remove highlight on last Menu Option\r
+          //\r
+          gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);\r
+          ProcessOptions (Selection, MenuOption, FALSE, &OptionString);\r
+          gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);\r
+          if (OptionString != NULL) {\r
+            if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) ||\r
+                (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)\r
+               ) {\r
+              //\r
+              // If leading spaces on OptionString - remove the spaces\r
+              //\r
+              for (Index = 0; OptionString[Index] == L' '; Index++)\r
+                ;\r
+\r
+              for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {\r
+                OptionString[Count] = OptionString[Index];\r
+                Count++;\r
+              }\r
+\r
+              OptionString[Count] = CHAR_NULL;\r
+            }\r
+\r
+            Width               = (UINT16) gOptionBlockWidth;\r
+            OriginalRow         = MenuOption->Row;\r
+\r
+            for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {\r
+              if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {\r
+                PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);\r
+              }\r
+              //\r
+              // If there is more string to process print on the next row and increment the Skip value\r
+              //\r
+              if (StrLen (&OptionString[Index])) {\r
+                MenuOption->Row++;\r
+              }\r
+\r
+              gBS->FreePool (OutputString);\r
+            }\r
+\r
+            MenuOption->Row = OriginalRow;\r
+\r
+            gBS->FreePool (OptionString);\r
+          } else {\r
+            if (NewLine) {\r
+              if (MenuOption->GrayOut) {\r
+                gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_GRAYED | FIELD_BACKGROUND);\r
+              } else if (MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP) {\r
+                gST->ConOut->SetAttribute (gST->ConOut, SUBTITLE_TEXT | FIELD_BACKGROUND);\r
+              }\r
+\r
+              OriginalRow = MenuOption->Row;\r
+              Width       = GetWidth (MenuOption->ThisTag, MenuOption->Handle);\r
+\r
+              for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {\r
+                if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {\r
+                  PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString);\r
+                }\r
+                //\r
+                // If there is more string to process print on the next row and increment the Skip value\r
+                //\r
+                if (StrLen (&MenuOption->Description[Index])) {\r
+                  MenuOption->Row++;\r
+                }\r
+\r
+                gBS->FreePool (OutputString);\r
+              }\r
+\r
+              MenuOption->Row = OriginalRow;\r
+              gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);\r
+            }\r
+          }\r
+        }\r
+\r
+        //\r
+        // This is only possible if we entered this page and the first menu option is\r
+        // a "non-menu" item.  In that case, force it UiDown\r
+        //\r
+        MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+        if (!IsSelectable (MenuOption)) {\r
+          ASSERT (ScreenOperation == UiNoOperation);\r
+          ScreenOperation = UiDown;\r
+          ControlFlag     = CfScreenOperation;\r
+          break;\r
+        }\r
+\r
+        //\r
+        // This is the current selected statement\r
+        //\r
+        Statement = MenuOption->ThisTag;\r
+        Selection->Statement = Statement;\r
+\r
+        //\r
+        // Set reverse attribute\r
+        //\r
+        gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT);\r
+        gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);\r
+\r
+        //\r
+        // Assuming that we have a refresh linked-list created, lets annotate the\r
+        // appropriate entry that we are highlighting with its new attribute.  Just prior to this\r
+        // lets reset all of the entries' attribute so we do not get multiple highlights in he refresh\r
+        //\r
+        if (gMenuRefreshHead != NULL) {\r
+          for (MenuRefreshEntry = gMenuRefreshHead; MenuRefreshEntry != NULL; MenuRefreshEntry = MenuRefreshEntry->Next) {\r
+            MenuRefreshEntry->CurrentAttribute = FIELD_TEXT | FIELD_BACKGROUND;\r
+            if (MenuRefreshEntry->MenuOption == MenuOption) {\r
+              MenuRefreshEntry->CurrentAttribute = FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT;\r
+            }\r
+          }\r
+        }\r
+\r
+        ProcessOptions (Selection, MenuOption, FALSE, &OptionString);\r
+        if (OptionString != NULL) {\r
+          if (Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) {\r
+            //\r
+            // If leading spaces on OptionString - remove the spaces\r
+            //\r
+            for (Index = 0; OptionString[Index] == L' '; Index++)\r
+              ;\r
+\r
+            for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {\r
+              OptionString[Count] = OptionString[Index];\r
+              Count++;\r
+            }\r
+\r
+            OptionString[Count] = CHAR_NULL;\r
+          }\r
+          Width               = (UINT16) gOptionBlockWidth;\r
+\r
+          OriginalRow         = MenuOption->Row;\r
+\r
+          for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {\r
+            if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {\r
+              PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);\r
+            }\r
+            //\r
+            // If there is more string to process print on the next row and increment the Skip value\r
+            //\r
+            if (StrLen (&OptionString[Index])) {\r
+              MenuOption->Row++;\r
+            }\r
+\r
+            gBS->FreePool (OutputString);\r
+          }\r
+\r
+          MenuOption->Row = OriginalRow;\r
+\r
+          gBS->FreePool (OptionString);\r
+        } else {\r
+          if (NewLine) {\r
+            OriginalRow = MenuOption->Row;\r
+\r
+            Width       = GetWidth (Statement, MenuOption->Handle);\r
+\r
+            for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {\r
+              if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {\r
+                PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString);\r
+              }\r
+              //\r
+              // If there is more string to process print on the next row and increment the Skip value\r
+              //\r
+              if (StrLen (&MenuOption->Description[Index])) {\r
+                MenuOption->Row++;\r
+              }\r
+\r
+              gBS->FreePool (OutputString);\r
+            }\r
+\r
+            MenuOption->Row = OriginalRow;\r
+\r
+          }\r
+        }\r
+\r
+        if (((NewPos->ForwardLink != &Menu) && (ScreenOperation == UiDown)) ||\r
+            ((NewPos->BackLink != &Menu) && (ScreenOperation == UiUp)) ||\r
+            (ScreenOperation == UiNoOperation)\r
+            ) {\r
+          UpdateKeyHelp (MenuOption, FALSE);\r
+        }\r
+        //\r
+        // Clear reverse attribute\r
+        //\r
+        gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);\r
+      }\r
+      //\r
+      // Repaint flag will be used when process CfUpdateHelpString, so restore its value\r
+      // if we didn't break halfway when process CfRefreshHighLight.\r
+      //\r
+      Repaint = SavedValue;\r
+      break;\r
+\r
+    case CfUpdateHelpString:\r
+      ControlFlag = CfPrepareToReadKey;\r
+\r
+        if ((Repaint || NewLine) && (gClassOfVfr != EFI_GENERAL_APPLICATION_SUBCLASS)) {\r
+        //\r
+        // Don't print anything if it is a NULL help token\r
+        //\r
+        if (MenuOption->ThisTag->Help == 0) {\r
+          StringPtr = L"\0";\r
+        } else {\r
+          StringPtr = GetToken (MenuOption->ThisTag->Help, MenuOption->Handle);\r
+        }\r
+\r
+        ProcessHelpString (StringPtr, &FormattedString, BottomRow - TopRow);\r
+\r
+        gST->ConOut->SetAttribute (gST->ConOut, HELP_TEXT | FIELD_BACKGROUND);\r
+\r
+        for (Index = 0; Index < BottomRow - TopRow; Index++) {\r
+          //\r
+          // Pad String with spaces to simulate a clearing of the previous line\r
+          //\r
+          for (; GetStringWidth (&FormattedString[Index * gHelpBlockWidth * 2]) / 2 < gHelpBlockWidth;) {\r
+            StrCat (&FormattedString[Index * gHelpBlockWidth * 2], L" ");\r
+          }\r
+\r
+          PrintStringAt (\r
+            LocalScreen.RightColumn - gHelpBlockWidth,\r
+            Index + TopRow,\r
+            &FormattedString[Index * gHelpBlockWidth * 2]\r
+            );\r
+        }\r
+      }\r
+      //\r
+      // Reset this flag every time we finish using it.\r
+      //\r
+      Repaint = FALSE;\r
+      NewLine = FALSE;\r
+      break;\r
+\r
+    case CfPrepareToReadKey:\r
+      ControlFlag = CfReadKey;\r
+      ScreenOperation = UiNoOperation;\r
+      break;\r
+\r
+    case CfReadKey:\r
+      ControlFlag = CfScreenOperation;\r
+\r
+      //\r
+      // Wait for user's selection\r
+      //\r
+      do {\r
+        Status = UiWaitForSingleEvent (gST->ConIn->WaitForKey, 0, MinRefreshInterval);\r
+      } while (Status == EFI_TIMEOUT);\r
+\r
+      if (Status == EFI_TIMEOUT) {\r
+        Key.UnicodeChar = CHAR_CARRIAGE_RETURN;\r
+      } else {\r
+        Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+        //\r
+        // if we encounter error, continue to read another key in.\r
+        //\r
+        if (EFI_ERROR (Status)) {\r
+          ControlFlag = CfReadKey;\r
+          continue;\r
+        }\r
+      }\r
+\r
+      if (IsListEmpty (&Menu) && Key.UnicodeChar != CHAR_NULL) {\r
+        //\r
+        // If the screen has no menu items, and the user didn't select UiPrevious, or UiReset\r
+        //\r
+        break;\r
+      }\r
+\r
+      switch (Key.UnicodeChar) {\r
+      case CHAR_CARRIAGE_RETURN:\r
+        ScreenOperation = UiSelect;\r
+        gDirection      = 0;\r
+        break;\r
+\r
+      //\r
+      // We will push the adjustment of these numeric values directly to the input handler\r
+      //  NOTE: we won't handle manual input numeric\r
+      //\r
+      case '+':\r
+      case '-':\r
+        Statement = MenuOption->ThisTag;\r
+        if ((Statement->Operand == EFI_IFR_DATE_OP)\r
+          || (Statement->Operand == EFI_IFR_TIME_OP)\r
+          || ((Statement->Operand == EFI_IFR_NUMERIC_OP) && (Statement->Step != 0))\r
+        ){\r
+          if (Key.UnicodeChar == '+') {\r
+            gDirection = SCAN_RIGHT;\r
+          } else {\r
+            gDirection = SCAN_LEFT;\r
+          }\r
+          Status = ProcessOptions (Selection, MenuOption, TRUE, &OptionString);\r
+          SafeFreePool (OptionString);\r
+        }\r
+        break;\r
+\r
+      case '^':\r
+        ScreenOperation = UiUp;\r
+        break;\r
+\r
+      case 'V':\r
+      case 'v':\r
+        ScreenOperation = UiDown;\r
+        break;\r
+\r
+      case ' ':\r
+        if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {\r
+          if (MenuOption->ThisTag->Operand == EFI_IFR_CHECKBOX_OP && !MenuOption->GrayOut) {\r
+            ScreenOperation = UiSelect;\r
+          }\r
+        }\r
+        break;\r
+\r
+      case CHAR_NULL:\r
+        if (((Key.ScanCode == SCAN_F1) && ((gFunctionKeySetting & FUNCTION_ONE) != FUNCTION_ONE)) ||\r
+            ((Key.ScanCode == SCAN_F2) && ((gFunctionKeySetting & FUNCTION_TWO) != FUNCTION_TWO)) ||\r
+            ((Key.ScanCode == SCAN_F9) && ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE)) ||\r
+            ((Key.ScanCode == SCAN_F10) && ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN))\r
+            ) {\r
+          //\r
+          // If the function key has been disabled, just ignore the key.\r
+          //\r
+        } else {\r
+          for (Index = 0; Index < sizeof (gScanCodeToOperation) / sizeof (gScanCodeToOperation[0]); Index++) {\r
+            if (Key.ScanCode == gScanCodeToOperation[Index].ScanCode) {\r
+              if (Key.ScanCode == SCAN_F9) {\r
+                //\r
+                // Reset to standard default\r
+                //\r
+                DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
+              }\r
+              ScreenOperation = gScanCodeToOperation[Index].ScreenOperation;\r
+              break;\r
+            }\r
+          }\r
+        }\r
+        break;\r
+      }\r
+      break;\r
+\r
+    case CfScreenOperation:\r
+      if (ScreenOperation != UiPrevious && ScreenOperation != UiReset) {\r
+        //\r
+        // If the screen has no menu items, and the user didn't select UiPrevious, or UiReset\r
+        // ignore the selection and go back to reading keys.\r
+        //\r
+        if (IsListEmpty (&Menu)) {\r
+          ControlFlag = CfReadKey;\r
+          break;\r
+        }\r
+        //\r
+        // if there is nothing logical to place a cursor on, just move on to wait for a key.\r
+        //\r
+        for (Link = Menu.ForwardLink; Link != &Menu; Link = Link->ForwardLink) {\r
+          NextMenuOption = MENU_OPTION_FROM_LINK (Link);\r
+          if (IsSelectable (NextMenuOption)) {\r
+            break;\r
+          }\r
+        }\r
+\r
+        if (Link == &Menu) {\r
+          ControlFlag = CfPrepareToReadKey;\r
+          break;\r
+        }\r
+      } else if (ScreenOperation == UiReset) {\r
+        //\r
+        // Press ESC to exit FormSet\r
+        //\r
+        Selection->Action = UI_ACTION_EXIT;\r
+        Selection->Statement = NULL;\r
+      }\r
+\r
+      for (Index = 0;\r
+           Index < sizeof (gScreenOperationToControlFlag) / sizeof (gScreenOperationToControlFlag[0]);\r
+           Index++\r
+          ) {\r
+        if (ScreenOperation == gScreenOperationToControlFlag[Index].ScreenOperation) {\r
+          ControlFlag = gScreenOperationToControlFlag[Index].ControlFlag;\r
+          break;\r
+        }\r
+      }\r
+      break;\r
+\r
+    case CfUiPrevious:\r
+      ControlFlag = CfCheckSelection;\r
+\r
+      if (IsListEmpty (&gMenuList)) {\r
+        Selection->Action = UI_ACTION_NONE;\r
+        if (IsListEmpty (&Menu)) {\r
+          ControlFlag = CfReadKey;\r
+        }\r
+        break;\r
+      }\r
+\r
+      //\r
+      // Remove the Cached page entry\r
+      //\r
+      UiRemoveMenuListEntry (Selection);\r
+\r
+      Selection->Action = UI_ACTION_REFRESH_FORM;\r
+      Selection->Statement = NULL;\r
+      break;\r
+\r
+    case CfUiSelect:\r
+      ControlFlag = CfCheckSelection;\r
+\r
+      Statement = MenuOption->ThisTag;\r
+      if ((Statement->Operand == EFI_IFR_TEXT_OP) ||\r
+          (Statement->Operand == EFI_IFR_DATE_OP) ||\r
+          (Statement->Operand == EFI_IFR_TIME_OP) ||\r
+          (Statement->Operand == EFI_IFR_NUMERIC_OP && Statement->Step != 0)) {\r
+        break;\r
+      }\r
+\r
+      //\r
+      // Keep highlight on current MenuOption\r
+      //\r
+      Selection->QuestionId = Statement->QuestionId;\r
+\r
+      switch (Statement->Operand) {\r
+      case EFI_IFR_REF_OP:\r
+        if (Statement->RefDevicePath != 0) {\r
+          //\r
+          // Goto another Hii Package list\r
+          //\r
+          ControlFlag = CfUiReset;\r
+          Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+\r
+          StringPtr = GetToken (Statement->RefDevicePath, Selection->FormSet->HiiHandle);\r
+          if (StringPtr == NULL) {\r
+            //\r
+            // No device path string not found, exit\r
+            //\r
+            Selection->Action = UI_ACTION_EXIT;\r
+            Selection->Statement = NULL;\r
+            break;\r
+          }\r
+          BufferSize = StrLen (StringPtr) / 2;\r
+          DevicePath = AllocatePool (BufferSize);\r
+\r
+          HexStringToBuffer ((UINT8 *) DevicePath, &BufferSize, StringPtr);\r
+          Selection->Handle = HiiLibDevicePathToHiiHandle (DevicePath);\r
+          if (Selection->Handle == NULL) {\r
+            //\r
+            // If target Hii Handle not found, exit\r
+            //\r
+            Selection->Action = UI_ACTION_EXIT;\r
+            Selection->Statement = NULL;\r
+            break;\r
+          }\r
+\r
+          gBS->FreePool (StringPtr);\r
+          gBS->FreePool (DevicePath);\r
+\r
+          CopyMem (&Selection->FormSetGuid, &Statement->RefFormSetId, sizeof (EFI_GUID));\r
+          Selection->FormId = Statement->RefFormId;\r
+          Selection->QuestionId = Statement->RefQuestionId;\r
+        } else if (!CompareGuid (&Statement->RefFormSetId, &gZeroGuid)) {\r
+          //\r
+          // Goto another Formset, check for uncommitted data\r
+          //\r
+          ControlFlag = CfUiReset;\r
+          Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+\r
+          CopyMem (&Selection->FormSetGuid, &Statement->RefFormSetId, sizeof (EFI_GUID));\r
+          Selection->FormId = Statement->RefFormId;\r
+          Selection->QuestionId = Statement->RefQuestionId;\r
+        } else if (Statement->RefFormId != 0) {\r
+          //\r
+          // Goto another form inside this formset,\r
+          //\r
+          Selection->Action = UI_ACTION_REFRESH_FORM;\r
+\r
+          //\r
+          // Link current form so that we can always go back when someone hits the UiPrevious\r
+          //\r
+          UiAddMenuListEntry (Selection);\r
+\r
+          Selection->FormId = Statement->RefFormId;\r
+          Selection->QuestionId = Statement->RefQuestionId;\r
+        } else if (Statement->RefQuestionId != 0) {\r
+          //\r
+          // Goto another Question\r
+          //\r
+          Selection->QuestionId = Statement->RefQuestionId;\r
+\r
+          if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
+            Selection->Action = UI_ACTION_REFRESH_FORM;\r
+          } else {\r
+            Repaint = TRUE;\r
+            NewLine = TRUE;\r
+            break;\r
+          }\r
+        }\r
+        break;\r
+\r
+      case EFI_IFR_ACTION_OP:\r
+        //\r
+        // Process the Config string <ConfigResp>\r
+        //\r
+        Status = ProcessQuestionConfig (Selection, Statement);\r
+\r
+        if (EFI_ERROR (Status)) {\r
+          break;\r
+        }\r
+\r
+        //\r
+        // The action button may change some Question value, so refresh the form\r
+        //\r
+        Selection->Action = UI_ACTION_REFRESH_FORM;\r
+        break;\r
+\r
+      case EFI_IFR_RESET_BUTTON_OP:\r
+        //\r
+        // Reset Question to default value specified by DefaultId\r
+        //\r
+        ControlFlag = CfUiDefault;\r
+        DefaultId = Statement->DefaultId;\r
+        break;\r
+\r
+      default:\r
+        //\r
+        // Editable Questions: oneof, ordered list, checkbox, numeric, string, password\r
+        //\r
+        UpdateKeyHelp (MenuOption, TRUE);\r
+        Status = ProcessOptions (Selection, MenuOption, TRUE, &OptionString);\r
+\r
+        if (EFI_ERROR (Status)) {\r
+          Repaint = TRUE;\r
+          NewLine = TRUE;\r
+          break;\r
+        }\r
+\r
+        if (OptionString != NULL) {\r
+          PrintStringAt (LocalScreen.LeftColumn + gPromptBlockWidth + 1, MenuOption->Row, OptionString);\r
+          gBS->FreePool (OptionString);\r
+        }\r
+\r
+        Selection->Action = UI_ACTION_REFRESH_FORM;\r
+        break;\r
+      }\r
+      break;\r
+\r
+    case CfUiReset:\r
+      //\r
+      // We are going to leave current FormSet, so check uncommited data in this FormSet\r
+      //\r
+      ControlFlag = CfCheckSelection;\r
+\r
+      if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {\r
+        //\r
+        // There is no parent menu for FrontPage\r
+        //\r
+        Selection->Action = UI_ACTION_NONE;\r
+        Selection->Statement = MenuOption->ThisTag;\r
+        break;\r
+      }\r
+\r
+      //\r
+      // If NV flag is up, prompt user\r
+      //\r
+      if (gNvUpdateRequired) {\r
+        Status      = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+\r
+        YesResponse = gYesResponse[0];\r
+        NoResponse  = gNoResponse[0];\r
+\r
+        do {\r
+          CreateDialog (3, TRUE, 0, NULL, &Key, gEmptyString, gAreYouSure, gEmptyString);\r
+        } while\r
+        (\r
+          (Key.ScanCode != SCAN_ESC) &&\r
+          ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (NoResponse | UPPER_LOWER_CASE_OFFSET)) &&\r
+          ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (YesResponse | UPPER_LOWER_CASE_OFFSET))\r
+        );\r
+\r
+        //\r
+        // If the user hits the YesResponse key\r
+        //\r
+        if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse | UPPER_LOWER_CASE_OFFSET)) {\r
+        } else {\r
+          Repaint = TRUE;\r
+          NewLine = TRUE;\r
+\r
+          Selection->Action = UI_ACTION_NONE;\r
+          break;\r
+        }\r
+      }\r
+\r
+      gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
+      gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
+\r
+      UiFreeMenuList ();\r
+      gST->ConOut->ClearScreen (gST->ConOut);\r
+      return EFI_SUCCESS;\r
+\r
+    case CfUiLeft:\r
+      ControlFlag = CfCheckSelection;\r
+      if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {\r
+        if (MenuOption->Sequence != 0) {\r
+          //\r
+          // In the middle or tail of the Date/Time op-code set, go left.\r
+          //\r
+          NewPos = NewPos->BackLink;\r
+        }\r
+      }\r
+      break;\r
+\r
+    case CfUiRight:\r
+      ControlFlag = CfCheckSelection;\r
+      if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {\r
+        if (MenuOption->Sequence != 2) {\r
+          //\r
+          // In the middle or tail of the Date/Time op-code set, go left.\r
+          //\r
+          NewPos = NewPos->ForwardLink;\r
+        }\r
+      }\r
+      break;\r
+\r
+    case CfUiUp:\r
+      ControlFlag = CfCheckSelection;\r
+\r
+      SavedListEntry = TopOfScreen;\r
+\r
+      if (NewPos->BackLink != &Menu) {\r
+        NewLine = TRUE;\r
+        //\r
+        // Adjust Date/Time position before we advance forward.\r
+        //\r
+        AdjustDateAndTimePosition (TRUE, &NewPos);\r
+\r
+        //\r
+        // Caution that we have already rewind to the top, don't go backward in this situation.\r
+        //\r
+        if (NewPos->BackLink != &Menu) {\r
+          NewPos = NewPos->BackLink;\r
+        }\r
+\r
+        PreviousMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+        DistanceValue = PreviousMenuOption->Skip;\r
+\r
+        //\r
+        // Since the behavior of hitting the up arrow on a Date/Time op-code is intended\r
+        // to be one that back to the previous set of op-codes, we need to advance to the sencond\r
+        // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate\r
+        // checking can be done.\r
+        //\r
+        DistanceValue += AdjustDateAndTimePosition (TRUE, &NewPos);\r
+\r
+        //\r
+        // Check the previous menu entry to see if it was a zero-length advance.  If it was,\r
+        // don't worry about a redraw.\r
+        //\r
+        if ((INTN) MenuOption->Row - (INTN) DistanceValue < (INTN) TopRow) {\r
+          Repaint     = TRUE;\r
+          TopOfScreen = NewPos;\r
+        }\r
+\r
+        Difference = MoveToNextStatement (TRUE, &NewPos);\r
+        if ((INTN) MenuOption->Row - (INTN) DistanceValue < (INTN) TopRow) {\r
+          if (Difference > 0) {\r
+            //\r
+            // Previous focus MenuOption is above the TopOfScreen, so we need to scroll\r
+            //\r
+            TopOfScreen = NewPos;\r
+            Repaint     = TRUE;\r
+          }\r
+        }\r
+        if (Difference < 0) {\r
+          //\r
+          // We want to goto previous MenuOption, but finally we go down.\r
+          // it means that we hit the begining MenuOption that can be focused\r
+          // so we simply scroll to the top\r
+          //\r
+          if (SavedListEntry != Menu.ForwardLink) {\r
+            TopOfScreen = Menu.ForwardLink;\r
+            Repaint     = TRUE;\r
+          }\r
+        }\r
+\r
+        //\r
+        // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.\r
+        //\r
+        AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
+\r
+        UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);\r
+      } else {\r
+        SavedMenuOption = MenuOption;\r
+        MenuOption      = MENU_OPTION_FROM_LINK (NewPos);\r
+        if (!IsSelectable (MenuOption)) {\r
+          //\r
+          // If we are at the end of the list and sitting on a text op, we need to more forward\r
+          //\r
+          ScreenOperation = UiDown;\r
+          ControlFlag     = CfScreenOperation;\r
+          break;\r
+        }\r
+\r
+        MenuOption = SavedMenuOption;\r
+      }\r
+      break;\r
+\r
+    case CfUiPageUp:\r
+      ControlFlag     = CfCheckSelection;\r
+\r
+      if (NewPos->BackLink == &Menu) {\r
+        NewLine = FALSE;\r
+        Repaint = FALSE;\r
+        break;\r
+      }\r
+\r
+      NewLine   = TRUE;\r
+      Repaint   = TRUE;\r
+      Link      = TopOfScreen;\r
+      PreviousMenuOption = MENU_OPTION_FROM_LINK (Link);\r
+      Index = BottomRow;\r
+      while ((Index >= TopRow) && (Link->BackLink != &Menu)) {\r
+        Index = Index - PreviousMenuOption->Skip;\r
+        Link = Link->BackLink;\r
+        PreviousMenuOption = MENU_OPTION_FROM_LINK (Link);\r
+      }\r
+\r
+      TopOfScreen = Link;\r
+      Difference = MoveToNextStatement (TRUE, &Link);\r
+      if (Difference > 0) {\r
+        //\r
+        // The focus MenuOption is above the TopOfScreen\r
+        //\r
+        TopOfScreen = Link;\r
+      } else if (Difference < 0) {\r
+        //\r
+        // This happens when there is no MenuOption can be focused from\r
+        // Current MenuOption to the first MenuOption\r
+        //\r
+        TopOfScreen = Menu.ForwardLink;\r
+      }\r
+      Index += Difference;\r
+      if (Index < TopRow) {\r
+        MenuOption = NULL;\r
+      }\r
+\r
+      if (NewPos == Link) {\r
+        Repaint = FALSE;\r
+        NewLine = FALSE;\r
+      } else {\r
+        NewPos = Link;\r
+      }\r
+\r
+      //\r
+      // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.\r
+      // Don't do this when we are already in the first page.\r
+      //\r
+      AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
+      AdjustDateAndTimePosition (TRUE, &NewPos);\r
+      break;\r
+\r
+    case CfUiPageDown:\r
+      ControlFlag     = CfCheckSelection;\r
+\r
+      if (NewPos->ForwardLink == &Menu) {\r
+        NewLine = FALSE;\r
+        Repaint = FALSE;\r
+        break;\r
+      }\r
+\r
+      NewLine = TRUE;\r
+      Repaint = TRUE;\r
+      Link    = TopOfScreen;\r
+      NextMenuOption = MENU_OPTION_FROM_LINK (Link);\r
+      Index = TopRow;\r
+      while ((Index <= BottomRow) && (Link->ForwardLink != &Menu)) {\r
+        Index = Index + NextMenuOption->Skip;\r
+        Link           = Link->ForwardLink;\r
+        NextMenuOption = MENU_OPTION_FROM_LINK (Link);\r
+      }\r
+\r
+      Index += MoveToNextStatement (FALSE, &Link);\r
+      if (Index > BottomRow) {\r
+        //\r
+        // There are more MenuOption needing scrolling\r
+        //\r
+        TopOfScreen = Link;\r
+        MenuOption = NULL;\r
+      }\r
+      if (NewPos == Link && Index <= BottomRow) {\r
+        //\r
+        // Finally we know that NewPos is the last MenuOption can be focused.\r
+        //\r
+        NewLine = FALSE;\r
+        Repaint = FALSE;\r
+      } else {\r
+        NewPos  = Link;\r
+      }\r
+\r
+      //\r
+      // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.\r
+      // Don't do this when we are already in the last page.\r
+      //\r
+      AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
+      AdjustDateAndTimePosition (TRUE, &NewPos);\r
+      break;\r
+\r
+    case CfUiDown:\r
+      ControlFlag = CfCheckSelection;\r
+      //\r
+      // Since the behavior of hitting the down arrow on a Date/Time op-code is intended\r
+      // to be one that progresses to the next set of op-codes, we need to advance to the last\r
+      // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate\r
+      // checking can be done.  The only other logic we need to introduce is that if a Date/Time\r
+      // op-code is the last entry in the menu, we need to rewind back to the first op-code of\r
+      // the Date/Time op-code.\r
+      //\r
+      SavedListEntry = NewPos;\r
+      DistanceValue  = AdjustDateAndTimePosition (FALSE, &NewPos);\r
+\r
+      if (NewPos->ForwardLink != &Menu) {\r
+        MenuOption      = MENU_OPTION_FROM_LINK (NewPos);\r
+        NewLine         = TRUE;\r
+        NewPos          = NewPos->ForwardLink;\r
+        NextMenuOption  = MENU_OPTION_FROM_LINK (NewPos);\r
+\r
+        DistanceValue  += NextMenuOption->Skip;\r
+        DistanceValue  += MoveToNextStatement (FALSE, &NewPos);\r
+        //\r
+        // An option might be multi-line, so we need to reflect that data in the overall skip value\r
+        //\r
+        UpdateOptionSkipLines (Selection, NextMenuOption, &OptionString, SkipValue);\r
+\r
+        Temp = MenuOption->Row + MenuOption->Skip + DistanceValue - 1;\r
+        if ((MenuOption->Row + MenuOption->Skip == BottomRow + 1) &&\r
+            (NextMenuOption->ThisTag->Operand == EFI_IFR_DATE_OP ||\r
+             NextMenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)\r
+            ) {\r
+          Temp ++;\r
+        }\r
+\r
+        //\r
+        // If we are going to scroll, update TopOfScreen\r
+        //\r
+        if (Temp > BottomRow) {\r
+          do {\r
+            //\r
+            // Is the current top of screen a zero-advance op-code?\r
+            // If so, keep moving forward till we hit a >0 advance op-code\r
+            //\r
+            SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
+\r
+            //\r
+            // If bottom op-code is more than one line or top op-code is more than one line\r
+            //\r
+            if ((DistanceValue > 1) || (MenuOption->Skip > 1)) {\r
+              //\r
+              // Is the bottom op-code greater than or equal in size to the top op-code?\r
+              //\r
+              if ((Temp - BottomRow) >= (SavedMenuOption->Skip - OldSkipValue)) {\r
+                //\r
+                // Skip the top op-code\r
+                //\r
+                TopOfScreen     = TopOfScreen->ForwardLink;\r
+                Difference      = (Temp - BottomRow) - (SavedMenuOption->Skip - OldSkipValue);\r
+\r
+                OldSkipValue    = Difference;\r
+\r
+                SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
+\r
+                //\r
+                // If we have a remainder, skip that many more op-codes until we drain the remainder\r
+                //\r
+                for (;\r
+                     Difference >= (INTN) SavedMenuOption->Skip;\r
+                     Difference = Difference - (INTN) SavedMenuOption->Skip\r
+                    ) {\r
+                  //\r
+                  // Since the Difference is greater than or equal to this op-code's skip value, skip it\r
+                  //\r
+                  TopOfScreen     = TopOfScreen->ForwardLink;\r
+                  SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
+                  if (Difference < (INTN) SavedMenuOption->Skip) {\r
+                    Difference = SavedMenuOption->Skip - Difference - 1;\r
+                    break;\r
+                  } else {\r
+                    if (Difference == (INTN) SavedMenuOption->Skip) {\r
+                      TopOfScreen     = TopOfScreen->ForwardLink;\r
+                      SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
+                      Difference      = SavedMenuOption->Skip - Difference;\r
+                      break;\r
+                    }\r
+                  }\r
+                }\r
+                //\r
+                // Since we will act on this op-code in the next routine, and increment the\r
+                // SkipValue, set the skips to one less than what is required.\r
+                //\r
+                SkipValue = Difference - 1;\r
+\r
+              } else {\r
+                //\r
+                // Since we will act on this op-code in the next routine, and increment the\r
+                // SkipValue, set the skips to one less than what is required.\r
+                //\r
+                SkipValue = OldSkipValue + (Temp - BottomRow) - 1;\r
+              }\r
+            } else {\r
+              if ((OldSkipValue + 1) == (INTN) SavedMenuOption->Skip) {\r
+                TopOfScreen = TopOfScreen->ForwardLink;\r
+                break;\r
+              } else {\r
+                SkipValue = OldSkipValue;\r
+              }\r
+            }\r
+            //\r
+            // If the op-code at the top of the screen is more than one line, let's not skip it yet\r
+            // Let's set a skip flag to smoothly scroll the top of the screen.\r
+            //\r
+            if (SavedMenuOption->Skip > 1) {\r
+              if (SavedMenuOption == NextMenuOption) {\r
+                SkipValue = 0;\r
+              } else {\r
+                SkipValue++;\r
+              }\r
+            } else {\r
+              SkipValue   = 0;\r
+              TopOfScreen = TopOfScreen->ForwardLink;\r
+            }\r
+          } while (SavedMenuOption->Skip == 0);\r
+\r
+          Repaint       = TRUE;\r
+          OldSkipValue  = SkipValue;\r
+        }\r
+\r
+        MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
+\r
+        UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);\r
+\r
+      } else {\r
+        SavedMenuOption = MenuOption;\r
+        MenuOption      = MENU_OPTION_FROM_LINK (NewPos);\r
+        if (!IsSelectable (MenuOption)) {\r
+          //\r
+          // If we are at the end of the list and sitting on a text op, we need to more forward\r
+          //\r
+          ScreenOperation = UiUp;\r
+          ControlFlag     = CfScreenOperation;\r
+          break;\r
+        }\r
+\r
+        MenuOption = SavedMenuOption;\r
+        //\r
+        // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.\r
+        //\r
+        AdjustDateAndTimePosition (TRUE, &NewPos);\r
+      }\r
+      break;\r
+\r
+    case CfUiSave:\r
+      ControlFlag = CfCheckSelection;\r
+\r
+      //\r
+      // Submit the form\r
+      //\r
+      Status = SubmitForm (Selection->FormSet, Selection->Form);\r
+\r
+      if (!EFI_ERROR (Status)) {\r
+        UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);\r
+        UpdateStatusBar (NV_UPDATE_REQUIRED, MenuOption->ThisTag->QuestionFlags, FALSE);\r
+      } else {\r
+        do {\r
+          CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gSaveFailed, gPressEnter, gEmptyString);\r
+        } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+\r
+        Repaint = TRUE;\r
+        NewLine = TRUE;\r
+      }\r
+      break;\r
+\r
+    case CfUiDefault:\r
+      ControlFlag = CfCheckSelection;\r
+\r
+      Status = ExtractFormDefault (Selection->FormSet, Selection->Form, DefaultId);\r
+\r
+      if (!EFI_ERROR (Status)) {\r
+        Selection->Action = UI_ACTION_REFRESH_FORM;\r
+\r
+        //\r
+        // Show NV update flag on status bar\r
+        //\r
+        gNvUpdateRequired = TRUE;\r
+      }\r
+      break;\r
+\r
+    case CfUiNoOperation:\r
+      ControlFlag = CfCheckSelection;\r
+      break;\r
+\r
+    case CfExit:\r
+      UiFreeRefreshList ();\r
+\r
+      gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
+      gST->ConOut->SetCursorPosition (gST->ConOut, 0, Row + 4);\r
+      gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
+      gST->ConOut->OutputString (gST->ConOut, L"\n");\r
+\r
+      return EFI_SUCCESS;\r
+\r
+    default:\r
+      break;\r
+    }\r
+  }\r
+}\r
index e402248204c7e21fc307b0959a5a0c1a982d28c4..6e6b8975c17bcd2af65c4762e84c19df9f35262e 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:
-
-  Ui.h
-
-Abstract:
-
-  Head file UI
-
-Revision History
-
-
-**/
-
-#ifndef _UI_H
-#define _UI_H
-
-#include "Setup.h"
-
-//
-// Globals
-//
-#define REGULAR_NUMERIC 0
-#define TIME_NUMERIC    1
-#define DATE_NUMERIC    2
-
-#define SUBTITLE_INDENT  2
-
-typedef enum {
-  UiNoOperation,
-  UiDefault,
-  UiSelect,
-  UiUp,
-  UiDown,
-  UiLeft,
-  UiRight,
-  UiReset,
-  UiSave,
-  UiPrevious,
-  UiPageUp,
-  UiPageDown,
-  UiMaxOperation
-} UI_SCREEN_OPERATION;
-
-typedef enum {
-  CfInitialization,
-  CfCheckSelection,
-  CfRepaint,
-  CfRefreshHighLight,
-  CfUpdateHelpString,
-  CfPrepareToReadKey,
-  CfReadKey,
-  CfScreenOperation,
-  CfUiPrevious,
-  CfUiSelect,
-  CfUiReset,
-  CfUiLeft,
-  CfUiRight,
-  CfUiUp,
-  CfUiPageUp,
-  CfUiPageDown,
-  CfUiDown,
-  CfUiSave,
-  CfUiDefault,
-  CfUiNoOperation,
-  CfExit,
-  CfMaxControlFlag
-} UI_CONTROL_FLAG;
-
-#define UI_ACTION_NONE               0
-#define UI_ACTION_REFRESH_FORM       1
-#define UI_ACTION_REFRESH_FORMSET    2
-#define UI_ACTION_EXIT               3
-
-typedef struct {
-  EFI_HII_HANDLE  Handle;
-
-  //
-  // Target formset/form/Question information
-  //
-  EFI_GUID        FormSetGuid;
-  UINT16          FormId;
-  UINT16          QuestionId;
-
-  UINTN           TopRow;
-  UINTN           BottomRow;
-  UINTN           PromptCol;
-  UINTN           OptionCol;
-  UINTN           CurrentRow;
-
-  //
-  // Ation for Browser to taken:
-  //   UI_ACTION_NONE            - navigation inside a form
-  //   UI_ACTION_REFRESH_FORM    - re-evaluate expressions and repaint form
-  //   UI_ACTION_REFRESH_FORMSET - re-parse formset IFR binary
-  //
-  UINTN           Action;
-
-  //
-  // Current selected fomset/form/Question
-  //
-  FORM_BROWSER_FORMSET    *FormSet;
-  FORM_BROWSER_FORM       *Form;
-  FORM_BROWSER_STATEMENT  *Statement;
-} UI_MENU_SELECTION;
-
-#define UI_MENU_OPTION_SIGNATURE  EFI_SIGNATURE_32 ('u', 'i', 'm', 'm')
-#define UI_MENU_LIST_SIGNATURE    EFI_SIGNATURE_32 ('u', 'i', 'm', 'l')
-
-typedef struct {
-  UINTN                   Signature;
-  LIST_ENTRY              Link;
-
-  EFI_HII_HANDLE          Handle;
-  FORM_BROWSER_STATEMENT  *ThisTag;
-  UINT16                  EntryNumber;
-
-  UINTN                   Row;
-  UINTN                   Col;
-  UINTN                   OptCol;
-  CHAR16                  *Description;
-  UINTN                   Skip;           // Number of lines
-
-  //
-  // Display item sequence for date/time
-  //  Date:      Month/Day/Year
-  //  Sequence:  0     1   2
-  //
-  //  Time:      Hour : Minute : Second
-  //  Sequence:  0      1        2
-  //
-  //
-  UINTN                   Sequence;
-
-  BOOLEAN                 GrayOut;
-  BOOLEAN                 ReadOnly;
-} UI_MENU_OPTION;
-
-#define MENU_OPTION_FROM_LINK(a)  CR (a, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE)
-
-typedef struct {
-  UINTN           Signature;
-  LIST_ENTRY      MenuLink;
-
-  UINT16          FormId;
-  UINT16          QuestionId;
-} UI_MENU_LIST;
-
-typedef struct _MENU_REFRESH_ENTRY {
-  struct _MENU_REFRESH_ENTRY  *Next;
-  UI_MENU_OPTION              *MenuOption;  // Describes the entry needing an update
-  UI_MENU_SELECTION           *Selection;
-  UINTN                       CurrentColumn;
-  UINTN                       CurrentRow;
-  UINTN                       CurrentAttribute;
-} MENU_REFRESH_ENTRY;
-
-typedef struct {
-  UINT16              ScanCode;
-  UI_SCREEN_OPERATION ScreenOperation;
-} SCAN_CODE_TO_SCREEN_OPERATION;
-
-typedef struct {
-  UI_SCREEN_OPERATION ScreenOperation;
-  UI_CONTROL_FLAG     ControlFlag;
-} SCREEN_OPERATION_T0_CONTROL_FLAG;
-
-
-extern LIST_ENTRY          gMenuList;
-extern MENU_REFRESH_ENTRY  *gMenuRefreshHead;
-extern UI_MENU_SELECTION   *gCurrentSelection;
-
-//
-// Global Functions
-//
-VOID
-UiInitMenu (
-  VOID
-  )
-;
-
-VOID
-UiInitMenuList (
-  VOID
-  )
-;
-
-VOID
-UiRemoveMenuListEntry (
-  OUT UI_MENU_SELECTION  *Selection
-  )
-;
-
-VOID
-UiFreeMenuList (
-  VOID
-  )
-;
-
-VOID
-UiAddMenuListEntry (
-  IN UI_MENU_SELECTION            *Selection
-  )
-;
-
-VOID
-UiFreeMenu (
-  VOID
-  )
-;
-
-VOID
-UiAddMenuOption (
-  IN CHAR16                  *String,
-  IN EFI_HII_HANDLE          Handle,
-  IN FORM_BROWSER_STATEMENT  *Statement,
-  IN UINT16                  NumberOfLines,
-  IN UINT16                  MenuItemCount
-  )
-;
-
-EFI_STATUS
-UiDisplayMenu (
-  IN OUT UI_MENU_SELECTION           *Selection
-  )
-;
-
-VOID
-FreeBrowserStrings (
-  VOID
-  )
-;
-
-EFI_STATUS
-SetupBrowser (
-  IN OUT UI_MENU_SELECTION    *Selection
-  )
-;
-
-VOID
-ValueToString (
-  IN CHAR16   *Buffer,
-  IN BOOLEAN  Comma,
-  IN INT64    v
-  )
-;
-
-EFI_STATUS
-UiIntToString (
-  IN UINTN      num,
-  IN OUT CHAR16 *str,
-  IN UINT16     size
-  )
-;
-
-VOID
-SetUnicodeMem (
-  IN VOID   *Buffer,
-  IN UINTN  Size,
-  IN CHAR16 Value
-  )
-;
-
-EFI_STATUS
-UiWaitForSingleEvent (
-  IN EFI_EVENT                Event,
-  IN UINT64                   Timeout, OPTIONAL
-  IN UINT8                    RefreshInterval OPTIONAL
-  )
-;
-
-VOID
-CreatePopUp (
-  IN  UINTN                       ScreenWidth,
-  IN  UINTN                       NumberOfLines,
-  IN  CHAR16                      *ArrayOfStrings,
-  ...
-  )
-;
-
-EFI_STATUS
-ReadString (
-  IN  UI_MENU_OPTION              *MenuOption,
-  IN  CHAR16                      *Prompt,
-  OUT CHAR16                      *StringPtr
-  )
-;
-
-EFI_STATUS
-GetSelectionInputPopUp (
-  IN  UI_MENU_SELECTION           *Selection,
-  IN  UI_MENU_OPTION              *MenuOption
-  )
-;
-
-EFI_STATUS
-GetNumericInput (
-  IN  UI_MENU_SELECTION           *Selection,
-  IN  UI_MENU_OPTION              *MenuOption
-  )
-;
-
-VOID
-UpdateStatusBar (
-  IN  UINTN                       MessageType,
-  IN  UINT8                       Flags,
-  IN  BOOLEAN                     State
-  )
-;
-
-EFI_STATUS
-ProcessQuestionConfig (
-  IN  UI_MENU_SELECTION       *Selection,
-  IN  FORM_BROWSER_STATEMENT  *Question
-  )
-;
-
-EFI_STATUS
-PrintFormattedNumber (
-  IN FORM_BROWSER_STATEMENT   *Question,
-  IN OUT CHAR16               *FormattedNumber,
-  IN UINTN                    BufferSize
-  )
-;
-
-QUESTION_OPTION *
-ValueToOption (
-  IN FORM_BROWSER_STATEMENT   *Question,
-  IN EFI_HII_VALUE            *OptionValue
-  )
-;
-
-EFI_STATUS
-ProcessOptions (
-  IN  UI_MENU_SELECTION           *Selection,
-  IN  UI_MENU_OPTION              *MenuOption,
-  IN  BOOLEAN                     Selected,
-  OUT CHAR16                      **OptionString
-  )
-;
-
-VOID
-ProcessHelpString (
-  IN  CHAR16                      *StringPtr,
-  OUT CHAR16                      **FormattedString,
-  IN  UINTN                       RowCount
-  )
-;
-
-VOID
-UpdateKeyHelp (
-  IN  UI_MENU_OPTION              *MenuOption,
-  IN  BOOLEAN                     Selected
-  )
-;
-
-VOID
-ClearLines (
-  UINTN                                       LeftColumn,
-  UINTN                                       RightColumn,
-  UINTN                                       TopRow,
-  UINTN                                       BottomRow,
-  UINTN                                       TextAttribute
-  )
-;
-
-UINTN
-GetStringWidth (
-  CHAR16                                      *String
-  )
-;
-
-UINT16
-GetLineByWidth (
-  IN      CHAR16                      *InputString,
-  IN      UINT16                      LineWidth,
-  IN OUT  UINTN                       *Index,
-  OUT     CHAR16                      **OutputString
-  )
-;
-
-UINT16
-GetWidth (
-  IN FORM_BROWSER_STATEMENT        *Statement,
-  IN EFI_HII_HANDLE                 Handle
-  )
-;
-
-VOID
-NewStrCat (
-  CHAR16                                      *Destination,
-  CHAR16                                      *Source
-  )
-;
-
-EFI_STATUS
-WaitForKeyStroke (
-  OUT  EFI_INPUT_KEY           *Key
-  )
-;
-
-VOID
-ResetScopeStack (
-  VOID
-  )
-;
-
-EFI_STATUS
-PushScope (
-  IN UINT8   Operand
-  )
-;
-
-EFI_STATUS
-PopScope (
-  OUT UINT8     *Operand
-  )
-;
-
-FORM_BROWSER_FORM *
-IdToForm (
-  IN FORM_BROWSER_FORMSET  *FormSet,
-  IN UINT16                FormId
-)
-;
-
-FORM_BROWSER_STATEMENT *
-IdToQuestion (
-  IN FORM_BROWSER_FORMSET  *FormSet,
-  IN FORM_BROWSER_FORM     *Form,
-  IN UINT16                QuestionId
-  )
-;
-
-FORM_EXPRESSION *
-IdToExpression (
-  IN FORM_BROWSER_FORM  *Form,
-  IN UINT8              RuleId
-  )
-;
-
-VOID
-ExtendValueToU64 (
-  IN  EFI_HII_VALUE   *Value
-  )
-;
-
-INTN
-CompareHiiValue (
-  IN  EFI_HII_VALUE   *Value1,
-  IN  EFI_HII_VALUE   *Value2,
-  IN  EFI_HII_HANDLE  HiiHandle OPTIONAL
-  )
-;
-
-EFI_STATUS
-EvaluateExpression (
-  IN FORM_BROWSER_FORMSET  *FormSet,
-  IN FORM_BROWSER_FORM     *Form,
-  IN OUT FORM_EXPRESSION   *Expression
-  )
-;
-
-#endif // _UI_H
+/** @file\r
+Private structure, MACRO and function definitions for User Interface related functionalities.\r
+\r
+Copyright (c) 2004 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _UI_H_\r
+#define _UI_H_\r
+\r
+#include "Setup.h"\r
+\r
+//\r
+// Globals\r
+//\r
+#define REGULAR_NUMERIC 0\r
+#define TIME_NUMERIC    1\r
+#define DATE_NUMERIC    2\r
+\r
+#define SUBTITLE_INDENT  2\r
+\r
+typedef enum {\r
+  UiNoOperation,\r
+  UiDefault,\r
+  UiSelect,\r
+  UiUp,\r
+  UiDown,\r
+  UiLeft,\r
+  UiRight,\r
+  UiReset,\r
+  UiSave,\r
+  UiPrevious,\r
+  UiPageUp,\r
+  UiPageDown,\r
+  UiMaxOperation\r
+} UI_SCREEN_OPERATION;\r
+\r
+typedef enum {\r
+  CfInitialization,\r
+  CfCheckSelection,\r
+  CfRepaint,\r
+  CfRefreshHighLight,\r
+  CfUpdateHelpString,\r
+  CfPrepareToReadKey,\r
+  CfReadKey,\r
+  CfScreenOperation,\r
+  CfUiPrevious,\r
+  CfUiSelect,\r
+  CfUiReset,\r
+  CfUiLeft,\r
+  CfUiRight,\r
+  CfUiUp,\r
+  CfUiPageUp,\r
+  CfUiPageDown,\r
+  CfUiDown,\r
+  CfUiSave,\r
+  CfUiDefault,\r
+  CfUiNoOperation,\r
+  CfExit,\r
+  CfMaxControlFlag\r
+} UI_CONTROL_FLAG;\r
+\r
+#define UI_ACTION_NONE               0\r
+#define UI_ACTION_REFRESH_FORM       1\r
+#define UI_ACTION_REFRESH_FORMSET    2\r
+#define UI_ACTION_EXIT               3\r
+\r
+typedef struct {\r
+  EFI_HII_HANDLE  Handle;\r
+\r
+  //\r
+  // Target formset/form/Question information\r
+  //\r
+  EFI_GUID        FormSetGuid;\r
+  UINT16          FormId;\r
+  UINT16          QuestionId;\r
+\r
+  UINTN           TopRow;\r
+  UINTN           BottomRow;\r
+  UINTN           PromptCol;\r
+  UINTN           OptionCol;\r
+  UINTN           CurrentRow;\r
+\r
+  //\r
+  // Ation for Browser to taken:\r
+  //   UI_ACTION_NONE            - navigation inside a form\r
+  //   UI_ACTION_REFRESH_FORM    - re-evaluate expressions and repaint form\r
+  //   UI_ACTION_REFRESH_FORMSET - re-parse formset IFR binary\r
+  //\r
+  UINTN           Action;\r
+\r
+  //\r
+  // Current selected fomset/form/Question\r
+  //\r
+  FORM_BROWSER_FORMSET    *FormSet;\r
+  FORM_BROWSER_FORM       *Form;\r
+  FORM_BROWSER_STATEMENT  *Statement;\r
+} UI_MENU_SELECTION;\r
+\r
+#define UI_MENU_OPTION_SIGNATURE  EFI_SIGNATURE_32 ('u', 'i', 'm', 'm')\r
+#define UI_MENU_LIST_SIGNATURE    EFI_SIGNATURE_32 ('u', 'i', 'm', 'l')\r
+\r
+typedef struct {\r
+  UINTN                   Signature;\r
+  LIST_ENTRY              Link;\r
+\r
+  EFI_HII_HANDLE          Handle;\r
+  FORM_BROWSER_STATEMENT  *ThisTag;\r
+  UINT16                  EntryNumber;\r
+\r
+  UINTN                   Row;\r
+  UINTN                   Col;\r
+  UINTN                   OptCol;\r
+  CHAR16                  *Description;\r
+  UINTN                   Skip;           // Number of lines\r
+\r
+  //\r
+  // Display item sequence for date/time\r
+  //  Date:      Month/Day/Year\r
+  //  Sequence:  0     1   2\r
+  //\r
+  //  Time:      Hour : Minute : Second\r
+  //  Sequence:  0      1        2\r
+  //\r
+  //\r
+  UINTN                   Sequence;\r
+\r
+  BOOLEAN                 GrayOut;\r
+  BOOLEAN                 ReadOnly;\r
+} UI_MENU_OPTION;\r
+\r
+#define MENU_OPTION_FROM_LINK(a)  CR (a, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE)\r
+\r
+typedef struct {\r
+  UINTN           Signature;\r
+  LIST_ENTRY      MenuLink;\r
+\r
+  UINT16          FormId;\r
+  UINT16          QuestionId;\r
+} UI_MENU_LIST;\r
+\r
+typedef struct _MENU_REFRESH_ENTRY {\r
+  struct _MENU_REFRESH_ENTRY  *Next;\r
+  UI_MENU_OPTION              *MenuOption;  // Describes the entry needing an update\r
+  UI_MENU_SELECTION           *Selection;\r
+  UINTN                       CurrentColumn;\r
+  UINTN                       CurrentRow;\r
+  UINTN                       CurrentAttribute;\r
+} MENU_REFRESH_ENTRY;\r
+\r
+typedef struct {\r
+  UINT16              ScanCode;\r
+  UI_SCREEN_OPERATION ScreenOperation;\r
+} SCAN_CODE_TO_SCREEN_OPERATION;\r
+\r
+typedef struct {\r
+  UI_SCREEN_OPERATION ScreenOperation;\r
+  UI_CONTROL_FLAG     ControlFlag;\r
+} SCREEN_OPERATION_T0_CONTROL_FLAG;\r
+\r
+\r
+extern LIST_ENTRY          gMenuList;\r
+extern MENU_REFRESH_ENTRY  *gMenuRefreshHead;\r
+extern UI_MENU_SELECTION   *gCurrentSelection;\r
+\r
+//\r
+// Global Functions\r
+//\r
+/**\r
+  Initialize Menu option list.\r
+\r
+**/\r
+VOID\r
+UiInitMenu (\r
+  VOID\r
+  )\r
+;\r
+\r
+/**\r
+  Initialize Menu option list.\r
+\r
+**/\r
+VOID\r
+UiInitMenuList (\r
+  VOID\r
+  )\r
+;\r
+\r
+/**\r
+  Remove a Menu in list, and return FormId/QuestionId for previous Menu.\r
+\r
+  @param  Selection              Menu selection.\r
+\r
+**/\r
+VOID\r
+UiRemoveMenuListEntry (\r
+  OUT UI_MENU_SELECTION  *Selection\r
+  )\r
+;\r
+\r
+/**\r
+  Free Menu option linked list.\r
+\r
+**/\r
+VOID\r
+UiFreeMenuList (\r
+  VOID\r
+  )\r
+;\r
+\r
+/**\r
+  Add one menu entry to the linked lst\r
+\r
+  @param  Selection              Menu selection.\r
+\r
+**/\r
+VOID\r
+UiAddMenuListEntry (\r
+  IN UI_MENU_SELECTION            *Selection\r
+  )\r
+;\r
+\r
+/**\r
+  Free Menu option linked list.\r
+\r
+**/\r
+VOID\r
+UiFreeMenu (\r
+  VOID\r
+  )\r
+;\r
+\r
+/**\r
+  Add one menu option by specified description and context.\r
+\r
+  @param  String                 String description for this option.\r
+  @param  Handle                 Hii handle for the package list.\r
+  @param  Statement              Statement of this Menu Option.\r
+  @param  NumberOfLines          Display lines for this Menu Option.\r
+  @param  MenuItemCount          The index for this Option in the Menu.\r
+\r
+**/\r
+VOID\r
+UiAddMenuOption (\r
+  IN CHAR16                  *String,\r
+  IN EFI_HII_HANDLE          Handle,\r
+  IN FORM_BROWSER_STATEMENT  *Statement,\r
+  IN UINT16                  NumberOfLines,\r
+  IN UINT16                  MenuItemCount\r
+  )\r
+;\r
+\r
+/**\r
+  Display menu and wait for user to select one menu option, then return it.\r
+  If AutoBoot is enabled, then if user doesn't select any option,\r
+  after period of time, it will automatically return the first menu option.\r
+\r
+  @param  Selection              Menu selection.\r
+\r
+  @return Return the pointer of the menu which selected,\r
+  @return otherwise return NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+UiDisplayMenu (\r
+  IN OUT UI_MENU_SELECTION           *Selection\r
+  )\r
+;\r
+\r
+/**\r
+  Free up the resource allocated for all strings required\r
+  by Setup Browser.\r
+\r
+**/\r
+VOID\r
+FreeBrowserStrings (\r
+  VOID\r
+  )\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
+\r
+/**\r
+  VSPrint worker function that prints a Value as a decimal number in Buffer.\r
+\r
+  @param  Buffer     Location to place ascii decimal number string of Value.\r
+  @param  Flags      Flags to use in printing decimal string, see file header for\r
+                     details.\r
+  @param  Value      Decimal value to convert to a string in Buffer.\r
+\r
+  @return Number of characters printed.\r
+\r
+**/\r
+VOID\r
+ValueToString (\r
+  IN CHAR16   *Buffer,\r
+  IN BOOLEAN  Flags,\r
+  IN INT64    Value\r
+  )\r
+;\r
+\r
+/**\r
+  Set Buffer to Value for Size bytes.\r
+\r
+  @param  Buffer                 Memory to set.\r
+  @param  Size                   Number of bytes to set\r
+  @param  Value                  Value of the set operation.\r
+\r
+**/\r
+VOID\r
+SetUnicodeMem (\r
+  IN VOID   *Buffer,\r
+  IN UINTN  Size,\r
+  IN CHAR16 Value\r
+  )\r
+;\r
+\r
+/**\r
+  Wait for a given event to fire, or for an optional timeout to expire.\r
+\r
+  @param  Event                  The event to wait for\r
+  @param  Timeout                An optional timeout value in 100 ns units.\r
+  @param  RefreshInterval        Menu refresh interval (in seconds).\r
+\r
+  @retval EFI_SUCCESS            Event fired before Timeout expired.\r
+  @retval EFI_TIME_OUT           Timout expired before Event fired.\r
+\r
+**/\r
+EFI_STATUS\r
+UiWaitForSingleEvent (\r
+  IN EFI_EVENT                Event,\r
+  IN UINT64                   Timeout, OPTIONAL\r
+  IN UINT8                    RefreshInterval OPTIONAL\r
+  )\r
+;\r
+\r
+/**\r
+  Draw a pop up windows based on the dimension, number of lines and\r
+  strings specified.\r
+\r
+  @param RequestedWidth  The width of the pop-up.\r
+  @param NumberOfLines   The number of lines.\r
+  @param ArrayOfStrings  The array of string to be printed.\r
+  @param ...             A series of text strings that displayed in the pop-up.\r
+\r
+**/\r
+VOID\r
+CreatePopUp (\r
+  IN  UINTN                       ScreenWidth,\r
+  IN  UINTN                       NumberOfLines,\r
+  IN  CHAR16                      *ArrayOfStrings,\r
+  ...\r
+  )\r
+;\r
+\r
+/**\r
+  Get string or password input from user.\r
+\r
+  @param  MenuOption        Pointer to the current input menu.\r
+  @param  Prompt            The prompt string shown on popup window.\r
+  @param  StringPtr         Destination for use input string.\r
+\r
+  @retval EFI_SUCCESS       If string input is read successfully\r
+  @retval EFI_DEVICE_ERROR  If operation fails\r
+\r
+**/\r
+EFI_STATUS\r
+ReadString (\r
+  IN  UI_MENU_OPTION              *MenuOption,\r
+  IN  CHAR16                      *Prompt,\r
+  OUT CHAR16                      *StringPtr\r
+  )\r
+;\r
+\r
+/**\r
+  Get selection for OneOf and OrderedList (Left/Right will be ignored).\r
+\r
+  @param  Selection         Pointer to current selection.\r
+  @param  MenuOption        Pointer to the current input menu.\r
+\r
+  @retval EFI_SUCCESS       If Option input is processed successfully\r
+  @retval EFI_DEVICE_ERROR  If operation fails\r
+\r
+**/\r
+EFI_STATUS\r
+GetSelectionInputPopUp (\r
+  IN  UI_MENU_SELECTION           *Selection,\r
+  IN  UI_MENU_OPTION              *MenuOption\r
+  )\r
+;\r
+\r
+/**\r
+  This routine reads a numeric value from the user input.\r
+\r
+  @param  Selection         Pointer to current selection.\r
+  @param  MenuOption        Pointer to the current input menu.\r
+\r
+  @retval EFI_SUCCESS       If numerical input is read successfully\r
+  @retval EFI_DEVICE_ERROR  If operation fails\r
+\r
+**/\r
+EFI_STATUS\r
+GetNumericInput (\r
+  IN  UI_MENU_SELECTION           *Selection,\r
+  IN  UI_MENU_OPTION              *MenuOption\r
+  )\r
+;\r
+\r
+/**\r
+  Update status bar on the bottom of menu.\r
+\r
+  @param  MessageType            The type of message to be shown.\r
+  @param  Flags                  The flags in Question header.\r
+  @param  State                  Set or clear.\r
+\r
+**/\r
+VOID\r
+UpdateStatusBar (\r
+  IN  UINTN                       MessageType,\r
+  IN  UINT8                       Flags,\r
+  IN  BOOLEAN                     State\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
+\r
+/**\r
+  Print Question Value according to it's storage width and display attributes.\r
+\r
+  @param  Question               The Question to be printed.\r
+  @param  FormattedNumber        Buffer for output string.\r
+  @param  BufferSize             The FormattedNumber buffer size in bytes.\r
+\r
+  @retval EFI_SUCCESS            Print success.\r
+  @retval EFI_BUFFER_TOO_SMALL   Buffer size is not enough for formatted number.\r
+\r
+**/\r
+EFI_STATUS\r
+PrintFormattedNumber (\r
+  IN FORM_BROWSER_STATEMENT   *Question,\r
+  IN OUT CHAR16               *FormattedNumber,\r
+  IN UINTN                    BufferSize\r
+  )\r
+;\r
+\r
+/**\r
+  Search an Option of a Question by its value.\r
+\r
+  @param  Question               The Question\r
+  @param  OptionValue            Value for Option to be searched.\r
+\r
+  @retval Pointer                Pointer to the found Option.\r
+  @retval NULL                   Option not found.\r
+\r
+**/\r
+QUESTION_OPTION *\r
+ValueToOption (\r
+  IN FORM_BROWSER_STATEMENT   *Question,\r
+  IN EFI_HII_VALUE            *OptionValue\r
+  )\r
+;\r
+\r
+/**\r
+  Process a Question's Option (whether selected or un-selected).\r
+\r
+  @param  Selection              Pointer to UI_MENU_SELECTION.\r
+  @param  MenuOption             The MenuOption for this Question.\r
+  @param  Selected               TRUE: if Question is selected.\r
+  @param  OptionString           Pointer of the Option String to be displayed.\r
+\r
+  @retval EFI_SUCCESS            Question Option process success.\r
+  @retval Other                  Question Option process fail.\r
+\r
+**/\r
+EFI_STATUS\r
+ProcessOptions (\r
+  IN  UI_MENU_SELECTION           *Selection,\r
+  IN  UI_MENU_OPTION              *MenuOption,\r
+  IN  BOOLEAN                     Selected,\r
+  OUT CHAR16                      **OptionString\r
+  )\r
+;\r
+\r
+/**\r
+  Process the help string: Split StringPtr to several lines of strings stored in\r
+  FormattedString and the glyph width of each line cannot exceed gHelpBlockWidth.\r
+\r
+  @param  StringPtr              The entire help string.\r
+  @param  FormattedString        The oupput formatted string.\r
+  @param  RowCount               TRUE: if Question is selected.\r
+\r
+**/\r
+VOID\r
+ProcessHelpString (\r
+  IN  CHAR16                      *StringPtr,\r
+  OUT CHAR16                      **FormattedString,\r
+  IN  UINTN                       RowCount\r
+  )\r
+;\r
+\r
+/**\r
+  Update key's help imformation.\r
+\r
+  @param  MenuOption     The Menu option\r
+  @param  Selected       Whether or not a tag be selected\r
+\r
+**/\r
+VOID\r
+UpdateKeyHelp (\r
+  IN  UI_MENU_OPTION              *MenuOption,\r
+  IN  BOOLEAN                     Selected\r
+  )\r
+;\r
+\r
+/**\r
+  Clear retangle with specified text attribute.\r
+\r
+  @param  LeftColumn     Left column of retangle.\r
+  @param  RightColumn    Right column of retangle.\r
+  @param  TopRow         Start row of retangle.\r
+  @param  BottomRow      End row of retangle.\r
+  @param  TextAttribute  The character foreground and background.\r
+\r
+**/\r
+VOID\r
+ClearLines (\r
+  UINTN                                       LeftColumn,\r
+  UINTN                                       RightColumn,\r
+  UINTN                                       TopRow,\r
+  UINTN                                       BottomRow,\r
+  UINTN                                       TextAttribute\r
+  )\r
+;\r
+\r
+/**\r
+  Count the storage space of a Unicode string.\r
+\r
+  This function handles the Unicode string with NARROW_CHAR\r
+  and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR\r
+  does not count in the resultant output. If a WIDE_CHAR is \r
+  hit, then 2 Unicode character will consume an output storage\r
+  space with size of CHAR16 till a NARROW_CHAR is hit.\r
+\r
+  @param String          The input string to be counted.\r
+\r
+  @return Storage space for the input string.\r
+\r
+**/\r
+UINTN\r
+GetStringWidth (\r
+  CHAR16                                      *String\r
+  )\r
+;\r
+\r
+/**\r
+  Will copy LineWidth amount of a string in the OutputString buffer and return the\r
+  number of CHAR16 characters that were copied into the OutputString buffer.\r
+\r
+  @param  InputString            String description for this option.\r
+  @param  LineWidth              Width of the desired string to extract in CHAR16\r
+                                 characters\r
+  @param  Index                  Where in InputString to start the copy process\r
+  @param  OutputString           Buffer to copy the string into\r
+\r
+  @return Returns the number of CHAR16 characters that were copied into the OutputString buffer.\r
+\r
+**/\r
+UINT16\r
+GetLineByWidth (\r
+  IN      CHAR16                      *InputString,\r
+  IN      UINT16                      LineWidth,\r
+  IN OUT  UINTN                       *Index,\r
+  OUT     CHAR16                      **OutputString\r
+  )\r
+;\r
+\r
+/**\r
+  Get the supported width for a particular op-code\r
+\r
+  @param  Statement              The FORM_BROWSER_STATEMENT structure passed in.\r
+  @param  Handle                 The handle in the HII database being used\r
+\r
+  @return Returns the number of CHAR16 characters that is support.\r
+\r
+**/\r
+UINT16\r
+GetWidth (\r
+  IN FORM_BROWSER_STATEMENT        *Statement,\r
+  IN EFI_HII_HANDLE                 Handle\r
+  )\r
+;\r
+\r
+/**\r
+  Concatenate a narrow string to another string.\r
+\r
+  @param Destination The destination string.\r
+  @param Source      The source string. The string to be concatenated.\r
+                     to the end of Destination.\r
+\r
+**/\r
+VOID\r
+NewStrCat (\r
+  CHAR16                                      *Destination,\r
+  CHAR16                                      *Source\r
+  )\r
+;\r
+\r
+/**\r
+  Wait for a key to be pressed by user.\r
+\r
+  @param Key         The key which is pressed by user.\r
+\r
+  @retval EFI_SUCCESS The function always completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+WaitForKeyStroke (\r
+  OUT  EFI_INPUT_KEY           *Key\r
+  )\r
+;\r
+\r
+/**\r
+  Reset stack pointer to begin of the stack.\r
+\r
+**/\r
+VOID\r
+ResetScopeStack (\r
+  VOID\r
+  )\r
+;\r
+\r
+/**\r
+  Push an Operand onto the Stack\r
+\r
+  @param  Operand                Operand to push.\r
+\r
+  @retval EFI_SUCCESS            The value was pushed onto the stack.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the\r
+                                 stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushScope (\r
+  IN UINT8   Operand\r
+  )\r
+;\r
+\r
+/**\r
+  Pop an Operand from the Stack\r
+\r
+  @param  Operand                Operand to pop.\r
+\r
+  @retval EFI_SUCCESS            The value was pushed onto the stack.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the\r
+                                 stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopScope (\r
+  OUT UINT8     *Operand\r
+  )\r
+;\r
+\r
+/**\r
+  Get Form given its FormId.\r
+\r
+  @param  FormSet                The formset which contains this form.\r
+  @param  FormId                 Id of this form.\r
+\r
+  @retval Pointer                The form.\r
+  @retval NULL                   Specified Form is not found in the formset.\r
+\r
+**/\r
+FORM_BROWSER_FORM *\r
+IdToForm (\r
+  IN FORM_BROWSER_FORMSET  *FormSet,\r
+  IN UINT16                FormId\r
+  )\r
+;\r
+\r
+/**\r
+  Search a Question in Formset scope using its QuestionId.\r
+\r
+  @param  FormSet                The formset which contains this form.\r
+  @param  Form                   The form which contains this Question.\r
+  @param  QuestionId             Id of this Question.\r
+\r
+  @retval Pointer                The Question.\r
+  @retval NULL                   Specified Question not found in the form.\r
+\r
+**/\r
+FORM_BROWSER_STATEMENT *\r
+IdToQuestion (\r
+  IN FORM_BROWSER_FORMSET  *FormSet,\r
+  IN FORM_BROWSER_FORM     *Form,\r
+  IN UINT16                QuestionId\r
+  )\r
+;\r
+\r
+/**\r
+  Zero extend integer/boolean/date/time to UINT64 for comparing.\r
+\r
+  @param  Value                  HII Value to be converted.\r
+\r
+**/\r
+VOID\r
+ExtendValueToU64 (\r
+  IN  EFI_HII_VALUE   *Value\r
+  )\r
+;\r
+\r
+/**\r
+  Compare two Hii value.\r
+\r
+  @param  Value1                 Expression value to compare on left-hand.\r
+  @param  Value2                 Expression value to compare on right-hand.\r
+  @param  HiiHandle              Only required for string compare.\r
+\r
+  @retval EFI_INVALID_PARAMETER  Could not perform comparation on two values.\r
+  @retval 0                      Two operators equeal.\r
+  @return Positive value if Value1 is greater than Value2.\r
+  @retval Negative value if Value1 is less than Value2.\r
+\r
+**/\r
+INTN\r
+CompareHiiValue (\r
+  IN  EFI_HII_VALUE   *Value1,\r
+  IN  EFI_HII_VALUE   *Value2,\r
+  IN  EFI_HII_HANDLE  HiiHandle OPTIONAL\r
+  )\r
+;\r
+\r
+/**\r
+  Evaluate the result of a HII expression\r
+\r
+  @param  FormSet                FormSet associated with this expression.\r
+  @param  Form                   Form associated with this expression.\r
+  @param  Expression             Expression to be evaluated.\r
+\r
+  @retval EFI_SUCCESS            The expression evaluated successfuly\r
+  @retval EFI_NOT_FOUND          The Question which referenced by a QuestionId\r
+                                 could not be found.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the\r
+                                 stack.\r
+  @retval EFI_ACCESS_DENIED      The pop operation underflowed the stack\r
+  @retval EFI_INVALID_PARAMETER  Syntax error with the Expression\r
+\r
+**/\r
+EFI_STATUS\r
+EvaluateExpression (\r
+  IN FORM_BROWSER_FORMSET  *FormSet,\r
+  IN FORM_BROWSER_FORM     *Form,\r
+  IN OUT FORM_EXPRESSION   *Expression\r
+  )\r
+;\r
+\r
+#endif // _UI_H\r