]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c
1. Support inconsistent if opcode used in string/password opcode.
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / IfrParse.c
index 02684e46ca799614817287e4aa26f1987e8219ae..314f91b529bb1225677d8e94c5946fa0b8dfbe32 100644 (file)
@@ -1,8 +1,8 @@
 /** @file\r
 Parser for IFR binary encoding.\r
 \r
-Copyright (c) 2007 - 2010, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
+Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
 http://opensource.org/licenses/bsd-license.php\r
@@ -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
@@ -527,11 +542,13 @@ DestroyStorage (
 /**\r
   Free resources of a Statement.\r
 \r
+  @param  FormSet                Pointer of the FormSet\r
   @param  Statement              Pointer of the Statement\r
 \r
 **/\r
 VOID\r
 DestroyStatement (\r
+  IN     FORM_BROWSER_FORMSET    *FormSet,\r
   IN OUT FORM_BROWSER_STATEMENT  *Statement\r
   )\r
 {\r
@@ -590,18 +607,26 @@ DestroyStatement (
   if (Statement->BlockName != NULL) {\r
     FreePool (Statement->BlockName);\r
   }\r
+  if (Statement->BufferValue != NULL) {\r
+    FreePool (Statement->BufferValue);\r
+  }\r
+  if (Statement->Operand == EFI_IFR_STRING_OP || Statement->Operand == EFI_IFR_PASSWORD_OP) {\r
+    DeleteString(Statement->HiiValue.Value.string, FormSet->HiiHandle);\r
+  }\r
 }\r
 \r
 \r
 /**\r
   Free resources of a Form.\r
 \r
+  @param  FormSet                Pointer of the FormSet\r
   @param  Form                   Pointer of the Form.\r
 \r
 **/\r
 VOID\r
 DestroyForm (\r
-  IN OUT FORM_BROWSER_FORM  *Form\r
+  IN     FORM_BROWSER_FORMSET  *FormSet,\r
+  IN OUT FORM_BROWSER_FORM     *Form\r
   )\r
 {\r
   LIST_ENTRY              *Link;\r
@@ -627,7 +652,7 @@ DestroyForm (
     Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
     RemoveEntryList (&Statement->Link);\r
 \r
-    DestroyStatement (Statement);\r
+    DestroyStatement (FormSet, Statement);\r
   }\r
 \r
   //\r
@@ -713,7 +738,7 @@ DestroyFormSet (
       Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
       RemoveEntryList (&Form->Link);\r
 \r
-      DestroyForm (Form);\r
+      DestroyForm (FormSet, Form);\r
     }\r
   }\r
 \r
@@ -743,10 +768,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
@@ -845,6 +872,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
@@ -864,6 +897,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
@@ -885,6 +924,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
@@ -986,6 +1027,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 = (UINT8) sizeof (EFI_IFR_DATE);\r
+          break;\r
+\r
+        case EFI_IFR_TYPE_TIME:\r
+          ExpressionOpCode->ValueWidth = (UINT8) 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
@@ -1060,11 +1176,38 @@ 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
+        ASSERT (MapExpressionList != NULL);\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
@@ -1131,6 +1274,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
@@ -1154,6 +1298,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
@@ -1305,7 +1506,7 @@ ParseOpCodes (
         CurrentStatement->Minimum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MinValue;\r
         CurrentStatement->Maximum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MaxValue;\r
         CurrentStatement->Step    = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.Step;\r
-        CurrentStatement->StorageWidth = sizeof (UINT8);\r
+        CurrentStatement->StorageWidth = (UINT16) sizeof (UINT8);\r
         Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
         break;\r
 \r
@@ -1313,7 +1514,7 @@ ParseOpCodes (
         CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MinValue, sizeof (UINT16));\r
         CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MaxValue, sizeof (UINT16));\r
         CopyMem (&CurrentStatement->Step,    &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.Step,     sizeof (UINT16));\r
-        CurrentStatement->StorageWidth = sizeof (UINT16);\r
+        CurrentStatement->StorageWidth = (UINT16) sizeof (UINT16);\r
         Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;\r
         break;\r
 \r
@@ -1321,7 +1522,7 @@ ParseOpCodes (
         CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MinValue, sizeof (UINT32));\r
         CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MaxValue, sizeof (UINT32));\r
         CopyMem (&CurrentStatement->Step,    &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.Step,     sizeof (UINT32));\r
-        CurrentStatement->StorageWidth = sizeof (UINT32);\r
+        CurrentStatement->StorageWidth = (UINT16) sizeof (UINT32);\r
         Value->Type = EFI_IFR_TYPE_NUM_SIZE_32;\r
         break;\r
 \r
@@ -1329,7 +1530,7 @@ ParseOpCodes (
         CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MinValue, sizeof (UINT64));\r
         CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MaxValue, sizeof (UINT64));\r
         CopyMem (&CurrentStatement->Step,    &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.Step,     sizeof (UINT64));\r
-        CurrentStatement->StorageWidth = sizeof (UINT64);\r
+        CurrentStatement->StorageWidth = (UINT16) sizeof (UINT64);\r
         Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
         break;\r
 \r
@@ -1352,6 +1553,7 @@ ParseOpCodes (
       CurrentStatement->MaxContainers = ((EFI_IFR_ORDERED_LIST *) OpCodeData)->MaxContainers;\r
 \r
       CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_BUFFER;\r
+      CurrentStatement->BufferValue = NULL;\r
 \r
       if (Scope != 0) {\r
         SuppressForOption = TRUE;\r
@@ -1363,7 +1565,7 @@ ParseOpCodes (
       ASSERT(CurrentStatement != NULL);\r
 \r
       CurrentStatement->Flags = ((EFI_IFR_CHECKBOX *) OpCodeData)->Flags;\r
-      CurrentStatement->StorageWidth = sizeof (BOOLEAN);\r
+      CurrentStatement->StorageWidth = (UINT16) sizeof (BOOLEAN);\r
       CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_BOOLEAN;\r
 \r
       InitializeRequestElement (FormSet, CurrentStatement);\r
@@ -1385,6 +1587,7 @@ ParseOpCodes (
 \r
       CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;\r
       CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth + sizeof (CHAR16));\r
+      CurrentStatement->HiiValue.Value.string = NewString ((CHAR16*) CurrentStatement->BufferValue, FormSet->HiiHandle);\r
 \r
       InitializeRequestElement (FormSet, CurrentStatement);\r
       break;\r
@@ -1403,6 +1606,7 @@ ParseOpCodes (
 \r
       CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;\r
       CurrentStatement->BufferValue = AllocateZeroPool ((CurrentStatement->StorageWidth + sizeof (CHAR16)));\r
+      CurrentStatement->HiiValue.Value.string = NewString ((CHAR16*) CurrentStatement->BufferValue, FormSet->HiiHandle);\r
 \r
       InitializeRequestElement (FormSet, CurrentStatement);\r
       break;\r
@@ -1415,7 +1619,7 @@ ParseOpCodes (
       CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_DATE;\r
 \r
       if ((CurrentStatement->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_NORMAL) {\r
-        CurrentStatement->StorageWidth = sizeof (EFI_HII_DATE);\r
+        CurrentStatement->StorageWidth = (UINT16) sizeof (EFI_HII_DATE);\r
 \r
         InitializeRequestElement (FormSet, CurrentStatement);\r
       } else {\r
@@ -1435,7 +1639,7 @@ ParseOpCodes (
       CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_TIME;\r
 \r
       if ((CurrentStatement->Flags & QF_TIME_STORAGE) == QF_TIME_STORAGE_NORMAL) {\r
-        CurrentStatement->StorageWidth = sizeof (EFI_IFR_TIME);\r
+        CurrentStatement->StorageWidth = (UINT16) sizeof (EFI_IFR_TIME);\r
 \r
         InitializeRequestElement (FormSet, CurrentStatement);\r
       } else {\r
@@ -1703,6 +1907,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
@@ -1719,6 +1967,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
@@ -1814,6 +2063,7 @@ ParseOpCodes (
         break;\r
 \r
       case EFI_IFR_FORM_OP:\r
+      case EFI_IFR_FORM_MAP_OP:\r
         //\r
         // End of Form\r
         //\r
@@ -1867,6 +2117,23 @@ 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
+        ASSERT (MapScopeDepth > 0);\r
+        MapScopeDepth --;\r
+        break;\r
+\r
       default:\r
         if (IsExpressionOpCode (ScopeOpCode)) {\r
           if (mInScopeDisable && CurrentForm == NULL) {\r
@@ -1885,7 +2152,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