]> xenbits.xensource.com Git - ovmf.git/commitdiff
RedfishPkg: introduce HII utility helper library
authorNickle Wang <nicklew@nvidia.com>
Mon, 10 Apr 2023 13:12:03 +0000 (21:12 +0800)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Fri, 28 Apr 2023 12:21:38 +0000 (12:21 +0000)
HiiUtilityLib is a helper library that provides the
functions to manipulate HII options.

Signed-off-by: Nickle Wang <nicklew@nvidia.com>
Cc: Abner Chang <abner.chang@amd.com>
Cc: Igor Kulchytskyy <igork@ami.com>
Cc: Nick Ramirez <nramirez@nvidia.com>
Reviewed-by: Abner Chang <abner.chang@amd.com>
Reviewed-by: Igor Kulchytskyy <igork @ami.com>
RedfishPkg/Include/Library/HiiUtilityLib.h [new file with mode: 0644]
RedfishPkg/Library/HiiUtilityLib/HiiExpression.c [new file with mode: 0644]
RedfishPkg/Library/HiiUtilityLib/HiiExpression.h [new file with mode: 0644]
RedfishPkg/Library/HiiUtilityLib/HiiIfrParse.c [new file with mode: 0644]
RedfishPkg/Library/HiiUtilityLib/HiiInternal.h [new file with mode: 0644]
RedfishPkg/Library/HiiUtilityLib/HiiUtilityInternal.c [new file with mode: 0644]
RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.c [new file with mode: 0644]
RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.inf [new file with mode: 0644]
RedfishPkg/RedfishPkg.dec

diff --git a/RedfishPkg/Include/Library/HiiUtilityLib.h b/RedfishPkg/Include/Library/HiiUtilityLib.h
new file mode 100644 (file)
index 0000000..0999ef7
--- /dev/null
@@ -0,0 +1,1204 @@
+/** @file\r
+  Definitions of RedfishPlatformConfigLib.\r
+\r
+  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+  (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>\r
+  Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.\r
+\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#ifndef HII_UTILITY_LIB_\r
+#define HII_UTILITY_LIB_\r
+\r
+#include <Protocol/DisplayProtocol.h>\r
+#include <Protocol/HiiConfigAccess.h>\r
+\r
+//\r
+// IFR relative definition\r
+//\r
+#define EFI_HII_EXPRESSION_INCONSISTENT_IF  0\r
+#define EFI_HII_EXPRESSION_NO_SUBMIT_IF     1\r
+#define EFI_HII_EXPRESSION_GRAY_OUT_IF      2\r
+#define EFI_HII_EXPRESSION_SUPPRESS_IF      3\r
+#define EFI_HII_EXPRESSION_DISABLE_IF       4\r
+#define EFI_HII_EXPRESSION_VALUE            5\r
+#define EFI_HII_EXPRESSION_RULE             6\r
+#define EFI_HII_EXPRESSION_READ             7\r
+#define EFI_HII_EXPRESSION_WRITE            8\r
+#define EFI_HII_EXPRESSION_WARNING_IF       9\r
+\r
+#define EFI_HII_VARSTORE_BUFFER               0\r
+#define EFI_HII_VARSTORE_NAME_VALUE           1\r
+#define EFI_HII_VARSTORE_EFI_VARIABLE         2   // EFI Varstore type follow UEFI spec before 2.3.1.\r
+#define EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER  3   // EFI varstore type follow UEFI spec 2.3.1 and later.\r
+\r
+///\r
+/// HII_NAME_VALUE_NODE for name/value storage\r
+///\r
+typedef struct {\r
+  UINTN         Signature;\r
+  LIST_ENTRY    Link;\r
+  CHAR16        *Name;\r
+  CHAR16        *Value;\r
+} HII_NAME_VALUE_NODE;\r
+\r
+#define HII_NAME_VALUE_NODE_SIGNATURE  SIGNATURE_32 ('N', 'V', 'S', 'T')\r
+#define HII_NAME_VALUE_NODE_FROM_LINK(a)  CR (a, HII_NAME_VALUE_NODE, Link, HII_NAME_VALUE_NODE_SIGNATURE)\r
+\r
+///\r
+/// Storage info\r
+///\r
+typedef union {\r
+  EFI_STRING_ID    VarName;\r
+  UINT16           VarOffset;\r
+} HII_VAR_STORE_INFO;\r
+\r
+///\r
+/// FormSet storage\r
+///\r
+typedef struct {\r
+  UINTN             Signature;\r
+  LIST_ENTRY        Link;\r
+\r
+  UINT8             Type;          ///< Storage type\r
+  EFI_HII_HANDLE    HiiHandle;     ///< HiiHandle for this varstore.\r
+\r
+  ///\r
+  /// For all type of storages.\r
+  ///\r
+  UINT16            VarStoreId;    ///< VarStore ID.\r
+  EFI_GUID          Guid;          ///< VarStore Guid.\r
+\r
+  ///\r
+  /// For EFI_IFR_VARSTORE, EFI_IFR_VARSTORE_EFI\r
+  ///\r
+  CHAR16            *Name;         ///< VarStore name\r
+  UINT16            Size;          ///< VarStore size.\r
+  UINT8             *Buffer;       ///< Buffer storage.\r
+  UINT8             *EditBuffer;   ///< Edit copy for Buffer Storage\r
+\r
+  ///\r
+  /// For EFI_IFR_VARSTORE_EFI: EFI Variable.\r
+  ///\r
+  UINT32            Attributes;\r
+\r
+  ///\r
+  /// For EFI_IFR_VARSTORE_NAME_VALUE.\r
+  ///\r
+  LIST_ENTRY        NameValueList;  ///< List of NAME_VALUE_NODE\r
+\r
+  CHAR16            *ConfigHdr;     ///< <ConfigHdr>\r
+  CHAR16            *ConfigRequest; ///< <ConfigRequest> = <ConfigHdr> + <RequestElement>\r
+  UINTN             ElementCount;   ///< Number of <RequestElement> in the <ConfigRequest>\r
+  UINTN             SpareStrLen;    ///< Spare length of ConfigRequest string buffer\r
+} HII_FORMSET_STORAGE;\r
+\r
+#define HII_STORAGE_SIGNATURE  SIGNATURE_32 ('B', 'S', 'T', 'G')\r
+#define HII_STORAGE_FROM_LINK(a)  CR (a, HII_FORMSET_STORAGE, Link, HII_STORAGE_SIGNATURE)\r
+\r
+///\r
+/// Definition of EXPRESS_RESULT\r
+///\r
+typedef enum {\r
+  ExpressFalse = 0,\r
+  ExpressGrayOut,\r
+  ExpressSuppress,\r
+  ExpressDisable\r
+} EXPRESS_RESULT;\r
+\r
+///\r
+/// Definition of EXPRESS_LEVEL\r
+///\r
+typedef enum {\r
+  ExpressNone = 0,\r
+  ExpressForm,\r
+  ExpressStatement,\r
+  ExpressOption\r
+} EXPRESS_LEVEL;\r
+\r
+///\r
+/// Definition of HII_EXPRESSION_OPCODE_EXTRA\r
+///\r
+typedef union {\r
+  EFI_HII_VALUE    Value;         ///< EFI_IFR_UINT64, EFI_IFR_UINT32, EFI_IFR_UINT16, EFI_IFR_UINT8, EFI_IFR_STRING_REF1\r
+  UINT8            Format;        ///< For EFI_IFR_TO_STRING, EFI_IFR_FIND\r
+  UINT8            Flags;         ///< For EFI_IFR_SPAN\r
+  UINT8            RuleId;        ///< For EFI_IFR_RULE_REF\r
+  EFI_GUID         Guid;          ///< For EFI_IFR_SECURITY, EFI_IFR_MATCH2\r
+\r
+  struct {\r
+    EFI_QUESTION_ID    QuestionId;\r
+    EFI_HII_VALUE      Value;\r
+  } EqIdValData;\r
+\r
+  struct {\r
+    EFI_QUESTION_ID    QuestionId1;\r
+    EFI_QUESTION_ID    QuestionId2;\r
+  } EqIdIdData;\r
+\r
+  struct {\r
+    EFI_QUESTION_ID    QuestionId; ///< For EFI_IFR_EQ_ID_VAL_LIST\r
+    UINT16             ListLength;\r
+    UINT16             *ValueList;\r
+  } EqIdListData;\r
+\r
+  struct {\r
+    EFI_QUESTION_ID    QuestionId;\r
+  } QuestionRef1Data;\r
+\r
+  struct {\r
+    EFI_STRING_ID    DevicePath;  ///< For EFI_IFR_QUESTION_REF3_3\r
+    EFI_GUID         Guid;\r
+  } QuestionRef3Data;\r
+\r
+  struct {\r
+    HII_FORMSET_STORAGE    *VarStorage;\r
+    HII_VAR_STORE_INFO     VarStoreInfo;\r
+    UINT8                  ValueType;\r
+    UINT8                  ValueWidth;\r
+    CHAR16                 *ValueName;\r
+  } GetSetData;\r
+} HII_EXPRESSION_OPCODE_EXTRA;\r
+\r
+typedef union _HII_DEPENDENCY_EXPRESSION HII_DEPENDENCY_EXPRESSION;\r
+\r
+///\r
+/// Definition of HII_EXPRESSION_CONSTANT\r
+///\r
+/// Operand:\r
+///\r
+/// EFI_IFR_TRUE\r
+/// EFI_IFR_FALSE\r
+/// EFI_IFR_ONE\r
+/// EFI_IFR_ONES\r
+/// EFI_IFR_ZERO\r
+/// EFI_IFR_UNDEFINED\r
+/// EFI_IFR_VERSION\r
+/// EFI_IFR_UINT8\r
+/// EFI_IFR_UINT16\r
+/// EFI_IFR_UINT32\r
+/// EFI_IFR_UINT64\r
+///\r
+typedef struct {\r
+  UINT8            Operand;\r
+  EFI_HII_VALUE    Value;\r
+} HII_EXPRESSION_CONSTANT;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_DUP\r
+///\r
+typedef struct {\r
+  UINT8    Operand;\r
+} HII_DEPENDENCY_DUP;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_EQ_ID_VAL\r
+///\r
+typedef struct {\r
+  UINT8              Operand;\r
+  EFI_QUESTION_ID    QuestionId;\r
+  EFI_HII_VALUE      Value;\r
+} HII_DEPENDENCY_EQ_ID_VAL;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_EQ_ID_VAL\r
+///\r
+typedef struct {\r
+  UINT8              Operand;\r
+  EFI_QUESTION_ID    QuestionId1;\r
+  EFI_QUESTION_ID    QuestionId2;\r
+} HII_DEPENDENCY_EQ_ID_ID;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_EQ_ID_VAL_LIST\r
+///\r
+typedef struct {\r
+  UINT8              Operand;\r
+  EFI_QUESTION_ID    QuestionId;\r
+  UINT16             ListLength;\r
+  UINT16             *ValueList;\r
+} HII_DEPENDENCY_EQ_ID_VAL_LIST;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_QUESTION_REF1\r
+///\r
+typedef struct {\r
+  UINT8              Operand;\r
+  EFI_QUESTION_ID    QuestionId;\r
+} HII_DEPENDENCY_QUESTION_REF1;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_RULE_REF\r
+///\r
+typedef struct {\r
+  UINT8    Operand;\r
+  UINT8    RuleId;\r
+} HII_DEPENDENCY_RULE_REF;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_STRING_REF1\r
+///\r
+typedef struct {\r
+  UINT8            Operand;\r
+  EFI_HII_VALUE    Value;\r
+} HII_DEPENDENCY_STRING_REF1;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_THIS\r
+///\r
+typedef struct {\r
+  UINT8              Operand;\r
+  EFI_QUESTION_ID    QuestionId;\r
+} HII_DEPENDENCY_THIS;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_SECURITY\r
+///\r
+typedef struct {\r
+  UINT8       Operand;\r
+  EFI_GUID    Permissions;\r
+} HII_DEPENDENCY_SECURITY;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_GET\r
+///\r
+typedef struct  {\r
+  UINT8                  Operand;\r
+  HII_FORMSET_STORAGE    *VarStorage;\r
+  HII_VAR_STORE_INFO     VarStoreInfo;\r
+  UINT8                  ValueType;\r
+  UINT8                  ValueWidth;\r
+  CHAR16                 *ValueName;\r
+} HII_DEPENDENCY_GET;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_LENGTH\r
+///\r
+typedef struct  {\r
+  UINT8                        Operand;\r
+  HII_DEPENDENCY_EXPRESSION    *SubExpression;\r
+} HII_DEPENDENCY_LENGTH;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_BITWISE_NOT\r
+///\r
+typedef struct  {\r
+  UINT8                        Operand;\r
+  HII_DEPENDENCY_EXPRESSION    *SubExpression;\r
+} HII_DEPENDENCY_BITWISE_NOT;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_STRING_REF2\r
+///\r
+typedef struct  {\r
+  UINT8                        Operand;\r
+  HII_DEPENDENCY_EXPRESSION    *SubExpression;\r
+} HII_DEPENDENCY_STRING_REF2;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_QUESTION_REF2\r
+///\r
+typedef struct  {\r
+  UINT8                        Operand;\r
+  HII_DEPENDENCY_EXPRESSION    *SubExpression;\r
+} HII_DEPENDENCY_QUESTION_REF2;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_QUESTION_REF3\r
+///\r
+typedef struct  {\r
+  UINT8                        Operand;\r
+  EFI_STRING_ID                DevicePath;\r
+  EFI_GUID                     Guid;\r
+  HII_DEPENDENCY_EXPRESSION    *SubExpression;\r
+} HII_DEPENDENCY_QUESTION_REF3;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_TO_BOOLEAN\r
+///\r
+typedef struct  {\r
+  UINT8                        Operand;\r
+  HII_DEPENDENCY_EXPRESSION    *SubExpression;\r
+} HII_DEPENDENCY_TO_BOOLEAN;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_TO_STRING\r
+///\r
+typedef struct  {\r
+  UINT8                        Operand;\r
+  UINT8                        Format;\r
+  HII_DEPENDENCY_EXPRESSION    *SubExpression;\r
+} HII_DEPENDENCY_TO_STRING;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_TO_UINT\r
+///\r
+typedef struct  {\r
+  UINT8                        Operand;\r
+  HII_DEPENDENCY_EXPRESSION    *SubExpression;\r
+} HII_DEPENDENCY_TO_UINT;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_TO_UPPER\r
+///\r
+typedef struct  {\r
+  UINT8                        Operand;\r
+  HII_DEPENDENCY_EXPRESSION    *SubExpression;\r
+} HII_DEPENDENCY_TO_UPPER;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_TO_LOWER\r
+///\r
+typedef struct  {\r
+  UINT8                        Operand;\r
+  HII_DEPENDENCY_EXPRESSION    *SubExpression;\r
+} HII_DEPENDENCY_TO_LOWER;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_SET\r
+///\r
+typedef struct  {\r
+  UINT8                        Operand;\r
+  HII_FORMSET_STORAGE          *VarStorage;\r
+  HII_VAR_STORE_INFO           VarStoreInfo;\r
+  UINT8                        ValueType;\r
+  UINT8                        ValueWidth;\r
+  CHAR16                       *ValueName;\r
+  HII_DEPENDENCY_EXPRESSION    *SubExpression;\r
+} HII_DEPENDENCY_SET;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_NOT\r
+///\r
+typedef struct {\r
+  UINT8                        Operand;\r
+  HII_DEPENDENCY_EXPRESSION    *SubExpression;\r
+} HII_DEPENDENCY_NOT;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_CATENATE\r
+///\r
+typedef struct {\r
+  UINT8                        Operand;\r
+  HII_DEPENDENCY_EXPRESSION    *LeftStringExp;\r
+  HII_DEPENDENCY_EXPRESSION    *RightStringExp;\r
+} HII_DEPENDENCY_CATENATE;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_MATCH\r
+///\r
+typedef struct {\r
+  UINT8                        Operand;\r
+  HII_DEPENDENCY_EXPRESSION    *StringExp;\r
+  HII_DEPENDENCY_EXPRESSION    *PatternExp;\r
+} HII_DEPENDENCY_MATCH;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_MATCH2\r
+///\r
+typedef struct {\r
+  UINT8                        Operand;\r
+  EFI_GUID                     SyntaxType;\r
+  HII_DEPENDENCY_EXPRESSION    *StringExp;\r
+  HII_DEPENDENCY_EXPRESSION    *PatternExp;\r
+} HII_DEPENDENCY_MATCH2;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_MULT\r
+///\r
+typedef struct {\r
+  UINT8                        Operand;\r
+  HII_DEPENDENCY_EXPRESSION    *RightHandExp;\r
+  HII_DEPENDENCY_EXPRESSION    *LeftHandExp;\r
+} HII_DEPENDENCY_MULT;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_DIV\r
+///\r
+typedef struct {\r
+  UINT8                        Operand;\r
+  HII_DEPENDENCY_EXPRESSION    *RightHandExp;    ///< right value\r
+  HII_DEPENDENCY_EXPRESSION    *LeftHandExp;     ///< left value\r
+} HII_DEPENDENCY_DIV;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_MOD\r
+///\r
+typedef struct {\r
+  UINT8                        Operand;\r
+  HII_DEPENDENCY_EXPRESSION    *RightHandExp;    ///< right value\r
+  HII_DEPENDENCY_EXPRESSION    *LeftHandExp;     ///< left value\r
+} HII_DEPENDENCY_MOD;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_ADD\r
+///\r
+typedef struct {\r
+  UINT8                        Operand;\r
+  HII_DEPENDENCY_EXPRESSION    *RightHandExp;     ///< right value\r
+  HII_DEPENDENCY_EXPRESSION    *LeftHandExp;      ///< left value\r
+} HII_DEPENDENCY_ADD;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_SUBTRACT\r
+///\r
+typedef struct {\r
+  UINT8                        Operand;\r
+  HII_DEPENDENCY_EXPRESSION    *RightHandExp;    ///< right value\r
+  HII_DEPENDENCY_EXPRESSION    *LeftHandExp;     ///< left value\r
+} HII_DEPENDENCY_SUBTRACT;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_SHIFT_LEFT\r
+///\r
+typedef struct {\r
+  UINT8                        Operand;\r
+  HII_DEPENDENCY_EXPRESSION    *RightHandExp;\r
+  HII_DEPENDENCY_EXPRESSION    *LeftHandExp;\r
+} HII_DEPENDENCY_SHIFT_LEFT;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_SHIFT_RIGHT\r
+///\r
+typedef struct {\r
+  UINT8                        Operand;\r
+  HII_DEPENDENCY_EXPRESSION    *RightHandExp;\r
+  HII_DEPENDENCY_EXPRESSION    *LeftHandExp;\r
+} HII_DEPENDENCY_SHIFT_RIGHT;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_GREATER_THAN\r
+///\r
+typedef struct {\r
+  UINT8                        Operand;\r
+  HII_DEPENDENCY_EXPRESSION    *RightHandExp;\r
+  HII_DEPENDENCY_EXPRESSION    *LeftHandExp;\r
+} HII_DEPENDENCY_GREATER_THAN;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_GREATER_EQUAL\r
+///\r
+typedef struct {\r
+  UINT8                        Operand;\r
+  HII_DEPENDENCY_EXPRESSION    *RightHandExp;\r
+  HII_DEPENDENCY_EXPRESSION    *LeftHandExp;\r
+} HII_DEPENDENCY_GREATER_EQUAL;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_LESS_THAN\r
+///\r
+typedef struct {\r
+  UINT8                        Operand;\r
+  HII_DEPENDENCY_EXPRESSION    *RightHandExp;\r
+  HII_DEPENDENCY_EXPRESSION    *LeftHandExp;\r
+} HII_DEPENDENCY_LESS_THAN;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_LESS_EQUAL\r
+///\r
+typedef struct {\r
+  UINT8                        Operand;\r
+  HII_DEPENDENCY_EXPRESSION    *RightHandExp;\r
+  HII_DEPENDENCY_EXPRESSION    *LeftHandExp;\r
+} HII_DEPENDENCY_LESS_EQUAL;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_EQUAL\r
+///\r
+typedef struct {\r
+  UINT8                        Operand;\r
+  HII_DEPENDENCY_EXPRESSION    *SubExpression1;\r
+  HII_DEPENDENCY_EXPRESSION    *SubExpression2;\r
+} HII_DEPENDENCY_EQUAL;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_NOT_EQUAL\r
+///\r
+typedef struct {\r
+  UINT8                        Operand;\r
+  HII_DEPENDENCY_EXPRESSION    *SubExpression1;\r
+  HII_DEPENDENCY_EXPRESSION    *SubExpression2;\r
+} HII_DEPENDENCY_NOT_EQUAL;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_BITWISE_AND\r
+///\r
+typedef struct {\r
+  UINT8                        Operand;\r
+  HII_DEPENDENCY_EXPRESSION    *SubExpression1;\r
+  HII_DEPENDENCY_EXPRESSION    *SubExpression2;\r
+} HII_DEPENDENCY_BITWISE_AND;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_BITWISE_OR\r
+///\r
+typedef struct {\r
+  UINT8                        Operand;\r
+  HII_DEPENDENCY_EXPRESSION    *SubExpression1;\r
+  HII_DEPENDENCY_EXPRESSION    *SubExpression2;\r
+} HII_DEPENDENCY_BITWISE_OR;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_AND\r
+///\r
+typedef struct {\r
+  UINT8                        Operand;\r
+  HII_DEPENDENCY_EXPRESSION    *SubExpression1;\r
+  HII_DEPENDENCY_EXPRESSION    *SubExpression2;\r
+} HII_DEPENDENCY_AND;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_OR\r
+///\r
+typedef struct {\r
+  UINT8                        Operand;\r
+  HII_DEPENDENCY_EXPRESSION    *SubExpression1;\r
+  HII_DEPENDENCY_EXPRESSION    *SubExpression2;\r
+} HII_DEPENDENCY_OR;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_CONDITIONAL\r
+///\r
+/// Ternary expression\r
+///\r
+typedef struct  {\r
+  UINT8                        Operand;\r
+  HII_DEPENDENCY_EXPRESSION    *CondTrueValExp;  ///< right value\r
+  HII_DEPENDENCY_EXPRESSION    *CondFalseValExp; ///< middle value\r
+  HII_DEPENDENCY_EXPRESSION    *ConditionExp;    ///< left value\r
+} HII_DEPENDENCY_CONDITIONAL;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_FIND\r
+///\r
+typedef struct  {\r
+  UINT8                        Operand;\r
+  UINT8                        Format;\r
+  HII_DEPENDENCY_EXPRESSION    *IndexExp;             ///< right value\r
+  HII_DEPENDENCY_EXPRESSION    *StringToCompWithExp;  ///< middle value\r
+  HII_DEPENDENCY_EXPRESSION    *StringToSearchExp;    ///< left value\r
+} HII_DEPENDENCY_FIND;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_MID\r
+///\r
+typedef struct  {\r
+  UINT8                        Operand;\r
+  HII_DEPENDENCY_EXPRESSION    *LengthExp;         ///< right value\r
+  HII_DEPENDENCY_EXPRESSION    *IndexExp;          ///< middle value\r
+  HII_DEPENDENCY_EXPRESSION    *StringOrBufferExp; ///< left value\r
+} HII_DEPENDENCY_MID;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_TOKEN\r
+///\r
+typedef struct  {\r
+  UINT8                        Operand;\r
+  HII_DEPENDENCY_EXPRESSION    *IndexExp;           ///< right value\r
+  HII_DEPENDENCY_EXPRESSION    *DelimiterExp;       ///< middle value\r
+  HII_DEPENDENCY_EXPRESSION    *StringToSearchExp;  ///< left value\r
+} HII_DEPENDENCY_TOKEN;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_SPAN\r
+///\r
+typedef struct  {\r
+  UINT8                        Operand;\r
+  UINT8                        Flags;\r
+  HII_DEPENDENCY_EXPRESSION    *IndexExp;            ///< right value\r
+  HII_DEPENDENCY_EXPRESSION    *CharsetExp;          ///< middle value\r
+  HII_DEPENDENCY_EXPRESSION    *StringToSearchExp;   ///< left value\r
+} HII_DEPENDENCY_SPAN;\r
+\r
+///\r
+/// Map expression\r
+///\r
+typedef struct {\r
+  HII_DEPENDENCY_EXPRESSION    *MatchExp;\r
+  HII_DEPENDENCY_EXPRESSION    *ReturnExp;\r
+} HII_DEPENDENCY_EXPRESSION_PAIR;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_MAP\r
+///\r
+typedef struct  {\r
+  UINT8                             Operand;\r
+  HII_DEPENDENCY_EXPRESSION         *SubExp;\r
+  HII_DEPENDENCY_EXPRESSION_PAIR    *ExpPair;\r
+  UINT8                             ExpPairNo;\r
+} HII_DEPENDENCY_MAP;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_EXPRESSION\r
+///\r
+union _HII_DEPENDENCY_EXPRESSION {\r
+  ///\r
+  /// Constant\r
+  ///\r
+  HII_EXPRESSION_CONSTANT          ConstantExp;\r
+  ///\r
+  /// build-in expression\r
+  ///\r
+  HII_DEPENDENCY_DUP               DupExp;\r
+  HII_DEPENDENCY_EQ_ID_VAL         EqIdValExp;\r
+  HII_DEPENDENCY_EQ_ID_ID          EqIdIdExp;\r
+  HII_DEPENDENCY_EQ_ID_VAL_LIST    EqIdListExp;\r
+  HII_DEPENDENCY_QUESTION_REF1     QuestionRef1Exp;\r
+  HII_DEPENDENCY_RULE_REF          RuleRefExp;\r
+  HII_DEPENDENCY_STRING_REF1       StringRef1Exp;\r
+  HII_DEPENDENCY_THIS              ThisExp;\r
+  HII_DEPENDENCY_SECURITY          SecurityExp;\r
+  HII_DEPENDENCY_GET               GetExp;\r
+\r
+  ///\r
+  /// unary expression\r
+  ///\r
+  HII_DEPENDENCY_LENGTH            LengthExp;\r
+  HII_DEPENDENCY_BITWISE_NOT       BitWiseNotExp;\r
+  HII_DEPENDENCY_STRING_REF2       StringRef2Exp;\r
+  HII_DEPENDENCY_QUESTION_REF2     QuestionRef2Exp;\r
+  HII_DEPENDENCY_QUESTION_REF3     QuestionRef3Exp;\r
+  HII_DEPENDENCY_TO_BOOLEAN        ToBooleanExp;\r
+  HII_DEPENDENCY_TO_STRING         ToStringExp;\r
+  HII_DEPENDENCY_TO_UINT           ToUintExp;\r
+  HII_DEPENDENCY_TO_UPPER          ToUpperExp;\r
+  HII_DEPENDENCY_TO_LOWER          ToLowerExp;\r
+  HII_DEPENDENCY_SET               SetExp;\r
+  HII_DEPENDENCY_NOT               NotExp;\r
+\r
+  ///\r
+  /// Binary expression\r
+  ///\r
+  HII_DEPENDENCY_CATENATE          CatenateExp;\r
+  HII_DEPENDENCY_MATCH             MatchExp;\r
+  HII_DEPENDENCY_MATCH2            Match2Exp;\r
+  HII_DEPENDENCY_MULT              MultExp;\r
+  HII_DEPENDENCY_DIV               DivExp;\r
+  HII_DEPENDENCY_MOD               ModExp;\r
+  HII_DEPENDENCY_ADD               AddExp;\r
+  HII_DEPENDENCY_SUBTRACT          SubtractExp;\r
+  HII_DEPENDENCY_SHIFT_LEFT        ShiftLeftExp;\r
+  HII_DEPENDENCY_SHIFT_RIGHT       ShiftRightExp;\r
+  HII_DEPENDENCY_GREATER_THAN      GreaterThanExp;\r
+  HII_DEPENDENCY_GREATER_EQUAL     GreaterEqualExp;\r
+  HII_DEPENDENCY_LESS_THAN         LessThanExp;\r
+  HII_DEPENDENCY_LESS_EQUAL        LessEqualExp;\r
+  HII_DEPENDENCY_EQUAL             EqualExp;\r
+  HII_DEPENDENCY_NOT_EQUAL         NotEqualExp;\r
+  HII_DEPENDENCY_BITWISE_AND       BitwiseAndExp;\r
+  HII_DEPENDENCY_BITWISE_OR        BitwiseOrExp;\r
+  HII_DEPENDENCY_AND               AndExp;\r
+  HII_DEPENDENCY_OR                OrExp;\r
+\r
+  ///\r
+  /// ternary expression\r
+  ///\r
+  HII_DEPENDENCY_CONDITIONAL       ConditionalExp;\r
+  HII_DEPENDENCY_FIND              FindExp;\r
+  HII_DEPENDENCY_MID               MidExp;\r
+  HII_DEPENDENCY_TOKEN             TokenExp;\r
+  HII_DEPENDENCY_SPAN              SpanExp;\r
+  HII_DEPENDENCY_MAP               MapExp;\r
+};\r
+\r
+///\r
+/// Definition of HII_EXPRESSION_OPCODE\r
+///\r
+typedef struct {\r
+  UINTN                          Signature;\r
+  LIST_ENTRY                     Link;\r
+  UINT8                          Operand;\r
+  HII_EXPRESSION_OPCODE_EXTRA    ExtraData;\r
+  LIST_ENTRY                     MapExpressionList; ///< nested expressions inside of Map opcode.\r
+} HII_EXPRESSION_OPCODE;\r
+\r
+#define HII_EXPRESSION_OPCODE_SIGNATURE  SIGNATURE_32 ('E', 'X', 'O', 'P')\r
+#define HII_EXPRESSION_OPCODE_FROM_LINK(a)  CR (a, HII_EXPRESSION_OPCODE, Link, HII_EXPRESSION_OPCODE_SIGNATURE)\r
+\r
+///\r
+/// Definition of HII_WARNING_IF_DATA\r
+///\r
+typedef struct {\r
+  EFI_STRING_ID    WarningIfError;\r
+  UINT8            TimeOut;\r
+} HII_WARNING_IF_DATA;\r
+\r
+///\r
+/// Definition of HII_EXTRA_DATA\r
+///\r
+typedef union {\r
+  UINT8                  RuleId;      ///< For EFI_IFR_RULE only\r
+  EFI_STRING_ID          Error;       ///< For EFI_IFR_NO_SUBMIT_IF, EFI_IFR_INCONSISTENT_IF only\r
+  HII_WARNING_IF_DATA    WarningIfData;\r
+} HII_EXTRA_DATA;\r
+\r
+///\r
+/// Definition of HII_EXPRESSION\r
+///\r
+typedef struct {\r
+  UINTN                        Signature;\r
+  LIST_ENTRY                   Link;\r
+  UINT8                        Type;               ///< Type for this expression\r
+  EFI_IFR_OP_HEADER            *OpCode;            ///< Save the opcode buffer.\r
+  LIST_ENTRY                   OpCodeListHead;     ///< OpCodes consist of this expression (HII_EXPRESSION_OPCODE)\r
+  HII_DEPENDENCY_EXPRESSION    *RootDependencyExp; ///< Expression OpCodes tree layout to describe dependency of this expression.\r
+  HII_EXTRA_DATA               ExtraData;\r
+  EFI_HII_VALUE                Result;             ///< Expression evaluation result\r
+} HII_EXPRESSION;\r
+\r
+#define HII_EXPRESSION_SIGNATURE  SIGNATURE_32 ('F', 'E', 'X', 'P')\r
+#define HII_EXPRESSION_FROM_LINK(a)  CR (a, HII_EXPRESSION, Link, HII_EXPRESSION_SIGNATURE)\r
+\r
+///\r
+/// Definition of HII_EXPRESSION_LIST\r
+///\r
+typedef struct {\r
+  UINTN             Signature;\r
+  UINTN             Count;\r
+  HII_EXPRESSION    *Expression[1];    ///< Array[Count] of expressions\r
+} HII_EXPRESSION_LIST;\r
+\r
+#define HII_EXPRESSION_LIST_SIGNATURE  SIGNATURE_32 ('F', 'E', 'X', 'R')\r
+\r
+///\r
+/// Definition of HII_STATEMENT_VALUE\r
+///\r
+typedef struct {\r
+  ///\r
+  /// HII Data Type\r
+  ///\r
+  UINT8                 Type;\r
+  EFI_IFR_TYPE_VALUE    Value;\r
+  ///\r
+  /// Buffer Data and Length if Type is EFI_IFR_TYPE_BUFFER or EFI_IFR_TYPE_STRING\r
+  ///\r
+  UINT8                 *Buffer;\r
+  UINT16                BufferLen;\r
+  UINT8                 BufferValueType; ///< Data type for buffer internal data, currently only for orderedlist\r
+} HII_STATEMENT_VALUE;\r
+\r
+///\r
+/// Default value\r
+///\r
+typedef struct {\r
+  UINTN                  Signature;\r
+  LIST_ENTRY             Link;\r
+\r
+  UINT16                 DefaultId;\r
+  HII_STATEMENT_VALUE    Value;            ///< Default value\r
+\r
+  HII_EXPRESSION         *ValueExpression; ///< Not-NULL indicates default value is provided by EFI_IFR_VALUE\r
+} HII_QUESTION_DEFAULT;\r
+\r
+#define HII_QUESTION_DEFAULT_SIGNATURE  SIGNATURE_32 ('Q', 'D', 'F', 'T')\r
+#define HII_QUESTION_DEFAULT_FROM_LINK(a)  CR (a, HII_QUESTION_DEFAULT, Link, HII_QUESTION_DEFAULT_SIGNATURE)\r
+\r
+#define HII_QUESTION_OPTION_SIGNATURE  SIGNATURE_32 ('Q', 'O', 'P', 'T')\r
+\r
+///\r
+/// Option value\r
+///\r
+typedef struct {\r
+  UINTN                    Signature;\r
+  LIST_ENTRY               Link;\r
+\r
+  EFI_IFR_ONE_OF_OPTION    *OpCode;             ///< OneOfOption Data\r
+\r
+  EFI_STRING_ID            Text;\r
+  UINT8                    Flags;\r
+  HII_STATEMENT_VALUE      Value;\r
+  EFI_IMAGE_ID             ImageId;\r
+\r
+  HII_EXPRESSION_LIST      *SuppressExpression; ///< Non-NULL indicates nested inside of SuppressIf\r
+} HII_QUESTION_OPTION;\r
+\r
+#define HII_QUESTION_OPTION_FROM_LINK(a)  CR (a, HII_QUESTION_OPTION, Link, HII_QUESTION_OPTION_SIGNATURE)\r
+\r
+///\r
+/// class of default\r
+///\r
+typedef struct {\r
+  UINTN            Signature;\r
+  LIST_ENTRY       Link;\r
+\r
+  UINT16           DefaultId;\r
+  EFI_STRING_ID    DefaultName;\r
+} HII_FORMSET_DEFAULTSTORE;\r
+\r
+#define HII_FORMSET_DEFAULTSTORE_SIGNATURE  SIGNATURE_32 ('F', 'D', 'F', 'S')\r
+#define HII_FORMSET_DEFAULTSTORE_FROM_LINK(a)  CR (a, HII_FORMSET_DEFAULTSTORE, Link, HII_FORMSET_DEFAULTSTORE_SIGNATURE)\r
+\r
+///\r
+/// Definition of HII_STATEMENT_EXTRA\r
+///\r
+typedef union {\r
+  UINT8             Flags;\r
+  EFI_STRING_ID     TextTwo;\r
+  EFI_DEFAULT_ID    DefaultId;\r
+  EFI_STRING_ID     QuestionConfig;\r
+  EFI_GUID          Guid;\r
+\r
+  struct {\r
+    UINT8       Flags;\r
+    UINT64      Minimum;            ///< for EFI_IFR_ONE_OF/EFI_IFR_NUMERIC, it's Min/Max value\r
+    UINT64      Maximum;            ///< for EFI_IFR_STRING/EFI_IFR_PASSWORD, it's Min/Max length\r
+    UINT64      Step;\r
+    EFI_GUID    Guid;\r
+  } NumData;\r
+\r
+  struct {\r
+    UINT8    Flags;\r
+    UINT8    MaxContainers;         ///< for EFI_IFR_ORDERED_LIST\r
+  } OrderListData;\r
+\r
+  struct {\r
+    UINT8    Flags;\r
+    UINT8    MinSize;\r
+    UINT8    MaxSize;\r
+  } StrData;\r
+\r
+  struct {\r
+    UINT16    MinSize;\r
+    UINT16    MaxSize;\r
+  } PwdData;\r
+} HII_STATEMENT_EXTRA;\r
+\r
+///\r
+/// Statement (Question)\r
+///\r
+typedef struct _HII_STATEMENT HII_STATEMENT;\r
+struct _HII_STATEMENT {\r
+  UINTN                  Signature;\r
+  LIST_ENTRY             Link;\r
+\r
+  UINT8                  Operand;         ///< The operand (first byte) of this Statement or Question\r
+  EFI_IFR_OP_HEADER      *OpCode;\r
+\r
+  ///\r
+  /// Statement Header\r
+  ///\r
+  EFI_STRING_ID          Prompt;\r
+  EFI_STRING_ID          Help;\r
+\r
+  ///\r
+  /// Question Header\r
+  ///\r
+  EFI_QUESTION_ID        QuestionId;      ///< Question id, the value of zero is reserved\r
+  EFI_VARSTORE_ID        VarStoreId;      ///< VarStore id, a value of zero indicates no variable storage\r
+  HII_VAR_STORE_INFO     VarStoreInfo;    ///< VarStoreInfoIf VarStoreId refers to Buffer Storage (EFI_IFR_VARSTORE or EFI_IFR_VARSTORE_EFI), then VarStoreInfo contains a 16-bit Buffer Storage offset (VarOffset).\r
+                                          ///< If VarStoreId refers to Name/Value Storage (EFI_IFR_VARSTORE_NAME_VALUE), then VarStoreInfo contains the String ID of the name (VarName) for this name/value pair.\r
+  UINT8                  QuestionFlags;   ///< The flag of this Question.(Readonly, reset required, callback attribute....)\r
+\r
+  BOOLEAN                QuestionReferToBitField;   ///< Whether the question is stored in a bit field.\r
+  UINT16                 StorageWidth;              ///< The storage width of this Question.\r
+  UINT16                 BitStorageWidth;           ///< The Storage width of this Question in bit level.\r
+  UINT16                 BitVarOffset;              ///< The storage offset of this Question in bit level.\r
+  CHAR16                 *VariableName;             ///< Name/Value or EFI Variable name\r
+  CHAR16                 *BlockName;                ///< Buffer storage block name: "OFFSET=...WIDTH=..."\r
+\r
+  HII_FORMSET_STORAGE    *Storage;                  ///< Point to the storage that store this question.\r
+  HII_STATEMENT_EXTRA    ExtraData;\r
+\r
+  BOOLEAN                Locked;                    ///< Whether this statement is locked.\r
+\r
+  HII_STATEMENT_VALUE    Value;\r
+\r
+  ///\r
+  /// Get from IFR parsing\r
+  ///\r
+\r
+  HII_STATEMENT          *ParentStatement;     ///< Parent Statement of current statement.\r
+  HII_EXPRESSION_LIST    *ExpressionList;      ///< nesting inside of GrayedOutIf/DisableIf/SuppressIf\r
+  HII_EXPRESSION         *ValueExpression;     ///< nested EFI_IFR_VALUE, provide Question value and indicate Question is ReadOnly\r
+\r
+  EFI_IMAGE_ID           ImageId;              ///< nested EFI_IFR_IMAGE\r
+  UINT8                  RefreshInterval;      ///< nested EFI_IFR_REFRESH, refresh interval(in seconds) for Question value, 0 means no refresh\r
+\r
+  LIST_ENTRY             DefaultListHead;      ///< nested EFI_IFR_DEFAULT list (HII_QUESTION_DEFAULT), provide default values\r
+  LIST_ENTRY             OptionListHead;       ///< nested EFI_IFR_ONE_OF_OPTION list (HII_QUESTION_OPTION)\r
+  LIST_ENTRY             InconsistentListHead; ///< nested inconsistent expression list (HII_EXPRESSION)\r
+  LIST_ENTRY             NoSubmitListHead;     ///< nested nosubmit expression list (HII_EXPRESSION)\r
+  LIST_ENTRY             WarningListHead;      ///< nested warning expression list (HII_EXPRESSION)\r
+\r
+  HII_EXPRESSION         *ReadExpression;       ///< nested EFI_IFR_READ, provide this question value by read expression.\r
+  HII_EXPRESSION         *WriteExpression;      ///< nested EFI_IFR_WRITE, evaluate write expression after this question value is set.\r
+};\r
+\r
+#define HII_STATEMENT_SIGNATURE  SIGNATURE_32 ('H', 'S', 'T', 'A')\r
+#define HII_STATEMENT_FROM_LINK(a)  CR (a, HII_STATEMENT, Link, HII_STATEMENT_SIGNATURE)\r
+\r
+///\r
+/// Form\r
+///\r
+#define STANDARD_MAP_FORM_TYPE  0x01\r
+\r
+typedef struct {\r
+  UINTN                  Signature;\r
+  LIST_ENTRY             Link;\r
+\r
+  UINT16                 FormId;              ///< FormId of normal form or formmap form.\r
+  EFI_STRING_ID          FormTitle;           ///< FormTile of normal form, or FormMapMethod title of formmap form.\r
+  UINT16                 FormType;            ///< Specific form type for the different form.\r
+\r
+  EFI_IMAGE_ID           ImageId;             ///< The image id.\r
+\r
+  BOOLEAN                ModalForm;           ///< Whether this is a modal form.\r
+  BOOLEAN                Locked;              ///< Whether this form is locked.\r
+  EFI_GUID               RefreshGuid;         ///< Form refresh event guid.\r
+\r
+  LIST_ENTRY             StatementListHead;   ///< List of Statements and Questions (HII_STATEMENT)\r
+  LIST_ENTRY             ConfigRequestHead;   ///< List of configrequest for all storage.\r
+  LIST_ENTRY             RuleListHead;        ///< nested EFI_IFR_RULE list, pre-defined expressions attached to the form.\r
+  HII_EXPRESSION_LIST    *SuppressExpression; ///< nesting inside of SuppressIf\r
+} HII_FORM;\r
+\r
+#define HII_FORM_SIGNATURE  SIGNATURE_32 ('F', 'F', 'R', 'M')\r
+#define HII_FORM_FROM_LINK(a)  CR (a, HII_FORM, Link, HII_FORM_SIGNATURE)\r
+\r
+///\r
+/// FormSet\r
+///\r
+typedef struct {\r
+  UINTN                             Signature;\r
+  LIST_ENTRY                        Link;\r
+\r
+  EFI_HII_HANDLE                    HiiHandle;             ///< Unique id for formset, HII Handle of this FormSet package.\r
+  EFI_HANDLE                        DriverHandle;          ///< EFI_HANDLE which was registered with the package list in NewPackageList().\r
+  EFI_HII_CONFIG_ACCESS_PROTOCOL    *ConfigAccess;         ///< ConfigAccess Protocol associated with this HiiPackageList\r
+  EFI_DEVICE_PATH_PROTOCOL          *DevicePath;\r
+\r
+  UINTN                             IfrBinaryLength;       ///< Ifr binary data length of this formset.\r
+  UINT8                             *IfrBinaryData;        ///< Point to the Ifr binary data.\r
+\r
+  EFI_GUID                          Guid;                  ///< Formset Guid.\r
+  EFI_STRING_ID                     FormSetTitle;          ///< String Id of Formset title.\r
+  EFI_STRING_ID                     Help;                  ///< String Id of Formset title.\r
+\r
+  UINT8                             NumberOfClassGuid;     ///< Class Guid name\r
+  EFI_GUID                          ClassGuid[3];          ///< Up to three ClassGuid\r
+\r
+  EFI_IMAGE_ID                      ImageId;               ///< The image id.\r
+\r
+  LIST_ENTRY                        StatementListOSF;      ///< Statement list out side of the form.\r
+  LIST_ENTRY                        StorageListHead;       ///< Storage list (HII_FORMSET_STORAGE)\r
+  LIST_ENTRY                        DefaultStoreListHead;  ///< DefaultStore list (HII_FORMSET_DEFAULTSTORE)\r
+  LIST_ENTRY                        FormListHead;          ///< Form list (HII_FORM_BROWSER_FORM)\r
+} HII_FORMSET;\r
+\r
+#define HII_FORMSET_SIGNATURE  SIGNATURE_32 ('H', 'I', 'F', 'S')\r
+#define HII_FORMSET_FROM_LINK(a)  CR (a, HII_FORMSET, Link, HII_FORMSET_SIGNATURE)\r
+\r
+///\r
+/// Get/set question value from/to.\r
+///\r
+typedef enum {\r
+  GetSetValueWithBuffer = 0,       ///< Get/Set question value from/to buffer in the storage.\r
+  GetSetValueWithHiiDriver,        ///< Get/Set question value from/to hii driver.\r
+  GetSetValueWithBoth,             ///< Compare the editbuffer with buffer for this question, not use the question value.\r
+  GetSetValueWithMax               ///< Invalid value.\r
+} GET_SET_QUESTION_VALUE_WITH;\r
+\r
+/**\r
+  Initialize the internal data structure of a FormSet.\r
+\r
+  @param[in]      Handle         PackageList Handle\r
+  @param[in,out]  FormSetGuid    On input, GUID or class GUID of a formset. If not\r
+                                 specified (NULL or zero GUID), take the first\r
+                                 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
+                                 found in package list.\r
+                                 On output, GUID of the formset found(if not NULL).\r
+  @param[out]     FormSet        FormSet data structure.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+  @retval EFI_NOT_FOUND          The specified FormSet could not be found.\r
+\r
+**/\r
+EFI_STATUS\r
+CreateFormSetFromHiiHandle (\r
+  IN     EFI_HII_HANDLE  Handle,\r
+  IN OUT EFI_GUID        *FormSetGuid,\r
+  OUT HII_FORMSET        *FormSet\r
+  );\r
+\r
+/**\r
+  Initialize a Formset and get current setting for Questions.\r
+\r
+  @param[in,out]  FormSet                FormSet data structure.\r
+\r
+**/\r
+VOID\r
+InitializeFormSet (\r
+  IN OUT HII_FORMSET  *FormSet\r
+  );\r
+\r
+/**\r
+  Free resources allocated for a FormSet.\r
+\r
+  @param[in,out]  FormSet                Pointer of the FormSet\r
+\r
+**/\r
+VOID\r
+DestroyFormSet (\r
+  IN OUT HII_FORMSET  *FormSet\r
+  );\r
+\r
+/**\r
+  Save Question Value to the memory, but not to storage.\r
+\r
+  @param[in]     FormSet                FormSet data structure.\r
+  @param[in]     Form                   Form data structure.\r
+  @param[in,out] Question               Pointer to the Question.\r
+  @param[in]     QuestionValue          New Question Value to be set.\r
+\r
+  @retval EFI_SUCCESS            The question value has been set successfully.\r
+  @retval EFI_INVALID_PARAMETER  One or more parameters are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+SetQuestionValue (\r
+  IN     HII_FORMSET          *FormSet,\r
+  IN     HII_FORM             *Form,\r
+  IN OUT HII_STATEMENT        *Question,\r
+  IN     HII_STATEMENT_VALUE  *QuestionValue\r
+  );\r
+\r
+/**\r
+  Get Question's current Value from storage.\r
+\r
+  @param[in]     FormSet                FormSet data structure.\r
+  @param[in]     Form                   Form data structure.\r
+  @param[in,out] Question               Question to be initialized.\r
+\r
+  @return the current Question Value in storage if success.\r
+  @return NULL if Question is not found or any error occurs.\r
+\r
+**/\r
+HII_STATEMENT_VALUE *\r
+RetrieveQuestion (\r
+  IN     HII_FORMSET    *FormSet,\r
+  IN     HII_FORM       *Form,\r
+  IN OUT HII_STATEMENT  *Question\r
+  );\r
+\r
+/**\r
+  Get Question's current Value.\r
+\r
+  @param[in]   FormSet                FormSet data structure.\r
+  @param[in]   Form                   Form data structure.\r
+  @param[out]  Question               Question to be initialized.\r
+  @param[in]   GetValueFrom           Where to get value, may from editbuffer, buffer or hii driver.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+  @retval EFI_INVALID_PARAMETER  Formset, Form or Question is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+GetQuestionValue (\r
+  IN HII_FORMSET                  *FormSet,\r
+  IN HII_FORM                     *Form,\r
+  IN OUT HII_STATEMENT            *Question,\r
+  IN GET_SET_QUESTION_VALUE_WITH  GetValueFrom\r
+  );\r
+\r
+/**\r
+  Submit data for a form.\r
+\r
+  @param[in]  FormSet                FormSet which contains the Form.\r
+  @param[in]  Form                   Form to submit.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+  @retval Others                 Other errors occur.\r
+\r
+**/\r
+EFI_STATUS\r
+SubmitForm (\r
+  IN     HII_FORMSET  *FormSet,\r
+  IN     HII_FORM     *Form\r
+  );\r
+\r
+/**\r
+  Evaluate the result of a HII expression.\r
+\r
+  If Expression is NULL, then ASSERT.\r
+\r
+  @param[in]     FormSet                FormSet associated with this expression.\r
+  @param[in]     Form                   Form associated with this expression.\r
+  @param[in,out] Expression             Expression to be evaluated.\r
+\r
+  @retval EFI_SUCCESS            The expression evaluated successfully\r
+  @retval EFI_NOT_FOUND          The Question which referenced by a QuestionId\r
+                                 could not be found.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the\r
+                                 stack.\r
+  @retval EFI_ACCESS_DENIED      The pop operation underflowed the stack\r
+  @retval EFI_INVALID_PARAMETER  Syntax error with the Expression\r
+\r
+**/\r
+EFI_STATUS\r
+EvaluateHiiExpression (\r
+  IN     HII_FORMSET     *FormSet,\r
+  IN     HII_FORM        *Form,\r
+  IN OUT HII_EXPRESSION  *Expression\r
+  );\r
+\r
+/**\r
+  Retrieve dependencies within an expression. These dependencies can express how\r
+  this expression will be evaluated.\r
+\r
+  @param[in]  Expression             Expression to retrieve dependencies.\r
+\r
+  @retval EFI_SUCCESS            The dependencies were successfully retrieved.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory.\r
+\r
+**/\r
+EFI_STATUS\r
+GetHiiExpressionDependency (\r
+  IN HII_EXPRESSION  *Expression\r
+  );\r
+\r
+/**\r
+  Get default value of question.\r
+\r
+  @param[in]  FormSet                The form set.\r
+  @param[in]  Form                   The form.\r
+  @param[in]  Question               The question.\r
+  @param[in]  DefaultId              The Class of the default.\r
+  @param[out] DefaultValue           The default value of given question.\r
+\r
+  @retval EFI_SUCCESS            Question is reset to default value.\r
+\r
+**/\r
+EFI_STATUS\r
+GetQuestionDefault (\r
+  IN HII_FORMSET           *FormSet,\r
+  IN HII_FORM              *Form,\r
+  IN HII_STATEMENT         *Question,\r
+  IN UINT16                DefaultId,\r
+  OUT HII_STATEMENT_VALUE  *DefaultValue\r
+  );\r
+\r
+/**\r
+  Return the result of the expression list. Check the expression list and\r
+  return the highest priority express result.\r
+  Priority: DisableIf > SuppressIf > GrayOutIf > FALSE\r
+\r
+  @param[in]  ExpList         The input expression list.\r
+  @param[in]  Evaluate        Whether need to evaluate the expression first.\r
+  @param[in]  FormSet         FormSet associated with this expression.\r
+  @param[in]  Form            Form associated with this expression.\r
+\r
+  @retval EXPRESS_RESULT      Return the higher priority express result.\r
+                              DisableIf > SuppressIf > GrayOutIf > FALSE\r
+\r
+**/\r
+EXPRESS_RESULT\r
+EvaluateExpressionList (\r
+  IN HII_EXPRESSION_LIST  *ExpList,\r
+  IN BOOLEAN              Evaluate,\r
+  IN HII_FORMSET          *FormSet OPTIONAL,\r
+  IN HII_FORM             *Form OPTIONAL\r
+  );\r
+\r
+#endif // HII_UTILITY_LIB_\r
diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiExpression.c b/RedfishPkg/Library/HiiUtilityLib/HiiExpression.c
new file mode 100644 (file)
index 0000000..c36c241
--- /dev/null
@@ -0,0 +1,1439 @@
+/** @file\r
+  The implementation of HII expression.\r
+\r
+  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+  (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>\r
+  Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.\r
+\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+#include "HiiInternal.h"\r
+\r
+//\r
+// Global stack used to evaluate boolean expressions\r
+//\r
+EFI_HII_VALUE  *mOpCodeScopeStack        = NULL;\r
+EFI_HII_VALUE  *mOpCodeScopeStackEnd     = NULL;\r
+EFI_HII_VALUE  *mOpCodeScopeStackPointer = NULL;\r
+\r
+//\r
+// Stack used for Suppressif/grayoutif/disableif expression list.\r
+//\r
+HII_EXPRESSION  **mFormExpressionStack   = NULL;\r
+HII_EXPRESSION  **mFormExpressionEnd     = NULL;\r
+HII_EXPRESSION  **mFormExpressionPointer = NULL;\r
+\r
+HII_EXPRESSION  **mStatementExpressionStack   = NULL;\r
+HII_EXPRESSION  **mStatementExpressionEnd     = NULL;\r
+HII_EXPRESSION  **mStatementExpressionPointer = NULL;\r
+\r
+HII_EXPRESSION  **mOptionExpressionStack   = NULL;\r
+HII_EXPRESSION  **mOptionExpressionEnd     = NULL;\r
+HII_EXPRESSION  **mOptionExpressionPointer = NULL;\r
+\r
+//\r
+// Stack used for the sub expresion in map expression.\r
+//\r
+EFI_HII_VALUE  *mCurrentExpressionStack   = NULL;\r
+EFI_HII_VALUE  *mCurrentExpressionEnd     = NULL;\r
+EFI_HII_VALUE  *mCurrentExpressionPointer = NULL;\r
+\r
+//\r
+// Stack used for the map expression list.\r
+//\r
+EFI_HII_VALUE  *mMapExpressionListStack   = NULL;\r
+EFI_HII_VALUE  *mMapExpressionListEnd     = NULL;\r
+EFI_HII_VALUE  *mMapExpressionListPointer = NULL;\r
+\r
+//\r
+// Stack used for dependency expression.\r
+//\r
+HII_DEPENDENCY_EXPRESSION  **mExpressionDependencyStack   = NULL;\r
+HII_DEPENDENCY_EXPRESSION  **mExpressionDependencyEnd     = NULL;\r
+HII_DEPENDENCY_EXPRESSION  **mExpressionDependencyPointer = NULL;\r
+\r
+/**\r
+  Grow size of the stack.\r
+\r
+  This is an internal function.\r
+\r
+  @param  Stack                  On input: old stack; On output: new stack\r
+  @param  StackPtr               On input: old stack pointer; On output: new stack\r
+                                 pointer\r
+  @param  StackEnd               On input: old stack end; On output: new stack end\r
+\r
+  @retval EFI_SUCCESS            Grow stack success.\r
+  @retval EFI_OUT_OF_RESOURCES   No enough memory for stack space.\r
+\r
+**/\r
+EFI_STATUS\r
+GrowStack (\r
+  IN OUT EFI_HII_VALUE  **Stack,\r
+  IN OUT EFI_HII_VALUE  **StackPtr,\r
+  IN OUT EFI_HII_VALUE  **StackEnd\r
+  )\r
+{\r
+  UINTN          Size;\r
+  EFI_HII_VALUE  *NewStack;\r
+\r
+  Size = EXPRESSION_STACK_SIZE_INCREMENT;\r
+  if (*StackPtr != NULL) {\r
+    Size = Size + (*StackEnd - *Stack);\r
+  }\r
+\r
+  NewStack = AllocatePool (Size * sizeof (EFI_HII_VALUE));\r
+  if (NewStack == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  if (*StackPtr != NULL) {\r
+    //\r
+    // Copy from Old Stack to the New Stack\r
+    //\r
+    CopyMem (\r
+      NewStack,\r
+      *Stack,\r
+      (*StackEnd - *Stack) * sizeof (EFI_HII_VALUE)\r
+      );\r
+\r
+    //\r
+    // Free The Old Stack\r
+    //\r
+    FreePool (*Stack);\r
+  }\r
+\r
+  //\r
+  // Make the Stack pointer point to the old data in the new stack\r
+  //\r
+  *StackPtr = NewStack + (*StackPtr - *Stack);\r
+  *Stack    = NewStack;\r
+  *StackEnd = NewStack + Size;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Push an element onto the Boolean Stack.\r
+\r
+  @param  Stack                  On input: old stack; On output: new stack\r
+  @param  StackPtr               On input: old stack pointer; On output: new stack\r
+                                 pointer\r
+  @param  StackEnd               On input: old stack end; On output: new stack end\r
+  @param  Data                   Data to push.\r
+\r
+  @retval EFI_SUCCESS            Push stack success.\r
+\r
+**/\r
+EFI_STATUS\r
+PushStack (\r
+  IN OUT EFI_HII_VALUE  **Stack,\r
+  IN OUT EFI_HII_VALUE  **StackPtr,\r
+  IN OUT EFI_HII_VALUE  **StackEnd,\r
+  IN     EFI_HII_VALUE  *Data\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // Check for a stack overflow condition\r
+  //\r
+  if (*StackPtr >= *StackEnd) {\r
+    //\r
+    // Grow the stack\r
+    //\r
+    Status = GrowStack (Stack, StackPtr, StackEnd);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Push the item onto the stack\r
+  //\r
+  CopyMem (*StackPtr, Data, sizeof (EFI_HII_VALUE));\r
+  if (Data->Type == EFI_IFR_TYPE_BUFFER) {\r
+    (*StackPtr)->Buffer = AllocateCopyPool (Data->BufferLen, Data->Buffer);\r
+    if ((*StackPtr)->Buffer == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+  }\r
+\r
+  *StackPtr = *StackPtr + 1;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Pop an element from the stack.\r
+\r
+  @param  Stack                  On input: old stack\r
+  @param  StackPtr               On input: old stack pointer; On output: new stack pointer\r
+  @param  Data                   Data to pop.\r
+\r
+  @retval EFI_SUCCESS            The value was popped onto the stack.\r
+  @retval EFI_ACCESS_DENIED      The pop operation underflowed the stack\r
+\r
+**/\r
+EFI_STATUS\r
+PopStack (\r
+  IN     EFI_HII_VALUE  *Stack,\r
+  IN OUT EFI_HII_VALUE  **StackPtr,\r
+  OUT EFI_HII_VALUE     *Data\r
+  )\r
+{\r
+  //\r
+  // Check for a stack underflow condition\r
+  //\r
+  if (*StackPtr == Stack) {\r
+    return EFI_ACCESS_DENIED;\r
+  }\r
+\r
+  //\r
+  // Pop the item off the stack\r
+  //\r
+  *StackPtr = *StackPtr - 1;\r
+  CopyMem (Data, *StackPtr, sizeof (EFI_HII_VALUE));\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Reset stack pointer to begin of the stack.\r
+\r
+**/\r
+VOID\r
+ResetCurrentExpressionStack (\r
+  VOID\r
+  )\r
+{\r
+  mCurrentExpressionPointer   = mCurrentExpressionStack;\r
+  mFormExpressionPointer      = mFormExpressionStack;\r
+  mStatementExpressionPointer = mStatementExpressionStack;\r
+  mOptionExpressionPointer    = mOptionExpressionStack;\r
+}\r
+\r
+/**\r
+  Push current expression onto the Stack\r
+\r
+  @param  Pointer                Pointer to current expression.\r
+\r
+  @retval EFI_SUCCESS            The value was pushed onto the stack.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushCurrentExpression (\r
+  IN VOID  *Pointer\r
+  )\r
+{\r
+  EFI_HII_VALUE  Data;\r
+\r
+  Data.Type      = EFI_IFR_TYPE_NUM_SIZE_64;\r
+  Data.Value.u64 = (UINT64)(UINTN)Pointer;\r
+\r
+  return PushStack (\r
+           &mCurrentExpressionStack,\r
+           &mCurrentExpressionPointer,\r
+           &mCurrentExpressionEnd,\r
+           &Data\r
+           );\r
+}\r
+\r
+/**\r
+  Pop current expression from the Stack\r
+\r
+  @param  Pointer                Pointer to current expression to be pop.\r
+\r
+  @retval EFI_SUCCESS            The value was pushed onto the stack.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopCurrentExpression (\r
+  OUT VOID  **Pointer\r
+  )\r
+{\r
+  EFI_STATUS     Status;\r
+  EFI_HII_VALUE  Data;\r
+\r
+  Status = PopStack (\r
+             mCurrentExpressionStack,\r
+             &mCurrentExpressionPointer,\r
+             &Data\r
+             );\r
+\r
+  *Pointer = (VOID *)(UINTN)Data.Value.u64;\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Reset stack pointer to begin of the stack.\r
+\r
+**/\r
+VOID\r
+ResetMapExpressionListStack (\r
+  VOID\r
+  )\r
+{\r
+  mMapExpressionListPointer = mMapExpressionListStack;\r
+}\r
+\r
+/**\r
+  Grow size of the stack.\r
+\r
+  This is an internal function.\r
+\r
+  @param  Stack                  On input: old stack; On output: new stack\r
+  @param  StackPtr               On input: old stack pointer; On output: new stack\r
+                                 pointer\r
+  @param  StackEnd               On input: old stack end; On output: new stack end\r
+  @param  MemberSize             The stack member size.\r
+\r
+  @retval EFI_SUCCESS            Grow stack success.\r
+  @retval EFI_OUT_OF_RESOURCES   No enough memory for stack space.\r
+\r
+**/\r
+EFI_STATUS\r
+GrowConditionalStack (\r
+  IN OUT HII_EXPRESSION  ***Stack,\r
+  IN OUT HII_EXPRESSION  ***StackPtr,\r
+  IN OUT HII_EXPRESSION  ***StackEnd,\r
+  IN     UINTN           MemberSize\r
+  )\r
+{\r
+  UINTN           Size;\r
+  HII_EXPRESSION  **NewStack;\r
+\r
+  Size = EXPRESSION_STACK_SIZE_INCREMENT;\r
+  if (*StackPtr != NULL) {\r
+    Size = Size + (*StackEnd - *Stack);\r
+  }\r
+\r
+  NewStack = AllocatePool (Size * MemberSize);\r
+  if (NewStack == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  if (*StackPtr != NULL) {\r
+    //\r
+    // Copy from Old Stack to the New Stack\r
+    //\r
+    CopyMem (\r
+      NewStack,\r
+      *Stack,\r
+      (*StackEnd - *Stack) * MemberSize\r
+      );\r
+\r
+    //\r
+    // Free The Old Stack\r
+    //\r
+    FreePool (*Stack);\r
+  }\r
+\r
+  //\r
+  // Make the Stack pointer point to the old data in the new stack\r
+  //\r
+  *StackPtr = NewStack + (*StackPtr - *Stack);\r
+  *Stack    = NewStack;\r
+  *StackEnd = NewStack + Size;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Push an element onto the Stack.\r
+\r
+  @param  Stack                  On input: old stack; On output: new stack\r
+  @param  StackPtr               On input: old stack pointer; On output: new stack\r
+                                 pointer\r
+  @param  StackEnd               On input: old stack end; On output: new stack end\r
+  @param  Data                   Data to push.\r
+\r
+  @retval EFI_SUCCESS            Push stack success.\r
+\r
+**/\r
+EFI_STATUS\r
+PushConditionalStack (\r
+  IN OUT HII_EXPRESSION  ***Stack,\r
+  IN OUT HII_EXPRESSION  ***StackPtr,\r
+  IN OUT HII_EXPRESSION  ***StackEnd,\r
+  IN     HII_EXPRESSION  **Data\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // Check for a stack overflow condition\r
+  //\r
+  if (*StackPtr >= *StackEnd) {\r
+    //\r
+    // Grow the stack\r
+    //\r
+    Status = GrowConditionalStack (Stack, StackPtr, StackEnd, sizeof (HII_EXPRESSION *));\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Push the item onto the stack\r
+  //\r
+  CopyMem (*StackPtr, Data, sizeof (HII_EXPRESSION *));\r
+  *StackPtr = *StackPtr + 1;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Pop an element from the stack.\r
+\r
+  @param  Stack                  On input: old stack\r
+  @param  StackPtr               On input: old stack pointer; On output: new stack pointer\r
+  @param  Data                   Data to pop.\r
+\r
+  @retval EFI_SUCCESS            The value was popped onto the stack.\r
+  @retval EFI_ACCESS_DENIED      The pop operation underflowed the stack\r
+\r
+**/\r
+EFI_STATUS\r
+PopConditionalStack (\r
+  IN     HII_EXPRESSION  **Stack,\r
+  IN OUT HII_EXPRESSION  ***StackPtr,\r
+  OUT HII_EXPRESSION     **Data\r
+  )\r
+{\r
+  //\r
+  // Check for a stack underflow condition\r
+  //\r
+  if (*StackPtr == Stack) {\r
+    return EFI_ACCESS_DENIED;\r
+  }\r
+\r
+  //\r
+  // Pop the item off the stack\r
+  //\r
+  *StackPtr = *StackPtr - 1;\r
+  CopyMem (Data, *StackPtr, sizeof (HII_EXPRESSION  *));\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Get the expression list count.\r
+\r
+  @param  Level                  Which type this expression belong to. Form,\r
+                                 statement or option?\r
+\r
+  @retval >=0                    The expression count\r
+  @retval -1                     Input parameter error.\r
+\r
+**/\r
+INTN\r
+GetConditionalExpressionCount (\r
+  IN EXPRESS_LEVEL  Level\r
+  )\r
+{\r
+  switch (Level) {\r
+    case ExpressForm:\r
+      return mFormExpressionPointer - mFormExpressionStack;\r
+    case ExpressStatement:\r
+      return mStatementExpressionPointer - mStatementExpressionStack;\r
+    case ExpressOption:\r
+      return mOptionExpressionPointer - mOptionExpressionStack;\r
+    default:\r
+      ASSERT (FALSE);\r
+      return -1;\r
+  }\r
+}\r
+\r
+/**\r
+  Get the expression Buffer pointer.\r
+\r
+  @param  Level                  Which type this expression belong to. Form,\r
+                                 statement or option?\r
+\r
+  @retval  The start pointer of the expression buffer or NULL.\r
+\r
+**/\r
+HII_EXPRESSION **\r
+GetConditionalExpressionList (\r
+  IN EXPRESS_LEVEL  Level\r
+  )\r
+{\r
+  switch (Level) {\r
+    case ExpressForm:\r
+      return mFormExpressionStack;\r
+    case ExpressStatement:\r
+      return mStatementExpressionStack;\r
+    case ExpressOption:\r
+      return mOptionExpressionStack;\r
+    default:\r
+      ASSERT (FALSE);\r
+      return NULL;\r
+  }\r
+}\r
+\r
+/**\r
+  Push the expression options onto the Stack.\r
+\r
+  @param  Pointer                Pointer to the current expression.\r
+  @param  Level                  Which type this expression belong to. Form,\r
+                                 statement or option?\r
+\r
+  @retval EFI_SUCCESS            The value was pushed onto the stack.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushConditionalExpression (\r
+  IN HII_EXPRESSION  *Pointer,\r
+  IN EXPRESS_LEVEL   Level\r
+  )\r
+{\r
+  switch (Level) {\r
+    case ExpressForm:\r
+      return PushConditionalStack (\r
+               &mFormExpressionStack,\r
+               &mFormExpressionPointer,\r
+               &mFormExpressionEnd,\r
+               &Pointer\r
+               );\r
+    case ExpressStatement:\r
+      return PushConditionalStack (\r
+               &mStatementExpressionStack,\r
+               &mStatementExpressionPointer,\r
+               &mStatementExpressionEnd,\r
+               &Pointer\r
+               );\r
+    case ExpressOption:\r
+      return PushConditionalStack (\r
+               &mOptionExpressionStack,\r
+               &mOptionExpressionPointer,\r
+               &mOptionExpressionEnd,\r
+               &Pointer\r
+               );\r
+    default:\r
+      ASSERT (FALSE);\r
+      return EFI_INVALID_PARAMETER;\r
+  }\r
+}\r
+\r
+/**\r
+  Pop the expression options from the Stack\r
+\r
+  @param  Level                  Which type this expression belong to. Form,\r
+                                 statement or option?\r
+\r
+  @retval EFI_SUCCESS            The value was pushed onto the stack.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopConditionalExpression (\r
+  IN EXPRESS_LEVEL  Level\r
+  )\r
+{\r
+  HII_EXPRESSION  *Pointer;\r
+\r
+  switch (Level) {\r
+    case ExpressForm:\r
+      return PopConditionalStack (\r
+               mFormExpressionStack,\r
+               &mFormExpressionPointer,\r
+               &Pointer\r
+               );\r
+\r
+    case ExpressStatement:\r
+      return PopConditionalStack (\r
+               mStatementExpressionStack,\r
+               &mStatementExpressionPointer,\r
+               &Pointer\r
+               );\r
+\r
+    case ExpressOption:\r
+      return PopConditionalStack (\r
+               mOptionExpressionStack,\r
+               &mOptionExpressionPointer,\r
+               &Pointer\r
+               );\r
+\r
+    default:\r
+      ASSERT (FALSE);\r
+      return EFI_INVALID_PARAMETER;\r
+  }\r
+}\r
+\r
+/**\r
+  Push the list of map expression onto the Stack\r
+\r
+  @param  Pointer                Pointer to the list of map expression to be pushed.\r
+\r
+  @retval EFI_SUCCESS            The value was pushed onto the stack.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushMapExpressionList (\r
+  IN VOID  *Pointer\r
+  )\r
+{\r
+  EFI_HII_VALUE  Data;\r
+\r
+  Data.Type      = EFI_IFR_TYPE_NUM_SIZE_64;\r
+  Data.Value.u64 = (UINT64)(UINTN)Pointer;\r
+\r
+  return PushStack (\r
+           &mMapExpressionListStack,\r
+           &mMapExpressionListPointer,\r
+           &mMapExpressionListEnd,\r
+           &Data\r
+           );\r
+}\r
+\r
+/**\r
+  Pop the list of map expression from the Stack\r
+\r
+  @param  Pointer                Pointer to the list of map expression to be pop.\r
+\r
+  @retval EFI_SUCCESS            The value was pushed onto the stack.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopMapExpressionList (\r
+  OUT VOID  **Pointer\r
+  )\r
+{\r
+  EFI_STATUS     Status;\r
+  EFI_HII_VALUE  Data;\r
+\r
+  Status = PopStack (\r
+             mMapExpressionListStack,\r
+             &mMapExpressionListPointer,\r
+             &Data\r
+             );\r
+\r
+  *Pointer = (VOID *)(UINTN)Data.Value.u64;\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Reset stack pointer to begin of the stack.\r
+\r
+**/\r
+VOID\r
+ResetScopeStack (\r
+  VOID\r
+  )\r
+{\r
+  mOpCodeScopeStackPointer = mOpCodeScopeStack;\r
+}\r
+\r
+/**\r
+  Push an Operand onto the Stack\r
+\r
+  @param  Operand                Operand to push.\r
+\r
+  @retval EFI_SUCCESS            The value was pushed onto the stack.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the\r
+                                 stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushScope (\r
+  IN UINT8  Operand\r
+  )\r
+{\r
+  EFI_HII_VALUE  Data;\r
+\r
+  Data.Type     = EFI_IFR_TYPE_NUM_SIZE_8;\r
+  Data.Value.u8 = Operand;\r
+\r
+  return PushStack (\r
+           &mOpCodeScopeStack,\r
+           &mOpCodeScopeStackPointer,\r
+           &mOpCodeScopeStackEnd,\r
+           &Data\r
+           );\r
+}\r
+\r
+/**\r
+  Pop an Operand from the Stack\r
+\r
+  @param  Operand                Operand to pop.\r
+\r
+  @retval EFI_SUCCESS            The value was pushed onto the stack.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the\r
+                                 stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopScope (\r
+  OUT UINT8  *Operand\r
+  )\r
+{\r
+  EFI_STATUS     Status;\r
+  EFI_HII_VALUE  Data;\r
+\r
+  Status = PopStack (\r
+             mOpCodeScopeStack,\r
+             &mOpCodeScopeStackPointer,\r
+             &Data\r
+             );\r
+\r
+  *Operand = Data.Value.u8;\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Grow size of the stack for Expression Dependencies.\r
+\r
+  This is an internal function.\r
+\r
+  @param  Stack                  On input: old stack; On output: new stack\r
+  @param  StackPtr               On input: old stack pointer; On output: new stack\r
+                                 pointer\r
+  @param  StackEnd               On input: old stack end; On output: new stack end\r
+\r
+  @retval EFI_SUCCESS            Grow Dependency stack success.\r
+  @retval EFI_OUT_OF_RESOURCES   No enough memory for stack space.\r
+\r
+**/\r
+EFI_STATUS\r
+GrowDependencyStack (\r
+  IN OUT HII_DEPENDENCY_EXPRESSION  ***Stack,\r
+  IN OUT HII_DEPENDENCY_EXPRESSION  ***StackPtr,\r
+  IN OUT HII_DEPENDENCY_EXPRESSION  ***StackEnd\r
+  )\r
+{\r
+  UINTN                      Size;\r
+  HII_DEPENDENCY_EXPRESSION  **NewStack;\r
+\r
+  Size = EXPRESSION_STACK_SIZE_INCREMENT;\r
+  if (*StackPtr != NULL) {\r
+    Size = Size + (*StackEnd - *Stack);\r
+  }\r
+\r
+  NewStack = AllocatePool (Size * sizeof (HII_DEPENDENCY_EXPRESSION *));\r
+  if (NewStack == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  if (*StackPtr != NULL) {\r
+    //\r
+    // Copy from Old Stack to the New Stack\r
+    //\r
+    CopyMem (\r
+      NewStack,\r
+      *Stack,\r
+      (*StackEnd - *Stack) * sizeof (HII_DEPENDENCY_EXPRESSION *)\r
+      );\r
+\r
+    //\r
+    // Free The Old Stack\r
+    //\r
+    FreePool (*Stack);\r
+  }\r
+\r
+  //\r
+  // Make the Stack pointer point to the old data in the new stack\r
+  //\r
+  *StackPtr = NewStack + (*StackPtr - *Stack);\r
+  *Stack    = NewStack;\r
+  *StackEnd = NewStack + Size;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Push an element onto the Stack for Expression Dependencies.\r
+\r
+  @param  Stack                  On input: old stack; On output: new stack\r
+  @param  StackPtr               On input: old stack pointer; On output: new stack\r
+                                 pointer\r
+  @param  StackEnd               On input: old stack end; On output: new stack end\r
+  @param  Data                   Data to push.\r
+\r
+  @retval EFI_SUCCESS            Push stack success.\r
+\r
+**/\r
+EFI_STATUS\r
+PushDependencyStack (\r
+  IN OUT HII_DEPENDENCY_EXPRESSION  ***Stack,\r
+  IN OUT HII_DEPENDENCY_EXPRESSION  ***StackPtr,\r
+  IN OUT HII_DEPENDENCY_EXPRESSION  ***StackEnd,\r
+  IN     HII_DEPENDENCY_EXPRESSION  **Data\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // Check for a stack overflow condition\r
+  //\r
+  if (*StackPtr >= *StackEnd) {\r
+    //\r
+    // Grow the stack\r
+    //\r
+    Status = GrowDependencyStack (Stack, StackPtr, StackEnd);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Push the item onto the stack\r
+  //\r
+  CopyMem (*StackPtr, Data, sizeof (HII_DEPENDENCY_EXPRESSION *));\r
+  *StackPtr = *StackPtr + 1;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Pop the Expression Dependency options from the Stack\r
+\r
+  @param  Stack                  On input: old stack; On output: new stack\r
+  @param  StackPtr               On input: old stack pointer; On output: new stack\r
+                                 pointer\r
+  @param  Data                   Data to push.\r
+\r
+  @retval EFI_SUCCESS            The value was pushed onto the stack.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopDependencyStack (\r
+  IN     HII_DEPENDENCY_EXPRESSION  **Stack,\r
+  IN OUT HII_DEPENDENCY_EXPRESSION  ***StackPtr,\r
+  OUT HII_DEPENDENCY_EXPRESSION     **Data\r
+  )\r
+{\r
+  //\r
+  // Check for a stack underflow condition\r
+  //\r
+  if (*StackPtr == Stack) {\r
+    return EFI_ACCESS_DENIED;\r
+  }\r
+\r
+  //\r
+  // Pop the item off the stack\r
+  //\r
+  *StackPtr = *StackPtr - 1;\r
+  CopyMem (Data, *StackPtr, sizeof (HII_DEPENDENCY_EXPRESSION *));\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Push the list of Expression Dependencies onto the Stack\r
+\r
+  @param  Pointer                Pointer to the list of map expression to be pushed.\r
+\r
+  @retval EFI_SUCCESS            The value was pushed onto the stack.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushDependencyExpDes (\r
+  IN HII_DEPENDENCY_EXPRESSION  **Pointer\r
+  )\r
+{\r
+  return PushDependencyStack (\r
+           &mExpressionDependencyStack,\r
+           &mExpressionDependencyPointer,\r
+           &mExpressionDependencyEnd,\r
+           Pointer\r
+           );\r
+}\r
+\r
+/**\r
+  Pop the list of Expression Dependencies from the Stack\r
+\r
+  @param  Pointer                Pointer to the list of map expression to be pop.\r
+\r
+  @retval EFI_SUCCESS            The value was pushed onto the stack.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopDependencyExpDes (\r
+  OUT HII_DEPENDENCY_EXPRESSION  **Pointer\r
+  )\r
+{\r
+  return PopDependencyStack (\r
+           mExpressionDependencyStack,\r
+           &mExpressionDependencyPointer,\r
+           Pointer\r
+           );\r
+}\r
+\r
+/**\r
+  Retrieve dependencies within an expression. These dependencies can express how\r
+  this expression will be evaluated.\r
+\r
+  @param[in,out]  Expression     Expression to retrieve dependencies.\r
+\r
+  @retval EFI_SUCCESS            The dependencies were successfully retrieved.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory.\r
+\r
+**/\r
+EFI_STATUS\r
+GetHiiExpressionDependency (\r
+  IN OUT HII_EXPRESSION  *Expression\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+  LIST_ENTRY                 *Link;\r
+  HII_EXPRESSION_OPCODE      *ExpressionOpCode;\r
+  HII_DEPENDENCY_EXPRESSION  *DepExpressionOpCode;\r
+  LIST_ENTRY                 *SubExpressionLink;\r
+  HII_EXPRESSION             *SubExpression;\r
+  UINT8                      MapPairCount;\r
+\r
+  Link = GetFirstNode (&Expression->OpCodeListHead);\r
+  while (!IsNull (&Expression->OpCodeListHead, Link)) {\r
+    ExpressionOpCode = HII_EXPRESSION_OPCODE_FROM_LINK (Link);\r
+    Link             = GetNextNode (&Expression->OpCodeListHead, Link);\r
+    Status           = EFI_SUCCESS;\r
+\r
+    DepExpressionOpCode = (HII_DEPENDENCY_EXPRESSION *)AllocateZeroPool (sizeof (HII_DEPENDENCY_EXPRESSION));\r
+    if (DepExpressionOpCode == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    switch (ExpressionOpCode->Operand) {\r
+      //\r
+      // Constant\r
+      //\r
+      case EFI_IFR_FALSE_OP:\r
+      case EFI_IFR_ONE_OP:\r
+      case EFI_IFR_ONES_OP:\r
+      case EFI_IFR_TRUE_OP:\r
+      case EFI_IFR_UINT8_OP:\r
+      case EFI_IFR_UINT16_OP:\r
+      case EFI_IFR_UINT32_OP:\r
+      case EFI_IFR_UINT64_OP:\r
+      case EFI_IFR_UNDEFINED_OP:\r
+      case EFI_IFR_VERSION_OP:\r
+      case EFI_IFR_ZERO_OP:\r
+        DepExpressionOpCode->ConstantExp.Operand = ExpressionOpCode->Operand;\r
+        CopyMem (&DepExpressionOpCode->ConstantExp.Value, &ExpressionOpCode->ExtraData.Value, sizeof (EFI_HII_VALUE));\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      //\r
+      // Built-in functions\r
+      //\r
+      case EFI_IFR_DUP_OP:\r
+        DepExpressionOpCode->DupExp.Operand = ExpressionOpCode->Operand;\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_EQ_ID_VAL_OP:\r
+        DepExpressionOpCode->EqIdValExp.Operand = ExpressionOpCode->Operand;\r
+        CopyMem (&DepExpressionOpCode->EqIdValExp.QuestionId, &ExpressionOpCode->ExtraData.EqIdValData.QuestionId, sizeof (EFI_QUESTION_ID));\r
+        CopyMem (&DepExpressionOpCode->EqIdValExp.Value, &ExpressionOpCode->ExtraData.EqIdValData.Value, sizeof (EFI_HII_VALUE));\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_EQ_ID_ID_OP:\r
+        DepExpressionOpCode->EqIdIdExp.Operand = ExpressionOpCode->Operand;\r
+        CopyMem (&DepExpressionOpCode->EqIdIdExp.QuestionId1, &ExpressionOpCode->ExtraData.EqIdIdData.QuestionId1, sizeof (EFI_QUESTION_ID));\r
+        CopyMem (&DepExpressionOpCode->EqIdIdExp.QuestionId2, &ExpressionOpCode->ExtraData.EqIdIdData.QuestionId2, sizeof (EFI_QUESTION_ID));\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_EQ_ID_VAL_LIST_OP:\r
+        DepExpressionOpCode->EqIdListExp.Operand    = ExpressionOpCode->Operand;\r
+        DepExpressionOpCode->EqIdListExp.ListLength = ExpressionOpCode->ExtraData.EqIdListData.ListLength;\r
+        CopyMem (&DepExpressionOpCode->EqIdListExp.QuestionId, &ExpressionOpCode->ExtraData.EqIdListData.QuestionId, sizeof (EFI_QUESTION_ID));\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        DepExpressionOpCode->EqIdListExp.ValueList = AllocateCopyPool (\r
+                                                       DepExpressionOpCode->EqIdListExp.ListLength * sizeof (UINT16),\r
+                                                       ExpressionOpCode->ExtraData.EqIdListData.ValueList\r
+                                                       );\r
+        if (DepExpressionOpCode->EqIdListExp.ValueList == NULL) {\r
+          return EFI_OUT_OF_RESOURCES;\r
+        }\r
+\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_GET_OP:\r
+        DepExpressionOpCode->GetExp.Operand    = ExpressionOpCode->Operand;\r
+        DepExpressionOpCode->GetExp.VarStorage = ExpressionOpCode->ExtraData.GetSetData.VarStorage;\r
+        CopyMem (&DepExpressionOpCode->GetExp.VarStoreInfo.VarName, &ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo.VarName, sizeof (EFI_STRING_ID));\r
+        CopyMem (&DepExpressionOpCode->GetExp.VarStoreInfo.VarOffset, &ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset, sizeof (UINT16));\r
+        DepExpressionOpCode->GetExp.VarStoreInfo = ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo;\r
+        if (ExpressionOpCode->ExtraData.GetSetData.ValueName != NULL) {\r
+          DepExpressionOpCode->GetExp.ValueName = (CHAR16 *)AllocateCopyPool (sizeof (ExpressionOpCode->ExtraData.GetSetData.ValueName), ExpressionOpCode->ExtraData.GetSetData.ValueName);\r
+          if (DepExpressionOpCode->GetExp.ValueName == NULL) {\r
+            return EFI_OUT_OF_RESOURCES;\r
+          }\r
+        }\r
+\r
+        DepExpressionOpCode->GetExp.ValueType  = ExpressionOpCode->ExtraData.GetSetData.ValueType;\r
+        DepExpressionOpCode->GetExp.ValueWidth = ExpressionOpCode->ExtraData.GetSetData.ValueWidth;\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_QUESTION_REF1_OP:\r
+        DepExpressionOpCode->QuestionRef1Exp.Operand = ExpressionOpCode->Operand;\r
+        CopyMem (&DepExpressionOpCode->QuestionRef1Exp.QuestionId, &ExpressionOpCode->ExtraData.QuestionRef1Data.QuestionId, sizeof (EFI_QUESTION_ID));\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_RULE_REF_OP:\r
+        DepExpressionOpCode->RuleRefExp.Operand = ExpressionOpCode->Operand;\r
+        DepExpressionOpCode->RuleRefExp.RuleId  = ExpressionOpCode->ExtraData.RuleId;\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_STRING_REF1_OP:\r
+        DepExpressionOpCode->StringRef1Exp.Operand = ExpressionOpCode->Operand;\r
+        CopyMem (&DepExpressionOpCode->StringRef1Exp.Value.Value.string, &ExpressionOpCode->ExtraData.Value.Value.string, sizeof (EFI_STRING_ID));\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_THIS_OP:\r
+        DepExpressionOpCode->ThisExp.Operand = ExpressionOpCode->Operand;\r
+        CopyMem (&DepExpressionOpCode->ThisExp.QuestionId, &ExpressionOpCode->ExtraData.QuestionRef1Data.QuestionId, sizeof (EFI_QUESTION_ID));\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_SECURITY_OP:\r
+        DepExpressionOpCode->SecurityExp.Operand = ExpressionOpCode->Operand;\r
+        CopyMem (&DepExpressionOpCode->SecurityExp.Permissions, &ExpressionOpCode->ExtraData.Guid, sizeof (EFI_GUID));\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      //\r
+      // unary-op\r
+      //\r
+      case EFI_IFR_LENGTH_OP:\r
+        DepExpressionOpCode->LengthExp.Operand = ExpressionOpCode->Operand;\r
+        PopDependencyExpDes (&DepExpressionOpCode->LengthExp.SubExpression);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_NOT_OP:\r
+        DepExpressionOpCode->NotExp.Operand = ExpressionOpCode->Operand;\r
+        PopDependencyExpDes (&DepExpressionOpCode->NotExp.SubExpression);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_BITWISE_NOT_OP:\r
+        DepExpressionOpCode->BitWiseNotExp.Operand = ExpressionOpCode->Operand;\r
+        PopDependencyExpDes (&DepExpressionOpCode->BitWiseNotExp.SubExpression);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_QUESTION_REF2_OP:\r
+        DepExpressionOpCode->QuestionRef2Exp.Operand = ExpressionOpCode->Operand;\r
+        PopDependencyExpDes (&DepExpressionOpCode->QuestionRef2Exp.SubExpression);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_QUESTION_REF3_OP:\r
+        DepExpressionOpCode->QuestionRef3Exp.Operand = ExpressionOpCode->Operand;\r
+        CopyMem (&DepExpressionOpCode->QuestionRef3Exp.DevicePath, &ExpressionOpCode->ExtraData.QuestionRef3Data.DevicePath, sizeof (EFI_DEVICE_PATH));\r
+        CopyMem (&DepExpressionOpCode->QuestionRef3Exp.Guid, &ExpressionOpCode->ExtraData.QuestionRef3Data.Guid, sizeof (EFI_GUID));\r
+        PopDependencyExpDes (&DepExpressionOpCode->QuestionRef3Exp.SubExpression);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_SET_OP:\r
+        DepExpressionOpCode->SetExp.Operand    = ExpressionOpCode->Operand;\r
+        DepExpressionOpCode->SetExp.VarStorage = ExpressionOpCode->ExtraData.GetSetData.VarStorage;\r
+        CopyMem (&DepExpressionOpCode->SetExp.VarStoreInfo.VarName, &ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo.VarName, sizeof (EFI_STRING_ID));\r
+        CopyMem (&DepExpressionOpCode->SetExp.VarStoreInfo.VarOffset, &ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset, sizeof (UINT16));\r
+        DepExpressionOpCode->SetExp.VarStoreInfo = ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo;\r
+        if (ExpressionOpCode->ExtraData.GetSetData.ValueName != NULL) {\r
+          DepExpressionOpCode->SetExp.ValueName = (CHAR16 *)AllocateCopyPool (sizeof (ExpressionOpCode->ExtraData.GetSetData.ValueName), ExpressionOpCode->ExtraData.GetSetData.ValueName);\r
+          if (DepExpressionOpCode->SetExp.ValueName == NULL) {\r
+            return EFI_OUT_OF_RESOURCES;\r
+          }\r
+        }\r
+\r
+        DepExpressionOpCode->SetExp.ValueType  = ExpressionOpCode->ExtraData.GetSetData.ValueType;\r
+        DepExpressionOpCode->SetExp.ValueWidth = ExpressionOpCode->ExtraData.GetSetData.ValueWidth;\r
+        PopDependencyExpDes (&DepExpressionOpCode->SetExp.SubExpression);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_STRING_REF2_OP:\r
+        DepExpressionOpCode->StringRef2Exp.Operand = ExpressionOpCode->Operand;\r
+        PopDependencyExpDes (&DepExpressionOpCode->StringRef2Exp.SubExpression);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_TO_BOOLEAN_OP:\r
+        DepExpressionOpCode->ToBooleanExp.Operand = ExpressionOpCode->Operand;\r
+        PopDependencyExpDes (&DepExpressionOpCode->ToBooleanExp.SubExpression);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_TO_STRING_OP:\r
+        DepExpressionOpCode->ToStringExp.Operand = ExpressionOpCode->Operand;\r
+        DepExpressionOpCode->ToStringExp.Format  = ExpressionOpCode->ExtraData.Format;\r
+        PopDependencyExpDes (&DepExpressionOpCode->ToStringExp.SubExpression);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_TO_UINT_OP:\r
+        DepExpressionOpCode->ToUintExp.Operand = ExpressionOpCode->Operand;\r
+        PopDependencyExpDes (&DepExpressionOpCode->ToUintExp.SubExpression);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_TO_LOWER_OP:\r
+        DepExpressionOpCode->ToLowerExp.Operand = ExpressionOpCode->Operand;\r
+        PopDependencyExpDes (&DepExpressionOpCode->ToLowerExp.SubExpression);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_TO_UPPER_OP:\r
+        DepExpressionOpCode->ToUpperExp.Operand = ExpressionOpCode->Operand;\r
+        PopDependencyExpDes (&DepExpressionOpCode->ToUpperExp.SubExpression);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      //\r
+      // binary-op\r
+      //\r
+      case EFI_IFR_ADD_OP:\r
+        DepExpressionOpCode->AddExp.Operand = ExpressionOpCode->Operand;\r
+        PopDependencyExpDes (&DepExpressionOpCode->AddExp.LeftHandExp);\r
+        PopDependencyExpDes (&DepExpressionOpCode->AddExp.RightHandExp);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_AND_OP:\r
+        DepExpressionOpCode->AndExp.Operand = ExpressionOpCode->Operand;\r
+        PopDependencyExpDes (&DepExpressionOpCode->AndExp.SubExpression1);\r
+        PopDependencyExpDes (&DepExpressionOpCode->AndExp.SubExpression2);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_BITWISE_AND_OP:\r
+        DepExpressionOpCode->BitwiseAndExp.Operand = ExpressionOpCode->Operand;\r
+        PopDependencyExpDes (&DepExpressionOpCode->BitwiseAndExp.SubExpression1);\r
+        PopDependencyExpDes (&DepExpressionOpCode->BitwiseAndExp.SubExpression2);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_BITWISE_OR_OP:\r
+        DepExpressionOpCode->BitwiseOrExp.Operand = ExpressionOpCode->Operand;\r
+        PopDependencyExpDes (&DepExpressionOpCode->BitwiseOrExp.SubExpression1);\r
+        PopDependencyExpDes (&DepExpressionOpCode->BitwiseOrExp.SubExpression2);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_CATENATE_OP:\r
+        DepExpressionOpCode->CatenateExp.Operand = ExpressionOpCode->Operand;\r
+        PopDependencyExpDes (&DepExpressionOpCode->CatenateExp.LeftStringExp);\r
+        PopDependencyExpDes (&DepExpressionOpCode->CatenateExp.RightStringExp);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_DIVIDE_OP:\r
+        DepExpressionOpCode->DivExp.Operand = ExpressionOpCode->Operand;\r
+        PopDependencyExpDes (&DepExpressionOpCode->DivExp.LeftHandExp);\r
+        PopDependencyExpDes (&DepExpressionOpCode->DivExp.RightHandExp);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_EQUAL_OP:\r
+        DepExpressionOpCode->EqualExp.Operand = ExpressionOpCode->Operand;\r
+        PopDependencyExpDes (&DepExpressionOpCode->EqualExp.SubExpression1);\r
+        PopDependencyExpDes (&DepExpressionOpCode->EqualExp.SubExpression2);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_GREATER_EQUAL_OP:\r
+        DepExpressionOpCode->GreaterEqualExp.Operand = ExpressionOpCode->Operand;\r
+        PopDependencyExpDes (&DepExpressionOpCode->GreaterEqualExp.LeftHandExp);\r
+        PopDependencyExpDes (&DepExpressionOpCode->GreaterEqualExp.RightHandExp);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_GREATER_THAN_OP:\r
+        DepExpressionOpCode->GreaterThanExp.Operand = ExpressionOpCode->Operand;\r
+        PopDependencyExpDes (&DepExpressionOpCode->GreaterThanExp.LeftHandExp);\r
+        PopDependencyExpDes (&DepExpressionOpCode->GreaterThanExp.RightHandExp);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_LESS_EQUAL_OP:\r
+        DepExpressionOpCode->LessEqualExp.Operand = ExpressionOpCode->Operand;\r
+        PopDependencyExpDes (&DepExpressionOpCode->LessEqualExp.LeftHandExp);\r
+        PopDependencyExpDes (&DepExpressionOpCode->LessEqualExp.RightHandExp);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_LESS_THAN_OP:\r
+        DepExpressionOpCode->LessThanExp.Operand = ExpressionOpCode->Operand;\r
+        PopDependencyExpDes (&DepExpressionOpCode->LessThanExp.LeftHandExp);\r
+        PopDependencyExpDes (&DepExpressionOpCode->LessThanExp.RightHandExp);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_MATCH_OP:\r
+        DepExpressionOpCode->MatchExp.Operand = ExpressionOpCode->Operand;\r
+        PopDependencyExpDes (&DepExpressionOpCode->MatchExp.PatternExp);\r
+        PopDependencyExpDes (&DepExpressionOpCode->MatchExp.StringExp);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_MATCH2_OP:\r
+        DepExpressionOpCode->Match2Exp.Operand = ExpressionOpCode->Operand;\r
+        CopyMem (&DepExpressionOpCode->Match2Exp.SyntaxType, &ExpressionOpCode->ExtraData.Guid, sizeof (EFI_GUID));\r
+        PopDependencyExpDes (&DepExpressionOpCode->Match2Exp.PatternExp);\r
+        PopDependencyExpDes (&DepExpressionOpCode->Match2Exp.StringExp);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_MODULO_OP:\r
+        DepExpressionOpCode->ModExp.Operand = ExpressionOpCode->Operand;\r
+        PopDependencyExpDes (&DepExpressionOpCode->ModExp.LeftHandExp);\r
+        PopDependencyExpDes (&DepExpressionOpCode->ModExp.RightHandExp);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_MULTIPLY_OP:\r
+        DepExpressionOpCode->MultExp.Operand = ExpressionOpCode->Operand;\r
+        PopDependencyExpDes (&DepExpressionOpCode->MultExp.LeftHandExp);\r
+        PopDependencyExpDes (&DepExpressionOpCode->MultExp.RightHandExp);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_NOT_EQUAL_OP:\r
+        DepExpressionOpCode->NotEqualExp.Operand = ExpressionOpCode->Operand;\r
+        PopDependencyExpDes (&DepExpressionOpCode->NotEqualExp.SubExpression1);\r
+        PopDependencyExpDes (&DepExpressionOpCode->NotEqualExp.SubExpression2);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_OR_OP:\r
+        DepExpressionOpCode->OrExp.Operand = ExpressionOpCode->Operand;\r
+        PopDependencyExpDes (&DepExpressionOpCode->OrExp.SubExpression1);\r
+        PopDependencyExpDes (&DepExpressionOpCode->OrExp.SubExpression2);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_SHIFT_LEFT_OP:\r
+        DepExpressionOpCode->ShiftLeftExp.Operand = ExpressionOpCode->Operand;\r
+        PopDependencyExpDes (&DepExpressionOpCode->ShiftLeftExp.LeftHandExp);\r
+        PopDependencyExpDes (&DepExpressionOpCode->ShiftLeftExp.RightHandExp);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_SHIFT_RIGHT_OP:\r
+        DepExpressionOpCode->ShiftRightExp.Operand = ExpressionOpCode->Operand;\r
+        PopDependencyExpDes (&DepExpressionOpCode->ShiftRightExp.LeftHandExp);\r
+        PopDependencyExpDes (&DepExpressionOpCode->ShiftRightExp.RightHandExp);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_SUBTRACT_OP:\r
+        DepExpressionOpCode->SubtractExp.Operand = ExpressionOpCode->Operand;\r
+        PopDependencyExpDes (&DepExpressionOpCode->SubtractExp.LeftHandExp);\r
+        PopDependencyExpDes (&DepExpressionOpCode->SubtractExp.RightHandExp);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      //\r
+      // ternary-op\r
+      //\r
+      case EFI_IFR_CONDITIONAL_OP:\r
+        DepExpressionOpCode->ConditionalExp.Operand = ExpressionOpCode->Operand;\r
+        PopDependencyExpDes (&DepExpressionOpCode->ConditionalExp.CondTrueValExp);\r
+        PopDependencyExpDes (&DepExpressionOpCode->ConditionalExp.CondFalseValExp);\r
+        PopDependencyExpDes (&DepExpressionOpCode->ConditionalExp.ConditionExp);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_FIND_OP:\r
+        DepExpressionOpCode->FindExp.Operand = ExpressionOpCode->Operand;\r
+        PopDependencyExpDes (&DepExpressionOpCode->FindExp.StringToSearchExp);\r
+        PopDependencyExpDes (&DepExpressionOpCode->FindExp.StringToCompWithExp);\r
+        PopDependencyExpDes (&DepExpressionOpCode->FindExp.IndexExp);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_MID_OP:\r
+        DepExpressionOpCode->MidExp.Operand = ExpressionOpCode->Operand;\r
+        PopDependencyExpDes (&DepExpressionOpCode->MidExp.StringOrBufferExp);\r
+        PopDependencyExpDes (&DepExpressionOpCode->MidExp.IndexExp);\r
+        PopDependencyExpDes (&DepExpressionOpCode->MidExp.LengthExp);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_TOKEN_OP:\r
+        DepExpressionOpCode->TokenExp.Operand = ExpressionOpCode->Operand;\r
+        PopDependencyExpDes (&DepExpressionOpCode->TokenExp.StringToSearchExp);\r
+        PopDependencyExpDes (&DepExpressionOpCode->TokenExp.DelimiterExp);\r
+        PopDependencyExpDes (&DepExpressionOpCode->TokenExp.IndexExp);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      case EFI_IFR_SPAN_OP:\r
+        DepExpressionOpCode->SpanExp.Operand = ExpressionOpCode->Operand;\r
+        PopDependencyExpDes (&DepExpressionOpCode->SpanExp.StringToSearchExp);\r
+        PopDependencyExpDes (&DepExpressionOpCode->SpanExp.CharsetExp);\r
+        PopDependencyExpDes (&DepExpressionOpCode->SpanExp.IndexExp);\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      //\r
+      // Map\r
+      //\r
+      case EFI_IFR_MAP_OP:\r
+        //\r
+        // Go through map expression list.\r
+        //\r
+        DepExpressionOpCode->MapExp.Operand = ExpressionOpCode->Operand;\r
+        MapPairCount                        = 0;\r
+        SubExpressionLink                   = GetFirstNode (&ExpressionOpCode->MapExpressionList);\r
+        while (!IsNull (&ExpressionOpCode->MapExpressionList, SubExpressionLink)) {\r
+          MapPairCount++;\r
+          SubExpressionLink = GetNextNode (&ExpressionOpCode->MapExpressionList, SubExpressionLink);\r
+          if (IsNull (&ExpressionOpCode->MapExpressionList, SubExpressionLink)) {\r
+            Status = EFI_INVALID_PARAMETER;\r
+            goto Done;\r
+          }\r
+\r
+          //\r
+          // Goto the first expression on next pair.\r
+          //\r
+          SubExpressionLink = GetNextNode (&ExpressionOpCode->MapExpressionList, SubExpressionLink);\r
+        }\r
+\r
+        DepExpressionOpCode->MapExp.ExpPair = (HII_DEPENDENCY_EXPRESSION_PAIR *)AllocateZeroPool (\r
+                                                                                  MapPairCount * sizeof (HII_DEPENDENCY_EXPRESSION_PAIR)\r
+                                                                                  );\r
+        if (DepExpressionOpCode->MapExp.ExpPair == NULL) {\r
+          Status = EFI_OUT_OF_RESOURCES;\r
+          goto Done;\r
+        }\r
+\r
+        DepExpressionOpCode->MapExp.ExpPairNo = MapPairCount;\r
+        MapPairCount                          = 0;\r
+        PopDependencyExpDes (&DepExpressionOpCode->MapExp.SubExp);\r
+\r
+        //\r
+        // Go through map expression list.\r
+        //\r
+        SubExpressionLink = GetFirstNode (&ExpressionOpCode->MapExpressionList);\r
+        while (!IsNull (&ExpressionOpCode->MapExpressionList, SubExpressionLink)) {\r
+          SubExpression = HII_EXPRESSION_FROM_LINK (SubExpressionLink);\r
+          //\r
+          // Get the first expression description in this pair.\r
+          //\r
+          GetHiiExpressionDependency (SubExpression);\r
+          DepExpressionOpCode->MapExp.ExpPair[MapPairCount].MatchExp = SubExpression->RootDependencyExp;\r
+\r
+          //\r
+          // Get the second expression description in this pair.\r
+          //\r
+          SubExpressionLink = GetNextNode (&ExpressionOpCode->MapExpressionList, SubExpressionLink);\r
+          SubExpression     = HII_EXPRESSION_FROM_LINK (SubExpressionLink);\r
+          GetHiiExpressionDependency (SubExpression);\r
+          DepExpressionOpCode->MapExp.ExpPair[MapPairCount].ReturnExp = SubExpression->RootDependencyExp;\r
+          //\r
+          // Goto the first expression on next pair.\r
+          //\r
+          SubExpressionLink = GetNextNode (&ExpressionOpCode->MapExpressionList, SubExpressionLink);\r
+          MapPairCount++;\r
+        }\r
+\r
+        PushDependencyExpDes (&DepExpressionOpCode);\r
+        break;\r
+\r
+      default:\r
+        break;\r
+    }\r
+  }\r
+\r
+  PopDependencyExpDes (&Expression->RootDependencyExp);\r
+\r
+Done:\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Return the result of the expression list. Check the expression list and\r
+  return the highest priority express result.\r
+  Priority: DisableIf > SuppressIf > GrayOutIf > FALSE\r
+\r
+  @param[in]  ExpList         The input expression list.\r
+  @param[in]  Evaluate        Whether need to evaluate the expression first.\r
+  @param[in]  FormSet         FormSet associated with this expression.\r
+  @param[in]  Form            Form associated with this expression.\r
+\r
+  @retval EXPRESS_RESULT      Return the higher priority express result.\r
+                              DisableIf > SuppressIf > GrayOutIf > FALSE\r
+\r
+**/\r
+EXPRESS_RESULT\r
+EvaluateExpressionList (\r
+  IN HII_EXPRESSION_LIST  *ExpList,\r
+  IN BOOLEAN              Evaluate,\r
+  IN HII_FORMSET          *FormSet  OPTIONAL,\r
+  IN HII_FORM             *Form OPTIONAL\r
+  )\r
+{\r
+  UINTN           Index;\r
+  EXPRESS_RESULT  ReturnVal;\r
+  EXPRESS_RESULT  CompareOne;\r
+  EFI_STATUS      Status;\r
+\r
+  if (ExpList == NULL) {\r
+    return ExpressFalse;\r
+  }\r
+\r
+  ASSERT (ExpList->Signature == HII_EXPRESSION_LIST_SIGNATURE);\r
+  Index = 0;\r
+\r
+  //\r
+  // Check whether need to evaluate the expression first.\r
+  //\r
+  if (Evaluate) {\r
+    while (ExpList->Count > Index) {\r
+      Status = EvaluateHiiExpression (FormSet, Form, ExpList->Expression[Index++]);\r
+      if (EFI_ERROR (Status)) {\r
+        return ExpressFalse;\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // Run the list of expressions.\r
+  //\r
+  ReturnVal = ExpressFalse;\r
+  for (Index = 0; Index < ExpList->Count; Index++) {\r
+    if (IsHiiValueTrue (&ExpList->Expression[Index]->Result)) {\r
+      switch (ExpList->Expression[Index]->Type) {\r
+        case EFI_HII_EXPRESSION_SUPPRESS_IF:\r
+          CompareOne = ExpressSuppress;\r
+          break;\r
+\r
+        case EFI_HII_EXPRESSION_GRAY_OUT_IF:\r
+          CompareOne = ExpressGrayOut;\r
+          break;\r
+\r
+        case EFI_HII_EXPRESSION_DISABLE_IF:\r
+          CompareOne = ExpressDisable;\r
+          break;\r
+\r
+        default:\r
+          return ExpressFalse;\r
+      }\r
+\r
+      ReturnVal = ReturnVal < CompareOne ? CompareOne : ReturnVal;\r
+    }\r
+  }\r
+\r
+  return ReturnVal;\r
+}\r
diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiExpression.h b/RedfishPkg/Library/HiiUtilityLib/HiiExpression.h
new file mode 100644 (file)
index 0000000..dda96ad
--- /dev/null
@@ -0,0 +1,191 @@
+/** @file\r
+  Definitions of Hii Expression.\r
+\r
+  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+  (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>\r
+  Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.\r
+\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#ifndef HII_EXPRESSION_H_\r
+#define HII_EXPRESSION_H_\r
+\r
+#include <Library/HiiUtilityLib.h>\r
+\r
+/**\r
+  Get the expression list count.\r
+\r
+  @param[in]  Level              Which type this expression belong to. Form,\r
+                                 statement or option?\r
+\r
+  @retval >=0                    The expression count\r
+  @retval -1                     Input parameter error.\r
+\r
+**/\r
+INTN\r
+GetConditionalExpressionCount (\r
+  IN EXPRESS_LEVEL  Level\r
+  );\r
+\r
+/**\r
+  Get the expression Buffer pointer.\r
+\r
+  @param[in]  Level              Which type this expression belong to. Form,\r
+                                 statement or option?\r
+\r
+  @retval  The start pointer of the expression buffer or NULL.\r
+\r
+**/\r
+HII_EXPRESSION **\r
+GetConditionalExpressionList (\r
+  IN EXPRESS_LEVEL  Level\r
+  );\r
+\r
+/**\r
+  Push the expression options onto the Stack.\r
+\r
+  @param[in]  Pointer            Pointer to the current expression.\r
+  @param[in]  Level              Which type this expression belong to. Form,\r
+                                 statement or option?\r
+\r
+  @retval EFI_SUCCESS            The value was pushed onto the stack.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushConditionalExpression (\r
+  IN HII_EXPRESSION  *Pointer,\r
+  IN EXPRESS_LEVEL   Level\r
+  );\r
+\r
+/**\r
+  Pop the expression options from the Stack\r
+\r
+  @param[in]  Level              Which type this expression belong to. Form,\r
+                                 statement or option?\r
+\r
+  @retval EFI_SUCCESS            The value was pushed onto the stack.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopConditionalExpression (\r
+  IN EXPRESS_LEVEL  Level\r
+  );\r
+\r
+/**\r
+  Reset stack pointer to begin of the stack.\r
+\r
+**/\r
+VOID\r
+ResetCurrentExpressionStack (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Push current expression onto the Stack\r
+\r
+  @param[in]  Pointer            Pointer to current expression.\r
+\r
+  @retval EFI_SUCCESS            The value was pushed onto the stack.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushCurrentExpression (\r
+  IN VOID  *Pointer\r
+  );\r
+\r
+/**\r
+  Pop current expression from the Stack\r
+\r
+  @param[in]  Pointer            Pointer to current expression to be pop.\r
+\r
+  @retval EFI_SUCCESS            The value was pushed onto the stack.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopCurrentExpression (\r
+  OUT VOID  **Pointer\r
+  );\r
+\r
+/**\r
+  Reset stack pointer to begin of the stack.\r
+\r
+**/\r
+VOID\r
+ResetMapExpressionListStack (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Push the list of map expression onto the Stack\r
+\r
+  @param[in]  Pointer            Pointer to the list of map expression to be pushed.\r
+\r
+  @retval EFI_SUCCESS            The value was pushed onto the stack.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushMapExpressionList (\r
+  IN VOID  *Pointer\r
+  );\r
+\r
+/**\r
+  Pop the list of map expression from the Stack\r
+\r
+  @param[in]  Pointer            Pointer to the list of map expression to be pop.\r
+\r
+  @retval EFI_SUCCESS            The value was pushed onto the stack.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopMapExpressionList (\r
+  OUT VOID  **Pointer\r
+  );\r
+\r
+/**\r
+  Reset stack pointer to begin of the stack.\r
+\r
+**/\r
+VOID\r
+ResetScopeStack (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Push an Operand onto the Stack\r
+\r
+  @param[in]  Operand            Operand to push.\r
+\r
+  @retval EFI_SUCCESS            The value was pushed onto the stack.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the\r
+                                 stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushScope (\r
+  IN UINT8  Operand\r
+  );\r
+\r
+/**\r
+  Pop an Operand from the Stack\r
+\r
+  @param[out]  Operand           Operand to pop.\r
+\r
+  @retval EFI_SUCCESS            The value was pushed onto the stack.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the\r
+                                 stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopScope (\r
+  OUT UINT8  *Operand\r
+  );\r
+\r
+#endif\r
diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiIfrParse.c b/RedfishPkg/Library/HiiUtilityLib/HiiIfrParse.c
new file mode 100644 (file)
index 0000000..a51d7b9
--- /dev/null
@@ -0,0 +1,2715 @@
+/** @file\r
+  The implementation of HII IFR parser.\r
+\r
+  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+  (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>\r
+  Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.\r
+\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include "HiiInternal.h"\r
+\r
+/**\r
+  Initialize Statement header members.\r
+\r
+  @param[in]      OpCodeData             Pointer of the raw OpCode data.\r
+  @param[in,out]  FormSet                Pointer of the current FormSet.\r
+  @param[in,out]  Form                   Pointer of the current Form.\r
+\r
+  @return The Statement.\r
+\r
+**/\r
+HII_STATEMENT *\r
+CreateStatement (\r
+  IN     UINT8        *OpCodeData,\r
+  IN OUT HII_FORMSET  *FormSet,\r
+  IN OUT HII_FORM     *Form\r
+  )\r
+{\r
+  HII_STATEMENT             *Statement;\r
+  EFI_IFR_STATEMENT_HEADER  *StatementHdr;\r
+  INTN                      ConditionalExprCount;\r
+\r
+  if (Form == NULL) {\r
+    //\r
+    // Only guid op may out side the form level.\r
+    //\r
+    if (((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode != EFI_IFR_GUID_OP) {\r
+      return NULL;\r
+    }\r
+  }\r
+\r
+  Statement = (HII_STATEMENT *)AllocateZeroPool (sizeof (HII_STATEMENT));\r
+  if (Statement == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  InitializeListHead (&Statement->DefaultListHead);\r
+  InitializeListHead (&Statement->OptionListHead);\r
+  InitializeListHead (&Statement->InconsistentListHead);\r
+  InitializeListHead (&Statement->NoSubmitListHead);\r
+  InitializeListHead (&Statement->WarningListHead);\r
+\r
+  Statement->Signature               = HII_STATEMENT_SIGNATURE;\r
+  Statement->Operand                 = ((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode;\r
+  Statement->OpCode                  = (EFI_IFR_OP_HEADER *)OpCodeData;\r
+  Statement->QuestionReferToBitField = FALSE;\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
+  ConditionalExprCount = GetConditionalExpressionCount (ExpressStatement);\r
+  if (ConditionalExprCount > 0) {\r
+    //\r
+    // Form is inside of suppressif\r
+    //\r
+    Statement->ExpressionList = (HII_EXPRESSION_LIST *)AllocatePool (\r
+                                                         (UINTN)(sizeof (HII_EXPRESSION_LIST) + ((ConditionalExprCount - 1) * sizeof (HII_EXPRESSION *)))\r
+                                                         );\r
+    if (Statement->ExpressionList == NULL) {\r
+      return NULL;\r
+    }\r
+\r
+    Statement->ExpressionList->Count     = (UINTN)ConditionalExprCount;\r
+    Statement->ExpressionList->Signature = HII_EXPRESSION_LIST_SIGNATURE;\r
+    CopyMem (\r
+      Statement->ExpressionList->Expression,\r
+      GetConditionalExpressionList (ExpressStatement),\r
+      (UINTN)(sizeof (HII_EXPRESSION *) * ConditionalExprCount)\r
+      );\r
+  }\r
+\r
+  //\r
+  // Insert this Statement into current Form\r
+  //\r
+  if (Form == NULL) {\r
+    InsertTailList (&FormSet->StatementListOSF, &Statement->Link);\r
+  } else {\r
+    InsertTailList (&Form->StatementListHead, &Statement->Link);\r
+  }\r
+\r
+  return Statement;\r
+}\r
+\r
+/**\r
+  Initialize Question's members.\r
+\r
+  @param[in]      OpCodeData             Pointer of the raw OpCode data.\r
+  @param[in,out]  FormSet                Pointer of the current FormSet.\r
+  @param[in,out]  Form                   Pointer of the current Form.\r
+\r
+  @return The Question.\r
+\r
+**/\r
+HII_STATEMENT *\r
+CreateQuestion (\r
+  IN     UINT8        *OpCodeData,\r
+  IN OUT HII_FORMSET  *FormSet,\r
+  IN OUT HII_FORM     *Form\r
+  )\r
+{\r
+  HII_STATEMENT            *Statement;\r
+  EFI_IFR_QUESTION_HEADER  *QuestionHdr;\r
+  LIST_ENTRY               *Link;\r
+  HII_FORMSET_STORAGE      *Storage;\r
+  HII_NAME_VALUE_NODE      *NameValueNode;\r
+  BOOLEAN                  Find;\r
+\r
+  Statement = CreateStatement (OpCodeData, FormSet, Form);\r
+  if (Statement == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  QuestionHdr = (EFI_IFR_QUESTION_HEADER *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER));\r
+  CopyMem (&Statement->QuestionId, &QuestionHdr->QuestionId, sizeof (EFI_QUESTION_ID));\r
+  CopyMem (&Statement->VarStoreId, &QuestionHdr->VarStoreId, sizeof (EFI_VARSTORE_ID));\r
+  CopyMem (&Statement->VarStoreInfo.VarOffset, &QuestionHdr->VarStoreInfo.VarOffset, sizeof (UINT16));\r
+\r
+  Statement->QuestionFlags = QuestionHdr->Flags;\r
+\r
+  if (Statement->VarStoreId == 0) {\r
+    //\r
+    // VarStoreId of zero indicates no variable storage\r
+    //\r
+    return Statement;\r
+  }\r
+\r
+  //\r
+  // Find Storage for this Question\r
+  //\r
+  Link = GetFirstNode (&FormSet->StorageListHead);\r
+  while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+    Storage = HII_STORAGE_FROM_LINK (Link);\r
+\r
+    if (Statement->VarStoreId == Storage->VarStoreId) {\r
+      Statement->Storage = Storage;\r
+      break;\r
+    }\r
+\r
+    Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+  }\r
+\r
+  if (Statement->Storage == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Initialize varname for Name/Value or EFI Variable\r
+  //\r
+  if ((Statement->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) ||\r
+      (Statement->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE))\r
+  {\r
+    Statement->VariableName = GetTokenString (Statement->VarStoreInfo.VarName, FormSet->HiiHandle);\r
+    if (Statement->VariableName == NULL) {\r
+      return NULL;\r
+    }\r
+\r
+    if (Statement->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+      //\r
+      // Check whether old string node already exist.\r
+      //\r
+      Find = FALSE;\r
+      if (!IsListEmpty (&Statement->Storage->NameValueList)) {\r
+        Link = GetFirstNode (&Statement->Storage->NameValueList);\r
+        while (!IsNull (&Statement->Storage->NameValueList, Link)) {\r
+          NameValueNode = HII_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->NameValueList, Link);\r
+        }\r
+      }\r
+\r
+      if (!Find) {\r
+        //\r
+        // Insert to Name/Value varstore list\r
+        //\r
+        NameValueNode = AllocateZeroPool (sizeof (HII_NAME_VALUE_NODE));\r
+        if (NameValueNode == NULL) {\r
+          return NULL;\r
+        }\r
+\r
+        NameValueNode->Signature = HII_NAME_VALUE_NODE_SIGNATURE;\r
+        NameValueNode->Name      = AllocateCopyPool (StrSize (Statement->VariableName), Statement->VariableName);\r
+        if (NameValueNode->Name == NULL) {\r
+          FreePool (NameValueNode);\r
+          return NULL;\r
+        }\r
+\r
+        NameValueNode->Value = AllocateZeroPool (0x10);\r
+        if (NameValueNode->Value == NULL) {\r
+          FreePool (NameValueNode->Name);\r
+          FreePool (NameValueNode);\r
+          return NULL;\r
+        }\r
+\r
+        InsertTailList (&Statement->Storage->NameValueList, &NameValueNode->Link);\r
+      }\r
+    }\r
+  }\r
+\r
+  return Statement;\r
+}\r
+\r
+/**\r
+  Allocate a HII_EXPRESSION node.\r
+\r
+  @param[in,out]  Form                   The Form associated with this Expression\r
+  @param[in]      OpCode                 The binary opcode data.\r
+\r
+  @return Pointer to a HII_EXPRESSION data structure.\r
+\r
+**/\r
+HII_EXPRESSION *\r
+CreateExpression (\r
+  IN OUT HII_FORM  *Form,\r
+  IN     UINT8     *OpCode\r
+  )\r
+{\r
+  HII_EXPRESSION  *Expression;\r
+\r
+  Expression = AllocateZeroPool (sizeof (HII_EXPRESSION));\r
+  if (Expression == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  Expression->Signature = HII_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[in]      FormSet                Pointer of the current FormSet\r
+  @param[in,out]  Storage                Pointer of the storage\r
+\r
+  @retval EFI_SUCCESS            Initialize ConfigHdr success\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeConfigHdr (\r
+  IN     HII_FORMSET          *FormSet,\r
+  IN OUT HII_FORMSET_STORAGE  *Storage\r
+  )\r
+{\r
+  CHAR16  *Name;\r
+\r
+  if ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ||\r
+      (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER))\r
+  {\r
+    Name = Storage->Name;\r
+  } else {\r
+    Name = NULL;\r
+  }\r
+\r
+  Storage->ConfigHdr = HiiConstructConfigHdr (\r
+                         &Storage->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
+  Convert Ascii string to Unicode.\r
+\r
+  This is an internal function.\r
+\r
+  @param[in]  AsciiString             The Ascii string to be converted.\r
+  @param[out] UnicodeString           The Unicode string retrieved.\r
+\r
+**/\r
+VOID\r
+AsciiToUnicode (\r
+  IN  CHAR8   *AsciiString,\r
+  OUT CHAR16  *UnicodeString\r
+  )\r
+{\r
+  UINT8  Index;\r
+\r
+  Index = 0;\r
+  while (AsciiString[Index] != 0) {\r
+    UnicodeString[Index] = (CHAR16)AsciiString[Index];\r
+    Index++;\r
+  }\r
+\r
+  UnicodeString[Index] = L'\0';\r
+}\r
+\r
+/**\r
+  Allocate a HII_FORMSET_STORAGE data structure and insert to FormSet Storage List.\r
+\r
+  @param[in]  FormSet                    Pointer of the current FormSet\r
+  @param[in]  StorageType                Storage type.\r
+  @param[in]  OpCodeData                 Binary data for this opcode.\r
+\r
+  @return Pointer to a HII_FORMSET_STORAGE data structure.\r
+\r
+**/\r
+HII_FORMSET_STORAGE *\r
+CreateStorage (\r
+  IN HII_FORMSET  *FormSet,\r
+  IN UINT8        StorageType,\r
+  IN UINT8        *OpCodeData\r
+  )\r
+{\r
+  HII_FORMSET_STORAGE  *Storage;\r
+  CHAR8                *AsciiStorageName;\r
+\r
+  AsciiStorageName = NULL;\r
+\r
+  Storage = AllocateZeroPool (sizeof (HII_FORMSET_STORAGE));\r
+  if (Storage == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  Storage->Signature = HII_STORAGE_SIGNATURE;\r
+  Storage->Type      = StorageType;\r
+\r
+  switch (StorageType) {\r
+    case EFI_HII_VARSTORE_BUFFER:\r
+\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
+      if (Storage->Buffer == NULL) {\r
+        FreePool (Storage);\r
+        return NULL;\r
+      }\r
+\r
+      AsciiStorageName = (CHAR8 *)((EFI_IFR_VARSTORE *)OpCodeData)->Name;\r
+      Storage->Name    = AllocatePool (sizeof (CHAR16) * (AsciiStrLen (AsciiStorageName) + 1));\r
+      if (Storage->Name == NULL) {\r
+        FreePool (Storage);\r
+        return NULL;\r
+      }\r
+\r
+      AsciiToUnicode (AsciiStorageName, Storage->Name);\r
+\r
+      break;\r
+\r
+    case EFI_HII_VARSTORE_EFI_VARIABLE:\r
+    case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\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
+      CopyMem (&Storage->Size, &((EFI_IFR_VARSTORE_EFI *)OpCodeData)->Size, sizeof (UINT16));\r
+\r
+      if (StorageType ==  EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
+        Storage->Buffer = AllocateZeroPool (Storage->Size);\r
+        if (Storage->Buffer == NULL) {\r
+          FreePool (Storage);\r
+          return NULL;\r
+        }\r
+      }\r
+\r
+      AsciiStorageName = (CHAR8 *)((EFI_IFR_VARSTORE_EFI *)OpCodeData)->Name;\r
+      Storage->Name    = AllocatePool (sizeof (CHAR16) * (AsciiStrLen (AsciiStorageName) + 1));\r
+      if (Storage->Name == NULL) {\r
+        FreePool (Storage);\r
+        return NULL;\r
+      }\r
+\r
+      AsciiToUnicode (AsciiStorageName, Storage->Name);\r
+\r
+      break;\r
+\r
+    case EFI_HII_VARSTORE_NAME_VALUE:\r
+      CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_NAME_VALUE *)OpCodeData)->Guid, sizeof (EFI_GUID));\r
+      InitializeListHead (&Storage->NameValueList);\r
+\r
+      break;\r
+\r
+    default:\r
+      break;\r
+  }\r
+\r
+  InitializeConfigHdr (FormSet, Storage);\r
+  InsertTailList (&FormSet->StorageListHead, &Storage->Link);\r
+\r
+  return Storage;\r
+}\r
+\r
+/**\r
+  Get formset storage based on the input varstoreid info.\r
+\r
+  @param[in]  FormSet                Pointer of the current FormSet.\r
+  @param[in]  VarStoreId             Varstore ID info.\r
+\r
+  @return Pointer to a HII_FORMSET_STORAGE data structure.\r
+\r
+**/\r
+HII_FORMSET_STORAGE *\r
+GetFstStgFromVarId (\r
+  IN HII_FORMSET      *FormSet,\r
+  IN EFI_VARSTORE_ID  VarStoreId\r
+  )\r
+{\r
+  HII_FORMSET_STORAGE  *Storage;\r
+  LIST_ENTRY           *Link;\r
+  BOOLEAN              Found;\r
+\r
+  Found   = FALSE;\r
+  Storage = NULL;\r
+  //\r
+  // Find Formset Storage for this Question\r
+  //\r
+  Link = GetFirstNode (&FormSet->StorageListHead);\r
+  while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+    Storage = HII_STORAGE_FROM_LINK (Link);\r
+\r
+    if (Storage->VarStoreId == VarStoreId) {\r
+      Found = TRUE;\r
+      break;\r
+    }\r
+\r
+    Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+  }\r
+\r
+  return Found ? Storage : NULL;\r
+}\r
+\r
+/**\r
+  Initialize Request Element of a Question. <RequestElement> ::= '&'<BlockName> | '&'<Label>\r
+\r
+  @param[in,out]  FormSet                Pointer of the current FormSet.\r
+  @param[in,out]  Question               The Question to be initialized.\r
+  @param[in,out]  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
+\r
+**/\r
+EFI_STATUS\r
+InitializeRequestElement (\r
+  IN OUT HII_FORMSET    *FormSet,\r
+  IN OUT HII_STATEMENT  *Question,\r
+  IN OUT HII_FORM       *Form\r
+  )\r
+{\r
+  HII_FORMSET_STORAGE      *Storage;\r
+  HII_FORM_CONFIG_REQUEST  *ConfigInfo;\r
+  UINTN                    StrLen;\r
+  UINTN                    StringSize;\r
+  CHAR16                   *NewStr;\r
+  CHAR16                   RequestElement[30];\r
+  LIST_ENTRY               *Link;\r
+  BOOLEAN                  Find;\r
+  UINTN                    MaxLen;\r
+\r
+  Storage = Question->Storage;\r
+  if (Storage == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+    //\r
+    // <ConfigRequest> is unnecessary for EFI variable storage,\r
+    // GetVariable()/SetVariable() will be used to retrieve/save values\r
+    //\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Prepare <RequestElement>\r
+  //\r
+  if ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ||\r
+      (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER))\r
+  {\r
+    StrLen = UnicodeSPrint (\r
+               RequestElement,\r
+               30 * sizeof (CHAR16),\r
+               L"&OFFSET=%04x&WIDTH=%04x",\r
+               Question->VarStoreInfo.VarOffset,\r
+               Question->StorageWidth\r
+               );\r
+    HiiStringToLowercase (RequestElement);\r
+    Question->BlockName = AllocateCopyPool ((StrLen + 1) * sizeof (CHAR16), RequestElement);\r
+    if (Question->BlockName == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+  } else {\r
+    StrLen = UnicodeSPrint (RequestElement, 30 * sizeof (CHAR16), L"&%s", Question->VariableName);\r
+  }\r
+\r
+  if ((Question->Operand == EFI_IFR_PASSWORD_OP) &&\r
+      ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK))\r
+  {\r
+    //\r
+    // Password with CALLBACK flag is stored in encoded format,\r
+    // so don't need to append it to <ConfigRequest>\r
+    //\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  StringSize = (Storage->ConfigRequest != NULL) ? StrSize (Storage->ConfigRequest) : sizeof (CHAR16);\r
+  MaxLen     = StringSize / sizeof (CHAR16) + Storage->SpareStrLen;\r
+\r
+  //\r
+  // Append <RequestElement> to <ConfigRequest>\r
+  //\r
+  if (StrLen > Storage->SpareStrLen) {\r
+    //\r
+    // Old String buffer is not sufficient for RequestElement, allocate a new one\r
+    //\r
+    MaxLen = StringSize / sizeof (CHAR16) + CONFIG_REQUEST_STRING_INCREMENTAL;\r
+    NewStr = AllocatePool (MaxLen * sizeof (CHAR16));\r
+    if (NewStr == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    if (Storage->ConfigRequest != NULL) {\r
+      CopyMem (NewStr, Storage->ConfigRequest, StringSize);\r
+      FreePool (Storage->ConfigRequest);\r
+    } else {\r
+      NewStr[0] = L'\0';\r
+    }\r
+\r
+    Storage->ConfigRequest = NewStr;\r
+    Storage->SpareStrLen   = CONFIG_REQUEST_STRING_INCREMENTAL;\r
+  }\r
+\r
+  StrCatS (Storage->ConfigRequest, MaxLen, RequestElement);\r
+  Storage->ElementCount++;\r
+  Storage->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 = HII_FORM_CONFIG_REQUEST_FROM_LINK (Link);\r
+    if ((ConfigInfo != NULL) && (ConfigInfo->Storage == Storage)) {\r
+      Find = TRUE;\r
+      break;\r
+    }\r
+\r
+    Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
+  }\r
+\r
+  if (!Find) {\r
+    ConfigInfo = AllocateZeroPool (sizeof (HII_FORM_CONFIG_REQUEST));\r
+    if (ConfigInfo == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    ConfigInfo->Signature     = HII_FORM_CONFIG_REQUEST_SIGNATURE;\r
+    ConfigInfo->ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigHdr), Storage->ConfigHdr);\r
+    if (ConfigInfo->ConfigRequest == NULL) {\r
+      FreePool (ConfigInfo);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    ConfigInfo->SpareStrLen = 0;\r
+    ConfigInfo->Storage     = Storage;\r
+    InsertTailList (&Form->ConfigRequestHead, &ConfigInfo->Link);\r
+  }\r
+\r
+  StringSize = (ConfigInfo->ConfigRequest != NULL) ? StrSize (ConfigInfo->ConfigRequest) : sizeof (CHAR16);\r
+  MaxLen     = StringSize / sizeof (CHAR16) + ConfigInfo->SpareStrLen;\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
+    MaxLen = StringSize / sizeof (CHAR16) + CONFIG_REQUEST_STRING_INCREMENTAL;\r
+    NewStr = AllocatePool (MaxLen * sizeof (CHAR16));\r
+    if (NewStr == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    if (ConfigInfo->ConfigRequest != NULL) {\r
+      CopyMem (NewStr, ConfigInfo->ConfigRequest, StringSize);\r
+      FreePool (ConfigInfo->ConfigRequest);\r
+    } else {\r
+      NewStr[0] = L'\0';\r
+    }\r
+\r
+    ConfigInfo->ConfigRequest = NewStr;\r
+    ConfigInfo->SpareStrLen   = CONFIG_REQUEST_STRING_INCREMENTAL;\r
+  }\r
+\r
+  StrCatS (ConfigInfo->ConfigRequest, MaxLen, RequestElement);\r
+  ConfigInfo->ElementCount++;\r
+  ConfigInfo->SpareStrLen -= StrLen;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Free resources of a Expression.\r
+\r
+  @param[in]  FormSet                Pointer of the Expression\r
+\r
+**/\r
+VOID\r
+DestroyExpression (\r
+  IN HII_EXPRESSION  *Expression\r
+  )\r
+{\r
+  LIST_ENTRY             *Link;\r
+  HII_EXPRESSION_OPCODE  *OpCode;\r
+  LIST_ENTRY             *SubExpressionLink;\r
+  HII_EXPRESSION         *SubExpression;\r
+\r
+  while (!IsListEmpty (&Expression->OpCodeListHead)) {\r
+    Link   = GetFirstNode (&Expression->OpCodeListHead);\r
+    OpCode = HII_EXPRESSION_OPCODE_FROM_LINK (Link);\r
+\r
+    RemoveEntryList (&OpCode->Link);\r
+    if ((OpCode->Operand == EFI_IFR_EQ_ID_VAL_LIST_OP) && (OpCode->ExtraData.EqIdListData.ValueList != NULL)) {\r
+      FreePool (OpCode->ExtraData.EqIdListData.ValueList);\r
+    }\r
+\r
+    if (((OpCode->Operand == EFI_IFR_GET_OP) || (OpCode->Operand == EFI_IFR_SET_OP)) &&\r
+        (OpCode->ExtraData.GetSetData.ValueName != NULL))\r
+    {\r
+      FreePool (OpCode->ExtraData.GetSetData.ValueName);\r
+    }\r
+\r
+    if (OpCode->MapExpressionList.ForwardLink != NULL) {\r
+      while (!IsListEmpty (&OpCode->MapExpressionList)) {\r
+        SubExpressionLink = GetFirstNode (&OpCode->MapExpressionList);\r
+        SubExpression     = HII_EXPRESSION_FROM_LINK (SubExpressionLink);\r
+        RemoveEntryList (&SubExpression->Link);\r
+        DestroyExpression (SubExpression);\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // Free this Expression\r
+  //\r
+  FreePool (Expression);\r
+}\r
+\r
+/**\r
+  Delete a string from HII Package List.\r
+\r
+  @param[in]  StringId               Id of the string in HII database.\r
+  @param[in]  HiiHandle              The HII package list handle.\r
+\r
+  @retval EFI_SUCCESS            The string was deleted successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+DeleteString (\r
+  IN  EFI_STRING_ID   StringId,\r
+  IN  EFI_HII_HANDLE  HiiHandle\r
+  )\r
+{\r
+  CHAR16  NullChar;\r
+\r
+  NullChar = CHAR_NULL;\r
+  HiiSetString (HiiHandle, StringId, &NullChar, NULL);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Free resources of a Statement.\r
+\r
+  @param[in]      FormSet                Pointer of the FormSet\r
+  @param[in,out]  Statement              Pointer of the Statement\r
+\r
+**/\r
+VOID\r
+DestroyStatement (\r
+  IN     HII_FORMSET    *FormSet,\r
+  IN OUT HII_STATEMENT  *Statement\r
+  )\r
+{\r
+  LIST_ENTRY            *Link;\r
+  HII_QUESTION_DEFAULT  *Default;\r
+  HII_QUESTION_OPTION   *Option;\r
+  HII_EXPRESSION        *Expression;\r
+\r
+  //\r
+  // Free Default value List\r
+  //\r
+  while (!IsListEmpty (&Statement->DefaultListHead)) {\r
+    Link    = GetFirstNode (&Statement->DefaultListHead);\r
+    Default = HII_QUESTION_DEFAULT_FROM_LINK (Link);\r
+    RemoveEntryList (&Default->Link);\r
+\r
+    if (Default->Value.Buffer != NULL) {\r
+      FreePool (Default->Value.Buffer);\r
+    }\r
+\r
+    FreePool (Default);\r
+  }\r
+\r
+  //\r
+  // Free Options List\r
+  //\r
+  while (!IsListEmpty (&Statement->OptionListHead)) {\r
+    Link   = GetFirstNode (&Statement->OptionListHead);\r
+    Option = HII_QUESTION_OPTION_FROM_LINK (Link);\r
+\r
+    if (Option->SuppressExpression != NULL) {\r
+      FreePool (Option->SuppressExpression);\r
+    }\r
+\r
+    RemoveEntryList (&Option->Link);\r
+\r
+    FreePool (Option);\r
+  }\r
+\r
+  //\r
+  // Free Inconsistent List\r
+  //\r
+  while (!IsListEmpty (&Statement->InconsistentListHead)) {\r
+    Link       = GetFirstNode (&Statement->InconsistentListHead);\r
+    Expression = HII_EXPRESSION_FROM_LINK (Link);\r
+    RemoveEntryList (&Expression->Link);\r
+\r
+    DestroyExpression (Expression);\r
+  }\r
+\r
+  //\r
+  // Free NoSubmit List\r
+  //\r
+  while (!IsListEmpty (&Statement->NoSubmitListHead)) {\r
+    Link       = GetFirstNode (&Statement->NoSubmitListHead);\r
+    Expression = HII_EXPRESSION_FROM_LINK (Link);\r
+    RemoveEntryList (&Expression->Link);\r
+\r
+    DestroyExpression (Expression);\r
+  }\r
+\r
+  //\r
+  // Free WarningIf List\r
+  //\r
+  while (!IsListEmpty (&Statement->WarningListHead)) {\r
+    Link       = GetFirstNode (&Statement->WarningListHead);\r
+    Expression = HII_EXPRESSION_FROM_LINK (Link);\r
+    RemoveEntryList (&Expression->Link);\r
+\r
+    DestroyExpression (Expression);\r
+  }\r
+\r
+  if (Statement->ExpressionList != NULL) {\r
+    FreePool (Statement->ExpressionList);\r
+  }\r
+\r
+  if (Statement->VariableName != NULL) {\r
+    FreePool (Statement->VariableName);\r
+  }\r
+\r
+  if (Statement->BlockName != NULL) {\r
+    FreePool (Statement->BlockName);\r
+  }\r
+\r
+  if (Statement->Value.Buffer != NULL) {\r
+    FreePool (Statement->Value.Buffer);\r
+  }\r
+\r
+  if ((Statement->Operand == EFI_IFR_STRING_OP) || (Statement->Operand == EFI_IFR_PASSWORD_OP)) {\r
+    DeleteString (Statement->Value.Value.string, FormSet->HiiHandle);\r
+  }\r
+}\r
+\r
+/**\r
+  Free resources of a Form.\r
+\r
+  @param[in]      FormSet                Pointer of the FormSet\r
+  @param[in,out]  Form                   Pointer of the Form.\r
+\r
+**/\r
+VOID\r
+DestroyForm (\r
+  IN     HII_FORMSET  *FormSet,\r
+  IN OUT HII_FORM     *Form\r
+  )\r
+{\r
+  LIST_ENTRY               *Link;\r
+  HII_EXPRESSION           *Expression;\r
+  HII_STATEMENT            *Statement;\r
+  HII_FORM_CONFIG_REQUEST  *ConfigInfo;\r
+\r
+  //\r
+  // Free Rule Expressions\r
+  //\r
+  while (!IsListEmpty (&Form->RuleListHead)) {\r
+    Link       = GetFirstNode (&Form->RuleListHead);\r
+    Expression = HII_EXPRESSION_FROM_LINK (Link);\r
+    RemoveEntryList (&Expression->Link);\r
+    DestroyExpression (Expression);\r
+  }\r
+\r
+  //\r
+  // Free Statements/Questions\r
+  //\r
+  while (!IsListEmpty (&Form->StatementListHead)) {\r
+    Link      = GetFirstNode (&Form->StatementListHead);\r
+    Statement = HII_STATEMENT_FROM_LINK (Link);\r
+    RemoveEntryList (&Statement->Link);\r
+    DestroyStatement (FormSet, Statement);\r
+  }\r
+\r
+  //\r
+  // Free ConfigRequest string.\r
+  //\r
+  while (!IsListEmpty (&Form->ConfigRequestHead)) {\r
+    Link       = GetFirstNode (&Form->ConfigRequestHead);\r
+    ConfigInfo = HII_FORM_CONFIG_REQUEST_FROM_LINK (Link);\r
+\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
+  //\r
+  // Free this Form\r
+  //\r
+  FreePool (Form);\r
+}\r
+\r
+/**\r
+  Tell whether this Operand is an Expression OpCode or not\r
+\r
+  @param[in]  Operand                Operand of an IFR OpCode.\r
+\r
+  @retval TRUE                   This is an Expression OpCode.\r
+  @retval FALSE                  Not an Expression OpCode.\r
+\r
+**/\r
+BOOLEAN\r
+IsExpressionOpCode (\r
+  IN UINT8  Operand\r
+  )\r
+{\r
+  if (((Operand >= EFI_IFR_EQ_ID_VAL_OP) && (Operand <= EFI_IFR_NOT_OP)) ||\r
+      ((Operand >= EFI_IFR_MATCH_OP) && (Operand <= EFI_IFR_SET_OP))  ||\r
+      ((Operand >= EFI_IFR_EQUAL_OP) && (Operand <= EFI_IFR_SPAN_OP)) ||\r
+      (Operand == EFI_IFR_CATENATE_OP) ||\r
+      (Operand == EFI_IFR_TO_LOWER_OP) ||\r
+      (Operand == EFI_IFR_TO_UPPER_OP) ||\r
+      (Operand == EFI_IFR_MAP_OP)      ||\r
+      (Operand == EFI_IFR_VERSION_OP)  ||\r
+      (Operand == EFI_IFR_SECURITY_OP) ||\r
+      (Operand == EFI_IFR_MATCH2_OP))\r
+  {\r
+    return TRUE;\r
+  } else {\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+/**\r
+  Tell whether this Operand is an Statement OpCode.\r
+\r
+  @param[in]  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
+  {\r
+    return TRUE;\r
+  } else {\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+/**\r
+  Tell whether this Operand is an known OpCode.\r
+\r
+  @param[in]  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 Statements(Questions) and Expression OpCodes.\r
+\r
+  @param[in]      FormSet                The FormSet to be counted.\r
+  @param[in,out]  NumberOfStatement      Number of Statements(Questions)\r
+  @param[in,out]  NumberOfExpression     Number of Expression OpCodes\r
+\r
+**/\r
+VOID\r
+CountOpCodes (\r
+  IN     HII_FORMSET  *FormSet,\r
+  IN OUT UINT16       *NumberOfStatement,\r
+  IN OUT UINT16       *NumberOfExpression\r
+  )\r
+{\r
+  UINT16  StatementCount;\r
+  UINT16  ExpressionCount;\r
+  UINT8   *OpCodeData;\r
+  UINTN   Offset;\r
+  UINTN   OpCodeLen;\r
+\r
+  Offset          = 0;\r
+  StatementCount  = 0;\r
+  ExpressionCount = 0;\r
+\r
+  while (Offset < FormSet->IfrBinaryLength) {\r
+    OpCodeData = FormSet->IfrBinaryData + Offset;\r
+    OpCodeLen  = ((EFI_IFR_OP_HEADER *)OpCodeData)->Length;\r
+    Offset    += OpCodeLen;\r
+\r
+    if (IsExpressionOpCode (((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode)) {\r
+      ExpressionCount++;\r
+    } else {\r
+      StatementCount++;\r
+    }\r
+  }\r
+\r
+  *NumberOfStatement  = StatementCount;\r
+  *NumberOfExpression = ExpressionCount;\r
+}\r
+\r
+/**\r
+  Parse opcodes in the formset IFR binary.\r
+\r
+  @param[in]  FormSet                Pointer of the FormSet data structure.\r
+\r
+  @retval EFI_SUCCESS            Opcode parse success.\r
+  @retval Other                  Opcode parse fail.\r
+\r
+**/\r
+EFI_STATUS\r
+ParseOpCodes (\r
+  IN HII_FORMSET  *FormSet\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  HII_FORM                  *CurrentForm;\r
+  HII_STATEMENT             *CurrentStatement;\r
+  HII_STATEMENT             *ParentStatement;\r
+  HII_EXPRESSION_OPCODE     *ExpressionOpCode;\r
+  HII_EXPRESSION            *CurrentExpression;\r
+  UINT8                     Operand;\r
+  UINT8                     Scope;\r
+  UINTN                     OpCodeOffset;\r
+  UINTN                     OpCodeLength;\r
+  UINT8                     *OpCodeData;\r
+  UINT8                     ScopeOpCode;\r
+  HII_FORMSET_DEFAULTSTORE  *DefaultStore;\r
+  HII_QUESTION_DEFAULT      *CurrentDefault;\r
+  HII_QUESTION_OPTION       *CurrentOption;\r
+  UINT8                     Width;\r
+  UINT16                    NumberOfStatement;\r
+  UINT16                    NumberOfExpression;\r
+  EFI_IMAGE_ID              *ImageId;\r
+  BOOLEAN                   SuppressForQuestion;\r
+  BOOLEAN                   SuppressForOption;\r
+  UINT16                    DepthOfDisable;\r
+  BOOLEAN                   OpCodeDisabled;\r
+  BOOLEAN                   SingleOpCodeExpression;\r
+  BOOLEAN                   InScopeDefault;\r
+  EFI_HII_VALUE             *ExpressionValue;\r
+  HII_STATEMENT_VALUE       *StatementValue;\r
+  EFI_IFR_FORM_MAP_METHOD   *MapMethod;\r
+  UINT8                     MapScopeDepth;\r
+  LIST_ENTRY                *Link;\r
+  HII_FORMSET_STORAGE       *Storage;\r
+  LIST_ENTRY                *MapExpressionList;\r
+  EFI_VARSTORE_ID           TempVarstoreId;\r
+  BOOLEAN                   InScopeDisable;\r
+  INTN                      ConditionalExprCount;\r
+  BOOLEAN                   InUnknownScope;\r
+  UINT8                     UnknownDepth;\r
+  HII_FORMSET_DEFAULTSTORE  *PreDefaultStore;\r
+  LIST_ENTRY                *DefaultLink;\r
+  BOOLEAN                   HaveInserted;\r
+  UINT16                    TotalBits;\r
+  BOOLEAN                   QuestionReferBitField;\r
+\r
+  SuppressForQuestion    = FALSE;\r
+  SuppressForOption      = FALSE;\r
+  InScopeDisable         = FALSE;\r
+  DepthOfDisable         = 0;\r
+  OpCodeDisabled         = FALSE;\r
+  SingleOpCodeExpression = FALSE;\r
+  InScopeDefault         = FALSE;\r
+  CurrentExpression      = NULL;\r
+  CurrentDefault         = NULL;\r
+  CurrentOption          = NULL;\r
+  ImageId                = NULL;\r
+  MapMethod              = NULL;\r
+  MapScopeDepth          = 0;\r
+  Link                   = NULL;\r
+  MapExpressionList      = NULL;\r
+  TempVarstoreId         = 0;\r
+  ConditionalExprCount   = 0;\r
+  InUnknownScope         = FALSE;\r
+  UnknownDepth           = 0;\r
+  QuestionReferBitField  = FALSE;\r
+\r
+  //\r
+  // Get the number of Statements and Expressions\r
+  //\r
+  CountOpCodes (FormSet, &NumberOfStatement, &NumberOfExpression);\r
+\r
+  InitializeListHead (&FormSet->StatementListOSF);\r
+  InitializeListHead (&FormSet->StorageListHead);\r
+  InitializeListHead (&FormSet->DefaultStoreListHead);\r
+  InitializeListHead (&FormSet->FormListHead);\r
+  ResetCurrentExpressionStack ();\r
+  ResetMapExpressionListStack ();\r
+\r
+  CurrentForm      = NULL;\r
+  CurrentStatement = NULL;\r
+  ParentStatement  = NULL;\r
+\r
+  ResetScopeStack ();\r
+\r
+  OpCodeOffset = 0;\r
+  while (OpCodeOffset < FormSet->IfrBinaryLength) {\r
+    OpCodeData = FormSet->IfrBinaryData + OpCodeOffset;\r
+\r
+    OpCodeLength  = ((EFI_IFR_OP_HEADER *)OpCodeData)->Length;\r
+    OpCodeOffset += OpCodeLength;\r
+    Operand       = ((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode;\r
+    Scope         = ((EFI_IFR_OP_HEADER *)OpCodeData)->Scope;\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
+    if (Scope != 0) {\r
+      PushScope (Operand);\r
+    }\r
+\r
+    if (OpCodeDisabled) {\r
+      //\r
+      // DisableIf Expression is evaluated to be TRUE, try to find its end.\r
+      // Here only cares the EFI_IFR_DISABLE_IF and EFI_IFR_END\r
+      //\r
+      if (Operand == EFI_IFR_DISABLE_IF_OP) {\r
+        DepthOfDisable++;\r
+      } else if (Operand == EFI_IFR_END_OP) {\r
+        Status = PopScope (&ScopeOpCode);\r
+        if (EFI_ERROR (Status)) {\r
+          return Status;\r
+        }\r
+\r
+        if (ScopeOpCode == EFI_IFR_DISABLE_IF_OP) {\r
+          if (DepthOfDisable == 0) {\r
+            InScopeDisable = FALSE;\r
+            OpCodeDisabled = FALSE;\r
+          } else {\r
+            DepthOfDisable--;\r
+          }\r
+        }\r
+      }\r
+\r
+      continue;\r
+    }\r
+\r
+    if (IsExpressionOpCode (Operand)) {\r
+      ExpressionOpCode = (HII_EXPRESSION_OPCODE *)AllocateZeroPool (sizeof (HII_EXPRESSION_OPCODE));\r
+      if (ExpressionOpCode == NULL) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      ExpressionOpCode->Signature = HII_EXPRESSION_OPCODE_SIGNATURE;\r
+      ExpressionOpCode->Operand   = Operand;\r
+\r
+      switch (Operand) {\r
+        case EFI_IFR_EQ_ID_VAL_OP:\r
+\r
+          CopyMem (&ExpressionOpCode->ExtraData.EqIdValData.QuestionId, &((EFI_IFR_EQ_ID_VAL *)OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));\r
+\r
+          ExpressionValue       = &ExpressionOpCode->ExtraData.EqIdValData.Value;\r
+          ExpressionValue->Type = EFI_IFR_TYPE_NUM_SIZE_16;\r
+          CopyMem (&ExpressionValue->Value.u16, &((EFI_IFR_EQ_ID_VAL *)OpCodeData)->Value, sizeof (UINT16));\r
+          break;\r
+\r
+        case EFI_IFR_EQ_ID_ID_OP:\r
+          CopyMem (&ExpressionOpCode->ExtraData.EqIdIdData.QuestionId1, &((EFI_IFR_EQ_ID_ID *)OpCodeData)->QuestionId1, sizeof (EFI_QUESTION_ID));\r
+          CopyMem (&ExpressionOpCode->ExtraData.EqIdIdData.QuestionId2, &((EFI_IFR_EQ_ID_ID *)OpCodeData)->QuestionId2, sizeof (EFI_QUESTION_ID));\r
+          break;\r
+\r
+        case EFI_IFR_EQ_ID_VAL_LIST_OP:\r
+\r
+          CopyMem (&ExpressionOpCode->ExtraData.EqIdListData.QuestionId, &((EFI_IFR_EQ_ID_VAL_LIST *)OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));\r
+          CopyMem (&ExpressionOpCode->ExtraData.EqIdListData.ListLength, &((EFI_IFR_EQ_ID_VAL_LIST *)OpCodeData)->ListLength, sizeof (UINT16));\r
+          ExpressionOpCode->ExtraData.EqIdListData.ValueList = AllocateCopyPool (\r
+                                                                 ExpressionOpCode->ExtraData.EqIdListData.ListLength * sizeof (UINT16),\r
+                                                                 &((EFI_IFR_EQ_ID_VAL_LIST *)OpCodeData)->ValueList\r
+                                                                 );\r
+          if (ExpressionOpCode->ExtraData.EqIdListData.ValueList == NULL) {\r
+            return EFI_OUT_OF_RESOURCES;\r
+          }\r
+\r
+          break;\r
+\r
+        case EFI_IFR_TO_STRING_OP:\r
+        case EFI_IFR_FIND_OP:\r
+\r
+          ExpressionOpCode->ExtraData.Format = ((EFI_IFR_TO_STRING *)OpCodeData)->Format;\r
+          break;\r
+\r
+        case EFI_IFR_STRING_REF1_OP:\r
+\r
+          ExpressionValue       = &ExpressionOpCode->ExtraData.Value;\r
+          ExpressionValue->Type = EFI_IFR_TYPE_STRING;\r
+          CopyMem (&ExpressionValue->Value.string, &((EFI_IFR_STRING_REF1 *)OpCodeData)->StringId, sizeof (EFI_STRING_ID));\r
+          break;\r
+\r
+        case EFI_IFR_RULE_REF_OP:\r
+\r
+          ExpressionOpCode->ExtraData.RuleId = ((EFI_IFR_RULE_REF *)OpCodeData)->RuleId;\r
+          break;\r
+\r
+        case EFI_IFR_SPAN_OP:\r
+\r
+          ExpressionOpCode->ExtraData.Flags = ((EFI_IFR_SPAN *)OpCodeData)->Flags;\r
+          break;\r
+\r
+        case EFI_IFR_THIS_OP:\r
+\r
+          if (ParentStatement != NULL) {\r
+            ExpressionOpCode->ExtraData.QuestionRef1Data.QuestionId = ParentStatement->QuestionId;\r
+          }\r
+\r
+          break;\r
+\r
+        case EFI_IFR_SECURITY_OP:\r
+\r
+          CopyMem (&ExpressionOpCode->ExtraData.Guid, &((EFI_IFR_SECURITY *)OpCodeData)->Permissions, sizeof (EFI_GUID));\r
+          break;\r
+\r
+        case EFI_IFR_MATCH2_OP:\r
+\r
+          CopyMem (&ExpressionOpCode->ExtraData.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
+\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
+                Storage = HII_STORAGE_FROM_LINK (Link);\r
+                if (Storage->VarStoreId == ((EFI_IFR_GET *)OpCodeData)->VarStoreId) {\r
+                  ExpressionOpCode->ExtraData.GetSetData.VarStorage = Storage;\r
+                  break;\r
+                }\r
+\r
+                Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+              }\r
+            }\r
+\r
+            if (ExpressionOpCode->ExtraData.GetSetData.VarStorage == NULL) {\r
+              //\r
+              // VarStorage is not found.\r
+              //\r
+              return EFI_INVALID_PARAMETER;\r
+            }\r
+          }\r
+\r
+          ExpressionOpCode->ExtraData.GetSetData.ValueType = ((EFI_IFR_GET *)OpCodeData)->VarStoreType;\r
+          switch (ExpressionOpCode->ExtraData.GetSetData.ValueType) {\r
+            case EFI_IFR_TYPE_BOOLEAN:\r
+            case EFI_IFR_TYPE_NUM_SIZE_8:\r
+              ExpressionOpCode->ExtraData.GetSetData.ValueWidth = 1;\r
+              break;\r
+\r
+            case EFI_IFR_TYPE_NUM_SIZE_16:\r
+            case EFI_IFR_TYPE_STRING:\r
+              ExpressionOpCode->ExtraData.GetSetData.ValueWidth = 2;\r
+              break;\r
+\r
+            case EFI_IFR_TYPE_NUM_SIZE_32:\r
+              ExpressionOpCode->ExtraData.GetSetData.ValueWidth = 4;\r
+              break;\r
+\r
+            case EFI_IFR_TYPE_NUM_SIZE_64:\r
+              ExpressionOpCode->ExtraData.GetSetData.ValueWidth = 8;\r
+              break;\r
+\r
+            case EFI_IFR_TYPE_DATE:\r
+              ExpressionOpCode->ExtraData.GetSetData.ValueWidth = (UINT8)sizeof (EFI_IFR_DATE);\r
+              break;\r
+\r
+            case EFI_IFR_TYPE_TIME:\r
+              ExpressionOpCode->ExtraData.GetSetData.ValueWidth = (UINT8)sizeof (EFI_IFR_TIME);\r
+              break;\r
+\r
+            case EFI_IFR_TYPE_REF:\r
+              ExpressionOpCode->ExtraData.GetSetData.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
+\r
+          CopyMem (\r
+            &ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo.VarName,\r
+            &((EFI_IFR_GET *)OpCodeData)->VarStoreInfo.VarName,\r
+            sizeof (EFI_STRING_ID)\r
+            );\r
+          CopyMem (\r
+            &ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset,\r
+            &((EFI_IFR_GET *)OpCodeData)->VarStoreInfo.VarOffset,\r
+            sizeof (UINT16)\r
+            );\r
+          if ((ExpressionOpCode->ExtraData.GetSetData.VarStorage != NULL) &&\r
+              ((ExpressionOpCode->ExtraData.GetSetData.VarStorage->Type == EFI_HII_VARSTORE_NAME_VALUE) ||\r
+               (ExpressionOpCode->ExtraData.GetSetData.VarStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)))\r
+          {\r
+            ExpressionOpCode->ExtraData.GetSetData.ValueName = GetTokenString (ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo.VarName, FormSet->HiiHandle);\r
+            if (ExpressionOpCode->ExtraData.GetSetData.ValueName == NULL) {\r
+              //\r
+              // String ID is invalid.\r
+              //\r
+              return EFI_INVALID_PARAMETER;\r
+            }\r
+          }\r
+\r
+          break;\r
+\r
+        case EFI_IFR_QUESTION_REF1_OP:\r
+\r
+          CopyMem (&ExpressionOpCode->ExtraData.QuestionRef1Data.QuestionId, &((EFI_IFR_EQ_ID_VAL_LIST *)OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));\r
+          break;\r
+\r
+        case EFI_IFR_QUESTION_REF3_OP:\r
+\r
+          if (OpCodeLength >= sizeof (EFI_IFR_QUESTION_REF3_2)) {\r
+            CopyMem (&ExpressionOpCode->ExtraData.QuestionRef3Data.DevicePath, &((EFI_IFR_QUESTION_REF3_2 *)OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));\r
+\r
+            if (OpCodeLength >= sizeof (EFI_IFR_QUESTION_REF3_3)) {\r
+              CopyMem (&ExpressionOpCode->ExtraData.QuestionRef3Data.Guid, &((EFI_IFR_QUESTION_REF3_3 *)OpCodeData)->Guid, sizeof (EFI_GUID));\r
+            }\r
+          }\r
+\r
+          break;\r
+\r
+        //\r
+        // constant\r
+        //\r
+        case EFI_IFR_TRUE_OP:\r
+\r
+          ExpressionValue          = &ExpressionOpCode->ExtraData.Value;\r
+          ExpressionValue->Type    = EFI_IFR_TYPE_BOOLEAN;\r
+          ExpressionValue->Value.b = TRUE;\r
+          break;\r
+\r
+        case EFI_IFR_FALSE_OP:\r
+\r
+          ExpressionValue          = &ExpressionOpCode->ExtraData.Value;\r
+          ExpressionValue->Type    = EFI_IFR_TYPE_BOOLEAN;\r
+          ExpressionValue->Value.b = FALSE;\r
+          break;\r
+\r
+        case EFI_IFR_ONE_OP:\r
+\r
+          ExpressionValue           = &ExpressionOpCode->ExtraData.Value;\r
+          ExpressionValue->Type     = EFI_IFR_TYPE_NUM_SIZE_8;\r
+          ExpressionValue->Value.u8 = 1;\r
+          break;\r
+\r
+        case EFI_IFR_ZERO_OP:\r
+\r
+          ExpressionValue           = &ExpressionOpCode->ExtraData.Value;\r
+          ExpressionValue->Type     = EFI_IFR_TYPE_NUM_SIZE_8;\r
+          ExpressionValue->Value.u8 = 0;\r
+          break;\r
+\r
+        case EFI_IFR_ONES_OP:\r
+\r
+          ExpressionValue            = &ExpressionOpCode->ExtraData.Value;\r
+          ExpressionValue->Type      = EFI_IFR_TYPE_NUM_SIZE_64;\r
+          ExpressionValue->Value.u64 = 0xffffffffffffffffULL;\r
+          break;\r
+\r
+        case EFI_IFR_UINT8_OP:\r
+\r
+          ExpressionValue           = &ExpressionOpCode->ExtraData.Value;\r
+          ExpressionValue->Type     = EFI_IFR_TYPE_NUM_SIZE_8;\r
+          ExpressionValue->Value.u8 = ((EFI_IFR_UINT8 *)OpCodeData)->Value;\r
+          break;\r
+\r
+        case EFI_IFR_UINT16_OP:\r
+\r
+          ExpressionValue       = &ExpressionOpCode->ExtraData.Value;\r
+          ExpressionValue->Type = EFI_IFR_TYPE_NUM_SIZE_16;\r
+          CopyMem (&ExpressionValue->Value.u16, &((EFI_IFR_UINT16 *)OpCodeData)->Value, sizeof (UINT16));\r
+          break;\r
+\r
+        case EFI_IFR_UINT32_OP:\r
+\r
+          ExpressionValue       = &ExpressionOpCode->ExtraData.Value;\r
+          ExpressionValue->Type = EFI_IFR_TYPE_NUM_SIZE_32;\r
+          CopyMem (&ExpressionValue->Value.u32, &((EFI_IFR_UINT32 *)OpCodeData)->Value, sizeof (UINT32));\r
+          break;\r
+\r
+        case EFI_IFR_UINT64_OP:\r
+\r
+          ExpressionValue       = &ExpressionOpCode->ExtraData.Value;\r
+          ExpressionValue->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+          CopyMem (&ExpressionValue->Value.u64, &((EFI_IFR_UINT64 *)OpCodeData)->Value, sizeof (UINT64));\r
+          break;\r
+\r
+        case EFI_IFR_UNDEFINED_OP:\r
+          ExpressionValue       = &ExpressionOpCode->ExtraData.Value;\r
+          ExpressionValue->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          break;\r
+\r
+        case EFI_IFR_VERSION_OP:\r
+          ExpressionValue            = &ExpressionOpCode->ExtraData.Value;\r
+          ExpressionValue->Type      = EFI_IFR_TYPE_NUM_SIZE_16;\r
+          ExpressionValue->Value.u16 = EFI_IFR_SPECIFICATION_VERSION;\r
+          break;\r
+\r
+        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
+        if (CurrentExpression == NULL) {\r
+          continue;\r
+        }\r
+\r
+        InsertTailList (MapExpressionList, &CurrentExpression->Link);\r
+        if (Scope == 0) {\r
+          SingleOpCodeExpression = TRUE;\r
+        }\r
+      }\r
+\r
+      InsertTailList (&CurrentExpression->OpCodeListHead, &ExpressionOpCode->Link);\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
+        //\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
+        // for expression consists of more than one OpCode: EFI_IFR_END\r
+        //\r
+        SingleOpCodeExpression = FALSE;\r
+\r
+        if (InScopeDisable && (CurrentForm == NULL)) {\r
+          //\r
+          // This is DisableIf expression for Form, it should be a constant expression\r
+          //\r
+          Status = EvaluateHiiExpression (FormSet, CurrentForm, CurrentExpression);\r
+          if (EFI_ERROR (Status)) {\r
+            return Status;\r
+          }\r
+\r
+          OpCodeDisabled = IsHiiValueTrue (&CurrentExpression->Result);\r
+        }\r
+\r
+        CurrentExpression = NULL;\r
+      }\r
+\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Parse the Opcode\r
+    //\r
+    switch (Operand) {\r
+      case EFI_IFR_FORM_SET_OP:\r
+        //\r
+        // Check the formset GUID\r
+        //\r
+\r
+        if (CompareMem (&FormSet->Guid, &((EFI_IFR_FORM_SET *)OpCodeData)->Guid, sizeof (EFI_GUID)) != 0) {\r
+          return EFI_INVALID_PARAMETER;\r
+        }\r
+\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
+\r
+        break;\r
+\r
+      case EFI_IFR_FORM_OP:\r
+\r
+        //\r
+        // Create a new Form for this FormSet\r
+        //\r
+        CurrentForm = AllocateZeroPool (sizeof (HII_FORM));\r
+        if (CurrentForm == NULL) {\r
+          break;\r
+        }\r
+\r
+        CurrentForm->Signature = HII_FORM_SIGNATURE;\r
+        InitializeListHead (&CurrentForm->StatementListHead);\r
+        InitializeListHead (&CurrentForm->ConfigRequestHead);\r
+        InitializeListHead (&CurrentForm->RuleListHead);\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 = (HII_EXPRESSION_LIST *)AllocatePool (\r
+                                                                     (UINTN)(sizeof (HII_EXPRESSION_LIST) + ((ConditionalExprCount -1) * sizeof (HII_EXPRESSION *)))\r
+                                                                     );\r
+          if (CurrentForm->SuppressExpression == NULL) {\r
+            break;\r
+          }\r
+\r
+          CurrentForm->SuppressExpression->Count     = (UINTN)ConditionalExprCount;\r
+          CurrentForm->SuppressExpression->Signature = HII_EXPRESSION_LIST_SIGNATURE;\r
+          CopyMem (CurrentForm->SuppressExpression->Expression, GetConditionalExpressionList (ExpressForm), (UINTN)(sizeof (HII_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
+        //\r
+        // Create a new Form for this FormSet\r
+        //\r
+        CurrentForm = AllocateZeroPool (sizeof (HII_FORM));\r
+        if (CurrentForm == NULL) {\r
+          return EFI_OUT_OF_RESOURCES;\r
+        }\r
+\r
+        CurrentForm->Signature = HII_FORM_SIGNATURE;\r
+        InitializeListHead (&CurrentForm->StatementListHead);\r
+        InitializeListHead (&CurrentForm->ConfigRequestHead);\r
+        InitializeListHead (&CurrentForm->RuleListHead);\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
+        //\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
+\r
+          MapMethod++;\r
+        }\r
+\r
+        //\r
+        // If the standard form map method is not found, the first map method title will be used.\r
+        //\r
+        if (CurrentForm->FormTitle == 0) {\r
+          MapMethod = (EFI_IFR_FORM_MAP_METHOD *)(OpCodeData + sizeof (EFI_IFR_FORM_MAP));\r
+          CopyMem (&CurrentForm->FormTitle, &MapMethod->MethodTitle, sizeof (EFI_STRING_ID));\r
+        }\r
+\r
+        ConditionalExprCount = GetConditionalExpressionCount (ExpressForm);\r
+        if ( ConditionalExprCount > 0) {\r
+          //\r
+          // Form is inside of suppressif\r
+          //\r
+          CurrentForm->SuppressExpression = (HII_EXPRESSION_LIST *)AllocateZeroPool (\r
+                                                                     (UINTN)(sizeof (HII_EXPRESSION_LIST) + ((ConditionalExprCount -1) * sizeof (HII_EXPRESSION *)))\r
+                                                                     );\r
+          if (CurrentForm->SuppressExpression == NULL) {\r
+            FreePool (CurrentForm);\r
+            return EFI_OUT_OF_RESOURCES;\r
+          }\r
+\r
+          CurrentForm->SuppressExpression->Count     = (UINTN)ConditionalExprCount;\r
+          CurrentForm->SuppressExpression->Signature = HII_EXPRESSION_LIST_SIGNATURE;\r
+          CopyMem (CurrentForm->SuppressExpression->Expression, GetConditionalExpressionList (ExpressForm), (UINTN)(sizeof (HII_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
+      //\r
+      // Storage\r
+      //\r
+      case EFI_IFR_VARSTORE_OP:\r
+\r
+        //\r
+        // Create a buffer Storage for this FormSet\r
+        //\r
+        Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_BUFFER, OpCodeData);\r
+        CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE *)OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));\r
+        break;\r
+\r
+      case EFI_IFR_VARSTORE_NAME_VALUE_OP:\r
+\r
+        //\r
+        // Create a name/value Storage for this FormSet\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
+        break;\r
+\r
+      case EFI_IFR_VARSTORE_EFI_OP:\r
+\r
+        //\r
+        // Create a EFI variable Storage for this FormSet\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
+\r
+        CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_EFI *)OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));\r
+        break;\r
+\r
+      //\r
+      // DefaultStore\r
+      //\r
+      case EFI_IFR_DEFAULTSTORE_OP:\r
+\r
+        HaveInserted = FALSE;\r
+        DefaultStore = AllocateZeroPool (sizeof (HII_FORMSET_DEFAULTSTORE));\r
+        if (DefaultStore == NULL) {\r
+          return EFI_OUT_OF_RESOURCES;\r
+        }\r
+\r
+        DefaultStore->Signature = HII_FORMSET_DEFAULTSTORE_SIGNATURE;\r
+\r
+        CopyMem (&DefaultStore->DefaultId, &((EFI_IFR_DEFAULTSTORE *)OpCodeData)->DefaultId, sizeof (UINT16));\r
+        CopyMem (&DefaultStore->DefaultName, &((EFI_IFR_DEFAULTSTORE *)OpCodeData)->DefaultName, sizeof (EFI_STRING_ID));\r
+        //\r
+        // Insert it to the DefaultStore list of this Formset with ascending order.\r
+        //\r
+        if (!IsListEmpty (&FormSet->DefaultStoreListHead)) {\r
+          DefaultLink = GetFirstNode (&FormSet->DefaultStoreListHead);\r
+          while (!IsNull (&FormSet->DefaultStoreListHead, DefaultLink)) {\r
+            PreDefaultStore = HII_FORMSET_DEFAULTSTORE_FROM_LINK (DefaultLink);\r
+            DefaultLink     = GetNextNode (&FormSet->DefaultStoreListHead, DefaultLink);\r
+            if (DefaultStore->DefaultId < PreDefaultStore->DefaultId) {\r
+              InsertTailList (&PreDefaultStore->Link, &DefaultStore->Link);\r
+              HaveInserted = TRUE;\r
+              break;\r
+            }\r
+          }\r
+        }\r
+\r
+        if (!HaveInserted) {\r
+          InsertTailList (&FormSet->DefaultStoreListHead, &DefaultStore->Link);\r
+        }\r
+\r
+        break;\r
+\r
+      //\r
+      // Statements\r
+      //\r
+      case EFI_IFR_SUBTITLE_OP:\r
+\r
+        CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);\r
+        break;\r
+\r
+      case EFI_IFR_TEXT_OP:\r
+\r
+        CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);\r
+        CopyMem (&CurrentStatement->ExtraData.TextTwo, &((EFI_IFR_TEXT *)OpCodeData)->TextTwo, sizeof (EFI_STRING_ID));\r
+        break;\r
+\r
+      case EFI_IFR_RESET_BUTTON_OP:\r
+\r
+        CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);\r
+        CopyMem (&CurrentStatement->ExtraData.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
+\r
+        CurrentStatement             = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
+        CurrentStatement->Value.Type = EFI_IFR_TYPE_ACTION;\r
+\r
+        if (OpCodeLength == sizeof (EFI_IFR_ACTION_1)) {\r
+          //\r
+          // No QuestionConfig present, so no configuration string will be processed\r
+          //\r
+          CurrentStatement->ExtraData.QuestionConfig = 0;\r
+        } else {\r
+          CopyMem (&CurrentStatement->ExtraData.QuestionConfig, &((EFI_IFR_ACTION *)OpCodeData)->QuestionConfig, sizeof (EFI_STRING_ID));\r
+        }\r
+\r
+        break;\r
+\r
+      case EFI_IFR_REF_OP:\r
+\r
+        CurrentStatement     = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
+        StatementValue       = &CurrentStatement->Value;\r
+        StatementValue->Type = EFI_IFR_TYPE_REF;\r
+        if (OpCodeLength >= sizeof (EFI_IFR_REF)) {\r
+          CopyMem (&StatementValue->Value.ref.FormId, &((EFI_IFR_REF *)OpCodeData)->FormId, sizeof (EFI_FORM_ID));\r
+\r
+          if (OpCodeLength >= sizeof (EFI_IFR_REF2)) {\r
+            CopyMem (&StatementValue->Value.ref.QuestionId, &((EFI_IFR_REF2 *)OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));\r
+\r
+            if (OpCodeLength >= sizeof (EFI_IFR_REF3)) {\r
+              CopyMem (&StatementValue->Value.ref.FormSetGuid, &((EFI_IFR_REF3 *)OpCodeData)->FormSetId, sizeof (EFI_GUID));\r
+\r
+              if (OpCodeLength >= sizeof (EFI_IFR_REF4)) {\r
+                CopyMem (&StatementValue->Value.ref.DevicePath, &((EFI_IFR_REF4 *)OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));\r
+              }\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
+\r
+        CurrentStatement                          = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
+        CurrentStatement->ExtraData.NumData.Flags = ((EFI_IFR_ONE_OF *)OpCodeData)->Flags;\r
+        StatementValue                            = &CurrentStatement->Value;\r
+\r
+        if (QuestionReferBitField) {\r
+          //\r
+          // Get the bit var store info (bit/byte offset, bit/byte offset)\r
+          //\r
+          CurrentStatement->QuestionReferToBitField = TRUE;\r
+          CurrentStatement->BitStorageWidth         = CurrentStatement->ExtraData.NumData.Flags & EDKII_IFR_NUMERIC_SIZE_BIT;\r
+          CurrentStatement->BitVarOffset            = CurrentStatement->VarStoreInfo.VarOffset;\r
+          CurrentStatement->VarStoreInfo.VarOffset  = CurrentStatement->BitVarOffset / 8;\r
+          TotalBits                                 = CurrentStatement->BitVarOffset % 8 + CurrentStatement->BitStorageWidth;\r
+          CurrentStatement->StorageWidth            = (TotalBits % 8 == 0 ? TotalBits / 8 : TotalBits / 8 + 1);\r
+\r
+          //\r
+          // Get the Minimum/Maximum/Step value(Note: bit field type has been stored as UINT32 type)\r
+          //\r
+          CurrentStatement->ExtraData.NumData.Minimum = ((EFI_IFR_NUMERIC *)OpCodeData)->data.u32.MinValue;\r
+          CurrentStatement->ExtraData.NumData.Maximum = ((EFI_IFR_NUMERIC *)OpCodeData)->data.u32.MaxValue;\r
+          CurrentStatement->ExtraData.NumData.Step    = ((EFI_IFR_NUMERIC *)OpCodeData)->data.u32.Step;\r
+\r
+          //\r
+          // Update the Flag and type of Minimum/Maximum/Step according to the actual width of bit field,\r
+          // in order to make Browser handle these question with bit varstore correctly.\r
+          //\r
+          ((EFI_IFR_NUMERIC *)OpCodeData)->Flags  &=  EDKII_IFR_DISPLAY_BIT;\r
+          ((EFI_IFR_NUMERIC *)OpCodeData)->Flags >>= 2;\r
+          switch (CurrentStatement->StorageWidth) {\r
+            case 1:\r
+              ((EFI_IFR_NUMERIC *)OpCodeData)->Flags           |= EFI_IFR_TYPE_NUM_SIZE_8;\r
+              ((EFI_IFR_NUMERIC *)OpCodeData)->data.u8.MinValue = (UINT8)CurrentStatement->ExtraData.NumData.Minimum;\r
+              ((EFI_IFR_NUMERIC *)OpCodeData)->data.u8.MaxValue = (UINT8)CurrentStatement->ExtraData.NumData.Maximum;\r
+              ((EFI_IFR_NUMERIC *)OpCodeData)->data.u8.Step     = (UINT8)CurrentStatement->ExtraData.NumData.Step;\r
+              StatementValue->Type                              = EFI_IFR_TYPE_NUM_SIZE_8;\r
+              break;\r
+            case 2:\r
+              ((EFI_IFR_NUMERIC *)OpCodeData)->Flags            |= EFI_IFR_TYPE_NUM_SIZE_16;\r
+              ((EFI_IFR_NUMERIC *)OpCodeData)->data.u16.MinValue = (UINT16)CurrentStatement->ExtraData.NumData.Minimum;\r
+              ((EFI_IFR_NUMERIC *)OpCodeData)->data.u16.MaxValue = (UINT16)CurrentStatement->ExtraData.NumData.Maximum;\r
+              ((EFI_IFR_NUMERIC *)OpCodeData)->data.u16.Step     = (UINT16)CurrentStatement->ExtraData.NumData.Step;\r
+              StatementValue->Type                               = EFI_IFR_TYPE_NUM_SIZE_16;\r
+              break;\r
+            case 3:\r
+            case 4:\r
+              ((EFI_IFR_NUMERIC *)OpCodeData)->Flags            |= EFI_IFR_TYPE_NUM_SIZE_32;\r
+              ((EFI_IFR_NUMERIC *)OpCodeData)->data.u32.MinValue = (UINT32)CurrentStatement->ExtraData.NumData.Minimum;\r
+              ((EFI_IFR_NUMERIC *)OpCodeData)->data.u32.MaxValue = (UINT32)CurrentStatement->ExtraData.NumData.Maximum;\r
+              ((EFI_IFR_NUMERIC *)OpCodeData)->data.u32.Step     = (UINT32)CurrentStatement->ExtraData.NumData.Step;\r
+              StatementValue->Type                               = EFI_IFR_TYPE_NUM_SIZE_32;\r
+              break;\r
+            default:\r
+              break;\r
+          }\r
+        } else {\r
+          switch (CurrentStatement->ExtraData.NumData.Flags & EFI_IFR_NUMERIC_SIZE) {\r
+            case EFI_IFR_NUMERIC_SIZE_1:\r
+              CurrentStatement->ExtraData.NumData.Minimum = ((EFI_IFR_NUMERIC *)OpCodeData)->data.u8.MinValue;\r
+              CurrentStatement->ExtraData.NumData.Maximum = ((EFI_IFR_NUMERIC *)OpCodeData)->data.u8.MaxValue;\r
+              CurrentStatement->ExtraData.NumData.Step    = ((EFI_IFR_NUMERIC *)OpCodeData)->data.u8.Step;\r
+              CurrentStatement->StorageWidth              = (UINT16)sizeof (UINT8);\r
+              StatementValue->Type                        = EFI_IFR_TYPE_NUM_SIZE_8;\r
+\r
+              break;\r
+\r
+            case EFI_IFR_NUMERIC_SIZE_2:\r
+              CopyMem (&CurrentStatement->ExtraData.NumData.Minimum, &((EFI_IFR_NUMERIC *)OpCodeData)->data.u16.MinValue, sizeof (UINT16));\r
+              CopyMem (&CurrentStatement->ExtraData.NumData.Maximum, &((EFI_IFR_NUMERIC *)OpCodeData)->data.u16.MaxValue, sizeof (UINT16));\r
+              CopyMem (&CurrentStatement->ExtraData.NumData.Step, &((EFI_IFR_NUMERIC *)OpCodeData)->data.u16.Step, sizeof (UINT16));\r
+              CurrentStatement->StorageWidth = (UINT16)sizeof (UINT16);\r
+              StatementValue->Type           = EFI_IFR_TYPE_NUM_SIZE_16;\r
+\r
+              break;\r
+\r
+            case EFI_IFR_NUMERIC_SIZE_4:\r
+              CopyMem (&CurrentStatement->ExtraData.NumData.Minimum, &((EFI_IFR_NUMERIC *)OpCodeData)->data.u32.MinValue, sizeof (UINT32));\r
+              CopyMem (&CurrentStatement->ExtraData.NumData.Maximum, &((EFI_IFR_NUMERIC *)OpCodeData)->data.u32.MaxValue, sizeof (UINT32));\r
+              CopyMem (&CurrentStatement->ExtraData.NumData.Step, &((EFI_IFR_NUMERIC *)OpCodeData)->data.u32.Step, sizeof (UINT32));\r
+              CurrentStatement->StorageWidth = (UINT16)sizeof (UINT32);\r
+              StatementValue->Type           = EFI_IFR_TYPE_NUM_SIZE_32;\r
+\r
+              break;\r
+\r
+            case EFI_IFR_NUMERIC_SIZE_8:\r
+              CopyMem (&CurrentStatement->ExtraData.NumData.Minimum, &((EFI_IFR_NUMERIC *)OpCodeData)->data.u64.MinValue, sizeof (UINT64));\r
+              CopyMem (&CurrentStatement->ExtraData.NumData.Maximum, &((EFI_IFR_NUMERIC *)OpCodeData)->data.u64.MaxValue, sizeof (UINT64));\r
+              CopyMem (&CurrentStatement->ExtraData.NumData.Step, &((EFI_IFR_NUMERIC *)OpCodeData)->data.u64.Step, sizeof (UINT64));\r
+              CurrentStatement->StorageWidth = (UINT16)sizeof (UINT64);\r
+              StatementValue->Type           = EFI_IFR_TYPE_NUM_SIZE_64;\r
+\r
+              break;\r
+\r
+            default:\r
+\r
+              break;\r
+          }\r
+        }\r
+\r
+        InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);\r
+\r
+        if ((Operand == EFI_IFR_ONE_OF_OP) && (Scope != 0)) {\r
+          SuppressForOption = TRUE;\r
+        }\r
+\r
+        break;\r
+\r
+      case EFI_IFR_ORDERED_LIST_OP:\r
+\r
+        CurrentStatement                                        = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
+        CurrentStatement->ExtraData.OrderListData.Flags         = ((EFI_IFR_ORDERED_LIST *)OpCodeData)->Flags;\r
+        CurrentStatement->ExtraData.OrderListData.MaxContainers = ((EFI_IFR_ORDERED_LIST *)OpCodeData)->MaxContainers;\r
+        CurrentStatement->Value.Type                            = EFI_IFR_TYPE_BUFFER;\r
+        CurrentStatement->Value.Buffer                          = NULL;\r
+\r
+        if (Scope != 0) {\r
+          SuppressForOption = TRUE;\r
+        }\r
+\r
+        break;\r
+\r
+      case EFI_IFR_CHECKBOX_OP:\r
+\r
+        CurrentStatement                  = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
+        CurrentStatement->ExtraData.Flags = ((EFI_IFR_CHECKBOX *)OpCodeData)->Flags;\r
+        CurrentStatement->StorageWidth    = (UINT16)sizeof (BOOLEAN);\r
+        CurrentStatement->Value.Type      = EFI_IFR_TYPE_BOOLEAN;\r
+\r
+        if (QuestionReferBitField) {\r
+          //\r
+          // Get the bit var store info (bit/byte offset, bit/byte offset)\r
+          //\r
+          CurrentStatement->QuestionReferToBitField = TRUE;\r
+          CurrentStatement->BitStorageWidth         = 1;\r
+          CurrentStatement->BitVarOffset            = CurrentStatement->VarStoreInfo.VarOffset;\r
+          CurrentStatement->VarStoreInfo.VarOffset  = CurrentStatement->BitVarOffset / 8;\r
+          TotalBits                                 = CurrentStatement->BitVarOffset % 8 + CurrentStatement->BitStorageWidth;\r
+          CurrentStatement->StorageWidth            = (TotalBits % 8 == 0 ? TotalBits / 8 : TotalBits / 8 + 1);\r
+        }\r
+\r
+        InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);\r
+\r
+        break;\r
+\r
+      case EFI_IFR_STRING_OP:\r
+\r
+        CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
+\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
+        // The characters are stored as Unicode, so the storage width should multiply 2.\r
+        //\r
+        CurrentStatement->ExtraData.StrData.MinSize = ((EFI_IFR_STRING *)OpCodeData)->MinSize;\r
+        CurrentStatement->ExtraData.StrData.MaxSize = ((EFI_IFR_STRING *)OpCodeData)->MaxSize;\r
+        CurrentStatement->ExtraData.StrData.Flags   = ((EFI_IFR_STRING *)OpCodeData)->Flags;\r
+        CurrentStatement->StorageWidth              = (UINT16)((UINTN)CurrentStatement->ExtraData.StrData.MaxSize * sizeof (CHAR16));\r
+\r
+        CurrentStatement->Value.Type   = EFI_IFR_TYPE_STRING;\r
+        CurrentStatement->Value.Buffer = AllocateZeroPool (CurrentStatement->StorageWidth + sizeof (CHAR16));\r
+        if (CurrentStatement->Value.Buffer == NULL) {\r
+          return EFI_OUT_OF_RESOURCES;\r
+        }\r
+\r
+        CurrentStatement->Value.Value.string = NewHiiString ((CHAR16 *)CurrentStatement->Value.Buffer, FormSet->HiiHandle);\r
+\r
+        InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);\r
+        break;\r
+\r
+      case EFI_IFR_PASSWORD_OP:\r
+\r
+        CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
+\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
+        // The characters are stored as Unicode, so the storage width should multiply 2.\r
+        //\r
+        CopyMem (&CurrentStatement->ExtraData.PwdData.MinSize, &((EFI_IFR_PASSWORD *)OpCodeData)->MinSize, sizeof (UINT16));\r
+        CopyMem (&CurrentStatement->ExtraData.PwdData.MaxSize, &((EFI_IFR_PASSWORD *)OpCodeData)->MaxSize, sizeof (UINT16));\r
+        CurrentStatement->StorageWidth = (UINT16)((UINTN)CurrentStatement->ExtraData.PwdData.MaxSize * sizeof (CHAR16));\r
+\r
+        CurrentStatement->Value.Type   = EFI_IFR_TYPE_STRING;\r
+        CurrentStatement->Value.Buffer = AllocateZeroPool ((CurrentStatement->StorageWidth + sizeof (CHAR16)));\r
+        if (CurrentStatement->Value.Buffer == NULL) {\r
+          return EFI_OUT_OF_RESOURCES;\r
+        }\r
+\r
+        CurrentStatement->Value.Value.string = NewHiiString ((CHAR16 *)CurrentStatement->Value.Buffer, FormSet->HiiHandle);\r
+\r
+        InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);\r
+        break;\r
+\r
+      case EFI_IFR_DATE_OP:\r
+\r
+        CurrentStatement                  = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
+        CurrentStatement->ExtraData.Flags = ((EFI_IFR_DATE *)OpCodeData)->Flags;\r
+        CurrentStatement->Value.Type      = EFI_IFR_TYPE_DATE;\r
+\r
+        if ((CurrentStatement->ExtraData.Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_NORMAL) {\r
+          CurrentStatement->StorageWidth = (UINT16)sizeof (EFI_HII_DATE);\r
+\r
+          InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);\r
+        } else {\r
+          //\r
+          // Don't assign storage for RTC type of date/time\r
+          //\r
+          CurrentStatement->Storage      = NULL;\r
+          CurrentStatement->StorageWidth = 0;\r
+        }\r
+\r
+        break;\r
+\r
+      case EFI_IFR_TIME_OP:\r
+\r
+        CurrentStatement                  = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
+        CurrentStatement->ExtraData.Flags = ((EFI_IFR_TIME *)OpCodeData)->Flags;\r
+        CurrentStatement->Value.Type      = EFI_IFR_TYPE_TIME;\r
+\r
+        if ((CurrentStatement->ExtraData.Flags & QF_TIME_STORAGE) == QF_TIME_STORAGE_NORMAL) {\r
+          CurrentStatement->StorageWidth = (UINT16)sizeof (EFI_HII_TIME);\r
+\r
+          InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);\r
+        } else {\r
+          //\r
+          // Don't assign storage for RTC type of date/time\r
+          //\r
+          CurrentStatement->Storage      = NULL;\r
+          CurrentStatement->StorageWidth = 0;\r
+        }\r
+\r
+        break;\r
+\r
+      //\r
+      // Default\r
+      //\r
+      case EFI_IFR_DEFAULT_OP:\r
+\r
+        //\r
+        // EFI_IFR_DEFAULT appear in scope of a Question,\r
+        // It creates a default value for the current question.\r
+        // A Question may have more than one Default value which have different default types.\r
+        //\r
+        CurrentDefault = AllocateZeroPool (sizeof (HII_QUESTION_DEFAULT));\r
+        if (CurrentDefault == NULL) {\r
+          return EFI_OUT_OF_RESOURCES;\r
+        }\r
+\r
+        CurrentDefault->Signature = HII_QUESTION_DEFAULT_SIGNATURE;\r
+\r
+        CurrentDefault->Value.Type = ((EFI_IFR_DEFAULT *)OpCodeData)->Type;\r
+        CopyMem (&CurrentDefault->DefaultId, &((EFI_IFR_DEFAULT *)OpCodeData)->DefaultId, sizeof (UINT16));\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
+          if (CurrentDefault->Value.Buffer == NULL) {\r
+            FreePool (CurrentDefault);\r
+            return EFI_OUT_OF_RESOURCES;\r
+          }\r
+\r
+          if (ParentStatement->Operand == EFI_IFR_ORDERED_LIST_OP) {\r
+            ParentStatement->Value.BufferLen = CurrentDefault->Value.BufferLen;\r
+            CopyMem (ParentStatement->Value.Buffer, CurrentDefault->Value.Buffer, ParentStatement->Value.BufferLen);\r
+          }\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
+          CopyMem (&ParentStatement->Value.Value, &((EFI_IFR_DEFAULT *)OpCodeData)->Value, OpCodeLength - OFFSET_OF (EFI_IFR_DEFAULT, Value));\r
+          ExtendValueToU64 (&ParentStatement->Value);\r
+        }\r
+\r
+        //\r
+        // Insert to Default Value list of current Question\r
+        //\r
+        InsertTailList (&ParentStatement->DefaultListHead, &CurrentDefault->Link);\r
+\r
+        if (Scope != 0) {\r
+          InScopeDefault = TRUE;\r
+        }\r
+\r
+        break;\r
+\r
+      //\r
+      // Option\r
+      //\r
+      case EFI_IFR_ONE_OF_OPTION_OP:\r
+\r
+        if (ParentStatement == NULL) {\r
+          break;\r
+        }\r
+\r
+        CurrentDefault = NULL;\r
+        if (((ParentStatement->Operand == EFI_IFR_ORDERED_LIST_OP) || (ParentStatement->Operand == EFI_IFR_ONE_OF_OP)) &&\r
+            ((((EFI_IFR_ONE_OF_OPTION *)OpCodeData)->Flags & (EFI_IFR_OPTION_DEFAULT | EFI_IFR_OPTION_DEFAULT_MFG)) != 0))\r
+        {\r
+          CurrentDefault = AllocateZeroPool (sizeof (HII_QUESTION_DEFAULT));\r
+          if (CurrentDefault == NULL) {\r
+            return EFI_OUT_OF_RESOURCES;\r
+          }\r
+\r
+          CurrentDefault->Signature = HII_QUESTION_DEFAULT_SIGNATURE;\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
+          if (ParentStatement->Operand == EFI_IFR_ORDERED_LIST_OP) {\r
+            CurrentDefault->Value.Type      = EFI_IFR_TYPE_BUFFER;\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
+            if (CurrentDefault->Value.Buffer == NULL) {\r
+              FreePool (CurrentDefault);\r
+              return EFI_OUT_OF_RESOURCES;\r
+            }\r
+          } else {\r
+            CurrentDefault->Value.Type = ((EFI_IFR_ONE_OF_OPTION *)OpCodeData)->Type;\r
+            CopyMem (&CurrentDefault->Value.Value, &((EFI_IFR_ONE_OF_OPTION *)OpCodeData)->Value, sizeof (EFI_IFR_TYPE_VALUE));\r
+            ExtendValueToU64 (&CurrentDefault->Value);\r
+          }\r
+\r
+          //\r
+          // Insert to Default Value list of current Question\r
+          //\r
+          InsertTailList (&ParentStatement->DefaultListHead, &CurrentDefault->Link);\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
+        //\r
+        CurrentOption = AllocateZeroPool (sizeof (HII_QUESTION_OPTION));\r
+        if (CurrentOption == NULL) {\r
+          return EFI_OUT_OF_RESOURCES;\r
+        }\r
+\r
+        CurrentOption->Signature  = HII_QUESTION_OPTION_SIGNATURE;\r
+        CurrentOption->OpCode     = (EFI_IFR_ONE_OF_OPTION *)OpCodeData;\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, OpCodeLength - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));\r
+        ExtendValueToU64 (&CurrentOption->Value);\r
+\r
+        ConditionalExprCount = GetConditionalExpressionCount (ExpressOption);\r
+        if ( ConditionalExprCount > 0) {\r
+          //\r
+          // Form is inside of suppressif\r
+          //\r
+          CurrentOption->SuppressExpression = (HII_EXPRESSION_LIST *)AllocatePool (\r
+                                                                       (UINTN)(sizeof (HII_EXPRESSION_LIST) + ((ConditionalExprCount -1) * sizeof (HII_EXPRESSION *)))\r
+                                                                       );\r
+          if (CurrentOption->SuppressExpression == NULL) {\r
+            FreePool (CurrentOption);\r
+            return EFI_OUT_OF_RESOURCES;\r
+          }\r
+\r
+          CurrentOption->SuppressExpression->Count     = (UINTN)ConditionalExprCount;\r
+          CurrentOption->SuppressExpression->Signature = HII_EXPRESSION_LIST_SIGNATURE;\r
+          CopyMem (CurrentOption->SuppressExpression->Expression, GetConditionalExpressionList (ExpressOption), (UINTN)(sizeof (HII_EXPRESSION *) * ConditionalExprCount));\r
+        }\r
+\r
+        //\r
+        // Insert to Option list of current Question\r
+        //\r
+        InsertTailList (&ParentStatement->OptionListHead, &CurrentOption->Link);\r
+\r
+        //\r
+        // Now we know the Storage width of nested Ordered List\r
+        //\r
+        if ((ParentStatement->Operand == EFI_IFR_ORDERED_LIST_OP) && (ParentStatement->Value.Buffer == 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->ExtraData.OrderListData.MaxContainers * Width);\r
+          ParentStatement->Value.Buffer = AllocateZeroPool (ParentStatement->StorageWidth);\r
+          if (ParentStatement->Value.Buffer == NULL) {\r
+            return EFI_OUT_OF_RESOURCES;\r
+          }\r
+\r
+          ParentStatement->Value.BufferLen       = 0;\r
+          ParentStatement->Value.BufferValueType = CurrentOption->Value.Type;\r
+          InitializeRequestElement (FormSet, ParentStatement, CurrentForm);\r
+        }\r
+\r
+        break;\r
+\r
+      //\r
+      // Conditional\r
+      //\r
+      case EFI_IFR_NO_SUBMIT_IF_OP:\r
+      case EFI_IFR_INCONSISTENT_IF_OP:\r
+\r
+        //\r
+        // Create an Expression node\r
+        //\r
+        CurrentExpression = CreateExpression (CurrentForm, OpCodeData);\r
+        CopyMem (&CurrentExpression->ExtraData.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 (&ParentStatement->NoSubmitListHead, &CurrentExpression->Link);\r
+        } else {\r
+          CurrentExpression->Type = EFI_HII_EXPRESSION_INCONSISTENT_IF;\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
+\r
+        break;\r
+\r
+      case EFI_IFR_WARNING_IF_OP:\r
+\r
+        //\r
+        // Create an Expression node\r
+        //\r
+        CurrentExpression = CreateExpression (CurrentForm, OpCodeData);\r
+        CopyMem (&CurrentExpression->ExtraData.WarningIfData.WarningIfError, &((EFI_IFR_WARNING_IF *)OpCodeData)->Warning, sizeof (EFI_STRING_ID));\r
+        CurrentExpression->ExtraData.WarningIfData.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
+\r
+        break;\r
+\r
+      case EFI_IFR_SUPPRESS_IF_OP:\r
+\r
+        //\r
+        // Question and Option will appear in scope of this OpCode\r
+        //\r
+        CurrentExpression       = CreateExpression (CurrentForm, OpCodeData);\r
+        CurrentExpression->Type = EFI_HII_EXPRESSION_SUPPRESS_IF;\r
+\r
+        if (SuppressForOption) {\r
+          PushConditionalExpression (CurrentExpression, ExpressOption);\r
+        } else if (SuppressForQuestion) {\r
+          PushConditionalExpression (CurrentExpression, ExpressStatement);\r
+        } else {\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
+\r
+        break;\r
+\r
+      case EFI_IFR_GRAY_OUT_IF_OP:\r
+\r
+        //\r
+        // Questions will appear in scope of this OpCode\r
+        //\r
+        CurrentExpression       = CreateExpression (CurrentForm, OpCodeData);\r
+        CurrentExpression->Type = EFI_HII_EXPRESSION_GRAY_OUT_IF;\r
+        PushConditionalExpression (CurrentExpression, ExpressStatement);\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
+\r
+        break;\r
+\r
+      case EFI_IFR_DISABLE_IF_OP:\r
+\r
+        //\r
+        // The DisableIf expression should only rely on constant, so it could be\r
+        // evaluated at initialization and it will not be queued\r
+        //\r
+        CurrentExpression = AllocateZeroPool (sizeof (HII_EXPRESSION));\r
+        if (CurrentExpression == NULL) {\r
+          return EFI_OUT_OF_RESOURCES;\r
+        }\r
+\r
+        CurrentExpression->Signature = HII_EXPRESSION_SIGNATURE;\r
+        CurrentExpression->Type      = EFI_HII_EXPRESSION_DISABLE_IF;\r
+        InitializeListHead (&CurrentExpression->OpCodeListHead);\r
+\r
+        if (CurrentForm != NULL) {\r
+          //\r
+          // This is DisableIf for Question, enqueue it to Form expression list\r
+          //\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
+        //\r
+        if (((EFI_IFR_OP_HEADER *)(OpCodeData + OpCodeLength))->Scope == 0) {\r
+          SingleOpCodeExpression = TRUE;\r
+        }\r
+\r
+        break;\r
+\r
+      //\r
+      // Expression\r
+      //\r
+      case EFI_IFR_VALUE_OP:\r
+\r
+        CurrentExpression       = CreateExpression (CurrentForm, OpCodeData);\r
+        CurrentExpression->Type = EFI_HII_EXPRESSION_VALUE;\r
+\r
+        if (InScopeDefault) {\r
+          //\r
+          // Used for default (EFI_IFR_DEFAULT)\r
+          //\r
+          CurrentDefault->ValueExpression = CurrentExpression;\r
+        } else {\r
+          //\r
+          // If used for a question, then the question will be read-only\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
+          if (ParentStatement == NULL) {\r
+            break;\r
+          }\r
+\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
+\r
+        break;\r
+\r
+      case EFI_IFR_RULE_OP:\r
+\r
+        CurrentExpression       = CreateExpression (CurrentForm, OpCodeData);\r
+        CurrentExpression->Type = EFI_HII_EXPRESSION_RULE;\r
+\r
+        CurrentExpression->ExtraData.RuleId = ((EFI_IFR_RULE *)OpCodeData)->RuleId;\r
+        InsertTailList (&CurrentForm->RuleListHead, &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
+\r
+        break;\r
+\r
+      case EFI_IFR_READ_OP:\r
+\r
+        CurrentExpression       = CreateExpression (CurrentForm, OpCodeData);\r
+        CurrentExpression->Type = EFI_HII_EXPRESSION_READ;\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
+        if (ParentStatement == NULL) {\r
+          break;\r
+        }\r
+\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
+\r
+        break;\r
+\r
+      case EFI_IFR_WRITE_OP:\r
+\r
+        CurrentExpression       = CreateExpression (CurrentForm, OpCodeData);\r
+        CurrentExpression->Type = EFI_HII_EXPRESSION_WRITE;\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
+        if (ParentStatement == NULL) {\r
+          break;\r
+        }\r
+\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
+\r
+        break;\r
+\r
+      //\r
+      // Image\r
+      //\r
+      case EFI_IFR_IMAGE_OP:\r
+        //\r
+        // Get ScopeOpcode from top of stack\r
+        //\r
+        PopScope (&ScopeOpCode);\r
+        PushScope (ScopeOpCode);\r
+\r
+        switch (ScopeOpCode) {\r
+          case EFI_IFR_FORM_SET_OP:\r
+\r
+            ImageId = &FormSet->ImageId;\r
+            break;\r
+\r
+          case EFI_IFR_FORM_OP:\r
+          case EFI_IFR_FORM_MAP_OP:\r
+\r
+            if (CurrentForm != NULL) {\r
+              ImageId = &CurrentForm->ImageId;\r
+            }\r
+\r
+            break;\r
+\r
+          case EFI_IFR_ONE_OF_OPTION_OP:\r
+\r
+            if (CurrentOption != NULL) {\r
+              ImageId = &CurrentOption->ImageId;\r
+            }\r
+\r
+            break;\r
+\r
+          default:\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.\r
+            //\r
+            if (ParentStatement != NULL) {\r
+              ImageId = &ParentStatement->ImageId;\r
+            }\r
+\r
+            break;\r
+        }\r
+\r
+        CopyMem (ImageId, &((EFI_IFR_IMAGE *)OpCodeData)->Id, sizeof (EFI_IMAGE_ID));\r
+        break;\r
+\r
+      //\r
+      // Refresh\r
+      //\r
+      case EFI_IFR_REFRESH_OP:\r
+\r
+        if (ParentStatement != NULL) {\r
+          ParentStatement->RefreshInterval = ((EFI_IFR_REFRESH *)OpCodeData)->RefreshInterval;\r
+        }\r
+\r
+        break;\r
+\r
+      //\r
+      // Refresh guid.\r
+      //\r
+      case EFI_IFR_REFRESH_ID_OP:\r
+        //\r
+        // Get ScopeOpcode from top of stack\r
+        //\r
+        PopScope (&ScopeOpCode);\r
+        PushScope (ScopeOpCode);\r
+\r
+        switch (ScopeOpCode) {\r
+          case EFI_IFR_FORM_OP:\r
+          case EFI_IFR_FORM_MAP_OP:\r
+\r
+            if (CurrentForm != NULL) {\r
+              CopyMem (&CurrentForm->RefreshGuid, &((EFI_IFR_REFRESH_ID *)OpCodeData)->RefreshEventGroupId, sizeof (EFI_GUID));\r
+            }\r
+\r
+            break;\r
+\r
+          default:\r
+\r
+            if (ParentStatement != NULL) {\r
+              if (ParentStatement->Operand == EFI_IFR_NUMERIC_OP) {\r
+                CopyMem (&ParentStatement->ExtraData.NumData.Guid, &((EFI_IFR_REFRESH_ID *)OpCodeData)->RefreshEventGroupId, sizeof (EFI_GUID));\r
+              }\r
+            }\r
+\r
+            break;\r
+        }\r
+\r
+        break;\r
+\r
+      //\r
+      // Modal tag\r
+      //\r
+      case EFI_IFR_MODAL_TAG_OP:\r
+\r
+        if (CurrentForm != NULL) {\r
+          CurrentForm->ModalForm = TRUE;\r
+        }\r
+\r
+        break;\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
+\r
+        switch (ScopeOpCode) {\r
+          case EFI_IFR_FORM_OP:\r
+          case EFI_IFR_FORM_MAP_OP:\r
+\r
+            if (CurrentForm != NULL) {\r
+              CurrentForm->Locked = TRUE;\r
+            }\r
+\r
+            break;\r
+\r
+          default:\r
+\r
+            if (ParentStatement != NULL) {\r
+              ParentStatement->Locked = TRUE;\r
+            }\r
+        }\r
+\r
+        break;\r
+\r
+      //\r
+      // Vendor specific\r
+      //\r
+      case EFI_IFR_GUID_OP:\r
+        CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);\r
+        if (CompareGuid ((EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)), &gEdkiiIfrBitVarstoreGuid)) {\r
+          Scope                 = 0;\r
+          QuestionReferBitField = TRUE;\r
+        }\r
+\r
+        break;\r
+\r
+      //\r
+      // Scope End\r
+      //\r
+      case EFI_IFR_END_OP:\r
+        QuestionReferBitField = FALSE;\r
+        Status                = PopScope (&ScopeOpCode);\r
+        if (EFI_ERROR (Status)) {\r
+          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
+            //\r
+            // End of FormSet, update FormSet IFR binary length\r
+            // to stop parsing substantial OpCodes\r
+            //\r
+            FormSet->IfrBinaryLength = OpCodeOffset;\r
+            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
+            //\r
+            // End of Option\r
+            //\r
+            CurrentOption = NULL;\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
+            break;\r
+\r
+          case EFI_IFR_SUPPRESS_IF_OP:\r
+            if (SuppressForOption) {\r
+              PopConditionalExpression (ExpressOption);\r
+            } else if (SuppressForQuestion) {\r
+              PopConditionalExpression (ExpressStatement);\r
+            } else {\r
+              PopConditionalExpression (ExpressForm);\r
+            }\r
+\r
+            break;\r
+\r
+          case EFI_IFR_GRAY_OUT_IF_OP:\r
+            PopConditionalExpression (ExpressStatement);\r
+            break;\r
+\r
+          case EFI_IFR_DISABLE_IF_OP:\r
+            if (CurrentForm != NULL) {\r
+              PopConditionalExpression (ExpressStatement);\r
+            }\r
+\r
+            InScopeDisable = FALSE;\r
+            OpCodeDisabled = FALSE;\r
+            break;\r
+\r
+          case EFI_IFR_ONE_OF_OP:\r
+          case EFI_IFR_ORDERED_LIST_OP:\r
+            SuppressForOption = FALSE;\r
+            break;\r
+\r
+          case EFI_IFR_DEFAULT_OP:\r
+            InScopeDefault = FALSE;\r
+            break;\r
+\r
+          case EFI_IFR_MAP_OP:\r
+\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
+            //\r
+            // Get current expression.\r
+            //\r
+            Status = PopCurrentExpression ((VOID **)&CurrentExpression);\r
+            if (EFI_ERROR (Status)) {\r
+              return Status;\r
+            }\r
+\r
+            if (MapScopeDepth > 0) {\r
+              MapScopeDepth--;\r
+            }\r
+\r
+            break;\r
+\r
+          default:\r
+\r
+            if (IsExpressionOpCode (ScopeOpCode)) {\r
+              if (InScopeDisable && (CurrentForm == NULL)) {\r
+                //\r
+                // This is DisableIf expression for Form, it should be a constant expression\r
+                //\r
+                Status = EvaluateHiiExpression (FormSet, CurrentForm, CurrentExpression);\r
+                if (EFI_ERROR (Status)) {\r
+                  return Status;\r
+                }\r
+\r
+                OpCodeDisabled = IsHiiValueTrue (&CurrentExpression->Result);\r
+\r
+                //\r
+                // DisableIf Expression is only used once and not queued, free it\r
+                //\r
+                DestroyExpression (CurrentExpression);\r
+              }\r
+\r
+              //\r
+              // End of current Expression\r
+              //\r
+              CurrentExpression = NULL;\r
+            }\r
+\r
+            break;\r
+        }\r
+\r
+        break;\r
+\r
+      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
+}\r
diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiInternal.h b/RedfishPkg/Library/HiiUtilityLib/HiiInternal.h
new file mode 100644 (file)
index 0000000..e68a61f
--- /dev/null
@@ -0,0 +1,376 @@
+/** @file\r
+  HII internal header file.\r
+\r
+  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+  (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>\r
+  Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.\r
+\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#ifndef HII_INTERNAL_H_\r
+#define HII_INTERNAL_H_\r
+\r
+#include <Uefi.h>\r
+\r
+#include <Protocol/UnicodeCollation.h>\r
+#include <Protocol/HiiConfigRouting.h>\r
+#include <Protocol/HiiDatabase.h>\r
+#include <Protocol/UserManager.h>\r
+#include <Protocol/DevicePathFromText.h>\r
+#include <Protocol/RegularExpressionProtocol.h>\r
+\r
+#include <Guid/MdeModuleHii.h>\r
+#include <Guid/ZeroGuid.h>\r
+#include <Guid/HiiPlatformSetupFormset.h>\r
+#include <Guid/HiiFormMapMethodGuid.h>\r
+\r
+#include <Library/PrintLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/HiiLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/UefiLib.h>\r
+\r
+#include "HiiExpression.h"\r
+#include <Library/HiiUtilityLib.h>\r
+\r
+#define EXPRESSION_STACK_SIZE_INCREMENT  0x100\r
+#define EFI_IFR_SPECIFICATION_VERSION    (UINT16) (((EFI_SYSTEM_TABLE_REVISION >> 16) << 8) | (((EFI_SYSTEM_TABLE_REVISION & 0xFFFF) / 10) << 4) | ((EFI_SYSTEM_TABLE_REVISION & 0xFFFF) % 10))\r
+\r
+///\r
+/// Definition of HII_FORM_CONFIG_REQUEST\r
+//\r
+typedef struct {\r
+  UINTN                  Signature;\r
+  LIST_ENTRY             Link;\r
+\r
+  CHAR16                 *ConfigRequest; ///< <ConfigRequest> = <ConfigHdr> + <RequestElement>\r
+  CHAR16                 *ConfigAltResp; ///< Alt config response string for this ConfigRequest.\r
+  UINTN                  ElementCount;   ///< Number of <RequestElement> in the <ConfigRequest>\r
+  UINTN                  SpareStrLen;\r
+  CHAR16                 *RestoreConfigRequest; ///< When submit form fail, the element need to be restored\r
+  CHAR16                 *SyncConfigRequest;    ///< When submit form fail, the element need to be synced\r
+\r
+  HII_FORMSET_STORAGE    *Storage;\r
+} HII_FORM_CONFIG_REQUEST;\r
+\r
+#define HII_FORM_CONFIG_REQUEST_SIGNATURE  SIGNATURE_32 ('F', 'C', 'R', 'S')\r
+#define HII_FORM_CONFIG_REQUEST_FROM_LINK(a)  CR (a, HII_FORM_CONFIG_REQUEST, Link, HII_FORM_CONFIG_REQUEST_SIGNATURE)\r
+\r
+///\r
+/// Incremental string length of ConfigRequest\r
+///\r
+#define CONFIG_REQUEST_STRING_INCREMENTAL  1024\r
+\r
+/**\r
+  Allocate new memory and then copy the Unicode string Source to Destination.\r
+\r
+  @param[in,out]  Dest                   Location to copy string\r
+  @param[in]      Src                    String to copy\r
+\r
+**/\r
+VOID\r
+NewStringCopy (\r
+  IN OUT CHAR16  **Dest,\r
+  IN     CHAR16  *Src\r
+  );\r
+\r
+/**\r
+  Set Value of given Name in a NameValue Storage.\r
+\r
+  @param[in]  Storage                The NameValue Storage.\r
+  @param[in]  Name                   The Name.\r
+  @param[in]  Value                  The Value to set.\r
+  @param[out] ReturnNode             The node use the input name.\r
+\r
+  @retval EFI_SUCCESS            Value found for given Name.\r
+  @retval EFI_NOT_FOUND          No such Name found in NameValue storage.\r
+\r
+**/\r
+EFI_STATUS\r
+SetValueByName (\r
+  IN     HII_FORMSET_STORAGE  *Storage,\r
+  IN     CHAR16               *Name,\r
+  IN     CHAR16               *Value,\r
+  OUT HII_NAME_VALUE_NODE     **ReturnNode\r
+  );\r
+\r
+/**\r
+  Get bit field value from the buffer and then set the value for the question.\r
+  Note: Data type UINT32 can cover all the bit field value.\r
+\r
+  @param[in]  Question        The question refer to bit field.\r
+  @param[in]  Buffer          Point to the buffer which the question value get from.\r
+  @param[out] QuestionValue   The Question Value retrieved from Bits.\r
+\r
+**/\r
+VOID\r
+GetBitsQuestionValue (\r
+  IN     HII_STATEMENT     *Question,\r
+  IN     UINT8             *Buffer,\r
+  OUT HII_STATEMENT_VALUE  *QuestionValue\r
+  );\r
+\r
+/**\r
+  Set bit field value to the buffer.\r
+  Note: Data type UINT32 can cover all the bit field value.\r
+\r
+  @param[in]     Question        The question refer to bit field.\r
+  @param[in,out] Buffer          Point to the buffer which the question value set to.\r
+  @param[in]     Value           The bit field value need to set.\r
+\r
+**/\r
+VOID\r
+SetBitsQuestionValue (\r
+  IN     HII_STATEMENT  *Question,\r
+  IN OUT UINT8          *Buffer,\r
+  IN     UINT32         Value\r
+  );\r
+\r
+/**\r
+  Convert the buffer value to HiiValue.\r
+\r
+  @param[in]  Question              The question.\r
+  @param[in]  Value                 Unicode buffer save the question value.\r
+  @param[out] QuestionValue         The Question Value retrieved from Buffer.\r
+\r
+  @retval  Status whether convert the value success.\r
+\r
+**/\r
+EFI_STATUS\r
+BufferToQuestionValue (\r
+  IN     HII_STATEMENT     *Question,\r
+  IN     CHAR16            *Value,\r
+  OUT HII_STATEMENT_VALUE  *QuestionValue\r
+  );\r
+\r
+/**\r
+  Get the string based on the StringId and HII Package List Handle.\r
+\r
+  @param[in]  Token                  The String's ID.\r
+  @param[in]  HiiHandle              The package list in the HII database to search for\r
+                                 the specified string.\r
+\r
+  @return The output string.\r
+\r
+**/\r
+CHAR16 *\r
+GetTokenString (\r
+  IN EFI_STRING_ID   Token,\r
+  IN EFI_HII_HANDLE  HiiHandle\r
+  );\r
+\r
+/**\r
+  Converts the unicode character of the string from uppercase to lowercase.\r
+  This is a internal function.\r
+\r
+  @param[in] ConfigString  String to be converted\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+HiiStringToLowercase (\r
+  IN EFI_STRING  ConfigString\r
+  );\r
+\r
+/**\r
+  Evaluate if the result is a non-zero value.\r
+\r
+  @param[in]  Result       The result to be evaluated.\r
+\r
+  @retval TRUE             It is a non-zero value.\r
+  @retval FALSE            It is a zero value.\r
+\r
+**/\r
+BOOLEAN\r
+IsHiiValueTrue (\r
+  IN EFI_HII_VALUE  *Result\r
+  );\r
+\r
+/**\r
+  Set a new string to string package.\r
+\r
+  @param[in]  String              A pointer to the Null-terminated Unicode string\r
+                                  to add or update in the String Package associated\r
+                                  with HiiHandle.\r
+  @param[in]  HiiHandle           A handle that was previously registered in the\r
+                                  HII Database.\r
+\r
+  @return the Id for this new string.\r
+\r
+**/\r
+EFI_STRING_ID\r
+NewHiiString (\r
+  IN CHAR16          *String,\r
+  IN EFI_HII_HANDLE  HiiHandle\r
+  );\r
+\r
+/**\r
+  Perform nosubmitif check for a Form.\r
+\r
+  @param[in]  FormSet                FormSet data structure.\r
+  @param[in]  Form                   Form data structure.\r
+  @param[in]  Question               The Question to be validated.\r
+\r
+  @retval EFI_SUCCESS            Form validation pass.\r
+  @retval other                  Form validation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+ValidateNoSubmit (\r
+  IN HII_FORMSET    *FormSet,\r
+  IN HII_FORM       *Form,\r
+  IN HII_STATEMENT  *Question\r
+  );\r
+\r
+/**\r
+  Perform NoSubmit check for each Form in FormSet.\r
+\r
+  @param[in]     FormSet                FormSet data structure.\r
+  @param[in,out] CurrentForm            Current input form data structure.\r
+  @param[out]    Statement              The statement for this check.\r
+\r
+  @retval EFI_SUCCESS            Form validation pass.\r
+  @retval other                  Form validation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+NoSubmitCheck (\r
+  IN     HII_FORMSET  *FormSet,\r
+  IN OUT HII_FORM     **CurrentForm,\r
+  OUT HII_STATEMENT   **Statement\r
+  );\r
+\r
+/**\r
+  Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.\r
+\r
+  @param[in]  Storage                The Storage to be converted.\r
+  @param[in]  ConfigResp             The returned <ConfigResp>.\r
+  @param[in]  ConfigRequest          The ConfigRequest string.\r
+\r
+  @retval EFI_SUCCESS            Convert success.\r
+  @retval EFI_INVALID_PARAMETER  Incorrect storage type.\r
+\r
+**/\r
+EFI_STATUS\r
+StorageToConfigResp (\r
+  IN HII_FORMSET_STORAGE  *Storage,\r
+  IN CHAR16               **ConfigResp,\r
+  IN CHAR16               *ConfigRequest\r
+  );\r
+\r
+/**\r
+  Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.\r
+\r
+  @param[in]  Storage                The Storage to receive the settings.\r
+  @param[in]  ConfigResp             The <ConfigResp> to be converted.\r
+\r
+  @retval EFI_SUCCESS            Convert success.\r
+  @retval EFI_INVALID_PARAMETER  Incorrect storage type.\r
+\r
+**/\r
+EFI_STATUS\r
+ConfigRespToStorage (\r
+  IN HII_FORMSET_STORAGE  *Storage,\r
+  IN CHAR16               *ConfigResp\r
+  );\r
+\r
+/**\r
+  Fetch the Ifr binary data of a FormSet.\r
+\r
+  @param[in]  Handle             PackageList Handle\r
+  @param[in,out]  FormSetGuid    On input, GUID or class GUID of a formset. If not\r
+                                 specified (NULL or zero GUID), take the first\r
+                                 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
+                                 found in package list.\r
+                                 On output, GUID of the formset found(if not NULL).\r
+  @param[out]  BinaryLength      The length of the FormSet IFR binary.\r
+  @param[out]  BinaryData        The buffer designed to receive the FormSet.\r
+\r
+  @retval EFI_SUCCESS            Buffer filled with the requested FormSet.\r
+                                 BufferLength was updated.\r
+  @retval EFI_INVALID_PARAMETER  The handle is unknown.\r
+  @retval EFI_NOT_FOUND          A form or FormSet on the requested handle cannot\r
+                                 be found with the requested FormId.\r
+\r
+**/\r
+EFI_STATUS\r
+GetIfrBinaryData (\r
+  IN     EFI_HII_HANDLE  Handle,\r
+  IN OUT EFI_GUID        *FormSetGuid,\r
+  OUT    UINTN           *BinaryLength,\r
+  OUT    UINT8           **BinaryData\r
+  );\r
+\r
+/**\r
+  Fill storage with settings requested from Configuration Driver.\r
+\r
+  @param[in] FormSet                FormSet data structure.\r
+  @param[in] Storage                Buffer Storage.\r
+\r
+**/\r
+VOID\r
+LoadFormSetStorage (\r
+  IN HII_FORMSET          *FormSet,\r
+  IN HII_FORMSET_STORAGE  *Storage\r
+  );\r
+\r
+/**\r
+  Free resources of a Form.\r
+\r
+  @param[in]     FormSet                Pointer of the FormSet\r
+  @param[in,out] Form                   Pointer of the Form.\r
+\r
+**/\r
+VOID\r
+DestroyForm (\r
+  IN     HII_FORMSET  *FormSet,\r
+  IN OUT HII_FORM     *Form\r
+  );\r
+\r
+/**\r
+  Get formset storage based on the input varstoreid info.\r
+\r
+  @param[in]  FormSet                Pointer of the current FormSet.\r
+  @param[in]  VarStoreId             Varstore ID info.\r
+\r
+  @return Pointer to a HII_FORMSET_STORAGE data structure.\r
+\r
+**/\r
+HII_FORMSET_STORAGE *\r
+GetFstStgFromVarId (\r
+  IN HII_FORMSET      *FormSet,\r
+  IN EFI_VARSTORE_ID  VarStoreId\r
+  );\r
+\r
+/**\r
+  Zero extend integer/boolean/date/time to UINT64 for comparing.\r
+\r
+  @param[in]  Value                  HII Value to be converted.\r
+\r
+**/\r
+VOID\r
+ExtendValueToU64 (\r
+  IN HII_STATEMENT_VALUE  *Value\r
+  );\r
+\r
+/**\r
+  Parse opcodes in the formset IFR binary.\r
+\r
+  @param[in]  FormSet                Pointer of the FormSet data structure.\r
+\r
+  @retval EFI_SUCCESS            Opcode parse success.\r
+  @retval Other                  Opcode parse fail.\r
+\r
+**/\r
+EFI_STATUS\r
+ParseOpCodes (\r
+  IN HII_FORMSET  *FormSet\r
+  );\r
+\r
+#endif // HII_INTERNAL_H_\r
diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiUtilityInternal.c b/RedfishPkg/Library/HiiUtilityLib/HiiUtilityInternal.c
new file mode 100644 (file)
index 0000000..80b93be
--- /dev/null
@@ -0,0 +1,5770 @@
+/** @file\r
+  HII utility internal functions.\r
+\r
+  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+  (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>\r
+  Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.\r
+\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include "HiiInternal.h"\r
+\r
+CHAR16  *mUnknownString = L"!";\r
+CHAR16  *gEmptyString   = L"";\r
+\r
+EFI_HII_VALUE  *mExpressionEvaluationStack        = NULL;\r
+EFI_HII_VALUE  *mExpressionEvaluationStackEnd     = NULL;\r
+EFI_HII_VALUE  *mExpressionEvaluationStackPointer = NULL;\r
+UINTN          mExpressionEvaluationStackOffset   = 0;\r
+\r
+//\r
+// Unicode collation protocol interface\r
+//\r
+EFI_UNICODE_COLLATION_PROTOCOL  *mUnicodeCollation = NULL;\r
+EFI_USER_MANAGER_PROTOCOL       *mUserManager      = NULL;\r
+\r
+/**\r
+  Allocate new memory and then copy the Unicode string Source to Destination.\r
+\r
+  @param[in,out]  Dest                   Location to copy string\r
+  @param[in]      Src                    String to copy\r
+\r
+**/\r
+VOID\r
+NewStringCopy (\r
+  IN OUT CHAR16  **Dest,\r
+  IN     CHAR16  *Src\r
+  )\r
+{\r
+  if (*Dest != NULL) {\r
+    FreePool (*Dest);\r
+  }\r
+\r
+  *Dest = AllocateCopyPool (StrSize (Src), Src);\r
+}\r
+\r
+/**\r
+  Set Value of given Name in a NameValue Storage.\r
+\r
+  @param[in]  Storage                The NameValue Storage.\r
+  @param[in]  Name                   The Name.\r
+  @param[in]  Value                  The Value to set.\r
+  @param[out] ReturnNode             The node use the input name.\r
+\r
+  @retval EFI_SUCCESS            Value found for given Name.\r
+  @retval EFI_NOT_FOUND          No such Name found in NameValue storage.\r
+\r
+**/\r
+EFI_STATUS\r
+SetValueByName (\r
+  IN     HII_FORMSET_STORAGE  *Storage,\r
+  IN     CHAR16               *Name,\r
+  IN     CHAR16               *Value,\r
+  OUT HII_NAME_VALUE_NODE     **ReturnNode\r
+  )\r
+{\r
+  LIST_ENTRY           *Link;\r
+  HII_NAME_VALUE_NODE  *Node;\r
+  CHAR16               *Buffer;\r
+\r
+  Link = GetFirstNode (&Storage->NameValueList);\r
+  while (!IsNull (&Storage->NameValueList, Link)) {\r
+    Node = HII_NAME_VALUE_NODE_FROM_LINK (Link);\r
+\r
+    if (StrCmp (Name, Node->Name) == 0) {\r
+      Buffer = Node->Value;\r
+      if (Buffer != NULL) {\r
+        FreePool (Buffer);\r
+      }\r
+\r
+      Buffer = AllocateCopyPool (StrSize (Value), Value);\r
+      if (Buffer == NULL) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      Node->Value = Buffer;\r
+\r
+      if (ReturnNode != NULL) {\r
+        *ReturnNode = Node;\r
+      }\r
+\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    Link = GetNextNode (&Storage->NameValueList, Link);\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+  Get bit field value from the buffer and then set the value for the question.\r
+  Note: Data type UINT32 can cover all the bit field value.\r
+\r
+  @param[in]  Question        The question refer to bit field.\r
+  @param[in]  Buffer          Point to the buffer which the question value get from.\r
+  @param[out] QuestionValue   The Question Value retrieved from Bits.\r
+\r
+**/\r
+VOID\r
+GetBitsQuestionValue (\r
+  IN     HII_STATEMENT     *Question,\r
+  IN     UINT8             *Buffer,\r
+  OUT HII_STATEMENT_VALUE  *QuestionValue\r
+  )\r
+{\r
+  UINTN   StartBit;\r
+  UINTN   EndBit;\r
+  UINT32  RetVal;\r
+  UINT32  BufferValue;\r
+\r
+  StartBit = Question->BitVarOffset % 8;\r
+  EndBit   = StartBit + Question->BitStorageWidth - 1;\r
+\r
+  CopyMem ((UINT8 *)&BufferValue, Buffer, Question->StorageWidth);\r
+\r
+  RetVal = BitFieldRead32 (BufferValue, StartBit, EndBit);\r
+\r
+  //\r
+  // Set question value.\r
+  // Note: Since Question with BufferValue (orderedlist, password, string)are not supported to refer bit field.\r
+  // Only oneof/checkbox/oneof can support bit field.So we can copy the value to the HiiValue of Question directly.\r
+  //\r
+  CopyMem ((UINT8 *)&QuestionValue->Value, (UINT8 *)&RetVal, Question->StorageWidth);\r
+}\r
+\r
+/**\r
+  Set bit field value to the buffer.\r
+  Note: Data type UINT32 can cover all the bit field value.\r
+\r
+  @param[in]     Question        The question refer to bit field.\r
+  @param[in,out] Buffer          Point to the buffer which the question value set to.\r
+  @param[in]     Value           The bit field value need to set.\r
+\r
+**/\r
+VOID\r
+SetBitsQuestionValue (\r
+  IN     HII_STATEMENT  *Question,\r
+  IN OUT UINT8          *Buffer,\r
+  IN     UINT32         Value\r
+  )\r
+{\r
+  UINT32  Operand;\r
+  UINTN   StartBit;\r
+  UINTN   EndBit;\r
+  UINT32  RetVal;\r
+\r
+  StartBit = Question->BitVarOffset % 8;\r
+  EndBit   = StartBit + Question->BitStorageWidth - 1;\r
+\r
+  CopyMem ((UINT8 *)&Operand, Buffer, Question->StorageWidth);\r
+  RetVal = BitFieldWrite32 (Operand, StartBit, EndBit, Value);\r
+  CopyMem (Buffer, (UINT8 *)&RetVal, Question->StorageWidth);\r
+}\r
+\r
+/**\r
+  Convert the buffer value to HiiValue.\r
+\r
+  @param[in]  Question              The question.\r
+  @param[in]  Value                 Unicode buffer save the question value.\r
+  @param[out] QuestionValue         The Question Value retrieved from Buffer.\r
+\r
+  @retval  Status whether convert the value success.\r
+\r
+**/\r
+EFI_STATUS\r
+BufferToQuestionValue (\r
+  IN     HII_STATEMENT     *Question,\r
+  IN     CHAR16            *Value,\r
+  OUT HII_STATEMENT_VALUE  *QuestionValue\r
+  )\r
+{\r
+  CHAR16      *StringPtr;\r
+  BOOLEAN     IsBufferStorage;\r
+  CHAR16      *DstBuf;\r
+  CHAR16      TempChar;\r
+  UINTN       LengthStr;\r
+  UINT8       *Dst;\r
+  CHAR16      TemStr[5];\r
+  UINTN       Index;\r
+  UINT8       DigitUint8;\r
+  BOOLEAN     IsString;\r
+  UINTN       Length;\r
+  EFI_STATUS  Status;\r
+  UINT8       *Buffer;\r
+\r
+  Buffer = NULL;\r
+\r
+  IsString = (BOOLEAN)((QuestionValue->Type == EFI_IFR_TYPE_STRING) ?  TRUE : FALSE);\r
+  if ((Question->Storage->Type == EFI_HII_VARSTORE_BUFFER) ||\r
+      (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER))\r
+  {\r
+    IsBufferStorage = TRUE;\r
+  } else {\r
+    IsBufferStorage = FALSE;\r
+  }\r
+\r
+  //\r
+  // Question Value is provided by Buffer Storage or NameValue Storage\r
+  //\r
+  if ((QuestionValue->Type == EFI_IFR_TYPE_STRING) || (QuestionValue->Type == EFI_IFR_TYPE_BUFFER)) {\r
+    //\r
+    // This Question is password or orderedlist\r
+    //\r
+    if (QuestionValue->Buffer == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    Dst = QuestionValue->Buffer;\r
+  } else {\r
+    //\r
+    // Other type of Questions\r
+    //\r
+    if (Question->QuestionReferToBitField) {\r
+      Buffer = (UINT8 *)AllocateZeroPool (Question->StorageWidth);\r
+      if (Buffer == NULL) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      Dst = Buffer;\r
+    } else {\r
+      Dst = (UINT8 *)&QuestionValue->Value;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Temp cut at the end of this section, end with '\0' or '&'.\r
+  //\r
+  StringPtr = Value;\r
+  while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
+    StringPtr++;\r
+  }\r
+\r
+  TempChar   = *StringPtr;\r
+  *StringPtr = L'\0';\r
+\r
+  LengthStr = StrLen (Value);\r
+\r
+  //\r
+  // Value points to a Unicode hexadecimal string, we need to convert the string to the value with CHAR16/UINT8...type.\r
+  // When generating the Value string, we follow this rule: 1 byte -> 2 Unicode characters (for string: 2 byte(CHAR16) ->4 Unicode characters).\r
+  // So the maximum value string length of a question is : Question->StorageWidth * 2.\r
+  // If the value string length > Question->StorageWidth * 2, only set the string length as Question->StorageWidth * 2, then convert.\r
+  //\r
+  if (LengthStr > (UINTN)Question->StorageWidth * 2) {\r
+    Length = (UINTN)Question->StorageWidth * 2;\r
+  } else {\r
+    Length = LengthStr;\r
+  }\r
+\r
+  Status = EFI_SUCCESS;\r
+  if (!IsBufferStorage && IsString) {\r
+    //\r
+    // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
+    // Add string tail char L'\0' into Length\r
+    //\r
+    DstBuf = (CHAR16 *)Dst;\r
+    ZeroMem (TemStr, sizeof (TemStr));\r
+    for (Index = 0; Index < Length; Index += 4) {\r
+      StrnCpyS (TemStr, sizeof (TemStr) / sizeof (CHAR16), Value + Index, 4);\r
+      DstBuf[Index/4] = (CHAR16)StrHexToUint64 (TemStr);\r
+    }\r
+\r
+    //\r
+    // Add tailing L'\0' character\r
+    //\r
+    DstBuf[Index/4] = L'\0';\r
+  } else {\r
+    ZeroMem (TemStr, sizeof (TemStr));\r
+    for (Index = 0; Index < Length; Index++) {\r
+      TemStr[0]  = Value[LengthStr - Index - 1];\r
+      DigitUint8 = (UINT8)StrHexToUint64 (TemStr);\r
+      if ((Index & 1) == 0) {\r
+        Dst[Index/2] = DigitUint8;\r
+      } else {\r
+        Dst[Index/2] = (UINT8)((DigitUint8 << 4) + Dst[Index/2]);\r
+      }\r
+    }\r
+  }\r
+\r
+  *StringPtr = TempChar;\r
+\r
+  if ((Buffer != NULL) && Question->QuestionReferToBitField) {\r
+    GetBitsQuestionValue (Question, Buffer, QuestionValue);\r
+    FreePool (Buffer);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Get the string based on the StringId and HII Package List Handle.\r
+\r
+  @param[in]  Token                  The String's ID.\r
+  @param[in]  HiiHandle              The package list in the HII database to search for\r
+                                 the specified string.\r
+\r
+  @return The output string.\r
+\r
+**/\r
+CHAR16 *\r
+GetTokenString (\r
+  IN EFI_STRING_ID   Token,\r
+  IN EFI_HII_HANDLE  HiiHandle\r
+  )\r
+{\r
+  EFI_STRING  String;\r
+\r
+  if (HiiHandle == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  String = HiiGetString (HiiHandle, Token, NULL);\r
+  if (String == NULL) {\r
+    String = AllocateCopyPool (StrSize (mUnknownString), mUnknownString);\r
+    if (String == NULL) {\r
+      return NULL;\r
+    }\r
+  }\r
+\r
+  return (CHAR16 *)String;\r
+}\r
+\r
+/**\r
+  Converts the unicode character of the string from uppercase to lowercase.\r
+  This is a internal function.\r
+\r
+  @param[in] ConfigString  String to be converted\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+HiiStringToLowercase (\r
+  IN EFI_STRING  ConfigString\r
+  )\r
+{\r
+  EFI_STRING  String;\r
+  BOOLEAN     Lower;\r
+\r
+  //\r
+  // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
+  //\r
+  for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {\r
+    if (*String == L'=') {\r
+      Lower = TRUE;\r
+    } else if (*String == L'&') {\r
+      Lower = FALSE;\r
+    } else if (Lower && (*String >= L'A') && (*String <= L'F')) {\r
+      *String = (CHAR16)(*String - L'A' + L'a');\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  Evaluate if the result is a non-zero value.\r
+\r
+  @param[in]  Result       The result to be evaluated.\r
+\r
+  @retval TRUE             It is a non-zero value.\r
+  @retval FALSE            It is a zero value.\r
+\r
+**/\r
+BOOLEAN\r
+IsHiiValueTrue (\r
+  IN EFI_HII_VALUE  *Result\r
+  )\r
+{\r
+  switch (Result->Type) {\r
+    case EFI_IFR_TYPE_BOOLEAN:\r
+      return Result->Value.b;\r
+\r
+    case EFI_IFR_TYPE_NUM_SIZE_8:\r
+      return (BOOLEAN)(Result->Value.u8 != 0);\r
+\r
+    case EFI_IFR_TYPE_NUM_SIZE_16:\r
+      return (BOOLEAN)(Result->Value.u16 != 0);\r
+\r
+    case EFI_IFR_TYPE_NUM_SIZE_32:\r
+      return (BOOLEAN)(Result->Value.u32 != 0);\r
+\r
+    case EFI_IFR_TYPE_NUM_SIZE_64:\r
+      return (BOOLEAN)(Result->Value.u64 != 0);\r
+\r
+    default:\r
+      return FALSE;\r
+  }\r
+}\r
+\r
+/**\r
+  Set a new string to string package.\r
+\r
+  @param[in]  String              A pointer to the Null-terminated Unicode string\r
+                                  to add or update in the String Package associated\r
+                                  with HiiHandle.\r
+  @param[in]  HiiHandle           A handle that was previously registered in the\r
+                                  HII Database.\r
+\r
+  @return the Id for this new string.\r
+\r
+**/\r
+EFI_STRING_ID\r
+NewHiiString (\r
+  IN CHAR16          *String,\r
+  IN EFI_HII_HANDLE  HiiHandle\r
+  )\r
+{\r
+  EFI_STRING_ID  StringId;\r
+\r
+  StringId = HiiSetString (HiiHandle, 0, String, NULL);\r
+  return StringId;\r
+}\r
+\r
+/**\r
+  Perform nosubmitif check for a Form.\r
+\r
+  @param[in]  FormSet                FormSet data structure.\r
+  @param[in]  Form                   Form data structure.\r
+  @param[in]  Question               The Question to be validated.\r
+\r
+  @retval EFI_SUCCESS            Form validation pass.\r
+  @retval other                  Form validation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+ValidateNoSubmit (\r
+  IN HII_FORMSET    *FormSet,\r
+  IN HII_FORM       *Form,\r
+  IN HII_STATEMENT  *Question\r
+  )\r
+{\r
+  EFI_STATUS      Status;\r
+  LIST_ENTRY      *Link;\r
+  LIST_ENTRY      *ListHead;\r
+  HII_EXPRESSION  *Expression;\r
+\r
+  ListHead = &Question->NoSubmitListHead;\r
+  Link     = GetFirstNode (ListHead);\r
+  while (!IsNull (ListHead, Link)) {\r
+    Expression = HII_EXPRESSION_FROM_LINK (Link);\r
+\r
+    //\r
+    // Evaluate the expression\r
+    //\r
+    Status = EvaluateHiiExpression (FormSet, Form, Expression);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    if (IsHiiValueTrue (&Expression->Result)) {\r
+      return EFI_NOT_READY;\r
+    }\r
+\r
+    Link = GetNextNode (ListHead, Link);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Perform NoSubmit check for each Form in FormSet.\r
+\r
+  @param[in]     FormSet                FormSet data structure.\r
+  @param[in,out] CurrentForm            Current input form data structure.\r
+  @param[out]    Statement              The statement for this check.\r
+\r
+  @retval EFI_SUCCESS            Form validation pass.\r
+  @retval other                  Form validation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+NoSubmitCheck (\r
+  IN     HII_FORMSET  *FormSet,\r
+  IN OUT HII_FORM     **CurrentForm,\r
+  OUT HII_STATEMENT   **Statement\r
+  )\r
+{\r
+  EFI_STATUS     Status;\r
+  LIST_ENTRY     *Link;\r
+  HII_STATEMENT  *Question;\r
+  HII_FORM       *Form;\r
+  LIST_ENTRY     *LinkForm;\r
+\r
+  LinkForm = GetFirstNode (&FormSet->FormListHead);\r
+  while (!IsNull (&FormSet->FormListHead, LinkForm)) {\r
+    Form     = HII_FORM_FROM_LINK (LinkForm);\r
+    LinkForm = GetNextNode (&FormSet->FormListHead, LinkForm);\r
+\r
+    if ((*CurrentForm != NULL) && (*CurrentForm != Form)) {\r
+      continue;\r
+    }\r
+\r
+    Link = GetFirstNode (&Form->StatementListHead);\r
+    while (!IsNull (&Form->StatementListHead, Link)) {\r
+      Question = HII_STATEMENT_FROM_LINK (Link);\r
+      Status   = ValidateNoSubmit (FormSet, Form, Question);\r
+      if (EFI_ERROR (Status)) {\r
+        if (*CurrentForm == NULL) {\r
+          *CurrentForm = Form;\r
+        }\r
+\r
+        if (Statement != NULL) {\r
+          *Statement = Question;\r
+        }\r
+\r
+        return Status;\r
+      }\r
+\r
+      Link = GetNextNode (&Form->StatementListHead, Link);\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Allocate new memory and concatenate Source on the end of Destination.\r
+\r
+  @param  Dest                   String to added to the end of.\r
+  @param  Src                    String to concatenate.\r
+\r
+**/\r
+VOID\r
+NewStringCat (\r
+  IN OUT CHAR16  **Dest,\r
+  IN     CHAR16  *Src\r
+  )\r
+{\r
+  CHAR16  *NewHiiString;\r
+  UINTN   MaxLen;\r
+\r
+  if (*Dest == NULL) {\r
+    NewStringCopy (Dest, Src);\r
+    return;\r
+  }\r
+\r
+  MaxLen       = (StrSize (*Dest) + StrSize (Src) - 2) / sizeof (CHAR16);\r
+  NewHiiString = AllocatePool (MaxLen * sizeof (CHAR16));\r
+  if (NewHiiString == NULL) {\r
+    return;\r
+  }\r
+\r
+  StrCpyS (NewHiiString, MaxLen, *Dest);\r
+  StrCatS (NewHiiString, MaxLen, Src);\r
+\r
+  FreePool (*Dest);\r
+  *Dest = NewHiiString;\r
+}\r
+\r
+/**\r
+  Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.\r
+\r
+  @param[in]  Storage                The Storage to be converted.\r
+  @param[in]  ConfigResp             The returned <ConfigResp>.\r
+  @param[in]  ConfigRequest          The ConfigRequest string.\r
+\r
+  @retval EFI_SUCCESS            Convert success.\r
+  @retval EFI_INVALID_PARAMETER  Incorrect storage type.\r
+\r
+**/\r
+EFI_STATUS\r
+StorageToConfigResp (\r
+  IN HII_FORMSET_STORAGE  *Storage,\r
+  IN CHAR16               **ConfigResp,\r
+  IN CHAR16               *ConfigRequest\r
+  )\r
+{\r
+  EFI_STATUS                       Status;\r
+  EFI_STRING                       Progress;\r
+  LIST_ENTRY                       *Link;\r
+  HII_NAME_VALUE_NODE              *Node;\r
+  UINT8                            *SourceBuf;\r
+  EFI_HII_CONFIG_ROUTING_PROTOCOL  *HiiConfigRouting;\r
+  EFI_STRING                       TempConfigRequest;\r
+  UINTN                            RequestStrSize;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  if (Storage->ConfigHdr == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (ConfigRequest != NULL) {\r
+    TempConfigRequest = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);\r
+    if (TempConfigRequest == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+  } else {\r
+    RequestStrSize    = (StrLen (Storage->ConfigHdr) + StrLen (Storage->ConfigRequest) + 1) * sizeof (CHAR16);\r
+    TempConfigRequest = AllocatePool (RequestStrSize);\r
+    if (TempConfigRequest == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    UnicodeSPrint (\r
+      TempConfigRequest,\r
+      RequestStrSize,\r
+      L"%s%s",\r
+      Storage->ConfigHdr,\r
+      Storage->ConfigRequest\r
+      );\r
+  }\r
+\r
+  switch (Storage->Type) {\r
+    case EFI_HII_VARSTORE_BUFFER:\r
+    case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
+\r
+      Status = gBS->LocateProtocol (\r
+                      &gEfiHiiConfigRoutingProtocolGuid,\r
+                      NULL,\r
+                      (VOID **)&HiiConfigRouting\r
+                      );\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      SourceBuf = Storage->Buffer;\r
+      Status    = HiiConfigRouting->BlockToConfig (\r
+                                      HiiConfigRouting,\r
+                                      TempConfigRequest,\r
+                                      SourceBuf,\r
+                                      Storage->Size,\r
+                                      ConfigResp,\r
+                                      &Progress\r
+                                      );\r
+      break;\r
+\r
+    case EFI_HII_VARSTORE_NAME_VALUE:\r
+\r
+      *ConfigResp = NULL;\r
+      NewStringCat (ConfigResp, Storage->ConfigHdr);\r
+\r
+      Link = GetFirstNode (&Storage->NameValueList);\r
+      while (!IsNull (&Storage->NameValueList, Link)) {\r
+        Node = HII_NAME_VALUE_NODE_FROM_LINK (Link);\r
+\r
+        if (StrStr (TempConfigRequest, Node->Name) != NULL) {\r
+          NewStringCat (ConfigResp, L"&");\r
+          NewStringCat (ConfigResp, Node->Name);\r
+          NewStringCat (ConfigResp, L"=");\r
+          NewStringCat (ConfigResp, Node->Value);\r
+        }\r
+\r
+        Link = GetNextNode (&Storage->NameValueList, Link);\r
+      }\r
+\r
+      break;\r
+\r
+    case EFI_HII_VARSTORE_EFI_VARIABLE:\r
+    default:\r
+      Status = EFI_INVALID_PARAMETER;\r
+      break;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.\r
+\r
+  @param[in]  Storage                The Storage to receive the settings.\r
+  @param[in]  ConfigResp             The <ConfigResp> to be converted.\r
+\r
+  @retval EFI_SUCCESS            Convert success.\r
+  @retval EFI_INVALID_PARAMETER  Incorrect storage type.\r
+\r
+**/\r
+EFI_STATUS\r
+ConfigRespToStorage (\r
+  IN HII_FORMSET_STORAGE  *Storage,\r
+  IN CHAR16               *ConfigResp\r
+  )\r
+{\r
+  EFI_STATUS                       Status;\r
+  EFI_STRING                       Progress;\r
+  UINTN                            BufferSize;\r
+  CHAR16                           *StrPtr;\r
+  CHAR16                           *Name;\r
+  CHAR16                           *Value;\r
+  EFI_HII_CONFIG_ROUTING_PROTOCOL  *HiiConfigRouting;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  switch (Storage->Type) {\r
+    case EFI_HII_VARSTORE_BUFFER:\r
+    case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
+\r
+      Status = gBS->LocateProtocol (\r
+                      &gEfiHiiConfigRoutingProtocolGuid,\r
+                      NULL,\r
+                      (VOID **)&HiiConfigRouting\r
+                      );\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      BufferSize = Storage->Size;\r
+      Status     = HiiConfigRouting->ConfigToBlock (\r
+                                       HiiConfigRouting,\r
+                                       ConfigResp,\r
+                                       Storage->Buffer,\r
+                                       &BufferSize,\r
+                                       &Progress\r
+                                       );\r
+      break;\r
+\r
+    case EFI_HII_VARSTORE_NAME_VALUE:\r
+      StrPtr = StrStr (ConfigResp, L"PATH");\r
+      if (StrPtr == NULL) {\r
+        break;\r
+      }\r
+\r
+      StrPtr = StrStr (ConfigResp, L"&");\r
+      while (StrPtr != NULL) {\r
+        //\r
+        // Skip '&'\r
+        //\r
+        StrPtr = StrPtr + 1;\r
+        Name   = StrPtr;\r
+        StrPtr = StrStr (StrPtr, L"=");\r
+        if (StrPtr == NULL) {\r
+          break;\r
+        }\r
+\r
+        *StrPtr = 0;\r
+\r
+        //\r
+        // Skip '='\r
+        //\r
+        StrPtr = StrPtr + 1;\r
+        Value  = StrPtr;\r
+        StrPtr = StrStr (StrPtr, L"&");\r
+        if (StrPtr != NULL) {\r
+          *StrPtr = 0;\r
+        }\r
+\r
+        SetValueByName (Storage, Name, Value, NULL);\r
+      }\r
+\r
+      break;\r
+\r
+    case EFI_HII_VARSTORE_EFI_VARIABLE:\r
+    default:\r
+      Status = EFI_INVALID_PARAMETER;\r
+      break;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Fetch the Ifr binary data of a FormSet.\r
+\r
+  @param[in]  Handle             PackageList Handle\r
+  @param[in,out]  FormSetGuid    On input, GUID or class GUID of a formset. If not\r
+                                 specified (NULL or zero GUID), take the first\r
+                                 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
+                                 found in package list.\r
+                                 On output, GUID of the formset found(if not NULL).\r
+  @param[out]  BinaryLength      The length of the FormSet IFR binary.\r
+  @param[out]  BinaryData        The buffer designed to receive the FormSet.\r
+\r
+  @retval EFI_SUCCESS            Buffer filled with the requested FormSet.\r
+                                 BufferLength was updated.\r
+  @retval EFI_INVALID_PARAMETER  The handle is unknown.\r
+  @retval EFI_NOT_FOUND          A form or FormSet on the requested handle cannot\r
+                                 be found with the requested FormId.\r
+\r
+**/\r
+EFI_STATUS\r
+GetIfrBinaryData (\r
+  IN     EFI_HII_HANDLE  Handle,\r
+  IN OUT EFI_GUID        *FormSetGuid,\r
+  OUT UINTN              *BinaryLength,\r
+  OUT UINT8              **BinaryData\r
+  )\r
+{\r
+  EFI_STATUS                   Status;\r
+  EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;\r
+  UINTN                        BufferSize;\r
+  UINT8                        *Package;\r
+  UINT8                        *OpCodeData;\r
+  UINT32                       Offset;\r
+  UINT32                       Offset2;\r
+  UINT32                       PackageListLength;\r
+  EFI_HII_PACKAGE_HEADER       PackageHeader;\r
+  UINT8                        Index;\r
+  UINT8                        NumberOfClassGuid;\r
+  BOOLEAN                      ClassGuidMatch;\r
+  EFI_GUID                     *ClassGuid;\r
+  EFI_GUID                     *ComparingGuid;\r
+  EFI_HII_DATABASE_PROTOCOL    *HiiDatabase;\r
+\r
+  OpCodeData = NULL;\r
+  Package    = NULL;\r
+  ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
+\r
+  //\r
+  // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list\r
+  //\r
+  if (FormSetGuid == NULL) {\r
+    ComparingGuid = &gZeroGuid;\r
+  } else {\r
+    ComparingGuid = FormSetGuid;\r
+  }\r
+\r
+  //\r
+  // Get HII PackageList\r
+  //\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiHiiDatabaseProtocolGuid,\r
+                  NULL,\r
+                  (VOID **)&HiiDatabase\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    *BinaryData = NULL;\r
+    return Status;\r
+  }\r
+\r
+  BufferSize     = 0;\r
+  HiiPackageList = NULL;\r
+  Status         = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList);\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    HiiPackageList = AllocatePool (BufferSize);\r
+    if (HiiPackageList == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList);\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    if (HiiPackageList != NULL) {\r
+      FreePool (HiiPackageList);\r
+    }\r
+\r
+    *BinaryData = NULL;\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Get Form package from this HII package List\r
+  //\r
+  Offset  = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+  Offset2 = 0;\r
+  CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
+\r
+  ClassGuidMatch = FALSE;\r
+  while (Offset < PackageListLength) {\r
+    Package = ((UINT8 *)HiiPackageList) + Offset;\r
+    CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
+\r
+    if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
+      //\r
+      // Search FormSet in this Form Package\r
+      //\r
+\r
+      Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
+      while (Offset2 < PackageHeader.Length) {\r
+        OpCodeData = Package + Offset2;\r
+\r
+        if (((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
+          //\r
+          // Try to compare against formset GUID\r
+          //\r
+\r
+          if (IsZeroGuid (FormSetGuid) ||\r
+              CompareGuid (ComparingGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER))))\r
+          {\r
+            break;\r
+          }\r
+\r
+          if (((EFI_IFR_OP_HEADER *)OpCodeData)->Length > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) {\r
+            //\r
+            // Try to compare against formset class GUID\r
+            //\r
+            NumberOfClassGuid = (UINT8)(((EFI_IFR_FORM_SET *)OpCodeData)->Flags & 0x3);\r
+            ClassGuid         = (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_FORM_SET));\r
+            for (Index = 0; Index < NumberOfClassGuid; Index++) {\r
+              if (CompareGuid (ComparingGuid, ClassGuid + Index)) {\r
+                ClassGuidMatch = TRUE;\r
+                break;\r
+              }\r
+            }\r
+\r
+            if (ClassGuidMatch) {\r
+              break;\r
+            }\r
+          } else if (ComparingGuid == &gEfiHiiPlatformSetupFormsetGuid) {\r
+            ClassGuidMatch = TRUE;\r
+            break;\r
+          }\r
+        }\r
+\r
+        Offset2 += ((EFI_IFR_OP_HEADER *)OpCodeData)->Length;\r
+      }\r
+\r
+      if (Offset2 < PackageHeader.Length) {\r
+        //\r
+        // Target formset found\r
+        //\r
+        break;\r
+      }\r
+    }\r
+\r
+    Offset += PackageHeader.Length;\r
+  }\r
+\r
+  if (Offset >= PackageListLength) {\r
+    //\r
+    // Form package not found in this Package List\r
+    //\r
+    FreePool (HiiPackageList);\r
+    *BinaryData = NULL;\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  if (FormSetGuid != NULL) {\r
+    //\r
+    // Return the FormSet GUID\r
+    //\r
+    CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *)OpCodeData)->Guid, sizeof (EFI_GUID));\r
+  }\r
+\r
+  //\r
+  // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes\r
+  // in this FormSet; So, here just simply copy the data from start of a FormSet to the end\r
+  // of the Form Package.\r
+  //\r
+\r
+  *BinaryLength = PackageHeader.Length - Offset2;\r
+  *BinaryData   = AllocateCopyPool (*BinaryLength, OpCodeData);\r
+  FreePool (HiiPackageList);\r
+  if (*BinaryData == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Check if the requested element is in storage.\r
+\r
+  @param  Storage                   The storage contains elements.\r
+  @param  RequestElement            The element to be searched.\r
+\r
+**/\r
+BOOLEAN\r
+ElementValidation (\r
+  IN HII_FORMSET_STORAGE  *Storage,\r
+  IN CHAR16               *RequestElement\r
+  )\r
+{\r
+  return StrStr (Storage->ConfigRequest, RequestElement) != NULL ? TRUE : FALSE;\r
+}\r
+\r
+/**\r
+  Append the Request element to the Config Request.\r
+\r
+  @param  ConfigRequest          Current ConfigRequest info.\r
+  @param  SpareStrLen            Current remain free buffer for config request.\r
+  @param  RequestElement         New Request element.\r
+\r
+**/\r
+VOID\r
+AppendConfigRequest (\r
+  IN OUT CHAR16  **ConfigRequest,\r
+  IN OUT UINTN   *SpareStrLen,\r
+  IN     CHAR16  *RequestElement\r
+  )\r
+{\r
+  CHAR16  *NewStr;\r
+  UINTN   StringSize;\r
+  UINTN   StrLength;\r
+  UINTN   MaxLen;\r
+\r
+  StrLength  = StrLen (RequestElement);\r
+  StringSize = (*ConfigRequest != NULL) ? StrSize (*ConfigRequest) : sizeof (CHAR16);\r
+  MaxLen     = StringSize / sizeof (CHAR16) + *SpareStrLen;\r
+\r
+  //\r
+  // Append <RequestElement> to <ConfigRequest>\r
+  //\r
+  if (StrLength > *SpareStrLen) {\r
+    //\r
+    // Old String buffer is not sufficient for RequestElement, allocate a new one\r
+    //\r
+    MaxLen = StringSize / sizeof (CHAR16) + CONFIG_REQUEST_STRING_INCREMENTAL;\r
+    NewStr = AllocatePool (MaxLen * sizeof (CHAR16));\r
+    if (NewStr == NULL) {\r
+      return;\r
+    }\r
+\r
+    if (*ConfigRequest != NULL) {\r
+      CopyMem (NewStr, *ConfigRequest, StringSize);\r
+      FreePool (*ConfigRequest);\r
+    } else {\r
+      NewStr[0] = L'\0';\r
+    }\r
+\r
+    *ConfigRequest = NewStr;\r
+    *SpareStrLen   = CONFIG_REQUEST_STRING_INCREMENTAL;\r
+  }\r
+\r
+  StrCatS (*ConfigRequest, MaxLen, RequestElement);\r
+  *SpareStrLen -= StrLength;\r
+}\r
+\r
+/**\r
+  Adjust the config request info, remove the request elements which already in AllConfigRequest string.\r
+\r
+  @param  Storage                Form set Storage.\r
+  @param  Request                The input request string.\r
+  @param  RespString             Whether the input is ConfigRequest or ConfigResp format.\r
+\r
+  @retval TRUE                   Has element not covered by current used elements, need to continue to call ExtractConfig\r
+  @retval FALSE                  All elements covered by current used elements.\r
+\r
+**/\r
+BOOLEAN\r
+ConfigRequestAdjust (\r
+  IN HII_FORMSET_STORAGE  *Storage,\r
+  IN CHAR16               *Request,\r
+  IN BOOLEAN              RespString\r
+  )\r
+{\r
+  CHAR16   *RequestElement;\r
+  CHAR16   *NextRequestElement;\r
+  CHAR16   *NextElementBackup;\r
+  CHAR16   *SearchKey;\r
+  CHAR16   *ValueKey;\r
+  BOOLEAN  RetVal;\r
+  CHAR16   *ConfigRequest;\r
+\r
+  RetVal            = FALSE;\r
+  NextElementBackup = NULL;\r
+  ValueKey          = NULL;\r
+\r
+  if (Request != NULL) {\r
+    ConfigRequest = Request;\r
+  } else {\r
+    ConfigRequest = Storage->ConfigRequest;\r
+  }\r
+\r
+  if (Storage->ConfigRequest == NULL) {\r
+    Storage->ConfigRequest = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);\r
+    if (Storage->ConfigRequest == NULL) {\r
+      return FALSE;\r
+    }\r
+\r
+    return TRUE;\r
+  }\r
+\r
+  if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+    //\r
+    // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage\r
+    //\r
+    SearchKey = L"&";\r
+  } else {\r
+    //\r
+    // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage\r
+    //\r
+    SearchKey = L"&OFFSET";\r
+    ValueKey  = L"&VALUE";\r
+  }\r
+\r
+  //\r
+  // Find SearchKey storage\r
+  //\r
+  if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+    RequestElement = StrStr (ConfigRequest, L"PATH");\r
+    if (RequestElement == NULL) {\r
+      return FALSE;\r
+    }\r
+\r
+    RequestElement = StrStr (RequestElement, SearchKey);\r
+  } else {\r
+    RequestElement = StrStr (ConfigRequest, SearchKey);\r
+  }\r
+\r
+  while (RequestElement != NULL) {\r
+    //\r
+    // +1 to avoid find header itself.\r
+    //\r
+    NextRequestElement = StrStr (RequestElement + 1, SearchKey);\r
+\r
+    //\r
+    // The last Request element in configRequest string.\r
+    //\r
+    if (NextRequestElement != NULL) {\r
+      if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
+        NextElementBackup  = NextRequestElement;\r
+        NextRequestElement = StrStr (RequestElement, ValueKey);\r
+        if (NextRequestElement == NULL) {\r
+          return FALSE;\r
+        }\r
+      }\r
+\r
+      //\r
+      // Replace "&" with '\0'.\r
+      //\r
+      *NextRequestElement = L'\0';\r
+    } else {\r
+      if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
+        NextElementBackup  = NextRequestElement;\r
+        NextRequestElement = StrStr (RequestElement, ValueKey);\r
+        if (NextRequestElement == NULL) {\r
+          return FALSE;\r
+        }\r
+\r
+        //\r
+        // Replace "&" with '\0'.\r
+        //\r
+        *NextRequestElement = L'\0';\r
+      }\r
+    }\r
+\r
+    if (!ElementValidation (Storage, RequestElement)) {\r
+      //\r
+      // Add this element to the Storage->BrowserStorage->AllRequestElement.\r
+      //\r
+      AppendConfigRequest (&Storage->ConfigRequest, &Storage->SpareStrLen, RequestElement);\r
+      RetVal = TRUE;\r
+    }\r
+\r
+    if (NextRequestElement != NULL) {\r
+      //\r
+      // Restore '&' with '\0' for later used.\r
+      //\r
+      *NextRequestElement = L'&';\r
+    }\r
+\r
+    if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
+      RequestElement = NextElementBackup;\r
+    } else {\r
+      RequestElement = NextRequestElement;\r
+    }\r
+  }\r
+\r
+  return RetVal;\r
+}\r
+\r
+/**\r
+  Fill storage with settings requested from Configuration Driver.\r
+\r
+  @param[in] FormSet                FormSet data structure.\r
+  @param[in] Storage                Buffer Storage.\r
+\r
+**/\r
+VOID\r
+LoadFormSetStorage (\r
+  IN HII_FORMSET          *FormSet,\r
+  IN HII_FORMSET_STORAGE  *Storage\r
+  )\r
+{\r
+  EFI_STATUS                       Status;\r
+  EFI_STRING                       Progress;\r
+  EFI_STRING                       Result;\r
+  CHAR16                           *StrPtr;\r
+  EFI_STRING                       ConfigRequest;\r
+  UINTN                            RequestStrSize;\r
+  EFI_HII_CONFIG_ROUTING_PROTOCOL  *HiiConfigRouting;\r
+\r
+  ConfigRequest = NULL;\r
+\r
+  switch (Storage->Type) {\r
+    case EFI_HII_VARSTORE_EFI_VARIABLE:\r
+      return;\r
+\r
+    case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
+ #if 0 // bug fix for efivarstore\r
+      if (Storage->ConfigRequest != NULL) {\r
+        ConfigRequestAdjust (Storage, Storage->ConfigRequest, FALSE);\r
+        return;\r
+      }\r
+\r
+ #endif\r
+      break;\r
+\r
+    case EFI_HII_VARSTORE_BUFFER:\r
+    case EFI_HII_VARSTORE_NAME_VALUE:\r
+      //\r
+      // Skip if there is no RequestElement.\r
+      //\r
+      if (Storage->ElementCount == 0) {\r
+        return;\r
+      }\r
+\r
+      break;\r
+\r
+    default:\r
+      return;\r
+  }\r
+\r
+  if (Storage->Type != EFI_HII_VARSTORE_NAME_VALUE) {\r
+    //\r
+    // Create the config request string to get all fields for this storage.\r
+    // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
+    // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator\r
+    //\r
+    RequestStrSize = StrSize (Storage->ConfigHdr) + 20 * sizeof (CHAR16);\r
+    ConfigRequest  = AllocatePool (RequestStrSize);\r
+    if (ConfigRequest == NULL) {\r
+      return;\r
+    }\r
+\r
+    UnicodeSPrint (\r
+      ConfigRequest,\r
+      RequestStrSize,\r
+      L"%s&OFFSET=0&WIDTH=%04x",\r
+      Storage->ConfigHdr,\r
+      Storage->Size\r
+      );\r
+  } else {\r
+    RequestStrSize = (StrLen (Storage->ConfigHdr) + StrLen (Storage->ConfigRequest) + 1) * sizeof (CHAR16);\r
+    ConfigRequest  = AllocatePool (RequestStrSize);\r
+    if (ConfigRequest == NULL) {\r
+      return;\r
+    }\r
+\r
+    UnicodeSPrint (\r
+      ConfigRequest,\r
+      RequestStrSize,\r
+      L"%s%s",\r
+      Storage->ConfigHdr,\r
+      Storage->ConfigRequest\r
+      );\r
+  }\r
+\r
+  //\r
+  // Request current settings from Configuration Driver\r
+  //\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiHiiConfigRoutingProtocolGuid,\r
+                  NULL,\r
+                  (VOID **)&HiiConfigRouting\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return;\r
+  }\r
+\r
+  Status = HiiConfigRouting->ExtractConfig (\r
+                               HiiConfigRouting,\r
+                               ConfigRequest,\r
+                               &Progress,\r
+                               &Result\r
+                               );\r
+  if (!EFI_ERROR (Status)) {\r
+    //\r
+    // Convert Result from <ConfigAltResp> to <ConfigResp>\r
+    //\r
+    StrPtr = StrStr (Result, L"&GUID=");\r
+    if (StrPtr != NULL) {\r
+      *StrPtr = L'\0';\r
+    }\r
+\r
+    Status = ConfigRespToStorage (Storage, Result);\r
+    FreePool (Result);\r
+  }\r
+\r
+  Storage->ConfigRequest = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);\r
+  if (Storage->ConfigRequest == NULL) {\r
+    if (ConfigRequest != NULL) {\r
+      FreePool (ConfigRequest);\r
+    }\r
+\r
+    return;\r
+  }\r
+\r
+  if (Storage->Type != EFI_HII_VARSTORE_NAME_VALUE) {\r
+    if (ConfigRequest != NULL) {\r
+      FreePool (ConfigRequest);\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  Zero extend integer/boolean/date/time to UINT64 for comparing.\r
+\r
+  @param[in]  Value                  HII Value to be converted.\r
+\r
+**/\r
+VOID\r
+ExtendValueToU64 (\r
+  IN HII_STATEMENT_VALUE  *Value\r
+  )\r
+{\r
+  UINT64  Temp;\r
+\r
+  Temp = 0;\r
+  switch (Value->Type) {\r
+    case EFI_IFR_TYPE_NUM_SIZE_8:\r
+      Temp = Value->Value.u8;\r
+      break;\r
+\r
+    case EFI_IFR_TYPE_NUM_SIZE_16:\r
+      Temp = Value->Value.u16;\r
+      break;\r
+\r
+    case EFI_IFR_TYPE_NUM_SIZE_32:\r
+      Temp = Value->Value.u32;\r
+      break;\r
+\r
+    case EFI_IFR_TYPE_BOOLEAN:\r
+      Temp = Value->Value.b;\r
+      break;\r
+\r
+    case EFI_IFR_TYPE_TIME:\r
+      Temp = Value->Value.u32 & 0xffffff;\r
+      break;\r
+\r
+    case EFI_IFR_TYPE_DATE:\r
+      Temp = Value->Value.u32;\r
+      break;\r
+\r
+    default:\r
+      return;\r
+  }\r
+\r
+  Value->Value.u64 = Temp;\r
+}\r
+\r
+/**\r
+  Pop an element from the stack.\r
+\r
+  @param  Stack                  On input: old stack\r
+  @param  StackPtr               On input: old stack pointer; On output: new stack pointer\r
+  @param  Data                   Data to pop.\r
+\r
+  @retval EFI_SUCCESS            The value was popped onto the stack.\r
+  @retval EFI_ACCESS_DENIED      The pop operation underflowed the stack\r
+\r
+**/\r
+EFI_STATUS\r
+PopStack (\r
+  IN     EFI_HII_VALUE  *Stack,\r
+  IN OUT EFI_HII_VALUE  **StackPtr,\r
+  OUT EFI_HII_VALUE     *Data\r
+  );\r
+\r
+/**\r
+  Push an element onto the Boolean Stack.\r
+\r
+  @param  Stack                  On input: old stack; On output: new stack\r
+  @param  StackPtr               On input: old stack pointer; On output: new stack\r
+                                 pointer\r
+  @param  StackEnd               On input: old stack end; On output: new stack end\r
+  @param  Data                   Data to push.\r
+\r
+  @retval EFI_SUCCESS            Push stack success.\r
+\r
+**/\r
+EFI_STATUS\r
+PushStack (\r
+  IN OUT EFI_HII_VALUE  **Stack,\r
+  IN OUT EFI_HII_VALUE  **StackPtr,\r
+  IN OUT EFI_HII_VALUE  **StackEnd,\r
+  IN     EFI_HII_VALUE  *Data\r
+  );\r
+\r
+/**\r
+  Initialize the internal data structure of a FormSet.\r
+\r
+  @param[in]      Handle         PackageList Handle\r
+  @param[in,out]  FormSetGuid    On input, GUID or class GUID of a formset. If not\r
+                                 specified (NULL or zero GUID), take the first\r
+                                 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
+                                 found in package list.\r
+                                 On output, GUID of the formset found(if not NULL).\r
+  @param[out]     FormSet        FormSet data structure.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+  @retval EFI_NOT_FOUND          The specified FormSet could not be found.\r
+\r
+**/\r
+EFI_STATUS\r
+CreateFormSetFromHiiHandle (\r
+  IN     EFI_HII_HANDLE  Handle,\r
+  IN OUT EFI_GUID        *FormSetGuid,\r
+  OUT HII_FORMSET        *FormSet\r
+  );\r
+\r
+/**\r
+  Initialize a Formset and get current setting for Questions.\r
+\r
+  @param[in,out]  FormSet                FormSet data structure.\r
+\r
+**/\r
+VOID\r
+InitializeFormSet (\r
+  IN OUT HII_FORMSET  *FormSet\r
+  );\r
+\r
+/**\r
+  Get Value for given Name from a NameValue Storage.\r
+\r
+  @param[in]      Storage        The NameValue Storage.\r
+  @param[in]      Name           The Name.\r
+  @param[in,out]  Value          The returned Value.\r
+\r
+  @retval EFI_SUCCESS            Value found for given Name.\r
+  @retval EFI_NOT_FOUND          No such Name found in NameValue storage.\r
+  @retval EFI_INVALID_PARAMETER  Storage or Value is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+GetValueByName (\r
+  IN HII_FORMSET_STORAGE  *Storage,\r
+  IN CHAR16               *Name,\r
+  IN OUT CHAR16           **Value\r
+  )\r
+{\r
+  LIST_ENTRY           *Link;\r
+  HII_NAME_VALUE_NODE  *Node;\r
+\r
+  if ((Storage == NULL) || (Value == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  *Value = NULL;\r
+\r
+  Link = GetFirstNode (&Storage->NameValueList);\r
+  while (!IsNull (&Storage->NameValueList, Link)) {\r
+    Node = HII_NAME_VALUE_NODE_FROM_LINK (Link);\r
+\r
+    if (StrCmp (Name, Node->Name) == 0) {\r
+      NewStringCopy (Value, Node->Value);\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    Link = GetNextNode (&Storage->NameValueList, Link);\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+  Get Question's current Value.\r
+\r
+  @param[in]      FormSet        FormSet data structure.\r
+  @param[in]      Form           Form data structure.\r
+  @param[in,out]  Question       Question to be initialized.\r
+  @param[in]      GetValueFrom   Where to get value, may from editbuffer, buffer or hii driver.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+  @retval EFI_INVALID_PARAMETER  Formset, Form or Question is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+GetQuestionValue (\r
+  IN HII_FORMSET                  *FormSet,\r
+  IN HII_FORM                     *Form,\r
+  IN OUT HII_STATEMENT            *Question,\r
+  IN GET_SET_QUESTION_VALUE_WITH  GetValueFrom\r
+  )\r
+{\r
+  EFI_STATUS                       Status;\r
+  BOOLEAN                          Enabled;\r
+  BOOLEAN                          Pending;\r
+  UINT8                            *Dst;\r
+  UINTN                            StorageWidth;\r
+  EFI_TIME                         EfiTime;\r
+  HII_FORMSET_STORAGE              *Storage;\r
+  HII_FORMSET_STORAGE              *FormsetStorage;\r
+  EFI_IFR_TYPE_VALUE               *QuestionValue;\r
+  CHAR16                           *ConfigRequest;\r
+  CHAR16                           *Progress;\r
+  CHAR16                           *Result;\r
+  CHAR16                           *Value;\r
+  UINTN                            Length;\r
+  BOOLEAN                          IsBufferStorage;\r
+  UINTN                            MaxLen;\r
+  EFI_HII_CONFIG_ROUTING_PROTOCOL  *HiiConfigRouting;\r
+\r
+  if ((FormSet == NULL) || (Form == NULL) || (Question == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = EFI_SUCCESS;\r
+  Value  = NULL;\r
+  Result = NULL;\r
+\r
+  if (GetValueFrom >= GetSetValueWithMax) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Question value is provided by an Expression, evaluate it\r
+  //\r
+  if (Question->ValueExpression != NULL) {\r
+    Status = EvaluateHiiExpression (FormSet, Form, Question->ValueExpression);\r
+    if (!EFI_ERROR (Status)) {\r
+      if (Question->ValueExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {\r
+        ASSERT (Question->Value.Type == EFI_IFR_TYPE_BUFFER && Question->Value.Buffer != NULL);\r
+        if (Question->StorageWidth > Question->ValueExpression->Result.BufferLen) {\r
+          CopyMem (Question->Value.Buffer, Question->ValueExpression->Result.Buffer, Question->ValueExpression->Result.BufferLen);\r
+          Question->Value.BufferLen = Question->ValueExpression->Result.BufferLen;\r
+        } else {\r
+          CopyMem (Question->Value.Buffer, Question->ValueExpression->Result.Buffer, Question->StorageWidth);\r
+          Question->Value.BufferLen = Question->StorageWidth;\r
+        }\r
+\r
+        FreePool (Question->ValueExpression->Result.Buffer);\r
+      }\r
+\r
+      Question->Value.Type = Question->ValueExpression->Result.Type;\r
+      CopyMem (&Question->Value.Value, &Question->ValueExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE));\r
+    }\r
+\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Get question value by read expression.\r
+  //\r
+  if ((Question->ReadExpression != NULL) && (Form->FormType == STANDARD_MAP_FORM_TYPE)) {\r
+    Status = EvaluateHiiExpression (FormSet, Form, Question->ReadExpression);\r
+    if (!EFI_ERROR (Status) &&\r
+        ((Question->ReadExpression->Result.Type < EFI_IFR_TYPE_OTHER) || (Question->ReadExpression->Result.Type == EFI_IFR_TYPE_BUFFER)))\r
+    {\r
+      //\r
+      // Only update question value to the valid result.\r
+      //\r
+      if (Question->ReadExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {\r
+        ASSERT (Question->Value.Type == EFI_IFR_TYPE_BUFFER && Question->Value.Buffer != NULL);\r
+        if (Question->StorageWidth > Question->ReadExpression->Result.BufferLen) {\r
+          CopyMem (Question->Value.Buffer, Question->ReadExpression->Result.Buffer, Question->ReadExpression->Result.BufferLen);\r
+          Question->Value.BufferLen = Question->ReadExpression->Result.BufferLen;\r
+        } else {\r
+          CopyMem (Question->Value.Buffer, Question->ReadExpression->Result.Buffer, Question->StorageWidth);\r
+          Question->Value.BufferLen = Question->StorageWidth;\r
+        }\r
+\r
+        FreePool (Question->ReadExpression->Result.Buffer);\r
+      }\r
+\r
+      Question->Value.Type = Question->ReadExpression->Result.Type;\r
+      CopyMem (&Question->Value.Value, &Question->ReadExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE));\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Question value is provided by RTC\r
+  //\r
+  Storage       = Question->Storage;\r
+  QuestionValue = &Question->Value.Value;\r
+  if (Storage == NULL) {\r
+    //\r
+    // It's a Question without storage, or RTC date/time\r
+    //\r
+    if ((Question->Operand == EFI_IFR_DATE_OP) || (Question->Operand == EFI_IFR_TIME_OP)) {\r
+      //\r
+      // Date and time define the same Flags bit\r
+      //\r
+      switch (Question->ExtraData.Flags & EFI_QF_DATE_STORAGE) {\r
+        case QF_DATE_STORAGE_TIME:\r
+          Status = gRT->GetTime (&EfiTime, NULL);\r
+          break;\r
+\r
+        case QF_DATE_STORAGE_WAKEUP:\r
+          Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
+          break;\r
+\r
+        case QF_DATE_STORAGE_NORMAL:\r
+        default:\r
+          //\r
+          // For date/time without storage\r
+          //\r
+          return EFI_SUCCESS;\r
+      }\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        if (Question->Operand == EFI_IFR_DATE_OP) {\r
+          QuestionValue->date.Year  = 0xff;\r
+          QuestionValue->date.Month = 0xff;\r
+          QuestionValue->date.Day   = 0xff;\r
+        } else {\r
+          QuestionValue->time.Hour   = 0xff;\r
+          QuestionValue->time.Minute = 0xff;\r
+          QuestionValue->time.Second = 0xff;\r
+        }\r
+\r
+        return EFI_SUCCESS;\r
+      }\r
+\r
+      if (Question->Operand == EFI_IFR_DATE_OP) {\r
+        QuestionValue->date.Year  = EfiTime.Year;\r
+        QuestionValue->date.Month = EfiTime.Month;\r
+        QuestionValue->date.Day   = EfiTime.Day;\r
+      } else {\r
+        QuestionValue->time.Hour   = EfiTime.Hour;\r
+        QuestionValue->time.Minute = EfiTime.Minute;\r
+        QuestionValue->time.Second = EfiTime.Second;\r
+      }\r
+    }\r
+\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Question value is provided by EFI variable\r
+  //\r
+  StorageWidth = Question->StorageWidth;\r
+  if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+    if (Question->Value.Buffer != NULL) {\r
+      Dst = Question->Value.Buffer;\r
+    } else {\r
+      Dst = (UINT8 *)QuestionValue;\r
+    }\r
+\r
+    Status = gRT->GetVariable (\r
+                    Question->VariableName,\r
+                    &Storage->Guid,\r
+                    NULL,\r
+                    &StorageWidth,\r
+                    Dst\r
+                    );\r
+    //\r
+    // Always return success, even this EFI variable doesn't exist\r
+    //\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Question Value is provided by Buffer Storage or NameValue Storage\r
+  //\r
+  if (Question->Value.Buffer != NULL) {\r
+    //\r
+    // This Question is password or orderedlist\r
+    //\r
+    Dst = Question->Value.Buffer;\r
+  } else {\r
+    //\r
+    // Other type of Questions\r
+    //\r
+    Dst = (UINT8 *)&Question->Value.Value;\r
+  }\r
+\r
+  if ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ||\r
+      (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER))\r
+  {\r
+    IsBufferStorage = TRUE;\r
+  } else {\r
+    IsBufferStorage = FALSE;\r
+  }\r
+\r
+  if (GetValueFrom == GetSetValueWithBuffer ) {\r
+    if (IsBufferStorage) {\r
+      //\r
+      // Copy from storage Edit buffer\r
+      // If the Question refer to bit filed, get the value in the related bit filed.\r
+      //\r
+      if (Question->QuestionReferToBitField) {\r
+        GetBitsQuestionValue (Question, Storage->Buffer + Question->VarStoreInfo.VarOffset, &Question->Value);\r
+      } else {\r
+        CopyMem (Dst, Storage->Buffer + Question->VarStoreInfo.VarOffset, StorageWidth);\r
+      }\r
+    } else {\r
+      Value  = NULL;\r
+      Status = GetValueByName (Storage, Question->VariableName, &Value);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      ASSERT (Value != NULL);\r
+      Status = BufferToQuestionValue (Question, Value, &Question->Value);\r
+      FreePool (Value);\r
+    }\r
+  } else {\r
+    FormsetStorage = GetFstStgFromVarId (FormSet, Question->VarStoreId);\r
+    ASSERT (FormsetStorage != NULL);\r
+    //\r
+    // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||\r
+    //                   <ConfigHdr> + "&" + <VariableName>\r
+    //\r
+    if (IsBufferStorage) {\r
+      Length  = StrLen (FormsetStorage->ConfigHdr);\r
+      Length += StrLen (Question->BlockName);\r
+    } else {\r
+      Length  = StrLen (FormsetStorage->ConfigHdr);\r
+      Length += StrLen (Question->VariableName) + 1;\r
+    }\r
+\r
+    // Allocate buffer include '\0'\r
+    MaxLen        = Length + 1;\r
+    ConfigRequest = AllocatePool (MaxLen * sizeof (CHAR16));\r
+    ASSERT (ConfigRequest != NULL);\r
+\r
+    StrCpyS (ConfigRequest, MaxLen, FormsetStorage->ConfigHdr);\r
+    if (IsBufferStorage) {\r
+      StrCatS (ConfigRequest, MaxLen, Question->BlockName);\r
+    } else {\r
+      StrCatS (ConfigRequest, MaxLen, L"&");\r
+      StrCatS (ConfigRequest, MaxLen, Question->VariableName);\r
+    }\r
+\r
+    Status = gBS->LocateProtocol (\r
+                    &gEfiHiiConfigRoutingProtocolGuid,\r
+                    NULL,\r
+                    (VOID **)&HiiConfigRouting\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Request current settings from Configuration Driver\r
+    //\r
+    Status = HiiConfigRouting->ExtractConfig (\r
+                                 HiiConfigRouting,\r
+                                 ConfigRequest,\r
+                                 &Progress,\r
+                                 &Result\r
+                                 );\r
+    FreePool (ConfigRequest);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Skip <ConfigRequest>\r
+    //\r
+    if (IsBufferStorage) {\r
+      Value = StrStr (Result, L"&VALUE");\r
+      if (Value == NULL) {\r
+        FreePool (Result);\r
+        return EFI_NOT_FOUND;\r
+      }\r
+\r
+      //\r
+      // Skip "&VALUE"\r
+      //\r
+      Value = Value + 6;\r
+    } else {\r
+      Value = Result + Length;\r
+    }\r
+\r
+    if (*Value != '=') {\r
+      FreePool (Result);\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    //\r
+    // Skip '=', point to value\r
+    //\r
+    Value = Value + 1;\r
+\r
+    Status = BufferToQuestionValue (Question, Value, &Question->Value);\r
+    if (EFI_ERROR (Status)) {\r
+      FreePool (Result);\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Synchronize Buffer\r
+    //\r
+    if (IsBufferStorage) {\r
+      CopyMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth);\r
+    } else {\r
+      SetValueByName (Storage, Question->VariableName, Value, NULL);\r
+    }\r
+\r
+    if (Result != NULL) {\r
+      FreePool (Result);\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Convert the input Unicode character to upper.\r
+\r
+  @param[in] String  Th Unicode character to be converted.\r
+\r
+**/\r
+VOID\r
+IfrStrToUpper (\r
+  IN CHAR16  *String\r
+  )\r
+{\r
+  if (String == NULL) {\r
+    return;\r
+  }\r
+\r
+  while (*String != 0) {\r
+    if ((*String >= 'a') && (*String <= 'z')) {\r
+      *String = (UINT16)((*String) & ((UINT16) ~0x20));\r
+    }\r
+\r
+    String++;\r
+  }\r
+}\r
+\r
+/**\r
+  Check whether this value type can be transfer to EFI_IFR_TYPE_BUFFER type.\r
+\r
+  EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to\r
+  EFI_IFR_TYPE_BUFFER when do the value compare.\r
+\r
+  @param[in]  Value              Expression value to compare on.\r
+\r
+  @retval TRUE                   This value type can be transferred to EFI_IFR_TYPE_BUFFER type.\r
+  @retval FALSE                  This value type can't be transferred to EFI_IFR_TYPE_BUFFER type.\r
+\r
+**/\r
+BOOLEAN\r
+IsTypeInBuffer (\r
+  IN  EFI_HII_VALUE  *Value\r
+  )\r
+{\r
+  if (Value == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  switch (Value->Type) {\r
+    case EFI_IFR_TYPE_BUFFER:\r
+    case EFI_IFR_TYPE_DATE:\r
+    case EFI_IFR_TYPE_TIME:\r
+    case EFI_IFR_TYPE_REF:\r
+      return TRUE;\r
+\r
+    default:\r
+      return FALSE;\r
+  }\r
+}\r
+\r
+/**\r
+  Check whether this value type can be transfer to EFI_IFR_TYPE_UINT64\r
+\r
+  @param[in]  Value              Expression value to compare on.\r
+\r
+  @retval TRUE                   This value type can be transferred to EFI_IFR_TYPE_BUFFER type.\r
+  @retval FALSE                  This value type can't be transferred to EFI_IFR_TYPE_BUFFER type.\r
+\r
+**/\r
+BOOLEAN\r
+IsTypeInUINT64 (\r
+  IN  EFI_HII_VALUE  *Value\r
+  )\r
+{\r
+  if (Value == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  switch (Value->Type) {\r
+    case EFI_IFR_TYPE_NUM_SIZE_8:\r
+    case EFI_IFR_TYPE_NUM_SIZE_16:\r
+    case EFI_IFR_TYPE_NUM_SIZE_32:\r
+    case EFI_IFR_TYPE_NUM_SIZE_64:\r
+    case EFI_IFR_TYPE_BOOLEAN:\r
+      return TRUE;\r
+\r
+    default:\r
+      return FALSE;\r
+  }\r
+}\r
+\r
+/**\r
+  Return the buffer pointer for this value.\r
+\r
+  EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to\r
+  EFI_IFR_TYPE_BUFFER when do the value compare.\r
+\r
+  @param[in]  Value              Expression value to compare on.\r
+\r
+  @retval Buf                    Return the buffer pointer.\r
+\r
+**/\r
+UINT8 *\r
+GetBufferForValue (\r
+  IN  EFI_HII_VALUE  *Value\r
+  )\r
+{\r
+  if (Value == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  switch (Value->Type) {\r
+    case EFI_IFR_TYPE_BUFFER:\r
+      return Value->Buffer;\r
+\r
+    case EFI_IFR_TYPE_DATE:\r
+      return (UINT8 *)(&Value->Value.date);\r
+\r
+    case EFI_IFR_TYPE_TIME:\r
+      return (UINT8 *)(&Value->Value.time);\r
+\r
+    case EFI_IFR_TYPE_REF:\r
+      return (UINT8 *)(&Value->Value.ref);\r
+\r
+    default:\r
+      return NULL;\r
+  }\r
+}\r
+\r
+/**\r
+  Return the buffer length for this value.\r
+\r
+  EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to\r
+  EFI_IFR_TYPE_BUFFER when do the value compare.\r
+\r
+  @param[in] Value                Expression value to compare on.\r
+\r
+  @retval  BufLen                 Return the buffer length.\r
+\r
+**/\r
+UINT16\r
+GetLengthForValue (\r
+  IN  EFI_HII_VALUE  *Value\r
+  )\r
+{\r
+  if (Value == NULL) {\r
+    return 0;\r
+  }\r
+\r
+  switch (Value->Type) {\r
+    case EFI_IFR_TYPE_BUFFER:\r
+      return Value->BufferLen;\r
+\r
+    case EFI_IFR_TYPE_DATE:\r
+      return (UINT16)sizeof (EFI_HII_DATE);\r
+\r
+    case EFI_IFR_TYPE_TIME:\r
+      return (UINT16)sizeof (EFI_HII_TIME);\r
+\r
+    case EFI_IFR_TYPE_REF:\r
+      return (UINT16)sizeof (EFI_HII_REF);\r
+\r
+    default:\r
+      return 0;\r
+  }\r
+}\r
+\r
+/**\r
+  Get UINT64 type value.\r
+\r
+  @param[in]  Value              Input Hii value.\r
+\r
+  @retval UINT64                 Return the UINT64 type value.\r
+\r
+**/\r
+UINT64\r
+HiiValueToUINT64 (\r
+  IN EFI_HII_VALUE  *Value\r
+  )\r
+{\r
+  UINT64  RetVal;\r
+\r
+  if (Value == NULL) {\r
+    return 0;\r
+  }\r
+\r
+  RetVal = 0;\r
+\r
+  switch (Value->Type) {\r
+    case EFI_IFR_TYPE_NUM_SIZE_8:\r
+      RetVal = Value->Value.u8;\r
+      break;\r
+\r
+    case EFI_IFR_TYPE_NUM_SIZE_16:\r
+      RetVal = Value->Value.u16;\r
+      break;\r
+\r
+    case EFI_IFR_TYPE_NUM_SIZE_32:\r
+      RetVal = Value->Value.u32;\r
+      break;\r
+\r
+    case EFI_IFR_TYPE_BOOLEAN:\r
+      RetVal = Value->Value.b;\r
+      break;\r
+\r
+    case EFI_IFR_TYPE_DATE:\r
+      RetVal = *(UINT64 *)&Value->Value.date;\r
+      break;\r
+\r
+    case EFI_IFR_TYPE_TIME:\r
+      RetVal = (*(UINT64 *)&Value->Value.time) & 0xffffff;\r
+      break;\r
+\r
+    default:\r
+      RetVal = Value->Value.u64;\r
+      break;\r
+  }\r
+\r
+  return RetVal;\r
+}\r
+\r
+/**\r
+  Compare two Hii value.\r
+\r
+  @param[in]  Value1             Expression value to compare on left-hand.\r
+  @param[in]  Value2             Expression value to compare on right-hand.\r
+  @param[out] Result             Return value after compare.\r
+                                 retval 0                      Two operators equal.\r
+                                 return Positive value if Value1 is greater than Value2.\r
+                                 retval Negative value if Value1 is less than Value2.\r
+  @param[in]  HiiHandle          Only required for string compare.\r
+\r
+  @retval other                  Could not perform compare on two values.\r
+  @retval EFI_SUCCESS            Compare the value success.\r
+  @retval EFI_INVALID_PARAMETER  Value1, Value2 or Result is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+CompareHiiValue (\r
+  IN  EFI_HII_VALUE   *Value1,\r
+  IN  EFI_HII_VALUE   *Value2,\r
+  OUT INTN            *Result,\r
+  IN  EFI_HII_HANDLE  HiiHandle OPTIONAL\r
+  )\r
+{\r
+  INT64   Temp64;\r
+  CHAR16  *Str1;\r
+  CHAR16  *Str2;\r
+  UINTN   Len;\r
+  UINT8   *Buf1;\r
+  UINT16  Buf1Len;\r
+  UINT8   *Buf2;\r
+  UINT16  Buf2Len;\r
+\r
+  if ((Value1 == NULL) || (Value2 == NULL) || (Result == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if ((Value1->Type == EFI_IFR_TYPE_STRING) && (Value2->Type == EFI_IFR_TYPE_STRING)) {\r
+    if ((Value1->Value.string == 0) || (Value2->Value.string == 0)) {\r
+      //\r
+      // StringId 0 is reserved\r
+      //\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    if (Value1->Value.string == Value2->Value.string) {\r
+      *Result = 0;\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    Str1 = GetTokenString (Value1->Value.string, HiiHandle);\r
+    if (Str1 == NULL) {\r
+      //\r
+      // String not found\r
+      //\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    Str2 = GetTokenString (Value2->Value.string, HiiHandle);\r
+    if (Str2 == NULL) {\r
+      FreePool (Str1);\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    *Result = StrCmp (Str1, Str2);\r
+\r
+    FreePool (Str1);\r
+    FreePool (Str2);\r
+\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Take types(date, time, ref, buffer) as buffer\r
+  //\r
+  if (IsTypeInBuffer (Value1) && IsTypeInBuffer (Value2)) {\r
+    Buf1    = GetBufferForValue (Value1);\r
+    Buf1Len = GetLengthForValue (Value1);\r
+    Buf2    = GetBufferForValue (Value2);\r
+    Buf2Len = GetLengthForValue (Value2);\r
+\r
+    Len     = Buf1Len > Buf2Len ? Buf2Len : Buf1Len;\r
+    *Result = CompareMem (Buf1, Buf2, Len);\r
+    if ((*Result == 0) && (Buf1Len != Buf2Len)) {\r
+      //\r
+      // In this case, means base on small number buffer, the data is same\r
+      // So which value has more data, which value is bigger.\r
+      //\r
+      *Result = Buf1Len > Buf2Len ? 1 : -1;\r
+    }\r
+\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Take types(integer, boolean) as integer\r
+  //\r
+  if (IsTypeInUINT64 (Value1) && IsTypeInUINT64 (Value2)) {\r
+    Temp64 = HiiValueToUINT64 (Value1) - HiiValueToUINT64 (Value2);\r
+    if (Temp64 > 0) {\r
+      *Result = 1;\r
+    } else if (Temp64 < 0) {\r
+      *Result = -1;\r
+    } else {\r
+      *Result = 0;\r
+    }\r
+\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+  Check if current user has the privilege specified by the permissions GUID.\r
+\r
+  @param[in] Guid  A GUID specifying setup access permissions.\r
+\r
+  @retval TRUE     Current user has the privilege.\r
+  @retval FALSE    Current user does not have the privilege.\r
+**/\r
+BOOLEAN\r
+CheckUserPrivilege (\r
+  IN EFI_GUID  *Guid\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  EFI_USER_PROFILE_HANDLE       UserProfileHandle;\r
+  EFI_USER_INFO_HANDLE          UserInfoHandle;\r
+  EFI_USER_INFO                 *UserInfo;\r
+  EFI_GUID                      *UserPermissionsGuid;\r
+  UINTN                         UserInfoSize;\r
+  UINTN                         AccessControlDataSize;\r
+  EFI_USER_INFO_ACCESS_CONTROL  *AccessControl;\r
+  UINTN                         RemainSize;\r
+\r
+  if (mUserManager == NULL) {\r
+    Status = gBS->LocateProtocol (\r
+                    &gEfiUserManagerProtocolGuid,\r
+                    NULL,\r
+                    (VOID **)&mUserManager\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      ///\r
+      /// If the system does not support user management, then it is assumed that\r
+      /// all users have admin privilege and evaluation of each EFI_IFR_SECURITY\r
+      /// op-code is always TRUE.\r
+      ///\r
+      return TRUE;\r
+    }\r
+  }\r
+\r
+  Status = mUserManager->Current (mUserManager, &UserProfileHandle);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  ///\r
+  /// Enumerate all user information of the current user profile\r
+  /// to look for any EFI_USER_INFO_ACCESS_SETUP record.\r
+  ///\r
+\r
+  for (UserInfoHandle = NULL; ;) {\r
+    Status = mUserManager->GetNextInfo (mUserManager, UserProfileHandle, &UserInfoHandle);\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+\r
+    UserInfoSize = 0;\r
+    Status       = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, NULL, &UserInfoSize);\r
+    if (Status != EFI_BUFFER_TOO_SMALL) {\r
+      continue;\r
+    }\r
+\r
+    UserInfo = (EFI_USER_INFO *)AllocatePool (UserInfoSize);\r
+    if (UserInfo == NULL) {\r
+      break;\r
+    }\r
+\r
+    Status = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, UserInfo, &UserInfoSize);\r
+    if (EFI_ERROR (Status) ||\r
+        (UserInfo->InfoType != EFI_USER_INFO_ACCESS_POLICY_RECORD) ||\r
+        (UserInfo->InfoSize <= sizeof (EFI_USER_INFO)))\r
+    {\r
+      FreePool (UserInfo);\r
+      continue;\r
+    }\r
+\r
+    RemainSize    = UserInfo->InfoSize - sizeof (EFI_USER_INFO);\r
+    AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)(UserInfo + 1);\r
+    while (RemainSize >= sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {\r
+      if ((RemainSize < AccessControl->Size) || (AccessControl->Size < sizeof (EFI_USER_INFO_ACCESS_CONTROL))) {\r
+        break;\r
+      }\r
+\r
+      if (AccessControl->Type == EFI_USER_INFO_ACCESS_SETUP) {\r
+        ///\r
+        /// Check if current user has the privilege specified by the permissions GUID.\r
+        ///\r
+\r
+        UserPermissionsGuid   = (EFI_GUID *)(AccessControl + 1);\r
+        AccessControlDataSize = AccessControl->Size - sizeof (EFI_USER_INFO_ACCESS_CONTROL);\r
+        while (AccessControlDataSize >= sizeof (EFI_GUID)) {\r
+          if (CompareGuid (Guid, UserPermissionsGuid)) {\r
+            FreePool (UserInfo);\r
+            return TRUE;\r
+          }\r
+\r
+          UserPermissionsGuid++;\r
+          AccessControlDataSize -= sizeof (EFI_GUID);\r
+        }\r
+      }\r
+\r
+      RemainSize   -= AccessControl->Size;\r
+      AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)((UINT8 *)AccessControl + AccessControl->Size);\r
+    }\r
+\r
+    FreePool (UserInfo);\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Search a Question in Form scope using its QuestionId.\r
+\r
+  @param[in]  Form               The form which contains this Question.\r
+  @param[in]  QuestionId         Id of this Question.\r
+\r
+  @retval Pointer                The Question.\r
+  @retval NULL                   Specified Question not found in the form.\r
+\r
+**/\r
+HII_STATEMENT *\r
+QuestionIdInForm (\r
+  IN HII_FORM  *Form,\r
+  IN UINT16    QuestionId\r
+  )\r
+{\r
+  LIST_ENTRY     *Link;\r
+  HII_STATEMENT  *Question;\r
+\r
+  if ((QuestionId == 0) || (Form == NULL)) {\r
+    //\r
+    // The value of zero is reserved\r
+    //\r
+    return NULL;\r
+  }\r
+\r
+  Link = GetFirstNode (&Form->StatementListHead);\r
+  while (!IsNull (&Form->StatementListHead, Link)) {\r
+    Question = HII_STATEMENT_FROM_LINK (Link);\r
+\r
+    if (Question->QuestionId == QuestionId) {\r
+      return Question;\r
+    }\r
+\r
+    Link = GetNextNode (&Form->StatementListHead, Link);\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Search a Question in Formset scope using its QuestionId.\r
+\r
+  @param[in]  FormSet            The formset which contains this form.\r
+  @param[in]  Form               The form which contains this Question.\r
+  @param[in]  QuestionId         Id of this Question.\r
+\r
+  @retval Pointer                The Question.\r
+  @retval NULL                   Specified Question not found in the form.\r
+\r
+**/\r
+HII_STATEMENT *\r
+QuestionIdInFormset (\r
+  IN HII_FORMSET  *FormSet,\r
+  IN HII_FORM     *Form,\r
+  IN UINT16       QuestionId\r
+  )\r
+{\r
+  LIST_ENTRY     *Link;\r
+  HII_STATEMENT  *Question;\r
+\r
+  if ((FormSet == NULL) || (Form == NULL)) {\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Search in the form scope first\r
+  //\r
+  Question = QuestionIdInForm (Form, QuestionId);\r
+  if (Question != NULL) {\r
+    return Question;\r
+  }\r
+\r
+  //\r
+  // Search in the formset scope\r
+  //\r
+  Link = GetFirstNode (&FormSet->FormListHead);\r
+  while (!IsNull (&FormSet->FormListHead, Link)) {\r
+    Form = HII_FORM_FROM_LINK (Link);\r
+\r
+    Question = QuestionIdInForm (Form, QuestionId);\r
+    if (Question != NULL) {\r
+      //\r
+      // EFI variable storage may be updated by Callback() asynchronous,\r
+      // to keep synchronous, always reload the Question Value.\r
+      //\r
+      if (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+        GetQuestionValue (FormSet, Form, Question, GetSetValueWithHiiDriver);\r
+      }\r
+\r
+      return Question;\r
+    }\r
+\r
+    Link = GetNextNode (&FormSet->FormListHead, Link);\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Push an Expression value onto the Stack\r
+\r
+  @param[in]  Value              Expression value to push.\r
+\r
+  @retval EFI_SUCCESS            The value was pushed onto the stack.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the\r
+                                 stack.\r
+  @retval EFI_INVALID_PARAMETER  Value is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+PushExpression (\r
+  IN EFI_HII_VALUE  *Value\r
+  )\r
+{\r
+  if (Value == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  return PushStack (\r
+           &mExpressionEvaluationStack,\r
+           &mExpressionEvaluationStackPointer,\r
+           &mExpressionEvaluationStackEnd,\r
+           Value\r
+           );\r
+}\r
+\r
+/**\r
+  Pop an Expression value from the stack.\r
+\r
+  @param[out]  Value              Expression value to pop.\r
+\r
+  @retval EFI_SUCCESS            The value was popped onto the stack.\r
+  @retval EFI_ACCESS_DENIED      The pop operation underflowed the stack\r
+  @retval EFI_INVALID_PARAMETER  Value is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+PopExpression (\r
+  OUT EFI_HII_VALUE  *Value\r
+  )\r
+{\r
+  if (Value == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  return PopStack (\r
+           mExpressionEvaluationStack + mExpressionEvaluationStackOffset,\r
+           &mExpressionEvaluationStackPointer,\r
+           Value\r
+           );\r
+}\r
+\r
+/**\r
+  Get current stack offset from stack start.\r
+\r
+  @return Stack offset to stack start.\r
+**/\r
+UINTN\r
+SaveExpressionEvaluationStackOffset (\r
+  VOID\r
+  )\r
+{\r
+  UINTN  TempStackOffset;\r
+\r
+  TempStackOffset                  = mExpressionEvaluationStackOffset;\r
+  mExpressionEvaluationStackOffset = mExpressionEvaluationStackPointer - mExpressionEvaluationStack;\r
+  return TempStackOffset;\r
+}\r
+\r
+/**\r
+  Restore stack offset based on input stack offset\r
+\r
+  @param[in]  StackOffset  Offset to stack start.\r
+\r
+**/\r
+VOID\r
+RestoreExpressionEvaluationStackOffset (\r
+  UINTN  StackOffset\r
+  )\r
+{\r
+  mExpressionEvaluationStackOffset = StackOffset;\r
+}\r
+\r
+/**\r
+  Evaluate opcode EFI_IFR_TO_STRING.\r
+\r
+  @param[in]  FormSet            Formset which contains this opcode.\r
+  @param[in]  Format             String format in EFI_IFR_TO_STRING.\r
+  @param[out] Result             Evaluation result for this opcode.\r
+\r
+  @retval EFI_SUCCESS            Opcode evaluation success.\r
+  @retval Other                  Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrToString (\r
+  IN HII_FORMSET      *FormSet,\r
+  IN UINT8            Format,\r
+  OUT  EFI_HII_VALUE  *Result\r
+  )\r
+{\r
+  EFI_STATUS     Status;\r
+  EFI_HII_VALUE  Value;\r
+  CHAR16         *String;\r
+  CHAR16         *PrintFormat;\r
+  CHAR16         Buffer[MAXIMUM_VALUE_CHARACTERS];\r
+  UINT8          *SrcBuf;\r
+  UINTN          BufferSize;\r
+\r
+  if ((FormSet == NULL) || (Result == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = PopExpression (&Value);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  switch (Value.Type) {\r
+    case EFI_IFR_TYPE_NUM_SIZE_8:\r
+    case EFI_IFR_TYPE_NUM_SIZE_16:\r
+    case EFI_IFR_TYPE_NUM_SIZE_32:\r
+    case EFI_IFR_TYPE_NUM_SIZE_64:\r
+      BufferSize = MAXIMUM_VALUE_CHARACTERS * sizeof (CHAR16);\r
+      switch (Format) {\r
+        case EFI_IFR_STRING_UNSIGNED_DEC:\r
+        case EFI_IFR_STRING_SIGNED_DEC:\r
+          PrintFormat = L"%ld";\r
+          break;\r
+\r
+        case EFI_IFR_STRING_LOWERCASE_HEX:\r
+          PrintFormat = L"%lx";\r
+          break;\r
+\r
+        case EFI_IFR_STRING_UPPERCASE_HEX:\r
+          PrintFormat = L"%lX";\r
+          break;\r
+\r
+        default:\r
+          Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          return EFI_SUCCESS;\r
+      }\r
+\r
+      UnicodeSPrint (Buffer, BufferSize, PrintFormat, Value.Value.u64);\r
+      String = Buffer;\r
+      break;\r
+\r
+    case EFI_IFR_TYPE_STRING:\r
+      CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));\r
+      return EFI_SUCCESS;\r
+\r
+    case EFI_IFR_TYPE_BOOLEAN:\r
+      String = (Value.Value.b) ? L"True" : L"False";\r
+      break;\r
+\r
+    case EFI_IFR_TYPE_BUFFER:\r
+    case EFI_IFR_TYPE_DATE:\r
+    case EFI_IFR_TYPE_TIME:\r
+    case EFI_IFR_TYPE_REF:\r
+      //\r
+      // + 3 is base on the unicode format, the length may be odd number,\r
+      // so need 1 byte to align, also need 2 bytes for L'\0'.\r
+      //\r
+      if (Value.Type == EFI_IFR_TYPE_BUFFER) {\r
+        SrcBuf = Value.Buffer;\r
+      } else {\r
+        SrcBuf = GetBufferForValue (&Value);\r
+      }\r
+\r
+      if (Format == EFI_IFR_STRING_ASCII) {\r
+        PrintFormat = L"%a";\r
+      } else {\r
+        // Format == EFI_IFR_STRING_UNICODE\r
+        PrintFormat = L"%s";\r
+      }\r
+\r
+      UnicodeSPrint (Buffer, sizeof (Buffer), PrintFormat, SrcBuf);\r
+      String = Buffer;\r
+      if (Value.Type == EFI_IFR_TYPE_BUFFER) {\r
+        FreePool (Value.Buffer);\r
+      }\r
+\r
+      break;\r
+\r
+    default:\r
+      Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+      return EFI_SUCCESS;\r
+  }\r
+\r
+  Result->Type         = EFI_IFR_TYPE_STRING;\r
+  Result->Value.string = NewHiiString (String, FormSet->HiiHandle);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Evaluate opcode EFI_IFR_TO_UINT.\r
+\r
+  @param[in]  FormSet            Formset which contains this opcode.\r
+  @param[out] Result             Evaluation result for this opcode.\r
+\r
+  @retval EFI_SUCCESS            Opcode evaluation success.\r
+  @retval Other                  Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrToUint (\r
+  IN HII_FORMSET      *FormSet,\r
+  OUT  EFI_HII_VALUE  *Result\r
+  )\r
+{\r
+  EFI_STATUS     Status;\r
+  EFI_HII_VALUE  Value;\r
+  CHAR16         *String;\r
+  CHAR16         *StringPtr;\r
+\r
+  if ((FormSet == NULL) || (Result == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = PopExpression (&Value);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if ((Value.Type >= EFI_IFR_TYPE_OTHER) && !IsTypeInBuffer (&Value)) {\r
+    Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  Status = EFI_SUCCESS;\r
+  if (Value.Type == EFI_IFR_TYPE_STRING) {\r
+    String = GetTokenString (Value.Value.string, FormSet->HiiHandle);\r
+    if (String == NULL) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    IfrStrToUpper (String);\r
+    StringPtr = StrStr (String, L"0X");\r
+    if (StringPtr != NULL) {\r
+      //\r
+      // Hex string\r
+      //\r
+      Result->Value.u64 = StrHexToUint64 (String);\r
+    } else {\r
+      //\r
+      // decimal string\r
+      //\r
+      Result->Value.u64 = StrDecimalToUint64 (String);\r
+    }\r
+\r
+    FreePool (String);\r
+  } else if (IsTypeInBuffer (&Value)) {\r
+    if (GetLengthForValue (&Value) > 8) {\r
+      if (Value.Type == EFI_IFR_TYPE_BUFFER) {\r
+        FreePool (Value.Buffer);\r
+      }\r
+\r
+      Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    Result->Value.u64 = *(UINT64 *)GetBufferForValue (&Value);\r
+    if (Value.Type == EFI_IFR_TYPE_BUFFER) {\r
+      FreePool (Value.Buffer);\r
+    }\r
+  } else {\r
+    CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));\r
+  }\r
+\r
+  Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Evaluate opcode EFI_IFR_CATENATE.\r
+\r
+  @param[in]  FormSet            Formset which contains this opcode.\r
+  @param[out] Result             Evaluation result for this opcode.\r
+\r
+  @retval EFI_SUCCESS            Opcode evaluation success.\r
+  @retval Other                  Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrCatenate (\r
+  IN HII_FORMSET      *FormSet,\r
+  OUT  EFI_HII_VALUE  *Result\r
+  )\r
+{\r
+  EFI_STATUS     Status;\r
+  EFI_HII_VALUE  Value[2];\r
+  CHAR16         *String[2];\r
+  UINTN          Index;\r
+  CHAR16         *StringPtr;\r
+  UINTN          Size;\r
+  UINT16         Length0;\r
+  UINT16         Length1;\r
+  UINT8          *TmpBuf;\r
+  UINTN          MaxLen;\r
+\r
+  if ((FormSet == NULL) || (Result == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // String[0] - The second string\r
+  // String[1] - The first string\r
+  //\r
+  String[0] = NULL;\r
+  String[1] = NULL;\r
+  StringPtr = NULL;\r
+  Status    = EFI_SUCCESS;\r
+  ZeroMem (Value, sizeof (Value));\r
+\r
+  Status = PopExpression (&Value[0]);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+\r
+  Status = PopExpression (&Value[1]);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+\r
+  for (Index = 0; Index < 2; Index++) {\r
+    if ((Value[Index].Type != EFI_IFR_TYPE_STRING) && !IsTypeInBuffer (&Value[Index])) {\r
+      Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+      Status       = EFI_SUCCESS;\r
+      goto Done;\r
+    }\r
+\r
+    if (Value[Index].Type == EFI_IFR_TYPE_STRING) {\r
+      String[Index] = GetTokenString (Value[Index].Value.string, FormSet->HiiHandle);\r
+      if (String[Index] == NULL) {\r
+        Status = EFI_NOT_FOUND;\r
+        goto Done;\r
+      }\r
+    }\r
+  }\r
+\r
+  if (Value[0].Type == EFI_IFR_TYPE_STRING) {\r
+    Size      = StrSize (String[0]);\r
+    MaxLen    = (StrSize (String[1]) + Size) / sizeof (CHAR16);\r
+    StringPtr = AllocatePool (MaxLen * sizeof (CHAR16));\r
+    ASSERT (StringPtr != NULL);\r
+    StrCpyS (StringPtr, MaxLen, String[1]);\r
+    StrCatS (StringPtr, MaxLen, String[0]);\r
+\r
+    Result->Type         = EFI_IFR_TYPE_STRING;\r
+    Result->Value.string = NewHiiString (StringPtr, FormSet->HiiHandle);\r
+  } else {\r
+    Result->Type      = EFI_IFR_TYPE_BUFFER;\r
+    Length0           = GetLengthForValue (&Value[0]);\r
+    Length1           = GetLengthForValue (&Value[1]);\r
+    Result->BufferLen = (UINT16)(Length0 + Length1);\r
+\r
+    Result->Buffer = AllocatePool (Result->BufferLen);\r
+    ASSERT (Result->Buffer != NULL);\r
+\r
+    TmpBuf = GetBufferForValue (&Value[0]);\r
+    ASSERT (TmpBuf != NULL);\r
+    CopyMem (Result->Buffer, TmpBuf, Length0);\r
+    TmpBuf = GetBufferForValue (&Value[1]);\r
+    ASSERT (TmpBuf != NULL);\r
+    CopyMem (&Result->Buffer[Length0], TmpBuf, Length1);\r
+  }\r
+\r
+Done:\r
+  if (Value[0].Buffer != NULL) {\r
+    FreePool (Value[0].Buffer);\r
+  }\r
+\r
+  if (Value[1].Buffer != NULL) {\r
+    FreePool (Value[1].Buffer);\r
+  }\r
+\r
+  if (String[0] != NULL) {\r
+    FreePool (String[0]);\r
+  }\r
+\r
+  if (String[1] != NULL) {\r
+    FreePool (String[1]);\r
+  }\r
+\r
+  if (StringPtr != NULL) {\r
+    FreePool (StringPtr);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Evaluate opcode EFI_IFR_MATCH.\r
+\r
+  @param[in]  FormSet            Formset which contains this opcode.\r
+  @param[out] Result             Evaluation result for this opcode.\r
+\r
+  @retval EFI_SUCCESS            Opcode evaluation success.\r
+  @retval Other                  Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrMatch (\r
+  IN   HII_FORMSET    *FormSet,\r
+  OUT  EFI_HII_VALUE  *Result\r
+  )\r
+{\r
+  EFI_STATUS     Status;\r
+  EFI_HII_VALUE  Value[2];\r
+  CHAR16         *String[2];\r
+  UINTN          Index;\r
+\r
+  if ((FormSet == NULL) || (Result == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // String[0] - The string to search\r
+  // String[1] - pattern\r
+  //\r
+  String[0] = NULL;\r
+  String[1] = NULL;\r
+  Status    = EFI_SUCCESS;\r
+  ZeroMem (Value, sizeof (Value));\r
+\r
+  Status = PopExpression (&Value[0]);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+\r
+  Status = PopExpression (&Value[1]);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+\r
+  for (Index = 0; Index < 2; Index++) {\r
+    if (Value[Index].Type != EFI_IFR_TYPE_STRING) {\r
+      Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+      Status       = EFI_SUCCESS;\r
+      goto Done;\r
+    }\r
+\r
+    String[Index] = GetTokenString (Value[Index].Value.string, FormSet->HiiHandle);\r
+    if (String[Index] == NULL) {\r
+      Status = EFI_NOT_FOUND;\r
+      goto Done;\r
+    }\r
+  }\r
+\r
+  Result->Type    = EFI_IFR_TYPE_BOOLEAN;\r
+  Result->Value.b = mUnicodeCollation->MetaiMatch (mUnicodeCollation, String[0], String[1]);\r
+\r
+Done:\r
+  if (String[0] != NULL) {\r
+    FreePool (String[0]);\r
+  }\r
+\r
+  if (String[1] != NULL) {\r
+    FreePool (String[1]);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Evaluate opcode EFI_IFR_MATCH2.\r
+\r
+  @param[in]  FormSet            Formset which contains this opcode.\r
+  @param[in]  SyntaxType         Syntax type for match2.\r
+  @param[out] Result             Evaluation result for this opcode.\r
+\r
+  @retval EFI_SUCCESS            Opcode evaluation success.\r
+  @retval Other                  Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrMatch2 (\r
+  IN HII_FORMSET      *FormSet,\r
+  IN EFI_GUID         *SyntaxType,\r
+  OUT  EFI_HII_VALUE  *Result\r
+  )\r
+{\r
+  EFI_STATUS                       Status;\r
+  EFI_HII_VALUE                    Value[2];\r
+  CHAR16                           *String[2];\r
+  UINTN                            Index;\r
+  UINTN                            GuidIndex;\r
+  EFI_HANDLE                       *HandleBuffer;\r
+  UINTN                            BufferSize;\r
+  EFI_REGULAR_EXPRESSION_PROTOCOL  *RegularExpressionProtocol;\r
+  UINTN                            RegExSyntaxTypeListSize;\r
+  EFI_REGEX_SYNTAX_TYPE            *RegExSyntaxTypeList;\r
+  UINTN                            CapturesCount;\r
+\r
+  if ((FormSet == NULL) || (SyntaxType == NULL) || (Result == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // String[0] - The string to search\r
+  // String[1] - pattern\r
+  //\r
+  String[0]           = NULL;\r
+  String[1]           = NULL;\r
+  HandleBuffer        = NULL;\r
+  RegExSyntaxTypeList = NULL;\r
+  Status              = EFI_SUCCESS;\r
+  ZeroMem (Value, sizeof (Value));\r
+\r
+  Status = PopExpression (&Value[0]);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+\r
+  Status = PopExpression (&Value[1]);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+\r
+  for (Index = 0; Index < 2; Index++) {\r
+    if (Value[Index].Type != EFI_IFR_TYPE_STRING) {\r
+      Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+      Status       = EFI_SUCCESS;\r
+      goto Done;\r
+    }\r
+\r
+    String[Index] = GetTokenString (Value[Index].Value.string, FormSet->HiiHandle);\r
+    if (String[Index] == NULL) {\r
+      Status = EFI_NOT_FOUND;\r
+      goto Done;\r
+    }\r
+  }\r
+\r
+  BufferSize   = 0;\r
+  HandleBuffer = NULL;\r
+  Status       = gBS->LocateHandle (\r
+                        ByProtocol,\r
+                        &gEfiRegularExpressionProtocolGuid,\r
+                        NULL,\r
+                        &BufferSize,\r
+                        HandleBuffer\r
+                        );\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    HandleBuffer = AllocatePool (BufferSize);\r
+    if (HandleBuffer == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto Done;\r
+    }\r
+\r
+    Status = gBS->LocateHandle (\r
+                    ByProtocol,\r
+                    &gEfiRegularExpressionProtocolGuid,\r
+                    NULL,\r
+                    &BufferSize,\r
+                    HandleBuffer\r
+                    );\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+    Status       = EFI_SUCCESS;\r
+    goto Done;\r
+  }\r
+\r
+  ASSERT (HandleBuffer != NULL);\r
+  for ( Index = 0; Index < BufferSize / sizeof (EFI_HANDLE); Index++) {\r
+    Status = gBS->HandleProtocol (\r
+                    HandleBuffer[Index],\r
+                    &gEfiRegularExpressionProtocolGuid,\r
+                    (VOID **)&RegularExpressionProtocol\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+\r
+    RegExSyntaxTypeListSize = 0;\r
+    RegExSyntaxTypeList     = NULL;\r
+\r
+    Status = RegularExpressionProtocol->GetInfo (\r
+                                          RegularExpressionProtocol,\r
+                                          &RegExSyntaxTypeListSize,\r
+                                          RegExSyntaxTypeList\r
+                                          );\r
+    if (Status == EFI_BUFFER_TOO_SMALL) {\r
+      RegExSyntaxTypeList = AllocatePool (RegExSyntaxTypeListSize);\r
+      if (RegExSyntaxTypeList == NULL) {\r
+        Status = EFI_OUT_OF_RESOURCES;\r
+        goto Done;\r
+      }\r
+\r
+      Status = RegularExpressionProtocol->GetInfo (\r
+                                            RegularExpressionProtocol,\r
+                                            &RegExSyntaxTypeListSize,\r
+                                            RegExSyntaxTypeList\r
+                                            );\r
+    } else if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+\r
+    for (GuidIndex = 0; GuidIndex < RegExSyntaxTypeListSize / sizeof (EFI_GUID); GuidIndex++) {\r
+      if (CompareGuid (&RegExSyntaxTypeList[GuidIndex], SyntaxType)) {\r
+        //\r
+        // Find the match type, return the value.\r
+        //\r
+        Result->Type = EFI_IFR_TYPE_BOOLEAN;\r
+        Status       = RegularExpressionProtocol->MatchString (\r
+                                                    RegularExpressionProtocol,\r
+                                                    String[0],\r
+                                                    String[1],\r
+                                                    SyntaxType,\r
+                                                    &Result->Value.b,\r
+                                                    NULL,\r
+                                                    &CapturesCount\r
+                                                    );\r
+        goto Done;\r
+      }\r
+    }\r
+\r
+    if (RegExSyntaxTypeList != NULL) {\r
+      FreePool (RegExSyntaxTypeList);\r
+    }\r
+  }\r
+\r
+  //\r
+  // Type specified by SyntaxType is not supported\r
+  // in any of the EFI_REGULAR_EXPRESSION_PROTOCOL instances.\r
+  //\r
+  Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+  Status       = EFI_SUCCESS;\r
+\r
+Done:\r
+  if (String[0] != NULL) {\r
+    FreePool (String[0]);\r
+  }\r
+\r
+  if (String[1] != NULL) {\r
+    FreePool (String[1]);\r
+  }\r
+\r
+  if (RegExSyntaxTypeList != NULL) {\r
+    FreePool (RegExSyntaxTypeList);\r
+  }\r
+\r
+  if (HandleBuffer != NULL) {\r
+    FreePool (HandleBuffer);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Evaluate opcode EFI_IFR_FIND.\r
+\r
+  @param[in]  FormSet            Formset which contains this opcode.\r
+  @param[in]  Format             Case sensitive or insensitive.\r
+  @param[out] Result             Evaluation result for this opcode.\r
+\r
+  @retval EFI_SUCCESS            Opcode evaluation success.\r
+  @retval Other                  Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrFind (\r
+  IN HII_FORMSET      *FormSet,\r
+  IN UINT8            Format,\r
+  OUT  EFI_HII_VALUE  *Result\r
+  )\r
+{\r
+  EFI_STATUS     Status;\r
+  EFI_HII_VALUE  Value[3];\r
+  CHAR16         *String[2];\r
+  UINTN          Base;\r
+  CHAR16         *StringPtr;\r
+  UINTN          Index;\r
+\r
+  if ((FormSet == NULL) || (Result == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  ZeroMem (Value, sizeof (Value));\r
+\r
+  if (Format > EFI_IFR_FF_CASE_INSENSITIVE) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = PopExpression (&Value[0]);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = PopExpression (&Value[1]);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = PopExpression (&Value[2]);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
+    Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  Base = (UINTN)Value[0].Value.u64;\r
+\r
+  //\r
+  // String[0] - sub-string\r
+  // String[1] - The string to search\r
+  //\r
+  String[0] = NULL;\r
+  String[1] = NULL;\r
+  for (Index = 0; Index < 2; Index++) {\r
+    if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {\r
+      Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+      Status       = EFI_SUCCESS;\r
+      goto Done;\r
+    }\r
+\r
+    String[Index] = GetTokenString (Value[Index + 1].Value.string, FormSet->HiiHandle);\r
+    if (String[Index] == NULL) {\r
+      Status = EFI_NOT_FOUND;\r
+      goto Done;\r
+    }\r
+\r
+    if (Format == EFI_IFR_FF_CASE_INSENSITIVE) {\r
+      //\r
+      // Case insensitive, convert both string to upper case\r
+      //\r
+      IfrStrToUpper (String[Index]);\r
+    }\r
+  }\r
+\r
+  Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+  if (Base >= StrLen (String[1])) {\r
+    Result->Value.u64 = 0xFFFFFFFFFFFFFFFFULL;\r
+  } else {\r
+    StringPtr         = StrStr (String[1] + Base, String[0]);\r
+    Result->Value.u64 = (StringPtr == NULL) ? 0xFFFFFFFFFFFFFFFFULL : (StringPtr - String[1]);\r
+  }\r
+\r
+Done:\r
+  if (String[0] != NULL) {\r
+    FreePool (String[0]);\r
+  }\r
+\r
+  if (String[1] != NULL) {\r
+    FreePool (String[1]);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Evaluate opcode EFI_IFR_MID.\r
+\r
+  @param[in]  FormSet            Formset which contains this opcode.\r
+  @param[out] Result             Evaluation result for this opcode.\r
+\r
+  @retval EFI_SUCCESS            Opcode evaluation success.\r
+  @retval Other                  Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrMid (\r
+  IN   HII_FORMSET    *FormSet,\r
+  OUT  EFI_HII_VALUE  *Result\r
+  )\r
+{\r
+  EFI_STATUS     Status;\r
+  EFI_HII_VALUE  Value[3];\r
+  CHAR16         *String;\r
+  UINTN          Base;\r
+  UINTN          Length;\r
+  CHAR16         *SubString;\r
+  UINT16         BufferLen;\r
+  UINT8          *Buffer;\r
+\r
+  if ((FormSet == NULL) || (Result == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  ZeroMem (Value, sizeof (Value));\r
+\r
+  Status = PopExpression (&Value[0]);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = PopExpression (&Value[1]);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = PopExpression (&Value[2]);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
+    Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  Length = (UINTN)Value[0].Value.u64;\r
+\r
+  if (Value[1].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
+    Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  Base = (UINTN)Value[1].Value.u64;\r
+\r
+  if ((Value[2].Type != EFI_IFR_TYPE_STRING) && !IsTypeInBuffer (&Value[2])) {\r
+    Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  if (Value[2].Type == EFI_IFR_TYPE_STRING) {\r
+    String = GetTokenString (Value[2].Value.string, FormSet->HiiHandle);\r
+    if (String == NULL) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    if ((Length == 0) || (Base >= StrLen (String))) {\r
+      SubString = gEmptyString;\r
+    } else {\r
+      SubString = String + Base;\r
+      if ((Base + Length) < StrLen (String)) {\r
+        SubString[Length] = L'\0';\r
+      }\r
+    }\r
+\r
+    Result->Type         = EFI_IFR_TYPE_STRING;\r
+    Result->Value.string = NewHiiString (SubString, FormSet->HiiHandle);\r
+\r
+    FreePool (String);\r
+  } else {\r
+    BufferLen = GetLengthForValue (&Value[2]);\r
+    Buffer    = GetBufferForValue (&Value[2]);\r
+\r
+    Result->Type = EFI_IFR_TYPE_BUFFER;\r
+    if ((Length == 0) || (Base >= BufferLen)) {\r
+      Result->BufferLen = 0;\r
+      Result->Buffer    = NULL;\r
+    } else {\r
+      Result->BufferLen = (UINT16)((BufferLen - Base) < Length ? (BufferLen - Base) : Length);\r
+      Result->Buffer    = AllocatePool (Result->BufferLen);\r
+      ASSERT (Result->Buffer != NULL);\r
+      CopyMem (Result->Buffer, &Buffer[Base], Result->BufferLen);\r
+    }\r
+\r
+    if (Value[2].Type == EFI_IFR_TYPE_BUFFER) {\r
+      FreePool (Value[2].Buffer);\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Evaluate opcode EFI_IFR_TOKEN.\r
+\r
+  @param[in]  FormSet            Formset which contains this opcode.\r
+  @param[out] Result             Evaluation result for this opcode.\r
+\r
+  @retval EFI_SUCCESS            Opcode evaluation success.\r
+  @retval Other                  Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrToken (\r
+  IN  HII_FORMSET    *FormSet,\r
+  OUT EFI_HII_VALUE  *Result\r
+  )\r
+{\r
+  EFI_STATUS     Status;\r
+  EFI_HII_VALUE  Value[3];\r
+  CHAR16         *String[2];\r
+  UINTN          Count;\r
+  CHAR16         *Delimiter;\r
+  CHAR16         *SubString;\r
+  CHAR16         *StringPtr;\r
+  UINTN          Index;\r
+\r
+  if ((FormSet == NULL) || (Result == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  ZeroMem (Value, sizeof (Value));\r
+\r
+  Status = PopExpression (&Value[0]);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = PopExpression (&Value[1]);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = PopExpression (&Value[2]);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
+    Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  Count = (UINTN)Value[0].Value.u64;\r
+\r
+  //\r
+  // String[0] - Delimiter\r
+  // String[1] - The string to search\r
+  //\r
+  String[0] = NULL;\r
+  String[1] = NULL;\r
+  for (Index = 0; Index < 2; Index++) {\r
+    if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {\r
+      Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+      Status       = EFI_SUCCESS;\r
+      goto Done;\r
+    }\r
+\r
+    String[Index] = GetTokenString (Value[Index + 1].Value.string, FormSet->HiiHandle);\r
+    if (String[Index] == NULL) {\r
+      Status = EFI_NOT_FOUND;\r
+      goto Done;\r
+    }\r
+  }\r
+\r
+  Delimiter = String[0];\r
+  SubString = String[1];\r
+  while (Count > 0) {\r
+    SubString = StrStr (SubString, Delimiter);\r
+    if (SubString != NULL) {\r
+      //\r
+      // Skip over the delimiter\r
+      //\r
+      SubString = SubString + StrLen (Delimiter);\r
+    } else {\r
+      break;\r
+    }\r
+\r
+    Count--;\r
+  }\r
+\r
+  if (SubString == NULL) {\r
+    //\r
+    // nth delimited sub-string not found, push an empty string\r
+    //\r
+    SubString = gEmptyString;\r
+  } else {\r
+    //\r
+    // Put a NULL terminator for nth delimited sub-string\r
+    //\r
+    StringPtr = StrStr (SubString, Delimiter);\r
+    if (StringPtr != NULL) {\r
+      *StringPtr = L'\0';\r
+    }\r
+  }\r
+\r
+  Result->Type         = EFI_IFR_TYPE_STRING;\r
+  Result->Value.string = NewHiiString (SubString, FormSet->HiiHandle);\r
+\r
+Done:\r
+  if (String[0] != NULL) {\r
+    FreePool (String[0]);\r
+  }\r
+\r
+  if (String[1] != NULL) {\r
+    FreePool (String[1]);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Evaluate opcode EFI_IFR_SPAN.\r
+\r
+  @param[in]  FormSet            Formset which contains this opcode.\r
+  @param[in]  Flags              FIRST_MATCHING or FIRST_NON_MATCHING.\r
+  @param[out] Result             Evaluation result for this opcode.\r
+\r
+  @retval EFI_SUCCESS            Opcode evaluation success.\r
+  @retval Other                  Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrSpan (\r
+  IN  HII_FORMSET    *FormSet,\r
+  IN  UINT8          Flags,\r
+  OUT EFI_HII_VALUE  *Result\r
+  )\r
+{\r
+  EFI_STATUS     Status;\r
+  EFI_HII_VALUE  Value[3];\r
+  CHAR16         *String[2];\r
+  CHAR16         *Charset;\r
+  UINTN          Base;\r
+  UINTN          Index;\r
+  CHAR16         *StringPtr;\r
+  BOOLEAN        Found;\r
+\r
+  if ((FormSet == NULL) || (Result == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  ZeroMem (Value, sizeof (Value));\r
+\r
+  Status = PopExpression (&Value[0]);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = PopExpression (&Value[1]);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = PopExpression (&Value[2]);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
+    Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  Base = (UINTN)Value[0].Value.u64;\r
+\r
+  //\r
+  // String[0] - Charset\r
+  // String[1] - The string to search\r
+  //\r
+  String[0] = NULL;\r
+  String[1] = NULL;\r
+  for (Index = 0; Index < 2; Index++) {\r
+    if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {\r
+      Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+      Status       = EFI_SUCCESS;\r
+      goto Done;\r
+    }\r
+\r
+    String[Index] = GetTokenString (Value[Index + 1].Value.string, FormSet->HiiHandle);\r
+    if (String[Index] == NULL) {\r
+      Status = EFI_NOT_FOUND;\r
+      goto Done;\r
+    }\r
+  }\r
+\r
+  if (Base >= StrLen (String[1])) {\r
+    Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+    Status       = EFI_SUCCESS;\r
+    goto Done;\r
+  }\r
+\r
+  Found     = FALSE;\r
+  StringPtr = String[1] + Base;\r
+  Charset   = String[0];\r
+  while (*StringPtr != 0 && !Found) {\r
+    Index = 0;\r
+    while (Charset[Index] != 0) {\r
+      if ((*StringPtr >= Charset[Index]) && (*StringPtr <= Charset[Index + 1])) {\r
+        if (Flags == EFI_IFR_FLAGS_FIRST_MATCHING) {\r
+          Found = TRUE;\r
+          break;\r
+        }\r
+      } else {\r
+        if (Flags == EFI_IFR_FLAGS_FIRST_NON_MATCHING) {\r
+          Found = TRUE;\r
+          break;\r
+        }\r
+      }\r
+\r
+      //\r
+      // Skip characters pair representing low-end of a range and high-end of a range\r
+      //\r
+      Index += 2;\r
+    }\r
+\r
+    if (!Found) {\r
+      StringPtr++;\r
+    }\r
+  }\r
+\r
+  Result->Type      = EFI_IFR_TYPE_NUM_SIZE_64;\r
+  Result->Value.u64 = StringPtr - String[1];\r
+\r
+Done:\r
+  if (String[0] != NULL) {\r
+    FreePool (String[0]);\r
+  }\r
+\r
+  if (String[1] != NULL) {\r
+    FreePool (String[1]);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Get Expression given its RuleId.\r
+\r
+  @param[in]  Form               The form which contains this Expression.\r
+  @param[in]  RuleId             Id of this Expression.\r
+\r
+  @retval Pointer                The Expression.\r
+  @retval NULL                   Specified Expression not found in the form.\r
+\r
+**/\r
+HII_EXPRESSION *\r
+RuleIdToExpression (\r
+  IN HII_FORM  *Form,\r
+  IN UINT8     RuleId\r
+  )\r
+{\r
+  LIST_ENTRY      *Link;\r
+  HII_EXPRESSION  *Expression;\r
+\r
+  if (Form == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  Link = GetFirstNode (&Form->RuleListHead);\r
+  while (!IsNull (&Form->RuleListHead, Link)) {\r
+    Expression = HII_EXPRESSION_FROM_LINK (Link);\r
+\r
+    if ((Expression->Type == EFI_HII_EXPRESSION_RULE) && (Expression->ExtraData.RuleId == RuleId)) {\r
+      return Expression;\r
+    }\r
+\r
+    Link = GetNextNode (&Form->RuleListHead, Link);\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Locate the Unicode Collation Protocol interface for later use.\r
+\r
+  @retval EFI_SUCCESS            Protocol interface initialize success.\r
+  @retval Other                  Protocol interface initialize failed.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeUnicodeCollationProtocol (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  if (mUnicodeCollation != NULL) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // BUGBUG: Proper implementation is to locate all Unicode Collation Protocol\r
+  // instances first and then select one which support English language.\r
+  // Current implementation just pick the first instance.\r
+  //\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiUnicodeCollation2ProtocolGuid,\r
+                  NULL,\r
+                  (VOID **)&mUnicodeCollation\r
+                  );\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Check whether the formset guid is in this Hii package list.\r
+\r
+  @param[in]  HiiHandle          The HiiHandle for this HII package list.\r
+  @param[in]  FormSetGuid        The formset guid for the request formset.\r
+\r
+  @retval TRUE                   Find the formset guid.\r
+  @retval FALSE                  Not found the formset guid.\r
+\r
+**/\r
+BOOLEAN\r
+IsFormsetGuidInHiiHandle (\r
+  IN EFI_HII_HANDLE  HiiHandle,\r
+  IN EFI_GUID        *FormSetGuid\r
+  )\r
+{\r
+  EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;\r
+  UINTN                        BufferSize;\r
+  UINT32                       Offset;\r
+  UINT32                       Offset2;\r
+  UINT32                       PackageListLength;\r
+  EFI_HII_PACKAGE_HEADER       *PackageHeader;\r
+  UINT8                        *Package;\r
+  UINT8                        *OpCodeData;\r
+  EFI_STATUS                   Status;\r
+  BOOLEAN                      FindGuid;\r
+  EFI_HII_DATABASE_PROTOCOL    *HiiDatabase;\r
+\r
+  if (FormSetGuid == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  BufferSize     = 0;\r
+  HiiPackageList = NULL;\r
+  FindGuid       = FALSE;\r
+\r
+  //\r
+  // Locate required Hii Database protocol\r
+  //\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiHiiDatabaseProtocolGuid,\r
+                  NULL,\r
+                  (VOID **)&HiiDatabase\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+\r
+  Status = HiiDatabase->ExportPackageLists (HiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    HiiPackageList = AllocatePool (BufferSize);\r
+    if (HiiPackageList == NULL) {\r
+      ASSERT (HiiPackageList != NULL);\r
+      return FALSE;\r
+    }\r
+\r
+    Status = HiiDatabase->ExportPackageLists (HiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
+  } else {\r
+    //\r
+    // Fix coverity: 14253 Explicit null dereferenced.\r
+    // When calling ExportPackageLists with BufferSize = 0, only EFI_BUFFER_TOO_SMALL is expected.\r
+    // Otherwise, return FALSE immediately.\r
+    //\r
+    return FALSE;\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    if (HiiPackageList != NULL) {\r
+      FreePool (HiiPackageList);\r
+    }\r
+\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Get Form package from this HII package List\r
+  //\r
+  Offset            = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+  Offset2           = 0;\r
+  PackageListLength = HiiPackageList->PackageLength;\r
+\r
+  while (Offset < PackageListLength) {\r
+    Package       = ((UINT8 *)HiiPackageList) + Offset;\r
+    PackageHeader = (EFI_HII_PACKAGE_HEADER *)Package;\r
+    Offset       += PackageHeader->Length;\r
+\r
+    if (PackageHeader->Type == EFI_HII_PACKAGE_FORMS) {\r
+      //\r
+      // Search FormSet in this Form Package\r
+      //\r
+      Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
+      while (Offset2 < PackageHeader->Length) {\r
+        OpCodeData = Package + Offset2;\r
+\r
+        if (((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
+          if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
+            FindGuid = TRUE;\r
+            break;\r
+          }\r
+        }\r
+\r
+        Offset2 += ((EFI_IFR_OP_HEADER *)OpCodeData)->Length;\r
+      }\r
+    }\r
+\r
+    if (FindGuid) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  FreePool (HiiPackageList);\r
+\r
+  return FindGuid;\r
+}\r
+\r
+/**\r
+  Find HII Handle in the HII database associated with given Device Path.\r
+\r
+  If DevicePath is NULL, then ASSERT.\r
+\r
+  @param[in]  DevicePath         Device Path associated with the HII package list\r
+                                 handle.\r
+  @param[in]  FormsetGuid        The formset guid for this formset.\r
+\r
+  @retval Handle                 HII package list Handle associated with the Device\r
+                                        Path.\r
+  @retval NULL                   Hii Package list handle is not found.\r
+\r
+**/\r
+EFI_HII_HANDLE\r
+DevicePathToHiiHandle (\r
+  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath,\r
+  IN EFI_GUID                  *FormsetGuid\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+  EFI_DEVICE_PATH_PROTOCOL   *TmpDevicePath;\r
+  UINTN                      Index;\r
+  EFI_HANDLE                 Handle;\r
+  EFI_HANDLE                 DriverHandle;\r
+  EFI_HII_HANDLE             *HiiHandles;\r
+  EFI_HII_HANDLE             HiiHandle;\r
+  EFI_HII_DATABASE_PROTOCOL  *HiiDatabase;\r
+\r
+  if ((DevicePath == NULL) || (FormsetGuid == NULL)) {\r
+    return NULL;\r
+  }\r
+\r
+  TmpDevicePath = DevicePath;\r
+  //\r
+  // Locate Device Path Protocol handle buffer\r
+  //\r
+  Status = gBS->LocateDevicePath (\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  &TmpDevicePath,\r
+                  &DriverHandle\r
+                  );\r
+  if (EFI_ERROR (Status) || !IsDevicePathEnd (TmpDevicePath)) {\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Locate required Hii Database protocol\r
+  //\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiHiiDatabaseProtocolGuid,\r
+                  NULL,\r
+                  (VOID **)&HiiDatabase\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Retrieve all HII Handles from HII database\r
+  //\r
+  HiiHandles = HiiGetHiiHandles (NULL);\r
+  if (HiiHandles == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Search Hii Handle by Driver Handle\r
+  //\r
+  HiiHandle = NULL;\r
+  for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
+    Status = HiiDatabase->GetPackageListHandle (\r
+                            HiiDatabase,\r
+                            HiiHandles[Index],\r
+                            &Handle\r
+                            );\r
+    if (!EFI_ERROR (Status) && (Handle == DriverHandle)) {\r
+      if (IsFormsetGuidInHiiHandle (HiiHandles[Index], FormsetGuid)) {\r
+        HiiHandle = HiiHandles[Index];\r
+        break;\r
+      }\r
+\r
+      if (HiiHandle != NULL) {\r
+        break;\r
+      }\r
+    }\r
+  }\r
+\r
+  FreePool (HiiHandles);\r
+  return HiiHandle;\r
+}\r
+\r
+/**\r
+  Get question value from the predefined formset.\r
+\r
+  @param[in]  DevicePath         The driver's device path which produce the formset data.\r
+  @param[in]  InputHiiHandle     The hii handle associate with the formset data.\r
+  @param[in]  FormSetGuid        The formset guid which include the question.\r
+  @param[in]  QuestionId         The question id which need to get value from.\r
+  @param[out] Value              The return data about question's value.\r
+\r
+  @retval TRUE                   Get the question value success.\r
+  @retval FALSE                  Get the question value failed.\r
+**/\r
+BOOLEAN\r
+GetQuestionValueFromForm (\r
+  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath,\r
+  IN EFI_HII_HANDLE            InputHiiHandle,\r
+  IN EFI_GUID                  *FormSetGuid,\r
+  IN EFI_QUESTION_ID           QuestionId,\r
+  OUT EFI_HII_VALUE            *Value\r
+  )\r
+{\r
+  EFI_STATUS      Status;\r
+  EFI_HII_HANDLE  HiiHandle;\r
+  HII_STATEMENT   *Question;\r
+  HII_FORMSET     *FormSet;\r
+  HII_FORM        *Form;\r
+  BOOLEAN         GetTheVal;\r
+  LIST_ENTRY      *Link;\r
+\r
+  //\r
+  // The input parameter DevicePath or InputHiiHandle must have one valid input.\r
+  //\r
+  if ((DevicePath == NULL) && (InputHiiHandle == NULL)) {\r
+    ASSERT (\r
+      (DevicePath != NULL && InputHiiHandle == NULL) ||\r
+      (DevicePath == NULL && InputHiiHandle != NULL)\r
+      );\r
+    return FALSE;\r
+  }\r
+\r
+  if ((FormSetGuid == NULL) || (Value == NULL)) {\r
+    return FALSE;\r
+  }\r
+\r
+  GetTheVal = TRUE;\r
+  HiiHandle = NULL;\r
+  Question  = NULL;\r
+  Form      = NULL;\r
+\r
+  //\r
+  // Get HiiHandle.\r
+  //\r
+  if (DevicePath != NULL) {\r
+    HiiHandle = DevicePathToHiiHandle (DevicePath, FormSetGuid);\r
+    if (HiiHandle == NULL) {\r
+      return FALSE;\r
+    }\r
+  } else {\r
+    HiiHandle = InputHiiHandle;\r
+  }\r
+\r
+  ASSERT (HiiHandle != NULL);\r
+\r
+  //\r
+  // Get the formset data include this question.\r
+  //\r
+  FormSet = AllocateZeroPool (sizeof (HII_FORMSET));\r
+  ASSERT (FormSet != NULL);\r
+\r
+  Status = CreateFormSetFromHiiHandle (HiiHandle, FormSetGuid, FormSet);\r
+  if (EFI_ERROR (Status)) {\r
+    GetTheVal = FALSE;\r
+    goto Done;\r
+  }\r
+\r
+  InitializeFormSet (FormSet);\r
+\r
+  //\r
+  // Base on the Question Id to get the question info.\r
+  //\r
+  Question = QuestionIdInFormset (FormSet, NULL, QuestionId);\r
+  if (Question == NULL) {\r
+    GetTheVal = FALSE;\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // Search form in the formset scope\r
+  //\r
+  Link = GetFirstNode (&FormSet->FormListHead);\r
+  while (!IsNull (&FormSet->FormListHead, Link)) {\r
+    Form = HII_FORM_FROM_LINK (Link);\r
+\r
+    Question = QuestionIdInForm (Form, QuestionId);\r
+    if (Question != NULL) {\r
+      break;\r
+    }\r
+\r
+    Link = GetNextNode (&FormSet->FormListHead, Link);\r
+    Form = NULL;\r
+  }\r
+\r
+  ASSERT (Form != NULL);\r
+\r
+  //\r
+  // Get the question value.\r
+  //\r
+  Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);\r
+  if (EFI_ERROR (Status)) {\r
+    GetTheVal = FALSE;\r
+    goto Done;\r
+  }\r
+\r
+  CopyMem (Value, &Question->Value, sizeof (EFI_HII_VALUE));\r
+\r
+Done:\r
+  //\r
+  // Clean the formset structure and restore the global parameter.\r
+  //\r
+  if (FormSet != NULL) {\r
+    DestroyFormSet (FormSet);\r
+  }\r
+\r
+  return GetTheVal;\r
+}\r
+\r
+/**\r
+  Covert HII_STATEMENT_VALUE to EFI_HII_VALUE.\r
+\r
+  The HiiValue->Buffer is allocated from EFI boot services memory. It is the\r
+  responsibility of the caller to free the memory allocated.\r
+\r
+  @param[in]  StatementValue     Source to be converted.\r
+  @param[out] HiiValue           The buffer that is converted from StatementValue\r
+\r
+  @retval EFI_SUCCESS            Convert successfully.\r
+  @retval EFI_INVALID_PARAMETER  StatementValue is NULL or HiiValue is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+HiiStatementValueToHiiValue (\r
+  IN  HII_STATEMENT_VALUE  *StatementValue,\r
+  OUT EFI_HII_VALUE        *HiiValue\r
+  )\r
+{\r
+  if ((StatementValue == NULL) || (HiiValue == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  ZeroMem (HiiValue, sizeof (EFI_HII_VALUE));\r
+\r
+  HiiValue->Type      = StatementValue->Type;\r
+  HiiValue->BufferLen = StatementValue->BufferLen;\r
+  if ((StatementValue->Buffer != NULL) && (StatementValue->BufferLen > 0)) {\r
+    HiiValue->Buffer = AllocateCopyPool (HiiValue->BufferLen, StatementValue->Buffer);\r
+  }\r
+\r
+  CopyMem (&HiiValue->Value, &StatementValue->Value, sizeof (EFI_IFR_TYPE_VALUE));\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Release the buffer in EFI_HII_VALUE if the buffer is not NULL.\r
+\r
+  @param[in] HiiValue           The buffer to be released.\r
+\r
+  @retval EFI_SUCCESS            release HiiValue successfully.\r
+  @retval EFI_INVALID_PARAMETER  HiiValue is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+ReleaseHiiValue (\r
+  IN EFI_HII_VALUE  *HiiValue\r
+  )\r
+{\r
+  if (HiiValue == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (HiiValue->Buffer == NULL) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  FreePool (HiiValue->Buffer);\r
+  ZeroMem (HiiValue, sizeof (EFI_HII_VALUE));\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Evaluate the result of a HII expression.\r
+\r
+  If Expression is NULL, then ASSERT.\r
+\r
+  @param[in]      FormSet        FormSet associated with this expression.\r
+  @param[in]      Form           Form associated with this expression.\r
+  @param[in,out]  Expression     Expression to be evaluated.\r
+\r
+  @retval EFI_SUCCESS            The expression evaluated successfully.\r
+  @retval EFI_NOT_FOUND          The Question which referenced by a QuestionId\r
+                                 could not be found.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the\r
+                                 stack.\r
+  @retval EFI_ACCESS_DENIED      The pop operation underflowed the stack.\r
+  @retval EFI_INVALID_PARAMETER  Syntax error with the Expression.\r
+  @retval EFI_INVALID_PARAMETER  Formset, Form or Expression is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EvaluateHiiExpression (\r
+  IN     HII_FORMSET     *FormSet,\r
+  IN     HII_FORM        *Form,\r
+  IN OUT HII_EXPRESSION  *Expression\r
+  )\r
+{\r
+  EFI_STATUS                          Status;\r
+  LIST_ENTRY                          *Link;\r
+  HII_EXPRESSION_OPCODE               *OpCode;\r
+  HII_STATEMENT                       *Question;\r
+  HII_STATEMENT                       *Question2;\r
+  UINT16                              Index;\r
+  EFI_HII_VALUE                       Data1;\r
+  EFI_HII_VALUE                       Data2;\r
+  EFI_HII_VALUE                       Data3;\r
+  HII_EXPRESSION                      *RuleExpression;\r
+  EFI_HII_VALUE                       *Value;\r
+  INTN                                Result;\r
+  CHAR16                              *StrPtr;\r
+  CHAR16                              *NameValue;\r
+  UINT32                              TempValue;\r
+  LIST_ENTRY                          *SubExpressionLink;\r
+  HII_EXPRESSION                      *SubExpression;\r
+  UINTN                               StackOffset;\r
+  UINTN                               TempLength;\r
+  CHAR16                              TempStr[5];\r
+  UINT8                               DigitUint8;\r
+  UINT8                               *TempBuffer;\r
+  EFI_TIME                            EfiTime;\r
+  EFI_HII_VALUE                       QuestionVal;\r
+  EFI_DEVICE_PATH_PROTOCOL            *DevicePath;\r
+  EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL  *PathFromText;\r
+\r
+  if ((FormSet == NULL) || (Form == NULL) || (Expression == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  StrPtr       = NULL;\r
+  DevicePath   = NULL;\r
+  PathFromText = NULL;\r
+\r
+  //\r
+  // Save current stack offset.\r
+  //\r
+  StackOffset = SaveExpressionEvaluationStackOffset ();\r
+\r
+  ASSERT (Expression != NULL);\r
+  Expression->Result.Type = EFI_IFR_TYPE_OTHER;\r
+\r
+  Link = GetFirstNode (&Expression->OpCodeListHead);\r
+  while (!IsNull (&Expression->OpCodeListHead, Link)) {\r
+    OpCode = HII_EXPRESSION_OPCODE_FROM_LINK (Link);\r
+\r
+    Link = GetNextNode (&Expression->OpCodeListHead, Link);\r
+\r
+    ZeroMem (&Data1, sizeof (EFI_HII_VALUE));\r
+    ZeroMem (&Data2, sizeof (EFI_HII_VALUE));\r
+    ZeroMem (&Data3, sizeof (EFI_HII_VALUE));\r
+\r
+    Value       = &Data3;\r
+    Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
+    Status      = EFI_SUCCESS;\r
+\r
+    switch (OpCode->Operand) {\r
+      //\r
+      // Built-in functions\r
+      //\r
+      case EFI_IFR_EQ_ID_VAL_OP:\r
+        Question = QuestionIdInFormset (FormSet, Form, OpCode->ExtraData.EqIdValData.QuestionId);\r
+        if (Question == NULL) {\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          break;\r
+        }\r
+\r
+        //\r
+        // Load value from storage.\r
+        //\r
+        Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);\r
+        if (EFI_ERROR (Status)) {\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          break;\r
+        }\r
+\r
+        Status = HiiStatementValueToHiiValue (&Question->Value, &Data1);\r
+        if (EFI_ERROR (Status)) {\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          break;\r
+        }\r
+\r
+        Status = CompareHiiValue (&Data1, &OpCode->ExtraData.EqIdValData.Value, &Result, NULL);\r
+        ReleaseHiiValue (&Data1);\r
+        if (Status == EFI_UNSUPPORTED) {\r
+          Status      = EFI_SUCCESS;\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          break;\r
+        }\r
+\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
+\r
+        Value->Value.b = (BOOLEAN)((Result == 0) ? TRUE : FALSE);\r
+        break;\r
+\r
+      case EFI_IFR_EQ_ID_ID_OP:\r
+        Question = QuestionIdInFormset (FormSet, Form, OpCode->ExtraData.EqIdIdData.QuestionId1);\r
+        if (Question == NULL) {\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          break;\r
+        }\r
+\r
+        //\r
+        // Load value from storage.\r
+        //\r
+        Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);\r
+        if (EFI_ERROR (Status)) {\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          break;\r
+        }\r
+\r
+        Status = HiiStatementValueToHiiValue (&Question->Value, &Data1);\r
+        if (EFI_ERROR (Status)) {\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          break;\r
+        }\r
+\r
+        Question2 = QuestionIdInFormset (FormSet, Form, OpCode->ExtraData.EqIdIdData.QuestionId2);\r
+        if (Question2 == NULL) {\r
+          ReleaseHiiValue (&Data1);\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          break;\r
+        }\r
+\r
+        //\r
+        // Load value from storage.\r
+        //\r
+        Status = GetQuestionValue (FormSet, Form, Question2, GetSetValueWithBuffer);\r
+        if (EFI_ERROR (Status)) {\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          break;\r
+        }\r
+\r
+        Status = HiiStatementValueToHiiValue (&Question2->Value, &Data2);\r
+        if (EFI_ERROR (Status)) {\r
+          ReleaseHiiValue (&Data1);\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          break;\r
+        }\r
+\r
+        Status = CompareHiiValue (&Data1, &Data2, &Result, FormSet->HiiHandle);\r
+        ReleaseHiiValue (&Data1);\r
+        ReleaseHiiValue (&Data2);\r
+        if (Status == EFI_UNSUPPORTED) {\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          Status      = EFI_SUCCESS;\r
+          break;\r
+        }\r
+\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
+\r
+        Value->Value.b = (BOOLEAN)((Result == 0) ? TRUE : FALSE);\r
+        break;\r
+\r
+      case EFI_IFR_EQ_ID_VAL_LIST_OP:\r
+        Question = QuestionIdInFormset (FormSet, Form, OpCode->ExtraData.EqIdListData.QuestionId);\r
+        if (Question == NULL) {\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          break;\r
+        }\r
+\r
+        //\r
+        // Load value from storage.\r
+        //\r
+        Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);\r
+        if (EFI_ERROR (Status)) {\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          break;\r
+        }\r
+\r
+        Value->Value.b = FALSE;\r
+        for (Index = 0; Index < OpCode->ExtraData.EqIdListData.ListLength; Index++) {\r
+          if (Question->Value.Value.u16 == OpCode->ExtraData.EqIdListData.ValueList[Index]) {\r
+            Value->Value.b = TRUE;\r
+            break;\r
+          }\r
+        }\r
+\r
+        break;\r
+\r
+      case EFI_IFR_DUP_OP:\r
+        Status = PopExpression (Value);\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
+\r
+        Status = PushExpression (Value);\r
+        break;\r
+\r
+      case EFI_IFR_QUESTION_REF1_OP:\r
+      case EFI_IFR_THIS_OP:\r
+        Question = QuestionIdInFormset (FormSet, Form, OpCode->ExtraData.QuestionRef1Data.QuestionId);\r
+        if (Question == NULL) {\r
+          Status = EFI_NOT_FOUND;\r
+          goto Done;\r
+        }\r
+\r
+        //\r
+        // Load value from storage.\r
+        //\r
+        Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
+\r
+        Value = (EFI_HII_VALUE *)&Question->Value;\r
+        break;\r
+\r
+      case EFI_IFR_SECURITY_OP:\r
+        Value->Value.b = CheckUserPrivilege (&OpCode->ExtraData.Guid);\r
+        break;\r
+\r
+      case EFI_IFR_GET_OP:\r
+        //\r
+        // Get Value from VarStore buffer, EFI VarStore, Name/Value VarStore.\r
+        //\r
+        Value->Type     = EFI_IFR_TYPE_UNDEFINED;\r
+        Value->Value.u8 = 0;\r
+        if (OpCode->ExtraData.GetSetData.VarStorage != NULL) {\r
+          switch (OpCode->ExtraData.GetSetData.VarStorage->Type) {\r
+            case EFI_HII_VARSTORE_BUFFER:\r
+            case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
+              //\r
+              // Get value from Edit Buffer\r
+              //\r
+              Value->Type = OpCode->ExtraData.GetSetData.ValueType;\r
+              CopyMem (&Value->Value, OpCode->ExtraData.GetSetData.VarStorage->EditBuffer + OpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset, OpCode->ExtraData.GetSetData.ValueWidth);\r
+              break;\r
+            case EFI_HII_VARSTORE_NAME_VALUE:\r
+              if (OpCode->ExtraData.GetSetData.ValueType != EFI_IFR_TYPE_STRING) {\r
+                //\r
+                // Get value from string except for STRING value.\r
+                //\r
+                Status = GetValueByName (OpCode->ExtraData.GetSetData.VarStorage, OpCode->ExtraData.GetSetData.ValueName, &StrPtr);\r
+                if (!EFI_ERROR (Status)) {\r
+                  ASSERT (StrPtr != NULL);\r
+                  TempLength = StrLen (StrPtr);\r
+                  if (OpCode->ExtraData.GetSetData.ValueWidth >= ((TempLength + 1) / 2)) {\r
+                    Value->Type = OpCode->ExtraData.GetSetData.ValueType;\r
+                    TempBuffer  = (UINT8 *)&Value->Value;\r
+                    ZeroMem (TempStr, sizeof (TempStr));\r
+                    for (Index = 0; Index < TempLength; Index++) {\r
+                      TempStr[0] = StrPtr[TempLength - Index - 1];\r
+                      DigitUint8 = (UINT8)StrHexToUint64 (TempStr);\r
+                      if ((Index & 1) == 0) {\r
+                        TempBuffer[Index/2] = DigitUint8;\r
+                      } else {\r
+                        TempBuffer[Index/2] = (UINT8)((DigitUint8 << 4) + TempBuffer[Index/2]);\r
+                      }\r
+                    }\r
+                  }\r
+                }\r
+              }\r
+\r
+              break;\r
+            case EFI_HII_VARSTORE_EFI_VARIABLE:\r
+              //\r
+              // Get value from variable.\r
+              //\r
+              TempLength  = OpCode->ExtraData.GetSetData.ValueWidth;\r
+              Value->Type = OpCode->ExtraData.GetSetData.ValueType;\r
+              Status      = gRT->GetVariable (\r
+                                   OpCode->ExtraData.GetSetData.ValueName,\r
+                                   &OpCode->ExtraData.GetSetData.VarStorage->Guid,\r
+                                   NULL,\r
+                                   &TempLength,\r
+                                   &Value->Value\r
+                                   );\r
+              if (EFI_ERROR (Status)) {\r
+                Value->Type     = EFI_IFR_TYPE_UNDEFINED;\r
+                Value->Value.u8 = 0;\r
+              }\r
+\r
+              break;\r
+            default:\r
+              //\r
+              // Not recognize storage.\r
+              //\r
+              Status = EFI_UNSUPPORTED;\r
+              goto Done;\r
+          }\r
+        } else {\r
+          //\r
+          // For Time/Date Data\r
+          //\r
+          if ((OpCode->ExtraData.GetSetData.ValueType != EFI_IFR_TYPE_DATE) && (OpCode->ExtraData.GetSetData.ValueType != EFI_IFR_TYPE_TIME)) {\r
+            //\r
+            // Only support Data/Time data when storage doesn't exist.\r
+            //\r
+            Status = EFI_UNSUPPORTED;\r
+            goto Done;\r
+          }\r
+\r
+          Status = gRT->GetTime (&EfiTime, NULL);\r
+          if (!EFI_ERROR (Status)) {\r
+            if (OpCode->ExtraData.GetSetData.ValueType == EFI_IFR_TYPE_DATE) {\r
+              switch (OpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset) {\r
+                case 0x00:\r
+                  Value->Type      = EFI_IFR_TYPE_NUM_SIZE_16;\r
+                  Value->Value.u16 = EfiTime.Year;\r
+                  break;\r
+                case 0x02:\r
+                  Value->Type     = EFI_IFR_TYPE_NUM_SIZE_8;\r
+                  Value->Value.u8 = EfiTime.Month;\r
+                  break;\r
+                case 0x03:\r
+                  Value->Type     = EFI_IFR_TYPE_NUM_SIZE_8;\r
+                  Value->Value.u8 = EfiTime.Day;\r
+                  break;\r
+                default:\r
+                  //\r
+                  // Invalid Date field.\r
+                  //\r
+                  Status = EFI_INVALID_PARAMETER;\r
+                  goto Done;\r
+              }\r
+            } else {\r
+              switch (OpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset) {\r
+                case 0x00:\r
+                  Value->Type     = EFI_IFR_TYPE_NUM_SIZE_8;\r
+                  Value->Value.u8 = EfiTime.Hour;\r
+                  break;\r
+                case 0x01:\r
+                  Value->Type     = EFI_IFR_TYPE_NUM_SIZE_8;\r
+                  Value->Value.u8 = EfiTime.Minute;\r
+                  break;\r
+                case 0x02:\r
+                  Value->Type     = EFI_IFR_TYPE_NUM_SIZE_8;\r
+                  Value->Value.u8 = EfiTime.Second;\r
+                  break;\r
+                default:\r
+                  //\r
+                  // Invalid Time field.\r
+                  //\r
+                  Status = EFI_INVALID_PARAMETER;\r
+                  goto Done;\r
+              }\r
+            }\r
+          }\r
+        }\r
+\r
+        break;\r
+\r
+      case EFI_IFR_QUESTION_REF3_OP:\r
+        //\r
+        // EFI_IFR_QUESTION_REF3\r
+        // Pop an expression from the expression stack\r
+        //\r
+        Status = PopExpression (Value);\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
+\r
+        //\r
+        // Validate the expression value\r
+        //\r
+        if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          break;\r
+        }\r
+\r
+        if (OpCode->ExtraData.QuestionRef3Data.DevicePath != 0) {\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+\r
+          Status = gBS->LocateProtocol (\r
+                          &gEfiDevicePathFromTextProtocolGuid,\r
+                          NULL,\r
+                          (VOID **)&PathFromText\r
+                          );\r
+          if (EFI_ERROR (Status)) {\r
+            goto Done;\r
+          }\r
+\r
+          StrPtr = GetTokenString (OpCode->ExtraData.QuestionRef3Data.DevicePath, FormSet->HiiHandle);\r
+          if ((StrPtr != NULL) && (PathFromText != NULL)) {\r
+            DevicePath = PathFromText->ConvertTextToDevicePath (StrPtr);\r
+            if ((DevicePath != NULL) && GetQuestionValueFromForm (DevicePath, NULL, &OpCode->ExtraData.Guid, Value->Value.u16, &QuestionVal)) {\r
+              Value = &QuestionVal;\r
+            }\r
+\r
+            if (DevicePath != NULL) {\r
+              FreePool (DevicePath);\r
+            }\r
+          }\r
+\r
+          if (StrPtr != NULL) {\r
+            FreePool (StrPtr);\r
+          }\r
+        } else if (IsZeroGuid (&OpCode->ExtraData.Guid)) {\r
+          if (!GetQuestionValueFromForm (NULL, FormSet->HiiHandle, &OpCode->ExtraData.Guid, Value->Value.u16, &QuestionVal)) {\r
+            Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+            break;\r
+          }\r
+\r
+          Value = &QuestionVal;\r
+        } else {\r
+          Question = QuestionIdInFormset (FormSet, Form, Value->Value.u16);\r
+          if (Question == NULL) {\r
+            Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+            break;\r
+          }\r
+\r
+          //\r
+          // Load value from storage.\r
+          //\r
+          Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);\r
+          if (EFI_ERROR (Status)) {\r
+            Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+            break;\r
+          }\r
+\r
+          //\r
+          // push the questions' value on to the expression stack\r
+          //\r
+          Value = (EFI_HII_VALUE *)&Question->Value;\r
+        }\r
+\r
+        break;\r
+\r
+      case EFI_IFR_RULE_REF_OP:\r
+        //\r
+        // Find expression for this rule\r
+        //\r
+        RuleExpression = RuleIdToExpression (Form, OpCode->ExtraData.RuleId);\r
+        if (RuleExpression == NULL) {\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          break;\r
+        }\r
+\r
+        //\r
+        // Evaluate this rule expression\r
+        //\r
+        Status = EvaluateHiiExpression (FormSet, Form, RuleExpression);\r
+        if (EFI_ERROR (Status) || (RuleExpression->Result.Type == EFI_IFR_TYPE_UNDEFINED)) {\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          break;\r
+        }\r
+\r
+        Value = &RuleExpression->Result;\r
+        break;\r
+\r
+      case EFI_IFR_STRING_REF1_OP:\r
+        Value->Type         = EFI_IFR_TYPE_STRING;\r
+        Value->Value.string = OpCode->ExtraData.Value.Value.string;\r
+        break;\r
+\r
+      //\r
+      // Constant\r
+      //\r
+      case EFI_IFR_TRUE_OP:\r
+      case EFI_IFR_FALSE_OP:\r
+      case EFI_IFR_ONE_OP:\r
+      case EFI_IFR_ONES_OP:\r
+      case EFI_IFR_UINT8_OP:\r
+      case EFI_IFR_UINT16_OP:\r
+      case EFI_IFR_UINT32_OP:\r
+      case EFI_IFR_UINT64_OP:\r
+      case EFI_IFR_UNDEFINED_OP:\r
+      case EFI_IFR_VERSION_OP:\r
+      case EFI_IFR_ZERO_OP:\r
+        Value = &OpCode->ExtraData.Value;\r
+        break;\r
+\r
+      //\r
+      // unary-op\r
+      //\r
+      case EFI_IFR_LENGTH_OP:\r
+        Status = PopExpression (Value);\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
+\r
+        if ((Value->Type != EFI_IFR_TYPE_STRING) && !IsTypeInBuffer (Value)) {\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          break;\r
+        }\r
+\r
+        if (Value->Type == EFI_IFR_TYPE_STRING) {\r
+          StrPtr = GetTokenString (Value->Value.string, FormSet->HiiHandle);\r
+          if (StrPtr == NULL) {\r
+            Status = EFI_INVALID_PARAMETER;\r
+            goto Done;\r
+          }\r
+\r
+          Value->Type      = EFI_IFR_TYPE_NUM_SIZE_64;\r
+          Value->Value.u64 = StrLen (StrPtr);\r
+          FreePool (StrPtr);\r
+        } else {\r
+          Value->Type      = EFI_IFR_TYPE_NUM_SIZE_64;\r
+          Value->Value.u64 = GetLengthForValue (Value);\r
+          FreePool (Value->Buffer);\r
+        }\r
+\r
+        break;\r
+\r
+      case EFI_IFR_NOT_OP:\r
+        Status = PopExpression (Value);\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
+\r
+        if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          break;\r
+        }\r
+\r
+        Value->Value.b = (BOOLEAN)(!Value->Value.b);\r
+        break;\r
+\r
+      case EFI_IFR_QUESTION_REF2_OP:\r
+        //\r
+        // Pop an expression from the expression stack\r
+        //\r
+        Status = PopExpression (Value);\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
+\r
+        //\r
+        // Validate the expression value\r
+        //\r
+        if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          break;\r
+        }\r
+\r
+        Question = QuestionIdInFormset (FormSet, Form, Value->Value.u16);\r
+        if (Question == NULL) {\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          break;\r
+        }\r
+\r
+        //\r
+        // Load value from storage.\r
+        //\r
+        Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);\r
+        if (EFI_ERROR (Status)) {\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          break;\r
+        }\r
+\r
+        Value = (EFI_HII_VALUE *)&Question->Value;\r
+        break;\r
+\r
+      case EFI_IFR_STRING_REF2_OP:\r
+        //\r
+        // Pop an expression from the expression stack\r
+        //\r
+        Status = PopExpression (Value);\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
+\r
+        //\r
+        // Validate the expression value\r
+        //\r
+        if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          break;\r
+        }\r
+\r
+        Value->Type = EFI_IFR_TYPE_STRING;\r
+        StrPtr      = GetTokenString (Value->Value.u16, FormSet->HiiHandle);\r
+        if (StrPtr == NULL) {\r
+          //\r
+          // If String not exit, push an empty string\r
+          //\r
+          Value->Value.string = NewHiiString (gEmptyString, FormSet->HiiHandle);\r
+        } else {\r
+          Index               = (UINT16)Value->Value.u64;\r
+          Value->Value.string = Index;\r
+          FreePool (StrPtr);\r
+        }\r
+\r
+        break;\r
+\r
+      case EFI_IFR_TO_BOOLEAN_OP:\r
+        //\r
+        // Pop an expression from the expression stack\r
+        //\r
+        Status = PopExpression (Value);\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
+\r
+        //\r
+        // Convert an expression to a Boolean\r
+        //\r
+        if (Value->Type <= EFI_IFR_TYPE_DATE) {\r
+          //\r
+          // When converting from an unsigned integer, zero will be converted to\r
+          // FALSE and any other value will be converted to TRUE.\r
+          //\r
+          Value->Value.b = (BOOLEAN)(HiiValueToUINT64 (Value) != 0);\r
+\r
+          Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
+        } else if (Value->Type == EFI_IFR_TYPE_STRING) {\r
+          //\r
+          // When converting from a string, if case-insensitive compare\r
+          // with "true" is True, then push True. If a case-insensitive compare\r
+          // with "false" is True, then push False. Otherwise, push Undefined.\r
+          //\r
+          StrPtr = GetTokenString (Value->Value.string, FormSet->HiiHandle);\r
+          if (StrPtr == NULL) {\r
+            Status = EFI_INVALID_PARAMETER;\r
+            goto Done;\r
+          }\r
+\r
+          IfrStrToUpper (StrPtr);\r
+          if (StrCmp (StrPtr, L"TRUE") == 0) {\r
+            Value->Value.b = TRUE;\r
+            Value->Type    = EFI_IFR_TYPE_BOOLEAN;\r
+          } else if (StrCmp (StrPtr, L"FALSE") == 0) {\r
+            Value->Value.b = FALSE;\r
+            Value->Type    = EFI_IFR_TYPE_BOOLEAN;\r
+          } else {\r
+            Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          }\r
+\r
+          FreePool (StrPtr);\r
+        } else if (Value->Type == EFI_IFR_TYPE_BUFFER) {\r
+          //\r
+          // When converting from a buffer, if the buffer is all zeroes,\r
+          // then push False. Otherwise push True.\r
+          //\r
+          for (Index = 0; Index < Value->BufferLen; Index++) {\r
+            if (Value->Buffer[Index] != 0) {\r
+              break;\r
+            }\r
+          }\r
+\r
+          if (Index >= Value->BufferLen) {\r
+            Value->Value.b = FALSE;\r
+          } else {\r
+            Value->Value.b = TRUE;\r
+          }\r
+\r
+          Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
+          FreePool (Value->Buffer);\r
+        }\r
+\r
+        break;\r
+\r
+      case EFI_IFR_TO_STRING_OP:\r
+        Status = IfrToString (FormSet, OpCode->ExtraData.Format, Value);\r
+        break;\r
+\r
+      case EFI_IFR_TO_UINT_OP:\r
+        Status = IfrToUint (FormSet, Value);\r
+        break;\r
+\r
+      case EFI_IFR_TO_LOWER_OP:\r
+      case EFI_IFR_TO_UPPER_OP:\r
+        Status = InitializeUnicodeCollationProtocol ();\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
+\r
+        Status = PopExpression (Value);\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
+\r
+        if (Value->Type != EFI_IFR_TYPE_STRING) {\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          break;\r
+        }\r
+\r
+        StrPtr = GetTokenString (Value->Value.string, FormSet->HiiHandle);\r
+        if (StrPtr == NULL) {\r
+          Status = EFI_NOT_FOUND;\r
+          goto Done;\r
+        }\r
+\r
+        if (OpCode->Operand == EFI_IFR_TO_LOWER_OP) {\r
+          mUnicodeCollation->StrLwr (mUnicodeCollation, StrPtr);\r
+        } else {\r
+          mUnicodeCollation->StrUpr (mUnicodeCollation, StrPtr);\r
+        }\r
+\r
+        Value->Value.string = NewHiiString (StrPtr, FormSet->HiiHandle);\r
+        FreePool (StrPtr);\r
+        break;\r
+\r
+      case EFI_IFR_BITWISE_NOT_OP:\r
+        //\r
+        // Pop an expression from the expression stack\r
+        //\r
+        Status = PopExpression (Value);\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
+\r
+        if (Value->Type > EFI_IFR_TYPE_DATE) {\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          break;\r
+        }\r
+\r
+        Value->Type      = EFI_IFR_TYPE_NUM_SIZE_64;\r
+        Value->Value.u64 = ~HiiValueToUINT64(Value);\r
+        break;\r
+\r
+      case EFI_IFR_SET_OP:\r
+        //\r
+        // Pop an expression from the expression stack\r
+        //\r
+        Status = PopExpression (Value);\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
+\r
+        Data1.Type    = EFI_IFR_TYPE_BOOLEAN;\r
+        Data1.Value.b = FALSE;\r
+        //\r
+        // Set value to var storage buffer\r
+        //\r
+        if (OpCode->ExtraData.GetSetData.VarStorage != NULL) {\r
+          switch (OpCode->ExtraData.GetSetData.VarStorage->Type) {\r
+            case EFI_HII_VARSTORE_BUFFER:\r
+            case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
+              CopyMem (OpCode->ExtraData.GetSetData.VarStorage->EditBuffer + OpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset, &Value->Value, OpCode->ExtraData.GetSetData.ValueWidth);\r
+              Data1.Value.b = TRUE;\r
+              break;\r
+            case EFI_HII_VARSTORE_NAME_VALUE:\r
+              if (OpCode->ExtraData.GetSetData.ValueType != EFI_IFR_TYPE_STRING) {\r
+                NameValue = AllocatePool ((OpCode->ExtraData.GetSetData.ValueWidth * 2 + 1) * sizeof (CHAR16));\r
+                ASSERT (NameValue != NULL);\r
+                //\r
+                // Convert Buffer to Hex String\r
+                //\r
+                TempBuffer = (UINT8 *)&Value->Value + OpCode->ExtraData.GetSetData.ValueWidth - 1;\r
+                StrPtr     = NameValue;\r
+                for (Index = 0; Index < OpCode->ExtraData.GetSetData.ValueWidth; Index++, TempBuffer--) {\r
+                  UnicodeValueToStringS (\r
+                    StrPtr,\r
+                    (OpCode->ExtraData.GetSetData.ValueWidth * 2 + 1) * sizeof (CHAR16) - ((UINTN)StrPtr - (UINTN)NameValue),\r
+                    PREFIX_ZERO | RADIX_HEX,\r
+                    *TempBuffer,\r
+                    2\r
+                    );\r
+                  StrPtr += StrnLenS (StrPtr, OpCode->ExtraData.GetSetData.ValueWidth * 2 + 1 - ((UINTN)StrPtr - (UINTN)NameValue) / sizeof (CHAR16));\r
+                }\r
+\r
+                Status = SetValueByName (OpCode->ExtraData.GetSetData.VarStorage, OpCode->ExtraData.GetSetData.ValueName, NameValue, NULL);\r
+                FreePool (NameValue);\r
+                if (!EFI_ERROR (Status)) {\r
+                  Data1.Value.b = TRUE;\r
+                }\r
+              }\r
+\r
+              break;\r
+            case EFI_HII_VARSTORE_EFI_VARIABLE:\r
+              Status = gRT->SetVariable (\r
+                              OpCode->ExtraData.GetSetData.ValueName,\r
+                              &OpCode->ExtraData.GetSetData.VarStorage->Guid,\r
+                              OpCode->ExtraData.GetSetData.VarStorage->Attributes,\r
+                              OpCode->ExtraData.GetSetData.ValueWidth,\r
+                              &Value->Value\r
+                              );\r
+              if (!EFI_ERROR (Status)) {\r
+                Data1.Value.b = TRUE;\r
+              }\r
+\r
+              break;\r
+            default:\r
+              //\r
+              // Not recognize storage.\r
+              //\r
+              Status = EFI_UNSUPPORTED;\r
+              goto Done;\r
+          }\r
+        } else {\r
+          //\r
+          // For Time/Date Data\r
+          //\r
+          if ((OpCode->ExtraData.GetSetData.ValueType != EFI_IFR_TYPE_DATE) && (OpCode->ExtraData.GetSetData.ValueType != EFI_IFR_TYPE_TIME)) {\r
+            //\r
+            // Only support Data/Time data when storage doesn't exist.\r
+            //\r
+            Status = EFI_UNSUPPORTED;\r
+            goto Done;\r
+          }\r
+\r
+          Status = gRT->GetTime (&EfiTime, NULL);\r
+          if (!EFI_ERROR (Status)) {\r
+            if (OpCode->ExtraData.GetSetData.ValueType == EFI_IFR_TYPE_DATE) {\r
+              switch (OpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset) {\r
+                case 0x00:\r
+                  EfiTime.Year = Value->Value.u16;\r
+                  break;\r
+                case 0x02:\r
+                  EfiTime.Month = Value->Value.u8;\r
+                  break;\r
+                case 0x03:\r
+                  EfiTime.Day = Value->Value.u8;\r
+                  break;\r
+                default:\r
+                  //\r
+                  // Invalid Date field.\r
+                  //\r
+                  Status = EFI_INVALID_PARAMETER;\r
+                  goto Done;\r
+              }\r
+            } else {\r
+              switch (OpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset) {\r
+                case 0x00:\r
+                  EfiTime.Hour = Value->Value.u8;\r
+                  break;\r
+                case 0x01:\r
+                  EfiTime.Minute = Value->Value.u8;\r
+                  break;\r
+                case 0x02:\r
+                  EfiTime.Second = Value->Value.u8;\r
+                  break;\r
+                default:\r
+                  //\r
+                  // Invalid Time field.\r
+                  //\r
+                  Status = EFI_INVALID_PARAMETER;\r
+                  goto Done;\r
+              }\r
+            }\r
+\r
+            Status = gRT->SetTime (&EfiTime);\r
+            if (!EFI_ERROR (Status)) {\r
+              Data1.Value.b = TRUE;\r
+            }\r
+          }\r
+        }\r
+\r
+        Value = &Data1;\r
+        break;\r
+\r
+      //\r
+      // binary-op\r
+      //\r
+      case EFI_IFR_ADD_OP:\r
+      case EFI_IFR_SUBTRACT_OP:\r
+      case EFI_IFR_MULTIPLY_OP:\r
+      case EFI_IFR_DIVIDE_OP:\r
+      case EFI_IFR_MODULO_OP:\r
+      case EFI_IFR_BITWISE_AND_OP:\r
+      case EFI_IFR_BITWISE_OR_OP:\r
+      case EFI_IFR_SHIFT_LEFT_OP:\r
+      case EFI_IFR_SHIFT_RIGHT_OP:\r
+        //\r
+        // Pop an expression from the expression stack\r
+        //\r
+        Status = PopExpression (&Data2);\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
+\r
+        //\r
+        // Pop another expression from the expression stack\r
+        //\r
+        Status = PopExpression (&Data1);\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
+\r
+        if (Data2.Type > EFI_IFR_TYPE_DATE) {\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          break;\r
+        }\r
+\r
+        if (Data1.Type > EFI_IFR_TYPE_DATE) {\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          break;\r
+        }\r
+\r
+        Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+\r
+        switch (OpCode->Operand) {\r
+          case EFI_IFR_ADD_OP:\r
+            Value->Value.u64 = HiiValueToUINT64 (&Data1) + HiiValueToUINT64 (&Data2);\r
+            break;\r
+\r
+          case EFI_IFR_SUBTRACT_OP:\r
+            Value->Value.u64 = HiiValueToUINT64 (&Data1) - HiiValueToUINT64 (&Data2);\r
+            break;\r
+\r
+          case EFI_IFR_MULTIPLY_OP:\r
+            Value->Value.u64 = MultU64x32 (HiiValueToUINT64 (&Data1), (UINT32)HiiValueToUINT64 (&Data2));\r
+            break;\r
+\r
+          case EFI_IFR_DIVIDE_OP:\r
+            Value->Value.u64 = DivU64x32 (HiiValueToUINT64 (&Data1), (UINT32)HiiValueToUINT64 (&Data2));\r
+            break;\r
+\r
+          case EFI_IFR_MODULO_OP:\r
+            DivU64x32Remainder (HiiValueToUINT64 (&Data1), (UINT32)HiiValueToUINT64 (&Data2), &TempValue);\r
+            Value->Value.u64 = TempValue;\r
+            break;\r
+\r
+          case EFI_IFR_BITWISE_AND_OP:\r
+            Value->Value.u64 = HiiValueToUINT64 (&Data1) & HiiValueToUINT64 (&Data2);\r
+            break;\r
+\r
+          case EFI_IFR_BITWISE_OR_OP:\r
+            Value->Value.u64 = HiiValueToUINT64 (&Data1) | HiiValueToUINT64 (&Data2);\r
+            break;\r
+\r
+          case EFI_IFR_SHIFT_LEFT_OP:\r
+            Value->Value.u64 = LShiftU64 (HiiValueToUINT64 (&Data1), (UINTN)HiiValueToUINT64 (&Data2));\r
+            break;\r
+\r
+          case EFI_IFR_SHIFT_RIGHT_OP:\r
+            Value->Value.u64 = RShiftU64 (HiiValueToUINT64 (&Data1), (UINTN)HiiValueToUINT64 (&Data2));\r
+            break;\r
+\r
+          default:\r
+            break;\r
+        }\r
+\r
+        break;\r
+\r
+      case EFI_IFR_AND_OP:\r
+      case EFI_IFR_OR_OP:\r
+        //\r
+        // Two Boolean operator\r
+        //\r
+        Status = PopExpression (&Data2);\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
+\r
+        //\r
+        // Pop another expression from the expression stack\r
+        //\r
+        Status = PopExpression (&Data1);\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
+\r
+        if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          break;\r
+        }\r
+\r
+        if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          break;\r
+        }\r
+\r
+        if (OpCode->Operand == EFI_IFR_AND_OP) {\r
+          Value->Value.b = (BOOLEAN)(Data1.Value.b && Data2.Value.b);\r
+        } else {\r
+          Value->Value.b = (BOOLEAN)(Data1.Value.b || Data2.Value.b);\r
+        }\r
+\r
+        break;\r
+\r
+      case EFI_IFR_EQUAL_OP:\r
+      case EFI_IFR_NOT_EQUAL_OP:\r
+      case EFI_IFR_GREATER_EQUAL_OP:\r
+      case EFI_IFR_GREATER_THAN_OP:\r
+      case EFI_IFR_LESS_EQUAL_OP:\r
+      case EFI_IFR_LESS_THAN_OP:\r
+        //\r
+        // Compare two integer, string, boolean or date/time\r
+        //\r
+        Status = PopExpression (&Data2);\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
+\r
+        //\r
+        // Pop another expression from the expression stack\r
+        //\r
+        Status = PopExpression (&Data1);\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
+\r
+        if ((Data2.Type > EFI_IFR_TYPE_BOOLEAN) &&\r
+            (Data2.Type != EFI_IFR_TYPE_STRING) &&\r
+            !IsTypeInBuffer (&Data2))\r
+        {\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          break;\r
+        }\r
+\r
+        if ((Data1.Type > EFI_IFR_TYPE_BOOLEAN) &&\r
+            (Data1.Type != EFI_IFR_TYPE_STRING) &&\r
+            !IsTypeInBuffer (&Data1))\r
+        {\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          break;\r
+        }\r
+\r
+        Status = CompareHiiValue (&Data1, &Data2, &Result, FormSet->HiiHandle);\r
+        if (Data1.Type == EFI_IFR_TYPE_BUFFER) {\r
+          FreePool (Data1.Buffer);\r
+        }\r
+\r
+        if (Data2.Type == EFI_IFR_TYPE_BUFFER) {\r
+          FreePool (Data2.Buffer);\r
+        }\r
+\r
+        if (Status == EFI_UNSUPPORTED) {\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          Status      = EFI_SUCCESS;\r
+          break;\r
+        }\r
+\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
+\r
+        switch (OpCode->Operand) {\r
+          case EFI_IFR_EQUAL_OP:\r
+            Value->Value.b = (BOOLEAN)((Result == 0) ? TRUE : FALSE);\r
+            break;\r
+\r
+          case EFI_IFR_NOT_EQUAL_OP:\r
+            Value->Value.b = (BOOLEAN)((Result != 0) ? TRUE : FALSE);\r
+            break;\r
+\r
+          case EFI_IFR_GREATER_EQUAL_OP:\r
+            Value->Value.b = (BOOLEAN)((Result >= 0) ? TRUE : FALSE);\r
+            break;\r
+\r
+          case EFI_IFR_GREATER_THAN_OP:\r
+            Value->Value.b = (BOOLEAN)((Result > 0) ? TRUE : FALSE);\r
+            break;\r
+\r
+          case EFI_IFR_LESS_EQUAL_OP:\r
+            Value->Value.b = (BOOLEAN)((Result <= 0) ? TRUE : FALSE);\r
+            break;\r
+\r
+          case EFI_IFR_LESS_THAN_OP:\r
+            Value->Value.b = (BOOLEAN)((Result < 0) ? TRUE : FALSE);\r
+            break;\r
+\r
+          default:\r
+            break;\r
+        }\r
+\r
+        break;\r
+\r
+      case EFI_IFR_MATCH_OP:\r
+        Status = InitializeUnicodeCollationProtocol ();\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
+\r
+        Status = IfrMatch (FormSet, Value);\r
+        break;\r
+\r
+      case EFI_IFR_MATCH2_OP:\r
+        Status = IfrMatch2 (FormSet, &OpCode->ExtraData.Guid, Value);\r
+        break;\r
+\r
+      case EFI_IFR_CATENATE_OP:\r
+        Status = IfrCatenate (FormSet, Value);\r
+        break;\r
+\r
+      //\r
+      // ternary-op\r
+      //\r
+      case EFI_IFR_CONDITIONAL_OP:\r
+        //\r
+        // Pop third expression from the expression stack\r
+        //\r
+        Status = PopExpression (&Data3);\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
+\r
+        //\r
+        // Pop second expression from the expression stack\r
+        //\r
+        Status = PopExpression (&Data2);\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
+\r
+        //\r
+        // Pop first expression from the expression stack\r
+        //\r
+        Status = PopExpression (&Data1);\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
+\r
+        if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
+          Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+          break;\r
+        }\r
+\r
+        if (Data1.Value.b) {\r
+          Value = &Data3;\r
+        } else {\r
+          Value = &Data2;\r
+        }\r
+\r
+        break;\r
+\r
+      case EFI_IFR_FIND_OP:\r
+        Status = IfrFind (FormSet, OpCode->ExtraData.Format, Value);\r
+        break;\r
+\r
+      case EFI_IFR_MID_OP:\r
+        Status = IfrMid (FormSet, Value);\r
+        break;\r
+\r
+      case EFI_IFR_TOKEN_OP:\r
+        Status = IfrToken (FormSet, Value);\r
+        break;\r
+\r
+      case EFI_IFR_SPAN_OP:\r
+        Status = IfrSpan (FormSet, OpCode->ExtraData.Flags, Value);\r
+        break;\r
+\r
+      case EFI_IFR_MAP_OP:\r
+        //\r
+        // Pop the check value\r
+        //\r
+        Status = PopExpression (&Data1);\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
+\r
+        //\r
+        // Check MapExpression list is valid.\r
+        //\r
+        if (OpCode->MapExpressionList.ForwardLink == NULL) {\r
+          Status = EFI_INVALID_PARAMETER;\r
+          goto Done;\r
+        }\r
+\r
+        //\r
+        // Go through map expression list.\r
+        //\r
+        SubExpressionLink = GetFirstNode (&OpCode->MapExpressionList);\r
+        while (!IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
+          SubExpression = HII_EXPRESSION_FROM_LINK (SubExpressionLink);\r
+          //\r
+          // Evaluate the first expression in this pair.\r
+          //\r
+          Status = EvaluateHiiExpression (FormSet, Form, SubExpression);\r
+          if (EFI_ERROR (Status)) {\r
+            goto Done;\r
+          }\r
+\r
+          //\r
+          // Compare the expression value with current value\r
+          //\r
+          if ((CompareHiiValue (&Data1, &SubExpression->Result, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {\r
+            //\r
+            // Try get the map value.\r
+            //\r
+            SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
+            if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
+              Status = EFI_INVALID_PARAMETER;\r
+              goto Done;\r
+            }\r
+\r
+            SubExpression = HII_EXPRESSION_FROM_LINK (SubExpressionLink);\r
+            Status        = EvaluateHiiExpression (FormSet, Form, SubExpression);\r
+            if (EFI_ERROR (Status)) {\r
+              goto Done;\r
+            }\r
+\r
+            Value = &SubExpression->Result;\r
+            break;\r
+          }\r
+\r
+          //\r
+          // Skip the second expression on this pair.\r
+          //\r
+          SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
+          if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
+            Status = EFI_INVALID_PARAMETER;\r
+            goto Done;\r
+          }\r
+\r
+          //\r
+          // Goto the first expression on next pair.\r
+          //\r
+          SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
+        }\r
+\r
+        //\r
+        // No map value is found.\r
+        //\r
+        if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
+          Value->Type     = EFI_IFR_TYPE_UNDEFINED;\r
+          Value->Value.u8 = 0;\r
+        }\r
+\r
+        break;\r
+\r
+      default:\r
+        break;\r
+    }\r
+\r
+    if (EFI_ERROR (Status) || (Value->Type == EFI_IFR_TYPE_UNDEFINED)) {\r
+      goto Done;\r
+    }\r
+\r
+    Status = PushExpression (Value);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Pop the final result from expression stack\r
+  //\r
+  Value  = &Data1;\r
+  Status = PopExpression (Value);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // After evaluating an expression, there should be only one value left on the expression stack\r
+  //\r
+  if (PopExpression (Value) != EFI_ACCESS_DENIED) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+Done:\r
+  RestoreExpressionEvaluationStackOffset (StackOffset);\r
+  if (!EFI_ERROR (Status)) {\r
+    CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Set value of a data element in an Array by its Index.\r
+\r
+  @param[in]  Array       The data array.\r
+  @param[in]  Type        Type of the data in this array.\r
+  @param[in]  Index       Zero based index for data in this array.\r
+  @param[in]  Value       The value to be set.\r
+\r
+**/\r
+VOID\r
+SetArrayData (\r
+  IN VOID    *Array,\r
+  IN UINT8   Type,\r
+  IN UINTN   Index,\r
+  IN UINT64  Value\r
+  )\r
+{\r
+  ASSERT (Array != NULL);\r
+\r
+  switch (Type) {\r
+    case EFI_IFR_TYPE_NUM_SIZE_8:\r
+      *(((UINT8 *)Array) + Index) = (UINT8)Value;\r
+      break;\r
+\r
+    case EFI_IFR_TYPE_NUM_SIZE_16:\r
+      *(((UINT16 *)Array) + Index) = (UINT16)Value;\r
+      break;\r
+\r
+    case EFI_IFR_TYPE_NUM_SIZE_32:\r
+      *(((UINT32 *)Array) + Index) = (UINT32)Value;\r
+      break;\r
+\r
+    case EFI_IFR_TYPE_NUM_SIZE_64:\r
+      *(((UINT64 *)Array) + Index) = (UINT64)Value;\r
+      break;\r
+\r
+    default:\r
+      break;\r
+  }\r
+}\r
+\r
+/**\r
+  Search an Option of a Question by its value.\r
+\r
+  @param[in]  Question           The Question\r
+  @param[in]  OptionValue        Value for Option to be searched.\r
+\r
+  @retval Pointer                Pointer to the found Option.\r
+  @retval NULL                   Option not found.\r
+\r
+**/\r
+HII_QUESTION_OPTION *\r
+ValueToOption (\r
+  IN HII_STATEMENT        *Question,\r
+  IN HII_STATEMENT_VALUE  *OptionValue\r
+  )\r
+{\r
+  LIST_ENTRY           *Link;\r
+  HII_QUESTION_OPTION  *Option;\r
+  EFI_HII_VALUE        Data1;\r
+  EFI_HII_VALUE        Data2;\r
+  INTN                 Result;\r
+  EFI_STATUS           Status;\r
+\r
+  Result = 0;\r
+  ZeroMem (&Data1, sizeof (EFI_HII_VALUE));\r
+  ZeroMem (&Data2, sizeof (EFI_HII_VALUE));\r
+\r
+  Status = HiiStatementValueToHiiValue (OptionValue, &Data1);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  Link = GetFirstNode (&Question->OptionListHead);\r
+  while (!IsNull (&Question->OptionListHead, Link)) {\r
+    Option = HII_QUESTION_OPTION_FROM_LINK (Link);\r
+\r
+    Status = HiiStatementValueToHiiValue (&Option->Value, &Data2);\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    if ((CompareHiiValue (&Data1, &Data2, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {\r
+      //\r
+      // Check the suppressif condition, only a valid option can be return.\r
+      //\r
+      if ((Option->SuppressExpression == NULL) ||\r
+          ((EvaluateExpressionList (Option->SuppressExpression, FALSE, NULL, NULL) == ExpressFalse)))\r
+      {\r
+        return Option;\r
+      }\r
+    }\r
+\r
+    Link = GetNextNode (&Question->OptionListHead, Link);\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Find the point in the ConfigResp string for this question.\r
+\r
+  @param[in]  Question         The question.\r
+  @param[in]  ConfigResp       Get ConfigResp string.\r
+\r
+  @retval  point to the offset where is for this question.\r
+\r
+**/\r
+CHAR16 *\r
+GetOffsetFromConfigResp (\r
+  IN HII_STATEMENT  *Question,\r
+  IN CHAR16         *ConfigResp\r
+  )\r
+{\r
+  CHAR16  *RequestElement;\r
+  CHAR16  *BlockData;\r
+\r
+  //\r
+  // Type is EFI_HII_VARSTORE_NAME_VALUE.\r
+  //\r
+  if (Question->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+    RequestElement = StrStr (ConfigResp, Question->VariableName);\r
+    if (RequestElement != NULL) {\r
+      //\r
+      // Skip the "VariableName=" field.\r
+      //\r
+      RequestElement += StrLen (Question->VariableName) + 1;\r
+    }\r
+\r
+    return RequestElement;\r
+  }\r
+\r
+  //\r
+  // Type is EFI_HII_VARSTORE_EFI_VARIABLE or EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER\r
+  //\r
+\r
+  //\r
+  // Convert all hex digits in ConfigResp to lower case before searching.\r
+  //\r
+  HiiStringToLowercase (ConfigResp);\r
+\r
+  //\r
+  // 1. Directly use Question->BlockName to find.\r
+  //\r
+  RequestElement = StrStr (ConfigResp, Question->BlockName);\r
+  if (RequestElement != NULL) {\r
+    //\r
+    // Skip the "Question->BlockName&VALUE=" field.\r
+    //\r
+    RequestElement += StrLen (Question->BlockName) + StrLen (L"&VALUE=");\r
+    return RequestElement;\r
+  }\r
+\r
+  //\r
+  // 2. Change all hex digits in Question->BlockName to lower and compare again.\r
+  //\r
+  BlockData = AllocateCopyPool (StrSize (Question->BlockName), Question->BlockName);\r
+  ASSERT (BlockData != NULL);\r
+  HiiStringToLowercase (BlockData);\r
+  RequestElement = StrStr (ConfigResp, BlockData);\r
+  FreePool (BlockData);\r
+\r
+  if (RequestElement != NULL) {\r
+    //\r
+    // Skip the "Question->BlockName&VALUE=" field.\r
+    //\r
+    RequestElement += StrLen (Question->BlockName) + StrLen (L"&VALUE=");\r
+  }\r
+\r
+  return RequestElement;\r
+}\r
+\r
+/**\r
+  Get Question default value from AltCfg string.\r
+\r
+  @param[in]  FormSet            The form set.\r
+  @param[in]  Form               The form\r
+  @param[in]  Question           The question.\r
+  @param[out] DefaultValue       Default value.\r
+\r
+  @retval EFI_SUCCESS            Question is reset to default value.\r
+\r
+**/\r
+EFI_STATUS\r
+GetDefaultValueFromAltCfg (\r
+  IN     HII_FORMSET          *FormSet,\r
+  IN     HII_FORM             *Form,\r
+  IN     HII_STATEMENT        *Question,\r
+  OUT    HII_STATEMENT_VALUE  *DefaultValue\r
+  )\r
+{\r
+  HII_FORMSET_STORAGE      *Storage;\r
+  CHAR16                   *ConfigResp;\r
+  CHAR16                   *Value;\r
+  LIST_ENTRY               *Link;\r
+  HII_FORM_CONFIG_REQUEST  *ConfigInfo;\r
+\r
+  Storage = Question->Storage;\r
+  if ((Storage == NULL) || (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  //\r
+  // Try to get AltCfg string from form. If not found it, then\r
+  // try to get it from formset.\r
+  //\r
+  ConfigResp = NULL;\r
+  Link       = GetFirstNode (&Form->ConfigRequestHead);\r
+  while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
+    ConfigInfo = HII_FORM_CONFIG_REQUEST_FROM_LINK (Link);\r
+    Link       = GetNextNode (&Form->ConfigRequestHead, Link);\r
+\r
+    if (Storage == ConfigInfo->Storage) {\r
+      ConfigResp = ConfigInfo->ConfigAltResp;\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (ConfigResp == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  Value = GetOffsetFromConfigResp (Question, ConfigResp);\r
+  if (Value == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  return BufferToQuestionValue (Question, Value, DefaultValue);\r
+}\r
+\r
+/**\r
+  Get default Id value used for browser.\r
+\r
+  @param[in]  DefaultId     The default id value used by hii.\r
+\r
+  @retval Browser used default value.\r
+\r
+**/\r
+INTN\r
+GetDefaultIdForCallBack (\r
+  IN UINTN  DefaultId\r
+  )\r
+{\r
+  if (DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) {\r
+    return EFI_BROWSER_ACTION_DEFAULT_STANDARD;\r
+  } else if (DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
+    return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING;\r
+  } else if (DefaultId == EFI_HII_DEFAULT_CLASS_SAFE) {\r
+    return EFI_BROWSER_ACTION_DEFAULT_SAFE;\r
+  } else if ((DefaultId >= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN) && (DefaultId < EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN + 0x1000)) {\r
+    return EFI_BROWSER_ACTION_DEFAULT_PLATFORM + DefaultId - EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN;\r
+  } else if ((DefaultId >= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN) && (DefaultId < EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN + 0x1000)) {\r
+    return EFI_BROWSER_ACTION_DEFAULT_HARDWARE + DefaultId - EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN;\r
+  } else if ((DefaultId >= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN) && (DefaultId < EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN + 0x1000)) {\r
+    return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE + DefaultId - EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN;\r
+  } else {\r
+    return -1;\r
+  }\r
+}\r
+\r
+/**\r
+  Get default value of question.\r
+\r
+  @param[in]  FormSet            The form set.\r
+  @param[in]  Form               The form.\r
+  @param[in]  Question           The question.\r
+  @param[in]  DefaultId          The Class of the default.\r
+  @param[out] DefaultValue       The default value of given question.\r
+\r
+  @retval EFI_SUCCESS            Question is reset to default value.\r
+\r
+**/\r
+EFI_STATUS\r
+GetQuestionDefault (\r
+  IN HII_FORMSET           *FormSet,\r
+  IN HII_FORM              *Form,\r
+  IN HII_STATEMENT         *Question,\r
+  IN UINT16                DefaultId,\r
+  OUT HII_STATEMENT_VALUE  *DefaultValue\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  LIST_ENTRY                      *Link;\r
+  HII_QUESTION_DEFAULT            *Default;\r
+  HII_QUESTION_OPTION             *Option;\r
+  HII_STATEMENT_VALUE             *HiiValue;\r
+  UINT8                           Index;\r
+  EFI_STRING                      StrValue;\r
+  EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;\r
+  EFI_BROWSER_ACTION_REQUEST      ActionRequest;\r
+  INTN                            Action;\r
+  EFI_IFR_TYPE_VALUE              *TypeValue;\r
+  UINT16                          OriginalDefaultId;\r
+  HII_FORMSET_DEFAULTSTORE        *DefaultStore;\r
+  LIST_ENTRY                      *DefaultLink;\r
+\r
+  if ((FormSet == NULL) || (Form == NULL) || (Question == NULL) || (DefaultValue == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status            = EFI_NOT_FOUND;\r
+  StrValue          = NULL;\r
+  OriginalDefaultId = DefaultId;\r
+  DefaultLink       = GetFirstNode (&FormSet->DefaultStoreListHead);\r
+\r
+  //\r
+  // Statement don't have storage, skip them\r
+  //\r
+  if (Question->QuestionId == 0) {\r
+    DEBUG ((DEBUG_ERROR, "%a: Question has no storage, skip it\n", __func__));\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // There are Five ways to specify default value for a Question:\r
+  //  1, use call back function (highest priority)\r
+  //  2, use ExtractConfig function\r
+  //  3, use nested EFI_IFR_DEFAULT\r
+  //  4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)\r
+  //  5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)\r
+  //\r
+  CopyMem (DefaultValue, &Question->Value, sizeof (HII_STATEMENT_VALUE));\r
+ReGetDefault:\r
+  HiiValue  = DefaultValue;\r
+  TypeValue = &HiiValue->Value;\r
+  if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
+    //\r
+    // For orderedlist, need to pass the BufferValue to Callback function.\r
+    //\r
+    DefaultValue->BufferLen = Question->Value.BufferLen;\r
+    DefaultValue->Buffer    = AllocateZeroPool (DefaultValue->BufferLen);\r
+    ASSERT (DefaultValue->Buffer != NULL);\r
+    if (DefaultValue->Buffer == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    TypeValue = (EFI_IFR_TYPE_VALUE *)DefaultValue->Buffer;\r
+  }\r
+\r
+  //\r
+  // Get Question default value from call back function.\r
+  // The string type of question cause HII driver to set string to its default value.\r
+  // So, we don't do this otherwise it will actually set question to default value.\r
+  // We only want to get default value of question.\r
+  //\r
+  if (HiiValue->Type != EFI_IFR_TYPE_STRING) {\r
+    ConfigAccess = FormSet->ConfigAccess;\r
+    Action       = GetDefaultIdForCallBack (DefaultId);\r
+    if ((Action > 0) && ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) && (ConfigAccess != NULL)) {\r
+      ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+      Status        = ConfigAccess->Callback (\r
+                                      ConfigAccess,\r
+                                      Action,\r
+                                      Question->QuestionId,\r
+                                      HiiValue->Type,\r
+                                      TypeValue,\r
+                                      &ActionRequest\r
+                                      );\r
+      if (!EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // Get default value from altcfg string.\r
+  //\r
+  if (ConfigAccess != NULL) {\r
+    Status = GetDefaultValueFromAltCfg (FormSet, Form, Question, DefaultValue);\r
+    if (!EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  //\r
+  // EFI_IFR_DEFAULT has highest priority\r
+  //\r
+  if (!IsListEmpty (&Question->DefaultListHead)) {\r
+    Link = GetFirstNode (&Question->DefaultListHead);\r
+    while (!IsNull (&Question->DefaultListHead, Link)) {\r
+      Default = HII_QUESTION_DEFAULT_FROM_LINK (Link);\r
+\r
+      if (Default->DefaultId == DefaultId) {\r
+        if (Default->ValueExpression != NULL) {\r
+          //\r
+          // Default is provided by an Expression, evaluate it\r
+          //\r
+          Status = EvaluateHiiExpression (FormSet, Form, Default->ValueExpression);\r
+          if (EFI_ERROR (Status)) {\r
+            return Status;\r
+          }\r
+\r
+          if (Default->ValueExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {\r
+            ASSERT (HiiValue->Type == EFI_IFR_TYPE_BUFFER && DefaultValue->Buffer != NULL);\r
+            if (DefaultValue->BufferLen > Default->ValueExpression->Result.BufferLen) {\r
+              CopyMem (DefaultValue->Buffer, Default->ValueExpression->Result.Buffer, Default->ValueExpression->Result.BufferLen);\r
+              DefaultValue->BufferLen = Default->ValueExpression->Result.BufferLen;\r
+            } else {\r
+              CopyMem (DefaultValue->Buffer, Default->ValueExpression->Result.Buffer, DefaultValue->BufferLen);\r
+            }\r
+\r
+            FreePool (Default->ValueExpression->Result.Buffer);\r
+          }\r
+\r
+          HiiValue->Type = Default->ValueExpression->Result.Type;\r
+          CopyMem (&HiiValue->Value, &Default->ValueExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE));\r
+        } else {\r
+          //\r
+          // Default value is embedded in EFI_IFR_DEFAULT\r
+          //\r
+          if (Default->Value.Type == EFI_IFR_TYPE_BUFFER) {\r
+            ASSERT (HiiValue->Buffer != NULL);\r
+            CopyMem (HiiValue->Buffer, Default->Value.Buffer, Default->Value.BufferLen);\r
+          } else {\r
+            CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));\r
+          }\r
+        }\r
+\r
+        if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
+          StrValue = HiiGetString (FormSet->HiiHandle, HiiValue->Value.string, NULL);\r
+          if (StrValue == NULL) {\r
+            return EFI_NOT_FOUND;\r
+          }\r
+\r
+          if (DefaultValue->BufferLen > StrSize (StrValue)) {\r
+            ZeroMem (DefaultValue->Buffer, DefaultValue->BufferLen);\r
+            CopyMem (DefaultValue->Buffer, StrValue, StrSize (StrValue));\r
+          } else {\r
+            CopyMem (DefaultValue->Buffer, StrValue, DefaultValue->BufferLen);\r
+          }\r
+        }\r
+\r
+        return EFI_SUCCESS;\r
+      }\r
+\r
+      Link = GetNextNode (&Question->DefaultListHead, Link);\r
+    }\r
+  }\r
+\r
+  //\r
+  // EFI_ONE_OF_OPTION\r
+  //\r
+  if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {\r
+    if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
+      //\r
+      // OneOfOption could only provide Standard and Manufacturing default\r
+      //\r
+      Link = GetFirstNode (&Question->OptionListHead);\r
+      while (!IsNull (&Question->OptionListHead, Link)) {\r
+        Option = HII_QUESTION_OPTION_FROM_LINK (Link);\r
+        Link   = GetNextNode (&Question->OptionListHead, Link);\r
+\r
+        if ((Option->SuppressExpression != NULL) &&\r
+            (EvaluateExpressionList (Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse))\r
+        {\r
+          continue;\r
+        }\r
+\r
+        if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||\r
+            ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))\r
+            )\r
+        {\r
+          CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
+\r
+          return EFI_SUCCESS;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // EFI_IFR_CHECKBOX - lowest priority\r
+  //\r
+  if (Question->Operand == EFI_IFR_CHECKBOX_OP) {\r
+    if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
+      //\r
+      // Checkbox could only provide Standard and Manufacturing default\r
+      //\r
+      if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Question->ExtraData.Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0)) ||\r
+          ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Question->ExtraData.Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0))\r
+          )\r
+      {\r
+        HiiValue->Value.b = TRUE;\r
+      }\r
+\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  //\r
+  // For question without default value for current default Id, we try to re-get the default value form other default id in the DefaultStoreList.\r
+  // If get, will exit the function, if not, will choose next default id in the DefaultStoreList.\r
+  // The default id in DefaultStoreList are in ascending order to make sure choose the smallest default id every time.\r
+  //\r
+  while (!IsNull (&FormSet->DefaultStoreListHead, DefaultLink)) {\r
+    DefaultStore = HII_FORMSET_DEFAULTSTORE_FROM_LINK (DefaultLink);\r
+    DefaultLink  = GetNextNode (&FormSet->DefaultStoreListHead, DefaultLink);\r
+    DefaultId    = DefaultStore->DefaultId;\r
+    if (DefaultId == OriginalDefaultId) {\r
+      continue;\r
+    }\r
+\r
+    goto ReGetDefault;\r
+  }\r
+\r
+  //\r
+  // For Questions without default value for all the default id in the DefaultStoreList.\r
+  //\r
+  Status = EFI_NOT_FOUND;\r
+  switch (Question->Operand) {\r
+    case EFI_IFR_CHECKBOX_OP:\r
+      HiiValue->Value.b = FALSE;\r
+      Status            = EFI_SUCCESS;\r
+      break;\r
+\r
+    case EFI_IFR_NUMERIC_OP:\r
+      //\r
+      // Take minimum value as numeric default value\r
+      //\r
+      if ((Question->ExtraData.NumData.Flags & EFI_IFR_DISPLAY) == 0) {\r
+        //\r
+        // In EFI_IFR_DISPLAY_INT_DEC type, should check value with int* type.\r
+        //\r
+        switch (Question->ExtraData.NumData.Flags & EFI_IFR_NUMERIC_SIZE) {\r
+          case EFI_IFR_NUMERIC_SIZE_1:\r
+            if (((INT8)HiiValue->Value.u8 < (INT8)Question->ExtraData.NumData.Minimum) || ((INT8)HiiValue->Value.u8 > (INT8)Question->ExtraData.NumData.Maximum)) {\r
+              HiiValue->Value.u8 = (UINT8)Question->ExtraData.NumData.Minimum;\r
+              Status             = EFI_SUCCESS;\r
+            }\r
+\r
+            break;\r
+          case EFI_IFR_NUMERIC_SIZE_2:\r
+            if (((INT16)HiiValue->Value.u16 < (INT16)Question->ExtraData.NumData.Minimum) || ((INT16)HiiValue->Value.u16 > (INT16)Question->ExtraData.NumData.Maximum)) {\r
+              HiiValue->Value.u16 = (UINT16)Question->ExtraData.NumData.Minimum;\r
+              Status              = EFI_SUCCESS;\r
+            }\r
+\r
+            break;\r
+          case EFI_IFR_NUMERIC_SIZE_4:\r
+            if (((INT32)HiiValue->Value.u32 < (INT32)Question->ExtraData.NumData.Minimum) || ((INT32)HiiValue->Value.u32 > (INT32)Question->ExtraData.NumData.Maximum)) {\r
+              HiiValue->Value.u32 = (UINT32)Question->ExtraData.NumData.Minimum;\r
+              Status              = EFI_SUCCESS;\r
+            }\r
+\r
+            break;\r
+          case EFI_IFR_NUMERIC_SIZE_8:\r
+            if (((INT64)HiiValue->Value.u64 < (INT64)Question->ExtraData.NumData.Minimum) || ((INT64)HiiValue->Value.u64 > (INT64)Question->ExtraData.NumData.Maximum)) {\r
+              HiiValue->Value.u64 = Question->ExtraData.NumData.Minimum;\r
+              Status              = EFI_SUCCESS;\r
+            }\r
+\r
+            break;\r
+          default:\r
+            break;\r
+        }\r
+      } else {\r
+        if ((HiiValue->Value.u64 < Question->ExtraData.NumData.Minimum) || (HiiValue->Value.u64 > Question->ExtraData.NumData.Maximum)) {\r
+          HiiValue->Value.u64 = Question->ExtraData.NumData.Minimum;\r
+          Status              = EFI_SUCCESS;\r
+        }\r
+      }\r
+\r
+      break;\r
+\r
+    case EFI_IFR_ONE_OF_OP:\r
+      //\r
+      // Take first oneof option as oneof's default value\r
+      //\r
+      Link = GetFirstNode (&Question->OptionListHead);\r
+      while (!IsNull (&Question->OptionListHead, Link)) {\r
+        Option = HII_QUESTION_OPTION_FROM_LINK (Link);\r
+        Link   = GetNextNode (&Question->OptionListHead, Link);\r
+\r
+        if ((Option->SuppressExpression != NULL) &&\r
+            (EvaluateExpressionList (Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse))\r
+        {\r
+          continue;\r
+        }\r
+\r
+        CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
+        Status = EFI_SUCCESS;\r
+        break;\r
+      }\r
+\r
+      break;\r
+\r
+    case EFI_IFR_ORDERED_LIST_OP:\r
+      //\r
+      // Take option sequence in IFR as ordered list's default value\r
+      //\r
+      Index = 0;\r
+      Link  = GetFirstNode (&Question->OptionListHead);\r
+      while (!IsNull (&Question->OptionListHead, Link)) {\r
+        Status = EFI_SUCCESS;\r
+        Option = HII_QUESTION_OPTION_FROM_LINK (Link);\r
+        Link   = GetNextNode (&Question->OptionListHead, Link);\r
+\r
+        if ((Option->SuppressExpression != NULL) &&\r
+            (EvaluateExpressionList (Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse))\r
+        {\r
+          continue;\r
+        }\r
+\r
+        SetArrayData (DefaultValue->Buffer, Question->Value.Type, Index, Option->Value.Value.u64);\r
+\r
+        Index++;\r
+        if (Index >= Question->ExtraData.OrderListData.MaxContainers) {\r
+          break;\r
+        }\r
+      }\r
+\r
+      break;\r
+\r
+    default:\r
+      break;\r
+  }\r
+\r
+  return Status;\r
+}\r
diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.c b/RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.c
new file mode 100644 (file)
index 0000000..168b445
--- /dev/null
@@ -0,0 +1,810 @@
+/** @file\r
+  Implementation of HII utility library.\r
+\r
+  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+  (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>\r
+  Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.\r
+\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include "HiiInternal.h"\r
+\r
+/**\r
+  Initialize the internal data structure of a FormSet.\r
+\r
+  @param  Handle                 PackageList Handle\r
+  @param  FormSetGuid            On input, GUID or class GUID of a formset. If not\r
+                                 specified (NULL or zero GUID), take the first\r
+                                 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
+                                 found in package list.\r
+                                 On output, GUID of the formset found(if not NULL).\r
+  @param  FormSet                FormSet data structure.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+  @retval EFI_NOT_FOUND          The specified FormSet could not be found.\r
+\r
+**/\r
+EFI_STATUS\r
+CreateFormSetFromHiiHandle (\r
+  IN     EFI_HII_HANDLE  Handle,\r
+  IN OUT EFI_GUID        *FormSetGuid,\r
+  OUT HII_FORMSET        *FormSet\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+  EFI_HANDLE                 DriverHandle;\r
+  EFI_HII_DATABASE_PROTOCOL  *HiiDatabase;\r
+\r
+  if ((FormSetGuid == NULL) || (FormSet == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Locate required Hii Database protocol\r
+  //\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiHiiDatabaseProtocolGuid,\r
+                  NULL,\r
+                  (VOID **)&HiiDatabase\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  FormSet->Signature = HII_FORMSET_SIGNATURE;\r
+  FormSet->HiiHandle = Handle;\r
+  CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));\r
+  //\r
+  // Retrieve ConfigAccess Protocol associated with this HiiPackageList\r
+  //\r
+  Status = HiiDatabase->GetPackageListHandle (HiiDatabase, Handle, &DriverHandle);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  FormSet->DriverHandle = DriverHandle;\r
+  Status                = gBS->HandleProtocol (\r
+                                 DriverHandle,\r
+                                 &gEfiHiiConfigAccessProtocolGuid,\r
+                                 (VOID **)&FormSet->ConfigAccess\r
+                                 );\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // Configuration Driver don't attach ConfigAccess protocol to its HII package\r
+    // list, then there will be no configuration action required\r
+    //\r
+    FormSet->ConfigAccess = NULL;\r
+  }\r
+\r
+  Status = gBS->HandleProtocol (\r
+                  DriverHandle,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  (VOID **)&FormSet->DevicePath\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // Configuration Driver don't attach ConfigAccess protocol to its HII package\r
+    // list, then there will be no configuration action required\r
+    //\r
+    FormSet->DevicePath = NULL;\r
+  }\r
+\r
+  //\r
+  // Parse the IFR binary OpCodes\r
+  //\r
+  Status = ParseOpCodes (FormSet);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Initialize a Formset and get current setting for Questions.\r
+\r
+  @param  FormSet                FormSet data structure.\r
+\r
+**/\r
+VOID\r
+InitializeFormSet (\r
+  IN OUT HII_FORMSET  *FormSet\r
+  )\r
+{\r
+  LIST_ENTRY           *Link;\r
+  HII_FORMSET_STORAGE  *Storage;\r
+  LIST_ENTRY           *FormLink;\r
+  HII_STATEMENT        *Question;\r
+  HII_FORM             *Form;\r
+\r
+  if (FormSet == NULL) {\r
+    return;\r
+  }\r
+\r
+  //\r
+  // Load Storage for all questions with storage\r
+  //\r
+  Link = GetFirstNode (&FormSet->StorageListHead);\r
+  while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+    Storage = HII_STORAGE_FROM_LINK (Link);\r
+    LoadFormSetStorage (FormSet, Storage);\r
+    Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+  }\r
+\r
+  //\r
+  // Get Current Value for all no storage questions\r
+  //\r
+  FormLink = GetFirstNode (&FormSet->FormListHead);\r
+  while (!IsNull (&FormSet->FormListHead, FormLink)) {\r
+    Form = HII_FORM_FROM_LINK (FormLink);\r
+    Link = GetFirstNode (&Form->StatementListHead);\r
+    while (!IsNull (&Form->StatementListHead, Link)) {\r
+      Question = HII_STATEMENT_FROM_LINK (Link);\r
+      if (Question->Storage == NULL) {\r
+        RetrieveQuestion (FormSet, Form, Question);\r
+      }\r
+\r
+      Link = GetNextNode (&Form->StatementListHead, Link);\r
+    }\r
+\r
+    FormLink = GetNextNode (&FormSet->FormListHead, FormLink);\r
+  }\r
+}\r
+\r
+/**\r
+  Free resources allocated for a FormSet.\r
+\r
+  @param[in,out]  FormSet                Pointer of the FormSet\r
+\r
+**/\r
+VOID\r
+DestroyFormSet (\r
+  IN OUT HII_FORMSET  *FormSet\r
+  )\r
+{\r
+  LIST_ENTRY                *Link;\r
+  HII_FORMSET_STORAGE       *Storage;\r
+  HII_FORMSET_DEFAULTSTORE  *DefaultStore;\r
+  HII_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
+  FreePool (FormSet->IfrBinaryData);\r
+\r
+  //\r
+  // Free FormSet Storage\r
+  //\r
+  if (FormSet->StorageListHead.ForwardLink != NULL) {\r
+    while (!IsListEmpty (&FormSet->StorageListHead)) {\r
+      Link    = GetFirstNode (&FormSet->StorageListHead);\r
+      Storage = HII_STORAGE_FROM_LINK (Link);\r
+      RemoveEntryList (&Storage->Link);\r
+\r
+      if (Storage != NULL) {\r
+        FreePool (Storage);\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // Free FormSet Default Store\r
+  //\r
+  if (FormSet->DefaultStoreListHead.ForwardLink != NULL) {\r
+    while (!IsListEmpty (&FormSet->DefaultStoreListHead)) {\r
+      Link         = GetFirstNode (&FormSet->DefaultStoreListHead);\r
+      DefaultStore = HII_FORMSET_DEFAULTSTORE_FROM_LINK (Link);\r
+      RemoveEntryList (&DefaultStore->Link);\r
+\r
+      FreePool (DefaultStore);\r
+    }\r
+  }\r
+\r
+  //\r
+  // Free Forms\r
+  //\r
+  if (FormSet->FormListHead.ForwardLink != NULL) {\r
+    while (!IsListEmpty (&FormSet->FormListHead)) {\r
+      Link = GetFirstNode (&FormSet->FormListHead);\r
+      Form = HII_FORM_FROM_LINK (Link);\r
+      RemoveEntryList (&Form->Link);\r
+\r
+      DestroyForm (FormSet, Form);\r
+    }\r
+  }\r
+\r
+  FreePool (FormSet);\r
+}\r
+\r
+/**\r
+  Submit data for a form.\r
+\r
+  @param[in]  FormSet                FormSet which contains the Form.\r
+  @param[in]  Form                   Form to submit.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+  @retval Others                 Other errors occur.\r
+\r
+**/\r
+EFI_STATUS\r
+SubmitForm (\r
+  IN HII_FORMSET  *FormSet,\r
+  IN HII_FORM     *Form\r
+  )\r
+{\r
+  EFI_STATUS                       Status;\r
+  EFI_HII_CONFIG_ROUTING_PROTOCOL  *HiiConfigRouting;\r
+  LIST_ENTRY                       *Link;\r
+  EFI_STRING                       ConfigResp;\r
+  EFI_STRING                       Progress;\r
+  HII_FORMSET_STORAGE              *Storage;\r
+  HII_FORM_CONFIG_REQUEST          *ConfigInfo;\r
+\r
+  if ((FormSet == NULL) || (Form == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = NoSubmitCheck (FormSet, &Form, NULL);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Link = GetFirstNode (&Form->ConfigRequestHead);\r
+  while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
+    ConfigInfo = HII_FORM_CONFIG_REQUEST_FROM_LINK (Link);\r
+    Link       = GetNextNode (&Form->ConfigRequestHead, Link);\r
+\r
+    Storage = ConfigInfo->Storage;\r
+    if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Skip if there is no RequestElement\r
+    //\r
+    if (ConfigInfo->ElementCount == 0) {\r
+      continue;\r
+    }\r
+\r
+    Status = StorageToConfigResp (ConfigInfo->Storage, &ConfigResp, ConfigInfo->ConfigRequest);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    Status = gBS->LocateProtocol (\r
+                    &gEfiHiiConfigRoutingProtocolGuid,\r
+                    NULL,\r
+                    (VOID **)&HiiConfigRouting\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    Status = HiiConfigRouting->RouteConfig (\r
+                                 HiiConfigRouting,\r
+                                 ConfigResp,\r
+                                 &Progress\r
+                                 );\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      FreePool (ConfigResp);\r
+      continue;\r
+    }\r
+\r
+    FreePool (ConfigResp);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Save Question Value to the memory, but not to storage.\r
+\r
+  @param[in]     FormSet                FormSet data structure.\r
+  @param[in]     Form                   Form data structure.\r
+  @param[in,out] Question               Pointer to the Question.\r
+  @param[in]     QuestionValue          New Question Value to be set.\r
+\r
+  @retval EFI_SUCCESS            The question value has been set successfully.\r
+  @retval EFI_INVALID_PARAMETER  One or more parameters are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+SetQuestionValue (\r
+  IN     HII_FORMSET          *FormSet,\r
+  IN     HII_FORM             *Form,\r
+  IN OUT HII_STATEMENT        *Question,\r
+  IN     HII_STATEMENT_VALUE  *QuestionValue\r
+  )\r
+{\r
+  UINT8                *Src;\r
+  UINTN                BufferLen;\r
+  UINTN                StorageWidth;\r
+  HII_FORMSET_STORAGE  *Storage;\r
+  CHAR16               *ValueStr;\r
+  BOOLEAN              IsBufferStorage;\r
+  UINT8                *TemBuffer;\r
+  CHAR16               *TemName;\r
+  CHAR16               *TemString;\r
+  UINTN                Index;\r
+  HII_NAME_VALUE_NODE  *Node;\r
+  EFI_STATUS           Status;\r
+\r
+  if ((FormSet == NULL) || (Form == NULL) || (Question == NULL) || (QuestionValue == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = EFI_SUCCESS;\r
+  Node   = NULL;\r
+\r
+  //\r
+  // If Question value is provided by an Expression, then it is read only\r
+  //\r
+  if ((Question->ValueExpression != NULL) || (Question->Value.Type != QuestionValue->Type)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Before set question value, evaluate its write expression.\r
+  //\r
+  if ((Question->WriteExpression != NULL) && (Form->FormType == STANDARD_MAP_FORM_TYPE)) {\r
+    Status = EvaluateHiiExpression (FormSet, Form, Question->WriteExpression);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  Storage = Question->Storage;\r
+  if (Storage != NULL) {\r
+    StorageWidth = Question->StorageWidth;\r
+    if (Question->Value.Type == EFI_IFR_TYPE_BUFFER) {\r
+      Question->Value.BufferLen = QuestionValue->BufferLen;\r
+      Question->Value.Buffer    = AllocateCopyPool (QuestionValue->BufferLen, QuestionValue->Buffer);\r
+      if (Question->Value.Buffer == NULL) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      Question->Value.BufferValueType = QuestionValue->BufferValueType;\r
+      Src                             = Question->Value.Buffer;\r
+    } else if (Question->Value.Type == EFI_IFR_TYPE_STRING) {\r
+      Question->Value.Value.string = QuestionValue->Value.string;\r
+      TemString                    = HiiGetString (FormSet->HiiHandle, QuestionValue->Value.string, NULL);\r
+      if (TemString == NULL) {\r
+        return EFI_ABORTED;\r
+      }\r
+\r
+      Question->Value.BufferLen = Question->StorageWidth;\r
+      Question->Value.Buffer    = AllocateZeroPool (Question->StorageWidth);\r
+      if (Question->Value.Buffer == NULL) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      CopyMem (Question->Value.Buffer, TemString, StrSize (TemString));\r
+      Src = Question->Value.Buffer;\r
+    } else {\r
+      CopyMem (&Question->Value.Value, &QuestionValue->Value, sizeof (EFI_IFR_TYPE_VALUE));\r
+      Src = (UINT8 *)&Question->Value.Value;\r
+    }\r
+\r
+    if ((Storage->Type == EFI_HII_VARSTORE_BUFFER) || (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
+      IsBufferStorage = TRUE;\r
+    } else {\r
+      IsBufferStorage = FALSE;\r
+    }\r
+\r
+    if (IsBufferStorage) {\r
+      //\r
+      // If the Question refer to bit filed, copy the value in related bit filed to storage edit buffer.\r
+      //\r
+      if (Question->QuestionReferToBitField) {\r
+        SetBitsQuestionValue (Question, Storage->Buffer + Question->VarStoreInfo.VarOffset, (UINT32)(*Src));\r
+      } else {\r
+        CopyMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
+      }\r
+    } else {\r
+      if (Question->Value.Type == EFI_IFR_TYPE_STRING) {\r
+        //\r
+        // Allocate enough string buffer.\r
+        //\r
+        ValueStr  = NULL;\r
+        BufferLen = ((StrLen ((CHAR16 *)Src) * 4) + 1) * sizeof (CHAR16);\r
+        ValueStr  = AllocatePool (BufferLen);\r
+        if (ValueStr == NULL) {\r
+          if (Question->Value.Buffer != NULL) {\r
+            FreePool (Question->Value.Buffer);\r
+          }\r
+\r
+          return EFI_OUT_OF_RESOURCES;\r
+        }\r
+\r
+        //\r
+        // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
+        //\r
+        TemName   = (CHAR16 *)Src;\r
+        TemString = ValueStr;\r
+        for ( ; *TemName != L'\0'; TemName++) {\r
+          UnicodeValueToStringS (\r
+            TemString,\r
+            BufferLen - ((UINTN)TemString - (UINTN)ValueStr),\r
+            PREFIX_ZERO | RADIX_HEX,\r
+            *TemName,\r
+            4\r
+            );\r
+          TemString += StrnLenS (TemString, (BufferLen - ((UINTN)TemString - (UINTN)ValueStr)) / sizeof (CHAR16));\r
+        }\r
+      } else {\r
+        BufferLen = StorageWidth * 2 + 1;\r
+        ValueStr  = AllocateZeroPool (BufferLen * sizeof (CHAR16));\r
+        if (ValueStr == NULL) {\r
+          if (Question->Value.Buffer != NULL) {\r
+            FreePool (Question->Value.Buffer);\r
+          }\r
+\r
+          return EFI_OUT_OF_RESOURCES;\r
+        }\r
+\r
+        //\r
+        // Convert Buffer to Hex String\r
+        //\r
+        TemBuffer = Src + StorageWidth - 1;\r
+        TemString = ValueStr;\r
+        for (Index = 0; Index < StorageWidth; Index++, TemBuffer--) {\r
+          UnicodeValueToStringS (\r
+            TemString,\r
+            BufferLen * sizeof (CHAR16) - ((UINTN)TemString - (UINTN)ValueStr),\r
+            PREFIX_ZERO | RADIX_HEX,\r
+            *TemBuffer,\r
+            2\r
+            );\r
+          TemString += StrnLenS (TemString, BufferLen - ((UINTN)TemString - (UINTN)ValueStr) / sizeof (CHAR16));\r
+        }\r
+      }\r
+\r
+      Status = SetValueByName (Storage, Question->VariableName, ValueStr, &Node);\r
+      FreePool (ValueStr);\r
+      if (EFI_ERROR (Status)) {\r
+        if (Question->Value.Buffer != NULL) {\r
+          FreePool (Question->Value.Buffer);\r
+        }\r
+\r
+        return Status;\r
+      }\r
+    }\r
+  } else {\r
+    if (Question->Value.Type == EFI_IFR_TYPE_BUFFER) {\r
+      Question->Value.BufferLen = QuestionValue->BufferLen;\r
+      Question->Value.Buffer    = AllocateCopyPool (QuestionValue->BufferLen, QuestionValue->Buffer);\r
+      if (Question->Value.Buffer == NULL) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      Question->Value.BufferValueType = QuestionValue->BufferValueType;\r
+    } else if (Question->Value.Type == EFI_IFR_TYPE_STRING) {\r
+      Question->Value.Value.string = QuestionValue->Value.string;\r
+      TemString                    = HiiGetString (FormSet->HiiHandle, QuestionValue->Value.string, NULL);\r
+      if (TemString == NULL) {\r
+        return EFI_ABORTED;\r
+      }\r
+\r
+      Question->Value.BufferLen = (UINT16)StrSize (TemString);\r
+      Question->Value.Buffer    = AllocateZeroPool (QuestionValue->BufferLen);\r
+      if (Question->Value.Buffer == NULL) {\r
+        FreePool (TemString);\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      CopyMem (Question->Value.Buffer, TemString, StrSize (TemString));\r
+      FreePool (TemString);\r
+    } else {\r
+      CopyMem (&Question->Value.Value, &QuestionValue->Value, sizeof (EFI_IFR_TYPE_VALUE));\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Get Question's current Value from storage.\r
+\r
+  @param[in]     FormSet                FormSet data structure.\r
+  @param[in]     Form                   Form data structure.\r
+  @param[in,out] Question               Question to be initialized.\r
+\r
+  @return the current Question Value in storage if success.\r
+  @return NULL if Question is not found or any error occurs.\r
+\r
+**/\r
+HII_STATEMENT_VALUE *\r
+RetrieveQuestion (\r
+  IN     HII_FORMSET    *FormSet,\r
+  IN     HII_FORM       *Form,\r
+  IN OUT HII_STATEMENT  *Question\r
+  )\r
+{\r
+  EFI_STATUS                       Status;\r
+  EFI_HII_CONFIG_ROUTING_PROTOCOL  *HiiConfigRouting;\r
+  EFI_BROWSER_ACTION_REQUEST       ActionRequest;\r
+  HII_FORMSET_STORAGE              *Storage;\r
+  HII_STATEMENT_VALUE              *QuestionValue;\r
+  EFI_IFR_TYPE_VALUE               *TypeValue;\r
+  EFI_TIME                         EfiTime;\r
+  BOOLEAN                          Enabled;\r
+  BOOLEAN                          Pending;\r
+  UINT8                            *Dst;\r
+  UINTN                            StorageWidth;\r
+  CHAR16                           *ConfigRequest;\r
+  CHAR16                           *Progress;\r
+  CHAR16                           *Result;\r
+  CHAR16                           *ValueStr;\r
+  UINTN                            Length;\r
+  BOOLEAN                          IsBufferStorage;\r
+  CHAR16                           *NewHiiString;\r
+\r
+  if ((FormSet == NULL) || (Form == NULL) || (Question == NULL)) {\r
+    return NULL;\r
+  }\r
+\r
+  Status   = EFI_SUCCESS;\r
+  ValueStr = NULL;\r
+  Result   = NULL;\r
+\r
+  QuestionValue = AllocateZeroPool (sizeof (HII_STATEMENT_VALUE));\r
+  if (QuestionValue == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  QuestionValue->Type      = Question->Value.Type;\r
+  QuestionValue->BufferLen = Question->Value.BufferLen;\r
+  if (QuestionValue->BufferLen != 0) {\r
+    QuestionValue->Buffer = AllocateZeroPool (QuestionValue->BufferLen);\r
+    if (QuestionValue->Buffer == NULL) {\r
+      FreePool (QuestionValue);\r
+      return NULL;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Question value is provided by RTC\r
+  //\r
+  Storage      = Question->Storage;\r
+  StorageWidth = Question->StorageWidth;\r
+\r
+  if (Storage == NULL) {\r
+    //\r
+    // It's a Question without storage, or RTC date/time\r
+    //\r
+    if ((Question->Operand == EFI_IFR_DATE_OP) || (Question->Operand == EFI_IFR_TIME_OP)) {\r
+      //\r
+      // Date and time define the same Flags bit\r
+      //\r
+      switch (Question->ExtraData.Flags & EFI_QF_DATE_STORAGE) {\r
+        case QF_DATE_STORAGE_TIME:\r
+\r
+          Status = gRT->GetTime (&EfiTime, NULL);\r
+          break;\r
+\r
+        case QF_DATE_STORAGE_WAKEUP:\r
+\r
+          Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
+          break;\r
+\r
+        case QF_DATE_STORAGE_NORMAL:\r
+        default:\r
+\r
+          goto ON_ERROR;\r
+      }\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        if (Question->Operand == EFI_IFR_DATE_OP) {\r
+          QuestionValue->Value.date.Year  = 0xff;\r
+          QuestionValue->Value.date.Month = 0xff;\r
+          QuestionValue->Value.date.Day   = 0xff;\r
+        } else {\r
+          QuestionValue->Value.time.Hour   = 0xff;\r
+          QuestionValue->Value.time.Minute = 0xff;\r
+          QuestionValue->Value.time.Second = 0xff;\r
+        }\r
+\r
+        return QuestionValue;\r
+      }\r
+\r
+      if (Question->Operand == EFI_IFR_DATE_OP) {\r
+        QuestionValue->Value.date.Year  = EfiTime.Year;\r
+        QuestionValue->Value.date.Month = EfiTime.Month;\r
+        QuestionValue->Value.date.Day   = EfiTime.Day;\r
+      } else {\r
+        QuestionValue->Value.time.Hour   = EfiTime.Hour;\r
+        QuestionValue->Value.time.Minute = EfiTime.Minute;\r
+        QuestionValue->Value.time.Second = EfiTime.Second;\r
+      }\r
+    } else {\r
+      if (((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) ||\r
+          (FormSet->ConfigAccess == NULL))\r
+      {\r
+        goto ON_ERROR;\r
+      }\r
+\r
+      if (QuestionValue->Type == EFI_IFR_TYPE_BUFFER) {\r
+        //\r
+        // For OrderedList, passing in the value buffer to Callback()\r
+        //\r
+        TypeValue = (EFI_IFR_TYPE_VALUE *)QuestionValue->Buffer;\r
+      } else {\r
+        TypeValue = &QuestionValue->Value;\r
+      }\r
+\r
+      ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+      Status        = FormSet->ConfigAccess->Callback (\r
+                                               FormSet->ConfigAccess,\r
+                                               EFI_BROWSER_ACTION_RETRIEVE,\r
+                                               Question->QuestionId,\r
+                                               QuestionValue->Type,\r
+                                               TypeValue,\r
+                                               &ActionRequest\r
+                                               );\r
+\r
+      if (!EFI_ERROR (Status) && (QuestionValue->Type == EFI_IFR_TYPE_STRING)) {\r
+        if (TypeValue->string == 0) {\r
+          goto ON_ERROR;\r
+        }\r
+\r
+        NewHiiString = GetTokenString (TypeValue->string, FormSet->HiiHandle);\r
+        if (NewHiiString == NULL) {\r
+          goto ON_ERROR;\r
+        }\r
+\r
+        QuestionValue->Buffer = AllocatePool (StrSize (NewHiiString));\r
+        if (QuestionValue->Buffer == NULL) {\r
+          FreePool (NewHiiString);\r
+          goto ON_ERROR;\r
+        }\r
+\r
+        CopyMem (QuestionValue->Buffer, NewHiiString, StrSize (NewHiiString));\r
+        QuestionValue->BufferLen = (UINT16)StrSize (NewHiiString);\r
+\r
+        FreePool (NewHiiString);\r
+      }\r
+    }\r
+\r
+    return QuestionValue;\r
+  }\r
+\r
+  //\r
+  // Question value is provided by EFI variable\r
+  //\r
+  if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+    if ((QuestionValue->Type != EFI_IFR_TYPE_BUFFER) && (QuestionValue->Type != EFI_IFR_TYPE_STRING)) {\r
+      Dst          = QuestionValue->Buffer;\r
+      StorageWidth = QuestionValue->BufferLen;\r
+    } else {\r
+      Dst          = (UINT8 *)&QuestionValue->Value;\r
+      StorageWidth = sizeof (EFI_IFR_TYPE_VALUE);\r
+    }\r
+\r
+    Status = gRT->GetVariable (\r
+                    Question->VariableName,\r
+                    &Storage->Guid,\r
+                    NULL,\r
+                    &StorageWidth,\r
+                    Dst\r
+                    );\r
+\r
+    return QuestionValue;\r
+  }\r
+\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiHiiConfigRoutingProtocolGuid,\r
+                  NULL,\r
+                  (VOID **)&HiiConfigRouting\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_ERROR;\r
+  }\r
+\r
+  if (QuestionValue->BufferLen != 0) {\r
+    Dst = QuestionValue->Buffer;\r
+  } else {\r
+    Dst = (UINT8 *)&QuestionValue->Value;\r
+  }\r
+\r
+  if ((Storage->Type == EFI_HII_VARSTORE_BUFFER) || (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
+    IsBufferStorage = TRUE;\r
+  } else {\r
+    IsBufferStorage = FALSE;\r
+  }\r
+\r
+  Storage = GetFstStgFromVarId (FormSet, Question->VarStoreId);\r
+  if (Storage == NULL) {\r
+    goto ON_ERROR;\r
+  }\r
+\r
+  //\r
+  // <ConfigRequest> ::= <ConfigHdr> + <BlockName> || <ConfigHdr> + "&" + <VariableName>\r
+  //\r
+  if (IsBufferStorage) {\r
+    Length  = StrLen (Storage->ConfigHdr);\r
+    Length += StrLen (Question->BlockName);\r
+  } else {\r
+    Length  = StrLen (Storage->ConfigHdr);\r
+    Length += StrLen (Question->VariableName) + 1;\r
+  }\r
+\r
+  ConfigRequest = AllocatePool ((Length + 1) * sizeof (CHAR16));\r
+  if (ConfigRequest == NULL) {\r
+    goto ON_ERROR;\r
+  }\r
+\r
+  StrCpyS (ConfigRequest, Length + 1, Storage->ConfigHdr);\r
+  if (IsBufferStorage) {\r
+    StrCatS (ConfigRequest, Length + 1, Question->BlockName);\r
+  } else {\r
+    StrCatS (ConfigRequest, Length + 1, L"&");\r
+    StrCatS (ConfigRequest, Length + 1, Question->VariableName);\r
+  }\r
+\r
+  //\r
+  // Request current settings from Configuration Driver\r
+  //\r
+  Status = HiiConfigRouting->ExtractConfig (\r
+                               HiiConfigRouting,\r
+                               ConfigRequest,\r
+                               &Progress,\r
+                               &Result\r
+                               );\r
+  FreePool (ConfigRequest);\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_ERROR;\r
+  }\r
+\r
+  if (IsBufferStorage) {\r
+    ValueStr = StrStr (Result, L"&VALUE");\r
+    if (ValueStr == NULL) {\r
+      FreePool (Result);\r
+      goto ON_ERROR;\r
+    }\r
+\r
+    ValueStr = ValueStr + 6;\r
+  } else {\r
+    ValueStr = Result + Length;\r
+  }\r
+\r
+  if (*ValueStr != '=') {\r
+    FreePool (Result);\r
+    goto ON_ERROR;\r
+  }\r
+\r
+  ValueStr++;\r
+  Status = BufferToQuestionValue (Question, ValueStr, QuestionValue);\r
+  if (EFI_ERROR (Status)) {\r
+    FreePool (Result);\r
+    goto ON_ERROR;\r
+  }\r
+\r
+  if (Result != NULL) {\r
+    FreePool (Result);\r
+  }\r
+\r
+  return QuestionValue;\r
+\r
+ON_ERROR:\r
+\r
+  if (QuestionValue->Buffer != NULL) {\r
+    FreePool (QuestionValue->Buffer);\r
+  }\r
+\r
+  FreePool (QuestionValue);\r
+\r
+  return NULL;\r
+}\r
diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.inf b/RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.inf
new file mode 100644 (file)
index 0000000..cab3f8a
--- /dev/null
@@ -0,0 +1,62 @@
+## @file\r
+#  Library to handle HII IFR data.\r
+#\r
+#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+#  (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>\r
+#  Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.\r
+#\r
+#  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = HiiUtilityLib\r
+  FILE_GUID                      = D00DA028-F19A-47AF-B22A-6EE9E8BD7335\r
+  MODULE_TYPE                    = UEFI_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = HiiUtilityLib|DXE_DRIVER UEFI_DRIVER UEFI_APPLICATION\r
+\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 EBC\r
+#\r
+\r
+[Sources]\r
+  HiiUtilityLib.c\r
+  HiiExpression.c\r
+  HiiUtilityInternal.c\r
+  HiiIfrParse.c\r
+  HiiInternal.h\r
+  HiiExpression.h\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  RedfishPkg/RedfishPkg.dec\r
+\r
+[LibraryClasses]\r
+  PrintLib\r
+  DebugLib\r
+  BaseMemoryLib\r
+  UefiRuntimeServicesTableLib\r
+  UefiBootServicesTableLib\r
+  MemoryAllocationLib\r
+  HiiLib\r
+\r
+[Guids]\r
+  gZeroGuid\r
+  gEdkiiIfrBitVarstoreGuid\r
+  gEfiHiiPlatformSetupFormsetGuid\r
+  gEfiHiiStandardFormGuid\r
+\r
+[Protocols]\r
+  gEfiHiiDatabaseProtocolGuid\r
+  gEfiHiiConfigRoutingProtocolGuid\r
+  gEfiHiiConfigAccessProtocolGuid\r
+  gEfiDevicePathFromTextProtocolGuid\r
+  gEfiUnicodeCollation2ProtocolGuid\r
+  gEfiRegularExpressionProtocolGuid\r
+  gEfiUserManagerProtocolGuid\r
+\r
+[Depex]\r
+  TRUE\r
index 904630ae4be60235951f118087bcdfeebb5c5815..e2892ce9cec111f09929c1dc8a7120b8e359e1d3 100644 (file)
   #   Library provides Redfish debug functions.\r
   RedfishDebugLib|Include/Library/RedfishDebugLib.h\r
 \r
+  ##  @libraryclass  Provides the library functions to parse IFR binary data.\r
+  #\r
+  HiiUtilityLib|Include/Library/HiiUtilityLib.h\r
+\r
 [LibraryClasses.Common.Private]\r
   ##  @libraryclass  Provides the private C runtime library functions.\r
   #   CRT library is currently used by edk2 JsonLib (open source\r