public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH RESEND 0/5] Implementation of EDKII Redfish Platform Config Protocol
@ 2021-10-28  1:07 Abner Chang
  2021-10-28  1:07 ` [PATCH RESEND 1/5] edk2-staging/RedfishPkg: EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL Abner Chang
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Abner Chang @ 2021-10-28  1:07 UTC (permalink / raw)
  To: devel; +Cc: nickle.wang, Liming Gao

EDKII Redfish Platform Config Protocol is an abstract driver that abstracts
the platform configuration format and storage from EDK2 Redfish Feature
driver. This protocol provides the interfaces to get and set platform
configuration with the format and configuration storage agnostic to the
Redfish feature driver. The platform can provide its own EDKII Redfish
Platform Config driver instance to access platform-specific configuration
format and storage.

On EDK2 open source, EDKII Redfish Platform Config
Protocol accesses the platform configuration in EDK2 HII defined format.

Refer to below link for he architecture design,
https://github.com/tianocore/edk2-staging/tree/edk2-redfish-client/RedfishClientPkg#edkii-redfish-platform-config-protocol-6

Signed-off-by: Nickle Wang <nickle.wang@hpe.com>
Cc: Abner Chang <abner.chang@hpe.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>

Abner Chang (5):
  edk2-staging/RedfishPkg: EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL
  edk2-staging/RedfishPkg: HII utility helper library
  edk2-staging/RedfishPkg: Implementation of
    EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL
  edk2-staging/RedfishPkg: Helper library of
    EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL
  edk2-staging/RedfishPkg: Enable Redfish Platform Config Protocol build
    process

 RedfishPkg/RedfishPkg.dec                     |   12 +
 RedfishPkg/RedfishComponents.dsc.inc          |    2 +
 RedfishPkg/RedfishLibs.dsc.inc                |    2 +
 RedfishPkg/RedfishPkg.dsc                     |    4 +
 .../Library/HiiUtilityLib/HiiUtilityLib.inf   |   61 +
 .../RedfishPlatformConfigLib.inf              |   41 +
 .../RedfishPlatformConfigDxe.inf              |   53 +
 RedfishPkg/Include/Library/HiiUtilityLib.h    | 1195 ++++
 .../Library/RedfishPlatformConfigLib.h        |  101 +
 .../Protocol/EdkIIRedfishPlatformConfig.h     |  147 +
 .../Library/HiiUtilityLib/HiiExpression.h     |  190 +
 .../Library/HiiUtilityLib/HiiInternal.h       |  371 ++
 .../RedfishPlatformConfigInternal.h           |   31 +
 .../RedfishPlatformConfigDxe.h                |   64 +
 .../RedfishPlatformConfigImpl.h               |  274 +
 .../Library/HiiUtilityLib/HiiExpression.c     | 1367 +++++
 .../Library/HiiUtilityLib/HiiIfrParse.c       | 2671 +++++++++
 .../HiiUtilityLib/HiiUtilityInternal.c        | 5045 +++++++++++++++++
 .../Library/HiiUtilityLib/HiiUtilityLib.c     |  855 +++
 .../RedfishPlatformConfigLib.c                |  243 +
 .../RedfishPlatformConfigDxe.c                | 1304 +++++
 .../RedfishPlatformConfigImpl.c               | 1240 ++++
 RedfishPkg/Redfish.fdf.inc                    |    2 +
 23 files changed, 15275 insertions(+)
 create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.inf
 create mode 100644 RedfishPkg/Library/RedfishPlatformConfigLib/RedfishPlatformConfigLib.inf
 create mode 100644 RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.inf
 create mode 100644 RedfishPkg/Include/Library/HiiUtilityLib.h
 create mode 100644 RedfishPkg/Include/Library/RedfishPlatformConfigLib.h
 create mode 100644 RedfishPkg/Include/Protocol/EdkIIRedfishPlatformConfig.h
 create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiExpression.h
 create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiInternal.h
 create mode 100644 RedfishPkg/Library/RedfishPlatformConfigLib/RedfishPlatformConfigInternal.h
 create mode 100644 RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.h
 create mode 100644 RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.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
 create mode 100644 RedfishPkg/Library/RedfishPlatformConfigLib/RedfishPlatformConfigLib.c
 create mode 100644 RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.c
 create mode 100644 RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.c

-- 
2.21.0.windows.1


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

* [PATCH RESEND 1/5] edk2-staging/RedfishPkg: EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL
  2021-10-28  1:07 [PATCH RESEND 0/5] Implementation of EDKII Redfish Platform Config Protocol Abner Chang
@ 2021-10-28  1:07 ` Abner Chang
  2021-10-28  1:07 ` [PATCH RESEND 2/5] edk2-staging/RedfishPkg: HII utility helper library Abner Chang
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Abner Chang @ 2021-10-28  1:07 UTC (permalink / raw)
  To: devel; +Cc: nickle.wang, Liming Gao

EDKII Redfish Platform Config Protocol defines the protocol
interfaces that abstracts the platform configuration format
and storage from EDK2 Redfish Feature driver. This protocol
provides the interfaces to get and set platform configuration
with the format and configuration storage agnostic to the
Redfish feature driver.

Signed-off-by: Nickle Wang <nickle.wang@hpe.com>
Cc: Abner Chang <abner.chang@hpe.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
---
 RedfishPkg/RedfishPkg.dec                     |   3 +
 .../Protocol/EdkIIRedfishPlatformConfig.h     | 147 ++++++++++++++++++
 2 files changed, 150 insertions(+)
 create mode 100644 RedfishPkg/Include/Protocol/EdkIIRedfishPlatformConfig.h

diff --git a/RedfishPkg/RedfishPkg.dec b/RedfishPkg/RedfishPkg.dec
index 9886502a0db..4d80515fe07 100644
--- a/RedfishPkg/RedfishPkg.dec
+++ b/RedfishPkg/RedfishPkg.dec
@@ -73,6 +73,9 @@
   ## Include/Protocol/Edk2RedfishConfigHandler.h
   gEdkIIRedfishConfigHandlerProtocolGuid = { 0xbc0fe6bb, 0x2cc9, 0x463e, { 0x90, 0x82, 0xfa, 0x11, 0x76, 0xfc, 0x67, 0xde } }
 
+  ## Include/Protocol/EdkIIRedfishPlatformConfig.h
+  gEdkIIRedfishPlatformConfigProtocolGuid = { 0X4D94A7C7, 0X4CE4, 0X4A84, { 0X88, 0XC1, 0X33, 0X0C, 0XD4, 0XA3, 0X47, 0X67 } }
+
 [Guids]
   gEfiRedfishPkgTokenSpaceGuid      = { 0x4fdbccb7, 0xe829, 0x4b4c, { 0x88, 0x87, 0xb2, 0x3f, 0xd7, 0x25, 0x4b, 0x85 }}
 
diff --git a/RedfishPkg/Include/Protocol/EdkIIRedfishPlatformConfig.h b/RedfishPkg/Include/Protocol/EdkIIRedfishPlatformConfig.h
new file mode 100644
index 00000000000..895b010227f
--- /dev/null
+++ b/RedfishPkg/Include/Protocol/EdkIIRedfishPlatformConfig.h
@@ -0,0 +1,147 @@
+/** @file
+  This file defines the EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL interface.
+
+  (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef EDKII_REDFISH_PLATFORM_CONFIG_H_
+#define EDKII_REDFISH_PLATFORM_CONFIG_H_
+
+typedef struct _EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL;
+
+/**
+  Definition of EDKII_REDFISH_TYPE_VALUE
+ **/
+typedef union {
+  INT64           Integer;
+  BOOLEAN         Boolean;
+  CHAR8           *Buffer;
+} EDKII_REDFISH_TYPE_VALUE;
+
+/**
+  Definition of EDKII_REDFISH_VALUE_TYPES
+ **/
+typedef enum {
+  REDFISH_VALUE_TYPE_UNKNOWN = 0,
+  REDFISH_VALUE_TYPE_INTEGER,
+  REDFISH_VALUE_TYPE_BOOLEAN,
+  REDFISH_VALUE_TYPE_STRING,
+  REDFISH_VALUE_TYPE_MAX
+} EDKII_REDFISH_VALUE_TYPES;
+
+/**
+  Definition of EDKII_REDFISH_VALUE
+ **/
+typedef struct {
+  EDKII_REDFISH_VALUE_TYPES Type;
+  EDKII_REDFISH_TYPE_VALUE  Value;
+} EDKII_REDFISH_VALUE;
+
+/**
+  Get Redfish value with the given Schema and Configure Language.
+
+  @param[in]   This                Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance.
+  @param[in]   Schema              The Redfish schema to query.
+  @param[in]   Version             The Redfish version to query.
+  @param[in]   ConfigureLang       The target value which match this configure Language.
+  @param[out]  Value               The returned value.
+
+  @retval EFI_SUCCESS              Value is returned successfully.
+  @retval Others                   Some error happened.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EDKII_REDFISH_PLATFORM_CONFIG_GET_VALUE) (
+  IN     EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL *This,
+  IN     CHAR8                                  *Schema,
+  IN     CHAR8                                  *Version,
+  IN     EFI_STRING                             ConfigureLang,
+  OUT    EDKII_REDFISH_VALUE                    *Value
+  );
+
+/**
+  Set Redfish value with the given Schema and Configure Language.
+
+  @param[in]   This                Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance.
+  @param[in]   Schema              The Redfish schema to query.
+  @param[in]   Version             The Redfish version to query.
+  @param[in]   ConfigureLang       The target value which match this configure Language.
+  @param[in]   Value               The value to set.
+
+  @retval EFI_SUCCESS              Value is returned successfully.
+  @retval Others                   Some error happened.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EDKII_REDFISH_PLATFORM_CONFIG_SET_VALUE) (
+  IN     EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL *This,
+  IN     CHAR8                                  *Schema,
+  IN     CHAR8                                  *Version,
+  IN     EFI_STRING                             ConfigureLang,
+  IN     EDKII_REDFISH_VALUE                    Value
+  );
+
+/**
+  Get the list of Configure Language from platform configuration by the given Schema and Pattern.
+
+  @param[in]   This                Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance.
+  @param[in]   Schema              The Redfish schema to query.
+  @param[in]   Version             The Redfish version to query.
+  @param[in]   Pattern             The target Configure Language pattern.
+  @param[out]  ConfigureLangList   The list of Configure Language.
+  @param[out]  Count               The number of Configure Language in ConfigureLangList.
+
+  @retval EFI_SUCCESS              ConfigureLangList is returned successfully.
+  @retval Others                   Some error happened.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EDKII_REDFISH_PLATFORM_CONFIG_GET_CONFIG_LANG) (
+  IN     EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL *This,
+  IN     CHAR8                                  *Schema,
+  IN     CHAR8                                  *Version,
+  IN     EFI_STRING                             Pattern,
+  OUT    EFI_STRING                             **ConfigureLangList,
+  OUT    UINTN                                  *Count
+  );
+
+
+/**
+  Get the list of supported Redfish schema from platform configuration on the give HII handle.
+
+  @param[in]   This                Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance.
+  @param[in]   HiiHandle           The target handle to search. If handle is NULL,
+                                   this function returns all schema from HII database.
+  @param[out]  SupportedSchema     The supported schema list which is separated by ';'.
+                                   For example: "x-uefi-redfish-Memory.v1_7_1;x-uefi-redfish-Boot.v1_0_1"
+                                   The SupportedSchema is allocated by the callee. It's caller's
+                                   responsibility to free this buffer using FreePool().
+
+  @retval EFI_SUCCESS              Schema is returned successfully.
+  @retval Others                   Some error happened.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EDKII_REDFISH_PLATFORM_CONFIG_GET_SUPPORTED_SCHEMA) (
+  IN     EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL    *This,
+  IN     EFI_HII_HANDLE                            HiiHandle,       OPTIONAL
+  OUT    CHAR8                                     **SupportedSchema
+  );
+
+struct _EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL {
+  EDKII_REDFISH_PLATFORM_CONFIG_GET_VALUE             GetValue;
+  EDKII_REDFISH_PLATFORM_CONFIG_SET_VALUE             SetValue;
+  EDKII_REDFISH_PLATFORM_CONFIG_GET_CONFIG_LANG       GetConfigureLang;
+  EDKII_REDFISH_PLATFORM_CONFIG_GET_SUPPORTED_SCHEMA  GetSupportedSchema;
+};
+
+extern EFI_GUID gEdkIIRedfishPlatformConfigProtocolGuid;
+
+#endif
-- 
2.21.0.windows.1


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

* [PATCH RESEND 2/5] edk2-staging/RedfishPkg: HII utility helper library
  2021-10-28  1:07 [PATCH RESEND 0/5] Implementation of EDKII Redfish Platform Config Protocol Abner Chang
  2021-10-28  1:07 ` [PATCH RESEND 1/5] edk2-staging/RedfishPkg: EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL Abner Chang
@ 2021-10-28  1:07 ` Abner Chang
  2021-10-28  1:07 ` [PATCH RESEND 3/5] edk2-staging/RedfishPkg: Implementation of EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL Abner Chang
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Abner Chang @ 2021-10-28  1:07 UTC (permalink / raw)
  To: devel; +Cc: nickle.wang, Liming Gao

HiiUtilityLib is a helper library that provides the
functions to manipulate HII options.

Signed-off-by: Nickle Wang <nickle.wang@hpe.com>
Cc: Abner Chang <abner.chang@hpe.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
---
 RedfishPkg/RedfishPkg.dec                     |    4 +
 .../Library/HiiUtilityLib/HiiUtilityLib.inf   |   61 +
 RedfishPkg/Include/Library/HiiUtilityLib.h    | 1195 ++++
 .../Library/HiiUtilityLib/HiiExpression.h     |  190 +
 .../Library/HiiUtilityLib/HiiInternal.h       |  371 ++
 .../Library/HiiUtilityLib/HiiExpression.c     | 1367 +++++
 .../Library/HiiUtilityLib/HiiIfrParse.c       | 2671 +++++++++
 .../HiiUtilityLib/HiiUtilityInternal.c        | 5045 +++++++++++++++++
 .../Library/HiiUtilityLib/HiiUtilityLib.c     |  855 +++
 9 files changed, 11759 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 4d80515fe07..eac219ccbb9 100644
--- a/RedfishPkg/RedfishPkg.dec
+++ b/RedfishPkg/RedfishPkg.dec
@@ -55,6 +55,10 @@
   #
   RedfishContentCodingLib|Include/Library/RedfishContentCodingLib.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 00000000000..36a629a758b
--- /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 00000000000..1f164ba49c6
--- /dev/null
+++ b/RedfishPkg/Include/Library/HiiUtilityLib.h
@@ -0,0 +1,1195 @@
+/** @file
+  Definitinos of RedfishPlatformConfigLib
+
+  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
+
+**/
+#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;           // Varatore 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    *IndeExp;             // 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      ContantExp;
+  //
+  // 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_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  *RootDepdencyExp;   // Expression OpCodes tree layout to describe dependency of this expression.
+
+  union {
+    UINT8            RuleId;          // For EFI_IFR_RULE only
+    EFI_STRING_ID    Error;           // For EFI_IFR_NO_SUBMIT_IF, EFI_IFR_INCONSISTENT_IF only
+
+    struct {
+      EFI_STRING_ID  WarningIfError;
+      UINT8          TimeOut;
+    } WarningIfData;
+
+  } 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, calback 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 storahe 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 GrayOutIf/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 configreques for all storage.
+  LIST_ENTRY           RuleListHead;         // nesed 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 Hanlde 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 successfuly
+  @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
+  );
+
+/**
+  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 successfuly
+  @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
+HpEvaluateHiiExpression (
+  IN     HII_FORMSET       *FormSet,
+  IN     HII_FORM          *Form,
+  IN OUT HII_EXPRESSION    *Expression
+  );
+
+#endif // _HII_UTILITY_LIB_
diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiExpression.h b/RedfishPkg/Library/HiiUtilityLib/HiiExpression.h
new file mode 100644
index 00000000000..e96c07b4de2
--- /dev/null
+++ b/RedfishPkg/Library/HiiUtilityLib/HiiExpression.h
@@ -0,0 +1,190 @@
+/** @file
+  Definitinos of RedfishPlatformConfigLib
+
+  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
+
+**/
+
+#ifndef HII_EXPRESSION_H_
+#define HII_EXPRESSION_H_
+
+#include <Library/HiiUtilityLib.h>
+
+/**
+  Get the expression list count.
+
+  @param[in]  Level              Which type this expression belong to. Form,
+                                 statement or option?
+
+  @retval >=0                    The expression count
+  @retval -1                     Input parameter error.
+
+**/
+INTN
+GetConditionalExpressionCount (
+  IN EXPRESS_LEVEL    Level
+  );
+
+/**
+  Get the expression Buffer pointer.
+
+  @param[in]  Level              Which type this expression belong to. Form,
+                                 statement or option?
+
+  @retval  The start pointer of the expression buffer or NULL.
+
+**/
+HII_EXPRESSION **
+GetConditionalExpressionList (
+  IN EXPRESS_LEVEL    Level
+  );
+
+/**
+  Push the expression options onto the Stack.
+
+  @param[in]  Pointer            Pointer to the current expression.
+  @param[in]  Level              Which type this expression belong to. Form,
+                                 statement or option?
+
+  @retval EFI_SUCCESS            The value was pushed onto the stack.
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the stack.
+
+**/
+EFI_STATUS
+PushConditionalExpression (
+  IN HII_EXPRESSION    *Pointer,
+  IN EXPRESS_LEVEL     Level
+  );
+
+/**
+  Pop the expression options from the Stack
+
+  @param[in]  Level              Which type this expression belong to. Form,
+                                 statement or option?
+
+  @retval EFI_SUCCESS            The value was pushed onto the stack.
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the stack.
+
+**/
+EFI_STATUS
+PopConditionalExpression (
+  IN EXPRESS_LEVEL    Level
+  );
+
+/**
+  Reset stack pointer to begin of the stack.
+
+**/
+VOID
+ResetCurrentExpressionStack (
+  VOID
+  );
+
+/**
+  Push current expression onto the Stack
+
+  @param[in]  Pointer            Pointer to current expression.
+
+  @retval EFI_SUCCESS            The value was pushed onto the stack.
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the stack.
+
+**/
+EFI_STATUS
+PushCurrentExpression (
+  IN VOID    *Pointer
+  );
+
+/**
+  Pop current expression from the Stack
+
+  @param[in]  Pointer            Pointer to current expression to be pop.
+
+  @retval EFI_SUCCESS            The value was pushed onto the stack.
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the stack.
+
+**/
+EFI_STATUS
+PopCurrentExpression (
+  OUT VOID    **Pointer
+  );
+
+/**
+  Reset stack pointer to begin of the stack.
+
+**/
+VOID
+ResetMapExpressionListStack (
+  VOID
+  );
+
+/**
+  Push the list of map expression onto the Stack
+
+  @param[in]  Pointer            Pointer to the list of map expression to be pushed.
+
+  @retval EFI_SUCCESS            The value was pushed onto the stack.
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the stack.
+
+**/
+EFI_STATUS
+PushMapExpressionList (
+  IN VOID    *Pointer
+  );
+
+/**
+  Pop the list of map expression from the Stack
+
+  @param[in]  Pointer            Pointer to the list of map expression to be pop.
+
+  @retval EFI_SUCCESS            The value was pushed onto the stack.
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the stack.
+
+**/
+EFI_STATUS
+PopMapExpressionList (
+  OUT VOID    **Pointer
+  );
+
+/**
+  Reset stack pointer to begin of the stack.
+
+**/
+VOID
+ResetScopeStack (
+  VOID
+  );
+
+/**
+  Push an Operand onto the Stack
+
+  @param[in]  Operand            Operand to push.
+
+  @retval EFI_SUCCESS            The value was pushed onto the stack.
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the
+                                 stack.
+
+**/
+EFI_STATUS
+PushScope (
+  IN UINT8    Operand
+  );
+
+/**
+  Pop an Operand from the Stack
+
+  @param[out]  Operand           Operand to pop.
+
+  @retval EFI_SUCCESS            The value was pushed onto the stack.
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the
+                                 stack.
+
+**/
+EFI_STATUS
+PopScope (
+  OUT UINT8    *Operand
+  );
+
+#endif
diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiInternal.h b/RedfishPkg/Library/HiiUtilityLib/HiiInternal.h
new file mode 100644
index 00000000000..1106896dc46
--- /dev/null
+++ b/RedfishPkg/Library/HiiUtilityLib/HiiInternal.h
@@ -0,0 +1,371 @@
+/** @file
+  Definitinos of RedfishPlatformConfigLib
+
+  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
+
+**/
+
+#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 lenght 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 conveted.
+  @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 00000000000..7111b40acf0
--- /dev/null
+++ b/RedfishPkg/Library/HiiUtilityLib/HiiExpression.c
@@ -0,0 +1,1367 @@
+/** @file
+  Definitinos of RedfishPlatformConfigLib
+
+  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
+
+**/
+#include "HiiInternal.h"
+
+//
+// Global stack used to evaluate boolean expresions
+//
+EFI_HII_VALUE *mOpCodeScopeStack = NULL;
+EFI_HII_VALUE *mOpCodeScopeStackEnd = NULL;
+EFI_HII_VALUE *mOpCodeScopeStackPointer = NULL;
+
+//
+// Stack used for Suppressif/grayoutif/dusableif 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                        MapPairpCount;
+
+  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->ContantExp.Operand = ExpressionOpCode->Operand;
+      CopyMem (&DepExpressionOpCode->ContantExp.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.IndeExp);
+      PushDependencyExpDes (&DepExpressionOpCode);
+      break;
+
+    //
+    // Map
+    //
+    case EFI_IFR_MAP_OP:
+      //
+      // Go through map expression list.
+      //
+      DepExpressionOpCode->MapExp.Operand = ExpressionOpCode->Operand;
+      MapPairpCount = 0;
+      SubExpressionLink = GetFirstNode(&ExpressionOpCode->MapExpressionList);
+      while (!IsNull (&ExpressionOpCode->MapExpressionList, SubExpressionLink)) {
+        MapPairpCount ++;
+        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 (
+                                              MapPairpCount * sizeof (HII_DEPENDENCY_EXPRESSION_PAIR));
+      if (DepExpressionOpCode->MapExp.ExpPair == NULL) {
+
+        Status = EFI_OUT_OF_RESOURCES;
+        goto Done;
+      }
+
+      DepExpressionOpCode->MapExp.ExpPairNo = MapPairpCount;
+      MapPairpCount = 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[MapPairpCount].MatchExp= SubExpression->RootDepdencyExp;
+
+        //
+        // Get the second expression description in this pair.
+        //
+        SubExpressionLink = GetNextNode (&ExpressionOpCode->MapExpressionList, SubExpressionLink);
+        SubExpression = HII_EXPRESSION_FROM_LINK (SubExpressionLink);
+        GetHiiExpressionDependency (SubExpression);
+        DepExpressionOpCode->MapExp.ExpPair[MapPairpCount].ReturnExp= SubExpression->RootDepdencyExp;
+        //
+        // Goto the first expression on next pair.
+        //
+        SubExpressionLink = GetNextNode (&ExpressionOpCode->MapExpressionList, SubExpressionLink);
+        MapPairpCount++;
+      }
+      PushDependencyExpDes (&DepExpressionOpCode);
+      break;
+
+    default:
+      break;
+    }
+  }
+
+  PopDependencyExpDes (&Expression->RootDepdencyExp);
+
+Done:
+  return Status;
+}
diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiIfrParse.c b/RedfishPkg/Library/HiiUtilityLib/HiiIfrParse.c
new file mode 100644
index 00000000000..3546f92c1e7
--- /dev/null
+++ b/RedfishPkg/Library/HiiUtilityLib/HiiIfrParse.c
@@ -0,0 +1,2671 @@
+/** @file
+  Definitinos of RedfishPlatformConfigLib
+
+  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
+
+**/
+
+#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;
+  }
+
+  //
+  // Initialilze 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 (
+                         &FormSet->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 Statemens(Questions) and Expression OpCodes.
+
+  @param[in]      FormSet                The FormSet to be counted.
+  @param[in,out]  NumberOfStatement      Number of Statemens(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 00000000000..55b78315d1d
--- /dev/null
+++ b/RedfishPkg/Library/HiiUtilityLib/HiiUtilityInternal.c
@@ -0,0 +1,5045 @@
+/** @file
+  Definitinos of RedfishPlatformConfigLib
+
+  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
+
+**/
+
+#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 concatinate Source on the end of Destination.
+
+  @param  Dest                   String to added to the end of.
+  @param  Src                    String to concatinate.
+
+**/
+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 conveted.
+  @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 reqeust.
+  @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       *NextElementBakup;
+  CHAR16       *SearchKey;
+  CHAR16       *ValueKey;
+  BOOLEAN      RetVal;
+  CHAR16       *ConfigRequest;
+
+  RetVal           = FALSE;
+  NextElementBakup = 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)) {
+
+        NextElementBakup   = 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)) {
+
+        NextElementBakup = 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 = NextElementBakup;
+    } 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 retured 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[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 transter to EFI_IFR_TYPE_BUFFER type.
+  @retval FALSE                  This value type can't be transter 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 transter to EFI_IFR_TYPE_BUFFER type.
+  @retval FALSE                  This value type can't be transter 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 samll 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[in]  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 impelmentation 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 produece 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 successfuly
+  @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;
+}
diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.c b/RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.c
new file mode 100644
index 00000000000..f6b8a20fbb8
--- /dev/null
+++ b/RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.c
@@ -0,0 +1,855 @@
+/** @file
+  Definitinos of RedfishPlatformConfigLib
+
+  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
+
+**/
+
+#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.21.0.windows.1


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

* [PATCH RESEND 3/5] edk2-staging/RedfishPkg: Implementation of EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL
  2021-10-28  1:07 [PATCH RESEND 0/5] Implementation of EDKII Redfish Platform Config Protocol Abner Chang
  2021-10-28  1:07 ` [PATCH RESEND 1/5] edk2-staging/RedfishPkg: EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL Abner Chang
  2021-10-28  1:07 ` [PATCH RESEND 2/5] edk2-staging/RedfishPkg: HII utility helper library Abner Chang
@ 2021-10-28  1:07 ` Abner Chang
  2021-10-28  1:07 ` [PATCH RESEND 4/5] edk2-staging/RedfishPkg: Helper library " Abner Chang
  2021-10-28  1:07 ` [PATCH RESEND 5/5] edk2-staging/RedfishPkg: Enable Redfish Platform Config Protocol build process Abner Chang
  4 siblings, 0 replies; 6+ messages in thread
From: Abner Chang @ 2021-10-28  1:07 UTC (permalink / raw)
  To: devel; +Cc: nickle.wang, Liming Gao

This is the Implementation of EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL,
which is the EDKII Redfish Platform Config driver instance that accesses
EDK2 HII configuration format and storage.

Signed-off-by: Nickle Wang <nickle.wang@hpe.com>
Cc: Abner Chang <abner.chang@hpe.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
---
 .../RedfishPlatformConfigDxe.inf              |   53 +
 .../RedfishPlatformConfigDxe.h                |   64 +
 .../RedfishPlatformConfigImpl.h               |  274 ++++
 .../RedfishPlatformConfigDxe.c                | 1304 +++++++++++++++++
 .../RedfishPlatformConfigImpl.c               | 1240 ++++++++++++++++
 5 files changed, 2935 insertions(+)
 create mode 100644 RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.inf
 create mode 100644 RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.h
 create mode 100644 RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.h
 create mode 100644 RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.c
 create mode 100644 RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.c

diff --git a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.inf b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.inf
new file mode 100644
index 00000000000..16739bef7a3
--- /dev/null
+++ b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.inf
@@ -0,0 +1,53 @@
+## @file
+#  Implementation of EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL interfaces.
+#
+#  (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION               = 0x00010005
+  BASE_NAME                 = RedfishPlatformConfigDxe
+  FILE_GUID                 = BEAEFFE1-0633-41B5-913C-9389339C2927
+  MODULE_TYPE               = DXE_DRIVER
+  VERSION_STRING            = 1.0
+  ENTRY_POINT               = RedfishPlatformConfigDxeEntryPoint
+  UNLOAD_IMAGE              = RedfishPlatformConfigDxeUnload
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  RedfishPkg/RedfishPkg.dec
+
+[Sources]
+  RedfishPlatformConfigDxe.h
+  RedfishPlatformConfigDxe.c
+  RedfishPlatformConfigImpl.h
+  RedfishPlatformConfigImpl.c
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  DevicePathLib
+  HiiLib
+  HiiUtilityLib
+  MemoryAllocationLib
+  PrintLib
+  UefiLib
+  UefiBootServicesTableLib
+  UefiRuntimeServicesTableLib
+  UefiDriverEntryPoint
+
+[Protocols]
+  gEdkIIRedfishPlatformConfigProtocolGuid ## PRODUCED
+  gEfiHiiDatabaseProtocolGuid             ## CONSUMED
+  gEfiHiiStringProtocolGuid               ## CONSUMED
+  gEfiRegularExpressionProtocolGuid       ## CONSUMED
+
+[Guids]
+  gEfiRegexSyntaxTypePerlGuid             ## CONSUMED
+
+[Depex]
+  TRUE
\ No newline at end of file
diff --git a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.h b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.h
new file mode 100644
index 00000000000..99a613d229c
--- /dev/null
+++ b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.h
@@ -0,0 +1,64 @@
+/** @file
+  This file defines the EDKII Redfish Platform Config Protocol interface.
+
+  (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef EDKII_REDFISH_PLATFORM_CONFIG_DXE_H_
+#define EDKII_REDFISH_PLATFORM_CONFIG_DXE_H_
+
+#include <Uefi.h>
+
+//
+// Libraries
+//
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+
+//
+// Produced Protocols
+//
+#include <Protocol/EdkIIRedfishPlatformConfig.h>
+#include <Protocol/HiiDatabase.h>
+#include <Protocol/HiiString.h>
+#include <Protocol/RegularExpressionProtocol.h>
+
+//
+// Definition of EDKII_REDFISH_PLATFORM_CONFIG_NOTIFY.
+//
+typedef struct {
+  EFI_EVENT                   ProtocolEvent;   // Protocol notification event.
+  VOID                        *Registration;   // Protocol notification registration.
+} REDFISH_PLATFORM_CONFIG_NOTIFY;
+
+//
+// Definition of REDFISH_PLATFORM_CONFIG_PRIVATE.
+//
+typedef struct {
+  EFI_HANDLE                                ImageHandle;                // Driver image handle.
+  EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL    Protocol;
+  REDFISH_PLATFORM_CONFIG_NOTIFY            HiiDbNotify;
+  EFI_HII_DATABASE_PROTOCOL                 *HiiDatabase;               // The HII database protocol.
+  REDFISH_PLATFORM_CONFIG_NOTIFY            HiiStringNotify;
+  EFI_HII_STRING_PROTOCOL                   *HiiString;                 // HII String Protocol.
+  REDFISH_PLATFORM_CONFIG_NOTIFY            RegexNotify;
+  EFI_REGULAR_EXPRESSION_PROTOCOL           *RegularExpressionProtocol; // Regular Expression Protocol.
+  EFI_HANDLE                                NotifyHandle;               // The notify handle.
+  LIST_ENTRY                                FormsetList;                // The list to keep cached HII formset.
+  LIST_ENTRY                                PendingList;                // The list to keep updated HII handle.
+} REDFISH_PLATFORM_CONFIG_PRIVATE;
+
+#define REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS(a)  BASE_CR (a, REDFISH_PLATFORM_CONFIG_PRIVATE, Protocol)
+#define REGULAR_EXPRESSION_INCLUDE_ALL                L".*"
+#define CONFIGURE_LANGUAGE_PREFIX                     "x-uefi-redfish-"
+
+#endif
diff --git a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.h b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.h
new file mode 100644
index 00000000000..e0ba0fb2d3d
--- /dev/null
+++ b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.h
@@ -0,0 +1,274 @@
+/** @file
+  This file defines the EDKII Redfish Platform Config Protocol interface.
+
+  (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef EDKII_REDFISH_PLATFORM_CONFIG_IMPL_H_
+#define EDKII_REDFISH_PLATFORM_CONFIG_IMPL_H_
+
+#include <Uefi.h>
+
+//
+// Libraries
+//
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HiiUtilityLib.h>
+#include <Library/HiiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+#define REDFISH_PLATFORM_CONFIG_DELETE_EXPIRED_FORMSET   0x00
+#define IS_EMPTY_STRING(a)                               (a == NULL || a[0] == L'\0')
+#define ENGLISH_LANGUAGE_CODE                            "en-US"
+#define X_UEFI_SCHEMA_PREFIX                             "x-uefi-redfish-"
+
+//
+// Definition of REDFISH_PLATFORM_CONFIG_PRIVATE.
+//
+typedef struct {
+  LIST_ENTRY                    Link;
+  EFI_HII_HANDLE                HiiHandle;
+  BOOLEAN                       IsDeleted;
+} REDFISH_PLATFORM_CONFIG_PENDING_LIST;
+
+#define REDFISH_PLATFORM_CONFIG_PENDING_LIST_FROM_LINK(a)  BASE_CR (a, REDFISH_PLATFORM_CONFIG_PENDING_LIST, Link)
+
+typedef struct {
+  UINTN   Count;                                // Number of schema in list
+  CHAR8   **SchemaList;                         // Schema list
+} REDFISH_PLATFORM_CONFIG_SCHEMA;
+
+//
+// Definition of REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE
+//
+typedef struct {
+  LIST_ENTRY                      Link;
+  HII_FORMSET                     *HiiFormSet;     // Pointer to HII formset data.
+  EFI_GUID                        Guid;            // Formset GUID.
+  EFI_HII_HANDLE                  HiiHandle;       // Hii Handle of this formset.
+  LIST_ENTRY                      HiiFormList;     // Form list that keep form data under this formset.
+  CHAR16                          *DevicePathStr;  // Device path of this formset.
+  REDFISH_PLATFORM_CONFIG_SCHEMA  SupportedSchema; // Schema that is supported in this formset.
+} REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE;
+
+#define REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK(a)  BASE_CR (a, REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE, Link)
+
+//
+// Definition of REDFISH_PLATFORM_CONFIG_FORM_PRIVATE
+//
+typedef struct {
+  LIST_ENTRY                                Link;
+  UINT16                                    Id;             // Form ID.
+  EFI_STRING_ID                             Title;          // String token of form title.
+  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *ParentFormset;
+  HII_FORM                                  *HiiForm;       // Pointer to HII form data.
+  LIST_ENTRY                                StatementList;  // Statement list that keep statement under this form.
+} REDFISH_PLATFORM_CONFIG_FORM_PRIVATE;
+
+#define REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK(a)  BASE_CR (a, REDFISH_PLATFORM_CONFIG_FORM_PRIVATE, Link)
+
+//
+// Definition of REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE
+//
+typedef struct {
+  LIST_ENTRY                            Link;
+  REDFISH_PLATFORM_CONFIG_FORM_PRIVATE  *ParentForm;
+  HII_STATEMENT                         *HiiStatement;  // Pointer to HII statement data.
+  EFI_QUESTION_ID                       QuestionId;     // Question ID of this statement.
+  EFI_STRING_ID                         Description;    // String token of this question.
+  EFI_STRING                            DesStringCache; // The string cache for search function.
+} REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE;
+
+#define REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK(a)  BASE_CR (a, REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE, Link)
+
+//
+// Definition of REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF
+//
+typedef struct {
+  LIST_ENTRY                                Link;
+  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *Statement;
+} REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF;
+
+#define REDFISH_PLATFORM_CONFIG_STATEMENT_REF_FROM_LINK(a)  BASE_CR (a, REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF, Link)
+
+//
+// Definition of REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST
+//
+typedef struct {
+  LIST_ENTRY  StatementList;        // List of REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF
+  UINTN       Count;
+} REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST;
+
+/**
+  Release formset list and all the forms that belong to this formset.
+
+  @param[in]      FormsetList   Pointer to formst list that needs to be
+                                released.
+
+  @retval         EFI_STATUS
+
+**/
+EFI_STATUS
+ReleaseFormsetList (
+  IN  LIST_ENTRY      *FormsetList
+  );
+
+/**
+  Release formset list and all the forms that belong to this formset.
+
+  @param[in]      FormsetList   Pointer to formst list that needs to be
+                                released.
+
+  @retval         EFI_STATUS
+
+**/
+EFI_STATUS
+LoadFormsetList (
+  IN   EFI_HII_HANDLE   *HiiHandle,
+  OUT  LIST_ENTRY       *FormsetList
+  );
+
+/**
+  When HII database is updated. Keep updated HII handle into pending list so
+  we can process them later.
+
+  @param[in]  HiiHandle   HII handle instance.
+  @param[in]  PendingList Pending list to keep HII handle which is recently updated.
+
+  @retval EFI_SUCCESS             HII handle is saved in pending list.
+  @retval EFI_INVALID_PARAMETER   HiiHnalde is NULL or PendingList is NULL.
+  @retval EFI_OUT_OF_RESOURCES    System is out of memory.
+
+**/
+EFI_STATUS
+NotifyFormsetUpdate (
+  IN  EFI_HII_HANDLE   *HiiHandle,
+  IN  LIST_ENTRY       *PendingList
+  );
+
+/**
+  When HII database is updated and form-set is deleted. Keep deleted HII handle into pending list so
+  we can process them later.
+
+  @param[in]  HiiHandle   HII handle instance.
+  @param[in]  PendingList Pending list to keep HII handle which is recently updated.
+
+  @retval EFI_SUCCESS             HII handle is saved in pending list.
+  @retval EFI_INVALID_PARAMETER   HiiHnalde is NULL or PendingList is NULL.
+  @retval EFI_OUT_OF_RESOURCES    System is out of memory.
+
+**/
+EFI_STATUS
+NotifyFormsetDeleted (
+  IN  EFI_HII_HANDLE   *HiiHandle,
+  IN  LIST_ENTRY       *PendingList
+  );
+
+/**
+  Get statement private instance by the given configure language.
+
+  @param[in]  FormsetList                 Form-set list to search.
+  @param[in]  Schema                      Schema to be matched.
+  @param[in]  ConfigureLang               Configure language.
+
+  @retval REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *   Pointer to statement private instance.
+
+**/
+REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *
+GetStatementPrivateByConfigureLang (
+  IN  LIST_ENTRY    *FormsetList,
+  IN  CHAR8         *Schema,
+  IN  EFI_STRING    ConfigureLang
+  );
+
+/**
+  Search and find statement private instance by given regular expression patthern
+  which describes the Configure Language.
+
+  @param[in]  RegularExpressionProtocol   Regular express protocol.
+  @param[in]  FormsetList                 Form-set list to search.
+  @param[in]  Schema                      Schema to be matched.
+  @param[in]  Pattern                     Regular expression pattern.
+  @param[out] StatementList               Statement list that match above pattern.
+
+  @retval EFI_SUCCESS             Statement list is returned.
+  @retval EFI_INVALID_PARAMETER   Input parameter is NULL.
+  @retval EFI_NOT_READY           Regular express protocol is NULL.
+  @retval EFI_NOT_FOUND           No statement is found.
+  @retval EFI_OUT_OF_RESOURCES    System is out of memory.
+
+**/
+EFI_STATUS
+GetStatementPrivateByConfigureLangRegex (
+  IN  EFI_REGULAR_EXPRESSION_PROTOCOL                 *RegularExpressionProtocol,
+  IN  LIST_ENTRY                                      *FormsetList,
+  IN  CHAR8                                           *Schema,
+  IN  EFI_STRING                                      Pattern,
+  OUT REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST  *StatementList
+  );
+
+/**
+  There are HII database update and we need to process them accordingly so that we
+  won't use stale data. This function will parse updated HII handle again in order
+  to get updated data-set.
+
+  @param[in]  FormsetList   List to keep HII form-set.
+  @param[in]  PendingList   List to keep HII handle that is updated.
+
+  @retval EFI_SUCCESS             HII handle is saved in pending list.
+  @retval EFI_INVALID_PARAMETER   FormsetList is NULL or PendingList is NULL.
+
+**/
+EFI_STATUS
+ProcessPendingList (
+  IN  LIST_ENTRY       *FormsetList,
+  IN  LIST_ENTRY       *PendingList
+  );
+
+/**
+  Retrieves a string from a string package in a English language. The
+  returned string is allocated using AllocatePool().  The caller is responsible
+  for freeing the allocated buffer using FreePool().
+
+  If HiiHandle is NULL, then ASSERT().
+  If StringId is 0, then ASSET.
+
+  @param[in]  HiiStringProtocol EFI_HII_STRING_PROTOCOL instance.
+  @param[in]  HiiHandle         A handle that was previously registered in the HII Database.
+  @param[in]  StringId          The identifier of the string to retrieved from the string
+                                package associated with HiiHandle.
+
+  @retval NULL   The string specified by StringId is not present in the string package.
+  @retval Other  The string was returned.
+
+**/
+EFI_STRING
+HiiGetRedfishString (
+  IN EFI_HII_HANDLE           HiiHandle,
+  IN CHAR8                    *Language,
+  IN EFI_STRING_ID            StringId
+  );
+
+/**
+  Release all resource in statement list.
+
+  @param[in]  StatementList   Statement list to be released.
+
+  @retval EFI_SUCCESS             All resource are released.
+  @retval EFI_INVALID_PARAMETER   StatementList is NULL.
+
+**/
+EFI_STATUS
+ReleaseStatementList (
+  IN  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST  *StatementList
+  );
+
+#endif
diff --git a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.c b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.c
new file mode 100644
index 00000000000..67818cccd24
--- /dev/null
+++ b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.c
@@ -0,0 +1,1304 @@
+/** @file
+
+  The implementation of EDKII Redfidh Platform Config Protocol.
+
+  (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "RedfishPlatformConfigDxe.h"
+#include "RedfishPlatformConfigImpl.h"
+
+REDFISH_PLATFORM_CONFIG_PRIVATE *mRedfishPlatformConfigPrivate = NULL;
+
+/**
+  Compare two value in HII statement format.
+
+  @param[in]  Value1        Firt value to compare.
+  @param[in]  Value2        Second value to be compared.
+
+  @retval UINTN         0 is retuned when two values are equal.
+                        1 is returned when first value is greater than second value.
+                        -1 is returned when second value is greater than first value.
+
+**/
+UINTN
+CompareHiiStatementValue (
+  IN HII_STATEMENT_VALUE  *Value1,
+  IN HII_STATEMENT_VALUE  *Value2
+  )
+{
+  INTN Result;
+  UINT64 Data1;
+  UINT64 Data2;
+
+  if (Value1 == NULL || Value2 == NULL) {
+    return 0xFF;
+  }
+
+  switch (Value1->Type) {
+    case EFI_IFR_TYPE_NUM_SIZE_8:
+      Data1 = Value1->Value.u8;
+      break;
+    case EFI_IFR_TYPE_NUM_SIZE_16:
+      Data1 = Value1->Value.u16;
+      break;
+    case EFI_IFR_TYPE_NUM_SIZE_32:
+      Data1 = Value1->Value.u32;
+      break;
+    case EFI_IFR_TYPE_NUM_SIZE_64:
+      Data1 = Value1->Value.u64;
+      break;
+    case EFI_IFR_TYPE_BOOLEAN:
+      Data1 = (Value1->Value.b ? 1 : 0);
+      break;
+    default:
+      return 0xFF;
+  }
+
+  switch (Value2->Type) {
+    case EFI_IFR_TYPE_NUM_SIZE_8:
+      Data2 = Value2->Value.u8;
+      break;
+    case EFI_IFR_TYPE_NUM_SIZE_16:
+      Data2 = Value2->Value.u16;
+      break;
+    case EFI_IFR_TYPE_NUM_SIZE_32:
+      Data2 = Value2->Value.u32;
+      break;
+    case EFI_IFR_TYPE_NUM_SIZE_64:
+      Data2 = Value2->Value.u64;
+      break;
+    case EFI_IFR_TYPE_BOOLEAN:
+      Data2 = (Value2->Value.b ? 1 : 0);
+      break;
+    default:
+      return 0xFF;
+  }
+
+  Result = (Data1 == Data2 ? 0 : (Data1 > Data2 ? 1 : -1));
+
+  return Result;
+}
+
+/**
+  Convert HII value to the string in HII one-of opcode.
+
+  @param[in]  Statement     Statement private instance
+
+  @retval EFI_STRING_ID     The string ID in HII database.
+                            0 is returned when something goes wrong.
+
+**/
+EFI_STRING_ID
+HiiValueToOneOfOptionStringId (
+  IN REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *Statement
+  )
+{
+  LIST_ENTRY            *Link;
+  HII_QUESTION_OPTION   *Option;
+
+  if (Statement->HiiStatement->Operand != EFI_IFR_ONE_OF_OP) {
+    return 0;
+  }
+
+  if (IsListEmpty (&Statement->HiiStatement->OptionListHead)) {
+    return 0;
+  }
+
+  Link = GetFirstNode (&Statement->HiiStatement->OptionListHead);
+  while (!IsNull (&Statement->HiiStatement->OptionListHead, Link)) {
+    Option = HII_QUESTION_OPTION_FROM_LINK (Link);
+
+    if (CompareHiiStatementValue (&Statement->HiiStatement->Value, &Option->Value) == 0) {
+      return Option->Text;
+    }
+
+    Link = GetNextNode (&Statement->HiiStatement->OptionListHead, Link);
+  }
+
+  return 0;
+}
+
+/**
+  Convert HII string to the value in HII one-of opcode.
+
+  @param[in]  Statement     Statement private instance
+  @param[in]  Schema        Schema string
+  @param[in]  HiiString     Input string
+  @param[out] Value         Value returned
+
+  @retval EFI_SUCCESS       HII value is returned successfully.
+  @retval Others            Errors occur
+
+**/
+EFI_STATUS
+HiiStringToOneOfOptionValue (
+  IN  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *Statement,
+  IN  CHAR8                           *Schema,
+  IN  EFI_STRING                      HiiString,
+  OUT HII_STATEMENT_VALUE             *Value
+  )
+{
+  LIST_ENTRY            *Link;
+  HII_QUESTION_OPTION   *Option;
+  EFI_STRING            TmpString;
+  BOOLEAN               Found;
+
+  if (Statement == NULL || IS_EMPTY_STRING (HiiString) || Value == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Statement->HiiStatement->Operand != EFI_IFR_ONE_OF_OP) {
+    return EFI_UNSUPPORTED;
+  }
+
+  if (IsListEmpty (&Statement->HiiStatement->OptionListHead)) {
+    return EFI_NOT_FOUND;
+  }
+
+  Found = FALSE;
+  Link = GetFirstNode (&Statement->HiiStatement->OptionListHead);
+  while (!IsNull (&Statement->HiiStatement->OptionListHead, Link)) {
+    Option = HII_QUESTION_OPTION_FROM_LINK (Link);
+
+    TmpString = HiiGetRedfishString (Statement->ParentForm->ParentFormset->HiiHandle, Schema, Option->Text);
+    if (TmpString != NULL) {
+      if (StrCmp (TmpString, HiiString) == 0) {
+        CopyMem (Value, &Option->Value, sizeof (HII_STATEMENT_VALUE));
+        Found = TRUE;
+      }
+      FreePool (TmpString);
+    }
+
+    if (Found) {
+      return EFI_SUCCESS;
+    }
+
+    Link = GetNextNode (&Statement->HiiStatement->OptionListHead, Link);
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+/**
+  Convert HII value to numeric value in Redfish format.
+
+  @param[in]  Value         Value to be converted.
+  @param[out] RedfishValue  Value in Redfish format.
+
+  @retval EFI_SUCCESS       Redfish value is returned successfully.
+  @retval Others            Errors occur
+
+**/
+EFI_STATUS
+HiiValueToRedfishNumeric (
+  IN  HII_STATEMENT_VALUE  *Value,
+  OUT EDKII_REDFISH_VALUE  *RedfishValue
+  )
+{
+  if (Value == NULL || RedfishValue == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  switch (Value->Type) {
+    case EFI_IFR_TYPE_NUM_SIZE_8:
+      RedfishValue->Type = REDFISH_VALUE_TYPE_INTEGER;
+      RedfishValue->Value.Integer = (INT64)Value->Value.u8;
+      break;
+    case EFI_IFR_TYPE_NUM_SIZE_16:
+      RedfishValue->Type = REDFISH_VALUE_TYPE_INTEGER;
+      RedfishValue->Value.Integer = (INT64)Value->Value.u16;
+      break;
+    case EFI_IFR_TYPE_NUM_SIZE_32:
+      RedfishValue->Type = REDFISH_VALUE_TYPE_INTEGER;
+      RedfishValue->Value.Integer = (INT64)Value->Value.u32;
+      break;
+    case EFI_IFR_TYPE_NUM_SIZE_64:
+      RedfishValue->Type = REDFISH_VALUE_TYPE_INTEGER;
+      RedfishValue->Value.Integer = (INT64)Value->Value.u64;
+      break;
+    case EFI_IFR_TYPE_BOOLEAN:
+      RedfishValue->Type = REDFISH_VALUE_TYPE_BOOLEAN;
+      RedfishValue->Value.Boolean = Value->Value.b;
+      break;
+    default:
+      RedfishValue->Type = REDFISH_VALUE_TYPE_UNKNOWN;
+      break;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Convert numeric value in Redfish format to HII value.
+
+  @param[in]   RedfishValue  Value in Redfish format to be converted.
+  @param[out]  Value         HII value returned.
+
+  @retval EFI_SUCCESS       HII value is returned successfully.
+  @retval Others            Errors occur
+
+**/
+EFI_STATUS
+RedfishNumericToHiiValue (
+  IN  EDKII_REDFISH_VALUE  *RedfishValue,
+  OUT HII_STATEMENT_VALUE  *Value
+  )
+{
+  if (Value == NULL || RedfishValue == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  switch (RedfishValue->Type) {
+    case REDFISH_VALUE_TYPE_INTEGER:
+      Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
+      Value->Value.u64 = (UINT64)RedfishValue->Value.Integer;
+      break;
+    case REDFISH_VALUE_TYPE_BOOLEAN:
+      Value->Type = EFI_IFR_TYPE_BOOLEAN;
+      Value->Value.b = RedfishValue->Value.Boolean;
+      break;
+    default:
+      Value->Type = EFI_IFR_TYPE_UNDEFINED;
+      break;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Return the full Redfish schema string from the given Schema and Version.
+
+  Returned schema string is: Schema + '.' + Version
+
+  @param[in]  Schema      Schema string
+  @param[in]  Version     Schema version string
+
+  @retval CHAR8 *         Schema string. NULL when errors occur.
+
+**/
+CHAR8 *
+GetFullSchemaString (
+  IN CHAR8   *Schema,
+  IN CHAR8  *Version
+  )
+{
+  UINTN Size;
+  CHAR8 *FullName;
+
+  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version)) {
+    return NULL;
+  }
+
+  Size = AsciiStrSize(CONFIGURE_LANGUAGE_PREFIX) + AsciiStrSize (Schema) + AsciiStrSize (Version);
+
+  FullName = AllocatePool (Size);
+  if (FullName == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a, out-of-resource\n", __FUNCTION__));
+    return NULL;
+  }
+
+  AsciiSPrint (FullName, Size, "%a%a.%a", CONFIGURE_LANGUAGE_PREFIX, Schema, Version);
+
+  return FullName;
+}
+
+/**
+  Common implementation to get statement private instance.
+
+  @param[in]   RedfishPlatformConfigPrivate   Private instance.
+  @param[in]   Schema                         Redfish schema string.
+  @param[in]   ConfigureLang                  Configure language that refers to this statement.
+  @param[out]  Statement                      Statement instance
+
+  @retval EFI_SUCCESS       HII value is returned successfully.
+  @retval Others            Errors occur
+
+**/
+EFI_STATUS
+RedfishPlatformConfigGetStatementCommon (
+  IN     REDFISH_PLATFORM_CONFIG_PRIVATE            *RedfishPlatformConfigPrivate,
+  IN     CHAR8                                      *Schema,
+  IN     EFI_STRING                                 ConfigureLang,
+  OUT    REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE  **Statement
+  )
+{
+  EFI_STATUS                      Status;
+  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *TargetStatement;
+
+  if (RedfishPlatformConfigPrivate == NULL || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (ConfigureLang) || Statement == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *Statement = NULL;
+
+  Status = ProcessPendingList (&RedfishPlatformConfigPrivate->FormsetList, &RedfishPlatformConfigPrivate->PendingList);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a, ProcessPendingList failure: %r\n", __FUNCTION__, Status));
+    return Status;
+  }
+
+  TargetStatement = GetStatementPrivateByConfigureLang (&RedfishPlatformConfigPrivate->FormsetList, Schema, ConfigureLang);
+  if (TargetStatement == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a, No match HII statement is found by the given %s in schema %a\n", __FUNCTION__, ConfigureLang, Schema));
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Find current HII question value.
+  //
+  Status = GetQuestionValue (
+             TargetStatement->ParentForm->ParentFormset->HiiFormSet,
+             TargetStatement->ParentForm->HiiForm,
+             TargetStatement->HiiStatement,
+             GetSetValueWithHiiDriver
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a, failed to get question current value: %r\n", __FUNCTION__, Status));
+    return Status;
+  }
+
+
+  if (TargetStatement->HiiStatement->Value.Type == EFI_IFR_TYPE_UNDEFINED) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  //
+  // Return Value.
+  //
+  *Statement = TargetStatement;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Get Redfish value with the given Schema and Configure Language.
+
+  @param[in]   This                Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance.
+  @param[in]   Schema              The Redfish schema to query.
+  @param[in]   Version             The Redfish version to query.
+  @param[in]   ConfigureLang       The target value which match this configure Language.
+  @param[out]  Value               The returned value.
+
+  @retval EFI_SUCCESS              Value is returned successfully.
+  @retval Others                   Some error happened.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishPlatformConfigProtocolGetValue (
+  IN     EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL *This,
+  IN     CHAR8                                  *Schema,
+  IN     CHAR8                                  *Version,
+  IN     EFI_STRING                             ConfigureLang,
+  OUT    EDKII_REDFISH_VALUE                    *Value
+  )
+{
+  EFI_STATUS                                Status;
+  REDFISH_PLATFORM_CONFIG_PRIVATE           *RedfishPlatformConfigPrivate;
+  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *TargetStatement;
+  EFI_STRING_ID                             StringId;
+  CHAR8                                     *FullSchema;
+  EFI_STRING                                HiiString;
+  UINTN                                     Size;
+
+  if (This == NULL || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || IS_EMPTY_STRING (ConfigureLang) || Value == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  RedfishPlatformConfigPrivate = REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS (This);
+  Value->Type = REDFISH_VALUE_TYPE_UNKNOWN;
+  FullSchema = NULL;
+  HiiString = NULL;
+
+  FullSchema = GetFullSchemaString (Schema, Version);
+  if (FullSchema == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Status = RedfishPlatformConfigGetStatementCommon (RedfishPlatformConfigPrivate, FullSchema, ConfigureLang, &TargetStatement);
+  if (EFI_ERROR (Status)) {
+    goto RELEASE_RESOURCE;
+  }
+
+  switch (TargetStatement->HiiStatement->Operand) {
+    case EFI_IFR_ONE_OF_OP:
+      StringId = HiiValueToOneOfOptionStringId (TargetStatement);
+      if (StringId == 0) {
+        ASSERT (FALSE);
+        Status = EFI_DEVICE_ERROR;
+        goto RELEASE_RESOURCE;
+      }
+
+      HiiString = HiiGetRedfishString (TargetStatement->ParentForm->ParentFormset->HiiHandle, FullSchema, StringId);
+      if (HiiString == NULL) {
+        DEBUG ((DEBUG_ERROR, "%a, Can not find string ID: 0x%x with %a\n", __FUNCTION__, StringId, FullSchema));
+        Status = EFI_NOT_FOUND;
+        goto RELEASE_RESOURCE;
+      }
+
+      Size = StrLen (HiiString) + 1;
+      Value->Value.Buffer = AllocatePool (Size);
+      if (Value->Value.Buffer == NULL) {
+        Status = EFI_OUT_OF_RESOURCES;
+        goto RELEASE_RESOURCE;
+      }
+
+      UnicodeStrToAsciiStrS (HiiString, Value->Value.Buffer, Size);
+      Value->Type = REDFISH_VALUE_TYPE_STRING;
+
+      break;
+    case EFI_IFR_STRING_OP:
+      if (TargetStatement->HiiStatement->Value.Type != EFI_IFR_TYPE_STRING) {
+        ASSERT (FALSE);
+        Status = EFI_DEVICE_ERROR;
+        goto RELEASE_RESOURCE;
+      }
+
+      Value->Type = REDFISH_VALUE_TYPE_STRING;
+      Value->Value.Buffer = AllocateCopyPool (StrSize ((CHAR16 *)TargetStatement->HiiStatement->Value.Buffer), TargetStatement->HiiStatement->Value.Buffer);
+      if (Value->Value.Buffer == NULL) {
+        Status = EFI_OUT_OF_RESOURCES;
+        goto RELEASE_RESOURCE;
+      }
+      break;
+    case EFI_IFR_CHECKBOX_OP:
+    case EFI_IFR_NUMERIC_OP:
+      Status = HiiValueToRedfishNumeric (&TargetStatement->HiiStatement->Value, Value);
+      if (EFI_ERROR (Status)) {
+        DEBUG ((DEBUG_ERROR, "%a, failed to convert HII value to Redfish value: %r\n", __FUNCTION__, Status));
+        goto RELEASE_RESOURCE;
+      }
+      break;
+    default:
+      DEBUG ((DEBUG_ERROR, "%a, catch unsupported type: 0x%x! Please contact with author if we need to support this type.\n", __FUNCTION__, TargetStatement->HiiStatement->Operand));
+      ASSERT (FALSE);
+      Status = EFI_UNSUPPORTED;
+      goto RELEASE_RESOURCE;
+  }
+
+RELEASE_RESOURCE:
+
+  if (FullSchema != NULL) {
+    FreePool (FullSchema);
+  }
+
+  if (HiiString != NULL) {
+    FreePool (HiiString);
+  }
+
+  return Status;
+}
+
+/**
+  Function to save question value into HII database.
+
+  @param[in]   HiiFormset       HII form-set instance
+  @param[in]   HiiForm          HII form instance
+  @param[in]   HiiStatement     HII statement that keeps new value.
+  @param[in]   Value            New value to applyu.
+
+  @retval EFI_SUCCESS       HII value is returned successfully.
+  @retval Others            Errors occur
+
+**/
+EFI_STATUS
+RedfishPlatformConfigSaveQuestionValue (
+  IN  HII_FORMSET         *HiiFormset,
+  IN  HII_FORM            *HiiForm,
+  IN  HII_STATEMENT       *HiiStatement,
+  IN  HII_STATEMENT_VALUE *Value
+  )
+{
+  EFI_STATUS  Status;
+
+  if (HiiFormset == NULL || HiiForm == NULL || HiiStatement == NULL || Value == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = SetQuestionValue (
+             HiiFormset,
+             HiiForm,
+             HiiStatement,
+             Value
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a, failed to set question value: %r\n", __FUNCTION__, Status));
+    return Status;
+  }
+
+  Status = SubmitForm (HiiFormset, HiiForm);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a, failed to submit form: %r\n", __FUNCTION__, Status));
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Common implementation to set statement private instance.
+
+  @param[in]   RedfishPlatformConfigPrivate   Private instance.
+  @param[in]   Schema                         Redfish schema string.
+  @param[in]   ConfigureLang                  Configure language that refers to this statement.
+  @param[in]   Statement                      Statement instance
+
+  @retval EFI_SUCCESS       HII value is returned successfully.
+  @retval Others            Errors occur
+
+**/
+EFI_STATUS
+RedfishPlatformConfigSetStatementCommon (
+  IN     REDFISH_PLATFORM_CONFIG_PRIVATE  *RedfishPlatformConfigPrivate,
+  IN     CHAR8                            *Schema,
+  IN     EFI_STRING                       ConfigureLang,
+  IN     HII_STATEMENT_VALUE              *StatementValue
+  )
+{
+  EFI_STATUS                                Status;
+  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *TargetStatement;
+  EFI_STRING                                TempBuffer;
+
+  if (RedfishPlatformConfigPrivate == NULL || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (ConfigureLang) || StatementValue == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  TempBuffer = NULL;
+
+  Status = ProcessPendingList (&RedfishPlatformConfigPrivate->FormsetList, &RedfishPlatformConfigPrivate->PendingList);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a, ProcessPendingList failure: %r\n", __FUNCTION__, Status));
+    return Status;
+  }
+
+  TargetStatement = GetStatementPrivateByConfigureLang (&RedfishPlatformConfigPrivate->FormsetList, Schema, ConfigureLang);
+  if (TargetStatement == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a, No match HII statement is found by the given %s in schema %a\n", __FUNCTION__, ConfigureLang, Schema));
+    return EFI_NOT_FOUND;
+  }
+
+  if (StatementValue->Type != TargetStatement->HiiStatement->Value.Type) {
+    //
+    // We treat one-of type as string in Redfish. But one-of statement is not
+    // in string format from HII point of view. Do a patch here.
+    //
+    if (TargetStatement->HiiStatement->Operand == EFI_IFR_ONE_OF_OP && StatementValue->Type == EFI_IFR_TYPE_STRING) {
+      TempBuffer = AllocatePool (StatementValue->BufferLen * sizeof (CHAR16));
+      if (TempBuffer == NULL) {
+        return EFI_OUT_OF_RESOURCES;
+      }
+
+      AsciiStrToUnicodeStrS (StatementValue->Buffer, TempBuffer, StatementValue->BufferLen);
+      FreePool (StatementValue->Buffer);
+      StatementValue->Buffer = NULL;
+      StatementValue->BufferLen = 0;
+
+      Status = HiiStringToOneOfOptionValue (TargetStatement, Schema, TempBuffer, StatementValue);
+      if (EFI_ERROR (Status)) {
+        DEBUG ((DEBUG_ERROR, "%a, failed to find option value by the given %s\n", __FUNCTION__, TempBuffer));
+        FreePool (TempBuffer);
+        return EFI_NOT_FOUND;
+      }
+
+      FreePool (TempBuffer);
+    } else if (TargetStatement->HiiStatement->Operand == EFI_IFR_NUMERIC_OP && StatementValue->Type == EFI_IFR_TYPE_NUM_SIZE_64) {
+      //
+      // Redfish only has numeric value type and it does not care about the value size.
+      // Do a patch here so we have proper value size applied.
+      //
+      StatementValue->Type = TargetStatement->HiiStatement->Value.Type;
+    } else {
+      DEBUG ((DEBUG_ERROR, "%a, catch value type mismatch! input type: 0x%x but target value type: 0x%x\n", __FUNCTION__, StatementValue->Type, TargetStatement->HiiStatement->Value.Type));
+      ASSERT (FALSE);
+    }
+  }
+
+  Status = RedfishPlatformConfigSaveQuestionValue (
+             TargetStatement->ParentForm->ParentFormset->HiiFormSet,
+             TargetStatement->ParentForm->HiiForm,
+             TargetStatement->HiiStatement,
+             StatementValue
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a, failed to save question value: %r\n", __FUNCTION__, Status));
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Set Redfish value with the given Schema and Configure Language.
+
+  @param[in]   This                Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance.
+  @param[in]   Schema              The Redfish schema to query.
+  @param[in]   Version             The Redfish version to query.
+  @param[in]   ConfigureLang       The target value which match this configure Language.
+  @param[in]   Value               The value to set.
+
+  @retval EFI_SUCCESS              Value is returned successfully.
+  @retval Others                   Some error happened.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishPlatformConfigProtocolSetValue (
+  IN     EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL *This,
+  IN     CHAR8                                  *Schema,
+  IN     CHAR8                                  *Version,
+  IN     EFI_STRING                             ConfigureLang,
+  IN     EDKII_REDFISH_VALUE                    Value
+  )
+{
+  EFI_STATUS                                Status;
+  REDFISH_PLATFORM_CONFIG_PRIVATE           *RedfishPlatformConfigPrivate;
+  CHAR8                                     *FullSchema;
+  HII_STATEMENT_VALUE                       NewValue;
+
+  if (This == NULL || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || IS_EMPTY_STRING (ConfigureLang)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Value.Type == REDFISH_VALUE_TYPE_UNKNOWN || Value.Type >= REDFISH_VALUE_TYPE_MAX) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  RedfishPlatformConfigPrivate = REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS (This);
+  FullSchema = NULL;
+
+  FullSchema = GetFullSchemaString (Schema, Version);
+  if (FullSchema == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  ZeroMem (&NewValue, sizeof (HII_STATEMENT_VALUE));
+
+  switch (Value.Type) {
+    case REDFISH_VALUE_TYPE_INTEGER:
+    case REDFISH_VALUE_TYPE_BOOLEAN:
+      Status = RedfishNumericToHiiValue (&Value, &NewValue);
+      if (EFI_ERROR (Status)) {
+        DEBUG ((DEBUG_ERROR, "%a, failed to convert Redfish value to Hii value: %r\n", __FUNCTION__, Status));
+        goto RELEASE_RESOURCE;
+      }
+      break;
+    case REDFISH_VALUE_TYPE_STRING:
+      NewValue.Type = EFI_IFR_TYPE_STRING;
+      NewValue.BufferLen = (UINT16)AsciiStrSize (Value.Value.Buffer);
+      NewValue.Buffer = AllocateCopyPool (NewValue.BufferLen, Value.Value.Buffer);
+      if (NewValue.Buffer == NULL) {
+        Status = EFI_OUT_OF_RESOURCES;
+        goto RELEASE_RESOURCE;
+      }
+      break;
+    default:
+      ASSERT (FALSE);
+      break;
+  }
+
+  Status = RedfishPlatformConfigSetStatementCommon (RedfishPlatformConfigPrivate, FullSchema, ConfigureLang, &NewValue);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a, failed to set value to statement: %r\n", __FUNCTION__, Status));
+  }
+
+RELEASE_RESOURCE:
+
+  if (FullSchema != NULL) {
+    FreePool (FullSchema);
+  }
+
+  return Status;
+}
+
+/**
+  Get the list of Configure Language from platform configuration by the given Schema and Pattern.
+
+  @param[in]   This                Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance.
+  @param[in]   Schema              The Redfish schema to query.
+  @param[in]   Version             The Redfish version to query.
+  @param[in]   Pattern             The target Configure Language pattern.
+  @param[out]  ConfigureLangList         The list of Configure Language.
+  @param[out]  Count               The number of Configure Language in ConfigureLangList.
+
+  @retval EFI_SUCCESS              ConfigureLangList is returned successfully.
+  @retval Others                   Some error happened.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishPlatformConfigProtocolGetConfigureLang (
+  IN     EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL *This,
+  IN     CHAR8                                  *Schema,
+  IN     CHAR8                                  *Version,
+  IN     EFI_STRING                             Pattern,
+  OUT    EFI_STRING                             **ConfigureLangList,
+  OUT    UINTN                                  *Count
+  )
+{
+  REDFISH_PLATFORM_CONFIG_PRIVATE                 *RedfishPlatformConfigPrivate;
+  EFI_STATUS                                      Status;
+  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST  StatementList;
+  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF   *StatementRef;
+  LIST_ENTRY                                      *NextLink;
+  EFI_STRING                                      TmpString;
+  EFI_STRING                                      *TmpConfigureLangList;
+  UINTN                                           Index;
+  CHAR8                                           *FullSchema;
+
+  if (This == NULL || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || Count == NULL || ConfigureLangList == NULL || IS_EMPTY_STRING (Pattern)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *Count = 0;
+  *ConfigureLangList = NULL;
+  FullSchema = NULL;
+  RedfishPlatformConfigPrivate = REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS (This);
+
+  Status = ProcessPendingList (&RedfishPlatformConfigPrivate->FormsetList, &RedfishPlatformConfigPrivate->PendingList);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a, ProcessPendingList failure: %r\n", __FUNCTION__, Status));
+    return Status;
+  }
+
+  FullSchema = GetFullSchemaString (Schema, Version);
+  if (FullSchema == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Status = GetStatementPrivateByConfigureLangRegex (
+             RedfishPlatformConfigPrivate->RegularExpressionProtocol,
+             &RedfishPlatformConfigPrivate->FormsetList,
+             FullSchema,
+             Pattern,
+             &StatementList
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a, GetStatementPrivateByConfigureLangRegex failure: %r\n", __FUNCTION__, Status));
+    goto RELEASE_RESOURCE;
+  }
+
+  if (!IsListEmpty (&StatementList.StatementList)) {
+
+    TmpConfigureLangList = AllocateZeroPool (sizeof (CHAR16 *) * StatementList.Count);
+    if (TmpConfigureLangList == NULL) {
+      Status = EFI_OUT_OF_RESOURCES;
+      goto RELEASE_RESOURCE;
+    }
+
+    Index = 0;
+    NextLink = GetFirstNode (&StatementList.StatementList);
+    while (!IsNull (&StatementList.StatementList, NextLink)) {
+      StatementRef = REDFISH_PLATFORM_CONFIG_STATEMENT_REF_FROM_LINK (NextLink);
+      NextLink = GetNextNode (&StatementList.StatementList, NextLink);
+
+      ASSERT (StatementRef->Statement->Description != 0);
+      if (StatementRef->Statement->Description != 0) {
+        TmpString = HiiGetRedfishString (StatementRef->Statement->ParentForm->ParentFormset->HiiHandle, FullSchema, StatementRef->Statement->Description);
+        ASSERT (TmpString != NULL);
+        if (TmpString != NULL) {
+          TmpConfigureLangList[Index] = AllocateCopyPool (StrSize (TmpString), TmpString);
+          ASSERT (TmpConfigureLangList[Index] != NULL);
+          FreePool (TmpString);
+          ++Index;
+        }
+      }
+    }
+  }
+
+  *Count = StatementList.Count;
+  *ConfigureLangList = TmpConfigureLangList;
+
+RELEASE_RESOURCE:
+
+  if (FullSchema != NULL) {
+    FreePool (FullSchema);
+  }
+
+  ReleaseStatementList (&StatementList);
+
+  return Status;
+}
+
+
+/**
+  Get the list of supported Redfish schema from paltform configuration on give HII handle.
+
+  @param[in]   This                Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance.
+  @param[in]   HiiHandle           The target handle to search. If handle is NULL,
+                                   this function return all schema from HII database.
+  @param[out]  SupportedSchema     The supported schema list which is separated by ';'.
+                                   The SupportedSchema is allocated by the callee. It's caller's
+                                   responsibility to free this buffer using FreePool().
+
+  @retval EFI_SUCCESS              Schema is returned successfully.
+  @retval Others                   Some error happened.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishPlatformConfigProtocolGetSupportedSchema (
+  IN     EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL   *This,
+  IN     EFI_HII_HANDLE                           HiiHandle,       OPTIONAL
+  OUT    CHAR8                                    **SupportedSchema
+  )
+{
+  REDFISH_PLATFORM_CONFIG_PRIVATE           *RedfishPlatformConfigPrivate;
+  EFI_STATUS                                Status;
+  LIST_ENTRY                                *HiiFormsetLink;
+  LIST_ENTRY                                *HiiFormsetNextLink;
+  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *HiiFormsetPrivate;
+  UINTN                                     Index;
+  UINTN                                     StringSize;
+  CHAR8                                     *StringBuffer;
+  UINTN                                     StringIndex;
+
+  if (This == NULL || SupportedSchema == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *SupportedSchema = NULL;
+
+  RedfishPlatformConfigPrivate = REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS (This);
+
+  Status = ProcessPendingList (&RedfishPlatformConfigPrivate->FormsetList, &RedfishPlatformConfigPrivate->PendingList);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a, ProcessPendingList failure: %r\n", __FUNCTION__, Status));
+    return Status;
+  }
+
+  if (IsListEmpty (&RedfishPlatformConfigPrivate->FormsetList)) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Calculate for string buffer size.
+  //
+  StringSize = 0;
+  HiiFormsetLink = GetFirstNode (&RedfishPlatformConfigPrivate->FormsetList);
+  while (!IsNull (&RedfishPlatformConfigPrivate->FormsetList, HiiFormsetLink)) {
+    HiiFormsetNextLink = GetNextNode (&RedfishPlatformConfigPrivate->FormsetList, HiiFormsetLink);
+    HiiFormsetPrivate = REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink);
+
+    if (HiiHandle != NULL && HiiHandle != HiiFormsetPrivate->HiiHandle) {
+      HiiFormsetLink = HiiFormsetNextLink;
+      continue;
+    }
+
+    if (HiiFormsetPrivate->SupportedSchema.Count > 0) {
+      for (Index = 0; Index < HiiFormsetPrivate->SupportedSchema.Count; Index++) {
+        StringSize += AsciiStrSize (HiiFormsetPrivate->SupportedSchema.SchemaList[Index]);
+      }
+    }
+
+    HiiFormsetLink = HiiFormsetNextLink;
+  }
+
+  if (StringSize == 0) {
+    return EFI_NOT_FOUND;
+  }
+
+  StringBuffer = AllocatePool (StringSize);
+  if (StringBuffer == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  StringIndex = 0;
+  HiiFormsetLink = GetFirstNode (&RedfishPlatformConfigPrivate->FormsetList);
+  while (!IsNull (&RedfishPlatformConfigPrivate->FormsetList, HiiFormsetLink)) {
+    HiiFormsetNextLink = GetNextNode (&RedfishPlatformConfigPrivate->FormsetList, HiiFormsetLink);
+    HiiFormsetPrivate = REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink);
+
+    if (HiiHandle != NULL && HiiHandle != HiiFormsetPrivate->HiiHandle) {
+      HiiFormsetLink = HiiFormsetNextLink;
+      continue;
+    }
+
+    if (HiiFormsetPrivate->SupportedSchema.Count > 0) {
+      for (Index = 0; Index < HiiFormsetPrivate->SupportedSchema.Count; Index++) {
+        AsciiStrCpyS (&StringBuffer[StringIndex], (StringSize - StringIndex), HiiFormsetPrivate->SupportedSchema.SchemaList[Index]);
+        StringIndex += AsciiStrLen (HiiFormsetPrivate->SupportedSchema.SchemaList[Index]);
+        StringBuffer[StringIndex] = ';';
+        ++StringIndex;
+      }
+    }
+
+    HiiFormsetLink = HiiFormsetNextLink;
+  }
+
+  StringBuffer[--StringIndex] = '\0';
+
+  *SupportedSchema = StringBuffer;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Functions which are registered to receive notification of
+  database events have this prototype. The actual event is encoded
+  in NotifyType. The following table describes how PackageType,
+  PackageGuid, Handle, and Package are used for each of the
+  notification types.
+
+  @param[in] PackageType  Package type of the notification.
+  @param[in] PackageGuid  If PackageType is
+                          EFI_HII_PACKAGE_TYPE_GUID, then this is
+                          the pointer to the GUID from the Guid
+                          field of EFI_HII_PACKAGE_GUID_HEADER.
+                          Otherwise, it must be NULL.
+  @param[in] Package      Points to the package referred to by the
+                          notification Handle The handle of the package
+                          list which contains the specified package.
+  @param[in] Handle       The HII handle.
+  @param[in] NotifyType   The type of change concerning the
+                          database. See
+                          EFI_HII_DATABASE_NOTIFY_TYPE.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishPlatformConfigFormUpdateNotify (
+  IN UINT8                              PackageType,
+  IN CONST EFI_GUID                     *PackageGuid,
+  IN CONST EFI_HII_PACKAGE_HEADER       *Package,
+  IN EFI_HII_HANDLE                     Handle,
+  IN EFI_HII_DATABASE_NOTIFY_TYPE       NotifyType
+  )
+{
+  EFI_STATUS  Status;
+
+  if (NotifyType == EFI_HII_DATABASE_NOTIFY_NEW_PACK || NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
+    //
+    // HII formset on this handle is updated by driver during run-time. The formset needs to be reloaded.
+    //
+    Status = NotifyFormsetUpdate (Handle, &mRedfishPlatformConfigPrivate->PendingList);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "%a, failed to notify updated formset of HII handle: 0x%x\n", __FUNCTION__, Handle));
+      return Status;
+    }
+  } else if (NotifyType == EFI_HII_DATABASE_NOTIFY_REMOVE_PACK) {
+    //
+    // HII resource is removed. The formset is no longer exist.
+    //
+    Status = NotifyFormsetDeleted (Handle, &mRedfishPlatformConfigPrivate->PendingList);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "%a, failed to notify deleted formset of HII handle: 0x%x\n", __FUNCTION__, Handle));
+      return Status;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This is a EFI_HII_STRING_PROTOCOL notification event handler.
+
+  Install HII package notification.
+
+  @param[in] Event    Event whose notification function is being invoked.
+  @param[in] Context  Pointer to the notification function's context.
+
+**/
+VOID
+EFIAPI
+HiiStringProtocolInstalled (
+  IN  EFI_EVENT       Event,
+  IN  VOID            *Context
+  )
+{
+  EFI_STATUS  Status;
+
+  //
+  // Locate HII database protocol.
+  //
+  Status = gBS->LocateProtocol (
+                  &gEfiHiiStringProtocolGuid,
+                  NULL,
+                  (VOID **)&mRedfishPlatformConfigPrivate->HiiString
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a, locate EFI_HII_STRING_PROTOCOL failure: %r\n", __FUNCTION__, Status));
+    return;
+  }
+
+  gBS->CloseEvent (Event);
+  mRedfishPlatformConfigPrivate->HiiStringNotify.ProtocolEvent = NULL;
+}
+
+/**
+  This is a EFI_HII_DATABASE_PROTOCOL notification event handler.
+
+  Install HII package notification.
+
+  @param[in] Event    Event whose notification function is being invoked.
+  @param[in] Context  Pointer to the notification function's context.
+
+**/
+VOID
+EFIAPI
+HiiDatabaseProtocolInstalled (
+  IN  EFI_EVENT       Event,
+  IN  VOID            *Context
+  )
+{
+  EFI_STATUS  Status;
+
+  //
+  // Locate HII database protocol.
+  //
+  Status = gBS->LocateProtocol (
+                  &gEfiHiiDatabaseProtocolGuid,
+                  NULL,
+                  (VOID **)&mRedfishPlatformConfigPrivate->HiiDatabase
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a, locate EFI_HII_DATABASE_PROTOCOL failure: %r\n", __FUNCTION__, Status));
+    return;
+  }
+
+  //
+  // Register package notification when new form package is installed.
+  //
+  Status = mRedfishPlatformConfigPrivate->HiiDatabase->RegisterPackageNotify (
+                                             mRedfishPlatformConfigPrivate->HiiDatabase,
+                                             EFI_HII_PACKAGE_FORMS,
+                                             NULL,
+                                             RedfishPlatformConfigFormUpdateNotify,
+                                             EFI_HII_DATABASE_NOTIFY_NEW_PACK,
+                                             &mRedfishPlatformConfigPrivate->NotifyHandle
+                                             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a, RegisterPackageNotify for EFI_HII_DATABASE_NOTIFY_NEW_PACK failure: %r\n", __FUNCTION__, Status));
+  }
+
+  //
+  // Register package notification when new form package is updated.
+  //
+  Status = mRedfishPlatformConfigPrivate->HiiDatabase->RegisterPackageNotify (
+                                             mRedfishPlatformConfigPrivate->HiiDatabase,
+                                             EFI_HII_PACKAGE_FORMS,
+                                             NULL,
+                                             RedfishPlatformConfigFormUpdateNotify,
+                                             EFI_HII_DATABASE_NOTIFY_ADD_PACK,
+                                             &mRedfishPlatformConfigPrivate->NotifyHandle
+                                             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a, RegisterPackageNotify for EFI_HII_DATABASE_NOTIFY_NEW_PACK failure: %r\n", __FUNCTION__, Status));
+  }
+
+#if REDFISH_PLATFORM_CONFIG_DELETE_EXPIRED_FORMSET
+  //
+  // Register package notification when new form package is removed.
+  //
+  Status = mRedfishPlatformConfigPrivate->HiiDatabase->RegisterPackageNotify (
+                                             mRedfishPlatformConfigPrivate->HiiDatabase,
+                                             EFI_HII_PACKAGE_FORMS,
+                                             NULL,
+                                             RedfishPlatformConfigFormUpdateNotify,
+                                             EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
+                                             &mRedfishPlatformConfigPrivate->NotifyHandle
+                                             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a, RegisterPackageNotify for EFI_HII_DATABASE_NOTIFY_NEW_PACK failure: %r\n", __FUNCTION__, Status));
+  }
+#endif
+
+  gBS->CloseEvent (Event);
+  mRedfishPlatformConfigPrivate->HiiDbNotify.ProtocolEvent = NULL;
+
+}
+
+/**
+  This is a EFI_REGULAR_EXPRESSION_PROTOCOL notification event handler.
+
+  @param[in] Event    Event whose notification function is being invoked.
+  @param[in] Context  Pointer to the notification function's context.
+
+**/
+VOID
+EFIAPI
+RegexProtocolInstalled (
+  IN  EFI_EVENT       Event,
+  IN  VOID            *Context
+  )
+{
+  EFI_STATUS  Status;
+
+  //
+  // Locate regular expression protocol.
+  //
+  Status = gBS->LocateProtocol (
+                  &gEfiRegularExpressionProtocolGuid,
+                  NULL,
+                  (VOID **)&mRedfishPlatformConfigPrivate->RegularExpressionProtocol
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a, locate EFI_REGULAR_EXPRESSION_PROTOCOL failure: %r\n", __FUNCTION__, Status));
+    return;
+  }
+
+  gBS->CloseEvent (Event);
+  mRedfishPlatformConfigPrivate->RegexNotify.ProtocolEvent = NULL;
+
+}
+
+/**
+  Unloads an image.
+
+  @param  ImageHandle           Handle that identifies the image to be unloaded.
+
+  @retval EFI_SUCCESS           The image has been unloaded.
+  @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishPlatformConfigDxeUnload (
+  IN EFI_HANDLE  ImageHandle
+  )
+{
+  EFI_STATUS Status;
+
+  if (mRedfishPlatformConfigPrivate != NULL) {
+    Status = gBS->UninstallProtocolInterface (
+                    mRedfishPlatformConfigPrivate->ImageHandle,
+                    &gEdkIIRedfishPlatformConfigProtocolGuid,
+                    (VOID*)&mRedfishPlatformConfigPrivate->Protocol
+                    );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "%a, can not uninstall gEdkIIRedfishPlatformConfigProtocolGuid: %r\n", __FUNCTION__, Status));
+      ASSERT (FALSE);
+    }
+
+    //
+    // Close events
+    //
+    if (mRedfishPlatformConfigPrivate->HiiDbNotify.ProtocolEvent != NULL) {
+      gBS->CloseEvent (mRedfishPlatformConfigPrivate->HiiDbNotify.ProtocolEvent);
+    }
+    if (mRedfishPlatformConfigPrivate->HiiStringNotify.ProtocolEvent != NULL) {
+      gBS->CloseEvent (mRedfishPlatformConfigPrivate->HiiStringNotify.ProtocolEvent);
+    }
+    if (mRedfishPlatformConfigPrivate->RegexNotify.ProtocolEvent != NULL) {
+      gBS->CloseEvent (mRedfishPlatformConfigPrivate->RegexNotify.ProtocolEvent);
+    }
+
+    //
+    // Unregister package notification.
+    //
+    if (mRedfishPlatformConfigPrivate->NotifyHandle != NULL) {
+      mRedfishPlatformConfigPrivate->HiiDatabase->UnregisterPackageNotify (
+                                          mRedfishPlatformConfigPrivate->HiiDatabase,
+                                          mRedfishPlatformConfigPrivate->NotifyHandle
+                                          );
+    }
+
+    ReleaseFormsetList (&mRedfishPlatformConfigPrivate->FormsetList);
+    FreePool (mRedfishPlatformConfigPrivate);
+    mRedfishPlatformConfigPrivate = NULL;
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  This is the declaration of an EFI image entry point. This entry point is
+  the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
+  both device drivers and bus drivers.
+
+  @param  ImageHandle           The firmware allocated handle for the UEFI image.
+  @param  SystemTable           A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS           The operation completed successfully.
+  @retval Others                An unexpected error occurred.
+**/
+EFI_STATUS
+EFIAPI
+RedfishPlatformConfigDxeEntryPoint (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  mRedfishPlatformConfigPrivate = (REDFISH_PLATFORM_CONFIG_PRIVATE *)AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_PRIVATE));
+  if (mRedfishPlatformConfigPrivate == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a, can not allocate pool for REDFISH_PLATFORM_CONFIG_PRIVATE\n", __FUNCTION__));
+    ASSERT (FALSE);
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Protocol initialization
+  //
+  mRedfishPlatformConfigPrivate->ImageHandle = ImageHandle;
+  mRedfishPlatformConfigPrivate->Protocol.GetValue = RedfishPlatformConfigProtocolGetValue;
+  mRedfishPlatformConfigPrivate->Protocol.SetValue = RedfishPlatformConfigProtocolSetValue;
+  mRedfishPlatformConfigPrivate->Protocol.GetConfigureLang = RedfishPlatformConfigProtocolGetConfigureLang;
+  mRedfishPlatformConfigPrivate->Protocol.GetSupportedSchema = RedfishPlatformConfigProtocolGetSupportedSchema;
+
+  InitializeListHead (&mRedfishPlatformConfigPrivate->FormsetList);
+  InitializeListHead (&mRedfishPlatformConfigPrivate->PendingList);
+
+  Status = gBS->InstallProtocolInterface (
+                  &ImageHandle,
+                  &gEdkIIRedfishPlatformConfigProtocolGuid,
+                  EFI_NATIVE_INTERFACE,
+                  (VOID*)&mRedfishPlatformConfigPrivate->Protocol
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a, can not install gEdkIIRedfishPlatformConfigProtocolGuid: %r\n", __FUNCTION__, Status));
+    ASSERT (FALSE);
+  }
+
+  //
+  // Install protocol notification if HII database protocol is installed.
+  //
+  mRedfishPlatformConfigPrivate->HiiDbNotify.ProtocolEvent = EfiCreateProtocolNotifyEvent (
+                                                              &gEfiHiiDatabaseProtocolGuid,
+                                                              TPL_CALLBACK,
+                                                              HiiDatabaseProtocolInstalled,
+                                                              NULL,
+                                                              &mRedfishPlatformConfigPrivate->HiiDbNotify.Registration
+                                                              );
+  if (mRedfishPlatformConfigPrivate->HiiDbNotify.ProtocolEvent == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a, failed to create protocol notification for gEfiHiiDatabaseProtocolGuid\n", __FUNCTION__));
+    ASSERT (FALSE);
+  }
+
+  //
+  // Install protocol notification if HII string protocol is installed.
+  //
+  mRedfishPlatformConfigPrivate->HiiStringNotify.ProtocolEvent = EfiCreateProtocolNotifyEvent (
+                                                                  &gEfiHiiStringProtocolGuid,
+                                                                  TPL_CALLBACK,
+                                                                  HiiStringProtocolInstalled,
+                                                                  NULL,
+                                                                  &mRedfishPlatformConfigPrivate->HiiStringNotify.Registration
+                                                                  );
+  if (mRedfishPlatformConfigPrivate->HiiStringNotify.ProtocolEvent == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a, failed to create protocol notification for gEfiHiiStringProtocolGuid\n", __FUNCTION__));
+    ASSERT (FALSE);
+  }
+
+  //
+  // Install protocol notification if regular expression protocol is installed.
+  //
+  mRedfishPlatformConfigPrivate->RegexNotify.ProtocolEvent = EfiCreateProtocolNotifyEvent (
+                                                              &gEfiRegularExpressionProtocolGuid,
+                                                              TPL_CALLBACK,
+                                                              RegexProtocolInstalled,
+                                                              NULL,
+                                                              &mRedfishPlatformConfigPrivate->RegexNotify.Registration
+                                                              );
+  if (mRedfishPlatformConfigPrivate->RegexNotify.ProtocolEvent == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a, failed to create protocol notification for gEfiRegularExpressionProtocolGuid\n", __FUNCTION__));
+    ASSERT (FALSE);
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.c b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.c
new file mode 100644
index 00000000000..d9eab6c883e
--- /dev/null
+++ b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.c
@@ -0,0 +1,1240 @@
+/** @file
+
+  The implementation of EDKII Redfidh Platform Config Protocol.
+
+  (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include "RedfishPlatformConfigDxe.h"
+#include "RedfishPlatformConfigImpl.h"
+
+extern REDFISH_PLATFORM_CONFIG_PRIVATE *mRedfishPlatformConfigPrivate;
+
+/**
+  Debug dump HII string
+
+  @param[in]  HiiHandle   HII handle instance
+  @param[in]  StringId    HII string to dump
+
+  @retval EFI_SUCCESS       Dump HII string successfully
+  @retval Others            Errors occur
+
+**/
+EFI_STATUS
+DumpHiiString (
+  IN EFI_HII_HANDLE HiiHandle,
+  IN EFI_STRING_ID  StringId
+  )
+{
+  EFI_STRING String;
+
+  if (HiiHandle == NULL || StringId == 0) {
+    DEBUG ((DEBUG_INFO, "???"));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  String = HiiGetString (HiiHandle, StringId, NULL);
+  if (String == NULL) {
+    return EFI_NOT_FOUND;
+  }
+
+  DEBUG ((DEBUG_INFO, "%s", String));
+  FreePool (String);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Debug dump HII form-set data
+
+  @param[in]  FormsetPrivate    HII form-set private instance.
+
+  @retval EFI_SUCCESS       Dump form-set successfully
+  @retval Others            Errors occur
+
+**/
+EFI_STATUS
+DumpFormset (
+  IN REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *FormsetPrivate
+  )
+{
+  LIST_ENTRY                      *HiiFormLink;
+  LIST_ENTRY                      *HiiNextFormLink;
+  REDFISH_PLATFORM_CONFIG_FORM_PRIVATE      *HiiFormPrivate;
+  LIST_ENTRY                      *HiiStatementLink;
+  LIST_ENTRY                      *HiiNextStatementLink;
+  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *HiiStatementPrivate;
+  UINTN                           Index;
+
+  if (FormsetPrivate == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Index = 0;
+  HiiFormLink = GetFirstNode (&FormsetPrivate->HiiFormList);
+  while (!IsNull (&FormsetPrivate->HiiFormList, HiiFormLink)) {
+    HiiFormPrivate = REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK (HiiFormLink);
+    HiiNextFormLink = GetNextNode (&FormsetPrivate->HiiFormList, HiiFormLink);
+
+    DEBUG ((DEBUG_INFO, "  [%d] form: %d title: ", ++Index, HiiFormPrivate->Id));
+    DumpHiiString (FormsetPrivate->HiiHandle, HiiFormPrivate->Title);
+    DEBUG ((DEBUG_INFO, "\n"));
+
+    HiiStatementLink = GetFirstNode (&HiiFormPrivate->StatementList);
+    while (!IsNull (&HiiFormPrivate->StatementList, HiiStatementLink)) {
+      HiiStatementPrivate = REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK (HiiStatementLink);
+      HiiNextStatementLink = GetNextNode (&HiiFormPrivate->StatementList, HiiStatementLink);
+
+      DEBUG ((DEBUG_INFO, "    QID: 0x%x Prompt: ", HiiStatementPrivate->QuestionId));
+      DumpHiiString (FormsetPrivate->HiiHandle, HiiStatementPrivate->Description);
+      DEBUG ((DEBUG_INFO, "\n"));
+
+      HiiStatementLink = HiiNextStatementLink;
+    }
+
+    HiiFormLink = HiiNextFormLink;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Debug dump HII form-set list
+
+  @param[in]  FormsetList   Form-set list instance
+
+  @retval EFI_SUCCESS       Dump list successfully
+  @retval Others            Errors occur
+
+**/
+EFI_STATUS
+DumpFormsetList (
+  IN  LIST_ENTRY      *FormsetList
+  )
+{
+  LIST_ENTRY                      *HiiFormsetLink;
+  LIST_ENTRY                      *HiiFormsetNextLink;
+  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *HiiFormsetPrivate;
+  UINTN                           Index;
+
+  if (FormsetList == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (IsListEmpty (FormsetList)) {
+    DEBUG ((DEBUG_INFO, "%a, Empty formset list\n", __FUNCTION__));
+    return EFI_SUCCESS;
+  }
+
+  Index = 0;
+  HiiFormsetLink = GetFirstNode (FormsetList);
+  while (!IsNull (FormsetList, HiiFormsetLink)) {
+    HiiFormsetNextLink = GetNextNode (FormsetList, HiiFormsetLink);
+    HiiFormsetPrivate = REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink);
+
+    DEBUG ((DEBUG_INFO, "[%d] HII Handle: 0x%x formset: %g at %s\n", ++Index, HiiFormsetPrivate->HiiHandle, &HiiFormsetPrivate->Guid, HiiFormsetPrivate->DevicePathStr));
+    DumpFormset (HiiFormsetPrivate);
+
+    HiiFormsetLink = HiiFormsetNextLink;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Retrieves a string from a string package in a English language. The
+  returned string is allocated using AllocatePool().  The caller is responsible
+  for freeing the allocated buffer using FreePool().
+
+  If HiiHandle is NULL, then ASSERT().
+  If StringId is 0, then ASSET.
+
+  @param[in]  HiiStringProtocol EFI_HII_STRING_PROTOCOL instance.
+  @param[in]  HiiHandle         A handle that was previously registered in the HII Database.
+  @param[in]  StringId          The identifier of the string to retrieved from the string
+                                package associated with HiiHandle.
+
+  @retval NULL   The string specified by StringId is not present in the string package.
+  @retval Other  The string was returned.
+
+**/
+EFI_STRING
+HiiGetRedfishString (
+  IN EFI_HII_HANDLE           HiiHandle,
+  IN CHAR8                    *Language,
+  IN EFI_STRING_ID            StringId
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       StringSize;
+  CHAR16      TempString;
+  EFI_STRING  String;
+
+  if (mRedfishPlatformConfigPrivate->HiiString == NULL || HiiHandle == NULL || StringId == 0 || IS_EMPTY_STRING (Language)) {
+    ASSERT (FALSE);
+    return NULL;
+  }
+
+  //
+  // Retrieve the size of the string in the string package for the BestLanguage
+  //
+  StringSize = 0;
+  Status = mRedfishPlatformConfigPrivate->HiiString->GetString (
+                                             mRedfishPlatformConfigPrivate->HiiString,
+                                             Language,
+                                             HiiHandle,
+                                             StringId,
+                                             &TempString,
+                                             &StringSize,
+                                             NULL
+                                             );
+  //
+  // If GetString() returns EFI_SUCCESS for a zero size,
+  // then there are no supported languages registered for HiiHandle.  If GetString()
+  // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
+  // in the HII Database
+  //
+  if (Status != EFI_BUFFER_TOO_SMALL) {
+    return NULL;
+  }
+
+  //
+  // Allocate a buffer for the return string
+  //
+  String = AllocateZeroPool (StringSize);
+  if (String == NULL) {
+    return NULL;
+  }
+
+  //
+  // Retrieve the string from the string package
+  //
+  Status = mRedfishPlatformConfigPrivate->HiiString->GetString (
+                                             mRedfishPlatformConfigPrivate->HiiString,
+                                             Language,
+                                             HiiHandle,
+                                             StringId,
+                                             String,
+                                             &StringSize,
+                                             NULL
+                                             );
+  if (EFI_ERROR (Status)) {
+    //
+    // Free the buffer and return NULL if the supported languages can not be retrieved.
+    //
+    FreePool (String);
+    String = NULL;
+  }
+
+  //
+  // Return the Null-terminated Unicode string
+  //
+  return String;
+}
+
+/**
+  Get string from HII database in English language.
+
+  @param[in]  HiiHandle         A handle that was previously registered in the HII Database.
+  @param[in]  StringId          The identifier of the string to retrieved from the string
+                                package associated with HiiHandle.
+
+  @retval NULL   The string specified by StringId is not present in the string package.
+  @retval Other  The string was returned.
+
+**/
+EFI_STRING
+HiiGetEnglishString (
+  IN EFI_HII_HANDLE           HiiHandle,
+  IN EFI_STRING_ID            StringId
+  )
+{
+  return HiiGetRedfishString (HiiHandle, ENGLISH_LANGUAGE_CODE, StringId);
+}
+
+/**
+  Check and see if this is supported schema or not.
+
+  @param[in]  SupportedSchema   The list of supported schema.
+  @param[in]  Schema            Schema string to be checked.
+
+  @retval BOOLEAN               TRUE if this is supported schema. FALSE otherwise.
+
+**/
+BOOLEAN
+CheckSupportedSchema (
+  IN REDFISH_PLATFORM_CONFIG_SCHEMA   *SupportedSchema,
+  IN CHAR8                            *Schema
+  )
+{
+  UINTN Index;
+
+  if (SupportedSchema == NULL || IS_EMPTY_STRING (Schema)) {
+    return FALSE;
+  }
+
+  if (SupportedSchema->Count == 0) {
+    return FALSE;
+  }
+
+  for (Index = 0; Index < SupportedSchema->Count; Index++) {
+    if (AsciiStrCmp (SupportedSchema->SchemaList[Index], Schema) == 0) {
+      return TRUE;
+    }
+  }
+
+  return FALSE;
+}
+
+/**
+  Get the list of supported schema from the given HII handle.
+
+  @param[in]  HiiHandle         HII handle instance.
+  @param[out] SupportedSchema   Supported schema on this HII handle.
+
+  @retval EFI_SUCCESS           Schema list is returned.
+  @retval EFI_INVALID_PARAMETER HiiHandle is NULL or SupportedSchema is NULL.
+  @retval EFI_NOT_FOUND         No supported schema found.
+  @retval EFI_OUT_OF_RESOURCES  System is out of memory.
+
+**/
+EFI_STATUS
+GetSupportedSchema (
+  IN  EFI_HII_HANDLE                  HiiHandle,
+  OUT REDFISH_PLATFORM_CONFIG_SCHEMA  *SupportedSchema
+  )
+{
+  CHAR8 *SupportedLanguages;
+  UINTN Index;
+  UINTN LangIndex;
+  UINTN Count;
+  UINTN StrSize;
+  UINTN ListIndex;
+
+  if (HiiHandle == NULL || SupportedSchema == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  SupportedSchema->Count = 0;
+
+  SupportedLanguages = HiiGetSupportedLanguages (HiiHandle);
+  if (SupportedLanguages == NULL) {
+    return EFI_NOT_FOUND;
+  }
+
+  Index = 0;
+  LangIndex = 0;
+  Count = 0;
+  while (TRUE) {
+    if (SupportedLanguages[Index] == ';' || SupportedLanguages[Index] == '\0') {
+      if (AsciiStrnCmp (&SupportedLanguages[LangIndex], X_UEFI_SCHEMA_PREFIX, AsciiStrLen (X_UEFI_SCHEMA_PREFIX)) == 0) {
+        ++Count;
+      }
+      LangIndex = Index + 1;
+    }
+
+    if (SupportedLanguages[Index] == '\0') {
+      break;
+    }
+
+    ++Index;
+  }
+
+  if (Count == 0) {
+    return EFI_NOT_FOUND;
+  }
+
+  SupportedSchema->Count = Count;
+  SupportedSchema->SchemaList = AllocatePool (sizeof (CHAR8 *) * Count);
+  if (SupportedSchema->SchemaList == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Index = 0;
+  LangIndex = 0;
+  ListIndex = 0;
+  while (TRUE) {
+
+    if (SupportedLanguages[Index] == ';' || SupportedLanguages[Index] == '\0') {
+      if (AsciiStrnCmp (&SupportedLanguages[LangIndex], X_UEFI_SCHEMA_PREFIX, AsciiStrLen (X_UEFI_SCHEMA_PREFIX)) == 0) {
+        StrSize = Index - LangIndex;
+        SupportedSchema->SchemaList[ListIndex] = AllocateCopyPool ((StrSize + 1), &SupportedLanguages[LangIndex]);
+        SupportedSchema->SchemaList[ListIndex][StrSize] = '\0';
+        ++ListIndex;
+      }
+
+      LangIndex = Index + 1;
+    }
+
+    if (SupportedLanguages[Index] == '\0') {
+      break;
+    }
+
+    ++Index;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Search and find statement private instance by given regular expression patthern
+  which describes the Configure Language.
+
+  @param[in]  RegularExpressionProtocol   Regular express protocol.
+  @param[in]  FormsetList                 Form-set list to search.
+  @param[in]  Schema                      Schema to be matched.
+  @param[in]  Pattern                     Regular expression pattern.
+  @param[out] StatementList               Statement list that match above pattern.
+
+  @retval EFI_SUCCESS             Statement list is returned.
+  @retval EFI_INVALID_PARAMETER   Input parameter is NULL.
+  @retval EFI_NOT_READY           Regular express protocol is NULL.
+  @retval EFI_NOT_FOUND           No statement is found.
+  @retval EFI_OUT_OF_RESOURCES    System is out of memory.
+
+**/
+EFI_STATUS
+GetStatementPrivateByConfigureLangRegex (
+  IN  EFI_REGULAR_EXPRESSION_PROTOCOL                 *RegularExpressionProtocol,
+  IN  LIST_ENTRY                                      *FormsetList,
+  IN  CHAR8                                           *Schema,
+  IN  EFI_STRING                                      Pattern,
+  OUT REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST  *StatementList
+  )
+{
+  LIST_ENTRY                      *HiiFormsetLink;
+  LIST_ENTRY                      *HiiFormsetNextLink;
+  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *HiiFormsetPrivate;
+  LIST_ENTRY                      *HiiFormLink;
+  LIST_ENTRY                      *HiiNextFormLink;
+  REDFISH_PLATFORM_CONFIG_FORM_PRIVATE      *HiiFormPrivate;
+  LIST_ENTRY                      *HiiStatementLink;
+  LIST_ENTRY                      *HiiNextStatementLink;
+  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *HiiStatementPrivate;
+  EFI_STRING                      TmpString;
+  UINTN                           CaptureCount;
+  BOOLEAN                         IsMatch;
+  EFI_STATUS                      Status;
+  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF *StatementRef;
+
+  if (FormsetList == NULL || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Pattern) || StatementList == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (RegularExpressionProtocol == NULL) {
+    return EFI_NOT_READY;
+  }
+
+  StatementList->Count = 0;
+  InitializeListHead (&StatementList->StatementList);
+
+  if (IsListEmpty (FormsetList)) {
+    return EFI_NOT_FOUND;
+  }
+
+  HiiFormsetLink = GetFirstNode (FormsetList);
+  while (!IsNull (FormsetList, HiiFormsetLink)) {
+    HiiFormsetNextLink = GetNextNode (FormsetList, HiiFormsetLink);
+    HiiFormsetPrivate = REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink);
+
+    //
+    // Performance check.
+    // If there is no desired Redfish schema found, skip this formset.
+    //
+    if (!CheckSupportedSchema (&HiiFormsetPrivate->SupportedSchema, Schema)) {
+      HiiFormsetLink = HiiFormsetNextLink;
+      continue;
+    }
+
+    HiiFormLink = GetFirstNode (&HiiFormsetPrivate->HiiFormList);
+    while (!IsNull (&HiiFormsetPrivate->HiiFormList, HiiFormLink)) {
+      HiiNextFormLink = GetNextNode (&HiiFormsetPrivate->HiiFormList, HiiFormLink);
+      HiiFormPrivate = REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK (HiiFormLink);
+
+      HiiStatementLink =GetFirstNode (&HiiFormPrivate->StatementList);
+      while (!IsNull (&HiiFormPrivate->StatementList, HiiStatementLink)) {
+        HiiNextStatementLink = GetNextNode (&HiiFormPrivate->StatementList, HiiStatementLink);
+        HiiStatementPrivate = REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK (HiiStatementLink);
+
+        if (HiiStatementPrivate->Description != 0) {
+          TmpString = HiiGetRedfishString (HiiFormsetPrivate->HiiHandle, Schema, HiiStatementPrivate->Description);
+          if (TmpString != NULL) {
+            Status = RegularExpressionProtocol->MatchString (
+                                                  RegularExpressionProtocol,
+                                                  TmpString,
+                                                  Pattern,
+                                                  &gEfiRegexSyntaxTypePerlGuid,
+                                                  &IsMatch,
+                                                  NULL,
+                                                  &CaptureCount
+                                                  );
+            if (EFI_ERROR (Status)) {
+              DEBUG ((DEBUG_ERROR, "%a, MatchString \"%s\" failed: %r\n", __FUNCTION__, Pattern, Status));
+              ASSERT (FALSE);
+              return Status;
+            }
+
+            //
+            // Found
+            //
+            if (IsMatch) {
+              StatementRef = AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF));
+              if (StatementRef == NULL) {
+                return EFI_OUT_OF_RESOURCES;
+              }
+
+              StatementRef->Statement = HiiStatementPrivate;
+              InsertTailList (&StatementList->StatementList, &StatementRef->Link);
+              ++StatementList->Count;
+            }
+
+            FreePool (TmpString);
+          }
+        }
+
+        HiiStatementLink = HiiNextStatementLink;
+      }
+
+      HiiFormLink = HiiNextFormLink;
+    }
+
+    HiiFormsetLink = HiiFormsetNextLink;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Get statement private instance by the given configure language.
+
+  @param[in]  FormsetList                 Form-set list to search.
+  @param[in]  Schema                      Schema to be matched.
+  @param[in]  ConfigureLang               Configure language.
+
+  @retval REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *   Pointer to statement private instance.
+
+**/
+REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *
+GetStatementPrivateByConfigureLang (
+  IN  LIST_ENTRY    *FormsetList,
+  IN  CHAR8         *Schema,
+  IN  EFI_STRING    ConfigureLang
+  )
+{
+  LIST_ENTRY                      *HiiFormsetLink;
+  LIST_ENTRY                      *HiiFormsetNextLink;
+  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *HiiFormsetPrivate;
+  LIST_ENTRY                      *HiiFormLink;
+  LIST_ENTRY                      *HiiNextFormLink;
+  REDFISH_PLATFORM_CONFIG_FORM_PRIVATE      *HiiFormPrivate;
+  LIST_ENTRY                      *HiiStatementLink;
+  LIST_ENTRY                      *HiiNextStatementLink;
+  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *HiiStatementPrivate;
+  EFI_STRING                      TmpString;
+
+  if (FormsetList == NULL || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (ConfigureLang)) {
+    return NULL;
+  }
+
+  if (IsListEmpty (FormsetList)) {
+    return NULL;
+  }
+
+  HiiFormsetLink = GetFirstNode (FormsetList);
+  while (!IsNull (FormsetList, HiiFormsetLink)) {
+    HiiFormsetNextLink = GetNextNode (FormsetList, HiiFormsetLink);
+    HiiFormsetPrivate = REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink);
+
+    //
+    // Performance check.
+    // If there is no desired Redfish schema found, skip this formset.
+    //
+    if (!CheckSupportedSchema (&HiiFormsetPrivate->SupportedSchema, Schema)) {
+      HiiFormsetLink = HiiFormsetNextLink;
+      continue;
+    }
+
+    HiiFormLink = GetFirstNode (&HiiFormsetPrivate->HiiFormList);
+    while (!IsNull (&HiiFormsetPrivate->HiiFormList, HiiFormLink)) {
+      HiiNextFormLink = GetNextNode (&HiiFormsetPrivate->HiiFormList, HiiFormLink);
+      HiiFormPrivate = REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK (HiiFormLink);
+
+      HiiStatementLink =GetFirstNode (&HiiFormPrivate->StatementList);
+      while (!IsNull (&HiiFormPrivate->StatementList, HiiStatementLink)) {
+        HiiNextStatementLink = GetNextNode (&HiiFormPrivate->StatementList, HiiStatementLink);
+        HiiStatementPrivate = REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK (HiiStatementLink);
+
+        DEBUG_CODE (
+          STATIC UINTN Index = 0;
+          DEBUG ((DEBUG_INFO, "%a, [%d] search %s in QID: 0x%x form: 0x%x formset: %g\n", __FUNCTION__, ++Index, ConfigureLang, HiiStatementPrivate->QuestionId, HiiFormPrivate->Id, &HiiFormsetPrivate->Guid));
+        );
+
+        if (HiiStatementPrivate->Description != 0) {
+          TmpString = HiiGetRedfishString (HiiFormsetPrivate->HiiHandle, Schema, HiiStatementPrivate->Description);
+          if (TmpString != NULL) {
+            if (StrCmp (TmpString, ConfigureLang) == 0) {
+              FreePool (TmpString);
+              return HiiStatementPrivate;
+            }
+
+            FreePool (TmpString);
+          }
+        }
+
+        HiiStatementLink = HiiNextStatementLink;
+      }
+
+      HiiFormLink = HiiNextFormLink;
+    }
+
+    HiiFormsetLink = HiiFormsetNextLink;
+  }
+
+  return NULL;
+}
+
+/**
+  Get form-set private instance by the given HII handle.
+
+  @param[in]  HiiHandle       HII handle instance.
+  @param[in]  FormsetList     Form-set list to search.
+
+  @retval REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *   Pointer to form-set private instance.
+
+**/
+REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *
+GetFormsetPrivateByHiiHandle (
+  IN  EFI_HII_HANDLE  HiiHandle,
+  IN  LIST_ENTRY      *FormsetList
+  )
+{
+  LIST_ENTRY                      *HiiFormsetLink;
+  LIST_ENTRY                      *HiiFormsetNextLink;
+  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *HiiFormsetPrivate;
+
+  if (HiiHandle == NULL || FormsetList == NULL) {
+    return NULL;
+  }
+
+  if (IsListEmpty (FormsetList)) {
+    return NULL;
+  }
+
+  HiiFormsetLink = GetFirstNode (FormsetList);
+  while (!IsNull (FormsetList, HiiFormsetLink)) {
+    HiiFormsetNextLink = GetNextNode (FormsetList, HiiFormsetLink);
+    HiiFormsetPrivate = REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink);
+
+    if (HiiFormsetPrivate->HiiHandle == HiiHandle) {
+      return HiiFormsetPrivate;
+    }
+
+    HiiFormsetLink = HiiFormsetNextLink;
+  }
+
+  return NULL;
+}
+
+/**
+  Release formset and all the forms and statements that belong to this formset.
+
+  @param[in]      FormsetPrivate Pointer to HP_HII_FORM_SET_PRIVATE
+
+  @retval         EFI_STATUS
+
+**/
+EFI_STATUS
+ReleaseFormset (
+  IN REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *FormsetPrivate
+  )
+{
+  LIST_ENTRY                      *HiiFormLink;
+  LIST_ENTRY                      *HiiNextFormLink;
+  REDFISH_PLATFORM_CONFIG_FORM_PRIVATE      *HiiFormPrivate;
+  LIST_ENTRY                      *HiiStatementLink;
+  LIST_ENTRY                      *HiiNextStatementLink;
+  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *HiiStatementPrivate;
+  UINTN                           Index;
+
+  if (FormsetPrivate == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  HiiFormLink = GetFirstNode (&FormsetPrivate->HiiFormList);
+  while (!IsNull (&FormsetPrivate->HiiFormList, HiiFormLink)) {
+    HiiFormPrivate = REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK (HiiFormLink);
+    HiiNextFormLink = GetNextNode (&FormsetPrivate->HiiFormList, HiiFormLink);
+
+    HiiStatementLink = GetFirstNode (&HiiFormPrivate->StatementList);
+    while (!IsNull (&HiiFormPrivate->StatementList, HiiStatementLink)) {
+      HiiStatementPrivate = REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK (HiiStatementLink);
+      HiiNextStatementLink = GetNextNode (&HiiFormPrivate->StatementList, HiiStatementLink);
+
+      //
+      // HiiStatementPrivate->HiiStatement will be released in DestroyFormSet().
+      //
+
+      if (HiiStatementPrivate->DesStringCache != NULL) {
+        FreePool (HiiStatementPrivate->DesStringCache);
+        HiiStatementPrivate->DesStringCache = NULL;
+      }
+
+      RemoveEntryList (&HiiStatementPrivate->Link);
+      FreePool (HiiStatementPrivate);
+      HiiStatementLink = HiiNextStatementLink;
+    }
+
+    //
+    // HiiStatementPrivate->HiiForm will be released in DestroyFormSet().
+    //
+
+    RemoveEntryList (&HiiFormPrivate->Link);
+    FreePool (HiiFormPrivate);
+    HiiFormLink = HiiNextFormLink;
+  }
+
+  if (FormsetPrivate->HiiFormSet != NULL) {
+    DestroyFormSet (FormsetPrivate->HiiFormSet);
+    FormsetPrivate->HiiFormSet = NULL;
+  }
+
+  FreePool (FormsetPrivate->DevicePathStr);
+
+  //
+  // Release schema list
+  //
+  if (FormsetPrivate->SupportedSchema.SchemaList != NULL) {
+    for (Index = 0; Index < FormsetPrivate->SupportedSchema.Count; Index++) {
+      FreePool (FormsetPrivate->SupportedSchema.SchemaList[Index]);
+    }
+
+    FreePool (FormsetPrivate->SupportedSchema.SchemaList);
+    FormsetPrivate->SupportedSchema.SchemaList = NULL;
+    FormsetPrivate->SupportedSchema.Count = 0;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Create new form-set instance.
+
+  @retval REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *   Pointer to newly created form-set private instance.
+
+**/
+REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *
+NewFormsetPrivate (
+  VOID
+  )
+{
+  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *NewFormsetPrivate;
+
+  NewFormsetPrivate = AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE));
+  if (NewFormsetPrivate == NULL) {
+    return NULL;
+  }
+
+  //
+  // Initial newly created formset private data.
+  //
+  InitializeListHead (&NewFormsetPrivate->HiiFormList);
+
+  return NewFormsetPrivate;
+}
+
+/**
+  Load the HII formset from the given HII handle.
+
+  @param[in]  HiiHandle       Target HII handle to load.
+  @param[out] FormsetPrivate  The formset private data.
+
+  @retval EFI_STATUS
+
+**/
+EFI_STATUS
+LoadFormset (
+  IN  EFI_HII_HANDLE                  HiiHandle,
+  OUT REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *FormsetPrivate
+  )
+{
+  EFI_STATUS                      Status;
+  HII_FORMSET                     *HiiFormSet;
+  HII_FORM                        *HiiForm;
+  LIST_ENTRY                      *HiiFormLink;
+  REDFISH_PLATFORM_CONFIG_FORM_PRIVATE      *HiiFormPrivate;
+  HII_STATEMENT                   *HiiStatement;
+  LIST_ENTRY                      *HiiStatementLink;
+  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *HiiStatementPrivate;
+  EFI_GUID                        ZeroGuid;
+
+  if (HiiHandle == NULL || FormsetPrivate == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+
+  HiiFormSet = AllocateZeroPool (sizeof (HII_FORMSET));
+  if (HiiFormSet == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Find HII formset by the given HII handle.
+  //
+  ZeroMem (&ZeroGuid, sizeof (ZeroGuid));
+  Status = CreateFormSetFromHiiHandle (HiiHandle, &ZeroGuid, HiiFormSet);
+  if (EFI_ERROR (Status) || IsListEmpty (&HiiFormSet->FormListHead)) {
+    Status = EFI_NOT_FOUND;
+    goto ErrorExit;
+  }
+
+  //
+  // Initialize formset
+  //
+  InitializeFormSet (HiiFormSet);
+
+  //
+  // Initialize formset private data.
+  //
+  FormsetPrivate->HiiFormSet = HiiFormSet;
+  FormsetPrivate->HiiHandle = HiiHandle;
+  CopyGuid (&FormsetPrivate->Guid, &HiiFormSet->Guid);
+  FormsetPrivate->DevicePathStr = ConvertDevicePathToText (HiiFormSet->DevicePath, FALSE, FALSE);
+  Status = GetSupportedSchema (FormsetPrivate->HiiHandle, &FormsetPrivate->SupportedSchema);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_WARN, "%a, No schema from HII handle: 0x%x found: %r\n", __FUNCTION__, FormsetPrivate->HiiHandle, Status));
+  }
+
+  HiiFormLink = GetFirstNode (&HiiFormSet->FormListHead);
+  while (!IsNull (&HiiFormSet->FormListHead, HiiFormLink)) {
+    HiiForm = HII_FORM_FROM_LINK (HiiFormLink);
+
+    HiiFormPrivate = AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_FORM_PRIVATE));
+    if (HiiFormPrivate == NULL) {
+      Status = EFI_OUT_OF_RESOURCES;
+      goto ErrorExit;
+    }
+
+    //
+    // Initialize form private data.
+    //
+    HiiFormPrivate->HiiForm = HiiForm;
+    HiiFormPrivate->Id = HiiForm->FormId;
+    HiiFormPrivate->Title = HiiForm->FormTitle;
+    HiiFormPrivate->ParentFormset = FormsetPrivate;
+    InitializeListHead (&HiiFormPrivate->StatementList);
+
+    HiiStatementLink = GetFirstNode (&HiiForm->StatementListHead);
+    while (!IsNull (&HiiForm->StatementListHead, HiiStatementLink)) {
+      HiiStatement = HII_STATEMENT_FROM_LINK (HiiStatementLink);
+
+      HiiStatementPrivate = AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE));
+      if (HiiStatementPrivate == NULL) {
+        Status = EFI_OUT_OF_RESOURCES;
+        goto ErrorExit;
+      }
+      //
+      // Initialize statement private data.
+      //
+      HiiStatementPrivate->HiiStatement = HiiStatement;
+      HiiStatementPrivate->QuestionId = HiiStatement->QuestionId;
+      HiiStatementPrivate->Description = HiiStatement->Prompt;
+      HiiStatementPrivate->ParentForm = HiiFormPrivate;
+
+      //
+      // Attach to statement list.
+      //
+      InsertTailList (&HiiFormPrivate->StatementList, &HiiStatementPrivate->Link);
+      HiiStatementLink = GetNextNode (&HiiForm->StatementListHead, HiiStatementLink);
+    }
+    //
+    // Attach to form list.
+    //
+    InsertTailList (&FormsetPrivate->HiiFormList, &HiiFormPrivate->Link);
+    HiiFormLink = GetNextNode (&HiiFormSet->FormListHead, HiiFormLink);
+  }
+
+  return EFI_SUCCESS;
+
+ErrorExit:
+
+  //
+  // Release HiiFormSet if HiiFormSet is not linked to FormsetPrivate yet.
+  //
+  if (HiiFormSet != NULL && FormsetPrivate->HiiFormSet != HiiFormSet) {
+    DestroyFormSet (HiiFormSet);
+  }
+
+  //
+  // Release resource when error happens.
+  //
+  ReleaseFormset (FormsetPrivate);
+
+  return Status;
+}
+
+/**
+  Release formset list and all the forms that belong to this formset.
+
+  @param[in]      FormsetList   Pointer to formst list that needs to be
+                                released.
+
+  @retval         EFI_STATUS
+
+**/
+EFI_STATUS
+LoadFormsetList (
+  IN   EFI_HII_HANDLE   *HiiHandle,
+  OUT  LIST_ENTRY       *FormsetList
+  )
+{
+  EFI_STATUS  Status;
+  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *FormsetPrivate;
+
+  if (HiiHandle == NULL || FormsetList == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  FormsetPrivate = GetFormsetPrivateByHiiHandle (HiiHandle, FormsetList);
+  if (FormsetPrivate != NULL) {
+    return EFI_ALREADY_STARTED;
+  }
+
+  FormsetPrivate =  NewFormsetPrivate ();
+  if (FormsetPrivate == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Load formset on the given HII handle.
+  //
+  Status = LoadFormset (HiiHandle, FormsetPrivate);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a, failed to load formset: %r\n", __FUNCTION__, Status));
+    FreePool (FormsetPrivate);
+    return Status;
+  }
+
+  //
+  // Attach to cache list.
+  //
+  InsertTailList (FormsetList, &FormsetPrivate->Link);
+
+  DEBUG_CODE (
+    DumpFormsetList (FormsetList);
+    );
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Release formset list and all the forms that belong to this formset.
+
+  @param[in]      FormsetList   Pointer to formst list that needs to be
+                                released.
+
+  @retval         EFI_STATUS
+
+**/
+EFI_STATUS
+ReleaseFormsetList (
+  IN  LIST_ENTRY      *FormsetList
+  )
+{
+  LIST_ENTRY                      *HiiFormsetLink;
+  LIST_ENTRY                      *HiiFormsetNextLink;
+  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *HiiFormsetPrivate;
+
+  if (FormsetList == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (IsListEmpty (FormsetList)) {
+    return EFI_SUCCESS;
+  }
+
+  HiiFormsetLink = GetFirstNode (FormsetList);
+  while (!IsNull (FormsetList, HiiFormsetLink)) {
+    HiiFormsetNextLink = GetNextNode (FormsetList, HiiFormsetLink);
+    HiiFormsetPrivate = REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink);
+
+    //
+    // Detach from list.
+    //
+    RemoveEntryList (&HiiFormsetPrivate->Link);
+    ReleaseFormset (HiiFormsetPrivate);
+    FreePool (HiiFormsetPrivate);
+    HiiFormsetLink = HiiFormsetNextLink;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Get all pending list.
+
+  @param[in]  HiiHandle   HII handle instance.
+  @param[in]  PendingList Pending list to keep pending data.
+
+  @retval REDFISH_PLATFORM_CONFIG_PENDING_LIST *   Pointer to pending list data.
+
+**/
+REDFISH_PLATFORM_CONFIG_PENDING_LIST *
+GetPendingList (
+  IN  EFI_HII_HANDLE   *HiiHandle,
+  IN  LIST_ENTRY       *PendingList
+  )
+{
+  LIST_ENTRY                 *PendingListLink;
+  REDFISH_PLATFORM_CONFIG_PENDING_LIST *Target;
+
+  if (HiiHandle == NULL || PendingList == NULL) {
+    return NULL;
+  }
+
+  if (IsListEmpty (PendingList)) {
+    return NULL;
+  }
+
+  PendingListLink = GetFirstNode (PendingList);
+  while (!IsNull (PendingList, PendingListLink)) {
+    Target = REDFISH_PLATFORM_CONFIG_PENDING_LIST_FROM_LINK (PendingListLink);
+
+    if (Target->HiiHandle == HiiHandle) {
+      return Target;
+    }
+
+    PendingListLink = GetNextNode (PendingList, PendingListLink);
+  }
+
+  return NULL;
+}
+
+/**
+  When HII database is updated. Keep updated HII handle into pending list so
+  we can process them later.
+
+  @param[in]  HiiHandle   HII handle instance.
+  @param[in]  PendingList Pending list to keep HII handle which is recently updated.
+
+  @retval EFI_SUCCESS             HII handle is saved in pending list.
+  @retval EFI_INVALID_PARAMETER   HiiHnalde is NULL or PendingList is NULL.
+  @retval EFI_OUT_OF_RESOURCES    System is out of memory.
+
+**/
+EFI_STATUS
+NotifyFormsetUpdate (
+  IN  EFI_HII_HANDLE   *HiiHandle,
+  IN  LIST_ENTRY       *PendingList
+  )
+{
+  REDFISH_PLATFORM_CONFIG_PENDING_LIST  *TargetPendingList;
+
+  if (HiiHandle == NULL || PendingList == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Check and see if this HII handle is processed already.
+  //
+  TargetPendingList = GetPendingList (HiiHandle, PendingList);
+  if (TargetPendingList != NULL) {
+    TargetPendingList->IsDeleted = FALSE;
+  DEBUG_CODE (
+    DEBUG ((DEBUG_INFO, "%a, HII handle: 0x%x is updated\n", __FUNCTION__, HiiHandle));
+    );
+    return EFI_SUCCESS;
+  }
+
+  TargetPendingList= AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_PENDING_LIST));
+  if (TargetPendingList == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  TargetPendingList->HiiHandle = HiiHandle;
+  TargetPendingList->IsDeleted = FALSE;
+
+  InsertTailList (PendingList, &TargetPendingList->Link);
+
+  DEBUG_CODE (
+    DEBUG ((DEBUG_INFO, "%a, HII handle: 0x%x is created\n", __FUNCTION__, HiiHandle));
+    );
+
+  return EFI_SUCCESS;
+}
+
+/**
+  When HII database is updated and form-set is deleted. Keep deleted HII handle into pending list so
+  we can process them later.
+
+  @param[in]  HiiHandle   HII handle instance.
+  @param[in]  PendingList Pending list to keep HII handle which is recently updated.
+
+  @retval EFI_SUCCESS             HII handle is saved in pending list.
+  @retval EFI_INVALID_PARAMETER   HiiHnalde is NULL or PendingList is NULL.
+  @retval EFI_OUT_OF_RESOURCES    System is out of memory.
+
+**/
+EFI_STATUS
+NotifyFormsetDeleted (
+  IN  EFI_HII_HANDLE   *HiiHandle,
+  IN  LIST_ENTRY       *PendingList
+  )
+{
+  REDFISH_PLATFORM_CONFIG_PENDING_LIST  *TargetPendingList;
+
+  if (HiiHandle == NULL || PendingList == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Check and see if this HII handle is processed already.
+  //
+  TargetPendingList = GetPendingList (HiiHandle, PendingList);
+  if (TargetPendingList != NULL) {
+    TargetPendingList->IsDeleted = TRUE;
+    DEBUG_CODE (
+      DEBUG ((DEBUG_INFO, "%a, HII handle: 0x%x is updated and deleted\n", __FUNCTION__, HiiHandle));
+      );
+    return EFI_SUCCESS;
+  }
+
+  TargetPendingList= AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_PENDING_LIST));
+  if (TargetPendingList == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  TargetPendingList->HiiHandle = HiiHandle;
+  TargetPendingList->IsDeleted = TRUE;
+
+  InsertTailList (PendingList, &TargetPendingList->Link);
+
+  DEBUG_CODE (
+    DEBUG ((DEBUG_INFO, "%a, HII handle: 0x%x is deleted\n", __FUNCTION__, HiiHandle));
+    );
+
+  return EFI_SUCCESS;
+}
+
+/**
+  There are HII database update and we need to process them accordingly so that we
+  won't use stale data. This function will parse updated HII handle again in order
+  to get updated data-set.
+
+  @param[in]  FormsetList   List to keep HII form-set.
+  @param[in]  PendingList   List to keep HII handle that is updated.
+
+  @retval EFI_SUCCESS             HII handle is saved in pending list.
+  @retval EFI_INVALID_PARAMETER   FormsetList is NULL or PendingList is NULL.
+
+**/
+EFI_STATUS
+ProcessPendingList (
+  IN  LIST_ENTRY       *FormsetList,
+  IN  LIST_ENTRY       *PendingList
+  )
+{
+  LIST_ENTRY                 *PendingListLink;
+  LIST_ENTRY                 *PendingListNextLink;
+  REDFISH_PLATFORM_CONFIG_PENDING_LIST *Target;
+  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *FormsetPrivate;
+  EFI_STATUS                      Status;
+
+
+  if (FormsetList == NULL || PendingList == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (IsListEmpty (PendingList)) {
+    return EFI_SUCCESS;
+  }
+
+  PendingListLink = GetFirstNode (PendingList);
+  while (!IsNull (PendingList, PendingListLink)) {
+    PendingListNextLink = GetNextNode (PendingList, PendingListLink);
+    Target = REDFISH_PLATFORM_CONFIG_PENDING_LIST_FROM_LINK (PendingListLink);
+
+    if (Target->IsDeleted) {
+      //
+      // The HII resource on this HII handle is removed. Release the formset.
+      //
+      FormsetPrivate = GetFormsetPrivateByHiiHandle (Target->HiiHandle, FormsetList);
+      if (FormsetPrivate != NULL) {
+        DEBUG ((DEBUG_INFO, "%a, formset: %g is removed because driver release HII resource it already\n", __FUNCTION__, FormsetPrivate->Guid));
+        RemoveEntryList (&FormsetPrivate->Link);
+        ReleaseFormset (FormsetPrivate);
+        FreePool (FormsetPrivate);
+      } else {
+        DEBUG ((DEBUG_WARN, "%a, formset on HII handle 0x%x was removed already\n", __FUNCTION__, Target->HiiHandle));
+      }
+    } else {
+      //
+      // The HII resource on this HII handle is updated/removed.
+      //
+      FormsetPrivate = GetFormsetPrivateByHiiHandle (Target->HiiHandle, FormsetList);
+      if (FormsetPrivate != NULL) {
+        //
+        // HII formset already exist, release it and query again.
+        //
+        DEBUG ((DEBUG_INFO, "%a, formset: %g is updated. Release current formset\n", __FUNCTION__, &FormsetPrivate->Guid));
+        RemoveEntryList (&FormsetPrivate->Link);
+        ReleaseFormset (FormsetPrivate);
+        FreePool (FormsetPrivate);
+      }
+
+      Status = LoadFormsetList (Target->HiiHandle, FormsetList);
+      if (EFI_ERROR (Status)) {
+        DEBUG ((DEBUG_ERROR, "%a, load formset from HII handle: 0x%x failed: %r\n", __FUNCTION__, Target->HiiHandle, Status));
+      }
+    }
+
+    //
+    // Detach it from list first.
+    //
+    RemoveEntryList (&Target->Link);
+    FreePool (Target);
+
+    PendingListLink = PendingListNextLink;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Release all resource in statement list.
+
+  @param[in]  StatementList   Statement list to be released.
+
+  @retval EFI_SUCCESS             All resource are released.
+  @retval EFI_INVALID_PARAMETER   StatementList is NULL.
+
+**/
+EFI_STATUS
+ReleaseStatementList (
+  IN  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST  *StatementList
+  )
+{
+  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF *StatementRef;
+  LIST_ENTRY  *NextLink;
+
+  if (StatementList == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (IsListEmpty (&StatementList->StatementList)) {
+    return EFI_SUCCESS;
+  }
+
+  NextLink = GetFirstNode (&StatementList->StatementList);
+  while (!IsNull (&StatementList->StatementList, NextLink)) {
+    StatementRef = REDFISH_PLATFORM_CONFIG_STATEMENT_REF_FROM_LINK (NextLink);
+    NextLink = GetNextNode (&StatementList->StatementList, NextLink);
+
+    RemoveEntryList (&StatementRef->Link);
+    FreePool (StatementRef);
+  }
+
+  return EFI_SUCCESS;
+}
-- 
2.21.0.windows.1


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

* [PATCH RESEND 4/5] edk2-staging/RedfishPkg: Helper library of EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL
  2021-10-28  1:07 [PATCH RESEND 0/5] Implementation of EDKII Redfish Platform Config Protocol Abner Chang
                   ` (2 preceding siblings ...)
  2021-10-28  1:07 ` [PATCH RESEND 3/5] edk2-staging/RedfishPkg: Implementation of EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL Abner Chang
@ 2021-10-28  1:07 ` Abner Chang
  2021-10-28  1:07 ` [PATCH RESEND 5/5] edk2-staging/RedfishPkg: Enable Redfish Platform Config Protocol build process Abner Chang
  4 siblings, 0 replies; 6+ messages in thread
From: Abner Chang @ 2021-10-28  1:07 UTC (permalink / raw)
  To: devel; +Cc: nickle.wang, Liming Gao

This is the helper library for using EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL.

Signed-off-by: Nickle Wang <nickle.wang@hpe.com>
Cc: Abner Chang <abner.chang@hpe.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
---
 RedfishPkg/RedfishPkg.dec                     |   5 +
 .../RedfishPlatformConfigLib.inf              |  41 +++
 .../Library/RedfishPlatformConfigLib.h        | 101 ++++++++
 .../RedfishPlatformConfigInternal.h           |  31 +++
 .../RedfishPlatformConfigLib.c                | 243 ++++++++++++++++++
 5 files changed, 421 insertions(+)
 create mode 100644 RedfishPkg/Library/RedfishPlatformConfigLib/RedfishPlatformConfigLib.inf
 create mode 100644 RedfishPkg/Include/Library/RedfishPlatformConfigLib.h
 create mode 100644 RedfishPkg/Library/RedfishPlatformConfigLib/RedfishPlatformConfigInternal.h
 create mode 100644 RedfishPkg/Library/RedfishPlatformConfigLib/RedfishPlatformConfigLib.c

diff --git a/RedfishPkg/RedfishPkg.dec b/RedfishPkg/RedfishPkg.dec
index eac219ccbb9..71f99066962 100644
--- a/RedfishPkg/RedfishPkg.dec
+++ b/RedfishPkg/RedfishPkg.dec
@@ -55,6 +55,11 @@
   #
   RedfishContentCodingLib|Include/Library/RedfishContentCodingLib.h
 
+  ##  @libraryclass  Provides the library functions to access Redfish Platform
+  #   Config protocol.
+  #
+  RedfishPlatformConfigLib|Include/Library/RedfishPlatformConfigLib.h
+
   ##  @libraryclass  Provides the library functions to parse IFR binary data.
   #
   HiiUtilityLib|Include/Library/HiiUtilityLib.h
diff --git a/RedfishPkg/Library/RedfishPlatformConfigLib/RedfishPlatformConfigLib.inf b/RedfishPkg/Library/RedfishPlatformConfigLib/RedfishPlatformConfigLib.inf
new file mode 100644
index 00000000000..5ad8d22087d
--- /dev/null
+++ b/RedfishPkg/Library/RedfishPlatformConfigLib/RedfishPlatformConfigLib.inf
@@ -0,0 +1,41 @@
+##  @file
+#   Library for Redfish Platform Config Protocol
+#
+#   (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+#   SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010006
+  BASE_NAME                      = RedfishPlatformConfigLib
+  FILE_GUID                      = C920FD62-21AC-4638-B9F5-9612942290F6
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = RedfishPlatformConfigLib| DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER
+  CONSTRUCTOR                    = RedfishPlatformConfigLibConstructor
+  DESTRUCTOR                     = RedfishPlatformConfigLibDestructor
+
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC RISCV64
+#
+
+[Sources]
+  RedfishPlatformConfigLib.c
+  RedfishPlatformConfigInternal.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  RedfishPkg/RedfishPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  MemoryAllocationLib
+  UefiBootServicesTableLib
+  UefiLib
+
+[Protocols]
+  gEdkIIRedfishPlatformConfigProtocolGuid
diff --git a/RedfishPkg/Include/Library/RedfishPlatformConfigLib.h b/RedfishPkg/Include/Library/RedfishPlatformConfigLib.h
new file mode 100644
index 00000000000..ebe2329fd9a
--- /dev/null
+++ b/RedfishPkg/Include/Library/RedfishPlatformConfigLib.h
@@ -0,0 +1,101 @@
+/** @file
+  Definitinos of RedfishPlatformConfigLib
+
+  (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef REDFISH_PLATFORM_CONFIG_LIB_H_
+#define REDFISH_PLATFORM_CONFIG_LIB_H_
+
+#include <Protocol/EdkIIRedfishPlatformConfig.h>
+
+/**
+  Get Redfish value with the given Schema and Configure Language.
+
+  @param[in]   Schema              The Redfish schema to query.
+  @param[in]   Version             The Redfish version to query.
+  @param[in]   ConfigureLang       The target value which match this configure Language.
+  @param[out]  Value               The returned value.
+
+  @retval EFI_SUCCESS              Value is returned successfully.
+  @retval EFI_NOT_READY            Redfish Platform Config protocol is not ready.
+  @retval Others                   Some error happened.
+
+**/
+EFI_STATUS
+RedfishPlatformConfigGetValue (
+  IN     CHAR8                *Schema,
+  IN     CHAR8                *Version,
+  IN     EFI_STRING           ConfigureLang,
+  OUT    EDKII_REDFISH_VALUE  *Value
+  );
+
+/**
+  Set Redfish value with the given Schema and Configure Language.
+
+  @param[in]   Schema              The Redfish schema to query.
+  @param[in]   Version             The Redfish version to query.
+  @param[in]   ConfigureLang       The target value which match this configure Language.
+  @param[in]   Value               The value to set.
+
+  @retval EFI_SUCCESS              Value is returned successfully.
+  @retval EFI_NOT_READY            Redfish Platform Config protocol is not ready.
+  @retval Others                   Some error happened.
+
+**/
+EFI_STATUS
+RedfishPlatformConfigSetValue (
+  IN     CHAR8                *Schema,
+  IN     CHAR8                *Version,
+  IN     EFI_STRING           ConfigureLang,
+  IN     EDKII_REDFISH_VALUE  Value
+  );
+
+/**
+  Get the list of Configure Language from platform configuration by the given Schema and Pattern.
+
+  @param[in]   Schema              The Redfish schema to query.
+  @param[in]   Version             The Redfish version to query.
+  @param[in]   Pattern             The target Configure Language pattern.
+  @param[out]  RedpathList         The list of Configure Language.
+  @param[out]  Count               The number of Configure Language in ConfigureLangList.
+
+  @retval EFI_SUCCESS              ConfigureLangList is returned successfully.
+  @retval EFI_NOT_READY            Redfish Platform Config protocol is not ready.
+  @retval Others                   Some error happened.
+
+**/
+EFI_STATUS
+RedfishPlatformConfigGetConfigureLang (
+  IN     CHAR8      *Schema,
+  IN     CHAR8      *Version,
+  IN     EFI_STRING Pattern,
+  OUT    EFI_STRING **ConfigureLangList,
+  OUT    UINTN      *Count
+  );
+
+/**
+  Get the list of supported Redfish schema from platform configuration on the give HII handle.
+
+  @param[in]   HiiHandle           The target handle to search. If handle is NULL,
+                                   this function return all schema from HII database.
+  @param[out]  SupportedSchema     The supported schema list which is separated by ';'.
+                                   For example: "x-uefi-redfish-Memory.v1_7_1;x-uefi-redfish-Boot.v1_0_1"
+                                   The SupportedSchema is allocated by the callee. It's caller's
+                                   responsibility to free this buffer using FreePool().
+
+  @retval EFI_SUCCESS              Schema is returned successfully.
+  @retval EFI_NOT_READY            Redfish Platform Config protocol is not ready.
+  @retval Others                   Some error happened.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishPlatformConfigGetSupportedSchema (
+  IN     EFI_HII_HANDLE HiiHandle,       OPTIONAL
+  OUT    CHAR8          **SupportedSchema
+  );
+
+#endif
diff --git a/RedfishPkg/Library/RedfishPlatformConfigLib/RedfishPlatformConfigInternal.h b/RedfishPkg/Library/RedfishPlatformConfigLib/RedfishPlatformConfigInternal.h
new file mode 100644
index 00000000000..8745faa0327
--- /dev/null
+++ b/RedfishPkg/Library/RedfishPlatformConfigLib/RedfishPlatformConfigInternal.h
@@ -0,0 +1,31 @@
+/** @file
+  Internal function header for Redfish Platform Config Library.
+
+  (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef REDFISH_PLATFORM_CONFIG_H_
+#define REDFISH_PLATFORM_CONFIG_H_
+
+#include <Uefi.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/RedfishPlatformConfigLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Protocol/EdkIIRedfishPlatformConfig.h>
+
+typedef struct {
+  EFI_EVENT                               ProtocolEvent;   // Protocol notification event.
+  VOID                                    *Registration;   // Protocol notification registration.
+  EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL  *Protocol;
+} REDFISH_PLATFORM_CONFIG_LIB_PRIVATE;
+
+#endif
diff --git a/RedfishPkg/Library/RedfishPlatformConfigLib/RedfishPlatformConfigLib.c b/RedfishPkg/Library/RedfishPlatformConfigLib/RedfishPlatformConfigLib.c
new file mode 100644
index 00000000000..eb2c64b0e60
--- /dev/null
+++ b/RedfishPkg/Library/RedfishPlatformConfigLib/RedfishPlatformConfigLib.c
@@ -0,0 +1,243 @@
+/** @file
+  Wrapper function to support Redfish Platform Config protocol.
+
+  (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "RedfishPlatformConfigInternal.h"
+
+REDFISH_PLATFORM_CONFIG_LIB_PRIVATE   mRedfishPlatformConfigLibPrivate;
+
+
+/**
+  Get Redfish value with the given Schema and Configure Language.
+
+  @param[in]   Schema              The Redfish schema to query.
+  @param[in]   Version             The Redfish version to query.
+  @param[in]   ConfigureLang       The target value which match this configure Language.
+  @param[out]  Value               The returned value.
+
+  @retval EFI_SUCCESS              Value is returned successfully.
+  @retval EFI_NOT_READY            Redfish Platform Config protocol is not ready.
+  @retval Others                   Some error happened.
+
+**/
+EFI_STATUS
+RedfishPlatformConfigGetValue (
+  IN     CHAR8                *Schema,
+  IN     CHAR8                *Version,
+  IN     EFI_STRING           ConfigureLang,
+  OUT    EDKII_REDFISH_VALUE  *Value
+  )
+{
+  if (mRedfishPlatformConfigLibPrivate.Protocol == NULL) {
+    return EFI_NOT_READY;
+  }
+
+  return mRedfishPlatformConfigLibPrivate.Protocol->GetValue (
+                                                      mRedfishPlatformConfigLibPrivate.Protocol,
+                                                      Schema,
+                                                      Version,
+                                                      ConfigureLang,
+                                                      Value
+                                                      );
+}
+
+/**
+  Set Redfish value with the given Schema and Configure Language.
+
+  @param[in]   Schema              The Redfish schema to query.
+  @param[in]   Version             The Redfish version to query.
+  @param[in]   ConfigureLang       The target value which match this configure Language.
+  @param[in]   Value               The value to set.
+
+  @retval EFI_SUCCESS              Value is returned successfully.
+  @retval EFI_NOT_READY            Redfish Platform Config protocol is not ready.
+  @retval Others                   Some error happened.
+
+**/
+EFI_STATUS
+RedfishPlatformConfigSetValue (
+  IN     CHAR8                *Schema,
+  IN     CHAR8                *Version,
+  IN     EFI_STRING           ConfigureLang,
+  IN     EDKII_REDFISH_VALUE  Value
+  )
+{
+  if (mRedfishPlatformConfigLibPrivate.Protocol == NULL) {
+    return EFI_NOT_READY;
+  }
+
+  return mRedfishPlatformConfigLibPrivate.Protocol->SetValue (
+                                                      mRedfishPlatformConfigLibPrivate.Protocol,
+                                                      Schema,
+                                                      Version,
+                                                      ConfigureLang,
+                                                      Value
+                                                      );
+}
+
+/**
+  Get the list of Configure Language from platform configuration by the given Schema and Pattern.
+
+  @param[in]   Schema              The Redfish schema to query.
+  @param[in]   Version             The Redfish version to query.
+  @param[in]   Pattern             The target Configure Language pattern.
+  @param[out]  RedpathList         The list of Configure Language.
+  @param[out]  Count               The number of Configure Language in ConfigureLangList.
+
+  @retval EFI_SUCCESS              ConfigureLangList is returned successfully.
+  @retval EFI_NOT_READY            Redfish Platform Config protocol is not ready.
+  @retval Others                   Some error happened.
+
+**/
+EFI_STATUS
+RedfishPlatformConfigGetConfigureLang (
+  IN     CHAR8      *Schema,
+  IN     CHAR8      *Version,
+  IN     EFI_STRING Pattern,
+  OUT    EFI_STRING **ConfigureLangList,
+  OUT    UINTN      *Count
+  )
+{
+  if (mRedfishPlatformConfigLibPrivate.Protocol == NULL) {
+    return EFI_NOT_READY;
+  }
+
+  return mRedfishPlatformConfigLibPrivate.Protocol->GetConfigureLang (
+                                                      mRedfishPlatformConfigLibPrivate.Protocol,
+                                                      Schema,
+                                                      Version,
+                                                      Pattern,
+                                                      ConfigureLangList,
+                                                      Count
+                                                      );
+}
+
+/**
+  Get the list of supported Redfish schema from paltform configuration on give HII handle.
+
+  @param[in]   HiiHandle           The target handle to search. If handle is NULL,
+                                   this function return all schema from HII database.
+  @param[out]  SupportedSchema     The supported schema list which is separated by ';'.
+                                   The SupportedSchema is allocated by the callee. It's caller's
+                                   responsibility to free this buffer using FreePool().
+
+  @retval EFI_SUCCESS              Schema is returned successfully.
+  @retval EFI_NOT_READY            Redfish Platform Config protocol is not ready.
+  @retval Others                   Some error happened.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishPlatformConfigGetSupportedSchema (
+  IN     EFI_HII_HANDLE HiiHandle     OPTIONAL,
+  OUT    CHAR8          **SupportedSchema
+  )
+{
+  if (mRedfishPlatformConfigLibPrivate.Protocol == NULL) {
+    return EFI_NOT_READY;
+  }
+
+  return mRedfishPlatformConfigLibPrivate.Protocol->GetSupportedSchema (
+                                                      mRedfishPlatformConfigLibPrivate.Protocol,
+                                                      HiiHandle,
+                                                      SupportedSchema
+                                                      );
+}
+
+/**
+  This is a EFI_REDFISH_PLATFORM_CONFIG_PROTOCOL notification event handler.
+
+  Install HII package notification.
+
+  @param[in] Event    Event whose notification function is being invoked.
+  @param[in] Context  Pointer to the notification function's context.
+
+**/
+VOID
+EFIAPI
+RedfishPlatformConfigProtocolInstalled (
+  IN  EFI_EVENT       Event,
+  IN  VOID            *Context
+  )
+{
+  EFI_STATUS  Status;
+
+  //
+  // Locate EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL.
+  //
+  Status = gBS->LocateProtocol (
+                  &gEdkIIRedfishPlatformConfigProtocolGuid,
+                  NULL,
+                  (VOID **)&mRedfishPlatformConfigLibPrivate.Protocol
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a, locate EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL failure: %r\n", __FUNCTION__, Status));
+    return;
+  }
+
+  gBS->CloseEvent (Event);
+  mRedfishPlatformConfigLibPrivate.ProtocolEvent = NULL;
+}
+
+/**
+
+  Create prottocol listener and wait for Redfish Platform Config protocol.
+
+  @param ImageHandle     The image handle.
+  @param SystemTable     The system table.
+
+  @retval  EFI_SUCEESS  Protocol listener is registered successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishPlatformConfigLibConstructor (
+  IN EFI_HANDLE                            ImageHandle,
+  IN EFI_SYSTEM_TABLE                      *SystemTable
+  )
+{
+  ZeroMem (&mRedfishPlatformConfigLibPrivate, sizeof (REDFISH_PLATFORM_CONFIG_LIB_PRIVATE));
+  mRedfishPlatformConfigLibPrivate.ProtocolEvent = EfiCreateProtocolNotifyEvent (
+                                                    &gEdkIIRedfishPlatformConfigProtocolGuid,
+                                                    TPL_CALLBACK,
+                                                    RedfishPlatformConfigProtocolInstalled,
+                                                    NULL,
+                                                    &mRedfishPlatformConfigLibPrivate.Registration
+                                                    );
+  if (mRedfishPlatformConfigLibPrivate.ProtocolEvent == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a, failed to create protocol notify event\n", __FUNCTION__));
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Unloads the application and its installed protocol.
+
+  @param ImageHandle       Handle that identifies the image to be unloaded.
+  @param  SystemTable      The system table.
+
+  @retval EFI_SUCCESS      The image has been unloaded.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishPlatformConfigLibDestructor (
+  IN EFI_HANDLE                            ImageHandle,
+  IN EFI_SYSTEM_TABLE                      *SystemTable
+  )
+{
+  if (mRedfishPlatformConfigLibPrivate.ProtocolEvent != NULL) {
+    gBS->CloseEvent (mRedfishPlatformConfigLibPrivate.ProtocolEvent);
+    mRedfishPlatformConfigLibPrivate.ProtocolEvent = NULL;
+  }
+
+  mRedfishPlatformConfigLibPrivate.Protocol = NULL;
+
+  return EFI_SUCCESS;
+}
\ No newline at end of file
-- 
2.21.0.windows.1


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

* [PATCH RESEND 5/5] edk2-staging/RedfishPkg: Enable Redfish Platform Config Protocol build process
  2021-10-28  1:07 [PATCH RESEND 0/5] Implementation of EDKII Redfish Platform Config Protocol Abner Chang
                   ` (3 preceding siblings ...)
  2021-10-28  1:07 ` [PATCH RESEND 4/5] edk2-staging/RedfishPkg: Helper library " Abner Chang
@ 2021-10-28  1:07 ` Abner Chang
  4 siblings, 0 replies; 6+ messages in thread
From: Abner Chang @ 2021-10-28  1:07 UTC (permalink / raw)
  To: devel; +Cc: nickle.wang, Liming Gao

Enable RedfishPlatformConfigDxe driver and the corresponding
library to build.

Signed-off-by: Nickle Wang <nickle.wang@hpe.com>
Cc: Abner Chang <abner.chang@hpe.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
---
 RedfishPkg/RedfishComponents.dsc.inc | 2 ++
 RedfishPkg/RedfishLibs.dsc.inc       | 2 ++
 RedfishPkg/RedfishPkg.dsc            | 4 ++++
 RedfishPkg/Redfish.fdf.inc           | 2 ++
 4 files changed, 10 insertions(+)

diff --git a/RedfishPkg/RedfishComponents.dsc.inc b/RedfishPkg/RedfishComponents.dsc.inc
index ccc62edf6a0..d0a390f5f0f 100644
--- a/RedfishPkg/RedfishComponents.dsc.inc
+++ b/RedfishPkg/RedfishComponents.dsc.inc
@@ -19,4 +19,6 @@
   RedfishPkg/RedfishCredentialDxe/RedfishCredentialDxe.inf
   RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.inf
   RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.inf
+  RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.inf
+  MdeModulePkg/Universal/RegularExpressionDxe/RegularExpressionDxe.inf
 !endif
diff --git a/RedfishPkg/RedfishLibs.dsc.inc b/RedfishPkg/RedfishLibs.dsc.inc
index 50e5dda7735..ed279966c5c 100644
--- a/RedfishPkg/RedfishLibs.dsc.inc
+++ b/RedfishPkg/RedfishLibs.dsc.inc
@@ -17,5 +17,7 @@
   RedfishCrtLib|RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.inf
   JsonLib|RedfishPkg/Library/JsonLib/JsonLib.inf
   RedfishLib|RedfishPkg/PrivateLibrary/RedfishLib/RedfishLib.inf
+  HiiUtilityLib|RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.inf
+  RedfishPlatformConfigLib|RedfishPkg/Library/RedfishPlatformConfigLib/RedfishPlatformConfigLib.inf
 !endif
 
diff --git a/RedfishPkg/RedfishPkg.dsc b/RedfishPkg/RedfishPkg.dsc
index 16139146ff8..fa704b826fe 100644
--- a/RedfishPkg/RedfishPkg.dsc
+++ b/RedfishPkg/RedfishPkg.dsc
@@ -38,6 +38,8 @@
   HttpIoLib|NetworkPkg/Library/DxeHttpIoLib/DxeHttpIoLib.inf
   NetLib|NetworkPkg/Library/DxeNetLib/DxeNetLib.inf
   DpcLib|NetworkPkg/Library/DxeDpcLib/DxeDpcLib.inf
+  HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
+  UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
   RedfishPlatformCredentialLib|RedfishPkg/Library/PlatformCredentialLibNull/PlatformCredentialLibNull.inf
   RedfishContentCodingLib|RedfishPkg/Library/RedfishContentCodingLibNull/RedfishContentCodingLibNull.inf
 
@@ -58,5 +60,7 @@
   RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.inf
   RedfishPkg/Library/JsonLib/JsonLib.inf
   RedfishPkg/PrivateLibrary/RedfishLib/RedfishLib.inf
+  RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.inf
+  RedfishPkg/Library/RedfishPlatformConfigLib/RedfishPlatformConfigLib.inf
 
   !include RedfishPkg/Redfish.dsc.inc
diff --git a/RedfishPkg/Redfish.fdf.inc b/RedfishPkg/Redfish.fdf.inc
index 60f31cfcee0..c0a12352d97 100644
--- a/RedfishPkg/Redfish.fdf.inc
+++ b/RedfishPkg/Redfish.fdf.inc
@@ -17,4 +17,6 @@
   INF RedfishPkg/RedfishCredentialDxe/RedfishCredentialDxe.inf
   INF RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.inf
   INF RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.inf
+  INF RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.inf
+  INF MdeModulePkg/Universal/RegularExpressionDxe/RegularExpressionDxe.inf
 !endif
-- 
2.21.0.windows.1


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

end of thread, other threads:[~2021-10-28  1:08 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-10-28  1:07 [PATCH RESEND 0/5] Implementation of EDKII Redfish Platform Config Protocol Abner Chang
2021-10-28  1:07 ` [PATCH RESEND 1/5] edk2-staging/RedfishPkg: EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL Abner Chang
2021-10-28  1:07 ` [PATCH RESEND 2/5] edk2-staging/RedfishPkg: HII utility helper library Abner Chang
2021-10-28  1:07 ` [PATCH RESEND 3/5] edk2-staging/RedfishPkg: Implementation of EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL Abner Chang
2021-10-28  1:07 ` [PATCH RESEND 4/5] edk2-staging/RedfishPkg: Helper library " Abner Chang
2021-10-28  1:07 ` [PATCH RESEND 5/5] edk2-staging/RedfishPkg: Enable Redfish Platform Config Protocol build process Abner Chang

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