]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/SetupBrowserDxe/Expression.c
Add the missing check for NULL pointer before use it.
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Expression.c
index eb109f4dfc02c3c726db9b1f073686018b3a4414..45ec96edf1bf736bc84eb8fb45975eeeb3eac384 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
 Utility functions for expression evaluation.\r
 \r
-Copyright (c) 2007 - 2008, Intel Corporation\r
+Copyright (c) 2007 - 2010, Intel Corporation\r
 All rights reserved. This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -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,21 @@ 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
 //\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 +87,7 @@ GrowStack (
     //\r
     // Free The Old Stack\r
     //\r
-    gBS->FreePool (*Stack);\r
+    FreePool (*Stack);\r
   }\r
 \r
   //\r
@@ -141,10 +149,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 +159,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 +180,144 @@ 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
+}\r
+\r
+\r
+/**\r
+  Push current expression onto the Stack\r
+\r
+  @param  Pointer                Pointer to current expression.\r
+\r
+  @retval EFI_SUCCESS            The value was pushed onto the stack.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushCurrentExpression (\r
+  IN VOID  *Pointer\r
+  )\r
+{\r
+  EFI_HII_VALUE  Data;\r
+\r
+  Data.Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+  Data.Value.u64 = (UINT64) (UINTN) Pointer;\r
+\r
+  return PushStack (\r
+    &mCurrentExpressionStack,\r
+    &mCurrentExpressionPointer,\r
+    &mCurrentExpressionEnd,\r
+    &Data\r
+    );\r
+}\r
+\r
+\r
+/**\r
+  Pop current expression from the Stack\r
+\r
+  @param  Pointer                Pointer to current expression to be pop.\r
+\r
+  @retval EFI_SUCCESS            The value was pushed onto the stack.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopCurrentExpression (\r
+  OUT VOID    **Pointer\r
+  )\r
+{\r
+  EFI_STATUS     Status;\r
+  EFI_HII_VALUE  Data;\r
+\r
+  Status = PopStack (\r
+    mCurrentExpressionStack,\r
+    &mCurrentExpressionPointer,\r
+    &Data\r
+    );\r
+\r
+  *Pointer = (VOID *) (UINTN) Data.Value.u64;\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Reset stack pointer to begin of the stack.\r
+\r
+**/\r
+VOID\r
+ResetMapExpressionListStack (\r
+  VOID\r
+  )\r
+{\r
+  mMapExpressionListPointer = mMapExpressionListStack;\r
+}\r
+\r
+\r
+/**\r
+  Push the list of map expression onto the Stack\r
+\r
+  @param  Pointer                Pointer to the list of map expression to be pushed.\r
+\r
+  @retval EFI_SUCCESS            The value was pushed onto the stack.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushMapExpressionList (\r
+  IN VOID  *Pointer\r
+  )\r
+{\r
+  EFI_HII_VALUE  Data;\r
+\r
+  Data.Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+  Data.Value.u64 = (UINT64) (UINTN) Pointer;\r
+\r
+  return PushStack (\r
+    &mMapExpressionListStack,\r
+    &mMapExpressionListPointer,\r
+    &mMapExpressionListEnd,\r
+    &Data\r
+    );\r
+}\r
+\r
+\r
+/**\r
+  Pop the list of map expression from the Stack\r
+\r
+  @param  Pointer                Pointer to the list of map expression to be pop.\r
+\r
+  @retval EFI_SUCCESS            The value was pushed onto the stack.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopMapExpressionList (\r
+  OUT VOID    **Pointer\r
+  )\r
+{\r
+  EFI_STATUS     Status;\r
+  EFI_HII_VALUE  Data;\r
+\r
+  Status = PopStack (\r
+    mMapExpressionListStack,\r
+    &mMapExpressionListPointer,\r
+    &Data\r
+    );\r
+\r
+  *Pointer = (VOID *) (UINTN) Data.Value.u64;\r
+\r
+  return Status;\r
+}\r
+\r
 /**\r
   Reset stack pointer to begin of the stack.\r
 \r
@@ -236,9 +379,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 +390,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 +429,40 @@ 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
+  )\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
@@ -512,7 +668,7 @@ InitializeUnicodeCollationProtocol (
 **/\r
 VOID\r
 IfrStrToUpper (\r
-  CHAR16                   *String\r
+  IN CHAR16                   *String\r
   )\r
 {\r
   while (*String != 0) {\r
@@ -619,7 +775,6 @@ 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
@@ -643,14 +798,14 @@ 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
-    gBS->FreePool (String);\r
+    FreePool (String);\r
   } else {\r
     CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));\r
   }\r
@@ -704,7 +859,7 @@ IfrCatenate (
     }\r
 \r
     String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
-    if (String== NULL) {\r
+    if (String[Index] == NULL) {\r
       Status = EFI_NOT_FOUND;\r
       goto Done;\r
     }\r
@@ -725,7 +880,7 @@ Done:
   }\r
   if (String[1] != NULL) {\r
     FreePool (String[1]);\r
-  }  \r
+  }\r
   if (StringPtr != NULL) {\r
     FreePool (StringPtr);\r
   }\r
@@ -774,7 +929,7 @@ IfrMatch (
     }\r
 \r
     String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
-    if (String== NULL) {\r
+    if (String [Index] == NULL) {\r
       Status = EFI_NOT_FOUND;\r
       goto Done;\r
     }\r
@@ -789,7 +944,7 @@ Done:
   }\r
   if (String[1] != NULL) {\r
     FreePool (String[1]);\r
-  }  \r
+  }\r
 \r
   return Status;\r
 }\r
@@ -851,7 +1006,7 @@ IfrFind (
     }\r
 \r
     String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
-    if (String== NULL) {\r
+    if (String[Index] == NULL) {\r
       Status = EFI_NOT_FOUND;\r
       goto Done;\r
     }\r
@@ -878,7 +1033,7 @@ Done:
   }\r
   if (String[1] != NULL) {\r
     FreePool (String[1]);\r
-  }  \r
+  }\r
 \r
   return Status;\r
 }\r
@@ -949,7 +1104,7 @@ IfrMid (
   Result->Type = EFI_IFR_TYPE_STRING;\r
   Result->Value.string = NewString (SubString, FormSet->HiiHandle);\r
 \r
-  gBS->FreePool (String);\r
+  FreePool (String);\r
 \r
   return Status;\r
 }\r
@@ -1007,7 +1162,7 @@ IfrToken (
     }\r
 \r
     String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
-    if (String== NULL) {\r
+    if (String[Index] == NULL) {\r
       Status = EFI_NOT_FOUND;\r
       goto Done;\r
     }\r
@@ -1052,7 +1207,7 @@ Done:
   }\r
   if (String[1] != NULL) {\r
     FreePool (String[1]);\r
-  }  \r
+  }\r
 \r
   return Status;\r
 }\r
@@ -1112,7 +1267,7 @@ IfrSpan (
     }\r
 \r
     String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
-    if (String== NULL) {\r
+    if (String [Index] == NULL) {\r
       Status = EFI_NOT_FOUND;\r
       goto Done;\r
     }\r
@@ -1160,7 +1315,7 @@ Done:
   }\r
   if (String[1] != NULL) {\r
     FreePool (String[1]);\r
-  }  \r
+  }\r
 \r
   return Status;\r
 }\r
@@ -1220,8 +1375,8 @@ ExtendValueToU64 (
   @param  Value2                 Expression value to compare on right-hand.\r
   @param  HiiHandle              Only required for string compare.\r
 \r
-  @retval EFI_INVALID_PARAMETER  Could not perform comparation on two values.\r
-  @retval 0                      Two operators equeal.\r
+  @retval EFI_INVALID_PARAMETER  Could not perform compare on two values.\r
+  @retval 0                      Two operators equal.\r
   @return Positive value if Value1 is greater than Value2.\r
   @retval Negative value if Value1 is less than Value2.\r
 \r
@@ -1271,14 +1426,14 @@ CompareHiiValue (
 \r
     Str2 = GetToken (Value2->Value.string, HiiHandle);\r
     if (Str2 == NULL) {\r
-      gBS->FreePool (Str1);\r
+      FreePool (Str1);\r
       return EFI_INVALID_PARAMETER;\r
     }\r
 \r
     Result = StrCmp (Str1, Str2);\r
 \r
-    gBS->FreePool (Str1);\r
-    gBS->FreePool (Str2);\r
+    FreePool (Str1);\r
+    FreePool (Str2);\r
 \r
     return Result;\r
   }\r
@@ -1298,9 +1453,113 @@ CompareHiiValue (
   return Result;\r
 }\r
 \r
+/**\r
+  Check if current user has the privilege specified by the permissions GUID.\r
+\r
+  @param[in] Guid  A GUID specifying setup access permissions.\r
+\r
+  @retval TRUE     Current user has the privilege.\r
+  @retval FALSE    Current user does not have the privilege.\r
+**/\r
+BOOLEAN\r
+CheckUserPrivilege (\r
+  IN EFI_GUID *Guid\r
+  )\r
+{\r
+  EFI_STATUS                   Status;\r
+  EFI_USER_PROFILE_HANDLE      UserProfileHandle;\r
+  EFI_USER_INFO_HANDLE         UserInfoHandle;\r
+  EFI_USER_INFO                *UserInfo;\r
+  EFI_GUID                     *UserPermissionsGuid;\r
+  UINTN                        UserInfoSize;\r
+  UINTN                        AccessControlDataSize;\r
+  EFI_USER_INFO_ACCESS_CONTROL *AccessControl;\r
+  UINTN                        RemainSize;\r
+\r
+  if (mUserManager == NULL) {\r
+    Status = gBS->LocateProtocol (\r
+                    &gEfiUserManagerProtocolGuid,\r
+                    NULL,\r
+                    (VOID **) &mUserManager\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      ///\r
+      /// If the system does not support user management, then it is assumed that\r
+      /// all users have admin privilege and evaluation of each EFI_IFR_SECURITY\r
+      /// op-code is always TRUE.\r
+      ///\r
+      return TRUE;\r
+    }\r
+  }\r
+\r
+  Status = mUserManager->Current (mUserManager, &UserProfileHandle);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  ///\r
+  /// Enumerate all user information of the current user profile\r
+  /// to look for any EFI_USER_INFO_ACCESS_SETUP record.\r
+  ///\r
+  \r
+  for (UserInfoHandle = NULL;;) {\r
+    Status = mUserManager->GetNextInfo (mUserManager, UserProfileHandle, &UserInfoHandle);\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+\r
+    UserInfoSize = 0;\r
+    Status = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, NULL, &UserInfoSize);\r
+    if (Status != EFI_BUFFER_TOO_SMALL) {\r
+      continue;\r
+    }\r
+\r
+    UserInfo = (EFI_USER_INFO *) AllocatePool (UserInfoSize);\r
+    if (UserInfo == NULL) {\r
+      break;\r
+    }\r
+\r
+    Status = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, UserInfo, &UserInfoSize);\r
+    if (EFI_ERROR (Status) ||\r
+        UserInfo->InfoType != EFI_USER_INFO_ACCESS_POLICY_RECORD ||\r
+        UserInfo->InfoSize <= sizeof (EFI_USER_INFO)) {\r
+      FreePool (UserInfo);\r
+      continue;\r
+    }\r
+\r
+    RemainSize = UserInfo->InfoSize - sizeof (EFI_USER_INFO);\r
+    AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)(UserInfo + 1);\r
+    while (RemainSize >= sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {\r
+      if (RemainSize < AccessControl->Size || AccessControl->Size <= sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {\r
+        break;\r
+      }\r
+      if (AccessControl->Type == EFI_USER_INFO_ACCESS_SETUP) {\r
+        ///\r
+        /// Check if current user has the privilege specified by the permissions GUID.\r
+        ///\r
+\r
+        UserPermissionsGuid = (EFI_GUID *)(AccessControl + 1);\r
+        AccessControlDataSize = AccessControl->Size - sizeof (EFI_USER_INFO_ACCESS_CONTROL);\r
+        while (AccessControlDataSize >= sizeof (EFI_GUID)) {\r
+          if (CompareGuid (Guid, UserPermissionsGuid)) {\r
+            FreePool (UserInfo);\r
+            return TRUE;\r
+          }\r
+          UserPermissionsGuid++;\r
+          AccessControlDataSize -= sizeof (EFI_GUID);\r
+        }\r
+      }\r
+      RemainSize -= AccessControl->Size;\r
+      AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)((UINT8 *)AccessControl + AccessControl->Size);\r
+    }\r
+\r
+    FreePool (UserInfo);\r
+  }\r
+  return FALSE;\r
+}\r
 \r
 /**\r
-  Evaluate the result of a HII expression\r
+  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
@@ -1335,13 +1594,23 @@ 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
 \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
@@ -1365,12 +1634,14 @@ 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
+        Status = EFI_NOT_FOUND;\r
+        goto Done;\r
       }\r
 \r
       Result = CompareHiiValue (&Question->HiiValue, &OpCode->Value, NULL);\r
       if (Result == EFI_INVALID_PARAMETER) {\r
-        return EFI_INVALID_PARAMETER;\r
+        Status = EFI_INVALID_PARAMETER;\r
+        goto Done;\r
       }\r
       Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
       break;\r
@@ -1378,17 +1649,20 @@ 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
+        Status = EFI_NOT_FOUND;\r
+        goto Done;\r
       }\r
 \r
       Question2 = IdToQuestion (FormSet, Form, OpCode->QuestionId2);\r
       if (Question2 == NULL) {\r
-        return EFI_NOT_FOUND;\r
+        Status = EFI_NOT_FOUND;\r
+        goto Done;\r
       }\r
 \r
       Result = CompareHiiValue (&Question->HiiValue, &Question2->HiiValue, FormSet->HiiHandle);\r
       if (Result == EFI_INVALID_PARAMETER) {\r
-        return EFI_INVALID_PARAMETER;\r
+        Status = EFI_INVALID_PARAMETER;\r
+        goto Done;\r
       }\r
       Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
       break;\r
@@ -1396,7 +1670,8 @@ EvaluateExpression (
     case EFI_IFR_EQ_ID_LIST_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->Value.b = FALSE;\r
@@ -1411,7 +1686,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
@@ -1421,12 +1696,143 @@ 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_SECURITY_OP:\r
+      Value->Value.b = CheckUserPrivilege (&OpCode->Guid);\r
+      break;\r
+\r
+    case EFI_IFR_GET_OP:\r
+      //\r
+      // Get Value from VarStore buffer, EFI VarStore, Name/Value VarStore.\r
+      //\r
+      Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+      Value->Value.u8 = 0;\r
+      if (OpCode->VarStorage != NULL) {\r
+        switch (OpCode->VarStorage->Type) {\r
+        case EFI_HII_VARSTORE_BUFFER:\r
+          //\r
+          // Get value from Edit Buffer\r
+          //\r
+          Value->Type = OpCode->ValueType;\r
+          CopyMem (&Value->Value, OpCode->VarStorage->EditBuffer + OpCode->VarStoreInfo.VarOffset, OpCode->ValueWidth);\r
+          break;\r
+        case EFI_HII_VARSTORE_NAME_VALUE:\r
+          if (OpCode->ValueType != EFI_IFR_TYPE_STRING) {\r
+            //\r
+            // Get value from string except for STRING value.\r
+            //\r
+            Status = GetValueByName (OpCode->VarStorage, OpCode->ValueName, &StrPtr);\r
+            if (!EFI_ERROR (Status)) {\r
+              ASSERT (StrPtr != NULL);\r
+              TempLength = StrLen (StrPtr);\r
+              if (OpCode->ValueWidth >= ((TempLength + 1) / 2)) {\r
+                Value->Type = OpCode->ValueType;\r
+                TempBuffer = (UINT8 *) &Value->Value;\r
+                ZeroMem (TempStr, sizeof (TempStr));\r
+                for (Index = 0; Index < TempLength; Index ++) {\r
+                  TempStr[0] = StrPtr[TempLength - Index - 1];\r
+                  DigitUint8 = (UINT8) StrHexToUint64 (TempStr);\r
+                  if ((Index & 1) == 0) {\r
+                    TempBuffer [Index/2] = DigitUint8;\r
+                  } else {\r
+                    TempBuffer [Index/2] = (UINT8) ((DigitUint8 << 4) + TempBuffer [Index/2]);\r
+                  }\r
+                }\r
+              }                \r
+            }\r
+          }\r
+          break;\r
+        case EFI_HII_VARSTORE_EFI_VARIABLE:\r
+          //\r
+          // Get value from variable.\r
+          //\r
+          TempLength = OpCode->ValueWidth;\r
+          Value->Type = OpCode->ValueType;\r
+          Status = gRT->GetVariable (\r
+                          OpCode->ValueName,\r
+                          &OpCode->VarStorage->Guid,\r
+                          NULL,\r
+                          &TempLength,\r
+                          &Value->Value\r
+                          );\r
+          if (EFI_ERROR (Status)) {\r
+            Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+            Value->Value.u8 = 0;\r
+          }\r
+        default:\r
+          //\r
+          // Not recognize storage.\r
+          //\r
+          Status = EFI_UNSUPPORTED;\r
+          goto Done;\r
+        }\r
+      } else {\r
+        //\r
+        // For Time/Date Data\r
+        //\r
+        if (OpCode->ValueType != EFI_IFR_TYPE_DATE && OpCode->ValueType != EFI_IFR_TYPE_TIME) {\r
+          //\r
+          // Only support Data/Time data when storage doesn't exist.\r
+          //\r
+          Status = EFI_UNSUPPORTED;\r
+          goto Done;\r
+        }\r
+        Status = gRT->GetTime (&EfiTime, NULL);\r
+        if (!EFI_ERROR (Status)) {\r
+          if (OpCode->ValueType == EFI_IFR_TYPE_DATE) {\r
+            switch (OpCode->VarStoreInfo.VarOffset) {\r
+            case 0x00:\r
+              Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;\r
+              Value->Value.u16 = EfiTime.Year;\r
+              break;\r
+            case 0x02:\r
+              Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
+              Value->Value.u8 = EfiTime.Month;\r
+              break;\r
+            case 0x03:\r
+              Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
+              Value->Value.u8 = EfiTime.Day;\r
+              break;\r
+            default:\r
+              //\r
+              // Invalid Date field.\r
+              //\r
+              Status = EFI_INVALID_PARAMETER;\r
+              goto Done;\r
+            }\r
+          } else {\r
+            switch (OpCode->VarStoreInfo.VarOffset) {\r
+            case 0x00:\r
+              Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
+              Value->Value.u8 = EfiTime.Hour;\r
+              break;\r
+            case 0x01:\r
+              Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
+              Value->Value.u8 = EfiTime.Minute;\r
+              break;\r
+            case 0x02:\r
+              Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
+              Value->Value.u8 = EfiTime.Second;\r
+              break;\r
+            default:\r
+              //\r
+              // Invalid Time field.\r
+              //\r
+              Status = EFI_INVALID_PARAMETER;\r
+              goto Done;\r
+            }\r
+          }\r
+        }\r
+      }\r
+\r
+      break;\r
+\r
     case EFI_IFR_QUESTION_REF3_OP:\r
       if (OpCode->DevicePath == 0) {\r
         //\r
@@ -1435,19 +1841,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
+          Status = EFI_NOT_FOUND;\r
+          goto Done;\r
         }\r
 \r
         Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
         if (Question == NULL) {\r
-          return EFI_NOT_FOUND;\r
+          Status = EFI_NOT_FOUND;\r
+          goto Done;\r
         }\r
 \r
         //\r
@@ -1470,7 +1878,8 @@ EvaluateExpression (
       //\r
       RuleExpression = RuleIdToExpression (Form, OpCode->RuleId);\r
       if (RuleExpression == NULL) {\r
-        return EFI_NOT_FOUND;\r
+        Status = EFI_NOT_FOUND;\r
+        goto Done;\r
       }\r
 \r
       //\r
@@ -1478,7 +1887,7 @@ EvaluateExpression (
       //\r
       Status = EvaluateExpression (FormSet, Form, RuleExpression);\r
       if (EFI_ERROR (Status)) {\r
-        return Status;\r
+        goto Done;\r
       }\r
 \r
       Value = &RuleExpression->Result;\r
@@ -1512,29 +1921,32 @@ 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
+        Status = EFI_INVALID_PARAMETER;\r
+        goto Done;\r
       }\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
       Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
       Value->Value.u64 = StrLen (StrPtr);\r
-      gBS->FreePool (StrPtr);\r
+      FreePool (StrPtr);\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
+        Status = EFI_INVALID_PARAMETER;\r
+        goto Done;\r
       }\r
       Value->Value.b = (BOOLEAN) (!Value->Value.b);\r
       break;\r
@@ -1545,19 +1957,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
+        Status = EFI_NOT_FOUND;\r
+        goto Done;\r
       }\r
 \r
       Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
       if (Question == NULL) {\r
-        return EFI_NOT_FOUND;\r
+        Status = EFI_NOT_FOUND;\r
+        goto Done;\r
       }\r
 \r
       Value = &Question->HiiValue;\r
@@ -1569,14 +1983,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
+        Status = EFI_NOT_FOUND;\r
+        goto Done;\r
       }\r
 \r
       Value->Type = EFI_IFR_TYPE_STRING;\r
@@ -1589,7 +2004,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
@@ -1599,7 +2014,7 @@ EvaluateExpression (
       //\r
       Status = PopExpression (Value);\r
       if (EFI_ERROR (Status)) {\r
-        return Status;\r
+        goto Done;\r
       }\r
 \r
       //\r
@@ -1610,7 +2025,7 @@ 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) (Value->Value.u64 != 0);\r
 \r
         Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
       } else if (Value->Type == EFI_IFR_TYPE_STRING) {\r
@@ -1621,7 +2036,8 @@ EvaluateExpression (
         //\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
@@ -1629,7 +2045,7 @@ EvaluateExpression (
         } else {\r
           Value->Value.b = FALSE;\r
         }\r
-        gBS->FreePool (StrPtr);\r
+        FreePool (StrPtr);\r
         Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
       }\r
       break;\r
@@ -1646,21 +2062,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
+        Status = EFI_UNSUPPORTED;\r
+        goto Done;\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
@@ -1669,7 +2087,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
@@ -1678,16 +2096,134 @@ 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
+        Status = EFI_INVALID_PARAMETER;\r
+        goto Done;\r
       }\r
 \r
       Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
       Value->Value.u64 = ~Value->Value.u64;\r
       break;\r
 \r
+    case EFI_IFR_SET_OP:\r
+      //\r
+      // Pop an expression from the expression stack\r
+      //\r
+      Status = PopExpression (Value);\r
+      if (EFI_ERROR (Status)) {\r
+        goto Done;\r
+      }\r
+      Data1.Type = EFI_IFR_TYPE_BOOLEAN;\r
+      Data1.Value.b = FALSE;\r
+      //\r
+      // Set value to var storage buffer\r
+      //\r
+      if (OpCode->VarStorage != NULL) {\r
+        switch (OpCode->VarStorage->Type) {\r
+        case EFI_HII_VARSTORE_BUFFER:\r
+          CopyMem (OpCode->VarStorage->EditBuffer + OpCode->VarStoreInfo.VarOffset, &Value->Value, OpCode->ValueWidth);\r
+          Data1.Value.b = TRUE;\r
+          break;\r
+        case EFI_HII_VARSTORE_NAME_VALUE:\r
+          if (OpCode->ValueType != EFI_IFR_TYPE_STRING) {\r
+            NameValue = AllocateZeroPool ((OpCode->ValueWidth * 2 + 1) * sizeof (CHAR16));\r
+            ASSERT (Value != NULL);\r
+            //\r
+            // Convert Buffer to Hex String\r
+            //\r
+            TempBuffer = (UINT8 *) &Value->Value + OpCode->ValueWidth - 1;\r
+            StrPtr = NameValue;\r
+            for (Index = 0; Index < OpCode->ValueWidth; Index ++, TempBuffer --) {\r
+              StrPtr += UnicodeValueToString (StrPtr, PREFIX_ZERO | RADIX_HEX, *TempBuffer, 2);\r
+            }\r
+            Status = SetValueByName (OpCode->VarStorage, OpCode->ValueName, NameValue);\r
+            FreePool (NameValue);\r
+            if (!EFI_ERROR (Status)) {\r
+              Data1.Value.b = TRUE;\r
+            }\r
+          }\r
+          break;\r
+        case EFI_HII_VARSTORE_EFI_VARIABLE:\r
+          Status = gRT->SetVariable (\r
+                          OpCode->ValueName,\r
+                          &OpCode->VarStorage->Guid,\r
+                          OpCode->VarStorage->Attributes,\r
+                          OpCode->ValueWidth,\r
+                          &Value->Value\r
+                          );\r
+          if (!EFI_ERROR (Status)) {\r
+            Data1.Value.b = TRUE;\r
+          }\r
+          break;\r
+        default:\r
+          //\r
+          // Not recognize storage.\r
+          //\r
+          Status = EFI_UNSUPPORTED;\r
+          goto Done;\r
+          break;\r
+        }\r
+      } else {\r
+        //\r
+        // For Time/Date Data\r
+        //\r
+        if (OpCode->ValueType != EFI_IFR_TYPE_DATE && OpCode->ValueType != EFI_IFR_TYPE_TIME) {\r
+          //\r
+          // Only support Data/Time data when storage doesn't exist.\r
+          //\r
+          Status = EFI_UNSUPPORTED;\r
+          goto Done;\r
+        }\r
+        Status = gRT->GetTime (&EfiTime, NULL);\r
+        if (!EFI_ERROR (Status)) {\r
+          if (OpCode->ValueType == EFI_IFR_TYPE_DATE) {\r
+            switch (OpCode->VarStoreInfo.VarOffset) {\r
+            case 0x00:\r
+              EfiTime.Year = Value->Value.u16;\r
+              break;\r
+            case 0x02:\r
+              EfiTime.Month = Value->Value.u8;\r
+              break;\r
+            case 0x03:\r
+              EfiTime.Day = Value->Value.u8;\r
+              break;\r
+            default:\r
+              //\r
+              // Invalid Date field.\r
+              //\r
+              Status = EFI_INVALID_PARAMETER;\r
+              goto Done;\r
+            }\r
+          } else {\r
+            switch (OpCode->VarStoreInfo.VarOffset) {\r
+            case 0x00:\r
+              EfiTime.Hour = Value->Value.u8;\r
+              break;\r
+            case 0x01:\r
+              EfiTime.Minute = Value->Value.u8;\r
+              break;\r
+            case 0x02:\r
+              EfiTime.Second = Value->Value.u8;\r
+              break;\r
+            default:\r
+              //\r
+              // Invalid Time field.\r
+              //\r
+              Status = EFI_INVALID_PARAMETER;\r
+              goto Done;\r
+            }\r
+          }\r
+          Status = gRT->SetTime (&EfiTime);\r
+          if (!EFI_ERROR (Status)) {\r
+            Data1.Value.b = TRUE;\r
+          }\r
+        }\r
+      }\r
+      Value = &Data1;\r
+      break;\r
+\r
     //\r
     // binary-op\r
     //\r
@@ -1705,10 +2241,11 @@ EvaluateExpression (
       //\r
       Status = PopExpression (&Data2);\r
       if (EFI_ERROR (Status)) {\r
-        return Status;\r
+        goto Done;\r
       }\r
       if (Data2.Type > EFI_IFR_TYPE_DATE) {\r
-        return EFI_INVALID_PARAMETER;\r
+        Status = EFI_INVALID_PARAMETER;\r
+        goto Done;\r
       }\r
 \r
       //\r
@@ -1716,10 +2253,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_DATE) {\r
-        return EFI_INVALID_PARAMETER;\r
+        Status = EFI_INVALID_PARAMETER;\r
+        goto Done;\r
       }\r
 \r
       Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
@@ -1774,10 +2312,11 @@ EvaluateExpression (
       //\r
       Status = PopExpression (&Data2);\r
       if (EFI_ERROR (Status)) {\r
-        return Status;\r
+        goto Done;\r
       }\r
       if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {\r
-        return EFI_INVALID_PARAMETER;\r
+        Status = EFI_INVALID_PARAMETER;\r
+        goto Done;\r
       }\r
 \r
       //\r
@@ -1785,10 +2324,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
+        Status = EFI_INVALID_PARAMETER;\r
+        goto Done;\r
       }\r
 \r
       if (OpCode->Operand == EFI_IFR_AND_OP) {\r
@@ -1809,10 +2349,11 @@ EvaluateExpression (
       //\r
       Status = PopExpression (&Data2);\r
       if (EFI_ERROR (Status)) {\r
-        return Status;\r
+        goto Done;\r
       }\r
       if (Data2.Type > EFI_IFR_TYPE_BOOLEAN && Data2.Type != EFI_IFR_TYPE_STRING) {\r
-        return EFI_INVALID_PARAMETER;\r
+        Status = EFI_INVALID_PARAMETER;\r
+        goto Done;\r
       }\r
 \r
       //\r
@@ -1820,12 +2361,13 @@ EvaluateExpression (
       //\r
       Status = PopExpression (&Data1);\r
       if (EFI_ERROR (Status)) {\r
-        return Status;\r
+        goto Done;\r
       }\r
 \r
       Result = CompareHiiValue (&Data1, &Data2, FormSet->HiiHandle);\r
       if (Result == EFI_INVALID_PARAMETER) {\r
-        return EFI_INVALID_PARAMETER;\r
+        Status = EFI_INVALID_PARAMETER;\r
+        goto Done;\r
       }\r
 \r
       switch (OpCode->Operand) {\r
@@ -1834,7 +2376,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
@@ -1875,7 +2417,7 @@ EvaluateExpression (
       //\r
       Status = PopExpression (&Data3);\r
       if (EFI_ERROR (Status)) {\r
-        return Status;\r
+        goto Done;\r
       }\r
 \r
       //\r
@@ -1883,7 +2425,7 @@ EvaluateExpression (
       //\r
       Status = PopExpression (&Data2);\r
       if (EFI_ERROR (Status)) {\r
-        return Status;\r
+        goto Done;\r
       }\r
 \r
       //\r
@@ -1891,10 +2433,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
+        Status = EFI_INVALID_PARAMETER;\r
+        goto Done;\r
       }\r
 \r
       if (Data1.Value.b) {\r
@@ -1920,16 +2463,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, NULL) == 0) {\r
+          //\r
+          // Try get the map value.\r
+          //\r
+          SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
+          if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
+            Status = EFI_INVALID_PARAMETER;\r
+            goto Done;\r
+          }\r
+          SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);\r
+          Status = EvaluateExpression (FormSet, Form, SubExpression);\r
+          if (EFI_ERROR (Status)) {\r
+            goto Done;\r
+          }\r
+          Value = &SubExpression->Result;\r
+          break;\r
+        }\r
+        //\r
+        // Skip the second expression on this pair.\r
+        //\r
+        SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
+        if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
+          Status = EFI_INVALID_PARAMETER;\r
+          goto Done;\r
+        }\r
+        //\r
+        // Goto the first expression on next pair.\r
+        //\r
+        SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
+      }\r
+\r
+      //\r
+      // No map value is found.\r
+      //\r
+      if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+        Value->Value.u8 = 0;\r
+      }\r
+      break;\r
+\r
     default:\r
       break;\r
     }\r
     if (EFI_ERROR (Status)) {\r
-      return Status;\r
+      goto Done;\r
     }\r
 \r
     Status = PushExpression (Value);\r
     if (EFI_ERROR (Status)) {\r
-      return Status;\r
+      goto Done;\r
     }\r
   }\r
 \r
@@ -1939,17 +2553,21 @@ 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
-  CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));\r
+Done:\r
+  RestoreExpressionEvaluationStackOffset (StackOffset);\r
+  if (!EFI_ERROR (Status)) {\r
+    CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));\r
+  }\r
 \r
-  return EFI_SUCCESS;\r
+  return Status;\r
 }\r