]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/SetupBrowserDxe/Expression.c
Add the missing check for NULL pointer before use it.
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Expression.c
index adeada2b292a41141d5f12e17b682be626ce185d..45ec96edf1bf736bc84eb8fb45975eeeb3eac384 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 = R8_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 = 0xFFFFFFFFFFFFFFFF;
-  } else {
-    StringPtr = StrStr (String[1] + Base, String[0]);
-    Result->Value.u64 = (StringPtr == NULL) ? 0xFFFFFFFFFFFFFFFF : (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 - 2010, 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
+// 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
+UINTN         mExpressionEvaluationStackOffset = 0;\r
+\r
+EFI_HII_VALUE *mCurrentExpressionStack = NULL;\r
+EFI_HII_VALUE *mCurrentExpressionEnd = NULL;\r
+EFI_HII_VALUE *mCurrentExpressionPointer = NULL;\r
+\r
+EFI_HII_VALUE *mMapExpressionListStack = NULL;\r
+EFI_HII_VALUE *mMapExpressionListEnd = NULL;\r
+EFI_HII_VALUE *mMapExpressionListPointer = NULL;\r
+\r
+//\r
+// Unicode collation protocol interface\r
+//\r
+EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollation = NULL;\r
+EFI_USER_MANAGER_PROTOCOL      *mUserManager = NULL;\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
+    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\r
+  @param  StackPtr               On input: old stack pointer; On output: new stack pointer\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  EFI_HII_VALUE          *Stack,\r
+  IN OUT EFI_HII_VALUE       **StackPtr,\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
+ResetCurrentExpressionStack (\r
+  VOID\r
+  )\r
+{\r
+  mCurrentExpressionPointer = mCurrentExpressionStack;\r
+}\r
+\r
+\r
+/**\r
+  Push current expression onto the Stack\r
+\r
+  @param  Pointer                Pointer to current expression.\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 stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushCurrentExpression (\r
+  IN VOID  *Pointer\r
+  )\r
+{\r
+  EFI_HII_VALUE  Data;\r
+\r
+  Data.Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+  Data.Value.u64 = (UINT64) (UINTN) Pointer;\r
+\r
+  return PushStack (\r
+    &mCurrentExpressionStack,\r
+    &mCurrentExpressionPointer,\r
+    &mCurrentExpressionEnd,\r
+    &Data\r
+    );\r
+}\r
+\r
+\r
+/**\r
+  Pop current expression from the Stack\r
+\r
+  @param  Pointer                Pointer to current expression to be 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 stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopCurrentExpression (\r
+  OUT VOID    **Pointer\r
+  )\r
+{\r
+  EFI_STATUS     Status;\r
+  EFI_HII_VALUE  Data;\r
+\r
+  Status = PopStack (\r
+    mCurrentExpressionStack,\r
+    &mCurrentExpressionPointer,\r
+    &Data\r
+    );\r
+\r
+  *Pointer = (VOID *) (UINTN) Data.Value.u64;\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Reset stack pointer to begin of the stack.\r
+\r
+**/\r
+VOID\r
+ResetMapExpressionListStack (\r
+  VOID\r
+  )\r
+{\r
+  mMapExpressionListPointer = mMapExpressionListStack;\r
+}\r
+\r
+\r
+/**\r
+  Push the list of map expression onto the Stack\r
+\r
+  @param  Pointer                Pointer to the list of map expression to be pushed.\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 stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushMapExpressionList (\r
+  IN VOID  *Pointer\r
+  )\r
+{\r
+  EFI_HII_VALUE  Data;\r
+\r
+  Data.Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+  Data.Value.u64 = (UINT64) (UINTN) Pointer;\r
+\r
+  return PushStack (\r
+    &mMapExpressionListStack,\r
+    &mMapExpressionListPointer,\r
+    &mMapExpressionListEnd,\r
+    &Data\r
+    );\r
+}\r
+\r
+\r
+/**\r
+  Pop the list of map expression from the Stack\r
+\r
+  @param  Pointer                Pointer to the list of map expression to be 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 stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopMapExpressionList (\r
+  OUT VOID    **Pointer\r
+  )\r
+{\r
+  EFI_STATUS     Status;\r
+  EFI_HII_VALUE  Data;\r
+\r
+  Status = PopStack (\r
+    mMapExpressionListStack,\r
+    &mMapExpressionListPointer,\r
+    &Data\r
+    );\r
+\r
+  *Pointer = (VOID *) (UINTN) Data.Value.u64;\r
+\r
+  return Status;\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
+             &Data\r
+             );\r
+\r
+  *Operand = Data.Value.u8;\r
+\r
+  return Status;\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 + mExpressionEvaluationStackOffset,\r
+           &mExpressionEvaluationStackPointer,\r
+           Value\r
+           );\r
+}\r
+\r
+/**\r
+  Get current stack offset from stack start.\r
+\r
+  @return Stack offset to stack start.\r
+**/\r
+UINTN\r
+SaveExpressionEvaluationStackOffset (\r
+  )\r
+{\r
+  UINTN TempStackOffset;\r
+  TempStackOffset = mExpressionEvaluationStackOffset;\r
+  mExpressionEvaluationStackOffset = mExpressionEvaluationStackPointer - mExpressionEvaluationStack;\r
+  return TempStackOffset;\r
+}\r
+\r
+/**\r
+  Restore stack offset based on input stack offset\r
+\r
+  @param  StackOffset  Offset to stack start.\r
+\r
+**/\r
+VOID\r
+RestoreExpressionEvaluationStackOffset (\r
+  UINTN StackOffset\r
+  )\r
+{\r
+  mExpressionEvaluationStackOffset = StackOffset;\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
+      //\r
+      // EFI variable storage may be updated by Callback() asynchronous,\r
+      // to keep synchronous, always reload the Question Value.\r
+      //\r
+      if (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+        GetQuestionValue (FormSet, Form, Question, FALSE);\r
+      }\r
+\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
+  IN 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
+\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
+      Result->Value.u64 = StrHexToUint64 (String);\r
+    } else {\r
+      //\r
+      // decimal string\r
+      //\r
+      Result->Value.u64 = StrDecimalToUint64 (String);\r
+    }\r
+    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[Index] == 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
+  if (String[0] != NULL) {\r
+    FreePool (String[0]);\r
+  }\r
+  if (String[1] != NULL) {\r
+    FreePool (String[1]);\r
+  }\r
+  if (StringPtr != NULL) {\r
+    FreePool (StringPtr);\r
+  }\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 [Index] == 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
+  if (String[0] != NULL) {\r
+    FreePool (String[0]);\r
+  }\r
+  if (String[1] != NULL) {\r
+    FreePool (String[1]);\r
+  }\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[Index] == 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
+  if (String[0] != NULL) {\r
+    FreePool (String[0]);\r
+  }\r
+  if (String[1] != NULL) {\r
+    FreePool (String[1]);\r
+  }\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
+  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[Index] == 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
+  if (String[0] != NULL) {\r
+    FreePool (String[0]);\r
+  }\r
+  if (String[1] != NULL) {\r
+    FreePool (String[1]);\r
+  }\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 [Index] == 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
+  if (String[0] != NULL) {\r
+    FreePool (String[0]);\r
+  }\r
+  if (String[1] != NULL) {\r
+    FreePool (String[1]);\r
+  }\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 compare on two values.\r
+  @retval 0                      Two operators equal.\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
+      FreePool (Str1);\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    Result = StrCmp (Str1, Str2);\r
+\r
+    FreePool (Str1);\r
+    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
+  Check if current user has the privilege specified by the permissions GUID.\r
+\r
+  @param[in] Guid  A GUID specifying setup access permissions.\r
+\r
+  @retval TRUE     Current user has the privilege.\r
+  @retval FALSE    Current user does not have the privilege.\r
+**/\r
+BOOLEAN\r
+CheckUserPrivilege (\r
+  IN EFI_GUID *Guid\r
+  )\r
+{\r
+  EFI_STATUS                   Status;\r
+  EFI_USER_PROFILE_HANDLE      UserProfileHandle;\r
+  EFI_USER_INFO_HANDLE         UserInfoHandle;\r
+  EFI_USER_INFO                *UserInfo;\r
+  EFI_GUID                     *UserPermissionsGuid;\r
+  UINTN                        UserInfoSize;\r
+  UINTN                        AccessControlDataSize;\r
+  EFI_USER_INFO_ACCESS_CONTROL *AccessControl;\r
+  UINTN                        RemainSize;\r
+\r
+  if (mUserManager == NULL) {\r
+    Status = gBS->LocateProtocol (\r
+                    &gEfiUserManagerProtocolGuid,\r
+                    NULL,\r
+                    (VOID **) &mUserManager\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      ///\r
+      /// If the system does not support user management, then it is assumed that\r
+      /// all users have admin privilege and evaluation of each EFI_IFR_SECURITY\r
+      /// op-code is always TRUE.\r
+      ///\r
+      return TRUE;\r
+    }\r
+  }\r
+\r
+  Status = mUserManager->Current (mUserManager, &UserProfileHandle);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  ///\r
+  /// Enumerate all user information of the current user profile\r
+  /// to look for any EFI_USER_INFO_ACCESS_SETUP record.\r
+  ///\r
+  \r
+  for (UserInfoHandle = NULL;;) {\r
+    Status = mUserManager->GetNextInfo (mUserManager, UserProfileHandle, &UserInfoHandle);\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+\r
+    UserInfoSize = 0;\r
+    Status = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, NULL, &UserInfoSize);\r
+    if (Status != EFI_BUFFER_TOO_SMALL) {\r
+      continue;\r
+    }\r
+\r
+    UserInfo = (EFI_USER_INFO *) AllocatePool (UserInfoSize);\r
+    if (UserInfo == NULL) {\r
+      break;\r
+    }\r
+\r
+    Status = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, UserInfo, &UserInfoSize);\r
+    if (EFI_ERROR (Status) ||\r
+        UserInfo->InfoType != EFI_USER_INFO_ACCESS_POLICY_RECORD ||\r
+        UserInfo->InfoSize <= sizeof (EFI_USER_INFO)) {\r
+      FreePool (UserInfo);\r
+      continue;\r
+    }\r
+\r
+    RemainSize = UserInfo->InfoSize - sizeof (EFI_USER_INFO);\r
+    AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)(UserInfo + 1);\r
+    while (RemainSize >= sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {\r
+      if (RemainSize < AccessControl->Size || AccessControl->Size <= sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {\r
+        break;\r
+      }\r
+      if (AccessControl->Type == EFI_USER_INFO_ACCESS_SETUP) {\r
+        ///\r
+        /// Check if current user has the privilege specified by the permissions GUID.\r
+        ///\r
+\r
+        UserPermissionsGuid = (EFI_GUID *)(AccessControl + 1);\r
+        AccessControlDataSize = AccessControl->Size - sizeof (EFI_USER_INFO_ACCESS_CONTROL);\r
+        while (AccessControlDataSize >= sizeof (EFI_GUID)) {\r
+          if (CompareGuid (Guid, UserPermissionsGuid)) {\r
+            FreePool (UserInfo);\r
+            return TRUE;\r
+          }\r
+          UserPermissionsGuid++;\r
+          AccessControlDataSize -= sizeof (EFI_GUID);\r
+        }\r
+      }\r
+      RemainSize -= AccessControl->Size;\r
+      AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)((UINT8 *)AccessControl + AccessControl->Size);\r
+    }\r
+\r
+    FreePool (UserInfo);\r
+  }\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Evaluate the result of a HII expression.\r
+\r
+  If Expression is NULL, then ASSERT.\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
+  CHAR16                  *NameValue;\r
+  UINT32                  TempValue;\r
+  LIST_ENTRY              *SubExpressionLink;\r
+  FORM_EXPRESSION         *SubExpression;\r
+  UINTN                   StackOffset;\r
+  UINTN                   TempLength;\r
+  CHAR16                  TempStr[5];\r
+  UINT8                   DigitUint8;\r
+  UINT8                   *TempBuffer;\r
+  EFI_TIME                EfiTime;\r
+\r
+  //\r
+  // Save current stack offset.\r
+  //\r
+  StackOffset = SaveExpressionEvaluationStackOffset ();\r
+\r
+  ASSERT (Expression != NULL);\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
+        Status = EFI_NOT_FOUND;\r
+        goto Done;\r
+      }\r
+\r
+      Result = CompareHiiValue (&Question->HiiValue, &OpCode->Value, NULL);\r
+      if (Result == EFI_INVALID_PARAMETER) {\r
+        Status = EFI_INVALID_PARAMETER;\r
+        goto Done;\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
+        Status = EFI_NOT_FOUND;\r
+        goto Done;\r
+      }\r
+\r
+      Question2 = IdToQuestion (FormSet, Form, OpCode->QuestionId2);\r
+      if (Question2 == NULL) {\r
+        Status = EFI_NOT_FOUND;\r
+        goto Done;\r
+      }\r
+\r
+      Result = CompareHiiValue (&Question->HiiValue, &Question2->HiiValue, FormSet->HiiHandle);\r
+      if (Result == EFI_INVALID_PARAMETER) {\r
+        Status = EFI_INVALID_PARAMETER;\r
+        goto Done;\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
+        Status = EFI_NOT_FOUND;\r
+        goto Done;\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
+        goto Done;\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
+        Status = EFI_NOT_FOUND;\r
+        goto Done;\r
+      }\r
+\r
+      Value = &Question->HiiValue;\r
+      break;\r
+\r
+    case EFI_IFR_SECURITY_OP:\r
+      Value->Value.b = CheckUserPrivilege (&OpCode->Guid);\r
+      break;\r
+\r
+    case EFI_IFR_GET_OP:\r
+      //\r
+      // Get Value from VarStore buffer, EFI VarStore, Name/Value VarStore.\r
+      //\r
+      Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+      Value->Value.u8 = 0;\r
+      if (OpCode->VarStorage != NULL) {\r
+        switch (OpCode->VarStorage->Type) {\r
+        case EFI_HII_VARSTORE_BUFFER:\r
+          //\r
+          // Get value from Edit Buffer\r
+          //\r
+          Value->Type = OpCode->ValueType;\r
+          CopyMem (&Value->Value, OpCode->VarStorage->EditBuffer + OpCode->VarStoreInfo.VarOffset, OpCode->ValueWidth);\r
+          break;\r
+        case EFI_HII_VARSTORE_NAME_VALUE:\r
+          if (OpCode->ValueType != EFI_IFR_TYPE_STRING) {\r
+            //\r
+            // Get value from string except for STRING value.\r
+            //\r
+            Status = GetValueByName (OpCode->VarStorage, OpCode->ValueName, &StrPtr);\r
+            if (!EFI_ERROR (Status)) {\r
+              ASSERT (StrPtr != NULL);\r
+              TempLength = StrLen (StrPtr);\r
+              if (OpCode->ValueWidth >= ((TempLength + 1) / 2)) {\r
+                Value->Type = OpCode->ValueType;\r
+                TempBuffer = (UINT8 *) &Value->Value;\r
+                ZeroMem (TempStr, sizeof (TempStr));\r
+                for (Index = 0; Index < TempLength; Index ++) {\r
+                  TempStr[0] = StrPtr[TempLength - Index - 1];\r
+                  DigitUint8 = (UINT8) StrHexToUint64 (TempStr);\r
+                  if ((Index & 1) == 0) {\r
+                    TempBuffer [Index/2] = DigitUint8;\r
+                  } else {\r
+                    TempBuffer [Index/2] = (UINT8) ((DigitUint8 << 4) + TempBuffer [Index/2]);\r
+                  }\r
+                }\r
+              }                \r
+            }\r
+          }\r
+          break;\r
+        case EFI_HII_VARSTORE_EFI_VARIABLE:\r
+          //\r
+          // Get value from variable.\r
+          //\r
+          TempLength = OpCode->ValueWidth;\r
+          Value->Type = OpCode->ValueType;\r
+          Status = gRT->GetVariable (\r
+                          OpCode->ValueName,\r
+                          &OpCode->VarStorage->Guid,\r
+                          NULL,\r
+                          &TempLength,\r
+                          &Value->Value\r
+                          );\r
+          if (EFI_ERROR (Status)) {\r
+            Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+            Value->Value.u8 = 0;\r
+          }\r
+        default:\r
+          //\r
+          // Not recognize storage.\r
+          //\r
+          Status = EFI_UNSUPPORTED;\r
+          goto Done;\r
+        }\r
+      } else {\r
+        //\r
+        // For Time/Date Data\r
+        //\r
+        if (OpCode->ValueType != EFI_IFR_TYPE_DATE && OpCode->ValueType != EFI_IFR_TYPE_TIME) {\r
+          //\r
+          // Only support Data/Time data when storage doesn't exist.\r
+          //\r
+          Status = EFI_UNSUPPORTED;\r
+          goto Done;\r
+        }\r
+        Status = gRT->GetTime (&EfiTime, NULL);\r
+        if (!EFI_ERROR (Status)) {\r
+          if (OpCode->ValueType == EFI_IFR_TYPE_DATE) {\r
+            switch (OpCode->VarStoreInfo.VarOffset) {\r
+            case 0x00:\r
+              Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;\r
+              Value->Value.u16 = EfiTime.Year;\r
+              break;\r
+            case 0x02:\r
+              Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
+              Value->Value.u8 = EfiTime.Month;\r
+              break;\r
+            case 0x03:\r
+              Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
+              Value->Value.u8 = EfiTime.Day;\r
+              break;\r
+            default:\r
+              //\r
+              // Invalid Date field.\r
+              //\r
+              Status = EFI_INVALID_PARAMETER;\r
+              goto Done;\r
+            }\r
+          } else {\r
+            switch (OpCode->VarStoreInfo.VarOffset) {\r
+            case 0x00:\r
+              Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
+              Value->Value.u8 = EfiTime.Hour;\r
+              break;\r
+            case 0x01:\r
+              Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
+              Value->Value.u8 = EfiTime.Minute;\r
+              break;\r
+            case 0x02:\r
+              Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
+              Value->Value.u8 = EfiTime.Second;\r
+              break;\r
+            default:\r
+              //\r
+              // Invalid Time field.\r
+              //\r
+              Status = EFI_INVALID_PARAMETER;\r
+              goto Done;\r
+            }\r
+          }\r
+        }\r
+      }\r
+\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
+          goto Done;\r
+        }\r
+\r
+        //\r
+        // Validate the expression value\r
+        //\r
+        if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
+          Status = EFI_NOT_FOUND;\r
+          goto Done;\r
+        }\r
+\r
+        Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
+        if (Question == NULL) {\r
+          Status = EFI_NOT_FOUND;\r
+          goto Done;\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
+        Status = EFI_NOT_FOUND;\r
+        goto Done;\r
+      }\r
+\r
+      //\r
+      // Evaluate this rule expression\r
+      //\r
+      Status = EvaluateExpression (FormSet, Form, RuleExpression);\r
+      if (EFI_ERROR (Status)) {\r
+        goto Done;\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
+        goto Done;\r
+      }\r
+      if (Value->Type != EFI_IFR_TYPE_STRING) {\r
+        Status = EFI_INVALID_PARAMETER;\r
+        goto Done;\r
+      }\r
+\r
+      StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
+      if (StrPtr == NULL) {\r
+        Status = EFI_INVALID_PARAMETER;\r
+        goto Done;\r
+      }\r
+\r
+      Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+      Value->Value.u64 = StrLen (StrPtr);\r
+      FreePool (StrPtr);\r
+      break;\r
+\r
+    case EFI_IFR_NOT_OP:\r
+      Status = PopExpression (Value);\r
+      if (EFI_ERROR (Status)) {\r
+        goto Done;\r
+      }\r
+      if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {\r
+        Status = EFI_INVALID_PARAMETER;\r
+        goto Done;\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
+        goto Done;\r
+      }\r
+\r
+      //\r
+      // Validate the expression value\r
+      //\r
+      if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
+        Status = EFI_NOT_FOUND;\r
+        goto Done;\r
+      }\r
+\r
+      Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
+      if (Question == NULL) {\r
+        Status = EFI_NOT_FOUND;\r
+        goto Done;\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
+        goto Done;\r
+      }\r
+\r
+      //\r
+      // Validate the expression value\r
+      //\r
+      if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
+        Status = EFI_NOT_FOUND;\r
+        goto Done;\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
+        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
+        goto Done;\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 != 0);\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
+          Status = EFI_INVALID_PARAMETER;\r
+          goto Done;\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
+        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
+        goto Done;\r
+      }\r
+\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
+      StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
+      if (StrPtr == NULL) {\r
+        Status = EFI_NOT_FOUND;\r
+        goto Done;\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
+      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
+        goto Done;\r
+      }\r
+      if (Value->Type > EFI_IFR_TYPE_DATE) {\r
+        Status = EFI_INVALID_PARAMETER;\r
+        goto Done;\r
+      }\r
+\r
+      Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+      Value->Value.u64 = ~Value->Value.u64;\r
+      break;\r
+\r
+    case EFI_IFR_SET_OP:\r
+      //\r
+      // Pop an expression from the expression stack\r
+      //\r
+      Status = PopExpression (Value);\r
+      if (EFI_ERROR (Status)) {\r
+        goto Done;\r
+      }\r
+      Data1.Type = EFI_IFR_TYPE_BOOLEAN;\r
+      Data1.Value.b = FALSE;\r
+      //\r
+      // Set value to var storage buffer\r
+      //\r
+      if (OpCode->VarStorage != NULL) {\r
+        switch (OpCode->VarStorage->Type) {\r
+        case EFI_HII_VARSTORE_BUFFER:\r
+          CopyMem (OpCode->VarStorage->EditBuffer + OpCode->VarStoreInfo.VarOffset, &Value->Value, OpCode->ValueWidth);\r
+          Data1.Value.b = TRUE;\r
+          break;\r
+        case EFI_HII_VARSTORE_NAME_VALUE:\r
+          if (OpCode->ValueType != EFI_IFR_TYPE_STRING) {\r
+            NameValue = AllocateZeroPool ((OpCode->ValueWidth * 2 + 1) * sizeof (CHAR16));\r
+            ASSERT (Value != NULL);\r
+            //\r
+            // Convert Buffer to Hex String\r
+            //\r
+            TempBuffer = (UINT8 *) &Value->Value + OpCode->ValueWidth - 1;\r
+            StrPtr = NameValue;\r
+            for (Index = 0; Index < OpCode->ValueWidth; Index ++, TempBuffer --) {\r
+              StrPtr += UnicodeValueToString (StrPtr, PREFIX_ZERO | RADIX_HEX, *TempBuffer, 2);\r
+            }\r
+            Status = SetValueByName (OpCode->VarStorage, OpCode->ValueName, NameValue);\r
+            FreePool (NameValue);\r
+            if (!EFI_ERROR (Status)) {\r
+              Data1.Value.b = TRUE;\r
+            }\r
+          }\r
+          break;\r
+        case EFI_HII_VARSTORE_EFI_VARIABLE:\r
+          Status = gRT->SetVariable (\r
+                          OpCode->ValueName,\r
+                          &OpCode->VarStorage->Guid,\r
+                          OpCode->VarStorage->Attributes,\r
+                          OpCode->ValueWidth,\r
+                          &Value->Value\r
+                          );\r
+          if (!EFI_ERROR (Status)) {\r
+            Data1.Value.b = TRUE;\r
+          }\r
+          break;\r
+        default:\r
+          //\r
+          // Not recognize storage.\r
+          //\r
+          Status = EFI_UNSUPPORTED;\r
+          goto Done;\r
+          break;\r
+        }\r
+      } else {\r
+        //\r
+        // For Time/Date Data\r
+        //\r
+        if (OpCode->ValueType != EFI_IFR_TYPE_DATE && OpCode->ValueType != EFI_IFR_TYPE_TIME) {\r
+          //\r
+          // Only support Data/Time data when storage doesn't exist.\r
+          //\r
+          Status = EFI_UNSUPPORTED;\r
+          goto Done;\r
+        }\r
+        Status = gRT->GetTime (&EfiTime, NULL);\r
+        if (!EFI_ERROR (Status)) {\r
+          if (OpCode->ValueType == EFI_IFR_TYPE_DATE) {\r
+            switch (OpCode->VarStoreInfo.VarOffset) {\r
+            case 0x00:\r
+              EfiTime.Year = Value->Value.u16;\r
+              break;\r
+            case 0x02:\r
+              EfiTime.Month = Value->Value.u8;\r
+              break;\r
+            case 0x03:\r
+              EfiTime.Day = Value->Value.u8;\r
+              break;\r
+            default:\r
+              //\r
+              // Invalid Date field.\r
+              //\r
+              Status = EFI_INVALID_PARAMETER;\r
+              goto Done;\r
+            }\r
+          } else {\r
+            switch (OpCode->VarStoreInfo.VarOffset) {\r
+            case 0x00:\r
+              EfiTime.Hour = Value->Value.u8;\r
+              break;\r
+            case 0x01:\r
+              EfiTime.Minute = Value->Value.u8;\r
+              break;\r
+            case 0x02:\r
+              EfiTime.Second = Value->Value.u8;\r
+              break;\r
+            default:\r
+              //\r
+              // Invalid Time field.\r
+              //\r
+              Status = EFI_INVALID_PARAMETER;\r
+              goto Done;\r
+            }\r
+          }\r
+          Status = gRT->SetTime (&EfiTime);\r
+          if (!EFI_ERROR (Status)) {\r
+            Data1.Value.b = TRUE;\r
+          }\r
+        }\r
+      }\r
+      Value = &Data1;\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
+        goto Done;\r
+      }\r
+      if (Data2.Type > EFI_IFR_TYPE_DATE) {\r
+        Status = EFI_INVALID_PARAMETER;\r
+        goto Done;\r
+      }\r
+\r
+      //\r
+      // Pop another expression from the expression stack\r
+      //\r
+      Status = PopExpression (&Data1);\r
+      if (EFI_ERROR (Status)) {\r
+        goto Done;\r
+      }\r
+      if (Data1.Type > EFI_IFR_TYPE_DATE) {\r
+        Status = EFI_INVALID_PARAMETER;\r
+        goto Done;\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
+        goto Done;\r
+      }\r
+      if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {\r
+        Status = EFI_INVALID_PARAMETER;\r
+        goto Done;\r
+      }\r
+\r
+      //\r
+      // Pop another expression from the expression stack\r
+      //\r
+      Status = PopExpression (&Data1);\r
+      if (EFI_ERROR (Status)) {\r
+        goto Done;\r
+      }\r
+      if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
+        Status = EFI_INVALID_PARAMETER;\r
+        goto Done;\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
+        goto Done;\r
+      }\r
+      if (Data2.Type > EFI_IFR_TYPE_BOOLEAN && Data2.Type != EFI_IFR_TYPE_STRING) {\r
+        Status = EFI_INVALID_PARAMETER;\r
+        goto Done;\r
+      }\r
+\r
+      //\r
+      // Pop another expression from the expression stack\r
+      //\r
+      Status = PopExpression (&Data1);\r
+      if (EFI_ERROR (Status)) {\r
+        goto Done;\r
+      }\r
+\r
+      Result = CompareHiiValue (&Data1, &Data2, FormSet->HiiHandle);\r
+      if (Result == EFI_INVALID_PARAMETER) {\r
+        Status = EFI_INVALID_PARAMETER;\r
+        goto Done;\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
+        goto Done;\r
+      }\r
+\r
+      //\r
+      // Pop second expression from the expression stack\r
+      //\r
+      Status = PopExpression (&Data2);\r
+      if (EFI_ERROR (Status)) {\r
+        goto Done;\r
+      }\r
+\r
+      //\r
+      // Pop first expression from the expression stack\r
+      //\r
+      Status = PopExpression (&Data1);\r
+      if (EFI_ERROR (Status)) {\r
+        goto Done;\r
+      }\r
+      if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
+        Status = EFI_INVALID_PARAMETER;\r
+        goto Done;\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
+    case EFI_IFR_MAP_OP:\r
+      //\r
+      // Pop the check value\r
+      //\r
+      Status = PopExpression (&Data1);\r
+      if (EFI_ERROR (Status)) {\r
+        goto Done;\r
+      }\r
+      //\r
+      // Check MapExpression list is valid.\r
+      //\r
+      if (OpCode->MapExpressionList.ForwardLink == NULL) {\r
+        Status = EFI_INVALID_PARAMETER;\r
+        goto Done;\r
+      }\r
+      //\r
+      // Go through map expression list.\r
+      //\r
+      SubExpressionLink = GetFirstNode(&OpCode->MapExpressionList);\r
+      while (!IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
+        SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);\r
+        //\r
+        // Evaluate the first expression in this pair.\r
+        //\r
+        Status = EvaluateExpression (FormSet, Form, SubExpression);\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
+        //\r
+        // Compare the expression value with current value\r
+        //\r
+        if (CompareHiiValue (&Data1, &SubExpression->Result, NULL) == 0) {\r
+          //\r
+          // Try get the map value.\r
+          //\r
+          SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
+          if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
+            Status = EFI_INVALID_PARAMETER;\r
+            goto Done;\r
+          }\r
+          SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);\r
+          Status = EvaluateExpression (FormSet, Form, SubExpression);\r
+          if (EFI_ERROR (Status)) {\r
+            goto Done;\r
+          }\r
+          Value = &SubExpression->Result;\r
+          break;\r
+        }\r
+        //\r
+        // Skip the second expression on this pair.\r
+        //\r
+        SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
+        if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
+          Status = EFI_INVALID_PARAMETER;\r
+          goto Done;\r
+        }\r
+        //\r
+        // Goto the first expression on next pair.\r
+        //\r
+        SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
+      }\r
+\r
+      //\r
+      // No map value is found.\r
+      //\r
+      if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        Value->Value.u8 = 0;\r
+      }\r
+      break;\r
+\r
+    default:\r
+      break;\r
+    }\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+\r
+    Status = PushExpression (Value);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\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
+    goto Done;\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
+    Status = EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+Done:\r
+  RestoreExpressionEvaluationStackOffset (StackOffset);\r
+  if (!EFI_ERROR (Status)) {\r
+    CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));\r
+  }\r
+\r
+  return Status;\r
+}\r