]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/SetupBrowserDxe/Expression.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Expression.c
index 883693fde59233acd397001b1bf3d8b290bb5246..7f4929c2fcd90a59e934723ba158a20db03a9fd5 100644 (file)
@@ -1,14 +1,8 @@
 /** @file\r
 Utility functions for expression evaluation.\r
 \r
-Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution.  The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -34,6 +28,19 @@ EFI_HII_VALUE *mMapExpressionListStack = NULL;
 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
@@ -144,7 +151,7 @@ PushStack (
     (*StackPtr)->Buffer = AllocateCopyPool(Data->BufferLen, Data->Buffer);\r
     ASSERT ((*StackPtr)->Buffer != NULL);\r
   }\r
-  \r
+\r
   *StackPtr = *StackPtr + 1;\r
 \r
   return EFI_SUCCESS;\r
@@ -194,7 +201,10 @@ ResetCurrentExpressionStack (
   VOID\r
   )\r
 {\r
-  mCurrentExpressionPointer = mCurrentExpressionStack;\r
+  mCurrentExpressionPointer   = mCurrentExpressionStack;\r
+  mFormExpressionPointer      = mFormExpressionStack;\r
+  mStatementExpressionPointer = mStatementExpressionStack;\r
+  mOptionExpressionPointer    = mOptionExpressionStack;\r
 }\r
 \r
 \r
@@ -267,6 +277,294 @@ ResetMapExpressionListStack (
 }\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
@@ -447,6 +745,7 @@ PopExpression (
 **/\r
 UINTN\r
 SaveExpressionEvaluationStackOffset (\r
+  VOID\r
   )\r
 {\r
   UINTN TempStackOffset;\r
@@ -483,7 +782,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
@@ -522,7 +821,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
@@ -587,7 +886,7 @@ IdToQuestion (
       // to keep synchronous, always reload the Question Value.\r
       //\r
       if (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
-        GetQuestionValue (FormSet, Form, Question, FALSE);\r
+        GetQuestionValue (FormSet, Form, Question, GetSetValueWithHiiDriver);\r
       }\r
 \r
       return Question;\r
@@ -684,95 +983,236 @@ IfrStrToUpper (
   }\r
 }\r
 \r
-\r
 /**\r
-  Evaluate opcode EFI_IFR_TO_STRING.\r
+  Check whether this value type can be transfer to EFI_IFR_TYPE_BUFFER type.\r
 \r
-  @param  FormSet                Formset which contains this opcode.\r
-  @param  Format                 String format in EFI_IFR_TO_STRING.\r
-  @param  Result                 Evaluation result for this opcode.\r
+  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
-  @retval EFI_SUCCESS            Opcode evaluation success.\r
-  @retval Other                  Opcode evaluation failed.\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
-EFI_STATUS\r
-IfrToString (\r
-  IN FORM_BROWSER_FORMSET  *FormSet,\r
-  IN UINT8                 Format,\r
-  OUT  EFI_HII_VALUE       *Result\r
+BOOLEAN\r
+IsTypeInBuffer (\r
+  IN  EFI_HII_VALUE   *Value\r
   )\r
 {\r
-  EFI_STATUS     Status;\r
-  EFI_HII_VALUE  Value;\r
-  CHAR16         *String;\r
-  CHAR16         *PrintFormat;\r
-  CHAR16         Buffer[MAXIMUM_VALUE_CHARACTERS];\r
-  UINT8          *TmpBuf;\r
-  UINTN          BufferSize;\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
-  Status = PopExpression (&Value);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
+  default:\r
+    return FALSE;\r
   }\r
+}\r
 \r
-  switch (Value.Type) {\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
-    BufferSize = MAXIMUM_VALUE_CHARACTERS * sizeof (CHAR16);\r
-    switch (Format) {\r
-    case EFI_IFR_STRING_UNSIGNED_DEC:\r
-    case EFI_IFR_STRING_SIGNED_DEC:\r
-      PrintFormat = L"%ld";\r
-      break;\r
+  case EFI_IFR_TYPE_BOOLEAN:\r
+    return TRUE;\r
 \r
-    case EFI_IFR_STRING_LOWERCASE_HEX:\r
-      PrintFormat = L"%lx";\r
-      break;\r
+  default:\r
+    return FALSE;\r
+  }\r
+}\r
 \r
-    case EFI_IFR_STRING_UPPERCASE_HEX:\r
-      PrintFormat = L"%lX";\r
-      break;\r
+/**\r
+  Return the buffer length for this value.\r
 \r
-    default:\r
-      return EFI_UNSUPPORTED;\r
-    }\r
-    UnicodeSPrint (Buffer, BufferSize, PrintFormat, Value.Value.u64);\r
-    String = Buffer;\r
-    break;\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
-  case EFI_IFR_TYPE_STRING:\r
-    CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));\r
-    return EFI_SUCCESS;\r
+  @param   Value                  Expression value to compare on.\r
 \r
-  case EFI_IFR_TYPE_BOOLEAN:\r
-    String = (Value.Value.b) ? L"True" : L"False";\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
+\r
+  @param  FormSet                Formset which contains this opcode.\r
+  @param  Format                 String format in EFI_IFR_TO_STRING.\r
+  @param  Result                 Evaluation result for this opcode.\r
+\r
+  @retval EFI_SUCCESS            Opcode evaluation success.\r
+  @retval Other                  Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrToString (\r
+  IN FORM_BROWSER_FORMSET  *FormSet,\r
+  IN UINT8                 Format,\r
+  OUT  EFI_HII_VALUE       *Result\r
+  )\r
+{\r
+  EFI_STATUS     Status;\r
+  EFI_HII_VALUE  Value;\r
+  CHAR16         *String;\r
+  CHAR16         *PrintFormat;\r
+  CHAR16         Buffer[MAXIMUM_VALUE_CHARACTERS];\r
+  UINT8          *TmpBuf;\r
+  UINT8          *SrcBuf;\r
+  UINTN          SrcLen;\r
+  UINTN          BufferSize;\r
+\r
+  Status = PopExpression (&Value);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  switch (Value.Type) {\r
+  case EFI_IFR_TYPE_NUM_SIZE_8:\r
+  case EFI_IFR_TYPE_NUM_SIZE_16:\r
+  case EFI_IFR_TYPE_NUM_SIZE_32:\r
+  case EFI_IFR_TYPE_NUM_SIZE_64:\r
+    BufferSize = MAXIMUM_VALUE_CHARACTERS * sizeof (CHAR16);\r
+    switch (Format) {\r
+    case EFI_IFR_STRING_UNSIGNED_DEC:\r
+    case EFI_IFR_STRING_SIGNED_DEC:\r
+      PrintFormat = L"%ld";\r
+      break;\r
+\r
+    case EFI_IFR_STRING_LOWERCASE_HEX:\r
+      PrintFormat = L"%lx";\r
+      break;\r
+\r
+    case EFI_IFR_STRING_UPPERCASE_HEX:\r
+      PrintFormat = L"%lX";\r
+      break;\r
+\r
+    default:\r
+      Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+      return EFI_SUCCESS;\r
+    }\r
+    UnicodeSPrint (Buffer, BufferSize, PrintFormat, Value.Value.u64);\r
+    String = Buffer;\r
     break;\r
-    \r
+\r
+  case EFI_IFR_TYPE_STRING:\r
+    CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));\r
+    return EFI_SUCCESS;\r
+\r
+  case EFI_IFR_TYPE_BOOLEAN:\r
+    String = (Value.Value.b) ? L"True" : L"False";\r
+    break;\r
+\r
   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
+    // + 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
-    TmpBuf = AllocateZeroPool (Value.BufferLen + 3);\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, Value.Buffer, Value.BufferLen);\r
-      PrintFormat = L"%a"; \r
+      CopyMem (TmpBuf, SrcBuf, SrcLen);\r
+      PrintFormat = L"%a";\r
     } else {\r
       // Format == EFI_IFR_STRING_UNICODE\r
-      CopyMem (TmpBuf, Value.Buffer, Value.BufferLen * sizeof (CHAR16));\r
-      PrintFormat = L"%s";  \r
+      CopyMem (TmpBuf, SrcBuf, SrcLen * sizeof (CHAR16));\r
+      PrintFormat = L"%s";\r
     }\r
-    UnicodeSPrint (Buffer, MAXIMUM_VALUE_CHARACTERS, PrintFormat, Value.Buffer);  \r
-    String = Buffer; \r
+    UnicodeSPrint (Buffer, sizeof (Buffer), PrintFormat, TmpBuf);\r
+    String = Buffer;\r
     FreePool (TmpBuf);\r
-    FreePool (Value.Buffer);\r
+    if (Value.Type == EFI_IFR_TYPE_BUFFER) {\r
+      FreePool (Value.Buffer);\r
+    }\r
     break;\r
-    \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
@@ -807,8 +1247,9 @@ IfrToUint (
     return Status;\r
   }\r
 \r
-  if (Value.Type >= EFI_IFR_TYPE_OTHER && Value.Type != EFI_IFR_TYPE_BUFFER) {\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
@@ -832,13 +1273,18 @@ IfrToUint (
       Result->Value.u64 = StrDecimalToUint64 (String);\r
     }\r
     FreePool (String);\r
-  } else if (Value.Type == EFI_IFR_TYPE_BUFFER) {\r
-    if (Value.BufferLen > 8) {\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
-      return EFI_UNSUPPORTED;\r
     }\r
-    Result->Value.u64 = *(UINT64*) Value.Buffer;\r
-    FreePool (Value.Buffer);\r
   } else {\r
     CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));\r
   }\r
@@ -870,6 +1316,10 @@ IfrCatenate (
   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
@@ -881,14 +1331,20 @@ IfrCatenate (
   Status = EFI_SUCCESS;\r
   ZeroMem (Value, sizeof (Value));\r
 \r
-  for (Index = 0; Index < 2; Index++) {\r
-    Status = PopExpression (&Value[Index]);\r
-    if (EFI_ERROR (Status)) {\r
-      goto Done;\r
-    }\r
+  Status = PopExpression (&Value[0]);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
 \r
-    if (Value[Index].Type != EFI_IFR_TYPE_STRING && Value[Index].Type != EFI_IFR_TYPE_BUFFER) {\r
-      Status = EFI_UNSUPPORTED;\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 && !IsTypeInBuffer(&Value[Index])) {\r
+      Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+      Status = EFI_SUCCESS;\r
       goto Done;\r
     }\r
 \r
@@ -903,22 +1359,29 @@ IfrCatenate (
 \r
   if (Value[0].Type == EFI_IFR_TYPE_STRING) {\r
     Size = StrSize (String[0]);\r
-    StringPtr= AllocatePool (StrSize (String[1]) + Size);\r
+    MaxLen = (StrSize (String[1]) + Size) / sizeof (CHAR16);\r
+    StringPtr= AllocatePool (MaxLen * sizeof (CHAR16));\r
     ASSERT (StringPtr != NULL);\r
-    StrCpy (StringPtr, String[1]);\r
-    StrCat (StringPtr, String[0]);\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
-    Result->BufferLen = (UINT16) (Value[0].BufferLen + Value[1].BufferLen);\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
-    CopyMem (Result->Buffer, Value[0].Buffer, Value[0].BufferLen);\r
-    CopyMem (&Result->Buffer[Value[0].BufferLen], Value[1].Buffer, Value[1].BufferLen);\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
@@ -958,7 +1421,7 @@ IfrMatch (
   )\r
 {\r
   EFI_STATUS     Status;\r
-  EFI_HII_VALUE  Value;\r
+  EFI_HII_VALUE  Value[2];\r
   CHAR16         *String[2];\r
   UINTN          Index;\r
 \r
@@ -969,18 +1432,26 @@ IfrMatch (
   String[0] = NULL;\r
   String[1] = NULL;\r
   Status = EFI_SUCCESS;\r
-  for (Index = 0; Index < 2; Index++) {\r
-    Status = PopExpression (&Value);\r
-    if (EFI_ERROR (Status)) {\r
-      goto Done;\r
-    }\r
+  ZeroMem (Value, sizeof (Value));\r
+\r
+  Status = PopExpression (&Value[0]);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
 \r
-    if (Value.Type != EFI_IFR_TYPE_STRING) {\r
-      Status = EFI_UNSUPPORTED;\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
+    String[Index] = GetToken (Value[Index].Value.string, FormSet->HiiHandle);\r
     if (String [Index] == NULL) {\r
       Status = EFI_NOT_FOUND;\r
       goto Done;\r
@@ -1001,6 +1472,180 @@ Done:
   return Status;\r
 }\r
 \r
+/**\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
+  @retval Other                  Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\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[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
+  // String[1] - pattern\r
+  //\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
+    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[Index].Value.string, FormSet->HiiHandle);\r
+    if (String [Index] == NULL) {\r
+      Status = EFI_NOT_FOUND;\r
+      goto Done;\r
+    }\r
+  }\r
+\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
+  if (EFI_ERROR (Status)) {\r
+    Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+    Status = EFI_SUCCESS;\r
+    goto Done;\r
+  }\r
+\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
   Evaluate opcode EFI_IFR_FIND.\r
@@ -1021,24 +1666,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
-  Base = (UINTN) Value.Value.u64;\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[0].Value.u64;\r
 \r
   //\r
   // String[0] - sub-string\r
@@ -1047,17 +1706,13 @@ 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
+    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
-    if (Value.Type != EFI_IFR_TYPE_STRING) {\r
-      Status = EFI_UNSUPPORTED;\r
-      goto Done;\r
-    }\r
-\r
-    String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
+    String[Index] = GetToken (Value[Index + 1].Value.string, FormSet->HiiHandle);\r
     if (String[Index] == NULL) {\r
       Status = EFI_NOT_FOUND;\r
       goto Done;\r
@@ -1108,41 +1763,49 @@ 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
-  UINT8          *Buffer;\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
-  if (Value.Type != EFI_IFR_TYPE_STRING && Value.Type != EFI_IFR_TYPE_BUFFER) {\r
-    return EFI_UNSUPPORTED;\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
-    String = GetToken (Value.Value.string, FormSet->HiiHandle);\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
+  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
@@ -1161,23 +1824,25 @@ IfrMid (
 \r
     FreePool (String);\r
   } else {\r
-    Buffer    = Value.Buffer;\r
-    BufferLen = Value.BufferLen;\r
-    \r
+    BufferLen = GetLengthForValue (&Value[2]);\r
+    Buffer = GetBufferForValue (&Value[2]);\r
+\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->BufferLen = (UINT16)((BufferLen - Base) < Length ? (BufferLen - Base) : Length);\r
       Result->Buffer = AllocateZeroPool (Result->BufferLen);\r
       ASSERT (Result->Buffer != NULL);\r
-      CopyMem (Result->Buffer, &Value.Buffer[Base], Result->BufferLen);\r
+      CopyMem (Result->Buffer, &Buffer[Base], Result->BufferLen);\r
     }\r
 \r
-    FreePool (Value.Buffer);\r
+    if (Value[2].Type == EFI_IFR_TYPE_BUFFER) {\r
+      FreePool (Value[2].Buffer);\r
+    }\r
   }\r
-  \r
+\r
   return Status;\r
 }\r
 \r
@@ -1199,7 +1864,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
@@ -1207,14 +1872,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
-  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
-  Count = (UINTN) Value.Value.u64;\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[0].Value.u64;\r
 \r
   //\r
   // String[0] - Delimiter\r
@@ -1223,17 +1902,13 @@ 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
+    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
-    if (Value.Type != EFI_IFR_TYPE_STRING) {\r
-      Status = EFI_UNSUPPORTED;\r
-      goto Done;\r
-    }\r
-\r
-    String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
+    String[Index] = GetToken (Value[Index + 1].Value.string, FormSet->HiiHandle);\r
     if (String[Index] == NULL) {\r
       Status = EFI_NOT_FOUND;\r
       goto Done;\r
@@ -1304,7 +1979,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
@@ -1312,14 +1987,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
-  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
-  Base = (UINTN) Value.Value.u64;\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[0].Value.u64;\r
 \r
   //\r
   // String[0] - Charset\r
@@ -1328,17 +2017,13 @@ 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
+    String[Index] = GetToken (Value[Index + 1].Value.string, FormSet->HiiHandle);\r
     if (String [Index] == NULL) {\r
       Status = EFI_NOT_FOUND;\r
       goto Done;\r
@@ -1346,7 +2031,8 @@ IfrSpan (
   }\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
@@ -1439,47 +2125,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 compare on two values.\r
-  @retval 0                      Two operators equal.\r
-  @return Positive value if Value1 is greater than Value2.\r
-  @retval Negative value if Value1 is less than Value2.\r
+  @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
-    if (Value1->Type != EFI_IFR_TYPE_BUFFER && Value2->Type != EFI_IFR_TYPE_BUFFER) {\r
-      return EFI_INVALID_PARAMETER;\r
-    }\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
@@ -1488,7 +2216,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
@@ -1496,56 +2225,61 @@ 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
       FreePool (Str1);\r
-      return EFI_INVALID_PARAMETER;\r
+      return EFI_NOT_FOUND;\r
     }\r
 \r
-    Result = StrCmp (Str1, Str2);\r
+    *Result = StrCmp (Str1, Str2);\r
 \r
     FreePool (Str1);\r
     FreePool (Str2);\r
 \r
-    return Result;\r
+    return EFI_SUCCESS;\r
   }\r
 \r
-  if (Value1->Type == EFI_IFR_TYPE_BUFFER || Value2->Type == EFI_IFR_TYPE_BUFFER ) {\r
-    if (Value1->Type != Value2->Type) {\r
-      //\r
-      // Both Operator should be type of Buffer.\r
-      //\r
-      return EFI_INVALID_PARAMETER;\r
-    }\r
-    Len = Value1->BufferLen > Value2->BufferLen ? Value2->BufferLen : Value1->BufferLen;\r
-    Result = CompareMem (Value1->Buffer, Value2->Buffer, Len);\r
-    if ((Result == 0) && (Value1->BufferLen != Value2->BufferLen))\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 = Value1->BufferLen > Value2->BufferLen ? 1 : -1;\r
+      *Result = Buf1Len > Buf2Len ? 1 : -1;\r
     }\r
-    return Result;\r
-  }  \r
+    return EFI_SUCCESS;\r
+  }\r
 \r
   //\r
-  // Take remain types(integer, boolean, date/time) as integer\r
+  // Take types(integer, boolean) as integer\r
   //\r
-  Temp64 = (INT64) (Value1->Value.u64 - Value2->Value.u64);\r
-  if (Temp64 > 0) {\r
-    Result = 1;\r
-  } else if (Temp64 < 0) {\r
-    Result = -1;\r
-  } else {\r
-    Result = 0;\r
+  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 Result;\r
+  return EFI_UNSUPPORTED;\r
 }\r
 \r
 /**\r
@@ -1594,7 +2328,7 @@ CheckUserPrivilege (
   /// Enumerate all user information of the current user profile\r
   /// to look for any EFI_USER_INFO_ACCESS_SETUP record.\r
   ///\r
-  \r
+\r
   for (UserInfoHandle = NULL;;) {\r
     Status = mUserManager->GetNextInfo (mUserManager, UserProfileHandle, &UserInfoHandle);\r
     if (EFI_ERROR (Status)) {\r
@@ -1631,24 +2365,136 @@ CheckUserPrivilege (
         /// 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
+        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
+  //\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
+    Question = IdToQuestion2 (Form, QuestionId);\r
+    if (Question != NULL) {\r
+      break;\r
     }\r
 \r
-    FreePool (UserInfo);\r
+    Link = GetNextNode (&FormSet->FormListHead, Link);\r
+    Form = NULL;\r
   }\r
-  return FALSE;\r
+  ASSERT (Form != NULL);\r
+\r
+  //\r
+  // Get the question value.\r
+  //\r
+  Status = GetQuestionValue(FormSet, Form, Question, GetSetValueWithEditBuffer);\r
+  if (EFI_ERROR (Status)) {\r
+    GetTheVal = FALSE;\r
+    goto Done;\r
+  }\r
+\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
@@ -1699,6 +2545,10 @@ EvaluateExpression (
   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
   // Save current stack offset.\r
@@ -1729,13 +2579,18 @@ EvaluateExpression (
     case EFI_IFR_EQ_ID_VAL_OP:\r
       Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
       if (Question == NULL) {\r
-        Status = EFI_NOT_FOUND;\r
-        goto Done;\r
+        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
-        Status = EFI_INVALID_PARAMETER;\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
+      if (EFI_ERROR (Status)) {\r
         goto Done;\r
       }\r
       Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
@@ -1744,29 +2599,33 @@ EvaluateExpression (
     case EFI_IFR_EQ_ID_ID_OP:\r
       Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
       if (Question == NULL) {\r
-        Status = EFI_NOT_FOUND;\r
-        goto Done;\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        break;\r
       }\r
 \r
       Question2 = IdToQuestion (FormSet, Form, OpCode->QuestionId2);\r
       if (Question2 == NULL) {\r
-        Status = EFI_NOT_FOUND;\r
-        goto Done;\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
-        Status = 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
-        Status = EFI_NOT_FOUND;\r
-        goto Done;\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        break;\r
       }\r
 \r
       Value->Value.b = FALSE;\r
@@ -1823,7 +2682,7 @@ EvaluateExpression (
             //\r
             // Get value from string except for STRING value.\r
             //\r
-            Status = GetValueByName (OpCode->VarStorage, OpCode->ValueName, &StrPtr);\r
+            Status = GetValueByName (OpCode->VarStorage, OpCode->ValueName, &StrPtr, GetSetValueWithEditBuffer);\r
             if (!EFI_ERROR (Status)) {\r
               ASSERT (StrPtr != NULL);\r
               TempLength = StrLen (StrPtr);\r
@@ -1840,7 +2699,7 @@ EvaluateExpression (
                     TempBuffer [Index/2] = (UINT8) ((DigitUint8 << 4) + TempBuffer [Index/2]);\r
                   }\r
                 }\r
-              }                \r
+              }\r
             }\r
           }\r
           break;\r
@@ -1931,41 +2790,57 @@ EvaluateExpression (
       break;\r
 \r
     case EFI_IFR_QUESTION_REF3_OP:\r
-      if (OpCode->DevicePath == 0) {\r
-        //\r
-        // EFI_IFR_QUESTION_REF3\r
-        // Pop an expression from the expression stack\r
-        //\r
-        Status = PopExpression (Value);\r
-        if (EFI_ERROR (Status)) {\r
-          goto Done;\r
-        }\r
+      //\r
+      // EFI_IFR_QUESTION_REF3\r
+      // Pop an expression from the expression stack\r
+      //\r
+      Status = PopExpression (Value);\r
+      if (EFI_ERROR (Status)) {\r
+        goto Done;\r
+      }\r
 \r
-        //\r
-        // Validate the expression value\r
-        //\r
-        if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
-          Status = EFI_NOT_FOUND;\r
-          goto Done;\r
+      //\r
+      // 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
-          Status = EFI_NOT_FOUND;\r
-          goto Done;\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
@@ -1975,16 +2850,17 @@ EvaluateExpression (
       //\r
       RuleExpression = RuleIdToExpression (Form, OpCode->RuleId);\r
       if (RuleExpression == NULL) {\r
-        Status = EFI_NOT_FOUND;\r
-        goto Done;\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
-        goto Done;\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
@@ -2020,9 +2896,9 @@ EvaluateExpression (
       if (EFI_ERROR (Status)) {\r
         goto Done;\r
       }\r
-      if (Value->Type != EFI_IFR_TYPE_STRING && Value->Type != EFI_IFR_TYPE_BUFFER) {\r
-        Status = EFI_INVALID_PARAMETER;\r
-        goto Done;\r
+      if (Value->Type != EFI_IFR_TYPE_STRING && !IsTypeInBuffer (Value)) {\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        break;\r
       }\r
 \r
       if (Value->Type == EFI_IFR_TYPE_STRING) {\r
@@ -2037,7 +2913,7 @@ EvaluateExpression (
         FreePool (StrPtr);\r
       } else {\r
         Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
-        Value->Value.u64 = Value->BufferLen;\r
+        Value->Value.u64 = GetLengthForValue(Value);\r
         FreePool (Value->Buffer);\r
       }\r
       break;\r
@@ -2048,8 +2924,8 @@ EvaluateExpression (
         goto Done;\r
       }\r
       if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {\r
-        Status = EFI_INVALID_PARAMETER;\r
-        goto Done;\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        break;\r
       }\r
       Value->Value.b = (BOOLEAN) (!Value->Value.b);\r
       break;\r
@@ -2067,14 +2943,14 @@ EvaluateExpression (
       // Validate the expression value\r
       //\r
       if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
-        Status = EFI_NOT_FOUND;\r
-        goto Done;\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        break;\r
       }\r
 \r
       Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
       if (Question == NULL) {\r
-        Status = EFI_NOT_FOUND;\r
-        goto Done;\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        break;\r
       }\r
 \r
       Value = &Question->HiiValue;\r
@@ -2093,8 +2969,8 @@ EvaluateExpression (
       // Validate the expression value\r
       //\r
       if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
-        Status = EFI_NOT_FOUND;\r
-        goto Done;\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        break;\r
       }\r
 \r
       Value->Type = EFI_IFR_TYPE_STRING;\r
@@ -2128,40 +3004,39 @@ 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 != 0);\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. Otherwise, push Undefined. \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
           Status = EFI_INVALID_PARAMETER;\r
           goto Done;\r
         }\r
-        \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
-          Status = EFI_INVALID_PARAMETER;\r
-          FreePool (StrPtr);\r
-          goto Done;\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
         }\r
         FreePool (StrPtr);\r
-        Value->Type = EFI_IFR_TYPE_BOOLEAN;\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
+        // 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
+          if (Value->Buffer[Index] != 0) {\r
             break;\r
           }\r
         }\r
@@ -2197,8 +3072,8 @@ EvaluateExpression (
       }\r
 \r
       if (Value->Type != EFI_IFR_TYPE_STRING) {\r
-        Status = EFI_UNSUPPORTED;\r
-        goto Done;\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        break;\r
       }\r
 \r
       StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
@@ -2225,12 +3100,12 @@ EvaluateExpression (
         goto Done;\r
       }\r
       if (Value->Type > EFI_IFR_TYPE_DATE) {\r
-        Status = EFI_INVALID_PARAMETER;\r
-        goto Done;\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
@@ -2256,16 +3131,23 @@ EvaluateExpression (
         case EFI_HII_VARSTORE_NAME_VALUE:\r
           if (OpCode->ValueType != EFI_IFR_TYPE_STRING) {\r
             NameValue = AllocateZeroPool ((OpCode->ValueWidth * 2 + 1) * sizeof (CHAR16));\r
-            ASSERT (Value != NULL);\r
+            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
-              StrPtr += UnicodeValueToString (StrPtr, PREFIX_ZERO | RADIX_HEX, *TempBuffer, 2);\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, TRUE);\r
+            Status = SetValueByName (OpCode->VarStorage, OpCode->ValueName, NameValue, GetSetValueWithEditBuffer, NULL);\r
             FreePool (NameValue);\r
             if (!EFI_ERROR (Status)) {\r
               Data1.Value.b = TRUE;\r
@@ -2290,7 +3172,6 @@ EvaluateExpression (
           //\r
           Status = EFI_UNSUPPORTED;\r
           goto Done;\r
-          break;\r
         }\r
       } else {\r
         //\r
@@ -2370,10 +3251,6 @@ EvaluateExpression (
       if (EFI_ERROR (Status)) {\r
         goto Done;\r
       }\r
-      if (Data2.Type > EFI_IFR_TYPE_DATE) {\r
-        Status = EFI_INVALID_PARAMETER;\r
-        goto Done;\r
-      }\r
 \r
       //\r
       // Pop another expression from the expression stack\r
@@ -2382,49 +3259,56 @@ EvaluateExpression (
       if (EFI_ERROR (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
-        Status = EFI_INVALID_PARAMETER;\r
-        goto Done;\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
@@ -2441,10 +3325,6 @@ EvaluateExpression (
       if (EFI_ERROR (Status)) {\r
         goto Done;\r
       }\r
-      if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {\r
-        Status = EFI_INVALID_PARAMETER;\r
-        goto Done;\r
-      }\r
 \r
       //\r
       // Pop another expression from the expression stack\r
@@ -2453,9 +3333,15 @@ EvaluateExpression (
       if (EFI_ERROR (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
-        Status = EFI_INVALID_PARAMETER;\r
-        goto Done;\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        break;\r
       }\r
 \r
       if (OpCode->Operand == EFI_IFR_AND_OP) {\r
@@ -2478,12 +3364,6 @@ EvaluateExpression (
       if (EFI_ERROR (Status)) {\r
         goto Done;\r
       }\r
-      if (Data2.Type > EFI_IFR_TYPE_BOOLEAN && \r
-          Data2.Type != EFI_IFR_TYPE_STRING && \r
-          Data2.Type != EFI_IFR_TYPE_BUFFER) {\r
-        Status = EFI_INVALID_PARAMETER;\r
-        goto Done;\r
-      }\r
 \r
       //\r
       // Pop another expression from the expression stack\r
@@ -2493,14 +3373,35 @@ EvaluateExpression (
         goto Done;\r
       }\r
 \r
-      Result = CompareHiiValue (&Data1, &Data2, FormSet->HiiHandle);\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
+      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 (Result == EFI_INVALID_PARAMETER) {\r
-        Status = EFI_INVALID_PARAMETER;\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
@@ -2539,10 +3440,14 @@ EvaluateExpression (
       if (EFI_ERROR (Status)) {\r
         goto Done;\r
       }\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
@@ -2575,8 +3480,8 @@ EvaluateExpression (
         goto Done;\r
       }\r
       if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
-        Status = EFI_INVALID_PARAMETER;\r
-        goto Done;\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        break;\r
       }\r
 \r
       if (Data1.Value.b) {\r
@@ -2633,7 +3538,7 @@ EvaluateExpression (
         //\r
         // Compare the expression value with current value\r
         //\r
-        if (CompareHiiValue (&Data1, &SubExpression->Result, NULL) == 0) {\r
+        if ((CompareHiiValue (&Data1, &SubExpression->Result, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {\r
           //\r
           // Try get the map value.\r
           //\r
@@ -2676,7 +3581,7 @@ EvaluateExpression (
     default:\r
       break;\r
     }\r
-    if (EFI_ERROR (Status)) {\r
+    if (EFI_ERROR (Status) || Value->Type == EFI_IFR_TYPE_UNDEFINED) {\r
       goto Done;\r
     }\r
 \r
@@ -2710,3 +3615,117 @@ Done:
 \r
   return Status;\r
 }\r
+\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