]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c
MdeModulePkg: Add match2 opcode support in SetupBrowserDxe and sample code in DriverS...
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / IfrParse.c
index 0070502f9b592b52276c341a71a43b4b2b4154d2..8ddc449e69b63c00b5aea2a20c364b5b1c0efa5e 100644 (file)
@@ -1,8 +1,8 @@
 /** @file\r
 Parser for IFR binary encoding.\r
 \r
-Copyright (c) 2007 - 2009, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
+Copyright (c) 2007 - 2015, 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
@@ -13,21 +13,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 **/\r
 \r
 #include "Setup.h"\r
-#include "Ui.h"\r
 \r
 UINT16           mStatementIndex;\r
 UINT16           mExpressionOpCodeIndex;\r
-\r
-BOOLEAN          mInScopeSubtitle;\r
-BOOLEAN          mInScopeSuppress;\r
-BOOLEAN          mInScopeGrayOut;\r
-FORM_EXPRESSION  *mSuppressExpression;\r
-FORM_EXPRESSION  *mGrayOutExpression;\r
-\r
-EFI_GUID  gTianoHiiIfrGuid = EFI_IFR_TIANO_GUID;\r
-GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID  mFrameworkHiiCompatibilityGuid = EFI_IFR_FRAMEWORK_GUID;\r
-\r
-\r
+EFI_QUESTION_ID  mUsedQuestionId;\r
+extern LIST_ENTRY      gBrowserStorageList;\r
 /**\r
   Initialize Statement header members.\r
 \r
@@ -47,12 +37,13 @@ CreateStatement (
 {\r
   FORM_BROWSER_STATEMENT    *Statement;\r
   EFI_IFR_STATEMENT_HEADER  *StatementHdr;\r
+  INTN                      ConditionalExprCount; \r
 \r
   if (Form == NULL) {\r
     //\r
-    // We are currently not in a Form Scope, so just skip this Statement\r
+    // Only guid op may out side the form level.\r
     //\r
-    return NULL;\r
+    ASSERT (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_GUID_OP);\r
   }\r
 \r
   Statement = &FormSet->StatementBuffer[mStatementIndex];\r
@@ -62,30 +53,39 @@ CreateStatement (
   InitializeListHead (&Statement->OptionListHead);\r
   InitializeListHead (&Statement->InconsistentListHead);\r
   InitializeListHead (&Statement->NoSubmitListHead);\r
+  InitializeListHead (&Statement->WarningListHead);\r
 \r
   Statement->Signature = FORM_BROWSER_STATEMENT_SIGNATURE;\r
 \r
   Statement->Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;\r
+  Statement->OpCode  = (EFI_IFR_OP_HEADER *) OpCodeData;\r
 \r
   StatementHdr = (EFI_IFR_STATEMENT_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER));\r
   CopyMem (&Statement->Prompt, &StatementHdr->Prompt, sizeof (EFI_STRING_ID));\r
   CopyMem (&Statement->Help, &StatementHdr->Help, sizeof (EFI_STRING_ID));\r
 \r
-  if (mInScopeSuppress) {\r
-    Statement->SuppressExpression = mSuppressExpression;\r
-  }\r
-\r
-  if (mInScopeGrayOut) {\r
-    Statement->GrayOutExpression = mGrayOutExpression;\r
+  ConditionalExprCount = GetConditionalExpressionCount(ExpressStatement);\r
+  if (ConditionalExprCount > 0) {\r
+    //\r
+    // Form is inside of suppressif\r
+    //\r
+    \r
+    Statement->Expression = (FORM_EXPRESSION_LIST *) AllocatePool( \r
+                                             (UINTN) (sizeof(FORM_EXPRESSION_LIST) + ((ConditionalExprCount -1) * sizeof(FORM_EXPRESSION *))));\r
+    ASSERT (Statement->Expression != NULL);\r
+    Statement->Expression->Count     = (UINTN) ConditionalExprCount;\r
+    Statement->Expression->Signature = FORM_EXPRESSION_LIST_SIGNATURE;\r
+    CopyMem (Statement->Expression->Expression, GetConditionalExpressionList(ExpressStatement), (UINTN) (sizeof (FORM_EXPRESSION *) * ConditionalExprCount));\r
   }\r
 \r
-  Statement->InSubtitle = mInScopeSubtitle;\r
-\r
   //\r
   // Insert this Statement into current Form\r
   //\r
-  InsertTailList (&Form->StatementListHead, &Statement->Link);\r
-\r
+  if (Form == NULL) {\r
+    InsertTailList (&FormSet->StatementListOSF, &Statement->Link);\r
+  } else {\r
+    InsertTailList (&Form->StatementListHead, &Statement->Link);\r
+  }\r
   return Statement;\r
 }\r
 \r
@@ -93,15 +93,15 @@ CreateStatement (
   Convert a numeric value to a Unicode String and insert it to String Package.\r
   This string is used as the Unicode Name for the EFI Variable. This is to support\r
   the deprecated vareqval opcode.\r
-  \r
+\r
   @param FormSet        The FormSet.\r
   @param Statement      The numeric question whose VarStoreInfo.VarName is the\r
                         numeric value which is used to produce the Unicode Name\r
                         for the EFI Variable.\r
-                        \r
+\r
   If the Statement is NULL, the ASSERT.\r
   If the opcode is not Numeric, then ASSERT.\r
-  \r
+\r
   @retval EFI_SUCCESS The funtion always succeeds.\r
 **/\r
 EFI_STATUS\r
@@ -112,35 +112,33 @@ UpdateCheckBoxStringToken (
 {\r
   CHAR16                  Str[MAXIMUM_VALUE_CHARACTERS];\r
   EFI_STRING_ID           Id;\r
-  EFI_STATUS              Status;\r
 \r
   ASSERT (Statement != NULL);\r
   ASSERT (Statement->Operand == EFI_IFR_NUMERIC_OP);\r
-  \r
+\r
   UnicodeValueToString (Str, 0, Statement->VarStoreInfo.VarName, MAXIMUM_VALUE_CHARACTERS - 1);\r
-  \r
-  Status = HiiLibNewString (FormSet->HiiHandle, &Id, Str);\r
 \r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
+  Id = HiiSetString (FormSet->HiiHandle, 0, Str, NULL);\r
+  if (Id == 0) {\r
+    return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
   Statement->VarStoreInfo.VarName = Id;\r
-    \r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
   Check if the next opcode is the EFI_IFR_EXTEND_OP_VAREQNAME.\r
-  \r
+\r
   @param OpCodeData     The current opcode.\r
-                        \r
+\r
   @retval TRUE Yes.\r
   @retval FALSE No.\r
 **/\r
 BOOLEAN\r
 IsNextOpCodeGuidedVarEqName (\r
-  UINT8 *OpCodeData\r
+  IN UINT8 *OpCodeData\r
   )\r
 {\r
   //\r
@@ -148,9 +146,9 @@ IsNextOpCodeGuidedVarEqName (
   //\r
   OpCodeData += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
   if (*OpCodeData == EFI_IFR_GUID_OP) {\r
-    if (CompareGuid (&mFrameworkHiiCompatibilityGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
+    if (CompareGuid (&gEfiIfrFrameworkGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
       //\r
-      // Specific GUIDed opcodes to support IFR generated from Framework HII VFR \r
+      // Specific GUIDed opcodes to support IFR generated from Framework HII VFR\r
       //\r
       if ((((EFI_IFR_GUID_VAREQNAME *) OpCodeData)->ExtendOpCode) == EFI_IFR_EXTEND_OP_VAREQNAME) {\r
         return TRUE;\r
@@ -184,6 +182,7 @@ CreateQuestion (
   FORMSET_STORAGE          *Storage;\r
   NAME_VALUE_NODE          *NameValueNode;\r
   EFI_STATUS               Status;\r
+  BOOLEAN                  Find;\r
 \r
   Statement = CreateStatement (OpCodeData, FormSet, Form);\r
   if (Statement == NULL) {\r
@@ -208,7 +207,7 @@ CreateQuestion (
   // Take a look at next OpCode to see whether it is a GUIDed opcode to support\r
   // Framework Compatibility\r
   //\r
-  if (FeaturePcdGet (PcdFrameworkHiiCompatibilitySupport)) {\r
+  if (FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {\r
     if ((*OpCodeData == EFI_IFR_NUMERIC_OP) && IsNextOpCodeGuidedVarEqName (OpCodeData)) {\r
       Status = UpdateCheckBoxStringToken (FormSet, Statement);\r
       if (EFI_ERROR (Status)) {\r
@@ -225,7 +224,7 @@ CreateQuestion (
     Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
 \r
     if (Storage->VarStoreId == Statement->VarStoreId) {\r
-      Statement->Storage = Storage;\r
+      Statement->Storage = Storage->BrowserStorage;\r
       break;\r
     }\r
 \r
@@ -243,19 +242,39 @@ CreateQuestion (
 \r
     if (Statement->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
       //\r
-      // Insert to Name/Value varstore list\r
+      // Check whether old string node already exist.\r
       //\r
-      NameValueNode = AllocateZeroPool (sizeof (NAME_VALUE_NODE));\r
-      ASSERT (NameValueNode != NULL);\r
-      NameValueNode->Signature = NAME_VALUE_NODE_SIGNATURE;\r
-      NameValueNode->Name = AllocateCopyPool (StrSize (Statement->VariableName), Statement->VariableName);\r
-      ASSERT (NameValueNode->Name != NULL);\r
-      NameValueNode->Value = AllocateZeroPool (0x10);\r
-      ASSERT (NameValueNode->Value != NULL);\r
-      NameValueNode->EditValue = AllocateZeroPool (0x10);\r
-      ASSERT (NameValueNode->EditValue != NULL);\r
+      Find = FALSE;\r
+      if (!IsListEmpty(&Statement->Storage->NameValueListHead)) {  \r
+        Link = GetFirstNode (&Statement->Storage->NameValueListHead);\r
+        while (!IsNull (&Statement->Storage->NameValueListHead, Link)) {\r
+          NameValueNode = NAME_VALUE_NODE_FROM_LINK (Link);\r
+\r
+          if (StrCmp (Statement->VariableName, NameValueNode->Name) == 0) {\r
+            Find = TRUE;\r
+            break;\r
+          }\r
+\r
+          Link = GetNextNode (&Statement->Storage->NameValueListHead, Link);\r
+        }\r
+      }\r
 \r
-      InsertTailList (&Statement->Storage->NameValueListHead, &NameValueNode->Link);\r
+      if (!Find) {\r
+        //\r
+        // Insert to Name/Value varstore list\r
+        //\r
+        NameValueNode = AllocateZeroPool (sizeof (NAME_VALUE_NODE));\r
+        ASSERT (NameValueNode != NULL);\r
+        NameValueNode->Signature = NAME_VALUE_NODE_SIGNATURE;\r
+        NameValueNode->Name = AllocateCopyPool (StrSize (Statement->VariableName), Statement->VariableName);\r
+        ASSERT (NameValueNode->Name != NULL);\r
+        NameValueNode->Value = AllocateZeroPool (0x10);\r
+        ASSERT (NameValueNode->Value != NULL);\r
+        NameValueNode->EditValue = AllocateZeroPool (0x10);\r
+        ASSERT (NameValueNode->EditValue != NULL);\r
+\r
+        InsertTailList (&Statement->Storage->NameValueListHead, &NameValueNode->Link);\r
+      }\r
     }\r
   }\r
 \r
@@ -267,13 +286,15 @@ CreateQuestion (
   Allocate a FORM_EXPRESSION node.\r
 \r
   @param  Form                   The Form associated with this Expression\r
+  @param  OpCode                 The binary opcode data.\r
 \r
   @return Pointer to a FORM_EXPRESSION data structure.\r
 \r
 **/\r
 FORM_EXPRESSION *\r
 CreateExpression (\r
-  IN OUT FORM_BROWSER_FORM        *Form\r
+  IN OUT FORM_BROWSER_FORM        *Form,\r
+  IN     UINT8                    *OpCode\r
   )\r
 {\r
   FORM_EXPRESSION  *Expression;\r
@@ -282,96 +303,370 @@ CreateExpression (
   ASSERT (Expression != NULL);\r
   Expression->Signature = FORM_EXPRESSION_SIGNATURE;\r
   InitializeListHead (&Expression->OpCodeListHead);\r
+  Expression->OpCode = (EFI_IFR_OP_HEADER *) OpCode;\r
 \r
   return Expression;\r
 }\r
 \r
+/**\r
+  Create ConfigHdr string for a storage.\r
+\r
+  @param  FormSet                Pointer of the current FormSet\r
+  @param  Storage                Pointer of the storage\r
+\r
+  @retval EFI_SUCCESS            Initialize ConfigHdr success\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeConfigHdr (\r
+  IN FORM_BROWSER_FORMSET  *FormSet,\r
+  IN OUT FORMSET_STORAGE   *Storage\r
+  )\r
+{\r
+  CHAR16      *Name;\r
+\r
+  if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_BUFFER || \r
+      Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
+    Name = Storage->BrowserStorage->Name;\r
+  } else {\r
+    Name = NULL;\r
+  }\r
+\r
+  Storage->ConfigHdr = HiiConstructConfigHdr (\r
+                         &Storage->BrowserStorage->Guid,\r
+                         Name,\r
+                         FormSet->DriverHandle\r
+                         );\r
+\r
+  if (Storage->ConfigHdr == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Find the global storage link base on the input storate type, name and guid.\r
+\r
+  For EFI_HII_VARSTORE_EFI_VARIABLE and EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER,\r
+  same guid + name = same storage\r
+\r
+  For EFI_HII_VARSTORE_NAME_VALUE:\r
+  same guid + HiiHandle = same storage\r
+\r
+  For EFI_HII_VARSTORE_BUFFER:\r
+  same guid + name + HiiHandle = same storage\r
+\r
+  @param  StorageType                Storage type.\r
+  @param  StorageGuid                Storage guid.\r
+  @param  StorageName                Storage Name.\r
+  @param  HiiHandle                  HiiHandle for this varstore.\r
+\r
+  @return Pointer to a GLOBAL_STORAGE data structure.\r
+\r
+**/\r
+BROWSER_STORAGE *\r
+FindStorageInList (\r
+  IN UINT8                 StorageType,\r
+  IN EFI_GUID              *StorageGuid,\r
+  IN CHAR16                *StorageName,\r
+  IN EFI_HII_HANDLE        HiiHandle\r
+  )\r
+{\r
+  LIST_ENTRY       *Link;\r
+  BROWSER_STORAGE  *BrowserStorage;\r
+\r
+  Link  = GetFirstNode (&gBrowserStorageList);\r
+  while (!IsNull (&gBrowserStorageList, Link)) {\r
+    BrowserStorage = BROWSER_STORAGE_FROM_LINK (Link);\r
+    Link = GetNextNode (&gBrowserStorageList, Link);\r
+\r
+    if ((BrowserStorage->Type == StorageType) && CompareGuid (&BrowserStorage->Guid, StorageGuid)) {\r
+      if (StorageType == EFI_HII_VARSTORE_NAME_VALUE) {\r
+        if (BrowserStorage->HiiHandle == HiiHandle) {\r
+          return BrowserStorage;\r
+        }\r
+\r
+        continue;\r
+      }\r
+\r
+      ASSERT (StorageName != NULL);\r
+      if (StrCmp (BrowserStorage->Name, StorageName) == 0) {\r
+        if (StorageType == EFI_HII_VARSTORE_EFI_VARIABLE || StorageType == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
+          return BrowserStorage;\r
+        } else if (StorageType == EFI_HII_VARSTORE_BUFFER && BrowserStorage->HiiHandle == HiiHandle) {\r
+          return BrowserStorage;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Intialize the Global Storage.\r
+\r
+  @param  BrowserStorage              Pointer to the global storage.\r
+  @param  StorageType                Storage type.\r
+  @param  OpCodeData                 Binary data for this opcode.\r
+\r
+**/\r
+VOID\r
+IntializeBrowserStorage (\r
+  IN BROWSER_STORAGE       *BrowserStorage,\r
+  IN UINT8                 StorageType,\r
+  IN UINT8                 *OpCodeData\r
+  )\r
+{\r
+  switch (StorageType) {\r
+    case EFI_HII_VARSTORE_BUFFER:\r
+      CopyMem (&BrowserStorage->Guid, &((EFI_IFR_VARSTORE *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
+      CopyMem (&BrowserStorage->Size, &((EFI_IFR_VARSTORE *) OpCodeData)->Size, sizeof (UINT16));\r
+\r
+      BrowserStorage->Buffer     = AllocateZeroPool (BrowserStorage->Size);\r
+      BrowserStorage->EditBuffer = AllocateZeroPool (BrowserStorage->Size);\r
+      break;\r
+\r
+    case EFI_HII_VARSTORE_EFI_VARIABLE:\r
+    case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
+      CopyMem (&BrowserStorage->Guid,       &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Guid,       sizeof (EFI_GUID));\r
+      CopyMem (&BrowserStorage->Attributes, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Attributes, sizeof (UINT32));\r
+      CopyMem (&BrowserStorage->Size,       &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Size,       sizeof (UINT16));\r
+\r
+      if (StorageType ==  EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
+        BrowserStorage->Buffer     = AllocateZeroPool (BrowserStorage->Size);\r
+        BrowserStorage->EditBuffer = AllocateZeroPool (BrowserStorage->Size);\r
+      }\r
+      break;\r
+\r
+    case EFI_HII_VARSTORE_NAME_VALUE:\r
+      CopyMem (&BrowserStorage->Guid, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
+\r
+      InitializeListHead (&BrowserStorage->NameValueListHead);\r
+      break;\r
+\r
+    default:\r
+      break;\r
+  }\r
+}\r
+\r
+/**\r
+  Check whether exist device path info in the ConfigHdr string.\r
+\r
+  @param  String                 UEFI configuration string\r
+\r
+  @retval TRUE                   Device Path exist.\r
+  @retval FALSE                  Not exist device path info.\r
+\r
+**/\r
+BOOLEAN\r
+IsDevicePathExist (\r
+  IN  EFI_STRING                   String\r
+  )\r
+{\r
+  UINTN                    Length;\r
+\r
+  for (; (*String != 0 && StrnCmp (String, L"PATH=", StrLen (L"PATH=")) != 0); String++);\r
+  if (*String == 0) {\r
+    return FALSE;\r
+  }\r
+\r
+  String += StrLen (L"PATH=");\r
+  if (*String == 0) {\r
+    return FALSE;\r
+  }\r
+\r
+  for (Length = 0; *String != 0 && *String != L'&'; String++, Length++);\r
+  if (((Length + 1) / 2) < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {\r
+    return FALSE;\r
+  }\r
+\r
+  return TRUE;\r
+}\r
 \r
 /**\r
   Allocate a FORMSET_STORAGE data structure and insert to FormSet Storage List.\r
 \r
-  @param  FormSet                Pointer of the current FormSet\r
+  @param  FormSet                    Pointer of the current FormSet\r
+  @param  StorageType                Storage type.\r
+  @param  OpCodeData                 Binary data for this opcode.\r
 \r
   @return Pointer to a FORMSET_STORAGE data structure.\r
 \r
 **/\r
 FORMSET_STORAGE *\r
 CreateStorage (\r
-  IN FORM_BROWSER_FORMSET  *FormSet\r
+  IN FORM_BROWSER_FORMSET  *FormSet,\r
+  IN UINT8                 StorageType,\r
+  IN UINT8                 *OpCodeData\r
   )\r
 {\r
-  FORMSET_STORAGE  *Storage;\r
+  FORMSET_STORAGE         *Storage;\r
+  CHAR16                  *UnicodeString;\r
+  UINT16                  Index;\r
+  BROWSER_STORAGE         *BrowserStorage;\r
+  EFI_GUID                *StorageGuid;\r
+  CHAR8                   *StorageName;\r
+\r
+  UnicodeString = NULL;\r
+  StorageName   = NULL;\r
+  switch (StorageType) {\r
+    case EFI_HII_VARSTORE_BUFFER:\r
+      StorageGuid = (EFI_GUID *) (CHAR8*) &((EFI_IFR_VARSTORE *) OpCodeData)->Guid;\r
+      StorageName = (CHAR8 *) ((EFI_IFR_VARSTORE *) OpCodeData)->Name;\r
+      break;\r
+\r
+    case EFI_HII_VARSTORE_EFI_VARIABLE:\r
+    case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
+      StorageGuid = (EFI_GUID *) (CHAR8*) &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Guid;\r
+      StorageName = (CHAR8 *) ((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Name;\r
+      break;\r
+\r
+    default:\r
+      ASSERT (StorageType == EFI_HII_VARSTORE_NAME_VALUE);\r
+      StorageGuid = &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->Guid;\r
+      break;\r
+  }\r
+\r
+  if (StorageType != EFI_HII_VARSTORE_NAME_VALUE) {\r
+    ASSERT (StorageName != NULL);\r
+\r
+    UnicodeString = AllocateZeroPool (AsciiStrSize (StorageName) * 2);\r
+    ASSERT (UnicodeString != NULL);\r
+    for (Index = 0; StorageName[Index] != 0; Index++) {\r
+      UnicodeString[Index] = (CHAR16) StorageName[Index];\r
+    }\r
+  }\r
 \r
   Storage = AllocateZeroPool (sizeof (FORMSET_STORAGE));\r
   ASSERT (Storage != NULL);\r
   Storage->Signature = FORMSET_STORAGE_SIGNATURE;\r
-  InitializeListHead (&Storage->NameValueListHead);\r
   InsertTailList (&FormSet->StorageListHead, &Storage->Link);\r
 \r
+  BrowserStorage = FindStorageInList(StorageType, StorageGuid, UnicodeString, FormSet->HiiHandle);\r
+  if (BrowserStorage == NULL) {\r
+    BrowserStorage = AllocateZeroPool (sizeof (BROWSER_STORAGE));\r
+    ASSERT (BrowserStorage != NULL);\r
+\r
+    BrowserStorage->Signature = BROWSER_STORAGE_SIGNATURE;\r
+    InsertTailList (&gBrowserStorageList, &BrowserStorage->Link);\r
+\r
+    IntializeBrowserStorage (BrowserStorage, StorageType, OpCodeData);\r
+    BrowserStorage->Type = StorageType;\r
+    if (StorageType != EFI_HII_VARSTORE_NAME_VALUE) {\r
+      BrowserStorage->Name = UnicodeString;\r
+    }\r
+\r
+    BrowserStorage->HiiHandle = FormSet->HiiHandle;\r
+\r
+    BrowserStorage->Initialized = FALSE;\r
+  }\r
+\r
+  Storage->BrowserStorage = BrowserStorage;\r
+  InitializeConfigHdr (FormSet, Storage);\r
+  Storage->ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigHdr), Storage->ConfigHdr);\r
+  Storage->SpareStrLen = 0;\r
+\r
   return Storage;\r
 }\r
 \r
-\r
 /**\r
-  Create ConfigHdr string for a storage.\r
+  Get Formset_storage base on the input varstoreid info.\r
 \r
-  @param  FormSet                Pointer of the current FormSet\r
-  @param  Storage                Pointer of the storage\r
+  @param  FormSet                Pointer of the current FormSet.\r
+  @param  VarStoreId             Varstore ID info.\r
 \r
-  @retval EFI_SUCCESS            Initialize ConfigHdr success\r
+  @return Pointer to a FORMSET_STORAGE data structure.\r
 \r
 **/\r
-EFI_STATUS\r
-InitializeConfigHdr (\r
+FORMSET_STORAGE *\r
+GetFstStgFromVarId (\r
   IN FORM_BROWSER_FORMSET  *FormSet,\r
-  IN OUT FORMSET_STORAGE   *Storage\r
+  IN EFI_VARSTORE_ID       VarStoreId\r
   )\r
 {\r
-  EFI_STATUS  Status;\r
-  UINTN       StrBufferLen;\r
-  CHAR16      *Name;\r
+  FORMSET_STORAGE  *FormsetStorage;\r
+  LIST_ENTRY       *Link;\r
+  BOOLEAN          Found;\r
 \r
-  if (Storage->Type == EFI_HII_VARSTORE_BUFFER) {\r
-    Name = Storage->Name;\r
-  } else {\r
-    Name = NULL;\r
-  }\r
+  Found = FALSE;\r
+  FormsetStorage = NULL;\r
+  //\r
+  // Find Formset Storage for this Question\r
+  //\r
+  Link = GetFirstNode (&FormSet->StorageListHead);\r
+  while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+    FormsetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
 \r
-  StrBufferLen = 0;\r
-  Status = ConstructConfigHdr (\r
-             Storage->ConfigHdr,\r
-             &StrBufferLen,\r
-             &Storage->Guid,\r
-             Name,\r
-             FormSet->DriverHandle\r
-             );\r
-  if (Status == EFI_BUFFER_TOO_SMALL) {\r
-    Storage->ConfigHdr = AllocateZeroPool (StrBufferLen);\r
-    Status = ConstructConfigHdr (\r
-               Storage->ConfigHdr,\r
-               &StrBufferLen,\r
-               &Storage->Guid,\r
-               Name,\r
-               FormSet->DriverHandle\r
-               );\r
-  }\r
+    if (FormsetStorage->VarStoreId == VarStoreId) {\r
+      Found = TRUE;\r
+      break;\r
+    }\r
 \r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
+    Link = GetNextNode (&FormSet->StorageListHead, Link);\r
   }\r
 \r
-  Storage->ConfigRequest = AllocateCopyPool (StrBufferLen, Storage->ConfigHdr);\r
-  Storage->SpareStrLen = 0;\r
-\r
-  return EFI_SUCCESS;\r
+  return Found ? FormsetStorage : NULL;\r
 }\r
 \r
+/**\r
+  Get Formset_storage base on the input browser storage.\r
+\r
+  More than one formsets may share the same browser storage,\r
+  this function just get the first formset storage which\r
+  share the browser storage.\r
+\r
+  @param  Storage              browser storage info.\r
+\r
+  @return Pointer to a FORMSET_STORAGE data structure.\r
+  \r
+\r
+**/\r
+FORMSET_STORAGE *\r
+GetFstStgFromBrsStg (\r
+  IN BROWSER_STORAGE       *Storage\r
+  )\r
+{\r
+  FORMSET_STORAGE      *FormsetStorage;\r
+  LIST_ENTRY           *Link;\r
+  LIST_ENTRY           *FormsetLink;\r
+  FORM_BROWSER_FORMSET *FormSet;\r
+  BOOLEAN              Found;\r
+\r
+  Found = FALSE;\r
+  FormsetStorage = NULL;\r
+\r
+  FormsetLink = GetFirstNode (&gBrowserFormSetList);\r
+  while (!IsNull (&gBrowserFormSetList, FormsetLink)) {\r
+    FormSet = FORM_BROWSER_FORMSET_FROM_LINK (FormsetLink);\r
+    FormsetLink = GetNextNode (&gBrowserFormSetList, FormsetLink);\r
+\r
+    Link = GetFirstNode (&FormSet->StorageListHead);\r
+    while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+      FormsetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
+      Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+\r
+      if (FormsetStorage->BrowserStorage == Storage) {\r
+        Found = TRUE;\r
+        break;\r
+      }\r
+    }\r
+\r
+    if (Found) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  return Found ? FormsetStorage : NULL;\r
+}\r
 \r
 /**\r
   Initialize Request Element of a Question. <RequestElement> ::= '&'<BlockName> | '&'<Label>\r
 \r
   @param  FormSet                Pointer of the current FormSet.\r
   @param  Question               The Question to be initialized.\r
+  @param  Form                   Pointer of the current form.\r
 \r
   @retval EFI_SUCCESS            Function success.\r
   @retval EFI_INVALID_PARAMETER  No storage associated with the Question.\r
@@ -380,14 +675,19 @@ InitializeConfigHdr (
 EFI_STATUS\r
 InitializeRequestElement (\r
   IN OUT FORM_BROWSER_FORMSET     *FormSet,\r
-  IN OUT FORM_BROWSER_STATEMENT   *Question\r
+  IN OUT FORM_BROWSER_STATEMENT   *Question,\r
+  IN OUT FORM_BROWSER_FORM        *Form\r
   )\r
 {\r
-  FORMSET_STORAGE  *Storage;\r
+  BROWSER_STORAGE  *Storage;\r
+  FORMSET_STORAGE  *FormsetStorage;\r
   UINTN            StrLen;\r
   UINTN            StringSize;\r
   CHAR16           *NewStr;\r
   CHAR16           RequestElement[30];\r
+  LIST_ENTRY       *Link;\r
+  BOOLEAN          Find;\r
+  FORM_BROWSER_CONFIG_REQUEST  *ConfigInfo;\r
 \r
   Storage = Question->Storage;\r
   if (Storage == NULL) {\r
@@ -405,11 +705,12 @@ InitializeRequestElement (
   //\r
   // Prepare <RequestElement>\r
   //\r
-  if (Storage->Type == EFI_HII_VARSTORE_BUFFER) {\r
+  if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
+      Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
     StrLen = UnicodeSPrint (\r
                RequestElement,\r
                30 * sizeof (CHAR16),\r
-               L"&OFFSET=%x&WIDTH=%x",\r
+               L"&OFFSET=%04x&WIDTH=%04x",\r
                Question->VarStoreInfo.VarOffset,\r
                Question->StorageWidth\r
                );\r
@@ -426,28 +727,83 @@ InitializeRequestElement (
     return EFI_SUCCESS;\r
   }\r
 \r
+  //\r
+  // Find Formset Storage for this Question\r
+  //\r
+  FormsetStorage = GetFstStgFromVarId(FormSet, Question->VarStoreId);\r
+  ASSERT (FormsetStorage != NULL);\r
+\r
   //\r
   // Append <RequestElement> to <ConfigRequest>\r
   //\r
-  if (StrLen > Storage->SpareStrLen) {\r
+  if (StrLen > FormsetStorage->SpareStrLen) {\r
     //\r
     // Old String buffer is not sufficient for RequestElement, allocate a new one\r
     //\r
-    StringSize = (Storage->ConfigRequest != NULL) ? StrSize (Storage->ConfigRequest) : sizeof (CHAR16);\r
+    StringSize = (FormsetStorage->ConfigRequest != NULL) ? StrSize (FormsetStorage->ConfigRequest) : sizeof (CHAR16);\r
     NewStr = AllocateZeroPool (StringSize + CONFIG_REQUEST_STRING_INCREMENTAL * sizeof (CHAR16));\r
     ASSERT (NewStr != NULL);\r
-    if (Storage->ConfigRequest != NULL) {\r
-      CopyMem (NewStr, Storage->ConfigRequest, StringSize);\r
-      FreePool (Storage->ConfigRequest);\r
+    if (FormsetStorage->ConfigRequest != NULL) {\r
+      CopyMem (NewStr, FormsetStorage->ConfigRequest, StringSize);\r
+      FreePool (FormsetStorage->ConfigRequest);\r
     }\r
-    Storage->ConfigRequest = NewStr;\r
-    Storage->SpareStrLen   = CONFIG_REQUEST_STRING_INCREMENTAL;\r
+    FormsetStorage->ConfigRequest = NewStr;\r
+    FormsetStorage->SpareStrLen   = CONFIG_REQUEST_STRING_INCREMENTAL;\r
   }\r
 \r
-  StrCat (Storage->ConfigRequest, RequestElement);\r
-  Storage->ElementCount++;\r
-  Storage->SpareStrLen -= StrLen;\r
+  StrCat (FormsetStorage->ConfigRequest, RequestElement);\r
+  FormsetStorage->ElementCount++;\r
+  FormsetStorage->SpareStrLen -= StrLen;\r
+\r
+  //\r
+  // Update the Config Request info saved in the form.\r
+  //\r
+  ConfigInfo = NULL;\r
+  Find       = FALSE;\r
+  Link = GetFirstNode (&Form->ConfigRequestHead);\r
+  while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
+    ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
+\r
+    if (ConfigInfo != NULL && ConfigInfo->Storage == FormsetStorage->BrowserStorage) {\r
+      Find = TRUE;\r
+      break;\r
+    }\r
+\r
+    Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
+  }\r
+\r
+  if (!Find) {\r
+    ConfigInfo = AllocateZeroPool(sizeof (FORM_BROWSER_CONFIG_REQUEST));\r
+    ASSERT (ConfigInfo != NULL);\r
+    ConfigInfo->Signature     = FORM_BROWSER_CONFIG_REQUEST_SIGNATURE;\r
+    ConfigInfo->ConfigRequest = AllocateCopyPool (StrSize (FormsetStorage->ConfigHdr), FormsetStorage->ConfigHdr);\r
+    ASSERT (ConfigInfo->ConfigRequest != NULL);\r
+    ConfigInfo->SpareStrLen   = 0;\r
+    ConfigInfo->Storage       = FormsetStorage->BrowserStorage;\r
+    InsertTailList(&Form->ConfigRequestHead, &ConfigInfo->Link);\r
+  }\r
+\r
+  //\r
+  // Append <RequestElement> to <ConfigRequest>\r
+  //\r
+  if (StrLen > ConfigInfo->SpareStrLen) {\r
+    //\r
+    // Old String buffer is not sufficient for RequestElement, allocate a new one\r
+    //\r
+    StringSize = (ConfigInfo->ConfigRequest != NULL) ? StrSize (ConfigInfo->ConfigRequest) : sizeof (CHAR16);\r
+    NewStr = AllocateZeroPool (StringSize + CONFIG_REQUEST_STRING_INCREMENTAL * sizeof (CHAR16));\r
+    ASSERT (NewStr != NULL);\r
+    if (ConfigInfo->ConfigRequest != NULL) {\r
+      CopyMem (NewStr, ConfigInfo->ConfigRequest, StringSize);\r
+      FreePool (ConfigInfo->ConfigRequest);\r
+    }\r
+    ConfigInfo->ConfigRequest = NewStr;\r
+    ConfigInfo->SpareStrLen   = CONFIG_REQUEST_STRING_INCREMENTAL;\r
+  }\r
 \r
+  StrCat (ConfigInfo->ConfigRequest, RequestElement);\r
+  ConfigInfo->ElementCount++;\r
+  ConfigInfo->SpareStrLen -= StrLen;\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -465,6 +821,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
@@ -474,6 +832,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
@@ -482,7 +853,6 @@ DestroyExpression (
   FreePool (Expression);\r
 }\r
 \r
-\r
 /**\r
   Free resources of a storage.\r
 \r
@@ -494,43 +864,10 @@ DestroyStorage (
   IN FORMSET_STORAGE   *Storage\r
   )\r
 {\r
-  LIST_ENTRY         *Link;\r
-  NAME_VALUE_NODE    *NameValueNode;\r
-\r
   if (Storage == NULL) {\r
     return;\r
   }\r
 \r
-  if (Storage->Name != NULL) {\r
-    FreePool (Storage->Name);\r
-  }\r
-  if (Storage->Buffer != NULL) {\r
-    FreePool (Storage->Buffer);\r
-  }\r
-  if (Storage->EditBuffer != NULL) {\r
-    FreePool (Storage->EditBuffer);\r
-  }\r
-\r
-  while (!IsListEmpty (&Storage->NameValueListHead)) {\r
-    Link = GetFirstNode (&Storage->NameValueListHead);\r
-    NameValueNode = NAME_VALUE_NODE_FROM_LINK (Link);\r
-    RemoveEntryList (&NameValueNode->Link);\r
-\r
-    if (NameValueNode->Name != NULL) {\r
-      FreePool (NameValueNode->Name);\r
-    }\r
-    if (NameValueNode->Value != NULL) {\r
-      FreePool (NameValueNode->Value);\r
-    }\r
-    if (NameValueNode->EditValue != NULL) {\r
-      FreePool (NameValueNode->EditValue);\r
-    }\r
-    FreePool (NameValueNode);\r
-  }\r
-\r
-  if (Storage->ConfigHdr != NULL) {\r
-    FreePool (Storage->ConfigHdr);\r
-  }\r
   if (Storage->ConfigRequest != NULL) {\r
     FreePool (Storage->ConfigRequest);\r
   }\r
@@ -542,11 +879,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
@@ -563,6 +902,9 @@ DestroyStatement (
     Default = QUESTION_DEFAULT_FROM_LINK (Link);\r
     RemoveEntryList (&Default->Link);\r
 \r
+    if (Default->Value.Buffer != NULL) {\r
+      FreePool (Default->Value.Buffer);\r
+    }\r
     FreePool (Default);\r
   }\r
 \r
@@ -572,6 +914,9 @@ DestroyStatement (
   while (!IsListEmpty (&Statement->OptionListHead)) {\r
     Link = GetFirstNode (&Statement->OptionListHead);\r
     Option = QUESTION_OPTION_FROM_LINK (Link);\r
+    if (Option->SuppressExpression != NULL) {\r
+      FreePool (Option->SuppressExpression);\r
+    }\r
     RemoveEntryList (&Option->Link);\r
 \r
     FreePool (Option);\r
@@ -599,29 +944,53 @@ DestroyStatement (
     DestroyExpression (Expression);\r
   }\r
 \r
+  //\r
+  // Free WarningIf List\r
+  //\r
+  while (!IsListEmpty (&Statement->WarningListHead)) {\r
+    Link = GetFirstNode (&Statement->WarningListHead);\r
+    Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
+    RemoveEntryList (&Expression->Link);\r
+\r
+    DestroyExpression (Expression);\r
+  }\r
+\r
+  if (Statement->Expression != NULL) {\r
+    FreePool (Statement->Expression);\r
+  }\r
+\r
   if (Statement->VariableName != NULL) {\r
     FreePool (Statement->VariableName);\r
   }\r
   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
   FORM_EXPRESSION         *Expression;\r
   FORM_BROWSER_STATEMENT  *Statement;\r
+  FORM_BROWSER_CONFIG_REQUEST  *ConfigInfo;\r
 \r
   //\r
   // Free Form Expressions\r
@@ -642,9 +1011,27 @@ DestroyForm (
     Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
     RemoveEntryList (&Statement->Link);\r
 \r
-    DestroyStatement (Statement);\r
+    DestroyStatement (FormSet, Statement);\r
   }\r
 \r
+  //\r
+  // Free ConfigRequest string.\r
+  //\r
+  while (!IsListEmpty (&Form->ConfigRequestHead)) {\r
+    Link = GetFirstNode (&Form->ConfigRequestHead);\r
+    ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);\r
+    RemoveEntryList (&ConfigInfo->Link);\r
+\r
+    FreePool (ConfigInfo->ConfigRequest);\r
+    FreePool (ConfigInfo);\r
+  }\r
+\r
+  if (Form->SuppressExpression != NULL) {\r
+    FreePool (Form->SuppressExpression);\r
+  }\r
+\r
+  UiFreeMenuList (&Form->FormViewListHead);\r
+\r
   //\r
   // Free this Form\r
   //\r
@@ -666,8 +1053,17 @@ DestroyFormSet (
   LIST_ENTRY            *Link;\r
   FORMSET_STORAGE       *Storage;\r
   FORMSET_DEFAULTSTORE  *DefaultStore;\r
+  FORM_EXPRESSION       *Expression;\r
   FORM_BROWSER_FORM     *Form;\r
 \r
+  if (FormSet->IfrBinaryData == NULL) {\r
+    //\r
+    // Uninitialized FormSet\r
+    //\r
+    FreePool (FormSet);\r
+    return;\r
+  }\r
+\r
   //\r
   // Free IFR binary buffer\r
   //\r
@@ -699,6 +1095,17 @@ DestroyFormSet (
     }\r
   }\r
 \r
+  //\r
+  // Free Formset Expressions\r
+  //\r
+  while (!IsListEmpty (&FormSet->ExpressionListHead)) {\r
+    Link = GetFirstNode (&FormSet->ExpressionListHead);\r
+    Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
+    RemoveEntryList (&Expression->Link);\r
+\r
+    DestroyExpression (Expression);\r
+  }\r
+\r
   //\r
   // Free Forms\r
   //\r
@@ -708,7 +1115,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
@@ -738,18 +1145,71 @@ 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_VERSION_OP)\r
-     ) {\r
+      (Operand == EFI_IFR_MAP_OP)      ||\r
+      (Operand == EFI_IFR_VERSION_OP)  ||\r
+      (Operand == EFI_IFR_SECURITY_OP) ||\r
+      (Operand == EFI_IFR_MATCH2_OP)) {\r
     return TRUE;\r
   } else {\r
     return FALSE;\r
   }\r
 }\r
 \r
+/**\r
+  Tell whether this Operand is an Statement OpCode.\r
+\r
+  @param  Operand                Operand of an IFR OpCode.\r
+\r
+  @retval TRUE                   This is an Statement OpCode.\r
+  @retval FALSE                  Not an Statement OpCode.\r
+\r
+**/\r
+BOOLEAN\r
+IsStatementOpCode (\r
+  IN UINT8              Operand\r
+  )\r
+{\r
+  if ((Operand == EFI_IFR_SUBTITLE_OP) ||\r
+      (Operand == EFI_IFR_TEXT_OP) ||\r
+      (Operand == EFI_IFR_RESET_BUTTON_OP) ||\r
+      (Operand == EFI_IFR_REF_OP) ||\r
+      (Operand == EFI_IFR_ACTION_OP) ||\r
+      (Operand == EFI_IFR_NUMERIC_OP) ||\r
+      (Operand == EFI_IFR_ORDERED_LIST_OP) ||\r
+      (Operand == EFI_IFR_CHECKBOX_OP) ||\r
+      (Operand == EFI_IFR_STRING_OP) ||\r
+      (Operand == EFI_IFR_PASSWORD_OP) ||\r
+      (Operand == EFI_IFR_DATE_OP) ||\r
+      (Operand == EFI_IFR_TIME_OP) ||\r
+      (Operand == EFI_IFR_GUID_OP) ||\r
+      (Operand == EFI_IFR_ONE_OF_OP)) {\r
+    return TRUE;\r
+  } else {\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+/**\r
+  Tell whether this Operand is an known OpCode.\r
+\r
+  @param  Operand                Operand of an IFR OpCode.\r
+\r
+  @retval TRUE                   This is an Statement OpCode.\r
+  @retval FALSE                  Not an Statement OpCode.\r
+\r
+**/\r
+BOOLEAN\r
+IsUnKnownOpCode (\r
+  IN UINT8              Operand\r
+  )\r
+{\r
+  return Operand > EFI_IFR_MATCH2_OP ? TRUE : FALSE;\r
+}\r
 \r
 /**\r
   Calculate number of Statemens(Questions) and Expression OpCodes.\r
@@ -809,9 +1269,9 @@ ParseOpCodes (
   )\r
 {\r
   EFI_STATUS              Status;\r
-  UINT16                  Index;\r
   FORM_BROWSER_FORM       *CurrentForm;\r
   FORM_BROWSER_STATEMENT  *CurrentStatement;\r
+  FORM_BROWSER_STATEMENT  *ParentStatement;\r
   EXPRESSION_OPCODE       *ExpressionOpCode;\r
   FORM_EXPRESSION         *CurrentExpression;\r
   UINT8                   Operand;\r
@@ -824,25 +1284,30 @@ ParseOpCodes (
   FORMSET_DEFAULTSTORE    *DefaultStore;\r
   QUESTION_DEFAULT        *CurrentDefault;\r
   QUESTION_OPTION         *CurrentOption;\r
-  CHAR8                   *AsciiString;\r
+  UINT8                   Width;\r
   UINT16                  NumberOfStatement;\r
   UINT16                  NumberOfExpression;\r
   EFI_IMAGE_ID            *ImageId;\r
+  BOOLEAN                 SuppressForQuestion;\r
   BOOLEAN                 SuppressForOption;\r
-  BOOLEAN                 InScopeOptionSuppress;\r
-  FORM_EXPRESSION         *OptionSuppressExpression;\r
-  BOOLEAN                 InScopeDisable;\r
   UINT16                  DepthOfDisable;\r
   BOOLEAN                 OpCodeDisabled;\r
   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
+  BOOLEAN                 InScopeDisable;\r
+  INTN                    ConditionalExprCount;\r
+  BOOLEAN                 InUnknownScope;\r
+  UINT8                   UnknownDepth;\r
 \r
-  mInScopeSubtitle         = FALSE;\r
+  SuppressForQuestion      = FALSE;\r
   SuppressForOption        = FALSE;\r
-  mInScopeSuppress         = FALSE;\r
-  InScopeOptionSuppress    = FALSE;\r
-  mInScopeGrayOut          = FALSE;\r
   InScopeDisable           = FALSE;\r
   DepthOfDisable           = 0;\r
   OpCodeDisabled           = FALSE;\r
@@ -851,8 +1316,16 @@ ParseOpCodes (
   CurrentExpression        = NULL;\r
   CurrentDefault           = NULL;\r
   CurrentOption            = NULL;\r
-  OptionSuppressExpression = NULL;\r
   ImageId                  = NULL;\r
+  MapMethod                = NULL;\r
+  MapScopeDepth            = 0;\r
+  Link                     = NULL;\r
+  VarStorage               = NULL;\r
+  MapExpressionList        = NULL;\r
+  TempVarstoreId           = 0;\r
+  ConditionalExprCount     = 0;\r
+  InUnknownScope           = FALSE;\r
+  UnknownDepth             = 0;\r
 \r
   //\r
   // Get the number of Statements and Expressions\r
@@ -860,6 +1333,7 @@ ParseOpCodes (
   CountOpCodes (FormSet, &NumberOfStatement, &NumberOfExpression);\r
 \r
   mStatementIndex = 0;\r
+  mUsedQuestionId = 1;\r
   FormSet->StatementBuffer = AllocateZeroPool (NumberOfStatement * sizeof (FORM_BROWSER_STATEMENT));\r
   if (FormSet->StatementBuffer == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
@@ -871,12 +1345,18 @@ ParseOpCodes (
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
+  InitializeListHead (&FormSet->StatementListOSF);\r
   InitializeListHead (&FormSet->StorageListHead);\r
+  InitializeListHead (&FormSet->SaveFailStorageListHead);\r
   InitializeListHead (&FormSet->DefaultStoreListHead);\r
   InitializeListHead (&FormSet->FormListHead);\r
+  InitializeListHead (&FormSet->ExpressionListHead);\r
+  ResetCurrentExpressionStack ();\r
+  ResetMapExpressionListStack ();\r
 \r
   CurrentForm = NULL;\r
   CurrentStatement = NULL;\r
+  ParentStatement  = NULL;\r
 \r
   ResetScopeStack ();\r
 \r
@@ -889,6 +1369,31 @@ ParseOpCodes (
     Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;\r
     Scope = ((EFI_IFR_OP_HEADER *) OpCodeData)->Scope;\r
 \r
+    if (InUnknownScope) {\r
+      if (Operand == EFI_IFR_END_OP) {\r
+        UnknownDepth --;\r
+\r
+        if (UnknownDepth == 0) {\r
+          InUnknownScope = FALSE;\r
+        }\r
+      } else {\r
+        if (Scope != 0) {\r
+          UnknownDepth ++;\r
+        }\r
+      }\r
+\r
+      continue;\r
+    }\r
+\r
+    if (IsUnKnownOpCode(Operand)) {\r
+      if (Scope != 0) {\r
+        InUnknownScope = TRUE;\r
+        UnknownDepth ++;\r
+      }\r
+\r
+      continue;\r
+    }\r
+\r
     //\r
     // If scope bit set, push onto scope stack\r
     //\r
@@ -942,10 +1447,10 @@ ParseOpCodes (
         CopyMem (&ExpressionOpCode->QuestionId2, &((EFI_IFR_EQ_ID_ID *) OpCodeData)->QuestionId2, sizeof (EFI_QUESTION_ID));\r
         break;\r
 \r
-      case EFI_IFR_EQ_ID_LIST_OP:\r
-        CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));\r
-        CopyMem (&ExpressionOpCode->ListLength, &((EFI_IFR_EQ_ID_LIST *) OpCodeData)->ListLength, sizeof (UINT16));\r
-        ExpressionOpCode->ValueList = AllocateCopyPool (ExpressionOpCode->ListLength * sizeof (UINT16), &((EFI_IFR_EQ_ID_LIST *) OpCodeData)->ValueList);\r
+      case EFI_IFR_EQ_ID_VAL_LIST_OP:\r
+        CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));\r
+        CopyMem (&ExpressionOpCode->ListLength, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->ListLength, sizeof (UINT16));\r
+        ExpressionOpCode->ValueList = AllocateCopyPool (ExpressionOpCode->ListLength * sizeof (UINT16), &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->ValueList);\r
         break;\r
 \r
       case EFI_IFR_TO_STRING_OP:\r
@@ -967,12 +1472,99 @@ ParseOpCodes (
         break;\r
 \r
       case EFI_IFR_THIS_OP:\r
-        ASSERT (CurrentStatement != NULL);\r
-        ExpressionOpCode->QuestionId = CurrentStatement->QuestionId;\r
+        ASSERT (ParentStatement != NULL);\r
+        ExpressionOpCode->QuestionId = ParentStatement->QuestionId;\r
+        break;\r
+\r
+      case EFI_IFR_SECURITY_OP:\r
+        CopyMem (&ExpressionOpCode->Guid, &((EFI_IFR_SECURITY *) OpCodeData)->Permissions, sizeof (EFI_GUID));\r
+        break;\r
+\r
+      case EFI_IFR_MATCH2_OP:\r
+        CopyMem (&ExpressionOpCode->Guid, &((EFI_IFR_MATCH2 *) OpCodeData)->SyntaxType, 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->BrowserStorage;\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_REF:\r
+          ExpressionOpCode->ValueWidth = (UINT8) sizeof (EFI_IFR_REF);\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_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));\r
+        CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));\r
         break;\r
 \r
       case EFI_IFR_QUESTION_REF3_OP:\r
@@ -1034,7 +1626,7 @@ ParseOpCodes (
         break;\r
 \r
       case EFI_IFR_UNDEFINED_OP:\r
-        Value->Type = EFI_IFR_TYPE_OTHER;\r
+        Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
         break;\r
 \r
       case EFI_IFR_VERSION_OP:\r
@@ -1045,10 +1637,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, OpCodeData);\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
@@ -1056,21 +1676,16 @@ ParseOpCodes (
         //\r
         SingleOpCodeExpression = FALSE;\r
 \r
-        if (InScopeDisable) {\r
+        if (InScopeDisable && CurrentForm == NULL) {\r
           //\r
-          // Evaluate DisableIf expression\r
+          // This is DisableIf expression for Form, it should be a constant expression\r
           //\r
           Status = EvaluateExpression (FormSet, CurrentForm, CurrentExpression);\r
           if (EFI_ERROR (Status)) {\r
             return Status;\r
           }\r
 \r
-          ASSERT (CurrentExpression != NULL);\r
-          if (CurrentExpression->Result.Type != EFI_IFR_TYPE_BOOLEAN) {\r
-            return EFI_INVALID_PARAMETER;\r
-          }\r
-\r
-          OpCodeDisabled = CurrentExpression->Result.Value.b;\r
+          OpCodeDisabled = IsTrue(&CurrentExpression->Result);\r
         }\r
 \r
         CurrentExpression = NULL;\r
@@ -1086,7 +1701,7 @@ ParseOpCodes (
 \r
     case EFI_IFR_FORM_SET_OP:\r
       //\r
-      // check the formset GUID\r
+      // Check the formset GUID\r
       //\r
       if (CompareMem (&FormSet->Guid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID)) != 0) {\r
         return EFI_INVALID_PARAMETER;\r
@@ -1094,20 +1709,117 @@ ParseOpCodes (
 \r
       CopyMem (&FormSet->FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID));\r
       CopyMem (&FormSet->Help,         &((EFI_IFR_FORM_SET *) OpCodeData)->Help,         sizeof (EFI_STRING_ID));\r
+\r
+      if (OpCodeLength > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) {\r
+        //\r
+        // The formset OpCode contains ClassGuid\r
+        //\r
+        FormSet->NumberOfClassGuid = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3);\r
+        CopyMem (FormSet->ClassGuid, OpCodeData + sizeof (EFI_IFR_FORM_SET), FormSet->NumberOfClassGuid * sizeof (EFI_GUID));\r
+      }\r
       break;\r
 \r
     case EFI_IFR_FORM_OP:\r
       //\r
-      // Create a new Form for this FormSet\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
+      InitializeListHead (&CurrentForm->ConfigRequestHead);\r
+      InitializeListHead (&CurrentForm->FormViewListHead);\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
+      ConditionalExprCount = GetConditionalExpressionCount(ExpressForm);\r
+      if ( ConditionalExprCount > 0) {\r
+        //\r
+        // Form is inside of suppressif\r
+        //\r
+        CurrentForm->SuppressExpression = (FORM_EXPRESSION_LIST *) AllocatePool( \r
+                                                 (UINTN) (sizeof(FORM_EXPRESSION_LIST) + ((ConditionalExprCount -1) * sizeof(FORM_EXPRESSION *))));\r
+        ASSERT (CurrentForm->SuppressExpression != NULL);\r
+        CurrentForm->SuppressExpression->Count     = (UINTN) ConditionalExprCount;\r
+        CurrentForm->SuppressExpression->Signature = FORM_EXPRESSION_LIST_SIGNATURE;\r
+        CopyMem (CurrentForm->SuppressExpression->Expression, GetConditionalExpressionList(ExpressForm), (UINTN) (sizeof (FORM_EXPRESSION *) * ConditionalExprCount));\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
+    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
+      InitializeListHead (&CurrentForm->ConfigRequestHead);\r
+      InitializeListHead (&CurrentForm->FormViewListHead);\r
+\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
-      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
+      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
-      CopyMem (&CurrentForm->FormId,    &((EFI_IFR_FORM *) OpCodeData)->FormId,    sizeof (UINT16));\r
-      CopyMem (&CurrentForm->FormTitle, &((EFI_IFR_FORM *) OpCodeData)->FormTitle, sizeof (EFI_STRING_ID));\r
+      ConditionalExprCount = GetConditionalExpressionCount(ExpressForm);\r
+      if ( ConditionalExprCount > 0) {\r
+        //\r
+        // Form is inside of suppressif\r
+        //\r
+        CurrentForm->SuppressExpression = (FORM_EXPRESSION_LIST *) AllocatePool( \r
+                                                 (UINTN) (sizeof(FORM_EXPRESSION_LIST) + ((ConditionalExprCount -1) * sizeof(FORM_EXPRESSION *))));\r
+        ASSERT (CurrentForm->SuppressExpression != NULL);\r
+        CurrentForm->SuppressExpression->Count     = (UINTN) ConditionalExprCount;\r
+        CurrentForm->SuppressExpression->Signature = FORM_EXPRESSION_LIST_SIGNATURE;\r
+        CopyMem (CurrentForm->SuppressExpression->Expression, GetConditionalExpressionList(ExpressForm), (UINTN) (sizeof (FORM_EXPRESSION *) * ConditionalExprCount));\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
@@ -1122,55 +1834,34 @@ ParseOpCodes (
       //\r
       // Create a buffer Storage for this FormSet\r
       //\r
-      Storage = CreateStorage (FormSet);\r
-      Storage->Type = EFI_HII_VARSTORE_BUFFER;\r
-\r
+      Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_BUFFER, OpCodeData);\r
       CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));\r
-      CopyMem (&Storage->Guid,       &((EFI_IFR_VARSTORE *) OpCodeData)->Guid,       sizeof (EFI_GUID));\r
-      CopyMem (&Storage->Size,       &((EFI_IFR_VARSTORE *) OpCodeData)->Size,       sizeof (UINT16));\r
-\r
-      Storage->Buffer = AllocateZeroPool (Storage->Size);\r
-      Storage->EditBuffer = AllocateZeroPool (Storage->Size);\r
-\r
-      AsciiString = (CHAR8 *) ((EFI_IFR_VARSTORE *) OpCodeData)->Name;\r
-      Storage->Name = AllocateZeroPool (AsciiStrSize (AsciiString) * 2);\r
-      ASSERT (Storage->Name != NULL);\r
-      for (Index = 0; AsciiString[Index] != 0; Index++) {\r
-        Storage->Name[Index] = (CHAR16) AsciiString[Index];\r
-      }\r
-\r
-      //\r
-      // Initialize <ConfigHdr>\r
-      //\r
-      InitializeConfigHdr (FormSet, Storage);\r
       break;\r
 \r
     case EFI_IFR_VARSTORE_NAME_VALUE_OP:\r
       //\r
       // Create a name/value Storage for this FormSet\r
       //\r
-      Storage = CreateStorage (FormSet);\r
-      Storage->Type = EFI_HII_VARSTORE_NAME_VALUE;\r
-\r
+      Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_NAME_VALUE, OpCodeData);\r
       CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));\r
-      CopyMem (&Storage->Guid,       &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->Guid,       sizeof (EFI_GUID));\r
-\r
-      //\r
-      // Initialize <ConfigHdr>\r
-      //\r
-      InitializeConfigHdr (FormSet, Storage);\r
       break;\r
 \r
     case EFI_IFR_VARSTORE_EFI_OP:\r
       //\r
       // Create a EFI variable Storage for this FormSet\r
       //\r
-      Storage = CreateStorage (FormSet);\r
-      Storage->Type = EFI_HII_VARSTORE_EFI_VARIABLE;\r
-\r
+      if (OpCodeLength < sizeof (EFI_IFR_VARSTORE_EFI)) {\r
+        //\r
+        // Create efi varstore with format follow UEFI spec before 2.3.1.\r
+        //\r
+        Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_EFI_VARIABLE, OpCodeData);\r
+      } else {\r
+        //\r
+        // Create efi varstore with format follow UEFI spec 2.3.1 and later.\r
+        //\r
+        Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER, OpCodeData);\r
+      }\r
       CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));\r
-      CopyMem (&Storage->Guid,       &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Guid,       sizeof (EFI_GUID));\r
-      CopyMem (&Storage->Attributes, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Attributes, sizeof (UINT32));\r
       break;\r
 \r
     //\r
@@ -1196,27 +1887,32 @@ ParseOpCodes (
     case EFI_IFR_SUBTITLE_OP:\r
       CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);\r
       ASSERT (CurrentStatement != NULL);\r
-      \r
-      CurrentStatement->Flags = ((EFI_IFR_SUBTITLE *) OpCodeData)->Flags;\r
 \r
-      if (Scope != 0) {\r
-        mInScopeSubtitle = TRUE;\r
-      }\r
+      CurrentStatement->Flags = ((EFI_IFR_SUBTITLE *) OpCodeData)->Flags;\r
+      CurrentStatement->FakeQuestionId = mUsedQuestionId++;\r
       break;\r
 \r
     case EFI_IFR_TEXT_OP:\r
       CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);\r
       ASSERT (CurrentStatement != NULL);\r
-\r
+      CurrentStatement->FakeQuestionId = mUsedQuestionId++;\r
       CopyMem (&CurrentStatement->TextTwo, &((EFI_IFR_TEXT *) OpCodeData)->TextTwo, sizeof (EFI_STRING_ID));\r
       break;\r
 \r
+    case EFI_IFR_RESET_BUTTON_OP:\r
+      CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);\r
+      ASSERT (CurrentStatement != NULL);\r
+      CurrentStatement->FakeQuestionId = mUsedQuestionId++;\r
+      CopyMem (&CurrentStatement->DefaultId, &((EFI_IFR_RESET_BUTTON *) OpCodeData)->DefaultId, sizeof (EFI_DEFAULT_ID));\r
+      break;\r
+\r
     //\r
     // Questions\r
     //\r
     case EFI_IFR_ACTION_OP:\r
       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
       ASSERT (CurrentStatement != NULL);\r
+      CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_ACTION;\r
 \r
       if (OpCodeLength == sizeof (EFI_IFR_ACTION_1)) {\r
         //\r
@@ -1228,32 +1924,34 @@ ParseOpCodes (
       }\r
       break;\r
 \r
-    case EFI_IFR_RESET_BUTTON_OP:\r
-      CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
-\r
-      CopyMem (&CurrentStatement->DefaultId, &((EFI_IFR_RESET_BUTTON *) OpCodeData)->DefaultId, sizeof (EFI_DEFAULT_ID));\r
-      break;\r
-\r
     case EFI_IFR_REF_OP:\r
       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
+      ASSERT (CurrentStatement != NULL);\r
+      Value = &CurrentStatement->HiiValue;\r
+      Value->Type = EFI_IFR_TYPE_REF;\r
+      if (OpCodeLength >= sizeof (EFI_IFR_REF)) {\r
+        CopyMem (&Value->Value.ref.FormId, &((EFI_IFR_REF *) OpCodeData)->FormId, sizeof (EFI_FORM_ID));\r
 \r
-      CopyMem (&CurrentStatement->RefFormId, &((EFI_IFR_REF *) OpCodeData)->FormId, sizeof (EFI_FORM_ID));\r
-      if (OpCodeLength >= sizeof (EFI_IFR_REF2)) {\r
-        CopyMem (&CurrentStatement->RefQuestionId, &((EFI_IFR_REF2 *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));\r
+        if (OpCodeLength >= sizeof (EFI_IFR_REF2)) {\r
+          CopyMem (&Value->Value.ref.QuestionId, &((EFI_IFR_REF2 *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));\r
 \r
-        if (OpCodeLength >= sizeof (EFI_IFR_REF3)) {\r
-          CopyMem (&CurrentStatement->RefFormSetId, &((EFI_IFR_REF3 *) OpCodeData)->FormSetId, sizeof (EFI_GUID));\r
+          if (OpCodeLength >= sizeof (EFI_IFR_REF3)) {\r
+            CopyMem (&Value->Value.ref.FormSetGuid, &((EFI_IFR_REF3 *) OpCodeData)->FormSetId, sizeof (EFI_GUID));\r
 \r
-          if (OpCodeLength >= sizeof (EFI_IFR_REF4)) {\r
-            CopyMem (&CurrentStatement->RefDevicePath, &((EFI_IFR_REF4 *) OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));\r
+            if (OpCodeLength >= sizeof (EFI_IFR_REF4)) {\r
+              CopyMem (&Value->Value.ref.DevicePath, &((EFI_IFR_REF4 *) OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));\r
+            }\r
           }\r
         }\r
       }\r
+      CurrentStatement->StorageWidth = (UINT16) sizeof (EFI_HII_REF);        \r
+      InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);\r
       break;\r
 \r
     case EFI_IFR_ONE_OF_OP:\r
     case EFI_IFR_NUMERIC_OP:\r
       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
+      ASSERT(CurrentStatement != NULL);\r
 \r
       CurrentStatement->Flags = ((EFI_IFR_ONE_OF *) OpCodeData)->Flags;\r
       Value = &CurrentStatement->HiiValue;\r
@@ -1263,7 +1961,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
@@ -1271,7 +1969,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
@@ -1279,7 +1977,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
@@ -1287,7 +1985,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
@@ -1295,7 +1993,7 @@ ParseOpCodes (
         break;\r
       }\r
 \r
-      InitializeRequestElement (FormSet, CurrentStatement);\r
+      InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);\r
 \r
       if ((Operand == EFI_IFR_ONE_OF_OP) && Scope != 0) {\r
         SuppressForOption = TRUE;\r
@@ -1304,19 +2002,13 @@ ParseOpCodes (
 \r
     case EFI_IFR_ORDERED_LIST_OP:\r
       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
+      ASSERT(CurrentStatement != NULL);\r
 \r
       CurrentStatement->Flags = ((EFI_IFR_ORDERED_LIST *) OpCodeData)->Flags;\r
       CurrentStatement->MaxContainers = ((EFI_IFR_ORDERED_LIST *) OpCodeData)->MaxContainers;\r
-      CurrentStatement->StorageWidth = (UINT16)(CurrentStatement->MaxContainers * sizeof (UINT8));\r
-      InitializeRequestElement (FormSet, CurrentStatement);\r
 \r
-      //\r
-      // No buffer type is defined in EFI_IFR_TYPE_VALUE, so a Configuration Driver\r
-      // has to use FormBrowser2.Callback() to retrieve the uncommited data for\r
-      // an interactive orderedlist (i.e. with EFI_IFR_FLAG_CALLBACK flag set).\r
-      //\r
-      CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_OTHER;\r
-      CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth);\r
+      CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_BUFFER;\r
+      CurrentStatement->BufferValue = NULL;\r
 \r
       if (Scope != 0) {\r
         SuppressForOption = TRUE;\r
@@ -1325,18 +2017,19 @@ ParseOpCodes (
 \r
     case EFI_IFR_CHECKBOX_OP:\r
       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
+      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
+      InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);\r
 \r
       break;\r
 \r
     case EFI_IFR_STRING_OP:\r
       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
-\r
+      ASSERT (CurrentStatement != NULL);\r
       //\r
       // MinSize is the minimum number of characters that can be accepted for this opcode,\r
       // MaxSize is the maximum number of characters that can be accepted for this opcode.\r
@@ -1349,13 +2042,14 @@ 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
+      InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);\r
       break;\r
 \r
     case EFI_IFR_PASSWORD_OP:\r
       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
-\r
+      ASSERT (CurrentStatement != NULL);\r
       //\r
       // MinSize is the minimum number of characters that can be accepted for this opcode,\r
       // MaxSize is the maximum number of characters that can be accepted for this opcode.\r
@@ -1367,20 +2061,22 @@ 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
+      InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);\r
       break;\r
 \r
     case EFI_IFR_DATE_OP:\r
       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
+      ASSERT(CurrentStatement != NULL);\r
 \r
       CurrentStatement->Flags = ((EFI_IFR_DATE *) OpCodeData)->Flags;\r
       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
+        InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);\r
       } else {\r
         //\r
         // Don't assign storage for RTC type of date/time\r
@@ -1392,14 +2088,15 @@ ParseOpCodes (
 \r
     case EFI_IFR_TIME_OP:\r
       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
+      ASSERT(CurrentStatement != NULL);\r
 \r
       CurrentStatement->Flags = ((EFI_IFR_TIME *) OpCodeData)->Flags;\r
       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_HII_TIME);\r
 \r
-        InitializeRequestElement (FormSet, CurrentStatement);\r
+        InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);\r
       } else {\r
         //\r
         // Don't assign storage for RTC type of date/time\r
@@ -1424,13 +2121,19 @@ ParseOpCodes (
 \r
       CurrentDefault->Value.Type = ((EFI_IFR_DEFAULT *) OpCodeData)->Type;\r
       CopyMem (&CurrentDefault->DefaultId, &((EFI_IFR_DEFAULT *) OpCodeData)->DefaultId, sizeof (UINT16));\r
-      CopyMem (&CurrentDefault->Value.Value, &((EFI_IFR_DEFAULT *) OpCodeData)->Value, sizeof (EFI_IFR_TYPE_VALUE));\r
-      ExtendValueToU64 (&CurrentDefault->Value);\r
+      if (CurrentDefault->Value.Type == EFI_IFR_TYPE_BUFFER) {\r
+        CurrentDefault->Value.BufferLen = (UINT16) (OpCodeLength - OFFSET_OF (EFI_IFR_DEFAULT, Value));\r
+        CurrentDefault->Value.Buffer = AllocateCopyPool (CurrentDefault->Value.BufferLen, &((EFI_IFR_DEFAULT *) OpCodeData)->Value);\r
+        ASSERT (CurrentDefault->Value.Buffer != NULL);\r
+      } else {\r
+        CopyMem (&CurrentDefault->Value.Value, &((EFI_IFR_DEFAULT *) OpCodeData)->Value, OpCodeLength - OFFSET_OF (EFI_IFR_DEFAULT, Value));\r
+        ExtendValueToU64 (&CurrentDefault->Value);\r
+      }\r
 \r
       //\r
       // Insert to Default Value list of current Question\r
       //\r
-      InsertTailList (&CurrentStatement->DefaultListHead, &CurrentDefault->Link);\r
+      InsertTailList (&ParentStatement->DefaultListHead, &CurrentDefault->Link);\r
 \r
       if (Scope != 0) {\r
         InScopeDefault = TRUE;\r
@@ -1441,6 +2144,32 @@ ParseOpCodes (
     // Option\r
     //\r
     case EFI_IFR_ONE_OF_OPTION_OP:\r
+      if (ParentStatement->Operand == EFI_IFR_ORDERED_LIST_OP && ((((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Flags & (EFI_IFR_OPTION_DEFAULT | EFI_IFR_OPTION_DEFAULT_MFG)) != 0)) {\r
+        //\r
+        // It's keep the default value for ordered list opcode.\r
+        //\r
+        CurrentDefault = AllocateZeroPool (sizeof (QUESTION_DEFAULT));\r
+        ASSERT (CurrentDefault != NULL);\r
+        CurrentDefault->Signature = QUESTION_DEFAULT_SIGNATURE;\r
+\r
+        CurrentDefault->Value.Type = EFI_IFR_TYPE_BUFFER;\r
+        if ((((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Flags & EFI_IFR_OPTION_DEFAULT) != 0) {\r
+          CurrentDefault->DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
+        } else {\r
+          CurrentDefault->DefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
+        }\r
+\r
+        CurrentDefault->Value.BufferLen = (UINT16) (OpCodeLength - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));\r
+        CurrentDefault->Value.Buffer = AllocateCopyPool (CurrentDefault->Value.BufferLen, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Value);\r
+        ASSERT (CurrentDefault->Value.Buffer != NULL);\r
+\r
+        //\r
+        // Insert to Default Value list of current Question\r
+        //\r
+        InsertTailList (&ParentStatement->DefaultListHead, &CurrentDefault->Link);\r
+        break;\r
+      }\r
+\r
       //\r
       // EFI_IFR_ONE_OF_OPTION appear in scope of a Question.\r
       // It create a selection for use in current Question.\r
@@ -1448,21 +2177,71 @@ ParseOpCodes (
       CurrentOption = AllocateZeroPool (sizeof (QUESTION_OPTION));\r
       ASSERT (CurrentOption != NULL);\r
       CurrentOption->Signature = QUESTION_OPTION_SIGNATURE;\r
+      CurrentOption->OpCode    = (EFI_IFR_ONE_OF_OPTION *) OpCodeData;\r
 \r
       CurrentOption->Flags = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Flags;\r
       CurrentOption->Value.Type = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Type;\r
       CopyMem (&CurrentOption->Text, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Option, sizeof (EFI_STRING_ID));\r
-      CopyMem (&CurrentOption->Value.Value, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Value, sizeof (EFI_IFR_TYPE_VALUE));\r
+      CopyMem (&CurrentOption->Value.Value, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Value, OpCodeLength - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));\r
       ExtendValueToU64 (&CurrentOption->Value);\r
 \r
-      if (InScopeOptionSuppress) {\r
-        CurrentOption->SuppressExpression = OptionSuppressExpression;\r
+      ConditionalExprCount = GetConditionalExpressionCount(ExpressOption);\r
+      if ( ConditionalExprCount > 0) {\r
+        //\r
+        // Form is inside of suppressif\r
+        //\r
+        CurrentOption->SuppressExpression = (FORM_EXPRESSION_LIST *) AllocatePool( \r
+                                                 (UINTN) (sizeof(FORM_EXPRESSION_LIST) + ((ConditionalExprCount -1) * sizeof(FORM_EXPRESSION *))));\r
+        ASSERT (CurrentOption->SuppressExpression != NULL);\r
+        CurrentOption->SuppressExpression->Count     = (UINTN) ConditionalExprCount;\r
+        CurrentOption->SuppressExpression->Signature = FORM_EXPRESSION_LIST_SIGNATURE;\r
+        CopyMem (CurrentOption->SuppressExpression->Expression, GetConditionalExpressionList(ExpressOption), (UINTN) (sizeof (FORM_EXPRESSION *) * ConditionalExprCount));\r
       }\r
 \r
+      ASSERT (ParentStatement != NULL);\r
       //\r
       // Insert to Option list of current Question\r
       //\r
-      InsertTailList (&CurrentStatement->OptionListHead, &CurrentOption->Link);\r
+      InsertTailList (&ParentStatement->OptionListHead, &CurrentOption->Link);\r
+      //\r
+      // Now we know the Storage width of nested Ordered List\r
+      //\r
+      if ((ParentStatement->Operand == EFI_IFR_ORDERED_LIST_OP) && (ParentStatement->BufferValue == NULL)) {\r
+        Width = 1;\r
+        switch (CurrentOption->Value.Type) {\r
+        case EFI_IFR_TYPE_NUM_SIZE_8:\r
+          Width = 1;\r
+          break;\r
+\r
+        case EFI_IFR_TYPE_NUM_SIZE_16:\r
+          Width = 2;\r
+          break;\r
+\r
+        case EFI_IFR_TYPE_NUM_SIZE_32:\r
+          Width = 4;\r
+          break;\r
+\r
+        case EFI_IFR_TYPE_NUM_SIZE_64:\r
+          Width = 8;\r
+          break;\r
+\r
+        default:\r
+          //\r
+          // Invalid type for Ordered List\r
+          //\r
+          break;\r
+        }\r
+\r
+        ParentStatement->StorageWidth = (UINT16) (ParentStatement->MaxContainers * Width);\r
+        ParentStatement->BufferValue = AllocateZeroPool (ParentStatement->StorageWidth);\r
+        ParentStatement->ValueType = CurrentOption->Value.Type;\r
+        if (ParentStatement->HiiValue.Type == EFI_IFR_TYPE_BUFFER) {\r
+          ParentStatement->HiiValue.Buffer = ParentStatement->BufferValue;\r
+          ParentStatement->HiiValue.BufferLen = ParentStatement->StorageWidth;\r
+        }\r
+\r
+        InitializeRequestElement (FormSet, ParentStatement, CurrentForm);\r
+      }\r
       break;\r
 \r
     //\r
@@ -1473,15 +2252,42 @@ ParseOpCodes (
       //\r
       // Create an Expression node\r
       //\r
-      CurrentExpression = CreateExpression (CurrentForm);\r
+      CurrentExpression = CreateExpression (CurrentForm, OpCodeData);\r
       CopyMem (&CurrentExpression->Error, &((EFI_IFR_INCONSISTENT_IF *) OpCodeData)->Error, sizeof (EFI_STRING_ID));\r
 \r
       if (Operand == EFI_IFR_NO_SUBMIT_IF_OP) {\r
         CurrentExpression->Type = EFI_HII_EXPRESSION_NO_SUBMIT_IF;\r
-        InsertTailList (&CurrentStatement->NoSubmitListHead, &CurrentExpression->Link);\r
+        InsertTailList (&ParentStatement->NoSubmitListHead, &CurrentExpression->Link);\r
       } else {\r
         CurrentExpression->Type = EFI_HII_EXPRESSION_INCONSISTENT_IF;\r
-        InsertTailList (&CurrentStatement->InconsistentListHead, &CurrentExpression->Link);\r
+        InsertTailList (&ParentStatement->InconsistentListHead, &CurrentExpression->Link);\r
+      }\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_WARNING_IF_OP:\r
+      //\r
+      // Create an Expression node\r
+      //\r
+      CurrentExpression = CreateExpression (CurrentForm, OpCodeData);\r
+      CopyMem (&CurrentExpression->Error, &((EFI_IFR_WARNING_IF *) OpCodeData)->Warning, sizeof (EFI_STRING_ID));\r
+      CurrentExpression->TimeOut = ((EFI_IFR_WARNING_IF *) OpCodeData)->TimeOut;\r
+      CurrentExpression->Type    = EFI_HII_EXPRESSION_WARNING_IF;\r
+      InsertTailList (&ParentStatement->WarningListHead, &CurrentExpression->Link);\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
@@ -1489,16 +2295,29 @@ ParseOpCodes (
       //\r
       // Question and Option will appear in scope of this OpCode\r
       //\r
-      CurrentExpression = CreateExpression (CurrentForm);\r
+      CurrentExpression = CreateExpression (CurrentForm, OpCodeData);\r
       CurrentExpression->Type = EFI_HII_EXPRESSION_SUPPRESS_IF;\r
-      InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);\r
+\r
+      if (CurrentForm == NULL) {\r
+        InsertTailList (&FormSet->ExpressionListHead, &CurrentExpression->Link);\r
+      } else {\r
+        InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);\r
+      }\r
 \r
       if (SuppressForOption) {\r
-        InScopeOptionSuppress = TRUE;\r
-        OptionSuppressExpression = CurrentExpression;\r
+        PushConditionalExpression(CurrentExpression, ExpressOption);       \r
+      } else if (SuppressForQuestion) {\r
+        PushConditionalExpression(CurrentExpression, ExpressStatement);  \r
       } else {\r
-        mInScopeSuppress = TRUE;\r
-        mSuppressExpression = CurrentExpression;\r
+        PushConditionalExpression(CurrentExpression, ExpressForm);  \r
+      }\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
@@ -1506,12 +2325,18 @@ ParseOpCodes (
       //\r
       // Questions will appear in scope of this OpCode\r
       //\r
-      CurrentExpression = CreateExpression (CurrentForm);\r
+      CurrentExpression = CreateExpression (CurrentForm, OpCodeData);\r
       CurrentExpression->Type = EFI_HII_EXPRESSION_GRAY_OUT_IF;\r
       InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);\r
+      PushConditionalExpression(CurrentExpression, ExpressStatement);\r
 \r
-      mInScopeGrayOut = TRUE;\r
-      mGrayOutExpression = CurrentExpression;\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_DISABLE_IF_OP:\r
@@ -1525,9 +2350,16 @@ ParseOpCodes (
       CurrentExpression->Type = EFI_HII_EXPRESSION_DISABLE_IF;\r
       InitializeListHead (&CurrentExpression->OpCodeListHead);\r
 \r
-      InScopeDisable = TRUE;\r
-      OpCodeDisabled = FALSE;\r
+      if (CurrentForm != NULL) {\r
+        //\r
+        // This is DisableIf for Question, enqueue it to Form expression list\r
+        //\r
+        InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);\r
+        PushConditionalExpression(CurrentExpression, ExpressStatement);\r
+      }\r
 \r
+      OpCodeDisabled  = FALSE;\r
+      InScopeDisable  = TRUE;\r
       //\r
       // Take a look at next OpCode to see whether current expression consists\r
       // of single OpCode\r
@@ -1541,7 +2373,7 @@ ParseOpCodes (
     // Expression\r
     //\r
     case EFI_IFR_VALUE_OP:\r
-      CurrentExpression = CreateExpression (CurrentForm);\r
+      CurrentExpression = CreateExpression (CurrentForm, OpCodeData);\r
       CurrentExpression->Type = EFI_HII_EXPRESSION_VALUE;\r
       InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);\r
 \r
@@ -1559,17 +2391,77 @@ ParseOpCodes (
         // 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->ValueExpression = CurrentExpression;\r
+        ASSERT (ParentStatement != NULL);\r
+        ParentStatement->ValueExpression = CurrentExpression;\r
+      }\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_RULE_OP:\r
-      CurrentExpression = CreateExpression (CurrentForm);\r
+      CurrentExpression = CreateExpression (CurrentForm, OpCodeData);\r
       CurrentExpression->Type = EFI_HII_EXPRESSION_RULE;\r
 \r
       CurrentExpression->RuleId = ((EFI_IFR_RULE *) OpCodeData)->RuleId;\r
       InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);\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_READ_OP:\r
+      CurrentExpression = CreateExpression (CurrentForm, OpCodeData);\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 (ParentStatement != NULL);\r
+      ParentStatement->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, OpCodeData);\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 (ParentStatement != NULL);\r
+      ParentStatement->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
@@ -1588,11 +2480,13 @@ 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
 \r
       case EFI_IFR_ONE_OF_OPTION_OP:\r
+        ASSERT (CurrentOption != NULL);\r
         ImageId = &CurrentOption->ImageId;\r
         break;\r
 \r
@@ -1602,8 +2496,8 @@ ParseOpCodes (
         // 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.\r
         //\r
-        ASSERT (CurrentStatement != NULL);\r
-        ImageId = &CurrentStatement->ImageId;\r
+        ASSERT (ParentStatement != NULL);\r
+        ImageId = &ParentStatement->ImageId;\r
         break;\r
       }\r
 \r
@@ -1615,49 +2509,69 @@ ParseOpCodes (
     // Refresh\r
     //\r
     case EFI_IFR_REFRESH_OP:\r
-      ASSERT (CurrentStatement != NULL);\r
-      CurrentStatement->RefreshInterval = ((EFI_IFR_REFRESH *) OpCodeData)->RefreshInterval;\r
+      ASSERT (ParentStatement != NULL);\r
+      ParentStatement->RefreshInterval = ((EFI_IFR_REFRESH *) OpCodeData)->RefreshInterval;\r
       break;\r
 \r
     //\r
-    // Vendor specific\r
+    // Refresh guid.\r
     //\r
-    case EFI_IFR_GUID_OP:\r
-      if (CompareGuid (&gTianoHiiIfrGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
-        //\r
-        // Tiano specific GUIDed opcodes\r
-        //\r
-        switch (((EFI_IFR_GUID_LABEL *) OpCodeData)->ExtendOpCode) {\r
-        case EFI_IFR_EXTEND_OP_LABEL:\r
-          //\r
-          // just ignore label\r
-          //\r
-          break;\r
+    case EFI_IFR_REFRESH_ID_OP:\r
+      //\r
+      // Get ScopeOpcode from top of stack\r
+      //\r
+      PopScope (&ScopeOpCode);\r
+      PushScope (ScopeOpCode);\r
 \r
-        case EFI_IFR_EXTEND_OP_BANNER:\r
-          if (FormSet->SubClass == EFI_FRONT_PAGE_SUBCLASS) {\r
-            CopyMem (\r
-              &BannerData->Banner[((EFI_IFR_GUID_BANNER *) OpCodeData)->LineNumber][\r
-              ((EFI_IFR_GUID_BANNER *) OpCodeData)->Alignment],\r
-              &((EFI_IFR_GUID_BANNER *) OpCodeData)->Title,\r
-              sizeof (EFI_STRING_ID)\r
-              );\r
-          }\r
-          break;\r
+      switch (ScopeOpCode) {\r
+      case EFI_IFR_FORM_OP:\r
+      case EFI_IFR_FORM_MAP_OP:\r
+        ASSERT (CurrentForm != NULL);\r
+        CopyMem (&CurrentForm->RefreshGuid, &((EFI_IFR_REFRESH_ID *) OpCodeData)->RefreshEventGroupId, sizeof (EFI_GUID));\r
+        break;\r
 \r
-        case EFI_IFR_EXTEND_OP_CLASS:\r
-          CopyMem (&FormSet->Class, &((EFI_IFR_GUID_CLASS *) OpCodeData)->Class, sizeof (UINT16));\r
-          break;\r
+      default:\r
+        ASSERT (ParentStatement != NULL);\r
+        CopyMem (&ParentStatement->RefreshGuid, &((EFI_IFR_REFRESH_ID *) OpCodeData)->RefreshEventGroupId, sizeof (EFI_GUID));\r
+        break;\r
+      }\r
+      break;\r
 \r
-        case EFI_IFR_EXTEND_OP_SUBCLASS:\r
-          CopyMem (&FormSet->SubClass, &((EFI_IFR_GUID_SUBCLASS *) OpCodeData)->SubClass, sizeof (UINT16));\r
-          break;\r
+    //\r
+    // Modal tag\r
+    //\r
+    case EFI_IFR_MODAL_TAG_OP:\r
+      ASSERT (CurrentForm != NULL);\r
+      CurrentForm->ModalForm = TRUE;\r
+      break;\r
 \r
-        default:\r
-          break;\r
-        }\r
-      }\r
+    //\r
+    // Lock tag, used by form and statement.\r
+    //\r
+    case EFI_IFR_LOCKED_OP:\r
+      //\r
+      // Get ScopeOpcode from top of stack\r
+      //\r
+      PopScope (&ScopeOpCode);\r
+      PushScope (ScopeOpCode);\r
+      switch (ScopeOpCode) {\r
+      case EFI_IFR_FORM_OP:\r
+      case EFI_IFR_FORM_MAP_OP:\r
+        ASSERT (CurrentForm != NULL);\r
+        CurrentForm->Locked = TRUE;\r
+        break;\r
+\r
+      default:\r
+        ASSERT (ParentStatement != NULL);\r
+        ParentStatement->Locked = TRUE;\r
+      }      \r
+      break;\r
 \r
+    //\r
+    // Vendor specific\r
+    //\r
+    case EFI_IFR_GUID_OP:     \r
+      CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);\r
       break;\r
 \r
     //\r
@@ -1669,6 +2583,13 @@ ParseOpCodes (
         ResetScopeStack ();\r
         return Status;\r
       }\r
+      \r
+      //\r
+      // Parent statement end tag found, update ParentStatement info.\r
+      //\r
+      if (IsStatementOpCode(ScopeOpCode) && (ParentStatement != NULL) && (ParentStatement->Operand == ScopeOpCode)) {\r
+        ParentStatement  = ParentStatement->ParentStatement;\r
+      }\r
 \r
       switch (ScopeOpCode) {\r
       case EFI_IFR_FORM_SET_OP:\r
@@ -1680,10 +2601,12 @@ ParseOpCodes (
         break;\r
 \r
       case EFI_IFR_FORM_OP:\r
+      case EFI_IFR_FORM_MAP_OP:\r
         //\r
         // End of Form\r
         //\r
         CurrentForm = NULL;\r
+        SuppressForQuestion = FALSE;\r
         break;\r
 \r
       case EFI_IFR_ONE_OF_OPTION_OP:\r
@@ -1693,12 +2616,9 @@ ParseOpCodes (
         CurrentOption = NULL;\r
         break;\r
 \r
-      case EFI_IFR_SUBTITLE_OP:\r
-        mInScopeSubtitle = FALSE;\r
-        break;\r
-\r
       case EFI_IFR_NO_SUBMIT_IF_OP:\r
       case EFI_IFR_INCONSISTENT_IF_OP:\r
+      case EFI_IFR_WARNING_IF_OP:\r
         //\r
         // Ignore end of EFI_IFR_NO_SUBMIT_IF and EFI_IFR_INCONSISTENT_IF\r
         //\r
@@ -1706,17 +2626,22 @@ ParseOpCodes (
 \r
       case EFI_IFR_SUPPRESS_IF_OP:\r
         if (SuppressForOption) {\r
-          InScopeOptionSuppress = FALSE;\r
+          PopConditionalExpression(ExpressOption);      \r
+        } else if (SuppressForQuestion) {\r
+          PopConditionalExpression(ExpressStatement);\r
         } else {\r
-          mInScopeSuppress = FALSE;\r
+          PopConditionalExpression(ExpressForm);\r
         }\r
         break;\r
 \r
       case EFI_IFR_GRAY_OUT_IF_OP:\r
-        mInScopeGrayOut = FALSE;\r
+        PopConditionalExpression(ExpressStatement);\r
         break;\r
 \r
       case EFI_IFR_DISABLE_IF_OP:\r
+        if (CurrentForm != NULL) {\r
+          PopConditionalExpression(ExpressStatement);\r
+        }\r
         InScopeDisable = FALSE;\r
         OpCodeDisabled = FALSE;\r
         break;\r
@@ -1730,23 +2655,39 @@ 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 (InScopeDisable) {\r
+          if (InScopeDisable && CurrentForm == NULL) {\r
             //\r
-            // Evaluate DisableIf expression\r
+            // This is DisableIf expression for Form, it should be a constant expression\r
             //\r
+            ASSERT (CurrentExpression != NULL);\r
             Status = EvaluateExpression (FormSet, CurrentForm, CurrentExpression);\r
             if (EFI_ERROR (Status)) {\r
               return Status;\r
             }\r
-            if (CurrentExpression->Result.Type != EFI_IFR_TYPE_BOOLEAN) {\r
-              return EFI_INVALID_PARAMETER;\r
-            }\r
 \r
-            OpCodeDisabled = CurrentExpression->Result.Value.b;\r
+            OpCodeDisabled = IsTrue (&CurrentExpression->Result);\r
+\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
@@ -1763,6 +2704,17 @@ ParseOpCodes (
     default:\r
       break;\r
     }\r
+\r
+    if (IsStatementOpCode(Operand)) {\r
+      CurrentStatement->ParentStatement = ParentStatement;\r
+      if (Scope != 0) {\r
+        //\r
+        // Scope != 0, other statements or options may nest in this statement.\r
+        // Update the ParentStatement info.\r
+        //\r
+        ParentStatement = CurrentStatement;\r
+      }\r
+    }\r
   }\r
 \r
   return EFI_SUCCESS;\r