public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH 2/5] RedfishPkg: introduce HII utility helper library
@ 2023-04-13  6:20 Nickle Wang
  2023-04-16  3:34 ` Chang, Abner
  0 siblings, 1 reply; 2+ messages in thread
From: Nickle Wang @ 2023-04-13  6:20 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   |   61 +
 RedfishPkg/Include/Library/HiiUtilityLib.h    | 1205 ++++
 .../Library/HiiUtilityLib/HiiExpression.h     |  214 +
 .../Library/HiiUtilityLib/HiiInternal.h       |  369 ++
 .../Library/HiiUtilityLib/HiiExpression.c     | 1442 ++++
 .../Library/HiiUtilityLib/HiiIfrParse.c       | 2717 ++++++++
 .../HiiUtilityLib/HiiUtilityInternal.c        | 5770 +++++++++++++++++
 .../Library/HiiUtilityLib/HiiUtilityLib.c     |  810 +++
 9 files changed, 12592 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..58306aa73227
--- /dev/null
+++ b/RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.inf
@@ -0,0 +1,61 @@
+## @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>
+#
+#  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..e2355b2f2898
--- /dev/null
+++ b/RedfishPkg/Include/Library/HiiUtilityLib.h
@@ -0,0 +1,1205 @@
+/** @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  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
+  );
+
+/**
+  Initialize a Formset and get current setting for Questions.
+
+  @param  FormSet                FormSet data structure.
+
+**/
+VOID
+InitializeFormSet (
+  IN OUT HII_FORMSET  *FormSet
+  );
+
+/**
+  Free resources allocated for a FormSet.
+
+  @param  FormSet                Pointer of the FormSet
+
+**/
+VOID
+DestroyFormSet (
+  IN OUT HII_FORMSET  *FormSet
+  );
+
+/**
+  Save Question Value to the memory, but not to storage.
+
+  @param  FormSet                FormSet data structure.
+  @param  Form                   Form data structure.
+  @param  Question               Pointer to the Question.
+  @param  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  FormSet                FormSet data structure.
+  @param  Form                   Form data structure.
+  @param  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  FormSet                FormSet which contains the Form.
+  @param  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  FormSet                FormSet associated with this expression.
+  @param  Form                   Form associated with this expression.
+  @param  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  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..1005e67220fb
--- /dev/null
+++ b/RedfishPkg/Library/HiiUtilityLib/HiiExpression.h
@@ -0,0 +1,214 @@
+/** @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
+  );
+
+/**
+  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
diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiInternal.h b/RedfishPkg/Library/HiiUtilityLib/HiiInternal.h
new file mode 100644
index 000000000000..b001502b34fa
--- /dev/null
+++ b/RedfishPkg/Library/HiiUtilityLib/HiiInternal.h
@@ -0,0 +1,369 @@
+/** @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>
+
+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  Dest                   Location to copy string
+  @param  Src                    String to copy
+
+**/
+VOID
+NewStringCpy (
+  IN OUT CHAR16  **Dest,
+  IN     CHAR16  *Src
+  );
+
+/**
+  Set Value of given Name in a NameValue Storage.
+
+  @param  Storage                The NameValue Storage.
+  @param  Name                   The Name.
+  @param  Value                  The Value to set.
+  @param  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  Question        The question refer to bit field.
+  @param  Buffer          Point to the buffer which the question value get from.
+  @param  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  Question        The question refer to bit field.
+  @param  Buffer          Point to the buffer which the question value set to.
+  @param  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  Question              The question.
+  @param  Value                 Unicode buffer save the question value.
+  @param  QuestionValue         The Question Value retrieved from Buffer.
+
+  @retval  Status whether convert the value success.
+
+**/
+EFI_STATUS
+BufferToValue (
+  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  Token                  The String's ID.
+  @param  HiiHandle              The package list in the HII database to search for
+                                 the specified string.
+
+  @return The output string.
+
+**/
+CHAR16 *
+GetToken (
+  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 ConfigString  String to be converted
+
+**/
+VOID
+EFIAPI
+HiiToLower (
+  IN EFI_STRING  ConfigString
+  );
+
+/**
+  Evaluate if the result is a non-zero value.
+
+  @param  Result           The result to be evaluated.
+
+  @retval TRUE             It is a non-zero value.
+  @retval FALSE            It is a zero value.
+
+**/
+BOOLEAN
+IsTrue (
+  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
+NewString (
+  IN CHAR16          *String,
+  IN EFI_HII_HANDLE  HiiHandle
+  );
+
+/**
+  Perform nosubmitif check for a Form.
+
+  @param  FormSet                FormSet data structure.
+  @param  Form                   Form data structure.
+  @param  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  FormSet                FormSet data structure.
+  @param  CurrentForm            Current input form data structure.
+  @param  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  Storage                The Storage to be converted.
+  @param  ConfigResp             The returned <ConfigResp>.
+  @param  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  Storage                The Storage to receive the settings.
+  @param  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  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  BinaryLength           The length of the FormSet IFR binary.
+  @param  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  FormSet                FormSet data structure.
+  @param  Storage                Buffer Storage.
+
+**/
+VOID
+LoadStorage (
+  IN HII_FORMSET          *FormSet,
+  IN HII_FORMSET_STORAGE  *Storage
+  );
+
+/**
+  Free resources of a Form.
+
+  @param  FormSet                Pointer of the FormSet
+  @param  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  FormSet                Pointer of the current FormSet.
+  @param  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  Value                  HII Value to be converted.
+
+**/
+VOID
+ExtendValueToU64 (
+  IN HII_STATEMENT_VALUE  *Value
+  );
+
+/**
+  Parse opcodes in the formset IFR binary.
+
+  @param  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..759ef3bb1836
--- /dev/null
+++ b/RedfishPkg/Library/HiiUtilityLib/HiiExpression.c
@@ -0,0 +1,1442 @@
+/** @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;
+
+#define EXPRESSION_STACK_SIZE_INCREMENT  0x100
+
+/**
+  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  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 (IsTrue (&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..8459ad0822c9
--- /dev/null
+++ b/RedfishPkg/Library/HiiUtilityLib/HiiIfrParse.c
@@ -0,0 +1,2717 @@
+/** @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"
+
+#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))
+
+/**
+  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 = GetToken (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
+               );
+    HiiToLower (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 = GetToken (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 = IsTrue (&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 = NewString ((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 = NewString ((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 = IsTrue (&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..9a328e53c0a5
--- /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  Dest                   Location to copy string
+  @param  Src                    String to copy
+
+**/
+VOID
+NewStringCpy (
+  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  Storage                The NameValue Storage.
+  @param  Name                   The Name.
+  @param  Value                  The Value to set.
+  @param  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  Question        The question refer to bit field.
+  @param  Buffer          Point to the buffer which the question value get from.
+  @param  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  Question        The question refer to bit field.
+  @param  Buffer          Point to the buffer which the question value set to.
+  @param  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  Question              The question.
+  @param  Value                 Unicode buffer save the question value.
+  @param  QuestionValue         The Question Value retrieved from Buffer.
+
+  @retval  Status whether convert the value success.
+
+**/
+EFI_STATUS
+BufferToValue (
+  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  Token                  The String's ID.
+  @param  HiiHandle              The package list in the HII database to search for
+                                 the specified string.
+
+  @return The output string.
+
+**/
+CHAR16 *
+GetToken (
+  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 ConfigString  String to be converted
+
+**/
+VOID
+EFIAPI
+HiiToLower (
+  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  Result           The result to be evaluated.
+
+  @retval TRUE             It is a non-zero value.
+  @retval FALSE            It is a zero value.
+
+**/
+BOOLEAN
+IsTrue (
+  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
+NewString (
+  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  FormSet                FormSet data structure.
+  @param  Form                   Form data structure.
+  @param  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 (IsTrue (&Expression->Result)) {
+      return EFI_NOT_READY;
+    }
+
+    Link = GetNextNode (ListHead, Link);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Perform NoSubmit check for each Form in FormSet.
+
+  @param  FormSet                FormSet data structure.
+  @param  CurrentForm            Current input form data structure.
+  @param  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  *NewString;
+  UINTN   MaxLen;
+
+  if (*Dest == NULL) {
+    NewStringCpy (Dest, Src);
+    return;
+  }
+
+  MaxLen    = (StrSize (*Dest) + StrSize (Src) - 2) / sizeof (CHAR16);
+  NewString = AllocatePool (MaxLen * sizeof (CHAR16));
+  if (NewString == NULL) {
+    return;
+  }
+
+  StrCpyS (NewString, MaxLen, *Dest);
+  StrCatS (NewString, MaxLen, Src);
+
+  FreePool (*Dest);
+  *Dest = NewString;
+}
+
+/**
+  Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
+
+  @param  Storage                The Storage to be converted.
+  @param  ConfigResp             The returned <ConfigResp>.
+  @param  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  Storage                The Storage to receive the settings.
+  @param  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  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  BinaryLength           The length of the FormSet IFR binary.
+  @param  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  FormSet                FormSet data structure.
+  @param  Storage                Buffer Storage.
+
+**/
+VOID
+LoadStorage (
+  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  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  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
+  );
+
+/**
+  Initialize a Formset and get current setting for Questions.
+
+  @param  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) {
+      NewStringCpy (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 = BufferToValue (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 = BufferToValue (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 = GetToken (Value1->Value.string, HiiHandle);
+    if (Str1 == NULL) {
+      //
+      // String not found
+      //
+      return EFI_NOT_FOUND;
+    }
+
+    Str2 = GetToken (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 = NewString (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 = GetToken (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] = GetToken (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 = NewString (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] = GetToken (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] = GetToken (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] = GetToken (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 = GetToken (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 = NewString (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] = GetToken (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 = NewString (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] = GetToken (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 = GetToken (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 = GetToken (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      = GetToken (Value->Value.u16, FormSet->HiiHandle);
+        if (StrPtr == NULL) {
+          //
+          // If String not exit, push an empty string
+          //
+          Value->Value.string = NewString (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 = GetToken (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 = GetToken (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 = NewString (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.
+  //
+  HiiToLower (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);
+  HiiToLower (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 BufferToValue (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", __FUNCTION__));
+    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..e6c9361bdec2
--- /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);
+    LoadStorage (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  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  FormSet                FormSet which contains the Form.
+  @param  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  FormSet                FormSet data structure.
+  @param  Form                   Form data structure.
+  @param  Question               Pointer to the Question.
+  @param  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  FormSet                FormSet data structure.
+  @param  Form                   Form data structure.
+  @param  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                           *NewString;
+
+  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;
+        }
+
+        NewString = GetToken (TypeValue->string, FormSet->HiiHandle);
+        if (NewString == NULL) {
+          goto ON_ERROR;
+        }
+
+        QuestionValue->Buffer = AllocatePool (StrSize (NewString));
+        if (QuestionValue->Buffer == NULL) {
+          FreePool (NewString);
+          goto ON_ERROR;
+        }
+
+        CopyMem (QuestionValue->Buffer, NewString, StrSize (NewString));
+        QuestionValue->BufferLen = (UINT16)StrSize (NewString);
+
+        FreePool (NewString);
+      }
+    }
+
+    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 = BufferToValue (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 2/5] RedfishPkg: introduce HII utility helper library
  2023-04-13  6:20 [PATCH 2/5] RedfishPkg: introduce HII utility helper library Nickle Wang
@ 2023-04-16  3:34 ` Chang, Abner
  0 siblings, 0 replies; 2+ messages in thread
From: Chang, Abner @ 2023-04-16  3:34 UTC (permalink / raw)
  To: Nickle Wang, devel@edk2.groups.io; +Cc: Igor Kulchytskyy, Nick Ramirez

[AMD Official Use Only - General]



> -----Original Message-----
> From: Nickle Wang <nicklew@nvidia.com>
> Sent: Thursday, April 13, 2023 2:21 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 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   |   61 +
>  RedfishPkg/Include/Library/HiiUtilityLib.h    | 1205 ++++
>  .../Library/HiiUtilityLib/HiiExpression.h     |  214 +
>  .../Library/HiiUtilityLib/HiiInternal.h       |  369 ++
>  .../Library/HiiUtilityLib/HiiExpression.c     | 1442 ++++
>  .../Library/HiiUtilityLib/HiiIfrParse.c       | 2717 ++++++++
>  .../HiiUtilityLib/HiiUtilityInternal.c        | 5770 +++++++++++++++++
>  .../Library/HiiUtilityLib/HiiUtilityLib.c     |  810 +++
>  9 files changed, 12592 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..58306aa73227
> --- /dev/null
> +++ b/RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.inf
> @@ -0,0 +1,61 @@
> +## @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>
> +#
> +#  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..e2355b2f2898
> --- /dev/null
> +++ b/RedfishPkg/Include/Library/HiiUtilityLib.h
> @@ -0,0 +1,1205 @@
> +/** @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
> +
> +**/
> +
Could you please use "///" for the comments of structures and "///<" for the structure members? I know some of header files we introduced earlier had inconsistent comment format of the structures. However, we can have the consistent comment format for the later introduced header file, this is also consistent with the example given in edk2 C coding standard.

Second, there are some "in" and "out" notation missed in @param, please also check it.



> +#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  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
> +  );
> +
> +/**
> +  Initialize a Formset and get current setting for Questions.
> +
> +  @param  FormSet                FormSet data structure.
> +
> +**/
> +VOID
> +InitializeFormSet (
> +  IN OUT HII_FORMSET  *FormSet
> +  );
> +
> +/**
> +  Free resources allocated for a FormSet.
> +
> +  @param  FormSet                Pointer of the FormSet
> +
> +**/
> +VOID
> +DestroyFormSet (
> +  IN OUT HII_FORMSET  *FormSet
> +  );
> +
> +/**
> +  Save Question Value to the memory, but not to storage.
> +
> +  @param  FormSet                FormSet data structure.
> +  @param  Form                   Form data structure.
> +  @param  Question               Pointer to the Question.
> +  @param  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  FormSet                FormSet data structure.
> +  @param  Form                   Form data structure.
> +  @param  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  FormSet                FormSet which contains the Form.
> +  @param  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  FormSet                FormSet associated with this expression.
> +  @param  Form                   Form associated with this expression.
> +  @param  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  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_
There is an extra leading "_" of HII_UTILITY_LIB.

> diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiExpression.h
> b/RedfishPkg/Library/HiiUtilityLib/HiiExpression.h
> new file mode 100644
> index 000000000000..1005e67220fb
> --- /dev/null
> +++ b/RedfishPkg/Library/HiiUtilityLib/HiiExpression.h
> @@ -0,0 +1,214 @@
> +/** @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
> +  );
> +
> +/**
> +  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
> diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiInternal.h
> b/RedfishPkg/Library/HiiUtilityLib/HiiInternal.h
> new file mode 100644
> index 000000000000..b001502b34fa
> --- /dev/null
> +++ b/RedfishPkg/Library/HiiUtilityLib/HiiInternal.h
> @@ -0,0 +1,369 @@
> +/** @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_

There are some "in" and "out" are missed for @param in HiiInternal.h. Please also check all other files in this patch set.

Second, some functions are named unclearly. Could you please consider to give them obvious names?

> +
> +#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>
> +
> +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
> +//
For above comment block, you can either add an blank line (with "//") above comment or remove the blank line below comment.


> +#define CONFIG_REQUEST_STRING_INCREMENTAL  1024
> +
> +/**
> +  Allocate new memory and then copy the Unicode string Source to
> Destination.
> +
> +  @param  Dest                   Location to copy string
> +  @param  Src                    String to copy
> +
> +**/
> +VOID
> +NewStringCpy (
Can we name this NewStringCopy?


> +  IN OUT CHAR16  **Dest,
> +  IN     CHAR16  *Src
> +  );
> +
> +/**
> +  Set Value of given Name in a NameValue Storage.
> +
> +  @param  Storage                The NameValue Storage.
> +  @param  Name                   The Name.
> +  @param  Value                  The Value to set.
> +  @param  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  Question        The question refer to bit field.
> +  @param  Buffer          Point to the buffer which the question value get from.
> +  @param  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  Question        The question refer to bit field.
> +  @param  Buffer          Point to the buffer which the question value set to.
> +  @param  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  Question              The question.
> +  @param  Value                 Unicode buffer save the question value.
> +  @param  QuestionValue         The Question Value retrieved from Buffer.
> +
> +  @retval  Status whether convert the value success.
> +
> +**/
> +EFI_STATUS
> +BufferToValue (
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  Token                  The String's ID.
> +  @param  HiiHandle              The package list in the HII database to search for
> +                                 the specified string.
> +
> +  @return The output string.
> +
> +**/
> +CHAR16 *
> +GetToken (
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 ConfigString  String to be converted
> +
> +**/
> +VOID
> +EFIAPI
> +HiiToLower (
HiiStringToLowercase?

> +  IN EFI_STRING  ConfigString
> +  );
> +
> +/**
> +  Evaluate if the result is a non-zero value.
> +
> +  @param  Result           The result to be evaluated.
> +
> +  @retval TRUE             It is a non-zero value.
> +  @retval FALSE            It is a zero value.
> +
> +**/
> +BOOLEAN
> +IsTrue (
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
> +NewString (
NewHiiString?

> +  IN CHAR16          *String,
> +  IN EFI_HII_HANDLE  HiiHandle
> +  );
> +
> +/**
> +  Perform nosubmitif check for a Form.
> +
> +  @param  FormSet                FormSet data structure.
> +  @param  Form                   Form data structure.
> +  @param  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  FormSet                FormSet data structure.
> +  @param  CurrentForm            Current input form data structure.
> +  @param  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  Storage                The Storage to be converted.
> +  @param  ConfigResp             The returned <ConfigResp>.
> +  @param  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  Storage                The Storage to receive the settings.
> +  @param  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  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  BinaryLength           The length of the FormSet IFR binary.
> +  @param  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  FormSet                FormSet data structure.
> +  @param  Storage                Buffer Storage.
> +
> +**/
> +VOID
> +LoadStorage (
LoadFormSetStorage?

> +  IN HII_FORMSET          *FormSet,
> +  IN HII_FORMSET_STORAGE  *Storage
> +  );
> +
> +/**
> +  Free resources of a Form.
> +
> +  @param  FormSet                Pointer of the FormSet
> +  @param  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  FormSet                Pointer of the current FormSet.
> +  @param  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  Value                  HII Value to be converted.
> +
> +**/
> +VOID
> +ExtendValueToU64 (
> +  IN HII_STATEMENT_VALUE  *Value
> +  );
> +
> +/**
> +  Parse opcodes in the formset IFR binary.
> +
> +  @param  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_
An extra leading "_".


> diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiExpression.c
> b/RedfishPkg/Library/HiiUtilityLib/HiiExpression.c
> new file mode 100644
> index 000000000000..759ef3bb1836
> --- /dev/null
> +++ b/RedfishPkg/Library/HiiUtilityLib/HiiExpression.c
> @@ -0,0 +1,1442 @@
> +/** @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;
> +
> +#define EXPRESSION_STACK_SIZE_INCREMENT  0x100
You can move this definition to HiiInternal.h

> +
> +/**
> +  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  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 (IsTrue (&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..8459ad0822c9
> --- /dev/null
> +++ b/RedfishPkg/Library/HiiUtilityLib/HiiIfrParse.c
> @@ -0,0 +1,2717 @@
> +/** @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"
> +
> +#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))
Can we also move this definition to Hiiinternal.h?

Abner

> +
> +/**
> +  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 = GetToken (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
> +               );
> +    HiiToLower (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 = GetToken
> (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 = IsTrue (&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 = NewString ((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 = NewString ((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 = IsTrue (&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..9a328e53c0a5
> --- /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  Dest                   Location to copy string
> +  @param  Src                    String to copy
> +
> +**/
> +VOID
> +NewStringCpy (
> +  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  Storage                The NameValue Storage.
> +  @param  Name                   The Name.
> +  @param  Value                  The Value to set.
> +  @param  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  Question        The question refer to bit field.
> +  @param  Buffer          Point to the buffer which the question value get from.
> +  @param  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  Question        The question refer to bit field.
> +  @param  Buffer          Point to the buffer which the question value set to.
> +  @param  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  Question              The question.
> +  @param  Value                 Unicode buffer save the question value.
> +  @param  QuestionValue         The Question Value retrieved from Buffer.
> +
> +  @retval  Status whether convert the value success.
> +
> +**/
> +EFI_STATUS
> +BufferToValue (
> +  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  Token                  The String's ID.
> +  @param  HiiHandle              The package list in the HII database to search for
> +                                 the specified string.
> +
> +  @return The output string.
> +
> +**/
> +CHAR16 *
> +GetToken (
> +  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 ConfigString  String to be converted
> +
> +**/
> +VOID
> +EFIAPI
> +HiiToLower (
> +  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  Result           The result to be evaluated.
> +
> +  @retval TRUE             It is a non-zero value.
> +  @retval FALSE            It is a zero value.
> +
> +**/
> +BOOLEAN
> +IsTrue (
> +  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
> +NewString (
> +  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  FormSet                FormSet data structure.
> +  @param  Form                   Form data structure.
> +  @param  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 (IsTrue (&Expression->Result)) {
> +      return EFI_NOT_READY;
> +    }
> +
> +    Link = GetNextNode (ListHead, Link);
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Perform NoSubmit check for each Form in FormSet.
> +
> +  @param  FormSet                FormSet data structure.
> +  @param  CurrentForm            Current input form data structure.
> +  @param  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  *NewString;
> +  UINTN   MaxLen;
> +
> +  if (*Dest == NULL) {
> +    NewStringCpy (Dest, Src);
> +    return;
> +  }
> +
> +  MaxLen    = (StrSize (*Dest) + StrSize (Src) - 2) / sizeof (CHAR16);
> +  NewString = AllocatePool (MaxLen * sizeof (CHAR16));
> +  if (NewString == NULL) {
> +    return;
> +  }
> +
> +  StrCpyS (NewString, MaxLen, *Dest);
> +  StrCatS (NewString, MaxLen, Src);
> +
> +  FreePool (*Dest);
> +  *Dest = NewString;
> +}
> +
> +/**
> +  Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
> +
> +  @param  Storage                The Storage to be converted.
> +  @param  ConfigResp             The returned <ConfigResp>.
> +  @param  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  Storage                The Storage to receive the settings.
> +  @param  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  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  BinaryLength           The length of the FormSet IFR binary.
> +  @param  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  FormSet                FormSet data structure.
> +  @param  Storage                Buffer Storage.
> +
> +**/
> +VOID
> +LoadStorage (
> +  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  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  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
> +  );
> +
> +/**
> +  Initialize a Formset and get current setting for Questions.
> +
> +  @param  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) {
> +      NewStringCpy (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 = BufferToValue (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 = BufferToValue (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 = GetToken (Value1->Value.string, HiiHandle);
> +    if (Str1 == NULL) {
> +      //
> +      // String not found
> +      //
> +      return EFI_NOT_FOUND;
> +    }
> +
> +    Str2 = GetToken (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 = NewString (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 = GetToken (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] = GetToken (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 = NewString (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] = GetToken (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] = GetToken (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] = GetToken (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 = GetToken (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 = NewString (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] = GetToken (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 = NewString (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] = GetToken (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 = GetToken (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 = GetToken (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      = GetToken (Value->Value.u16, FormSet->HiiHandle);
> +        if (StrPtr == NULL) {
> +          //
> +          // If String not exit, push an empty string
> +          //
> +          Value->Value.string = NewString (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 = GetToken (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 = GetToken (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 = NewString (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.
> +  //
> +  HiiToLower (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);
> +  HiiToLower (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 BufferToValue (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",
> __FUNCTION__));
> +    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..e6c9361bdec2
> --- /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);
> +    LoadStorage (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  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  FormSet                FormSet which contains the Form.
> +  @param  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  FormSet                FormSet data structure.
> +  @param  Form                   Form data structure.
> +  @param  Question               Pointer to the Question.
> +  @param  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  FormSet                FormSet data structure.
> +  @param  Form                   Form data structure.
> +  @param  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                           *NewString;
> +
> +  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;
> +        }
> +
> +        NewString = GetToken (TypeValue->string, FormSet->HiiHandle);
> +        if (NewString == NULL) {
> +          goto ON_ERROR;
> +        }
> +
> +        QuestionValue->Buffer = AllocatePool (StrSize (NewString));
> +        if (QuestionValue->Buffer == NULL) {
> +          FreePool (NewString);
> +          goto ON_ERROR;
> +        }
> +
> +        CopyMem (QuestionValue->Buffer, NewString, StrSize (NewString));
> +        QuestionValue->BufferLen = (UINT16)StrSize (NewString);
> +
> +        FreePool (NewString);
> +      }
> +    }
> +
> +    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 = BufferToValue (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-16  3:34 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-04-13  6:20 [PATCH 2/5] RedfishPkg: introduce HII utility helper library Nickle Wang
2023-04-16  3:34 ` Chang, Abner

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