Enhance SetupBrowser to support new UEFI HiiFormMap feature
authorlgao4 <lgao4@6f19259b-4bc3-4df7-8a09-765794883524>
Thu, 25 Feb 2010 10:10:59 +0000 (10:10 +0000)
committerlgao4 <lgao4@6f19259b-4bc3-4df7-8a09-765794883524>
Thu, 25 Feb 2010 10:10:59 +0000 (10:10 +0000)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk@10069 6f19259b-4bc3-4df7-8a09-765794883524

edk2/MdeModulePkg/Library/UefiHiiLib/HiiLib.c
edk2/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
edk2/MdeModulePkg/Universal/SetupBrowserDxe/Expression.c
edk2/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c
edk2/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
edk2/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
edk2/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h
edk2/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
edk2/MdeModulePkg/Universal/SetupBrowserDxe/Ui.h
edk2/MdePkg/Include/Uefi/UefiInternalFormRepresentation.h

index 3d7a4e5..891f44e 100644 (file)
@@ -1229,6 +1229,7 @@ InternalHiiValidateCurrentSetting (
           }\r
           break;\r
         case EFI_IFR_FORM_OP:\r
+        case EFI_IFR_FORM_MAP_OP:\r
           //\r
           // Check the matched VarStoreId is found.\r
           //\r
@@ -3333,7 +3334,7 @@ InternalHiiUpdateFormPackageData (
       } else {\r
         GetFormSet = FALSE;\r
       }\r
-    } else if (IfrOpHdr->OpCode == EFI_IFR_FORM_OP) {\r
+    } else if (IfrOpHdr->OpCode == EFI_IFR_FORM_OP || IfrOpHdr->OpCode == EFI_IFR_FORM_MAP_OP) {\r
       if (CompareMem (&((EFI_IFR_FORM *) IfrOpHdr)->FormId, &FormId, sizeof (EFI_FORM_ID)) == 0) {\r
         GetForm = TRUE;\r
       } else {\r
index 2f38b56..2934ab3 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
 Implementation of interfaces function for EFI_HII_CONFIG_ROUTING_PROTOCOL.\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
@@ -951,6 +951,7 @@ ParseIfrData (
       break;\r
 \r
     case EFI_IFR_FORM_OP:\r
+    case EFI_IFR_FORM_MAP_OP:\r
       //\r
       // No matched varstore is found and directly return.\r
       //\r
index b429605..90fdc74 100644 (file)
@@ -24,6 +24,15 @@ 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
@@ -140,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
@@ -152,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
@@ -174,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
@@ -235,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
@@ -247,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
@@ -299,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
@@ -1218,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
@@ -1437,12 +1594,21 @@ 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
@@ -1468,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
@@ -1481,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
@@ -1499,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
@@ -1514,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
@@ -1524,7 +1696,8 @@ 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
@@ -1534,6 +1707,131 @@ EvaluateExpression (
       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
+              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) + TempStr [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
@@ -1542,19 +1840,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
@@ -1577,7 +1877,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
@@ -1585,7 +1886,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
@@ -1619,15 +1920,17 @@ 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
@@ -1638,10 +1941,11 @@ EvaluateExpression (
     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
@@ -1652,19 +1956,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
@@ -1676,14 +1982,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
@@ -1706,7 +2013,7 @@ EvaluateExpression (
       //\r
       Status = PopExpression (Value);\r
       if (EFI_ERROR (Status)) {\r
-        return Status;\r
+        goto Done;\r
       }\r
 \r
       //\r
@@ -1728,7 +2035,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
@@ -1753,21 +2061,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
@@ -1785,16 +2095,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
@@ -1812,10 +2240,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
@@ -1823,10 +2252,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
@@ -1881,10 +2311,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
@@ -1892,10 +2323,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
@@ -1916,10 +2348,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
@@ -1927,12 +2360,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
@@ -1982,7 +2416,7 @@ EvaluateExpression (
       //\r
       Status = PopExpression (&Data3);\r
       if (EFI_ERROR (Status)) {\r
-        return Status;\r
+        goto Done;\r
       }\r
 \r
       //\r
@@ -1990,7 +2424,7 @@ EvaluateExpression (
       //\r
       Status = PopExpression (&Data2);\r
       if (EFI_ERROR (Status)) {\r
-        return Status;\r
+        goto Done;\r
       }\r
 \r
       //\r
@@ -1998,10 +2432,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
@@ -2027,16 +2462,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
@@ -2046,17 +2552,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
index fc03834..5593b6e 100644 (file)
@@ -450,6 +450,8 @@ DestroyExpression (
 {\r
   LIST_ENTRY         *Link;\r
   EXPRESSION_OPCODE  *OpCode;\r
+  LIST_ENTRY         *SubExpressionLink;\r
+  FORM_EXPRESSION    *SubExpression;\r
 \r
   while (!IsListEmpty (&Expression->OpCodeListHead)) {\r
     Link = GetFirstNode (&Expression->OpCodeListHead);\r
@@ -459,6 +461,19 @@ DestroyExpression (
     if (OpCode->ValueList != NULL) {\r
       FreePool (OpCode->ValueList);\r
     }\r
+\r
+    if (OpCode->ValueName != NULL) {\r
+      FreePool (OpCode->ValueName);\r
+    }\r
+\r
+    if (OpCode->MapExpressionList.ForwardLink != NULL) {\r
+      while (!IsListEmpty (&OpCode->MapExpressionList)) {\r
+        SubExpressionLink = GetFirstNode(&OpCode->MapExpressionList);\r
+        SubExpression     = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);\r
+        RemoveEntryList(&SubExpression->Link);\r
+        DestroyExpression (SubExpression);\r
+      }\r
+    }\r
   }\r
 \r
   //\r
@@ -746,10 +761,12 @@ IsExpressionOpCode (
   )\r
 {\r
   if (((Operand >= EFI_IFR_EQ_ID_VAL_OP) && (Operand <= EFI_IFR_NOT_OP)) ||\r
-      ((Operand >= EFI_IFR_MATCH_OP) && (Operand <= EFI_IFR_SPAN_OP)) ||\r
+      ((Operand >= EFI_IFR_MATCH_OP) && (Operand <= EFI_IFR_SET_OP))  ||\r
+      ((Operand >= EFI_IFR_EQUAL_OP) && (Operand <= EFI_IFR_SPAN_OP)) ||\r
       (Operand == EFI_IFR_CATENATE_OP) ||\r
       (Operand == EFI_IFR_TO_LOWER_OP) ||\r
       (Operand == EFI_IFR_TO_UPPER_OP) ||\r
+      (Operand == EFI_IFR_MAP_OP)      ||\r
       (Operand == EFI_IFR_VERSION_OP)  ||\r
       (Operand == EFI_IFR_SECURITY_OP)) {\r
     return TRUE;\r
@@ -848,6 +865,12 @@ ParseOpCodes (
   BOOLEAN                 SingleOpCodeExpression;\r
   BOOLEAN                 InScopeDefault;\r
   EFI_HII_VALUE           *Value;\r
+  EFI_IFR_FORM_MAP_METHOD *MapMethod;\r
+  UINT8                   MapScopeDepth;\r
+  LIST_ENTRY              *Link;\r
+  FORMSET_STORAGE         *VarStorage;\r
+  LIST_ENTRY              *MapExpressionList;\r
+  EFI_VARSTORE_ID         TempVarstoreId;\r
 \r
   mInScopeSubtitle         = FALSE;\r
   SuppressForQuestion      = FALSE;\r
@@ -867,6 +890,12 @@ ParseOpCodes (
   OptionSuppressExpression = NULL;\r
   FormSuppressExpression   = NULL;\r
   ImageId                  = NULL;\r
+  MapMethod                = NULL;\r
+  MapScopeDepth            = 0;\r
+  Link                     = NULL;\r
+  VarStorage               = NULL;\r
+  MapExpressionList        = NULL;\r
+  TempVarstoreId           = 0;\r
 \r
   //\r
   // Get the number of Statements and Expressions\r
@@ -888,6 +917,8 @@ ParseOpCodes (
   InitializeListHead (&FormSet->StorageListHead);\r
   InitializeListHead (&FormSet->DefaultStoreListHead);\r
   InitializeListHead (&FormSet->FormListHead);\r
+  ResetCurrentExpressionStack ();\r
+  ResetMapExpressionListStack ();\r
 \r
   CurrentForm = NULL;\r
   CurrentStatement = NULL;\r
@@ -989,6 +1020,81 @@ ParseOpCodes (
         CopyMem (&ExpressionOpCode->Guid, &((EFI_IFR_SECURITY *) OpCodeData)->Permissions, sizeof (EFI_GUID));\r
         break;\r
 \r
+      case EFI_IFR_GET_OP:\r
+      case EFI_IFR_SET_OP:\r
+        CopyMem (&TempVarstoreId, &((EFI_IFR_GET *) OpCodeData)->VarStoreId, sizeof (TempVarstoreId));\r
+        if (TempVarstoreId != 0) {\r
+          if (FormSet->StorageListHead.ForwardLink != NULL) {\r
+            Link = GetFirstNode (&FormSet->StorageListHead);\r
+            while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+              VarStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
+              if (VarStorage->VarStoreId == ((EFI_IFR_GET *) OpCodeData)->VarStoreId) {\r
+                ExpressionOpCode->VarStorage = VarStorage;\r
+                break;\r
+              }\r
+              Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+            }\r
+          }\r
+          if (ExpressionOpCode->VarStorage == NULL) {\r
+            //\r
+            // VarStorage is not found.\r
+            //\r
+            return EFI_INVALID_PARAMETER;\r
+          }\r
+        }\r
+        ExpressionOpCode->ValueType = ((EFI_IFR_GET *) OpCodeData)->VarStoreType;\r
+        switch (ExpressionOpCode->ValueType) {\r
+        case EFI_IFR_TYPE_BOOLEAN:\r
+        case EFI_IFR_TYPE_NUM_SIZE_8: \r
+          ExpressionOpCode->ValueWidth = 1;\r
+          break;\r
+\r
+        case EFI_IFR_TYPE_NUM_SIZE_16:\r
+        case EFI_IFR_TYPE_STRING:\r
+          ExpressionOpCode->ValueWidth = 2;\r
+          break;\r
+\r
+        case EFI_IFR_TYPE_NUM_SIZE_32:\r
+          ExpressionOpCode->ValueWidth = 4;\r
+          break;\r
+\r
+        case EFI_IFR_TYPE_NUM_SIZE_64:\r
+          ExpressionOpCode->ValueWidth = 8;\r
+          break;\r
+\r
+        case EFI_IFR_TYPE_DATE:\r
+          ExpressionOpCode->ValueWidth = sizeof (EFI_IFR_DATE);\r
+          break;\r
+\r
+        case EFI_IFR_TYPE_TIME:\r
+          ExpressionOpCode->ValueWidth = sizeof (EFI_IFR_TIME);\r
+          break;\r
+\r
+        case EFI_IFR_TYPE_OTHER:\r
+        case EFI_IFR_TYPE_UNDEFINED:\r
+        case EFI_IFR_TYPE_ACTION:\r
+        case EFI_IFR_TYPE_BUFFER:\r
+        default:\r
+          //\r
+          // Invalid value type for Get/Set opcode.\r
+          //\r
+          return EFI_INVALID_PARAMETER;\r
+        }\r
+        CopyMem (&ExpressionOpCode->VarStoreInfo.VarName,   &((EFI_IFR_GET *) OpCodeData)->VarStoreInfo.VarName,   sizeof (EFI_STRING_ID));\r
+        CopyMem (&ExpressionOpCode->VarStoreInfo.VarOffset, &((EFI_IFR_GET *) OpCodeData)->VarStoreInfo.VarOffset, sizeof (UINT16));\r
+        if ((ExpressionOpCode->VarStorage != NULL) && \r
+            (ExpressionOpCode->VarStorage->Type == EFI_HII_VARSTORE_NAME_VALUE || \r
+             ExpressionOpCode->VarStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
+          ExpressionOpCode->ValueName = GetToken (ExpressionOpCode->VarStoreInfo.VarName, FormSet->HiiHandle);\r
+          if (ExpressionOpCode->ValueName == NULL) {\r
+            //\r
+            // String ID is invalid.\r
+            //\r
+            return EFI_INVALID_PARAMETER;\r
+          }\r
+        }\r
+        break;\r
+\r
       case EFI_IFR_QUESTION_REF1_OP:\r
         CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));\r
         break;\r
@@ -1063,11 +1169,37 @@ ParseOpCodes (
       default:\r
         break;\r
       }\r
-\r
+      //\r
+      // Create sub expression nested in MAP opcode\r
+      //\r
+      if (CurrentExpression == NULL && MapScopeDepth > 0) {\r
+        CurrentExpression = CreateExpression (CurrentForm);\r
+        InsertTailList (MapExpressionList, &CurrentExpression->Link);\r
+        if (Scope == 0) {\r
+          SingleOpCodeExpression = TRUE;\r
+        }\r
+      }\r
       ASSERT (CurrentExpression != NULL);\r
       InsertTailList (&CurrentExpression->OpCodeListHead, &ExpressionOpCode->Link);\r
-\r
-      if (SingleOpCodeExpression) {\r
+      if (Operand == EFI_IFR_MAP_OP) {\r
+        //\r
+        // Store current Map Expression List.\r
+        //\r
+        if (MapExpressionList != NULL) {\r
+          PushMapExpressionList (MapExpressionList);\r
+        }\r
+        //\r
+        // Initialize new Map Expression List.\r
+        //\r
+        MapExpressionList = &ExpressionOpCode->MapExpressionList;\r
+        InitializeListHead (MapExpressionList);\r
+        //\r
+        // Store current expression.\r
+        //\r
+        PushCurrentExpression (CurrentExpression);\r
+        CurrentExpression = NULL;\r
+        MapScopeDepth ++;\r
+      } else if (SingleOpCodeExpression) {\r
         //\r
         // There are two cases to indicate the end of an Expression:\r
         // for single OpCode expression: one Expression OpCode\r
@@ -1134,6 +1266,7 @@ ParseOpCodes (
       InitializeListHead (&CurrentForm->ExpressionListHead);\r
       InitializeListHead (&CurrentForm->StatementListHead);\r
 \r
+      CurrentForm->FormType = STANDARD_MAP_FORM_TYPE;\r
       CopyMem (&CurrentForm->FormId,    &((EFI_IFR_FORM *) OpCodeData)->FormId,    sizeof (UINT16));\r
       CopyMem (&CurrentForm->FormTitle, &((EFI_IFR_FORM *) OpCodeData)->FormTitle, sizeof (EFI_STRING_ID));\r
 \r
@@ -1157,6 +1290,63 @@ ParseOpCodes (
       InsertTailList (&FormSet->FormListHead, &CurrentForm->Link);\r
       break;\r
 \r
+    case EFI_IFR_FORM_MAP_OP:\r
+      //\r
+      // Create a new Form for this FormSet\r
+      //\r
+      CurrentForm = AllocateZeroPool (sizeof (FORM_BROWSER_FORM));\r
+      ASSERT (CurrentForm != NULL);\r
+      CurrentForm->Signature = FORM_BROWSER_FORM_SIGNATURE;\r
+      InitializeListHead (&CurrentForm->ExpressionListHead);\r
+      InitializeListHead (&CurrentForm->StatementListHead);\r
+      CopyMem (&CurrentForm->FormId, &((EFI_IFR_FORM *) OpCodeData)->FormId, sizeof (UINT16));\r
+\r
+      MapMethod = (EFI_IFR_FORM_MAP_METHOD *) (OpCodeData + sizeof (EFI_IFR_FORM_MAP));\r
+      //\r
+      // FormMap Form must contain at least one Map Method.\r
+      //\r
+      if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length < ((UINTN) (UINT8 *) (MapMethod + 1) - (UINTN) OpCodeData)) {\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+      //\r
+      // Try to find the standard form map method.\r
+      //\r
+      while (((UINTN) (UINT8 *) MapMethod - (UINTN) OpCodeData) < ((EFI_IFR_OP_HEADER *) OpCodeData)->Length) {\r
+        if (CompareGuid ((EFI_GUID *) (VOID *) &MapMethod->MethodIdentifier, &gEfiHiiStandardFormGuid)) {\r
+          CopyMem (&CurrentForm->FormTitle, &MapMethod->MethodTitle, sizeof (EFI_STRING_ID));\r
+          CurrentForm->FormType = STANDARD_MAP_FORM_TYPE;\r
+          break;\r
+        }\r
+        MapMethod ++;\r
+      }\r
+      //\r
+      // If the standard form map method is not found, the first map method title will be used.\r
+      //\r
+      if (CurrentForm->FormTitle == 0) {\r
+        MapMethod = (EFI_IFR_FORM_MAP_METHOD *) (OpCodeData + sizeof (EFI_IFR_FORM_MAP));\r
+        CopyMem (&CurrentForm->FormTitle, &MapMethod->MethodTitle, sizeof (EFI_STRING_ID));\r
+      }\r
+\r
+      if (InScopeFormSuppress) {\r
+        //\r
+        // Form is inside of suppressif\r
+        //\r
+        CurrentForm->SuppressExpression = FormSuppressExpression;\r
+      }\r
+\r
+      if (Scope != 0) {\r
+        //\r
+        // Enter scope of a Form, suppressif will be used for Question or Option\r
+        //\r
+        SuppressForQuestion = TRUE;\r
+      }\r
+\r
+      //\r
+      // Insert into Form list of this FormSet\r
+      //\r
+      InsertTailList (&FormSet->FormListHead, &CurrentForm->Link);\r
+      break;\r
+\r
     //\r
     // Storage\r
     //\r
@@ -1707,6 +1897,50 @@ ParseOpCodes (
       }\r
       break;\r
 \r
+    case EFI_IFR_READ_OP:\r
+      CurrentExpression = CreateExpression (CurrentForm);\r
+      CurrentExpression->Type = EFI_HII_EXPRESSION_READ;\r
+      InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);\r
+\r
+      //\r
+      // Make sure CurrentStatement is not NULL.\r
+      // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR\r
+      // file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler.\r
+      //\r
+      ASSERT (CurrentStatement != NULL);\r
+      CurrentStatement->ReadExpression = CurrentExpression;\r
+\r
+      //\r
+      // Take a look at next OpCode to see whether current expression consists\r
+      // of single OpCode\r
+      //\r
+      if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {\r
+        SingleOpCodeExpression = TRUE;\r
+      }\r
+      break;\r
+\r
+    case EFI_IFR_WRITE_OP:\r
+      CurrentExpression = CreateExpression (CurrentForm);\r
+      CurrentExpression->Type = EFI_HII_EXPRESSION_WRITE;\r
+      InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);\r
+\r
+      //\r
+      // Make sure CurrentStatement is not NULL.\r
+      // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR\r
+      // file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler.\r
+      //\r
+      ASSERT (CurrentStatement != NULL);\r
+      CurrentStatement->WriteExpression = CurrentExpression;\r
+\r
+      //\r
+      // Take a look at next OpCode to see whether current expression consists\r
+      // of single OpCode\r
+      //\r
+      if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {\r
+        SingleOpCodeExpression = TRUE;\r
+      }\r
+      break;\r
+\r
     //\r
     // Image\r
     //\r
@@ -1723,6 +1957,7 @@ ParseOpCodes (
         break;\r
 \r
       case EFI_IFR_FORM_OP:\r
+      case EFI_IFR_FORM_MAP_OP:\r
         ASSERT (CurrentForm != NULL);\r
         ImageId = &CurrentForm->ImageId;\r
         break;\r
@@ -1818,6 +2053,7 @@ ParseOpCodes (
         break;\r
 \r
       case EFI_IFR_FORM_OP:\r
+      case EFI_IFR_FORM_MAP_OP:\r
         //\r
         // End of Form\r
         //\r
@@ -1871,6 +2107,22 @@ ParseOpCodes (
         InScopeDefault = FALSE;\r
         break;\r
 \r
+      case EFI_IFR_MAP_OP:\r
+        //\r
+        // Get current Map Expression List.\r
+        //\r
+        Status = PopMapExpressionList ((VOID **) &MapExpressionList);\r
+        if (Status == EFI_ACCESS_DENIED) {\r
+          MapExpressionList = NULL;\r
+        }\r
+        //\r
+        // Get current expression.\r
+        //\r
+        Status = PopCurrentExpression ((VOID **) &CurrentExpression);\r
+        ASSERT_EFI_ERROR (Status);\r
+        MapScopeDepth --;\r
+        break;\r
+\r
       default:\r
         if (IsExpressionOpCode (ScopeOpCode)) {\r
           if (mInScopeDisable && CurrentForm == NULL) {\r
@@ -1889,7 +2141,7 @@ ParseOpCodes (
 \r
             OpCodeDisabled = CurrentExpression->Result.Value.b;\r
             //\r
-            // DisableIf Expression is only used once and not quequed, free it\r
+            // DisableIf Expression is only used once and not queued, free it\r
             //\r
             DestroyExpression (CurrentExpression);\r
           }\r
index 9301fe6..6d5a3db 100644 (file)
@@ -387,9 +387,11 @@ EvaluateFormExpressions (
     Link = GetNextNode (&Form->ExpressionListHead, Link);\r
 \r
     if (Expression->Type == EFI_HII_EXPRESSION_INCONSISTENT_IF ||\r
-        Expression->Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {\r
+        Expression->Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF ||\r
+        Expression->Type == EFI_HII_EXPRESSION_WRITE ||\r
+        (Expression->Type == EFI_HII_EXPRESSION_READ && Form->FormType != STANDARD_MAP_FORM_TYPE)) {\r
       //\r
-      // Postpone Form validation to Question editing or Form submiting\r
+      // Postpone Form validation to Question editing or Form submitting or Question Write or Question Read for nonstandard form.\r
       //\r
       continue;\r
     }\r
index 81de737..d50071e 100644 (file)
@@ -661,6 +661,10 @@ GetToken (
 {\r
   EFI_STRING  String;\r
 \r
+  if (HiiHandle == NULL) {\r
+    return NULL;\r
+  }\r
+\r
   String = HiiGetString (HiiHandle, Token, NULL);\r
   if (String == NULL) {\r
     String = AllocateCopyPool (sizeof (mUnknownString), mUnknownString);\r
@@ -1041,6 +1045,20 @@ GetQuestionValue (
     }\r
     return Status;\r
   }\r
+  \r
+  //\r
+  // Get question value by read expression.\r
+  //\r
+  if (Question->ReadExpression != NULL && Form->FormType == STANDARD_MAP_FORM_TYPE) {\r
+    Status = EvaluateExpression (FormSet, Form, Question->ReadExpression);\r
+    if (!EFI_ERROR (Status) && (Question->ReadExpression->Result.Type < EFI_IFR_TYPE_OTHER)) {\r
+      //\r
+      // Only update question value to the valid result.\r
+      //\r
+      CopyMem (&Question->HiiValue, &Question->ReadExpression->Result, sizeof (EFI_HII_VALUE));\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
 \r
   //\r
   // Question value is provided by RTC\r
@@ -1369,6 +1387,16 @@ SetQuestionValue (
   if (Question->ValueExpression != NULL) {\r
     return Status;\r
   }\r
+  \r
+  //\r
+  // Before set question value, evaluate its write expression.\r
+  //\r
+  if (Question->WriteExpression != NULL && Form->FormType == STANDARD_MAP_FORM_TYPE) {\r
+    Status = EvaluateExpression (FormSet, Form, Question->WriteExpression);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
 \r
   //\r
   // Question value is provided by RTC\r
index 40030be..fdbb4c1 100644 (file)
@@ -32,6 +32,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 #include <Guid/MdeModuleHii.h>\r
 #include <Guid/HiiPlatformSetupFormset.h>\r
+#include <Guid/HiiFormMapMethodGuid.h>\r
 \r
 #include <Library/PrintLib.h>\r
 #include <Library/DebugLib.h>\r
@@ -183,6 +184,8 @@ typedef struct {
 #define EFI_HII_EXPRESSION_DISABLE_IF        4\r
 #define EFI_HII_EXPRESSION_VALUE             5\r
 #define EFI_HII_EXPRESSION_RULE              6\r
+#define EFI_HII_EXPRESSION_READ              7\r
+#define EFI_HII_EXPRESSION_WRITE             8\r
 \r
 #define EFI_HII_VARSTORE_BUFFER              0\r
 #define EFI_HII_VARSTORE_NAME_VALUE          1\r
@@ -239,6 +242,11 @@ typedef struct {
 \r
 #define FORMSET_STORAGE_FROM_LINK(a)  CR (a, FORMSET_STORAGE, Link, FORMSET_STORAGE_SIGNATURE)\r
 \r
+typedef union {\r
+  EFI_STRING_ID         VarName;\r
+  UINT16                VarOffset;\r
+} VAR_STORE_INFO;\r
+\r
 #define EXPRESSION_OPCODE_SIGNATURE  SIGNATURE_32 ('E', 'X', 'O', 'P')\r
 \r
 typedef struct {\r
@@ -261,6 +269,13 @@ typedef struct {
 \r
   EFI_STRING_ID     DevicePath;  // For EFI_IFR_QUESTION_REF3_2, EFI_IFR_QUESTION_REF3_3\r
   EFI_GUID          Guid;\r
+\r
+  FORMSET_STORAGE   *VarStorage; // For EFI_IFR_SET, EFI_IFR_GET\r
+  VAR_STORE_INFO    VarStoreInfo;// For EFI_IFR_SET, EFI_IFR_GET\r
+  UINT8             ValueType;   // For EFI_IFR_SET, EFI_IFR_GET\r
+  UINT8             ValueWidth;  // For EFI_IFR_SET, EFI_IFR_GET\r
+  CHAR16            *ValueName;  // For EFI_IFR_SET, EFI_IFR_GET\r
+  LIST_ENTRY        MapExpressionList;   // nested expressions inside of Map opcode.\r
 } EXPRESSION_OPCODE;\r
 \r
 #define EXPRESSION_OPCODE_FROM_LINK(a)  CR (a, EXPRESSION_OPCODE, Link, EXPRESSION_OPCODE_SIGNATURE)\r
@@ -315,11 +330,6 @@ typedef struct {
 \r
 #define FORM_BROWSER_STATEMENT_SIGNATURE  SIGNATURE_32 ('F', 'S', 'T', 'A')\r
 \r
-typedef union {\r
-  EFI_STRING_ID         VarName;\r
-  UINT16                VarOffset;\r
-} VAR_STORE_INFO;\r
-\r
 typedef struct {\r
   UINTN                 Signature;\r
   LIST_ENTRY            Link;\r
@@ -386,18 +396,22 @@ typedef struct {
   FORM_EXPRESSION       *SuppressExpression; // nesting inside of SuppressIf\r
   FORM_EXPRESSION       *DisableExpression;  // nesting inside of DisableIf\r
 \r
+  FORM_EXPRESSION       *ReadExpression;     // nested EFI_IFR_READ, provide this question value by read expression.\r
+  FORM_EXPRESSION       *WriteExpression;    // nested EFI_IFR_WRITE, evaluate write expression after this question value is set.\r
 } FORM_BROWSER_STATEMENT;\r
 \r
 #define FORM_BROWSER_STATEMENT_FROM_LINK(a)  CR (a, FORM_BROWSER_STATEMENT, Link, FORM_BROWSER_STATEMENT_SIGNATURE)\r
 \r
 #define FORM_BROWSER_FORM_SIGNATURE  SIGNATURE_32 ('F', 'F', 'R', 'M')\r
+#define STANDARD_MAP_FORM_TYPE 0x01\r
 \r
 typedef struct {\r
   UINTN             Signature;\r
   LIST_ENTRY        Link;\r
 \r
-  UINT16            FormId;\r
-  EFI_STRING_ID     FormTitle;\r
+  UINT16            FormId;               // FormId of normal form or formmap form.\r
+  EFI_STRING_ID     FormTitle;            // FormTile of normal form, or FormMapMethod title of formmap form.\r
+  UINT16            FormType;             // Specific form type for the different form.\r
 \r
   EFI_IMAGE_ID      ImageId;\r
 \r
@@ -795,6 +809,42 @@ CreateDialog (
   ...\r
   );\r
 \r
+/**\r
+  Get Value for given Name from a NameValue Storage.\r
+\r
+  @param  Storage                The NameValue Storage.\r
+  @param  Name                   The Name.\r
+  @param  Value                  The retured Value.\r
+\r
+  @retval EFI_SUCCESS            Value found for given Name.\r
+  @retval EFI_NOT_FOUND          No such Name found in NameValue storage.\r
+\r
+**/\r
+EFI_STATUS\r
+GetValueByName (\r
+  IN FORMSET_STORAGE         *Storage,\r
+  IN CHAR16                  *Name,\r
+  IN OUT CHAR16              **Value\r
+  );\r
+\r
+/**\r
+  Set Value of given Name in a NameValue Storage.\r
+\r
+  @param  Storage                The NameValue Storage.\r
+  @param  Name                   The Name.\r
+  @param  Value                  The Value to set.\r
+\r
+  @retval EFI_SUCCESS            Value found for given Name.\r
+  @retval EFI_NOT_FOUND          No such Name found in NameValue storage.\r
+\r
+**/\r
+EFI_STATUS\r
+SetValueByName (\r
+  IN FORMSET_STORAGE         *Storage,\r
+  IN CHAR16                  *Name,\r
+  IN CHAR16                  *Value\r
+  );\r
+\r
 /**\r
   Get Question's current Value.\r
 \r
index 4b5128b..dcaca62 100644 (file)
@@ -63,6 +63,7 @@
   gEfiIfrTianoGuid                              ## CONSUMES  ## GUID\r
   gEfiIfrFrameworkGuid                          ## CONSUMES  ## GUID\r
   gEfiHiiPlatformSetupFormsetGuid\r
+  gEfiHiiStandardFormGuid                       ## SOMETIMES_CONSUMES ## GUID\r
 \r
 [Protocols]\r
   gEfiHiiConfigAccessProtocolGuid               ## CONSUMES\r
index 6fb3d93..45fb3eb 100644 (file)
@@ -735,6 +735,80 @@ PopScope (
   OUT UINT8     *Operand\r
   );\r
 \r
+/**\r
+  Reset stack pointer to begin of the stack.\r
+\r
+**/\r
+VOID\r
+ResetCurrentExpressionStack (\r
+  VOID\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
+/**\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
+/**\r
+  Reset stack pointer to begin of the stack.\r
+\r
+**/\r
+VOID\r
+ResetMapExpressionListStack (\r
+  VOID\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
+/**\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
 /**\r
   Get Form given its FormId.\r
 \r
index 5cfe91a..1c900c9 100644 (file)
@@ -715,8 +715,8 @@ typedef union {
 #define EFI_IFR_VERSION_OP             0x28\r
 #define EFI_IFR_END_OP                 0x29\r
 #define EFI_IFR_MATCH_OP               0x2A\r
-#define EFI_IFR_SET_OP                 0x2C\r
 #define EFI_IFR_GET_OP                 0x2B\r
+#define EFI_IFR_SET_OP                 0x2C\r
 #define EFI_IFR_READ_OP                0x2D\r
 #define EFI_IFR_WRITE_OP               0x2E\r
 #define EFI_IFR_EQUAL_OP               0x2F\r
@@ -1459,7 +1459,7 @@ typedef struct _EFI_IFR_FORM_MAP {
   ///\r
   /// One or more configuration method's name and unique identifier.\r
   ///\r
-  EFI_IFR_FORM_MAP_METHOD  Methods[1];\r
+  // EFI_IFR_FORM_MAP_METHOD  Methods[];\r
 } EFI_IFR_FORM_MAP;\r
 \r
 typedef struct _EFI_IFR_SET {\r
@@ -1483,6 +1483,10 @@ typedef struct _EFI_IFR_SET {
     ///\r
     UINT16           VarOffset;\r
   }                  VarStoreInfo;\r
+  ///\r
+  /// Specifies the type used for storage. \r
+  ///\r
+  UINT8              VarStoreType;\r
 } EFI_IFR_SET;\r
 \r
 typedef struct _EFI_IFR_GET {\r