public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v3 2/5] RedfishPkg: introduce HII utility helper library
@ 2023-04-19  9:09 Nickle Wang
  2023-04-19  9:48 ` Chang, Abner
  0 siblings, 1 reply; 2+ messages in thread
From: Nickle Wang @ 2023-04-19  9:09 UTC (permalink / raw)
  To: devel; +Cc: Abner Chang, Igor Kulchytskyy, Nick Ramirez

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>
---
 RedfishPkg/RedfishPkg.dec                     |    4 +
 .../Library/HiiUtilityLib/HiiUtilityLib.inf   |   62 +
 RedfishPkg/Include/Library/HiiUtilityLib.h    | 1204 ++++
 .../Library/HiiUtilityLib/HiiExpression.h     |  191 +
 .../Library/HiiUtilityLib/HiiInternal.h       |  376 ++
 .../Library/HiiUtilityLib/HiiExpression.c     | 1439 ++++
 .../Library/HiiUtilityLib/HiiIfrParse.c       | 2715 ++++++++
 .../HiiUtilityLib/HiiUtilityInternal.c        | 5770 +++++++++++++++++
 .../Library/HiiUtilityLib/HiiUtilityLib.c     |  810 +++
 9 files changed, 12571 insertions(+)
 create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.inf
 create mode 100644 RedfishPkg/Include/Library/HiiUtilityLib.h
 create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiExpression.h
 create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiInternal.h
 create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiExpression.c
 create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiIfrParse.c
 create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiUtilityInternal.c
 create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.c

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


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH v3 2/5] RedfishPkg: introduce HII utility helper library
  2023-04-19  9:09 [PATCH v3 2/5] RedfishPkg: introduce HII utility helper library Nickle Wang
@ 2023-04-19  9:48 ` Chang, Abner
  0 siblings, 0 replies; 2+ messages in thread
From: Chang, Abner @ 2023-04-19  9:48 UTC (permalink / raw)
  To: Nickle Wang, devel@edk2.groups.io; +Cc: Igor Kulchytskyy, Nick Ramirez

[AMD Official Use Only - General]

Reviewed-by: Abner Chang <abner.chang@amd.com>

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

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2023-04-19  9:49 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-04-19  9:09 [PATCH v3 2/5] RedfishPkg: introduce HII utility helper library Nickle Wang
2023-04-19  9:48 ` Chang, Abner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox