]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/SetupBrowserDxe/Expression.c
MdeModulePkg: Fix MSFT C4255 warning
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Expression.c
index 25d4e0a678f2fc439de691dacf01465a9be9b774..297741c0fe9df9d031bd064e5f94e6472c7af8b3 100644 (file)
@@ -1,8 +1,8 @@
 /** @file\r
 Utility functions for expression evaluation.\r
 \r
-Copyright (c) 2007, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
+Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
 http://opensource.org/licenses/bsd-license.php\r
@@ -12,7 +12,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 **/\r
 \r
-#include "Ui.h"\r
 #include "Setup.h"\r
 \r
 //\r
@@ -25,12 +24,34 @@ EFI_HII_VALUE *mOpCodeScopeStackPointer = NULL;
 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
+FORM_EXPRESSION   **mFormExpressionStack = NULL;\r
+FORM_EXPRESSION   **mFormExpressionEnd = NULL;\r
+FORM_EXPRESSION   **mFormExpressionPointer = NULL;\r
+\r
+FORM_EXPRESSION   **mStatementExpressionStack = NULL;\r
+FORM_EXPRESSION   **mStatementExpressionEnd = NULL;\r
+FORM_EXPRESSION   **mStatementExpressionPointer = NULL;\r
+\r
+FORM_EXPRESSION   **mOptionExpressionStack = NULL;\r
+FORM_EXPRESSION   **mOptionExpressionEnd = NULL;\r
+FORM_EXPRESSION   **mOptionExpressionPointer = NULL;\r
+\r
 \r
 //\r
 // Unicode collation protocol interface\r
 //\r
 EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollation = NULL;\r
-\r
+EFI_USER_MANAGER_PROTOCOL      *mUserManager = NULL;\r
 \r
 /**\r
   Grow size of the stack.\r
@@ -79,7 +100,7 @@ GrowStack (
     //\r
     // Free The Old Stack\r
     //\r
-    gBS->FreePool (*Stack);\r
+    FreePool (*Stack);\r
   }\r
 \r
   //\r
@@ -132,6 +153,11 @@ PushStack (
   // Push the item onto the stack\r
   //\r
   CopyMem (*StackPtr, Data, sizeof (EFI_HII_VALUE));\r
+  if (Data->Type == EFI_IFR_TYPE_BUFFER) {\r
+    (*StackPtr)->Buffer = AllocateCopyPool(Data->BufferLen, Data->Buffer);\r
+    ASSERT ((*StackPtr)->Buffer != NULL);\r
+  }\r
+  \r
   *StackPtr = *StackPtr + 1;\r
 \r
   return EFI_SUCCESS;\r
@@ -141,10 +167,8 @@ PushStack (
 /**\r
   Pop an element from the stack.\r
 \r
-  @param  Stack                  On input: old stack; On output: new stack\r
-  @param  StackPtr               On input: old stack pointer; On output: new stack\r
-                                 pointer\r
-  @param  StackEnd               On input: old stack end; On output: new stack end\r
+  @param  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
@@ -153,16 +177,15 @@ PushStack (
 **/\r
 EFI_STATUS\r
 PopStack (\r
-  IN OUT EFI_HII_VALUE       **Stack,\r
+  IN  EFI_HII_VALUE          *Stack,\r
   IN OUT EFI_HII_VALUE       **StackPtr,\r
-  IN OUT EFI_HII_VALUE       **StackEnd,\r
   OUT EFI_HII_VALUE          *Data\r
   )\r
 {\r
   //\r
   // Check for a stack underflow condition\r
   //\r
-  if (*StackPtr == *Stack) {\r
+  if (*StackPtr == Stack) {\r
     return EFI_ACCESS_DENIED;\r
   }\r
 \r
@@ -175,6 +198,435 @@ PopStack (
 }\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
+  mFormExpressionPointer      = mFormExpressionStack;\r
+  mStatementExpressionPointer = mStatementExpressionStack;\r
+  mOptionExpressionPointer    = mOptionExpressionStack;  \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
+  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
+  @param  MemberSize             The stack member size.\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
+GrowConditionalStack (\r
+  IN OUT FORM_EXPRESSION   ***Stack,\r
+  IN OUT FORM_EXPRESSION   ***StackPtr,\r
+  IN OUT FORM_EXPRESSION   ***StackEnd,\r
+  IN     UINTN             MemberSize\r
+  )\r
+{\r
+  UINTN             Size;\r
+  FORM_EXPRESSION   **NewStack;\r
+\r
+  Size = EXPRESSION_STACK_SIZE_INCREMENT;\r
+  if (*StackPtr != NULL) {\r
+    Size = Size + (*StackEnd - *Stack);\r
+  }\r
+\r
+  NewStack = AllocatePool (Size * MemberSize);\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) * MemberSize\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
+  Push an element onto the Stack.\r
+\r
+  @param  Stack                  On input: old stack; On output: new stack\r
+  @param  StackPtr               On input: old stack pointer; On output: new stack\r
+                                 pointer\r
+  @param  StackEnd               On input: old stack end; On output: new stack end\r
+  @param  Data                   Data to push.\r
+\r
+  @retval EFI_SUCCESS            Push stack success.\r
+\r
+**/\r
+EFI_STATUS\r
+PushConditionalStack (\r
+  IN OUT FORM_EXPRESSION   ***Stack,\r
+  IN OUT FORM_EXPRESSION   ***StackPtr,\r
+  IN OUT FORM_EXPRESSION   ***StackEnd,\r
+  IN     FORM_EXPRESSION   **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 = GrowConditionalStack (Stack, StackPtr, StackEnd, sizeof (FORM_EXPRESSION *));\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 (FORM_EXPRESSION *)); \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
+PopConditionalStack (\r
+  IN     FORM_EXPRESSION   **Stack,\r
+  IN OUT FORM_EXPRESSION   ***StackPtr,\r
+  OUT    FORM_EXPRESSION   **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 (FORM_EXPRESSION  *));\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+/**\r
+  Get the expression list count.\r
+  \r
+  @param  Level                  Which type this expression belong to. Form, \r
+                                 statement or option?\r
+\r
+  @retval >=0                    The expression count\r
+  @retval -1                     Input parameter error.\r
+\r
+**/\r
+INTN \r
+GetConditionalExpressionCount (\r
+  IN EXPRESS_LEVEL       Level\r
+  )\r
+{\r
+  switch (Level) {\r
+    case ExpressForm:\r
+      return mFormExpressionPointer - mFormExpressionStack;\r
+    case ExpressStatement:\r
+      return mStatementExpressionPointer - mStatementExpressionStack;\r
+    case ExpressOption:\r
+      return mOptionExpressionPointer - mOptionExpressionStack;\r
+    default:\r
+      ASSERT (FALSE);\r
+      return -1;\r
+  } \r
+}\r
+\r
+/**\r
+  Get the expression Buffer pointer.\r
+  \r
+  @param  Level                  Which type this expression belong to. Form, \r
+                                 statement or option?\r
+\r
+  @retval  The start pointer of the expression buffer or NULL.\r
+\r
+**/\r
+FORM_EXPRESSION **\r
+GetConditionalExpressionList (\r
+  IN EXPRESS_LEVEL       Level\r
+  )\r
+{\r
+  switch (Level) {\r
+    case ExpressForm:\r
+      return mFormExpressionStack;\r
+    case ExpressStatement:\r
+      return mStatementExpressionStack;\r
+    case ExpressOption:\r
+      return mOptionExpressionStack;\r
+    default:\r
+      ASSERT (FALSE);\r
+      return NULL;\r
+  } \r
+}\r
+\r
+\r
+/**\r
+  Push the expression options onto the Stack.\r
+\r
+  @param  Pointer                Pointer to the current expression.\r
+  @param  Level                  Which type this expression belong to. Form, \r
+                                 statement or option?\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
+PushConditionalExpression (\r
+  IN FORM_EXPRESSION   *Pointer,\r
+  IN EXPRESS_LEVEL     Level\r
+  )\r
+{\r
+  switch (Level) {\r
+    case ExpressForm:\r
+      return PushConditionalStack (\r
+        &mFormExpressionStack,\r
+        &mFormExpressionPointer,\r
+        &mFormExpressionEnd,\r
+        &Pointer\r
+        );\r
+    case ExpressStatement:\r
+      return PushConditionalStack (\r
+        &mStatementExpressionStack,\r
+        &mStatementExpressionPointer,\r
+        &mStatementExpressionEnd,\r
+        &Pointer\r
+        );\r
+    case ExpressOption:\r
+      return PushConditionalStack (\r
+        &mOptionExpressionStack,\r
+        &mOptionExpressionPointer,\r
+        &mOptionExpressionEnd,\r
+        &Pointer\r
+        );\r
+    default:\r
+      ASSERT (FALSE);\r
+      return EFI_INVALID_PARAMETER;\r
+  }\r
+}\r
+\r
+/**\r
+  Pop the expression options from the Stack\r
+\r
+  @param  Level                  Which type this expression belong to. Form, \r
+                                 statement or option?\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
+PopConditionalExpression (\r
+  IN  EXPRESS_LEVEL      Level\r
+  )\r
+{\r
+  FORM_EXPRESSION   *Pointer;\r
+\r
+  switch (Level) {\r
+    case ExpressForm:\r
+      return PopConditionalStack (\r
+        mFormExpressionStack,\r
+        &mFormExpressionPointer,\r
+        &Pointer\r
+      );\r
+\r
+    case ExpressStatement:\r
+      return PopConditionalStack (\r
+        mStatementExpressionStack,\r
+        &mStatementExpressionPointer,\r
+        &Pointer\r
+      );\r
+\r
+    case ExpressOption:\r
+      return PopConditionalStack (\r
+        mOptionExpressionStack,\r
+        &mOptionExpressionPointer,\r
+        &Pointer\r
+      );\r
+\r
+    default:\r
+      ASSERT (FALSE);\r
+      return EFI_INVALID_PARAMETER;\r
+  }\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
@@ -236,9 +688,8 @@ PopScope (
   EFI_HII_VALUE  Data;\r
 \r
   Status = PopStack (\r
-             &mOpCodeScopeStack,\r
+             mOpCodeScopeStack,\r
              &mOpCodeScopeStackPointer,\r
-             &mOpCodeScopeStackEnd,\r
              &Data\r
              );\r
 \r
@@ -248,19 +699,6 @@ PopScope (
 }\r
 \r
 \r
-/**\r
-  Reset stack pointer to begin of the stack.\r
-\r
-**/\r
-VOID\r
-ResetExpressionStack (\r
-  VOID\r
-  )\r
-{\r
-  mExpressionEvaluationStackPointer = mExpressionEvaluationStack;\r
-}\r
-\r
-\r
 /**\r
   Push an Expression value onto the Stack\r
 \r
@@ -300,13 +738,41 @@ PopExpression (
   )\r
 {\r
   return PopStack (\r
-           &mExpressionEvaluationStack,\r
+           mExpressionEvaluationStack + mExpressionEvaluationStackOffset,\r
            &mExpressionEvaluationStackPointer,\r
-           &mExpressionEvaluationStackEnd,\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
+  VOID\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
@@ -322,7 +788,7 @@ FORM_BROWSER_FORM *
 IdToForm (\r
   IN FORM_BROWSER_FORMSET  *FormSet,\r
   IN UINT16                FormId\r
-)\r
+  )\r
 {\r
   LIST_ENTRY         *Link;\r
   FORM_BROWSER_FORM  *Form;\r
@@ -361,7 +827,7 @@ IdToQuestion2 (
   LIST_ENTRY              *Link;\r
   FORM_BROWSER_STATEMENT  *Question;\r
 \r
-  if (QuestionId == 0) {\r
+  if (QuestionId == 0 || Form == NULL) {\r
     //\r
     // The value of zero is reserved\r
     //\r
@@ -421,6 +887,14 @@ IdToQuestion (
 \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, GetSetValueWithHiiDriver);\r
+      }\r
+\r
       return Question;\r
     }\r
 \r
@@ -504,7 +978,7 @@ InitializeUnicodeCollationProtocol (
 **/\r
 VOID\r
 IfrStrToUpper (\r
-  CHAR16                   *String\r
+  IN CHAR16                   *String\r
   )\r
 {\r
   while (*String != 0) {\r
@@ -515,6 +989,129 @@ IfrStrToUpper (
   }\r
 }\r
 \r
+/**\r
+  Check whether this value type can be transfer to EFI_IFR_TYPE_BUFFER type.\r
+\r
+  EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to \r
+  EFI_IFR_TYPE_BUFFER when do the value compare.\r
+\r
+  @param  Value                  Expression value to compare on.\r
+\r
+  @retval TRUE                   This value type can be transter to EFI_IFR_TYPE_BUFFER type.\r
+  @retval FALSE                  This value type can't be transter to EFI_IFR_TYPE_BUFFER type.\r
+\r
+**/\r
+BOOLEAN\r
+IsTypeInBuffer (\r
+  IN  EFI_HII_VALUE   *Value\r
+  )\r
+{\r
+  switch (Value->Type) {\r
+  case EFI_IFR_TYPE_BUFFER:\r
+  case EFI_IFR_TYPE_DATE:\r
+  case EFI_IFR_TYPE_TIME:\r
+  case EFI_IFR_TYPE_REF:\r
+    return TRUE;\r
+\r
+  default:\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+/**\r
+  Check whether this value type can be transfer to EFI_IFR_TYPE_UINT64\r
+\r
+  @param  Value                  Expression value to compare on.\r
+\r
+  @retval TRUE                   This value type can be transter to EFI_IFR_TYPE_BUFFER type.\r
+  @retval FALSE                  This value type can't be transter to EFI_IFR_TYPE_BUFFER type.\r
+\r
+**/\r
+BOOLEAN\r
+IsTypeInUINT64 (\r
+  IN  EFI_HII_VALUE   *Value\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
+  case EFI_IFR_TYPE_BOOLEAN:\r
+    return TRUE;\r
+\r
+  default:\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+/**\r
+  Return the buffer length for this value.\r
+\r
+  EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to \r
+  EFI_IFR_TYPE_BUFFER when do the value compare.\r
+\r
+  @param   Value                  Expression value to compare on.\r
+  \r
+  @retval  BufLen                 Return the buffer length.\r
+\r
+**/\r
+UINT16\r
+GetLengthForValue (\r
+  IN  EFI_HII_VALUE   *Value\r
+  )\r
+{\r
+  switch (Value->Type) {\r
+  case EFI_IFR_TYPE_BUFFER:\r
+    return Value->BufferLen;\r
+\r
+  case EFI_IFR_TYPE_DATE:\r
+    return (UINT16) sizeof (EFI_HII_DATE);\r
+\r
+  case EFI_IFR_TYPE_TIME:\r
+    return (UINT16) sizeof (EFI_HII_TIME);\r
+\r
+  case EFI_IFR_TYPE_REF:\r
+    return (UINT16) sizeof (EFI_HII_REF);\r
+\r
+  default:\r
+    return 0;\r
+  }\r
+}\r
+\r
+/**\r
+  Return the buffer pointer for this value.\r
+\r
+  EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to \r
+  EFI_IFR_TYPE_BUFFER when do the value compare.\r
+\r
+  @param  Value                  Expression value to compare on.\r
+\r
+  @retval Buf                    Return the buffer pointer.\r
+\r
+**/\r
+UINT8 *\r
+GetBufferForValue (\r
+  IN  EFI_HII_VALUE   *Value\r
+  )\r
+{\r
+  switch (Value->Type) {\r
+  case EFI_IFR_TYPE_BUFFER:\r
+    return Value->Buffer;\r
+\r
+  case EFI_IFR_TYPE_DATE:\r
+    return (UINT8 *) (&Value->Value.date);\r
+\r
+  case EFI_IFR_TYPE_TIME:\r
+    return (UINT8 *) (&Value->Value.time);\r
+\r
+  case EFI_IFR_TYPE_REF:\r
+    return (UINT8 *) (&Value->Value.ref);\r
+\r
+  default:\r
+    return NULL;\r
+  }\r
+}\r
 \r
 /**\r
   Evaluate opcode EFI_IFR_TO_STRING.\r
@@ -539,6 +1136,9 @@ IfrToString (
   CHAR16         *String;\r
   CHAR16         *PrintFormat;\r
   CHAR16         Buffer[MAXIMUM_VALUE_CHARACTERS];\r
+  UINT8          *TmpBuf;\r
+  UINT8          *SrcBuf;\r
+  UINTN          SrcLen;\r
   UINTN          BufferSize;\r
 \r
   Status = PopExpression (&Value);\r
@@ -567,7 +1167,8 @@ IfrToString (
       break;\r
 \r
     default:\r
-      return EFI_UNSUPPORTED;\r
+      Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+      return EFI_SUCCESS;\r
     }\r
     UnicodeSPrint (Buffer, BufferSize, PrintFormat, Value.Value.u64);\r
     String = Buffer;\r
@@ -580,9 +1181,44 @@ IfrToString (
   case EFI_IFR_TYPE_BOOLEAN:\r
     String = (Value.Value.b) ? L"True" : L"False";\r
     break;\r
+    \r
+  case EFI_IFR_TYPE_BUFFER:\r
+  case EFI_IFR_TYPE_DATE:\r
+  case EFI_IFR_TYPE_TIME:\r
+  case EFI_IFR_TYPE_REF:\r
+    //\r
+    // + 3 is base on the unicode format, the length may be odd number, \r
+    // so need 1 byte to align, also need 2 bytes for L'\0'.\r
+    //\r
+    if (Value.Type == EFI_IFR_TYPE_BUFFER) {\r
+      SrcLen = Value.BufferLen;\r
+      SrcBuf = Value.Buffer;\r
+    } else {\r
+      SrcBuf = GetBufferForValue(&Value);\r
+      SrcLen = GetLengthForValue(&Value);\r
+    }\r
 \r
+    TmpBuf = AllocateZeroPool (SrcLen + 3);\r
+    ASSERT (TmpBuf != NULL);\r
+    if (Format == EFI_IFR_STRING_ASCII) {\r
+      CopyMem (TmpBuf, SrcBuf, SrcLen);\r
+      PrintFormat = L"%a"; \r
+    } else {\r
+      // Format == EFI_IFR_STRING_UNICODE\r
+      CopyMem (TmpBuf, SrcBuf, SrcLen * sizeof (CHAR16));\r
+      PrintFormat = L"%s";  \r
+    }\r
+    UnicodeSPrint (Buffer, sizeof (Buffer), PrintFormat, TmpBuf);\r
+    String = Buffer; \r
+    FreePool (TmpBuf);\r
+    if (Value.Type == EFI_IFR_TYPE_BUFFER) {\r
+      FreePool (Value.Buffer);\r
+    }\r
+    break;\r
+    \r
   default:\r
-    return EFI_UNSUPPORTED;\r
+    Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+    return EFI_SUCCESS;\r
   }\r
 \r
   Result->Type = EFI_IFR_TYPE_STRING;\r
@@ -611,15 +1247,15 @@ IfrToUint (
   EFI_HII_VALUE  Value;\r
   CHAR16         *String;\r
   CHAR16         *StringPtr;\r
-  UINTN          BufferSize;\r
 \r
   Status = PopExpression (&Value);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
 \r
-  if (Value.Type >= EFI_IFR_TYPE_OTHER) {\r
-    return EFI_UNSUPPORTED;\r
+  if (Value.Type >= EFI_IFR_TYPE_OTHER && !IsTypeInBuffer(&Value)) {\r
+    Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+    return EFI_SUCCESS;\r
   }\r
 \r
   Status = EFI_SUCCESS;\r
@@ -635,14 +1271,26 @@ IfrToUint (
       //\r
       // Hex string\r
       //\r
-      BufferSize = sizeof (UINT64);\r
-      Status = HexStringToBuf ((UINT8 *) &Result->Value.u64, &BufferSize, StringPtr + 2, NULL);\r
+      Result->Value.u64 = StrHexToUint64 (String);\r
     } else {\r
       //\r
-      // BUGBUG: Need handle decimal string\r
+      // decimal string\r
       //\r
+      Result->Value.u64 = StrDecimalToUint64 (String);\r
+    }\r
+    FreePool (String);\r
+  } else if (IsTypeInBuffer(&Value)) {\r
+    if (GetLengthForValue (&Value) > 8) {\r
+      if (Value.Type == EFI_IFR_TYPE_BUFFER) {\r
+        FreePool (Value.Buffer);\r
+      }\r
+      Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+      return EFI_SUCCESS;\r
+    }\r
+    Result->Value.u64 = *(UINT64*) GetBufferForValue (&Value);\r
+    if (Value.Type == EFI_IFR_TYPE_BUFFER) {\r
+      FreePool (Value.Buffer);\r
     }\r
-    gBS->FreePool (String);\r
   } else {\r
     CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));\r
   }\r
@@ -669,11 +1317,15 @@ IfrCatenate (
   )\r
 {\r
   EFI_STATUS     Status;\r
-  EFI_HII_VALUE  Value;\r
+  EFI_HII_VALUE  Value[2];\r
   CHAR16         *String[2];\r
   UINTN          Index;\r
   CHAR16         *StringPtr;\r
   UINTN          Size;\r
+  UINT16         Length0;\r
+  UINT16         Length1;\r
+  UINT8          *TmpBuf;\r
+  UINTN          MaxLen;\r
 \r
   //\r
   // String[0] - The second string\r
@@ -683,47 +1335,154 @@ IfrCatenate (
   String[1] = NULL;\r
   StringPtr = NULL;\r
   Status = EFI_SUCCESS;\r
+  ZeroMem (Value, sizeof (Value));\r
+\r
+  Status = PopExpression (&Value[0]);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+\r
+  Status = PopExpression (&Value[1]);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
 \r
   for (Index = 0; Index < 2; Index++) {\r
-    Status = PopExpression (&Value);\r
-    if (EFI_ERROR (Status)) {\r
+    if (Value[Index].Type != EFI_IFR_TYPE_STRING && !IsTypeInBuffer(&Value[Index])) {\r
+      Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+      Status = EFI_SUCCESS;\r
       goto Done;\r
     }\r
 \r
-    if (Value.Type != EFI_IFR_TYPE_STRING) {\r
-      Status = EFI_UNSUPPORTED;\r
+    if (Value[Index].Type == EFI_IFR_TYPE_STRING) {\r
+      String[Index] = GetToken (Value[Index].Value.string, FormSet->HiiHandle);\r
+      if (String[Index] == NULL) {\r
+        Status = EFI_NOT_FOUND;\r
+        goto Done;\r
+      }\r
+    }\r
+  }\r
+\r
+  if (Value[0].Type == EFI_IFR_TYPE_STRING) {\r
+    Size = StrSize (String[0]);\r
+    MaxLen = (StrSize (String[1]) + Size) / sizeof (CHAR16);\r
+    StringPtr= AllocatePool (MaxLen * sizeof (CHAR16));\r
+    ASSERT (StringPtr != NULL);\r
+    StrCpyS (StringPtr, MaxLen, String[1]);\r
+    StrCatS (StringPtr, MaxLen, String[0]);\r
+\r
+    Result->Type = EFI_IFR_TYPE_STRING;\r
+    Result->Value.string = NewString (StringPtr, FormSet->HiiHandle);\r
+  } else {\r
+    Result->Type = EFI_IFR_TYPE_BUFFER;\r
+    Length0 = GetLengthForValue(&Value[0]);\r
+    Length1 = GetLengthForValue(&Value[1]);\r
+    Result->BufferLen = (UINT16) (Length0 + Length1);\r
+\r
+    Result->Buffer = AllocateZeroPool (Result->BufferLen);\r
+    ASSERT (Result->Buffer != NULL);\r
+\r
+    TmpBuf = GetBufferForValue(&Value[0]);\r
+    ASSERT (TmpBuf != NULL);\r
+    CopyMem (Result->Buffer, TmpBuf, Length0);\r
+    TmpBuf = GetBufferForValue(&Value[1]);\r
+    ASSERT (TmpBuf != NULL);\r
+    CopyMem (&Result->Buffer[Length0], TmpBuf, Length1);\r
+  }\r
+Done:\r
+  if (Value[0].Buffer != NULL) {\r
+    FreePool (Value[0].Buffer);\r
+  }\r
+  if (Value[1].Buffer != NULL) {\r
+    FreePool (Value[1].Buffer);\r
+  }\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[2];\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
+  ZeroMem (Value, sizeof (Value));\r
+\r
+  Status = PopExpression (&Value[0]);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+\r
+  Status = PopExpression (&Value[1]);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+\r
+  for (Index = 0; Index < 2; Index++) {\r
+    if (Value[Index].Type != EFI_IFR_TYPE_STRING) {\r
+      Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+      Status = EFI_SUCCESS;\r
       goto Done;\r
     }\r
 \r
-    String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
-    if (String== NULL) {\r
+    String[Index] = GetToken (Value[Index].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
+  Result->Type = EFI_IFR_TYPE_BOOLEAN;\r
+  Result->Value.b = mUnicodeCollation->MetaiMatch (mUnicodeCollation, String[0], String[1]);\r
 \r
 Done:\r
-  SafeFreePool (String[0]);\r
-  SafeFreePool (String[1]);\r
-  SafeFreePool (StringPtr);\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_MATCH.\r
+  Evaluate opcode EFI_IFR_MATCH2.\r
 \r
   @param  FormSet                Formset which contains this opcode.\r
+  @param  SyntaxType             Syntax type for match2.\r
   @param  Result                 Evaluation result for this opcode.\r
 \r
   @retval EFI_SUCCESS            Opcode evaluation success.\r
@@ -731,15 +1490,23 @@ Done:
 \r
 **/\r
 EFI_STATUS\r
-IfrMatch (\r
+IfrMatch2 (\r
   IN FORM_BROWSER_FORMSET  *FormSet,\r
+  IN EFI_GUID              *SyntaxType,\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
+  EFI_STATUS                       Status;\r
+  EFI_HII_VALUE                    Value[2];\r
+  CHAR16                           *String[2];\r
+  UINTN                            Index;\r
+  UINTN                            GuidIndex;\r
+  EFI_HANDLE                       *HandleBuffer;\r
+  UINTN                            BufferSize;\r
+  EFI_REGULAR_EXPRESSION_PROTOCOL  *RegularExpressionProtocol;\r
+  UINTN                            RegExSyntaxTypeListSize;\r
+  EFI_REGEX_SYNTAX_TYPE            *RegExSyntaxTypeList;\r
+  UINTN                            CapturesCount;\r
 \r
   //\r
   // String[0] - The string to search\r
@@ -747,36 +1514,145 @@ IfrMatch (
   //\r
   String[0] = NULL;\r
   String[1] = NULL;\r
+  HandleBuffer = NULL;\r
+  RegExSyntaxTypeList = NULL;\r
   Status = EFI_SUCCESS;\r
+  ZeroMem (Value, sizeof (Value));\r
+\r
+  Status = PopExpression (&Value[0]);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+\r
+  Status = PopExpression (&Value[1]);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+\r
   for (Index = 0; Index < 2; Index++) {\r
-    Status = PopExpression (&Value);\r
-    if (EFI_ERROR (Status)) {\r
+    if (Value[Index].Type != EFI_IFR_TYPE_STRING) {\r
+      Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+      Status = EFI_SUCCESS;\r
       goto Done;\r
     }\r
 \r
-    if (Value.Type != EFI_IFR_TYPE_STRING) {\r
-      Status = EFI_UNSUPPORTED;\r
+    String[Index] = GetToken (Value[Index].Value.string, FormSet->HiiHandle);\r
+    if (String [Index] == NULL) {\r
+      Status = EFI_NOT_FOUND;\r
       goto Done;\r
     }\r
+  }\r
 \r
-    String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
-    if (String== NULL) {\r
-      Status = EFI_NOT_FOUND;\r
+  BufferSize    = 0;\r
+  HandleBuffer  = NULL;\r
+  Status = gBS->LocateHandle(\r
+                      ByProtocol,\r
+                      &gEfiRegularExpressionProtocolGuid,\r
+                      NULL,\r
+                      &BufferSize,\r
+                      HandleBuffer);\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    HandleBuffer = AllocateZeroPool(BufferSize);\r
+    if (HandleBuffer == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
       goto Done;\r
     }\r
+    Status = gBS->LocateHandle(\r
+                        ByProtocol,\r
+                        &gEfiRegularExpressionProtocolGuid,\r
+                        NULL,\r
+                        &BufferSize,\r
+                        HandleBuffer);\r
+\r
   }\r
 \r
-  Result->Type = EFI_IFR_TYPE_BOOLEAN;\r
-  Result->Value.b = mUnicodeCollation->MetaiMatch (mUnicodeCollation, String[0], String[1]);\r
+  if (EFI_ERROR (Status)) {\r
+    Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+    Status = EFI_SUCCESS;\r
+    goto Done;\r
+  }\r
 \r
-Done:\r
-  SafeFreePool (String[0]);\r
-  SafeFreePool (String[1]);\r
+  ASSERT (HandleBuffer != NULL);\r
+  for ( Index = 0; Index < BufferSize / sizeof(EFI_HANDLE); Index ++) {\r
+    Status = gBS->HandleProtocol (\r
+                  HandleBuffer[Index],\r
+                  &gEfiRegularExpressionProtocolGuid,\r
+                  (VOID**)&RegularExpressionProtocol\r
+                 );\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+\r
+    RegExSyntaxTypeListSize = 0;\r
+    RegExSyntaxTypeList = NULL;\r
+\r
+    Status = RegularExpressionProtocol->GetInfo (\r
+                                          RegularExpressionProtocol, \r
+                                          &RegExSyntaxTypeListSize, \r
+                                          RegExSyntaxTypeList\r
+                                          );\r
+    if (Status == EFI_BUFFER_TOO_SMALL) {\r
+      RegExSyntaxTypeList = AllocateZeroPool(RegExSyntaxTypeListSize);\r
+      if (RegExSyntaxTypeList == NULL) {\r
+        Status = EFI_OUT_OF_RESOURCES;\r
+        goto Done;\r
+      }\r
+      Status = RegularExpressionProtocol->GetInfo (\r
+                                            RegularExpressionProtocol, \r
+                                            &RegExSyntaxTypeListSize, \r
+                                            RegExSyntaxTypeList\r
+                                            );\r
+    } else if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+\r
+    for (GuidIndex = 0; GuidIndex < RegExSyntaxTypeListSize / sizeof(EFI_GUID); GuidIndex++) {\r
+      if (CompareGuid (&RegExSyntaxTypeList[GuidIndex], SyntaxType)) {\r
+        //\r
+        // Find the match type, return the value.\r
+        //\r
+        Result->Type = EFI_IFR_TYPE_BOOLEAN;\r
+        Status = RegularExpressionProtocol->MatchString (\r
+                                              RegularExpressionProtocol, \r
+                                              String[0],\r
+                                              String[1],\r
+                                              SyntaxType,\r
+                                              &Result->Value.b,\r
+                                              NULL,\r
+                                              &CapturesCount\r
+                                              );\r
+        goto Done;\r
+      }\r
+    }\r
+\r
+    if (RegExSyntaxTypeList != NULL) {\r
+      FreePool (RegExSyntaxTypeList);\r
+    }\r
+  }\r
+\r
+  //\r
+  // Type specified by SyntaxType is not supported \r
+  // in any of the EFI_REGULAR_EXPRESSION_PROTOCOL instances.\r
+  //\r
+  Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+  Status = EFI_SUCCESS;\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 (RegExSyntaxTypeList != NULL) {\r
+    FreePool (RegExSyntaxTypeList);\r
+  }\r
+  if (HandleBuffer != NULL) {\r
+    FreePool (HandleBuffer);\r
+  }\r
   return Status;\r
 }\r
 \r
-\r
 /**\r
   Evaluate opcode EFI_IFR_FIND.\r
 \r
@@ -796,24 +1672,38 @@ IfrFind (
   )\r
 {\r
   EFI_STATUS     Status;\r
-  EFI_HII_VALUE  Value;\r
+  EFI_HII_VALUE  Value[3];\r
   CHAR16         *String[2];\r
   UINTN          Base;\r
   CHAR16         *StringPtr;\r
   UINTN          Index;\r
 \r
+  ZeroMem (Value, sizeof (Value));\r
+\r
   if (Format > EFI_IFR_FF_CASE_INSENSITIVE) {\r
-    return EFI_UNSUPPORTED;\r
+    return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  Status = PopExpression (&Value);\r
+  Status = PopExpression (&Value[0]);\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
+  Status = PopExpression (&Value[1]);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = PopExpression (&Value[2]);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }  \r
+\r
+  if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
+    Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+    return EFI_SUCCESS;\r
   }\r
-  Base = (UINTN) Value.Value.u64;\r
+  Base = (UINTN) Value[0].Value.u64;\r
 \r
   //\r
   // String[0] - sub-string\r
@@ -822,18 +1712,14 @@ IfrFind (
   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
+    if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {\r
+      Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+      Status = EFI_SUCCESS;\r
       goto Done;\r
     }\r
 \r
-    String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
-    if (String== NULL) {\r
+    String[Index] = GetToken (Value[Index + 1].Value.string, FormSet->HiiHandle);\r
+    if (String[Index] == NULL) {\r
       Status = EFI_NOT_FOUND;\r
       goto Done;\r
     }\r
@@ -855,8 +1741,12 @@ IfrFind (
   }\r
 \r
 Done:\r
-  SafeFreePool (String[0]);\r
-  SafeFreePool (String[1]);\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
@@ -879,56 +1769,86 @@ IfrMid (
   )\r
 {\r
   EFI_STATUS     Status;\r
-  EFI_HII_VALUE  Value;\r
+  EFI_HII_VALUE  Value[3];\r
   CHAR16         *String;\r
   UINTN          Base;\r
   UINTN          Length;\r
   CHAR16         *SubString;\r
+  UINT16         BufferLen;\r
+  UINT8          *Buffer;\r
 \r
-  Status = PopExpression (&Value);\r
+  ZeroMem (Value, sizeof (Value));\r
+\r
+  Status = PopExpression (&Value[0]);\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
+  Status = PopExpression (&Value[1]);\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
+  Status = PopExpression (&Value[2]);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
+  } \r
+\r
+  if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
+    Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+    return EFI_SUCCESS;\r
   }\r
-  if (Value.Type != EFI_IFR_TYPE_STRING) {\r
-    return EFI_UNSUPPORTED;\r
+  Length = (UINTN) Value[0].Value.u64;\r
+\r
+  if (Value[1].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
+    Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+    return EFI_SUCCESS;\r
   }\r
-  String = GetToken (Value.Value.string, FormSet->HiiHandle);\r
-  if (String == NULL) {\r
-    return EFI_NOT_FOUND;\r
+  Base = (UINTN) Value[1].Value.u64;\r
+\r
+  if (Value[2].Type != EFI_IFR_TYPE_STRING && !IsTypeInBuffer(&Value[2])) {\r
+    Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+    return EFI_SUCCESS;\r
   }\r
+  if (Value[2].Type == EFI_IFR_TYPE_STRING) {\r
+    String = GetToken (Value[2].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
+    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
 \r
-  Result->Type = EFI_IFR_TYPE_STRING;\r
-  Result->Value.string = NewString (SubString, FormSet->HiiHandle);\r
+    Result->Type = EFI_IFR_TYPE_STRING;\r
+    Result->Value.string = NewString (SubString, FormSet->HiiHandle);\r
+\r
+    FreePool (String);\r
+  } else {\r
+    BufferLen = GetLengthForValue (&Value[2]);\r
+    Buffer = GetBufferForValue (&Value[2]);\r
 \r
-  gBS->FreePool (String);\r
+    Result->Type = EFI_IFR_TYPE_BUFFER;\r
+    if (Length == 0 || Base >= BufferLen) {\r
+      Result->BufferLen = 0;\r
+      Result->Buffer = NULL;\r
+    } else {\r
+      Result->BufferLen = (UINT16)((BufferLen - Base) < Length ? (BufferLen - Base) : Length);    \r
+      Result->Buffer = AllocateZeroPool (Result->BufferLen);\r
+      ASSERT (Result->Buffer != NULL);\r
+      CopyMem (Result->Buffer, &Buffer[Base], Result->BufferLen);\r
+    }\r
 \r
+    if (Value[2].Type == EFI_IFR_TYPE_BUFFER) {\r
+      FreePool (Value[2].Buffer);\r
+    }\r
+  }\r
+  \r
   return Status;\r
 }\r
 \r
@@ -950,7 +1870,7 @@ IfrToken (
   )\r
 {\r
   EFI_STATUS     Status;\r
-  EFI_HII_VALUE  Value;\r
+  EFI_HII_VALUE  Value[3];\r
   CHAR16         *String[2];\r
   UINTN          Count;\r
   CHAR16         *Delimiter;\r
@@ -958,14 +1878,28 @@ IfrToken (
   CHAR16         *StringPtr;\r
   UINTN          Index;\r
 \r
-  Status = PopExpression (&Value);\r
+  ZeroMem (Value, sizeof (Value));\r
+\r
+  Status = PopExpression (&Value[0]);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = PopExpression (&Value[1]);\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
+  Status = PopExpression (&Value[2]);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  } \r
+\r
+  if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) { \r
+    Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+    return EFI_SUCCESS;\r
   }\r
-  Count = (UINTN) Value.Value.u64;\r
+  Count = (UINTN) Value[0].Value.u64;\r
 \r
   //\r
   // String[0] - Delimiter\r
@@ -974,18 +1908,14 @@ IfrToken (
   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
+    if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {\r
+      Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+      Status = EFI_SUCCESS;   \r
       goto Done;\r
     }\r
 \r
-    String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
-    if (String== NULL) {\r
+    String[Index] = GetToken (Value[Index + 1].Value.string, FormSet->HiiHandle);\r
+    if (String[Index] == NULL) {\r
       Status = EFI_NOT_FOUND;\r
       goto Done;\r
     }\r
@@ -1025,8 +1955,12 @@ IfrToken (
   Result->Value.string = NewString (SubString, FormSet->HiiHandle);\r
 \r
 Done:\r
-  SafeFreePool (String[0]);\r
-  SafeFreePool (String[1]);\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
@@ -1051,7 +1985,7 @@ IfrSpan (
   )\r
 {\r
   EFI_STATUS     Status;\r
-  EFI_HII_VALUE  Value;\r
+  EFI_HII_VALUE  Value[3];\r
   CHAR16         *String[2];\r
   CHAR16         *Charset;\r
   UINTN          Base;\r
@@ -1059,14 +1993,28 @@ IfrSpan (
   CHAR16         *StringPtr;\r
   BOOLEAN        Found;\r
 \r
-  Status = PopExpression (&Value);\r
+  ZeroMem (Value, sizeof (Value));\r
+\r
+  Status = PopExpression (&Value[0]);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = PopExpression (&Value[1]);\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
+  Status = PopExpression (&Value[2]);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  } \r
+\r
+  if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
+    Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+    return EFI_SUCCESS;\r
   }\r
-  Base = (UINTN) Value.Value.u64;\r
+  Base = (UINTN) Value[0].Value.u64;\r
 \r
   //\r
   // String[0] - Charset\r
@@ -1075,25 +2023,22 @@ IfrSpan (
   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
+    if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {\r
+      Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+      Status = EFI_SUCCESS;\r
       goto Done;\r
     }\r
 \r
-    String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
-    if (String== NULL) {\r
+    String[Index] = GetToken (Value[Index + 1].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
+    Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+    Status = EFI_SUCCESS;\r
     goto Done;\r
   }\r
 \r
@@ -1129,8 +2074,12 @@ IfrSpan (
   Result->Value.u64 = StringPtr - String[1];\r
 \r
 Done:\r
-  SafeFreePool (String[0]);\r
-  SafeFreePool (String[1]);\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
@@ -1182,44 +2131,89 @@ ExtendValueToU64 (
   Value->Value.u64 = Temp;\r
 }\r
 \r
+/**\r
+  Get UINT64 type value.\r
+\r
+  @param  Value                  Input Hii value.\r
+\r
+  @retval UINT64                 Return the UINT64 type value.\r
+\r
+**/\r
+UINT64\r
+HiiValueToUINT64 (\r
+  IN EFI_HII_VALUE      *Value\r
+  )\r
+{\r
+  UINT64  RetVal;\r
+\r
+  RetVal = 0;\r
+\r
+  switch (Value->Type) {\r
+  case EFI_IFR_TYPE_NUM_SIZE_8:\r
+    RetVal = Value->Value.u8;\r
+    break;\r
+\r
+  case EFI_IFR_TYPE_NUM_SIZE_16:\r
+    RetVal = Value->Value.u16;\r
+    break;\r
+\r
+  case EFI_IFR_TYPE_NUM_SIZE_32:\r
+    RetVal = Value->Value.u32;\r
+    break;\r
+\r
+  case EFI_IFR_TYPE_BOOLEAN:\r
+    RetVal = Value->Value.b;\r
+    break;\r
+\r
+  case EFI_IFR_TYPE_DATE:\r
+    RetVal = *(UINT64*) &Value->Value.date;\r
+    break;\r
+\r
+  case EFI_IFR_TYPE_TIME:\r
+    RetVal = (*(UINT64*) &Value->Value.time) & 0xffffff;\r
+    break;\r
+\r
+  default:\r
+    RetVal = Value->Value.u64;\r
+    break;\r
+  }\r
+\r
+  return RetVal;\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  Result                 Return value after compare.\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
   @param  HiiHandle              Only required for string compare.\r
 \r
-  @retval EFI_INVALID_PARAMETER  Could not perform comparation on two values.\r
-  @retval 0                      Two operators equeal.\r
-  @return Positive value if Value1 is greater than Value2.\r
-  @retval Negative value if Value1 is less than Value2.\r
+  @retval other                  Could not perform compare on two values.\r
+  @retval EFI_SUCCESS            Compare the value success.\r
 \r
 **/\r
-INTN\r
+EFI_STATUS\r
 CompareHiiValue (\r
   IN  EFI_HII_VALUE   *Value1,\r
   IN  EFI_HII_VALUE   *Value2,\r
+  OUT INTN            *Result,\r
   IN  EFI_HII_HANDLE  HiiHandle OPTIONAL\r
   )\r
 {\r
-  INTN    Result;\r
   INT64   Temp64;\r
   CHAR16  *Str1;\r
   CHAR16  *Str2;\r
+  UINTN   Len;\r
+  UINT8   *Buf1;\r
+  UINT16  Buf1Len;\r
+  UINT8   *Buf2;\r
+  UINT16  Buf2Len;\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->Type == EFI_IFR_TYPE_STRING && Value2->Type == EFI_IFR_TYPE_STRING) {\r
     if (Value1->Value.string == 0 || Value2->Value.string == 0) {\r
       //\r
       // StringId 0 is reserved\r
@@ -1228,7 +2222,8 @@ CompareHiiValue (
     }\r
 \r
     if (Value1->Value.string == Value2->Value.string) {\r
-      return 0;\r
+      *Result = 0;\r
+      return EFI_SUCCESS;\r
     }\r
 \r
     Str1 = GetToken (Value1->Value.string, HiiHandle);\r
@@ -1236,41 +2231,282 @@ CompareHiiValue (
       //\r
       // String not found\r
       //\r
-      return EFI_INVALID_PARAMETER;\r
+      return EFI_NOT_FOUND;\r
     }\r
 \r
     Str2 = GetToken (Value2->Value.string, HiiHandle);\r
     if (Str2 == NULL) {\r
-      gBS->FreePool (Str1);\r
-      return EFI_INVALID_PARAMETER;\r
+      FreePool (Str1);\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    *Result = StrCmp (Str1, Str2);\r
+\r
+    FreePool (Str1);\r
+    FreePool (Str2);\r
+\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Take types(date, time, ref, buffer) as buffer\r
+  //\r
+  if (IsTypeInBuffer(Value1) && IsTypeInBuffer(Value2)) {\r
+    Buf1    = GetBufferForValue(Value1);\r
+    Buf1Len = GetLengthForValue(Value1);\r
+    Buf2    = GetBufferForValue(Value2);\r
+    Buf2Len = GetLengthForValue(Value2);\r
+    \r
+    Len = Buf1Len > Buf2Len ? Buf2Len : Buf1Len;\r
+    *Result = CompareMem (Buf1, Buf2, Len);\r
+    if ((*Result == 0) && (Buf1Len != Buf2Len)) {\r
+      //\r
+      // In this case, means base on samll number buffer, the data is same\r
+      // So which value has more data, which value is bigger.\r
+      //\r
+      *Result = Buf1Len > Buf2Len ? 1 : -1;\r
+    }\r
+    return EFI_SUCCESS;\r
+  }  \r
+\r
+  //\r
+  // Take types(integer, boolean) as integer\r
+  //\r
+  if (IsTypeInUINT64(Value1) && IsTypeInUINT64(Value2)) {\r
+    Temp64 = HiiValueToUINT64(Value1) - HiiValueToUINT64(Value2);\r
+    if (Temp64 > 0) {\r
+      *Result = 1;\r
+    } else if (Temp64 < 0) {\r
+      *Result = -1;\r
+    } else {\r
+      *Result = 0;\r
+    }\r
+\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  return EFI_UNSUPPORTED;\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
+  Get question value from the predefined formset.\r
+\r
+  @param  DevicePath             The driver's device path which produece the formset data.\r
+  @param  InputHiiHandle         The hii handle associate with the formset data.\r
+  @param  FormSetGuid            The formset guid which include the question.\r
+  @param  QuestionId             The question id which need to get value from.\r
+  @param  Value                  The return data about question's value.\r
+  \r
+  @retval TRUE                   Get the question value success.\r
+  @retval FALSE                  Get the question value failed.\r
+**/\r
+BOOLEAN \r
+GetQuestionValueFromForm (\r
+  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath,\r
+  IN EFI_HII_HANDLE            InputHiiHandle,\r
+  IN EFI_GUID                  *FormSetGuid,\r
+  IN EFI_QUESTION_ID           QuestionId,\r
+  OUT EFI_HII_VALUE            *Value\r
+  )\r
+{\r
+  EFI_STATUS                   Status;\r
+  EFI_HII_HANDLE               HiiHandle;\r
+  FORM_BROWSER_STATEMENT       *Question;\r
+  FORM_BROWSER_FORMSET         *FormSet;\r
+  FORM_BROWSER_FORM            *Form;\r
+  BOOLEAN                      GetTheVal;\r
+  LIST_ENTRY                   *Link;\r
+\r
+  // \r
+  // The input parameter DevicePath or InputHiiHandle must have one valid input. \r
+  //\r
+  ASSERT ((DevicePath != NULL && InputHiiHandle == NULL) || \r
+          (DevicePath == NULL && InputHiiHandle != NULL) );\r
+\r
+  GetTheVal    = TRUE;\r
+  HiiHandle    = NULL;\r
+  Question     = NULL;\r
+  Form         = NULL;\r
+\r
+  //\r
+  // Get HiiHandle.\r
+  //\r
+  if (DevicePath != NULL) {\r
+    HiiHandle = DevicePathToHiiHandle (DevicePath, FormSetGuid);\r
+    if (HiiHandle == NULL) {\r
+      return FALSE;\r
     }\r
+  } else {\r
+    HiiHandle = InputHiiHandle;\r
+  } \r
+  ASSERT (HiiHandle != NULL);\r
+\r
+  //\r
+  // Get the formset data include this question.\r
+  //\r
+  FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));\r
+  ASSERT (FormSet != NULL);\r
+  Status = InitializeFormSet(HiiHandle, FormSetGuid, FormSet);\r
+  if (EFI_ERROR (Status)) {\r
+    GetTheVal = FALSE;\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // Base on the Question Id to get the question info.\r
+  //  \r
+  Question = IdToQuestion(FormSet, NULL, QuestionId);\r
+  if (Question == NULL) {\r
+    GetTheVal = FALSE;\r
+    goto Done;\r
+  }\r
 \r
-    Result = StrCmp (Str1, Str2);\r
+  //\r
+  // Search form 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
-    gBS->FreePool (Str1);\r
-    gBS->FreePool (Str2);\r
+    Question = IdToQuestion2 (Form, QuestionId);\r
+    if (Question != NULL) {\r
+      break;\r
+    }\r
 \r
-    return Result;\r
+    Link = GetNextNode (&FormSet->FormListHead, Link);\r
+    Form = NULL;\r
   }\r
-\r
+  ASSERT (Form != NULL);\r
+  \r
   //\r
-  // Take remain types(integer, boolean, date/time) as integer\r
+  // Get the question value.\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
+  Status = GetQuestionValue(FormSet, Form, Question, GetSetValueWithEditBuffer);\r
+  if (EFI_ERROR (Status)) {\r
+    GetTheVal = FALSE;\r
+    goto Done;\r
   }\r
 \r
-  return Result;\r
+  CopyMem (Value, &Question->HiiValue, sizeof (EFI_HII_VALUE));\r
+  \r
+Done:\r
+  //\r
+  // Clean the formset structure and restore the global parameter.\r
+  //\r
+  if (FormSet != NULL) {\r
+    DestroyFormSet (FormSet);\r
+  }\r
+  \r
+  return GetTheVal;\r
 }\r
 \r
-\r
 /**\r
-  Evaluate the result of a HII expression\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
@@ -1305,13 +2541,27 @@ EvaluateExpression (
   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
+  EFI_HII_VALUE           QuestionVal;\r
+  EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+\r
+  StrPtr = NULL;\r
 \r
   //\r
-  // Always reset the stack before evaluating an Expression\r
+  // Save current stack offset.\r
   //\r
-  ResetExpressionStack ();\r
+  StackOffset = SaveExpressionEvaluationStackOffset ();\r
 \r
+  ASSERT (Expression != NULL);\r
   Expression->Result.Type = EFI_IFR_TYPE_OTHER;\r
 \r
   Link = GetFirstNode (&Expression->OpCodeListHead);\r
@@ -1335,12 +2585,19 @@ EvaluateExpression (
     case EFI_IFR_EQ_ID_VAL_OP:\r
       Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
       if (Question == NULL) {\r
-        return EFI_NOT_FOUND;\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        break;\r
+      }\r
+\r
+      Status = CompareHiiValue (&Question->HiiValue, &OpCode->Value, &Result, NULL);\r
+      if (Status == EFI_UNSUPPORTED) {\r
+        Status = EFI_SUCCESS;\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        break;\r
       }\r
 \r
-      Result = CompareHiiValue (&Question->HiiValue, &OpCode->Value, NULL);\r
-      if (Result == EFI_INVALID_PARAMETER) {\r
-        return EFI_INVALID_PARAMETER;\r
+      if (EFI_ERROR (Status)) {\r
+        goto Done;\r
       }\r
       Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
       break;\r
@@ -1348,25 +2605,33 @@ EvaluateExpression (
     case EFI_IFR_EQ_ID_ID_OP:\r
       Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
       if (Question == NULL) {\r
-        return EFI_NOT_FOUND;\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        break;\r
       }\r
 \r
       Question2 = IdToQuestion (FormSet, Form, OpCode->QuestionId2);\r
       if (Question2 == NULL) {\r
-        return EFI_NOT_FOUND;\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        break;\r
       }\r
 \r
-      Result = CompareHiiValue (&Question->HiiValue, &Question2->HiiValue, FormSet->HiiHandle);\r
-      if (Result == EFI_INVALID_PARAMETER) {\r
-        return EFI_INVALID_PARAMETER;\r
+      Status = CompareHiiValue (&Question->HiiValue, &Question2->HiiValue, &Result, FormSet->HiiHandle);\r
+      if (Status == EFI_UNSUPPORTED) {\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        Status = EFI_SUCCESS;\r
+        break;\r
+      }\r
+      if (EFI_ERROR (Status)) {\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
+    case EFI_IFR_EQ_ID_VAL_LIST_OP:\r
       Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
       if (Question == NULL) {\r
-        return EFI_NOT_FOUND;\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        break;\r
       }\r
 \r
       Value->Value.b = FALSE;\r
@@ -1381,7 +2646,7 @@ EvaluateExpression (
     case EFI_IFR_DUP_OP:\r
       Status = PopExpression (Value);\r
       if (EFI_ERROR (Status)) {\r
-        return Status;\r
+        goto Done;\r
       }\r
 \r
       Status = PushExpression (Value);\r
@@ -1391,46 +2656,197 @@ EvaluateExpression (
     case EFI_IFR_THIS_OP:\r
       Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
       if (Question == NULL) {\r
-        return EFI_NOT_FOUND;\r
+        Status = EFI_NOT_FOUND;\r
+        goto Done;\r
       }\r
 \r
       Value = &Question->HiiValue;\r
       break;\r
 \r
-    case EFI_IFR_QUESTION_REF3_OP:\r
-      if (OpCode->DevicePath == 0) {\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
+        case EFI_HII_VARSTORE_EFI_VARIABLE_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, GetSetValueWithEditBuffer);\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
+          break;\r
+        default:\r
+          //\r
+          // Not recognize storage.\r
+          //\r
+          Status = EFI_UNSUPPORTED;\r
+          goto Done;\r
+        }\r
+      } else {\r
         //\r
-        // EFI_IFR_QUESTION_REF3\r
-        // Pop an expression from the expression stack\r
+        // For Time/Date Data\r
         //\r
-        Status = PopExpression (Value);\r
-        if (EFI_ERROR (Status)) {\r
-          return Status;\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
-        //\r
-        // Validate the expression value\r
-        //\r
-        if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
-          return EFI_NOT_FOUND;\r
+      break;\r
+\r
+    case EFI_IFR_QUESTION_REF3_OP:\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
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        break;\r
+      }\r
+\r
+      if (OpCode->DevicePath != 0) {\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+\r
+        StrPtr = GetToken (OpCode->DevicePath, FormSet->HiiHandle);\r
+        if (StrPtr != NULL && mPathFromText != NULL) {\r
+          DevicePath = mPathFromText->ConvertTextToDevicePath(StrPtr);\r
+          if (DevicePath != NULL && GetQuestionValueFromForm(DevicePath, NULL, &OpCode->Guid, Value->Value.u16, &QuestionVal)) {\r
+            Value = &QuestionVal;\r
+          }\r
+          if (DevicePath != NULL) {\r
+            FreePool (DevicePath);\r
+          }\r
         }\r
 \r
+        if (StrPtr != NULL) {\r
+          FreePool (StrPtr);\r
+        }\r
+      } else if (IsZeroGuid (&OpCode->Guid)) {\r
+        if (!GetQuestionValueFromForm(NULL, FormSet->HiiHandle, &OpCode->Guid, Value->Value.u16, &QuestionVal)){\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          break;\r
+        }\r
+        Value = &QuestionVal;\r
+      } else {\r
         Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
         if (Question == NULL) {\r
-          return EFI_NOT_FOUND;\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          break;\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
@@ -1440,15 +2856,17 @@ EvaluateExpression (
       //\r
       RuleExpression = RuleIdToExpression (Form, OpCode->RuleId);\r
       if (RuleExpression == NULL) {\r
-        return EFI_NOT_FOUND;\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        break;\r
       }\r
 \r
       //\r
       // Evaluate this rule expression\r
       //\r
       Status = EvaluateExpression (FormSet, Form, RuleExpression);\r
-      if (EFI_ERROR (Status)) {\r
-        return Status;\r
+      if (EFI_ERROR (Status) || RuleExpression->Result.Type == EFI_IFR_TYPE_UNDEFINED) {\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        break;\r
       }\r
 \r
       Value = &RuleExpression->Result;\r
@@ -1482,29 +2900,38 @@ EvaluateExpression (
     case EFI_IFR_LENGTH_OP:\r
       Status = PopExpression (Value);\r
       if (EFI_ERROR (Status)) {\r
-        return Status;\r
+        goto Done;\r
       }\r
-      if (Value->Type != EFI_IFR_TYPE_STRING) {\r
-        return EFI_INVALID_PARAMETER;\r
+      if (Value->Type != EFI_IFR_TYPE_STRING && !IsTypeInBuffer (Value)) {\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        break;\r
       }\r
 \r
-      StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
-      if (StrPtr == NULL) {\r
-        return EFI_INVALID_PARAMETER;\r
-      }\r
+      if (Value->Type == EFI_IFR_TYPE_STRING) {\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
-      gBS->FreePool (StrPtr);\r
+        Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+        Value->Value.u64 = StrLen (StrPtr);\r
+        FreePool (StrPtr);\r
+      } else {\r
+        Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+        Value->Value.u64 = GetLengthForValue(Value);\r
+        FreePool (Value->Buffer);\r
+      }\r
       break;\r
 \r
     case EFI_IFR_NOT_OP:\r
       Status = PopExpression (Value);\r
       if (EFI_ERROR (Status)) {\r
-        return Status;\r
+        goto Done;\r
       }\r
       if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {\r
-        return EFI_INVALID_PARAMETER;\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        break;\r
       }\r
       Value->Value.b = (BOOLEAN) (!Value->Value.b);\r
       break;\r
@@ -1515,19 +2942,21 @@ EvaluateExpression (
       //\r
       Status = PopExpression (Value);\r
       if (EFI_ERROR (Status)) {\r
-        return 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
-        return EFI_NOT_FOUND;\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        break;\r
       }\r
 \r
       Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
       if (Question == NULL) {\r
-        return EFI_NOT_FOUND;\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        break;\r
       }\r
 \r
       Value = &Question->HiiValue;\r
@@ -1539,14 +2968,15 @@ EvaluateExpression (
       //\r
       Status = PopExpression (Value);\r
       if (EFI_ERROR (Status)) {\r
-        return 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
-        return EFI_NOT_FOUND;\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        break;\r
       }\r
 \r
       Value->Type = EFI_IFR_TYPE_STRING;\r
@@ -1559,7 +2989,7 @@ EvaluateExpression (
       } else {\r
         Index = (UINT16) Value->Value.u64;\r
         Value->Value.string = Index;\r
-        gBS->FreePool (StrPtr);\r
+        FreePool (StrPtr);\r
       }\r
       break;\r
 \r
@@ -1569,7 +2999,7 @@ EvaluateExpression (
       //\r
       Status = PopExpression (Value);\r
       if (EFI_ERROR (Status)) {\r
-        return Status;\r
+        goto Done;\r
       }\r
 \r
       //\r
@@ -1580,27 +3010,50 @@ EvaluateExpression (
         // When converting from an unsigned integer, zero will be converted to\r
         // FALSE and any other value will be converted to TRUE.\r
         //\r
-        Value->Value.b = (BOOLEAN) ((Value->Value.u64) ? TRUE : FALSE);\r
+        Value->Value.b = (BOOLEAN) (HiiValueToUINT64(Value) != 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
+        // with "false" is True, then push False. Otherwise, push Undefined. \r
         //\r
         StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
         if (StrPtr == NULL) {\r
-          return EFI_INVALID_PARAMETER;\r
+          Status = EFI_INVALID_PARAMETER;\r
+          goto Done;\r
         }\r
-\r
-        if ((StrCmp (StrPtr, L"true") == 0) || (StrCmp (StrPtr, L"false") == 0)){\r
+        \r
+        IfrStrToUpper (StrPtr);\r
+        if (StrCmp (StrPtr, L"TRUE") == 0){\r
           Value->Value.b = TRUE;\r
+          Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
+        } else if (StrCmp (StrPtr, L"FALSE") == 0) {\r
+          Value->Value.b = FALSE;\r
+          Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
         } else {\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        }\r
+        FreePool (StrPtr);\r
+      } else if (Value->Type == EFI_IFR_TYPE_BUFFER) {\r
+        //\r
+        // When converting from a buffer, if the buffer is all zeroes, \r
+        // then push False. Otherwise push True. \r
+        //\r
+        for (Index =0; Index < Value->BufferLen; Index ++) {\r
+          if (Value->Buffer[Index] != 0) {            \r
+            break;\r
+          }\r
+        }\r
+\r
+        if (Index >= Value->BufferLen) {\r
           Value->Value.b = FALSE;\r
+        } else {\r
+          Value->Value.b = TRUE;\r
         }\r
-        gBS->FreePool (StrPtr);\r
         Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
+        FreePool (Value->Buffer);\r
       }\r
       break;\r
 \r
@@ -1616,21 +3069,23 @@ EvaluateExpression (
     case EFI_IFR_TO_UPPER_OP:\r
       Status = InitializeUnicodeCollationProtocol ();\r
       if (EFI_ERROR (Status)) {\r
-        return Status;\r
+        goto Done;\r
       }\r
 \r
       Status = PopExpression (Value);\r
       if (EFI_ERROR (Status)) {\r
-        return Status;\r
+        goto Done;\r
       }\r
 \r
       if (Value->Type != EFI_IFR_TYPE_STRING) {\r
-        return EFI_UNSUPPORTED;\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        break;\r
       }\r
 \r
       StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
       if (StrPtr == NULL) {\r
-        return EFI_NOT_FOUND;\r
+        Status = EFI_NOT_FOUND;\r
+        goto Done;\r
       }\r
 \r
       if (OpCode->Operand == EFI_IFR_TO_LOWER_OP) {\r
@@ -1639,7 +3094,7 @@ EvaluateExpression (
         mUnicodeCollation->StrUpr (mUnicodeCollation, StrPtr);\r
       }\r
       Value->Value.string = NewString (StrPtr, FormSet->HiiHandle);\r
-      gBS->FreePool (StrPtr);\r
+      FreePool (StrPtr);\r
       break;\r
 \r
     case EFI_IFR_BITWISE_NOT_OP:\r
@@ -1648,14 +3103,139 @@ EvaluateExpression (
       //\r
       Status = PopExpression (Value);\r
       if (EFI_ERROR (Status)) {\r
-        return Status;\r
+        goto Done;\r
       }\r
       if (Value->Type > EFI_IFR_TYPE_DATE) {\r
-        return EFI_INVALID_PARAMETER;\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        break;\r
       }\r
 \r
       Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
-      Value->Value.u64 = ~Value->Value.u64;\r
+      Value->Value.u64 = ~ HiiValueToUINT64(Value);\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
+        case EFI_HII_VARSTORE_EFI_VARIABLE_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 (NameValue != 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
+              UnicodeValueToStringS (\r
+                StrPtr,\r
+                (OpCode->ValueWidth * 2 + 1) * sizeof (CHAR16) - ((UINTN)StrPtr - (UINTN)NameValue),\r
+                PREFIX_ZERO | RADIX_HEX,\r
+                *TempBuffer,\r
+                2\r
+                );\r
+              StrPtr += StrnLenS (StrPtr, OpCode->ValueWidth * 2 + 1 - ((UINTN)StrPtr - (UINTN)NameValue) / sizeof (CHAR16));\r
+            }\r
+            Status = SetValueByName (OpCode->VarStorage, OpCode->ValueName, NameValue, GetSetValueWithEditBuffer, NULL);\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
+        }\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
@@ -1675,10 +3255,7 @@ EvaluateExpression (
       //\r
       Status = PopExpression (&Data2);\r
       if (EFI_ERROR (Status)) {\r
-        return Status;\r
-      }\r
-      if (Data2.Type > EFI_IFR_TYPE_DATE) {\r
-        return EFI_INVALID_PARAMETER;\r
+        goto Done;\r
       }\r
 \r
       //\r
@@ -1686,50 +3263,58 @@ EvaluateExpression (
       //\r
       Status = PopExpression (&Data1);\r
       if (EFI_ERROR (Status)) {\r
-        return Status;\r
+        goto Done;\r
+      }\r
+\r
+      if (Data2.Type > EFI_IFR_TYPE_DATE) {\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        break;\r
       }\r
+\r
+\r
       if (Data1.Type > EFI_IFR_TYPE_DATE) {\r
-        return EFI_INVALID_PARAMETER;\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        break;\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
+          Value->Value.u64 = HiiValueToUINT64(&Data1) + HiiValueToUINT64(&Data2);\r
           break;\r
 \r
         case EFI_IFR_SUBTRACT_OP:\r
-          Value->Value.u64 = Data1.Value.u64 - Data2.Value.u64;\r
+          Value->Value.u64 = HiiValueToUINT64(&Data1) - HiiValueToUINT64(&Data2);\r
           break;\r
 \r
         case EFI_IFR_MULTIPLY_OP:\r
-          Value->Value.u64 = MultU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);\r
+          Value->Value.u64 = MultU64x32 (HiiValueToUINT64(&Data1), (UINT32) HiiValueToUINT64(&Data2));\r
           break;\r
 \r
         case EFI_IFR_DIVIDE_OP:\r
-          Value->Value.u64 = DivU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);\r
+          Value->Value.u64 = DivU64x32 (HiiValueToUINT64(&Data1), (UINT32) HiiValueToUINT64(&Data2));\r
           break;\r
 \r
         case EFI_IFR_MODULO_OP:\r
-          DivU64x32Remainder  (Data1.Value.u64, (UINT32) Data2.Value.u64, &TempValue);\r
+          DivU64x32Remainder  (HiiValueToUINT64(&Data1), (UINT32) HiiValueToUINT64(&Data2), &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
+          Value->Value.u64 = HiiValueToUINT64(&Data1) & HiiValueToUINT64(&Data2);\r
           break;\r
 \r
         case EFI_IFR_BITWISE_OR_OP:\r
-          Value->Value.u64 = Data1.Value.u64 | Data2.Value.u64;\r
+          Value->Value.u64 = HiiValueToUINT64(&Data1) | HiiValueToUINT64(&Data2);\r
           break;\r
 \r
         case EFI_IFR_SHIFT_LEFT_OP:\r
-          Value->Value.u64 = LShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);\r
+          Value->Value.u64 = LShiftU64 (HiiValueToUINT64(&Data1), (UINTN) HiiValueToUINT64(&Data2));\r
           break;\r
 \r
         case EFI_IFR_SHIFT_RIGHT_OP:\r
-          Value->Value.u64 = RShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);\r
+          Value->Value.u64 = RShiftU64 (HiiValueToUINT64(&Data1), (UINTN) HiiValueToUINT64(&Data2));\r
           break;\r
 \r
         default:\r
@@ -1744,10 +3329,7 @@ EvaluateExpression (
       //\r
       Status = PopExpression (&Data2);\r
       if (EFI_ERROR (Status)) {\r
-        return Status;\r
-      }\r
-      if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {\r
-        return EFI_INVALID_PARAMETER;\r
+        goto Done;\r
       }\r
 \r
       //\r
@@ -1755,10 +3337,17 @@ EvaluateExpression (
       //\r
       Status = PopExpression (&Data1);\r
       if (EFI_ERROR (Status)) {\r
-        return Status;\r
+        goto Done;\r
+      }\r
+\r
+      if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        break;\r
       }\r
+\r
       if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
-        return EFI_INVALID_PARAMETER;\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        break;\r
       }\r
 \r
       if (OpCode->Operand == EFI_IFR_AND_OP) {\r
@@ -1779,10 +3368,7 @@ EvaluateExpression (
       //\r
       Status = PopExpression (&Data2);\r
       if (EFI_ERROR (Status)) {\r
-        return Status;\r
-      }\r
-      if (Data2.Type > EFI_IFR_TYPE_BOOLEAN && Data2.Type != EFI_IFR_TYPE_STRING) {\r
-        return EFI_INVALID_PARAMETER;\r
+        goto Done;\r
       }\r
 \r
       //\r
@@ -1790,12 +3376,39 @@ EvaluateExpression (
       //\r
       Status = PopExpression (&Data1);\r
       if (EFI_ERROR (Status)) {\r
-        return Status;\r
+        goto Done;\r
+      }\r
+\r
+      if (Data2.Type > EFI_IFR_TYPE_BOOLEAN && \r
+          Data2.Type != EFI_IFR_TYPE_STRING && \r
+          !IsTypeInBuffer(&Data2)) {\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        break;\r
       }\r
 \r
-      Result = CompareHiiValue (&Data1, &Data2, FormSet->HiiHandle);\r
-      if (Result == EFI_INVALID_PARAMETER) {\r
-        return EFI_INVALID_PARAMETER;\r
+      if (Data1.Type > EFI_IFR_TYPE_BOOLEAN && \r
+          Data1.Type != EFI_IFR_TYPE_STRING && \r
+          !IsTypeInBuffer(&Data1)) {\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        break;\r
+      }\r
+\r
+      Status = CompareHiiValue (&Data1, &Data2, &Result, FormSet->HiiHandle);\r
+      if (Data1.Type == EFI_IFR_TYPE_BUFFER) {\r
+        FreePool (Data1.Buffer);\r
+      }\r
+      if (Data2.Type == EFI_IFR_TYPE_BUFFER) {\r
+        FreePool (Data2.Buffer);\r
+      }\r
+      \r
+      if (Status == EFI_UNSUPPORTED) {\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        Status = EFI_SUCCESS;\r
+        break;\r
+      }\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        goto Done;\r
       }\r
 \r
       switch (OpCode->Operand) {\r
@@ -1804,7 +3417,7 @@ EvaluateExpression (
         break;\r
 \r
       case EFI_IFR_NOT_EQUAL_OP:\r
-        Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
+        Value->Value.b = (BOOLEAN) ((Result != 0) ? TRUE : FALSE);\r
         break;\r
 \r
       case EFI_IFR_GREATER_EQUAL_OP:\r
@@ -1829,9 +3442,18 @@ EvaluateExpression (
       break;\r
 \r
     case EFI_IFR_MATCH_OP:\r
+      Status = InitializeUnicodeCollationProtocol ();\r
+      if (EFI_ERROR (Status)) {\r
+        goto Done;\r
+      }\r
+     \r
       Status = IfrMatch (FormSet, Value);\r
       break;\r
 \r
+    case EFI_IFR_MATCH2_OP:\r
+      Status = IfrMatch2 (FormSet, &OpCode->Guid, Value);\r
+      break;\r
+\r
     case EFI_IFR_CATENATE_OP:\r
       Status = IfrCatenate (FormSet, Value);\r
       break;\r
@@ -1845,7 +3467,7 @@ EvaluateExpression (
       //\r
       Status = PopExpression (&Data3);\r
       if (EFI_ERROR (Status)) {\r
-        return Status;\r
+        goto Done;\r
       }\r
 \r
       //\r
@@ -1853,7 +3475,7 @@ EvaluateExpression (
       //\r
       Status = PopExpression (&Data2);\r
       if (EFI_ERROR (Status)) {\r
-        return Status;\r
+        goto Done;\r
       }\r
 \r
       //\r
@@ -1861,10 +3483,11 @@ EvaluateExpression (
       //\r
       Status = PopExpression (&Data1);\r
       if (EFI_ERROR (Status)) {\r
-        return Status;\r
+        goto Done;\r
       }\r
       if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
-        return EFI_INVALID_PARAMETER;\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        break;\r
       }\r
 \r
       if (Data1.Value.b) {\r
@@ -1890,16 +3513,87 @@ EvaluateExpression (
       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, &Result, NULL) == EFI_SUCCESS) && (Result == 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
-      return Status;\r
+    if (EFI_ERROR (Status) || Value->Type == EFI_IFR_TYPE_UNDEFINED) {\r
+      goto Done;\r
     }\r
 \r
     Status = PushExpression (Value);\r
     if (EFI_ERROR (Status)) {\r
-      return Status;\r
+      goto Done;\r
     }\r
   }\r
 \r
@@ -1909,17 +3603,135 @@ EvaluateExpression (
   Value = &Data1;\r
   Status = PopExpression (Value);\r
   if (EFI_ERROR (Status)) {\r
-    return 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
-    return EFI_INVALID_PARAMETER;\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
-  CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));\r
+  return Status;\r
+}\r
 \r
-  return EFI_SUCCESS;\r
+/**\r
+  Check whether the result is TRUE or FALSE.\r
+  \r
+  For the EFI_HII_VALUE value type is numeric, return TRUE if the\r
+  value is not 0.\r
+\r
+  @param  Result             Input the result data.\r
+\r
+  @retval TRUE               The result is TRUE.\r
+  @retval FALSE              The result is FALSE.\r
+\r
+**/\r
+BOOLEAN\r
+IsTrue (\r
+  IN EFI_HII_VALUE     *Result\r
+  )\r
+{\r
+  switch (Result->Type) {\r
+  case EFI_IFR_TYPE_BOOLEAN:\r
+    return Result->Value.b;\r
+\r
+  case EFI_IFR_TYPE_NUM_SIZE_8:\r
+    return (BOOLEAN)(Result->Value.u8 != 0);\r
+\r
+  case EFI_IFR_TYPE_NUM_SIZE_16:\r
+    return (BOOLEAN)(Result->Value.u16 != 0);\r
+\r
+  case EFI_IFR_TYPE_NUM_SIZE_32:\r
+    return (BOOLEAN)(Result->Value.u32 != 0);\r
+\r
+  case EFI_IFR_TYPE_NUM_SIZE_64:\r
+    return (BOOLEAN)(Result->Value.u64 != 0);\r
+\r
+  default:\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+/**\r
+  Return the result of the expression list. Check the expression list and \r
+  return the highest priority express result.  \r
+  Priority: DisableIf > SuppressIf > GrayOutIf > FALSE\r
+\r
+  @param  ExpList             The input expression list.\r
+  @param  Evaluate            Whether need to evaluate the expression first.\r
+  @param  FormSet             FormSet associated with this expression.\r
+  @param  Form                Form associated with this expression.  \r
+\r
+  @retval EXPRESS_RESULT      Return the higher priority express result. \r
+                              DisableIf > SuppressIf > GrayOutIf > FALSE\r
+\r
+**/\r
+EXPRESS_RESULT \r
+EvaluateExpressionList (\r
+  IN FORM_EXPRESSION_LIST *ExpList,\r
+  IN BOOLEAN              Evaluate,\r
+  IN FORM_BROWSER_FORMSET *FormSet, OPTIONAL\r
+  IN FORM_BROWSER_FORM    *Form OPTIONAL\r
+  )\r
+{\r
+  UINTN              Index;\r
+  EXPRESS_RESULT     ReturnVal;\r
+  EXPRESS_RESULT     CompareOne;\r
+  EFI_STATUS         Status;\r
+\r
+  if (ExpList == NULL) {\r
+    return ExpressFalse;\r
+  }\r
+\r
+  ASSERT(ExpList->Signature == FORM_EXPRESSION_LIST_SIGNATURE);\r
+  Index     = 0;\r
+\r
+  //\r
+  // Check whether need to evaluate the expression first.\r
+  //\r
+  if (Evaluate) {  \r
+    while (ExpList->Count > Index) {\r
+      Status = EvaluateExpression (FormSet, Form, ExpList->Expression[Index++]);\r
+      if (EFI_ERROR (Status)) {\r
+        return ExpressFalse;\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // Run the list of expressions.\r
+  //\r
+  ReturnVal = ExpressFalse;\r
+  for (Index = 0; Index < ExpList->Count; Index++) {\r
+    if (IsTrue (&ExpList->Expression[Index]->Result)) {\r
+      switch (ExpList->Expression[Index]->Type) {\r
+        case EFI_HII_EXPRESSION_SUPPRESS_IF:\r
+          CompareOne = ExpressSuppress;\r
+          break;\r
+\r
+        case EFI_HII_EXPRESSION_GRAY_OUT_IF:\r
+          CompareOne = ExpressGrayOut;\r
+          break;\r
+\r
+        case EFI_HII_EXPRESSION_DISABLE_IF:\r
+          CompareOne = ExpressDisable;\r
+          break;\r
+\r
+        default:\r
+          return ExpressFalse; \r
+      }\r
+\r
+      ReturnVal = ReturnVal < CompareOne ? CompareOne : ReturnVal;\r
+    }\r
+  }\r
+  \r
+  return ReturnVal;\r
 }\r