* [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