* [PATCH v3 2/5] RedfishPkg: introduce HII utility helper library
@ 2023-04-19 9:09 Nickle Wang
2023-04-19 9:48 ` Chang, Abner
0 siblings, 1 reply; 2+ messages in thread
From: Nickle Wang @ 2023-04-19 9:09 UTC (permalink / raw)
To: devel; +Cc: Abner Chang, Igor Kulchytskyy, Nick Ramirez
HiiUtilityLib is a helper library that provides the
functions to manipulate HII options.
Signed-off-by: Nickle Wang <nicklew@nvidia.com>
Cc: Abner Chang <abner.chang@amd.com>
Cc: Igor Kulchytskyy <igork@ami.com>
Cc: Nick Ramirez <nramirez@nvidia.com>
---
RedfishPkg/RedfishPkg.dec | 4 +
.../Library/HiiUtilityLib/HiiUtilityLib.inf | 62 +
RedfishPkg/Include/Library/HiiUtilityLib.h | 1204 ++++
.../Library/HiiUtilityLib/HiiExpression.h | 191 +
.../Library/HiiUtilityLib/HiiInternal.h | 376 ++
.../Library/HiiUtilityLib/HiiExpression.c | 1439 ++++
.../Library/HiiUtilityLib/HiiIfrParse.c | 2715 ++++++++
.../HiiUtilityLib/HiiUtilityInternal.c | 5770 +++++++++++++++++
.../Library/HiiUtilityLib/HiiUtilityLib.c | 810 +++
9 files changed, 12571 insertions(+)
create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.inf
create mode 100644 RedfishPkg/Include/Library/HiiUtilityLib.h
create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiExpression.h
create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiInternal.h
create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiExpression.c
create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiIfrParse.c
create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiUtilityInternal.c
create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.c
diff --git a/RedfishPkg/RedfishPkg.dec b/RedfishPkg/RedfishPkg.dec
index 904630ae4be6..e2892ce9cec1 100644
--- a/RedfishPkg/RedfishPkg.dec
+++ b/RedfishPkg/RedfishPkg.dec
@@ -60,6 +60,10 @@
# Library provides Redfish debug functions.
RedfishDebugLib|Include/Library/RedfishDebugLib.h
+ ## @libraryclass Provides the library functions to parse IFR binary data.
+ #
+ HiiUtilityLib|Include/Library/HiiUtilityLib.h
+
[LibraryClasses.Common.Private]
## @libraryclass Provides the private C runtime library functions.
# CRT library is currently used by edk2 JsonLib (open source
diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.inf b/RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.inf
new file mode 100644
index 000000000000..cab3f8a0ee68
--- /dev/null
+++ b/RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.inf
@@ -0,0 +1,62 @@
+## @file
+# Library to handle HII IFR data.
+#
+# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+# Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = HiiUtilityLib
+ FILE_GUID = D00DA028-F19A-47AF-B22A-6EE9E8BD7335
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = HiiUtilityLib|DXE_DRIVER UEFI_DRIVER UEFI_APPLICATION
+
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+[Sources]
+ HiiUtilityLib.c
+ HiiExpression.c
+ HiiUtilityInternal.c
+ HiiIfrParse.c
+ HiiInternal.h
+ HiiExpression.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ RedfishPkg/RedfishPkg.dec
+
+[LibraryClasses]
+ PrintLib
+ DebugLib
+ BaseMemoryLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ MemoryAllocationLib
+ HiiLib
+
+[Guids]
+ gZeroGuid
+ gEdkiiIfrBitVarstoreGuid
+ gEfiHiiPlatformSetupFormsetGuid
+ gEfiHiiStandardFormGuid
+
+[Protocols]
+ gEfiHiiDatabaseProtocolGuid
+ gEfiHiiConfigRoutingProtocolGuid
+ gEfiHiiConfigAccessProtocolGuid
+ gEfiDevicePathFromTextProtocolGuid
+ gEfiUnicodeCollation2ProtocolGuid
+ gEfiRegularExpressionProtocolGuid
+ gEfiUserManagerProtocolGuid
+
+[Depex]
+ TRUE
diff --git a/RedfishPkg/Include/Library/HiiUtilityLib.h b/RedfishPkg/Include/Library/HiiUtilityLib.h
new file mode 100644
index 000000000000..0999ef77fe8c
--- /dev/null
+++ b/RedfishPkg/Include/Library/HiiUtilityLib.h
@@ -0,0 +1,1204 @@
+/** @file
+ Definitions of RedfishPlatformConfigLib.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+ Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef HII_UTILITY_LIB_
+#define HII_UTILITY_LIB_
+
+#include <Protocol/DisplayProtocol.h>
+#include <Protocol/HiiConfigAccess.h>
+
+//
+// IFR relative definition
+//
+#define EFI_HII_EXPRESSION_INCONSISTENT_IF 0
+#define EFI_HII_EXPRESSION_NO_SUBMIT_IF 1
+#define EFI_HII_EXPRESSION_GRAY_OUT_IF 2
+#define EFI_HII_EXPRESSION_SUPPRESS_IF 3
+#define EFI_HII_EXPRESSION_DISABLE_IF 4
+#define EFI_HII_EXPRESSION_VALUE 5
+#define EFI_HII_EXPRESSION_RULE 6
+#define EFI_HII_EXPRESSION_READ 7
+#define EFI_HII_EXPRESSION_WRITE 8
+#define EFI_HII_EXPRESSION_WARNING_IF 9
+
+#define EFI_HII_VARSTORE_BUFFER 0
+#define EFI_HII_VARSTORE_NAME_VALUE 1
+#define EFI_HII_VARSTORE_EFI_VARIABLE 2 // EFI Varstore type follow UEFI spec before 2.3.1.
+#define EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER 3 // EFI varstore type follow UEFI spec 2.3.1 and later.
+
+///
+/// HII_NAME_VALUE_NODE for name/value storage
+///
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+ CHAR16 *Name;
+ CHAR16 *Value;
+} HII_NAME_VALUE_NODE;
+
+#define HII_NAME_VALUE_NODE_SIGNATURE SIGNATURE_32 ('N', 'V', 'S', 'T')
+#define HII_NAME_VALUE_NODE_FROM_LINK(a) CR (a, HII_NAME_VALUE_NODE, Link, HII_NAME_VALUE_NODE_SIGNATURE)
+
+///
+/// Storage info
+///
+typedef union {
+ EFI_STRING_ID VarName;
+ UINT16 VarOffset;
+} HII_VAR_STORE_INFO;
+
+///
+/// FormSet storage
+///
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+
+ UINT8 Type; ///< Storage type
+ EFI_HII_HANDLE HiiHandle; ///< HiiHandle for this varstore.
+
+ ///
+ /// For all type of storages.
+ ///
+ UINT16 VarStoreId; ///< VarStore ID.
+ EFI_GUID Guid; ///< VarStore Guid.
+
+ ///
+ /// For EFI_IFR_VARSTORE, EFI_IFR_VARSTORE_EFI
+ ///
+ CHAR16 *Name; ///< VarStore name
+ UINT16 Size; ///< VarStore size.
+ UINT8 *Buffer; ///< Buffer storage.
+ UINT8 *EditBuffer; ///< Edit copy for Buffer Storage
+
+ ///
+ /// For EFI_IFR_VARSTORE_EFI: EFI Variable.
+ ///
+ UINT32 Attributes;
+
+ ///
+ /// For EFI_IFR_VARSTORE_NAME_VALUE.
+ ///
+ LIST_ENTRY NameValueList; ///< List of NAME_VALUE_NODE
+
+ CHAR16 *ConfigHdr; ///< <ConfigHdr>
+ CHAR16 *ConfigRequest; ///< <ConfigRequest> = <ConfigHdr> + <RequestElement>
+ UINTN ElementCount; ///< Number of <RequestElement> in the <ConfigRequest>
+ UINTN SpareStrLen; ///< Spare length of ConfigRequest string buffer
+} HII_FORMSET_STORAGE;
+
+#define HII_STORAGE_SIGNATURE SIGNATURE_32 ('B', 'S', 'T', 'G')
+#define HII_STORAGE_FROM_LINK(a) CR (a, HII_FORMSET_STORAGE, Link, HII_STORAGE_SIGNATURE)
+
+///
+/// Definition of EXPRESS_RESULT
+///
+typedef enum {
+ ExpressFalse = 0,
+ ExpressGrayOut,
+ ExpressSuppress,
+ ExpressDisable
+} EXPRESS_RESULT;
+
+///
+/// Definition of EXPRESS_LEVEL
+///
+typedef enum {
+ ExpressNone = 0,
+ ExpressForm,
+ ExpressStatement,
+ ExpressOption
+} EXPRESS_LEVEL;
+
+///
+/// Definition of HII_EXPRESSION_OPCODE_EXTRA
+///
+typedef union {
+ EFI_HII_VALUE Value; ///< EFI_IFR_UINT64, EFI_IFR_UINT32, EFI_IFR_UINT16, EFI_IFR_UINT8, EFI_IFR_STRING_REF1
+ UINT8 Format; ///< For EFI_IFR_TO_STRING, EFI_IFR_FIND
+ UINT8 Flags; ///< For EFI_IFR_SPAN
+ UINT8 RuleId; ///< For EFI_IFR_RULE_REF
+ EFI_GUID Guid; ///< For EFI_IFR_SECURITY, EFI_IFR_MATCH2
+
+ struct {
+ EFI_QUESTION_ID QuestionId;
+ EFI_HII_VALUE Value;
+ } EqIdValData;
+
+ struct {
+ EFI_QUESTION_ID QuestionId1;
+ EFI_QUESTION_ID QuestionId2;
+ } EqIdIdData;
+
+ struct {
+ EFI_QUESTION_ID QuestionId; ///< For EFI_IFR_EQ_ID_VAL_LIST
+ UINT16 ListLength;
+ UINT16 *ValueList;
+ } EqIdListData;
+
+ struct {
+ EFI_QUESTION_ID QuestionId;
+ } QuestionRef1Data;
+
+ struct {
+ EFI_STRING_ID DevicePath; ///< For EFI_IFR_QUESTION_REF3_3
+ EFI_GUID Guid;
+ } QuestionRef3Data;
+
+ struct {
+ HII_FORMSET_STORAGE *VarStorage;
+ HII_VAR_STORE_INFO VarStoreInfo;
+ UINT8 ValueType;
+ UINT8 ValueWidth;
+ CHAR16 *ValueName;
+ } GetSetData;
+} HII_EXPRESSION_OPCODE_EXTRA;
+
+typedef union _HII_DEPENDENCY_EXPRESSION HII_DEPENDENCY_EXPRESSION;
+
+///
+/// Definition of HII_EXPRESSION_CONSTANT
+///
+/// Operand:
+///
+/// EFI_IFR_TRUE
+/// EFI_IFR_FALSE
+/// EFI_IFR_ONE
+/// EFI_IFR_ONES
+/// EFI_IFR_ZERO
+/// EFI_IFR_UNDEFINED
+/// EFI_IFR_VERSION
+/// EFI_IFR_UINT8
+/// EFI_IFR_UINT16
+/// EFI_IFR_UINT32
+/// EFI_IFR_UINT64
+///
+typedef struct {
+ UINT8 Operand;
+ EFI_HII_VALUE Value;
+} HII_EXPRESSION_CONSTANT;
+
+///
+/// Definition of HII_DEPENDENCY_DUP
+///
+typedef struct {
+ UINT8 Operand;
+} HII_DEPENDENCY_DUP;
+
+///
+/// Definition of HII_DEPENDENCY_EQ_ID_VAL
+///
+typedef struct {
+ UINT8 Operand;
+ EFI_QUESTION_ID QuestionId;
+ EFI_HII_VALUE Value;
+} HII_DEPENDENCY_EQ_ID_VAL;
+
+///
+/// Definition of HII_DEPENDENCY_EQ_ID_VAL
+///
+typedef struct {
+ UINT8 Operand;
+ EFI_QUESTION_ID QuestionId1;
+ EFI_QUESTION_ID QuestionId2;
+} HII_DEPENDENCY_EQ_ID_ID;
+
+///
+/// Definition of HII_DEPENDENCY_EQ_ID_VAL_LIST
+///
+typedef struct {
+ UINT8 Operand;
+ EFI_QUESTION_ID QuestionId;
+ UINT16 ListLength;
+ UINT16 *ValueList;
+} HII_DEPENDENCY_EQ_ID_VAL_LIST;
+
+///
+/// Definition of HII_DEPENDENCY_QUESTION_REF1
+///
+typedef struct {
+ UINT8 Operand;
+ EFI_QUESTION_ID QuestionId;
+} HII_DEPENDENCY_QUESTION_REF1;
+
+///
+/// Definition of HII_DEPENDENCY_RULE_REF
+///
+typedef struct {
+ UINT8 Operand;
+ UINT8 RuleId;
+} HII_DEPENDENCY_RULE_REF;
+
+///
+/// Definition of HII_DEPENDENCY_STRING_REF1
+///
+typedef struct {
+ UINT8 Operand;
+ EFI_HII_VALUE Value;
+} HII_DEPENDENCY_STRING_REF1;
+
+///
+/// Definition of HII_DEPENDENCY_THIS
+///
+typedef struct {
+ UINT8 Operand;
+ EFI_QUESTION_ID QuestionId;
+} HII_DEPENDENCY_THIS;
+
+///
+/// Definition of HII_DEPENDENCY_SECURITY
+///
+typedef struct {
+ UINT8 Operand;
+ EFI_GUID Permissions;
+} HII_DEPENDENCY_SECURITY;
+
+///
+/// Definition of HII_DEPENDENCY_GET
+///
+typedef struct {
+ UINT8 Operand;
+ HII_FORMSET_STORAGE *VarStorage;
+ HII_VAR_STORE_INFO VarStoreInfo;
+ UINT8 ValueType;
+ UINT8 ValueWidth;
+ CHAR16 *ValueName;
+} HII_DEPENDENCY_GET;
+
+///
+/// Definition of HII_DEPENDENCY_LENGTH
+///
+typedef struct {
+ UINT8 Operand;
+ HII_DEPENDENCY_EXPRESSION *SubExpression;
+} HII_DEPENDENCY_LENGTH;
+
+///
+/// Definition of HII_DEPENDENCY_BITWISE_NOT
+///
+typedef struct {
+ UINT8 Operand;
+ HII_DEPENDENCY_EXPRESSION *SubExpression;
+} HII_DEPENDENCY_BITWISE_NOT;
+
+///
+/// Definition of HII_DEPENDENCY_STRING_REF2
+///
+typedef struct {
+ UINT8 Operand;
+ HII_DEPENDENCY_EXPRESSION *SubExpression;
+} HII_DEPENDENCY_STRING_REF2;
+
+///
+/// Definition of HII_DEPENDENCY_QUESTION_REF2
+///
+typedef struct {
+ UINT8 Operand;
+ HII_DEPENDENCY_EXPRESSION *SubExpression;
+} HII_DEPENDENCY_QUESTION_REF2;
+
+///
+/// Definition of HII_DEPENDENCY_QUESTION_REF3
+///
+typedef struct {
+ UINT8 Operand;
+ EFI_STRING_ID DevicePath;
+ EFI_GUID Guid;
+ HII_DEPENDENCY_EXPRESSION *SubExpression;
+} HII_DEPENDENCY_QUESTION_REF3;
+
+///
+/// Definition of HII_DEPENDENCY_TO_BOOLEAN
+///
+typedef struct {
+ UINT8 Operand;
+ HII_DEPENDENCY_EXPRESSION *SubExpression;
+} HII_DEPENDENCY_TO_BOOLEAN;
+
+///
+/// Definition of HII_DEPENDENCY_TO_STRING
+///
+typedef struct {
+ UINT8 Operand;
+ UINT8 Format;
+ HII_DEPENDENCY_EXPRESSION *SubExpression;
+} HII_DEPENDENCY_TO_STRING;
+
+///
+/// Definition of HII_DEPENDENCY_TO_UINT
+///
+typedef struct {
+ UINT8 Operand;
+ HII_DEPENDENCY_EXPRESSION *SubExpression;
+} HII_DEPENDENCY_TO_UINT;
+
+///
+/// Definition of HII_DEPENDENCY_TO_UPPER
+///
+typedef struct {
+ UINT8 Operand;
+ HII_DEPENDENCY_EXPRESSION *SubExpression;
+} HII_DEPENDENCY_TO_UPPER;
+
+///
+/// Definition of HII_DEPENDENCY_TO_LOWER
+///
+typedef struct {
+ UINT8 Operand;
+ HII_DEPENDENCY_EXPRESSION *SubExpression;
+} HII_DEPENDENCY_TO_LOWER;
+
+///
+/// Definition of HII_DEPENDENCY_SET
+///
+typedef struct {
+ UINT8 Operand;
+ HII_FORMSET_STORAGE *VarStorage;
+ HII_VAR_STORE_INFO VarStoreInfo;
+ UINT8 ValueType;
+ UINT8 ValueWidth;
+ CHAR16 *ValueName;
+ HII_DEPENDENCY_EXPRESSION *SubExpression;
+} HII_DEPENDENCY_SET;
+
+///
+/// Definition of HII_DEPENDENCY_NOT
+///
+typedef struct {
+ UINT8 Operand;
+ HII_DEPENDENCY_EXPRESSION *SubExpression;
+} HII_DEPENDENCY_NOT;
+
+///
+/// Definition of HII_DEPENDENCY_CATENATE
+///
+typedef struct {
+ UINT8 Operand;
+ HII_DEPENDENCY_EXPRESSION *LeftStringExp;
+ HII_DEPENDENCY_EXPRESSION *RightStringExp;
+} HII_DEPENDENCY_CATENATE;
+
+///
+/// Definition of HII_DEPENDENCY_MATCH
+///
+typedef struct {
+ UINT8 Operand;
+ HII_DEPENDENCY_EXPRESSION *StringExp;
+ HII_DEPENDENCY_EXPRESSION *PatternExp;
+} HII_DEPENDENCY_MATCH;
+
+///
+/// Definition of HII_DEPENDENCY_MATCH2
+///
+typedef struct {
+ UINT8 Operand;
+ EFI_GUID SyntaxType;
+ HII_DEPENDENCY_EXPRESSION *StringExp;
+ HII_DEPENDENCY_EXPRESSION *PatternExp;
+} HII_DEPENDENCY_MATCH2;
+
+///
+/// Definition of HII_DEPENDENCY_MULT
+///
+typedef struct {
+ UINT8 Operand;
+ HII_DEPENDENCY_EXPRESSION *RightHandExp;
+ HII_DEPENDENCY_EXPRESSION *LeftHandExp;
+} HII_DEPENDENCY_MULT;
+
+///
+/// Definition of HII_DEPENDENCY_DIV
+///
+typedef struct {
+ UINT8 Operand;
+ HII_DEPENDENCY_EXPRESSION *RightHandExp; ///< right value
+ HII_DEPENDENCY_EXPRESSION *LeftHandExp; ///< left value
+} HII_DEPENDENCY_DIV;
+
+///
+/// Definition of HII_DEPENDENCY_MOD
+///
+typedef struct {
+ UINT8 Operand;
+ HII_DEPENDENCY_EXPRESSION *RightHandExp; ///< right value
+ HII_DEPENDENCY_EXPRESSION *LeftHandExp; ///< left value
+} HII_DEPENDENCY_MOD;
+
+///
+/// Definition of HII_DEPENDENCY_ADD
+///
+typedef struct {
+ UINT8 Operand;
+ HII_DEPENDENCY_EXPRESSION *RightHandExp; ///< right value
+ HII_DEPENDENCY_EXPRESSION *LeftHandExp; ///< left value
+} HII_DEPENDENCY_ADD;
+
+///
+/// Definition of HII_DEPENDENCY_SUBTRACT
+///
+typedef struct {
+ UINT8 Operand;
+ HII_DEPENDENCY_EXPRESSION *RightHandExp; ///< right value
+ HII_DEPENDENCY_EXPRESSION *LeftHandExp; ///< left value
+} HII_DEPENDENCY_SUBTRACT;
+
+///
+/// Definition of HII_DEPENDENCY_SHIFT_LEFT
+///
+typedef struct {
+ UINT8 Operand;
+ HII_DEPENDENCY_EXPRESSION *RightHandExp;
+ HII_DEPENDENCY_EXPRESSION *LeftHandExp;
+} HII_DEPENDENCY_SHIFT_LEFT;
+
+///
+/// Definition of HII_DEPENDENCY_SHIFT_RIGHT
+///
+typedef struct {
+ UINT8 Operand;
+ HII_DEPENDENCY_EXPRESSION *RightHandExp;
+ HII_DEPENDENCY_EXPRESSION *LeftHandExp;
+} HII_DEPENDENCY_SHIFT_RIGHT;
+
+///
+/// Definition of HII_DEPENDENCY_GREATER_THAN
+///
+typedef struct {
+ UINT8 Operand;
+ HII_DEPENDENCY_EXPRESSION *RightHandExp;
+ HII_DEPENDENCY_EXPRESSION *LeftHandExp;
+} HII_DEPENDENCY_GREATER_THAN;
+
+///
+/// Definition of HII_DEPENDENCY_GREATER_EQUAL
+///
+typedef struct {
+ UINT8 Operand;
+ HII_DEPENDENCY_EXPRESSION *RightHandExp;
+ HII_DEPENDENCY_EXPRESSION *LeftHandExp;
+} HII_DEPENDENCY_GREATER_EQUAL;
+
+///
+/// Definition of HII_DEPENDENCY_LESS_THAN
+///
+typedef struct {
+ UINT8 Operand;
+ HII_DEPENDENCY_EXPRESSION *RightHandExp;
+ HII_DEPENDENCY_EXPRESSION *LeftHandExp;
+} HII_DEPENDENCY_LESS_THAN;
+
+///
+/// Definition of HII_DEPENDENCY_LESS_EQUAL
+///
+typedef struct {
+ UINT8 Operand;
+ HII_DEPENDENCY_EXPRESSION *RightHandExp;
+ HII_DEPENDENCY_EXPRESSION *LeftHandExp;
+} HII_DEPENDENCY_LESS_EQUAL;
+
+///
+/// Definition of HII_DEPENDENCY_EQUAL
+///
+typedef struct {
+ UINT8 Operand;
+ HII_DEPENDENCY_EXPRESSION *SubExpression1;
+ HII_DEPENDENCY_EXPRESSION *SubExpression2;
+} HII_DEPENDENCY_EQUAL;
+
+///
+/// Definition of HII_DEPENDENCY_NOT_EQUAL
+///
+typedef struct {
+ UINT8 Operand;
+ HII_DEPENDENCY_EXPRESSION *SubExpression1;
+ HII_DEPENDENCY_EXPRESSION *SubExpression2;
+} HII_DEPENDENCY_NOT_EQUAL;
+
+///
+/// Definition of HII_DEPENDENCY_BITWISE_AND
+///
+typedef struct {
+ UINT8 Operand;
+ HII_DEPENDENCY_EXPRESSION *SubExpression1;
+ HII_DEPENDENCY_EXPRESSION *SubExpression2;
+} HII_DEPENDENCY_BITWISE_AND;
+
+///
+/// Definition of HII_DEPENDENCY_BITWISE_OR
+///
+typedef struct {
+ UINT8 Operand;
+ HII_DEPENDENCY_EXPRESSION *SubExpression1;
+ HII_DEPENDENCY_EXPRESSION *SubExpression2;
+} HII_DEPENDENCY_BITWISE_OR;
+
+///
+/// Definition of HII_DEPENDENCY_AND
+///
+typedef struct {
+ UINT8 Operand;
+ HII_DEPENDENCY_EXPRESSION *SubExpression1;
+ HII_DEPENDENCY_EXPRESSION *SubExpression2;
+} HII_DEPENDENCY_AND;
+
+///
+/// Definition of HII_DEPENDENCY_OR
+///
+typedef struct {
+ UINT8 Operand;
+ HII_DEPENDENCY_EXPRESSION *SubExpression1;
+ HII_DEPENDENCY_EXPRESSION *SubExpression2;
+} HII_DEPENDENCY_OR;
+
+///
+/// Definition of HII_DEPENDENCY_CONDITIONAL
+///
+/// Ternary expression
+///
+typedef struct {
+ UINT8 Operand;
+ HII_DEPENDENCY_EXPRESSION *CondTrueValExp; ///< right value
+ HII_DEPENDENCY_EXPRESSION *CondFalseValExp; ///< middle value
+ HII_DEPENDENCY_EXPRESSION *ConditionExp; ///< left value
+} HII_DEPENDENCY_CONDITIONAL;
+
+///
+/// Definition of HII_DEPENDENCY_FIND
+///
+typedef struct {
+ UINT8 Operand;
+ UINT8 Format;
+ HII_DEPENDENCY_EXPRESSION *IndexExp; ///< right value
+ HII_DEPENDENCY_EXPRESSION *StringToCompWithExp; ///< middle value
+ HII_DEPENDENCY_EXPRESSION *StringToSearchExp; ///< left value
+} HII_DEPENDENCY_FIND;
+
+///
+/// Definition of HII_DEPENDENCY_MID
+///
+typedef struct {
+ UINT8 Operand;
+ HII_DEPENDENCY_EXPRESSION *LengthExp; ///< right value
+ HII_DEPENDENCY_EXPRESSION *IndexExp; ///< middle value
+ HII_DEPENDENCY_EXPRESSION *StringOrBufferExp; ///< left value
+} HII_DEPENDENCY_MID;
+
+///
+/// Definition of HII_DEPENDENCY_TOKEN
+///
+typedef struct {
+ UINT8 Operand;
+ HII_DEPENDENCY_EXPRESSION *IndexExp; ///< right value
+ HII_DEPENDENCY_EXPRESSION *DelimiterExp; ///< middle value
+ HII_DEPENDENCY_EXPRESSION *StringToSearchExp; ///< left value
+} HII_DEPENDENCY_TOKEN;
+
+///
+/// Definition of HII_DEPENDENCY_SPAN
+///
+typedef struct {
+ UINT8 Operand;
+ UINT8 Flags;
+ HII_DEPENDENCY_EXPRESSION *IndexExp; ///< right value
+ HII_DEPENDENCY_EXPRESSION *CharsetExp; ///< middle value
+ HII_DEPENDENCY_EXPRESSION *StringToSearchExp; ///< left value
+} HII_DEPENDENCY_SPAN;
+
+///
+/// Map expression
+///
+typedef struct {
+ HII_DEPENDENCY_EXPRESSION *MatchExp;
+ HII_DEPENDENCY_EXPRESSION *ReturnExp;
+} HII_DEPENDENCY_EXPRESSION_PAIR;
+
+///
+/// Definition of HII_DEPENDENCY_MAP
+///
+typedef struct {
+ UINT8 Operand;
+ HII_DEPENDENCY_EXPRESSION *SubExp;
+ HII_DEPENDENCY_EXPRESSION_PAIR *ExpPair;
+ UINT8 ExpPairNo;
+} HII_DEPENDENCY_MAP;
+
+///
+/// Definition of HII_DEPENDENCY_EXPRESSION
+///
+union _HII_DEPENDENCY_EXPRESSION {
+ ///
+ /// Constant
+ ///
+ HII_EXPRESSION_CONSTANT ConstantExp;
+ ///
+ /// build-in expression
+ ///
+ HII_DEPENDENCY_DUP DupExp;
+ HII_DEPENDENCY_EQ_ID_VAL EqIdValExp;
+ HII_DEPENDENCY_EQ_ID_ID EqIdIdExp;
+ HII_DEPENDENCY_EQ_ID_VAL_LIST EqIdListExp;
+ HII_DEPENDENCY_QUESTION_REF1 QuestionRef1Exp;
+ HII_DEPENDENCY_RULE_REF RuleRefExp;
+ HII_DEPENDENCY_STRING_REF1 StringRef1Exp;
+ HII_DEPENDENCY_THIS ThisExp;
+ HII_DEPENDENCY_SECURITY SecurityExp;
+ HII_DEPENDENCY_GET GetExp;
+
+ ///
+ /// unary expression
+ ///
+ HII_DEPENDENCY_LENGTH LengthExp;
+ HII_DEPENDENCY_BITWISE_NOT BitWiseNotExp;
+ HII_DEPENDENCY_STRING_REF2 StringRef2Exp;
+ HII_DEPENDENCY_QUESTION_REF2 QuestionRef2Exp;
+ HII_DEPENDENCY_QUESTION_REF3 QuestionRef3Exp;
+ HII_DEPENDENCY_TO_BOOLEAN ToBooleanExp;
+ HII_DEPENDENCY_TO_STRING ToStringExp;
+ HII_DEPENDENCY_TO_UINT ToUintExp;
+ HII_DEPENDENCY_TO_UPPER ToUpperExp;
+ HII_DEPENDENCY_TO_LOWER ToLowerExp;
+ HII_DEPENDENCY_SET SetExp;
+ HII_DEPENDENCY_NOT NotExp;
+
+ ///
+ /// Binary expression
+ ///
+ HII_DEPENDENCY_CATENATE CatenateExp;
+ HII_DEPENDENCY_MATCH MatchExp;
+ HII_DEPENDENCY_MATCH2 Match2Exp;
+ HII_DEPENDENCY_MULT MultExp;
+ HII_DEPENDENCY_DIV DivExp;
+ HII_DEPENDENCY_MOD ModExp;
+ HII_DEPENDENCY_ADD AddExp;
+ HII_DEPENDENCY_SUBTRACT SubtractExp;
+ HII_DEPENDENCY_SHIFT_LEFT ShiftLeftExp;
+ HII_DEPENDENCY_SHIFT_RIGHT ShiftRightExp;
+ HII_DEPENDENCY_GREATER_THAN GreaterThanExp;
+ HII_DEPENDENCY_GREATER_EQUAL GreaterEqualExp;
+ HII_DEPENDENCY_LESS_THAN LessThanExp;
+ HII_DEPENDENCY_LESS_EQUAL LessEqualExp;
+ HII_DEPENDENCY_EQUAL EqualExp;
+ HII_DEPENDENCY_NOT_EQUAL NotEqualExp;
+ HII_DEPENDENCY_BITWISE_AND BitwiseAndExp;
+ HII_DEPENDENCY_BITWISE_OR BitwiseOrExp;
+ HII_DEPENDENCY_AND AndExp;
+ HII_DEPENDENCY_OR OrExp;
+
+ ///
+ /// ternary expression
+ ///
+ HII_DEPENDENCY_CONDITIONAL ConditionalExp;
+ HII_DEPENDENCY_FIND FindExp;
+ HII_DEPENDENCY_MID MidExp;
+ HII_DEPENDENCY_TOKEN TokenExp;
+ HII_DEPENDENCY_SPAN SpanExp;
+ HII_DEPENDENCY_MAP MapExp;
+};
+
+///
+/// Definition of HII_EXPRESSION_OPCODE
+///
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+ UINT8 Operand;
+ HII_EXPRESSION_OPCODE_EXTRA ExtraData;
+ LIST_ENTRY MapExpressionList; ///< nested expressions inside of Map opcode.
+} HII_EXPRESSION_OPCODE;
+
+#define HII_EXPRESSION_OPCODE_SIGNATURE SIGNATURE_32 ('E', 'X', 'O', 'P')
+#define HII_EXPRESSION_OPCODE_FROM_LINK(a) CR (a, HII_EXPRESSION_OPCODE, Link, HII_EXPRESSION_OPCODE_SIGNATURE)
+
+///
+/// Definition of HII_WARNING_IF_DATA
+///
+typedef struct {
+ EFI_STRING_ID WarningIfError;
+ UINT8 TimeOut;
+} HII_WARNING_IF_DATA;
+
+///
+/// Definition of HII_EXTRA_DATA
+///
+typedef union {
+ UINT8 RuleId; ///< For EFI_IFR_RULE only
+ EFI_STRING_ID Error; ///< For EFI_IFR_NO_SUBMIT_IF, EFI_IFR_INCONSISTENT_IF only
+ HII_WARNING_IF_DATA WarningIfData;
+} HII_EXTRA_DATA;
+
+///
+/// Definition of HII_EXPRESSION
+///
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+ UINT8 Type; ///< Type for this expression
+ EFI_IFR_OP_HEADER *OpCode; ///< Save the opcode buffer.
+ LIST_ENTRY OpCodeListHead; ///< OpCodes consist of this expression (HII_EXPRESSION_OPCODE)
+ HII_DEPENDENCY_EXPRESSION *RootDependencyExp; ///< Expression OpCodes tree layout to describe dependency of this expression.
+ HII_EXTRA_DATA ExtraData;
+ EFI_HII_VALUE Result; ///< Expression evaluation result
+} HII_EXPRESSION;
+
+#define HII_EXPRESSION_SIGNATURE SIGNATURE_32 ('F', 'E', 'X', 'P')
+#define HII_EXPRESSION_FROM_LINK(a) CR (a, HII_EXPRESSION, Link, HII_EXPRESSION_SIGNATURE)
+
+///
+/// Definition of HII_EXPRESSION_LIST
+///
+typedef struct {
+ UINTN Signature;
+ UINTN Count;
+ HII_EXPRESSION *Expression[1]; ///< Array[Count] of expressions
+} HII_EXPRESSION_LIST;
+
+#define HII_EXPRESSION_LIST_SIGNATURE SIGNATURE_32 ('F', 'E', 'X', 'R')
+
+///
+/// Definition of HII_STATEMENT_VALUE
+///
+typedef struct {
+ ///
+ /// HII Data Type
+ ///
+ UINT8 Type;
+ EFI_IFR_TYPE_VALUE Value;
+ ///
+ /// Buffer Data and Length if Type is EFI_IFR_TYPE_BUFFER or EFI_IFR_TYPE_STRING
+ ///
+ UINT8 *Buffer;
+ UINT16 BufferLen;
+ UINT8 BufferValueType; ///< Data type for buffer internal data, currently only for orderedlist
+} HII_STATEMENT_VALUE;
+
+///
+/// Default value
+///
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+
+ UINT16 DefaultId;
+ HII_STATEMENT_VALUE Value; ///< Default value
+
+ HII_EXPRESSION *ValueExpression; ///< Not-NULL indicates default value is provided by EFI_IFR_VALUE
+} HII_QUESTION_DEFAULT;
+
+#define HII_QUESTION_DEFAULT_SIGNATURE SIGNATURE_32 ('Q', 'D', 'F', 'T')
+#define HII_QUESTION_DEFAULT_FROM_LINK(a) CR (a, HII_QUESTION_DEFAULT, Link, HII_QUESTION_DEFAULT_SIGNATURE)
+
+#define HII_QUESTION_OPTION_SIGNATURE SIGNATURE_32 ('Q', 'O', 'P', 'T')
+
+///
+/// Option value
+///
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+
+ EFI_IFR_ONE_OF_OPTION *OpCode; ///< OneOfOption Data
+
+ EFI_STRING_ID Text;
+ UINT8 Flags;
+ HII_STATEMENT_VALUE Value;
+ EFI_IMAGE_ID ImageId;
+
+ HII_EXPRESSION_LIST *SuppressExpression; ///< Non-NULL indicates nested inside of SuppressIf
+} HII_QUESTION_OPTION;
+
+#define HII_QUESTION_OPTION_FROM_LINK(a) CR (a, HII_QUESTION_OPTION, Link, HII_QUESTION_OPTION_SIGNATURE)
+
+///
+/// class of default
+///
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+
+ UINT16 DefaultId;
+ EFI_STRING_ID DefaultName;
+} HII_FORMSET_DEFAULTSTORE;
+
+#define HII_FORMSET_DEFAULTSTORE_SIGNATURE SIGNATURE_32 ('F', 'D', 'F', 'S')
+#define HII_FORMSET_DEFAULTSTORE_FROM_LINK(a) CR (a, HII_FORMSET_DEFAULTSTORE, Link, HII_FORMSET_DEFAULTSTORE_SIGNATURE)
+
+///
+/// Definition of HII_STATEMENT_EXTRA
+///
+typedef union {
+ UINT8 Flags;
+ EFI_STRING_ID TextTwo;
+ EFI_DEFAULT_ID DefaultId;
+ EFI_STRING_ID QuestionConfig;
+ EFI_GUID Guid;
+
+ struct {
+ UINT8 Flags;
+ UINT64 Minimum; ///< for EFI_IFR_ONE_OF/EFI_IFR_NUMERIC, it's Min/Max value
+ UINT64 Maximum; ///< for EFI_IFR_STRING/EFI_IFR_PASSWORD, it's Min/Max length
+ UINT64 Step;
+ EFI_GUID Guid;
+ } NumData;
+
+ struct {
+ UINT8 Flags;
+ UINT8 MaxContainers; ///< for EFI_IFR_ORDERED_LIST
+ } OrderListData;
+
+ struct {
+ UINT8 Flags;
+ UINT8 MinSize;
+ UINT8 MaxSize;
+ } StrData;
+
+ struct {
+ UINT16 MinSize;
+ UINT16 MaxSize;
+ } PwdData;
+} HII_STATEMENT_EXTRA;
+
+///
+/// Statement (Question)
+///
+typedef struct _HII_STATEMENT HII_STATEMENT;
+struct _HII_STATEMENT {
+ UINTN Signature;
+ LIST_ENTRY Link;
+
+ UINT8 Operand; ///< The operand (first byte) of this Statement or Question
+ EFI_IFR_OP_HEADER *OpCode;
+
+ ///
+ /// Statement Header
+ ///
+ EFI_STRING_ID Prompt;
+ EFI_STRING_ID Help;
+
+ ///
+ /// Question Header
+ ///
+ EFI_QUESTION_ID QuestionId; ///< Question id, the value of zero is reserved
+ EFI_VARSTORE_ID VarStoreId; ///< VarStore id, a value of zero indicates no variable storage
+ HII_VAR_STORE_INFO VarStoreInfo; ///< VarStoreInfoIf VarStoreId refers to Buffer Storage (EFI_IFR_VARSTORE or EFI_IFR_VARSTORE_EFI), then VarStoreInfo contains a 16-bit Buffer Storage offset (VarOffset).
+ ///< If VarStoreId refers to Name/Value Storage (EFI_IFR_VARSTORE_NAME_VALUE), then VarStoreInfo contains the String ID of the name (VarName) for this name/value pair.
+ UINT8 QuestionFlags; ///< The flag of this Question.(Readonly, reset required, callback attribute....)
+
+ BOOLEAN QuestionReferToBitField; ///< Whether the question is stored in a bit field.
+ UINT16 StorageWidth; ///< The storage width of this Question.
+ UINT16 BitStorageWidth; ///< The Storage width of this Question in bit level.
+ UINT16 BitVarOffset; ///< The storage offset of this Question in bit level.
+ CHAR16 *VariableName; ///< Name/Value or EFI Variable name
+ CHAR16 *BlockName; ///< Buffer storage block name: "OFFSET=...WIDTH=..."
+
+ HII_FORMSET_STORAGE *Storage; ///< Point to the storage that store this question.
+ HII_STATEMENT_EXTRA ExtraData;
+
+ BOOLEAN Locked; ///< Whether this statement is locked.
+
+ HII_STATEMENT_VALUE Value;
+
+ ///
+ /// Get from IFR parsing
+ ///
+
+ HII_STATEMENT *ParentStatement; ///< Parent Statement of current statement.
+ HII_EXPRESSION_LIST *ExpressionList; ///< nesting inside of GrayedOutIf/DisableIf/SuppressIf
+ HII_EXPRESSION *ValueExpression; ///< nested EFI_IFR_VALUE, provide Question value and indicate Question is ReadOnly
+
+ EFI_IMAGE_ID ImageId; ///< nested EFI_IFR_IMAGE
+ UINT8 RefreshInterval; ///< nested EFI_IFR_REFRESH, refresh interval(in seconds) for Question value, 0 means no refresh
+
+ LIST_ENTRY DefaultListHead; ///< nested EFI_IFR_DEFAULT list (HII_QUESTION_DEFAULT), provide default values
+ LIST_ENTRY OptionListHead; ///< nested EFI_IFR_ONE_OF_OPTION list (HII_QUESTION_OPTION)
+ LIST_ENTRY InconsistentListHead; ///< nested inconsistent expression list (HII_EXPRESSION)
+ LIST_ENTRY NoSubmitListHead; ///< nested nosubmit expression list (HII_EXPRESSION)
+ LIST_ENTRY WarningListHead; ///< nested warning expression list (HII_EXPRESSION)
+
+ HII_EXPRESSION *ReadExpression; ///< nested EFI_IFR_READ, provide this question value by read expression.
+ HII_EXPRESSION *WriteExpression; ///< nested EFI_IFR_WRITE, evaluate write expression after this question value is set.
+};
+
+#define HII_STATEMENT_SIGNATURE SIGNATURE_32 ('H', 'S', 'T', 'A')
+#define HII_STATEMENT_FROM_LINK(a) CR (a, HII_STATEMENT, Link, HII_STATEMENT_SIGNATURE)
+
+///
+/// Form
+///
+#define STANDARD_MAP_FORM_TYPE 0x01
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+
+ UINT16 FormId; ///< FormId of normal form or formmap form.
+ EFI_STRING_ID FormTitle; ///< FormTile of normal form, or FormMapMethod title of formmap form.
+ UINT16 FormType; ///< Specific form type for the different form.
+
+ EFI_IMAGE_ID ImageId; ///< The image id.
+
+ BOOLEAN ModalForm; ///< Whether this is a modal form.
+ BOOLEAN Locked; ///< Whether this form is locked.
+ EFI_GUID RefreshGuid; ///< Form refresh event guid.
+
+ LIST_ENTRY StatementListHead; ///< List of Statements and Questions (HII_STATEMENT)
+ LIST_ENTRY ConfigRequestHead; ///< List of configrequest for all storage.
+ LIST_ENTRY RuleListHead; ///< nested EFI_IFR_RULE list, pre-defined expressions attached to the form.
+ HII_EXPRESSION_LIST *SuppressExpression; ///< nesting inside of SuppressIf
+} HII_FORM;
+
+#define HII_FORM_SIGNATURE SIGNATURE_32 ('F', 'F', 'R', 'M')
+#define HII_FORM_FROM_LINK(a) CR (a, HII_FORM, Link, HII_FORM_SIGNATURE)
+
+///
+/// FormSet
+///
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+
+ EFI_HII_HANDLE HiiHandle; ///< Unique id for formset, HII Handle of this FormSet package.
+ EFI_HANDLE DriverHandle; ///< EFI_HANDLE which was registered with the package list in NewPackageList().
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess; ///< ConfigAccess Protocol associated with this HiiPackageList
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ UINTN IfrBinaryLength; ///< Ifr binary data length of this formset.
+ UINT8 *IfrBinaryData; ///< Point to the Ifr binary data.
+
+ EFI_GUID Guid; ///< Formset Guid.
+ EFI_STRING_ID FormSetTitle; ///< String Id of Formset title.
+ EFI_STRING_ID Help; ///< String Id of Formset title.
+
+ UINT8 NumberOfClassGuid; ///< Class Guid name
+ EFI_GUID ClassGuid[3]; ///< Up to three ClassGuid
+
+ EFI_IMAGE_ID ImageId; ///< The image id.
+
+ LIST_ENTRY StatementListOSF; ///< Statement list out side of the form.
+ LIST_ENTRY StorageListHead; ///< Storage list (HII_FORMSET_STORAGE)
+ LIST_ENTRY DefaultStoreListHead; ///< DefaultStore list (HII_FORMSET_DEFAULTSTORE)
+ LIST_ENTRY FormListHead; ///< Form list (HII_FORM_BROWSER_FORM)
+} HII_FORMSET;
+
+#define HII_FORMSET_SIGNATURE SIGNATURE_32 ('H', 'I', 'F', 'S')
+#define HII_FORMSET_FROM_LINK(a) CR (a, HII_FORMSET, Link, HII_FORMSET_SIGNATURE)
+
+///
+/// Get/set question value from/to.
+///
+typedef enum {
+ GetSetValueWithBuffer = 0, ///< Get/Set question value from/to buffer in the storage.
+ GetSetValueWithHiiDriver, ///< Get/Set question value from/to hii driver.
+ GetSetValueWithBoth, ///< Compare the editbuffer with buffer for this question, not use the question value.
+ GetSetValueWithMax ///< Invalid value.
+} GET_SET_QUESTION_VALUE_WITH;
+
+/**
+ Initialize the internal data structure of a FormSet.
+
+ @param[in] Handle PackageList Handle
+ @param[in,out] FormSetGuid On input, GUID or class GUID of a formset. If not
+ specified (NULL or zero GUID), take the first
+ FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
+ found in package list.
+ On output, GUID of the formset found(if not NULL).
+ @param[out] FormSet FormSet data structure.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_NOT_FOUND The specified FormSet could not be found.
+
+**/
+EFI_STATUS
+CreateFormSetFromHiiHandle (
+ IN EFI_HII_HANDLE Handle,
+ IN OUT EFI_GUID *FormSetGuid,
+ OUT HII_FORMSET *FormSet
+ );
+
+/**
+ Initialize a Formset and get current setting for Questions.
+
+ @param[in,out] FormSet FormSet data structure.
+
+**/
+VOID
+InitializeFormSet (
+ IN OUT HII_FORMSET *FormSet
+ );
+
+/**
+ Free resources allocated for a FormSet.
+
+ @param[in,out] FormSet Pointer of the FormSet
+
+**/
+VOID
+DestroyFormSet (
+ IN OUT HII_FORMSET *FormSet
+ );
+
+/**
+ Save Question Value to the memory, but not to storage.
+
+ @param[in] FormSet FormSet data structure.
+ @param[in] Form Form data structure.
+ @param[in,out] Question Pointer to the Question.
+ @param[in] QuestionValue New Question Value to be set.
+
+ @retval EFI_SUCCESS The question value has been set successfully.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+EFI_STATUS
+SetQuestionValue (
+ IN HII_FORMSET *FormSet,
+ IN HII_FORM *Form,
+ IN OUT HII_STATEMENT *Question,
+ IN HII_STATEMENT_VALUE *QuestionValue
+ );
+
+/**
+ Get Question's current Value from storage.
+
+ @param[in] FormSet FormSet data structure.
+ @param[in] Form Form data structure.
+ @param[in,out] Question Question to be initialized.
+
+ @return the current Question Value in storage if success.
+ @return NULL if Question is not found or any error occurs.
+
+**/
+HII_STATEMENT_VALUE *
+RetrieveQuestion (
+ IN HII_FORMSET *FormSet,
+ IN HII_FORM *Form,
+ IN OUT HII_STATEMENT *Question
+ );
+
+/**
+ Get Question's current Value.
+
+ @param[in] FormSet FormSet data structure.
+ @param[in] Form Form data structure.
+ @param[out] Question Question to be initialized.
+ @param[in] GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Formset, Form or Question is NULL.
+
+**/
+EFI_STATUS
+GetQuestionValue (
+ IN HII_FORMSET *FormSet,
+ IN HII_FORM *Form,
+ IN OUT HII_STATEMENT *Question,
+ IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
+ );
+
+/**
+ Submit data for a form.
+
+ @param[in] FormSet FormSet which contains the Form.
+ @param[in] Form Form to submit.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval Others Other errors occur.
+
+**/
+EFI_STATUS
+SubmitForm (
+ IN HII_FORMSET *FormSet,
+ IN HII_FORM *Form
+ );
+
+/**
+ Evaluate the result of a HII expression.
+
+ If Expression is NULL, then ASSERT.
+
+ @param[in] FormSet FormSet associated with this expression.
+ @param[in] Form Form associated with this expression.
+ @param[in,out] Expression Expression to be evaluated.
+
+ @retval EFI_SUCCESS The expression evaluated successfully
+ @retval EFI_NOT_FOUND The Question which referenced by a QuestionId
+ could not be found.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
+ stack.
+ @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
+ @retval EFI_INVALID_PARAMETER Syntax error with the Expression
+
+**/
+EFI_STATUS
+EvaluateHiiExpression (
+ IN HII_FORMSET *FormSet,
+ IN HII_FORM *Form,
+ IN OUT HII_EXPRESSION *Expression
+ );
+
+/**
+ Retrieve dependencies within an expression. These dependencies can express how
+ this expression will be evaluated.
+
+ @param[in] Expression Expression to retrieve dependencies.
+
+ @retval EFI_SUCCESS The dependencies were successfully retrieved.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory.
+
+**/
+EFI_STATUS
+GetHiiExpressionDependency (
+ IN HII_EXPRESSION *Expression
+ );
+
+/**
+ Get default value of question.
+
+ @param[in] FormSet The form set.
+ @param[in] Form The form.
+ @param[in] Question The question.
+ @param[in] DefaultId The Class of the default.
+ @param[out] DefaultValue The default value of given question.
+
+ @retval EFI_SUCCESS Question is reset to default value.
+
+**/
+EFI_STATUS
+GetQuestionDefault (
+ IN HII_FORMSET *FormSet,
+ IN HII_FORM *Form,
+ IN HII_STATEMENT *Question,
+ IN UINT16 DefaultId,
+ OUT HII_STATEMENT_VALUE *DefaultValue
+ );
+
+/**
+ Return the result of the expression list. Check the expression list and
+ return the highest priority express result.
+ Priority: DisableIf > SuppressIf > GrayOutIf > FALSE
+
+ @param[in] ExpList The input expression list.
+ @param[in] Evaluate Whether need to evaluate the expression first.
+ @param[in] FormSet FormSet associated with this expression.
+ @param[in] Form Form associated with this expression.
+
+ @retval EXPRESS_RESULT Return the higher priority express result.
+ DisableIf > SuppressIf > GrayOutIf > FALSE
+
+**/
+EXPRESS_RESULT
+EvaluateExpressionList (
+ IN HII_EXPRESSION_LIST *ExpList,
+ IN BOOLEAN Evaluate,
+ IN HII_FORMSET *FormSet OPTIONAL,
+ IN HII_FORM *Form OPTIONAL
+ );
+
+#endif // HII_UTILITY_LIB_
diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiExpression.h b/RedfishPkg/Library/HiiUtilityLib/HiiExpression.h
new file mode 100644
index 000000000000..dda96ada607e
--- /dev/null
+++ b/RedfishPkg/Library/HiiUtilityLib/HiiExpression.h
@@ -0,0 +1,191 @@
+/** @file
+ Definitions of Hii Expression.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+ Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef HII_EXPRESSION_H_
+#define HII_EXPRESSION_H_
+
+#include <Library/HiiUtilityLib.h>
+
+/**
+ Get the expression list count.
+
+ @param[in] Level Which type this expression belong to. Form,
+ statement or option?
+
+ @retval >=0 The expression count
+ @retval -1 Input parameter error.
+
+**/
+INTN
+GetConditionalExpressionCount (
+ IN EXPRESS_LEVEL Level
+ );
+
+/**
+ Get the expression Buffer pointer.
+
+ @param[in] Level Which type this expression belong to. Form,
+ statement or option?
+
+ @retval The start pointer of the expression buffer or NULL.
+
+**/
+HII_EXPRESSION **
+GetConditionalExpressionList (
+ IN EXPRESS_LEVEL Level
+ );
+
+/**
+ Push the expression options onto the Stack.
+
+ @param[in] Pointer Pointer to the current expression.
+ @param[in] Level Which type this expression belong to. Form,
+ statement or option?
+
+ @retval EFI_SUCCESS The value was pushed onto the stack.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
+
+**/
+EFI_STATUS
+PushConditionalExpression (
+ IN HII_EXPRESSION *Pointer,
+ IN EXPRESS_LEVEL Level
+ );
+
+/**
+ Pop the expression options from the Stack
+
+ @param[in] Level Which type this expression belong to. Form,
+ statement or option?
+
+ @retval EFI_SUCCESS The value was pushed onto the stack.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
+
+**/
+EFI_STATUS
+PopConditionalExpression (
+ IN EXPRESS_LEVEL Level
+ );
+
+/**
+ Reset stack pointer to begin of the stack.
+
+**/
+VOID
+ResetCurrentExpressionStack (
+ VOID
+ );
+
+/**
+ Push current expression onto the Stack
+
+ @param[in] Pointer Pointer to current expression.
+
+ @retval EFI_SUCCESS The value was pushed onto the stack.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
+
+**/
+EFI_STATUS
+PushCurrentExpression (
+ IN VOID *Pointer
+ );
+
+/**
+ Pop current expression from the Stack
+
+ @param[in] Pointer Pointer to current expression to be pop.
+
+ @retval EFI_SUCCESS The value was pushed onto the stack.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
+
+**/
+EFI_STATUS
+PopCurrentExpression (
+ OUT VOID **Pointer
+ );
+
+/**
+ Reset stack pointer to begin of the stack.
+
+**/
+VOID
+ResetMapExpressionListStack (
+ VOID
+ );
+
+/**
+ Push the list of map expression onto the Stack
+
+ @param[in] Pointer Pointer to the list of map expression to be pushed.
+
+ @retval EFI_SUCCESS The value was pushed onto the stack.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
+
+**/
+EFI_STATUS
+PushMapExpressionList (
+ IN VOID *Pointer
+ );
+
+/**
+ Pop the list of map expression from the Stack
+
+ @param[in] Pointer Pointer to the list of map expression to be pop.
+
+ @retval EFI_SUCCESS The value was pushed onto the stack.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
+
+**/
+EFI_STATUS
+PopMapExpressionList (
+ OUT VOID **Pointer
+ );
+
+/**
+ Reset stack pointer to begin of the stack.
+
+**/
+VOID
+ResetScopeStack (
+ VOID
+ );
+
+/**
+ Push an Operand onto the Stack
+
+ @param[in] Operand Operand to push.
+
+ @retval EFI_SUCCESS The value was pushed onto the stack.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
+ stack.
+
+**/
+EFI_STATUS
+PushScope (
+ IN UINT8 Operand
+ );
+
+/**
+ Pop an Operand from the Stack
+
+ @param[out] Operand Operand to pop.
+
+ @retval EFI_SUCCESS The value was pushed onto the stack.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
+ stack.
+
+**/
+EFI_STATUS
+PopScope (
+ OUT UINT8 *Operand
+ );
+
+#endif
diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiInternal.h b/RedfishPkg/Library/HiiUtilityLib/HiiInternal.h
new file mode 100644
index 000000000000..e68a61f8b27d
--- /dev/null
+++ b/RedfishPkg/Library/HiiUtilityLib/HiiInternal.h
@@ -0,0 +1,376 @@
+/** @file
+ HII internal header file.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+ Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef HII_INTERNAL_H_
+#define HII_INTERNAL_H_
+
+#include <Uefi.h>
+
+#include <Protocol/UnicodeCollation.h>
+#include <Protocol/HiiConfigRouting.h>
+#include <Protocol/HiiDatabase.h>
+#include <Protocol/UserManager.h>
+#include <Protocol/DevicePathFromText.h>
+#include <Protocol/RegularExpressionProtocol.h>
+
+#include <Guid/MdeModuleHii.h>
+#include <Guid/ZeroGuid.h>
+#include <Guid/HiiPlatformSetupFormset.h>
+#include <Guid/HiiFormMapMethodGuid.h>
+
+#include <Library/PrintLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/HiiLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/UefiLib.h>
+
+#include "HiiExpression.h"
+#include <Library/HiiUtilityLib.h>
+
+#define EXPRESSION_STACK_SIZE_INCREMENT 0x100
+#define EFI_IFR_SPECIFICATION_VERSION (UINT16) (((EFI_SYSTEM_TABLE_REVISION >> 16) << 8) | (((EFI_SYSTEM_TABLE_REVISION & 0xFFFF) / 10) << 4) | ((EFI_SYSTEM_TABLE_REVISION & 0xFFFF) % 10))
+
+///
+/// Definition of HII_FORM_CONFIG_REQUEST
+//
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+
+ CHAR16 *ConfigRequest; ///< <ConfigRequest> = <ConfigHdr> + <RequestElement>
+ CHAR16 *ConfigAltResp; ///< Alt config response string for this ConfigRequest.
+ UINTN ElementCount; ///< Number of <RequestElement> in the <ConfigRequest>
+ UINTN SpareStrLen;
+ CHAR16 *RestoreConfigRequest; ///< When submit form fail, the element need to be restored
+ CHAR16 *SyncConfigRequest; ///< When submit form fail, the element need to be synced
+
+ HII_FORMSET_STORAGE *Storage;
+} HII_FORM_CONFIG_REQUEST;
+
+#define HII_FORM_CONFIG_REQUEST_SIGNATURE SIGNATURE_32 ('F', 'C', 'R', 'S')
+#define HII_FORM_CONFIG_REQUEST_FROM_LINK(a) CR (a, HII_FORM_CONFIG_REQUEST, Link, HII_FORM_CONFIG_REQUEST_SIGNATURE)
+
+///
+/// Incremental string length of ConfigRequest
+///
+#define CONFIG_REQUEST_STRING_INCREMENTAL 1024
+
+/**
+ Allocate new memory and then copy the Unicode string Source to Destination.
+
+ @param[in,out] Dest Location to copy string
+ @param[in] Src String to copy
+
+**/
+VOID
+NewStringCopy (
+ IN OUT CHAR16 **Dest,
+ IN CHAR16 *Src
+ );
+
+/**
+ Set Value of given Name in a NameValue Storage.
+
+ @param[in] Storage The NameValue Storage.
+ @param[in] Name The Name.
+ @param[in] Value The Value to set.
+ @param[out] ReturnNode The node use the input name.
+
+ @retval EFI_SUCCESS Value found for given Name.
+ @retval EFI_NOT_FOUND No such Name found in NameValue storage.
+
+**/
+EFI_STATUS
+SetValueByName (
+ IN HII_FORMSET_STORAGE *Storage,
+ IN CHAR16 *Name,
+ IN CHAR16 *Value,
+ OUT HII_NAME_VALUE_NODE **ReturnNode
+ );
+
+/**
+ Get bit field value from the buffer and then set the value for the question.
+ Note: Data type UINT32 can cover all the bit field value.
+
+ @param[in] Question The question refer to bit field.
+ @param[in] Buffer Point to the buffer which the question value get from.
+ @param[out] QuestionValue The Question Value retrieved from Bits.
+
+**/
+VOID
+GetBitsQuestionValue (
+ IN HII_STATEMENT *Question,
+ IN UINT8 *Buffer,
+ OUT HII_STATEMENT_VALUE *QuestionValue
+ );
+
+/**
+ Set bit field value to the buffer.
+ Note: Data type UINT32 can cover all the bit field value.
+
+ @param[in] Question The question refer to bit field.
+ @param[in,out] Buffer Point to the buffer which the question value set to.
+ @param[in] Value The bit field value need to set.
+
+**/
+VOID
+SetBitsQuestionValue (
+ IN HII_STATEMENT *Question,
+ IN OUT UINT8 *Buffer,
+ IN UINT32 Value
+ );
+
+/**
+ Convert the buffer value to HiiValue.
+
+ @param[in] Question The question.
+ @param[in] Value Unicode buffer save the question value.
+ @param[out] QuestionValue The Question Value retrieved from Buffer.
+
+ @retval Status whether convert the value success.
+
+**/
+EFI_STATUS
+BufferToQuestionValue (
+ IN HII_STATEMENT *Question,
+ IN CHAR16 *Value,
+ OUT HII_STATEMENT_VALUE *QuestionValue
+ );
+
+/**
+ Get the string based on the StringId and HII Package List Handle.
+
+ @param[in] Token The String's ID.
+ @param[in] HiiHandle The package list in the HII database to search for
+ the specified string.
+
+ @return The output string.
+
+**/
+CHAR16 *
+GetTokenString (
+ IN EFI_STRING_ID Token,
+ IN EFI_HII_HANDLE HiiHandle
+ );
+
+/**
+ Converts the unicode character of the string from uppercase to lowercase.
+ This is a internal function.
+
+ @param[in] ConfigString String to be converted
+
+**/
+VOID
+EFIAPI
+HiiStringToLowercase (
+ IN EFI_STRING ConfigString
+ );
+
+/**
+ Evaluate if the result is a non-zero value.
+
+ @param[in] Result The result to be evaluated.
+
+ @retval TRUE It is a non-zero value.
+ @retval FALSE It is a zero value.
+
+**/
+BOOLEAN
+IsHiiValueTrue (
+ IN EFI_HII_VALUE *Result
+ );
+
+/**
+ Set a new string to string package.
+
+ @param[in] String A pointer to the Null-terminated Unicode string
+ to add or update in the String Package associated
+ with HiiHandle.
+ @param[in] HiiHandle A handle that was previously registered in the
+ HII Database.
+
+ @return the Id for this new string.
+
+**/
+EFI_STRING_ID
+NewHiiString (
+ IN CHAR16 *String,
+ IN EFI_HII_HANDLE HiiHandle
+ );
+
+/**
+ Perform nosubmitif check for a Form.
+
+ @param[in] FormSet FormSet data structure.
+ @param[in] Form Form data structure.
+ @param[in] Question The Question to be validated.
+
+ @retval EFI_SUCCESS Form validation pass.
+ @retval other Form validation failed.
+
+**/
+EFI_STATUS
+ValidateNoSubmit (
+ IN HII_FORMSET *FormSet,
+ IN HII_FORM *Form,
+ IN HII_STATEMENT *Question
+ );
+
+/**
+ Perform NoSubmit check for each Form in FormSet.
+
+ @param[in] FormSet FormSet data structure.
+ @param[in,out] CurrentForm Current input form data structure.
+ @param[out] Statement The statement for this check.
+
+ @retval EFI_SUCCESS Form validation pass.
+ @retval other Form validation failed.
+
+**/
+EFI_STATUS
+NoSubmitCheck (
+ IN HII_FORMSET *FormSet,
+ IN OUT HII_FORM **CurrentForm,
+ OUT HII_STATEMENT **Statement
+ );
+
+/**
+ Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
+
+ @param[in] Storage The Storage to be converted.
+ @param[in] ConfigResp The returned <ConfigResp>.
+ @param[in] ConfigRequest The ConfigRequest string.
+
+ @retval EFI_SUCCESS Convert success.
+ @retval EFI_INVALID_PARAMETER Incorrect storage type.
+
+**/
+EFI_STATUS
+StorageToConfigResp (
+ IN HII_FORMSET_STORAGE *Storage,
+ IN CHAR16 **ConfigResp,
+ IN CHAR16 *ConfigRequest
+ );
+
+/**
+ Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
+
+ @param[in] Storage The Storage to receive the settings.
+ @param[in] ConfigResp The <ConfigResp> to be converted.
+
+ @retval EFI_SUCCESS Convert success.
+ @retval EFI_INVALID_PARAMETER Incorrect storage type.
+
+**/
+EFI_STATUS
+ConfigRespToStorage (
+ IN HII_FORMSET_STORAGE *Storage,
+ IN CHAR16 *ConfigResp
+ );
+
+/**
+ Fetch the Ifr binary data of a FormSet.
+
+ @param[in] Handle PackageList Handle
+ @param[in,out] FormSetGuid On input, GUID or class GUID of a formset. If not
+ specified (NULL or zero GUID), take the first
+ FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
+ found in package list.
+ On output, GUID of the formset found(if not NULL).
+ @param[out] BinaryLength The length of the FormSet IFR binary.
+ @param[out] BinaryData The buffer designed to receive the FormSet.
+
+ @retval EFI_SUCCESS Buffer filled with the requested FormSet.
+ BufferLength was updated.
+ @retval EFI_INVALID_PARAMETER The handle is unknown.
+ @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
+ be found with the requested FormId.
+
+**/
+EFI_STATUS
+GetIfrBinaryData (
+ IN EFI_HII_HANDLE Handle,
+ IN OUT EFI_GUID *FormSetGuid,
+ OUT UINTN *BinaryLength,
+ OUT UINT8 **BinaryData
+ );
+
+/**
+ Fill storage with settings requested from Configuration Driver.
+
+ @param[in] FormSet FormSet data structure.
+ @param[in] Storage Buffer Storage.
+
+**/
+VOID
+LoadFormSetStorage (
+ IN HII_FORMSET *FormSet,
+ IN HII_FORMSET_STORAGE *Storage
+ );
+
+/**
+ Free resources of a Form.
+
+ @param[in] FormSet Pointer of the FormSet
+ @param[in,out] Form Pointer of the Form.
+
+**/
+VOID
+DestroyForm (
+ IN HII_FORMSET *FormSet,
+ IN OUT HII_FORM *Form
+ );
+
+/**
+ Get formset storage based on the input varstoreid info.
+
+ @param[in] FormSet Pointer of the current FormSet.
+ @param[in] VarStoreId Varstore ID info.
+
+ @return Pointer to a HII_FORMSET_STORAGE data structure.
+
+**/
+HII_FORMSET_STORAGE *
+GetFstStgFromVarId (
+ IN HII_FORMSET *FormSet,
+ IN EFI_VARSTORE_ID VarStoreId
+ );
+
+/**
+ Zero extend integer/boolean/date/time to UINT64 for comparing.
+
+ @param[in] Value HII Value to be converted.
+
+**/
+VOID
+ExtendValueToU64 (
+ IN HII_STATEMENT_VALUE *Value
+ );
+
+/**
+ Parse opcodes in the formset IFR binary.
+
+ @param[in] FormSet Pointer of the FormSet data structure.
+
+ @retval EFI_SUCCESS Opcode parse success.
+ @retval Other Opcode parse fail.
+
+**/
+EFI_STATUS
+ParseOpCodes (
+ IN HII_FORMSET *FormSet
+ );
+
+#endif // HII_INTERNAL_H_
diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiExpression.c b/RedfishPkg/Library/HiiUtilityLib/HiiExpression.c
new file mode 100644
index 000000000000..c36c2416426b
--- /dev/null
+++ b/RedfishPkg/Library/HiiUtilityLib/HiiExpression.c
@@ -0,0 +1,1439 @@
+/** @file
+ The implementation of HII expression.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+ Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include "HiiInternal.h"
+
+//
+// Global stack used to evaluate boolean expressions
+//
+EFI_HII_VALUE *mOpCodeScopeStack = NULL;
+EFI_HII_VALUE *mOpCodeScopeStackEnd = NULL;
+EFI_HII_VALUE *mOpCodeScopeStackPointer = NULL;
+
+//
+// Stack used for Suppressif/grayoutif/disableif expression list.
+//
+HII_EXPRESSION **mFormExpressionStack = NULL;
+HII_EXPRESSION **mFormExpressionEnd = NULL;
+HII_EXPRESSION **mFormExpressionPointer = NULL;
+
+HII_EXPRESSION **mStatementExpressionStack = NULL;
+HII_EXPRESSION **mStatementExpressionEnd = NULL;
+HII_EXPRESSION **mStatementExpressionPointer = NULL;
+
+HII_EXPRESSION **mOptionExpressionStack = NULL;
+HII_EXPRESSION **mOptionExpressionEnd = NULL;
+HII_EXPRESSION **mOptionExpressionPointer = NULL;
+
+//
+// Stack used for the sub expresion in map expression.
+//
+EFI_HII_VALUE *mCurrentExpressionStack = NULL;
+EFI_HII_VALUE *mCurrentExpressionEnd = NULL;
+EFI_HII_VALUE *mCurrentExpressionPointer = NULL;
+
+//
+// Stack used for the map expression list.
+//
+EFI_HII_VALUE *mMapExpressionListStack = NULL;
+EFI_HII_VALUE *mMapExpressionListEnd = NULL;
+EFI_HII_VALUE *mMapExpressionListPointer = NULL;
+
+//
+// Stack used for dependency expression.
+//
+HII_DEPENDENCY_EXPRESSION **mExpressionDependencyStack = NULL;
+HII_DEPENDENCY_EXPRESSION **mExpressionDependencyEnd = NULL;
+HII_DEPENDENCY_EXPRESSION **mExpressionDependencyPointer = NULL;
+
+/**
+ Grow size of the stack.
+
+ This is an internal function.
+
+ @param Stack On input: old stack; On output: new stack
+ @param StackPtr On input: old stack pointer; On output: new stack
+ pointer
+ @param StackEnd On input: old stack end; On output: new stack end
+
+ @retval EFI_SUCCESS Grow stack success.
+ @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.
+
+**/
+EFI_STATUS
+GrowStack (
+ IN OUT EFI_HII_VALUE **Stack,
+ IN OUT EFI_HII_VALUE **StackPtr,
+ IN OUT EFI_HII_VALUE **StackEnd
+ )
+{
+ UINTN Size;
+ EFI_HII_VALUE *NewStack;
+
+ Size = EXPRESSION_STACK_SIZE_INCREMENT;
+ if (*StackPtr != NULL) {
+ Size = Size + (*StackEnd - *Stack);
+ }
+
+ NewStack = AllocatePool (Size * sizeof (EFI_HII_VALUE));
+ if (NewStack == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (*StackPtr != NULL) {
+ //
+ // Copy from Old Stack to the New Stack
+ //
+ CopyMem (
+ NewStack,
+ *Stack,
+ (*StackEnd - *Stack) * sizeof (EFI_HII_VALUE)
+ );
+
+ //
+ // Free The Old Stack
+ //
+ FreePool (*Stack);
+ }
+
+ //
+ // Make the Stack pointer point to the old data in the new stack
+ //
+ *StackPtr = NewStack + (*StackPtr - *Stack);
+ *Stack = NewStack;
+ *StackEnd = NewStack + Size;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Push an element onto the Boolean Stack.
+
+ @param Stack On input: old stack; On output: new stack
+ @param StackPtr On input: old stack pointer; On output: new stack
+ pointer
+ @param StackEnd On input: old stack end; On output: new stack end
+ @param Data Data to push.
+
+ @retval EFI_SUCCESS Push stack success.
+
+**/
+EFI_STATUS
+PushStack (
+ IN OUT EFI_HII_VALUE **Stack,
+ IN OUT EFI_HII_VALUE **StackPtr,
+ IN OUT EFI_HII_VALUE **StackEnd,
+ IN EFI_HII_VALUE *Data
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Check for a stack overflow condition
+ //
+ if (*StackPtr >= *StackEnd) {
+ //
+ // Grow the stack
+ //
+ Status = GrowStack (Stack, StackPtr, StackEnd);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // Push the item onto the stack
+ //
+ CopyMem (*StackPtr, Data, sizeof (EFI_HII_VALUE));
+ if (Data->Type == EFI_IFR_TYPE_BUFFER) {
+ (*StackPtr)->Buffer = AllocateCopyPool (Data->BufferLen, Data->Buffer);
+ if ((*StackPtr)->Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ *StackPtr = *StackPtr + 1;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Pop an element from the stack.
+
+ @param Stack On input: old stack
+ @param StackPtr On input: old stack pointer; On output: new stack pointer
+ @param Data Data to pop.
+
+ @retval EFI_SUCCESS The value was popped onto the stack.
+ @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
+
+**/
+EFI_STATUS
+PopStack (
+ IN EFI_HII_VALUE *Stack,
+ IN OUT EFI_HII_VALUE **StackPtr,
+ OUT EFI_HII_VALUE *Data
+ )
+{
+ //
+ // Check for a stack underflow condition
+ //
+ if (*StackPtr == Stack) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ //
+ // Pop the item off the stack
+ //
+ *StackPtr = *StackPtr - 1;
+ CopyMem (Data, *StackPtr, sizeof (EFI_HII_VALUE));
+ return EFI_SUCCESS;
+}
+
+/**
+ Reset stack pointer to begin of the stack.
+
+**/
+VOID
+ResetCurrentExpressionStack (
+ VOID
+ )
+{
+ mCurrentExpressionPointer = mCurrentExpressionStack;
+ mFormExpressionPointer = mFormExpressionStack;
+ mStatementExpressionPointer = mStatementExpressionStack;
+ mOptionExpressionPointer = mOptionExpressionStack;
+}
+
+/**
+ Push current expression onto the Stack
+
+ @param Pointer Pointer to current expression.
+
+ @retval EFI_SUCCESS The value was pushed onto the stack.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
+
+**/
+EFI_STATUS
+PushCurrentExpression (
+ IN VOID *Pointer
+ )
+{
+ EFI_HII_VALUE Data;
+
+ Data.Type = EFI_IFR_TYPE_NUM_SIZE_64;
+ Data.Value.u64 = (UINT64)(UINTN)Pointer;
+
+ return PushStack (
+ &mCurrentExpressionStack,
+ &mCurrentExpressionPointer,
+ &mCurrentExpressionEnd,
+ &Data
+ );
+}
+
+/**
+ Pop current expression from the Stack
+
+ @param Pointer Pointer to current expression to be pop.
+
+ @retval EFI_SUCCESS The value was pushed onto the stack.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
+
+**/
+EFI_STATUS
+PopCurrentExpression (
+ OUT VOID **Pointer
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_VALUE Data;
+
+ Status = PopStack (
+ mCurrentExpressionStack,
+ &mCurrentExpressionPointer,
+ &Data
+ );
+
+ *Pointer = (VOID *)(UINTN)Data.Value.u64;
+
+ return Status;
+}
+
+/**
+ Reset stack pointer to begin of the stack.
+
+**/
+VOID
+ResetMapExpressionListStack (
+ VOID
+ )
+{
+ mMapExpressionListPointer = mMapExpressionListStack;
+}
+
+/**
+ Grow size of the stack.
+
+ This is an internal function.
+
+ @param Stack On input: old stack; On output: new stack
+ @param StackPtr On input: old stack pointer; On output: new stack
+ pointer
+ @param StackEnd On input: old stack end; On output: new stack end
+ @param MemberSize The stack member size.
+
+ @retval EFI_SUCCESS Grow stack success.
+ @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.
+
+**/
+EFI_STATUS
+GrowConditionalStack (
+ IN OUT HII_EXPRESSION ***Stack,
+ IN OUT HII_EXPRESSION ***StackPtr,
+ IN OUT HII_EXPRESSION ***StackEnd,
+ IN UINTN MemberSize
+ )
+{
+ UINTN Size;
+ HII_EXPRESSION **NewStack;
+
+ Size = EXPRESSION_STACK_SIZE_INCREMENT;
+ if (*StackPtr != NULL) {
+ Size = Size + (*StackEnd - *Stack);
+ }
+
+ NewStack = AllocatePool (Size * MemberSize);
+ if (NewStack == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (*StackPtr != NULL) {
+ //
+ // Copy from Old Stack to the New Stack
+ //
+ CopyMem (
+ NewStack,
+ *Stack,
+ (*StackEnd - *Stack) * MemberSize
+ );
+
+ //
+ // Free The Old Stack
+ //
+ FreePool (*Stack);
+ }
+
+ //
+ // Make the Stack pointer point to the old data in the new stack
+ //
+ *StackPtr = NewStack + (*StackPtr - *Stack);
+ *Stack = NewStack;
+ *StackEnd = NewStack + Size;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Push an element onto the Stack.
+
+ @param Stack On input: old stack; On output: new stack
+ @param StackPtr On input: old stack pointer; On output: new stack
+ pointer
+ @param StackEnd On input: old stack end; On output: new stack end
+ @param Data Data to push.
+
+ @retval EFI_SUCCESS Push stack success.
+
+**/
+EFI_STATUS
+PushConditionalStack (
+ IN OUT HII_EXPRESSION ***Stack,
+ IN OUT HII_EXPRESSION ***StackPtr,
+ IN OUT HII_EXPRESSION ***StackEnd,
+ IN HII_EXPRESSION **Data
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Check for a stack overflow condition
+ //
+ if (*StackPtr >= *StackEnd) {
+ //
+ // Grow the stack
+ //
+ Status = GrowConditionalStack (Stack, StackPtr, StackEnd, sizeof (HII_EXPRESSION *));
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // Push the item onto the stack
+ //
+ CopyMem (*StackPtr, Data, sizeof (HII_EXPRESSION *));
+ *StackPtr = *StackPtr + 1;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Pop an element from the stack.
+
+ @param Stack On input: old stack
+ @param StackPtr On input: old stack pointer; On output: new stack pointer
+ @param Data Data to pop.
+
+ @retval EFI_SUCCESS The value was popped onto the stack.
+ @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
+
+**/
+EFI_STATUS
+PopConditionalStack (
+ IN HII_EXPRESSION **Stack,
+ IN OUT HII_EXPRESSION ***StackPtr,
+ OUT HII_EXPRESSION **Data
+ )
+{
+ //
+ // Check for a stack underflow condition
+ //
+ if (*StackPtr == Stack) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ //
+ // Pop the item off the stack
+ //
+ *StackPtr = *StackPtr - 1;
+ CopyMem (Data, *StackPtr, sizeof (HII_EXPRESSION *));
+ return EFI_SUCCESS;
+}
+
+/**
+ Get the expression list count.
+
+ @param Level Which type this expression belong to. Form,
+ statement or option?
+
+ @retval >=0 The expression count
+ @retval -1 Input parameter error.
+
+**/
+INTN
+GetConditionalExpressionCount (
+ IN EXPRESS_LEVEL Level
+ )
+{
+ switch (Level) {
+ case ExpressForm:
+ return mFormExpressionPointer - mFormExpressionStack;
+ case ExpressStatement:
+ return mStatementExpressionPointer - mStatementExpressionStack;
+ case ExpressOption:
+ return mOptionExpressionPointer - mOptionExpressionStack;
+ default:
+ ASSERT (FALSE);
+ return -1;
+ }
+}
+
+/**
+ Get the expression Buffer pointer.
+
+ @param Level Which type this expression belong to. Form,
+ statement or option?
+
+ @retval The start pointer of the expression buffer or NULL.
+
+**/
+HII_EXPRESSION **
+GetConditionalExpressionList (
+ IN EXPRESS_LEVEL Level
+ )
+{
+ switch (Level) {
+ case ExpressForm:
+ return mFormExpressionStack;
+ case ExpressStatement:
+ return mStatementExpressionStack;
+ case ExpressOption:
+ return mOptionExpressionStack;
+ default:
+ ASSERT (FALSE);
+ return NULL;
+ }
+}
+
+/**
+ Push the expression options onto the Stack.
+
+ @param Pointer Pointer to the current expression.
+ @param Level Which type this expression belong to. Form,
+ statement or option?
+
+ @retval EFI_SUCCESS The value was pushed onto the stack.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
+
+**/
+EFI_STATUS
+PushConditionalExpression (
+ IN HII_EXPRESSION *Pointer,
+ IN EXPRESS_LEVEL Level
+ )
+{
+ switch (Level) {
+ case ExpressForm:
+ return PushConditionalStack (
+ &mFormExpressionStack,
+ &mFormExpressionPointer,
+ &mFormExpressionEnd,
+ &Pointer
+ );
+ case ExpressStatement:
+ return PushConditionalStack (
+ &mStatementExpressionStack,
+ &mStatementExpressionPointer,
+ &mStatementExpressionEnd,
+ &Pointer
+ );
+ case ExpressOption:
+ return PushConditionalStack (
+ &mOptionExpressionStack,
+ &mOptionExpressionPointer,
+ &mOptionExpressionEnd,
+ &Pointer
+ );
+ default:
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+}
+
+/**
+ Pop the expression options from the Stack
+
+ @param Level Which type this expression belong to. Form,
+ statement or option?
+
+ @retval EFI_SUCCESS The value was pushed onto the stack.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
+
+**/
+EFI_STATUS
+PopConditionalExpression (
+ IN EXPRESS_LEVEL Level
+ )
+{
+ HII_EXPRESSION *Pointer;
+
+ switch (Level) {
+ case ExpressForm:
+ return PopConditionalStack (
+ mFormExpressionStack,
+ &mFormExpressionPointer,
+ &Pointer
+ );
+
+ case ExpressStatement:
+ return PopConditionalStack (
+ mStatementExpressionStack,
+ &mStatementExpressionPointer,
+ &Pointer
+ );
+
+ case ExpressOption:
+ return PopConditionalStack (
+ mOptionExpressionStack,
+ &mOptionExpressionPointer,
+ &Pointer
+ );
+
+ default:
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+}
+
+/**
+ Push the list of map expression onto the Stack
+
+ @param Pointer Pointer to the list of map expression to be pushed.
+
+ @retval EFI_SUCCESS The value was pushed onto the stack.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
+
+**/
+EFI_STATUS
+PushMapExpressionList (
+ IN VOID *Pointer
+ )
+{
+ EFI_HII_VALUE Data;
+
+ Data.Type = EFI_IFR_TYPE_NUM_SIZE_64;
+ Data.Value.u64 = (UINT64)(UINTN)Pointer;
+
+ return PushStack (
+ &mMapExpressionListStack,
+ &mMapExpressionListPointer,
+ &mMapExpressionListEnd,
+ &Data
+ );
+}
+
+/**
+ Pop the list of map expression from the Stack
+
+ @param Pointer Pointer to the list of map expression to be pop.
+
+ @retval EFI_SUCCESS The value was pushed onto the stack.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
+
+**/
+EFI_STATUS
+PopMapExpressionList (
+ OUT VOID **Pointer
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_VALUE Data;
+
+ Status = PopStack (
+ mMapExpressionListStack,
+ &mMapExpressionListPointer,
+ &Data
+ );
+
+ *Pointer = (VOID *)(UINTN)Data.Value.u64;
+
+ return Status;
+}
+
+/**
+ Reset stack pointer to begin of the stack.
+
+**/
+VOID
+ResetScopeStack (
+ VOID
+ )
+{
+ mOpCodeScopeStackPointer = mOpCodeScopeStack;
+}
+
+/**
+ Push an Operand onto the Stack
+
+ @param Operand Operand to push.
+
+ @retval EFI_SUCCESS The value was pushed onto the stack.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
+ stack.
+
+**/
+EFI_STATUS
+PushScope (
+ IN UINT8 Operand
+ )
+{
+ EFI_HII_VALUE Data;
+
+ Data.Type = EFI_IFR_TYPE_NUM_SIZE_8;
+ Data.Value.u8 = Operand;
+
+ return PushStack (
+ &mOpCodeScopeStack,
+ &mOpCodeScopeStackPointer,
+ &mOpCodeScopeStackEnd,
+ &Data
+ );
+}
+
+/**
+ Pop an Operand from the Stack
+
+ @param Operand Operand to pop.
+
+ @retval EFI_SUCCESS The value was pushed onto the stack.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
+ stack.
+
+**/
+EFI_STATUS
+PopScope (
+ OUT UINT8 *Operand
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_VALUE Data;
+
+ Status = PopStack (
+ mOpCodeScopeStack,
+ &mOpCodeScopeStackPointer,
+ &Data
+ );
+
+ *Operand = Data.Value.u8;
+
+ return Status;
+}
+
+/**
+ Grow size of the stack for Expression Dependencies.
+
+ This is an internal function.
+
+ @param Stack On input: old stack; On output: new stack
+ @param StackPtr On input: old stack pointer; On output: new stack
+ pointer
+ @param StackEnd On input: old stack end; On output: new stack end
+
+ @retval EFI_SUCCESS Grow Dependency stack success.
+ @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.
+
+**/
+EFI_STATUS
+GrowDependencyStack (
+ IN OUT HII_DEPENDENCY_EXPRESSION ***Stack,
+ IN OUT HII_DEPENDENCY_EXPRESSION ***StackPtr,
+ IN OUT HII_DEPENDENCY_EXPRESSION ***StackEnd
+ )
+{
+ UINTN Size;
+ HII_DEPENDENCY_EXPRESSION **NewStack;
+
+ Size = EXPRESSION_STACK_SIZE_INCREMENT;
+ if (*StackPtr != NULL) {
+ Size = Size + (*StackEnd - *Stack);
+ }
+
+ NewStack = AllocatePool (Size * sizeof (HII_DEPENDENCY_EXPRESSION *));
+ if (NewStack == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (*StackPtr != NULL) {
+ //
+ // Copy from Old Stack to the New Stack
+ //
+ CopyMem (
+ NewStack,
+ *Stack,
+ (*StackEnd - *Stack) * sizeof (HII_DEPENDENCY_EXPRESSION *)
+ );
+
+ //
+ // Free The Old Stack
+ //
+ FreePool (*Stack);
+ }
+
+ //
+ // Make the Stack pointer point to the old data in the new stack
+ //
+ *StackPtr = NewStack + (*StackPtr - *Stack);
+ *Stack = NewStack;
+ *StackEnd = NewStack + Size;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Push an element onto the Stack for Expression Dependencies.
+
+ @param Stack On input: old stack; On output: new stack
+ @param StackPtr On input: old stack pointer; On output: new stack
+ pointer
+ @param StackEnd On input: old stack end; On output: new stack end
+ @param Data Data to push.
+
+ @retval EFI_SUCCESS Push stack success.
+
+**/
+EFI_STATUS
+PushDependencyStack (
+ IN OUT HII_DEPENDENCY_EXPRESSION ***Stack,
+ IN OUT HII_DEPENDENCY_EXPRESSION ***StackPtr,
+ IN OUT HII_DEPENDENCY_EXPRESSION ***StackEnd,
+ IN HII_DEPENDENCY_EXPRESSION **Data
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Check for a stack overflow condition
+ //
+ if (*StackPtr >= *StackEnd) {
+ //
+ // Grow the stack
+ //
+ Status = GrowDependencyStack (Stack, StackPtr, StackEnd);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // Push the item onto the stack
+ //
+ CopyMem (*StackPtr, Data, sizeof (HII_DEPENDENCY_EXPRESSION *));
+ *StackPtr = *StackPtr + 1;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Pop the Expression Dependency options from the Stack
+
+ @param Stack On input: old stack; On output: new stack
+ @param StackPtr On input: old stack pointer; On output: new stack
+ pointer
+ @param Data Data to push.
+
+ @retval EFI_SUCCESS The value was pushed onto the stack.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
+
+**/
+EFI_STATUS
+PopDependencyStack (
+ IN HII_DEPENDENCY_EXPRESSION **Stack,
+ IN OUT HII_DEPENDENCY_EXPRESSION ***StackPtr,
+ OUT HII_DEPENDENCY_EXPRESSION **Data
+ )
+{
+ //
+ // Check for a stack underflow condition
+ //
+ if (*StackPtr == Stack) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ //
+ // Pop the item off the stack
+ //
+ *StackPtr = *StackPtr - 1;
+ CopyMem (Data, *StackPtr, sizeof (HII_DEPENDENCY_EXPRESSION *));
+ return EFI_SUCCESS;
+}
+
+/**
+ Push the list of Expression Dependencies onto the Stack
+
+ @param Pointer Pointer to the list of map expression to be pushed.
+
+ @retval EFI_SUCCESS The value was pushed onto the stack.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
+
+**/
+EFI_STATUS
+PushDependencyExpDes (
+ IN HII_DEPENDENCY_EXPRESSION **Pointer
+ )
+{
+ return PushDependencyStack (
+ &mExpressionDependencyStack,
+ &mExpressionDependencyPointer,
+ &mExpressionDependencyEnd,
+ Pointer
+ );
+}
+
+/**
+ Pop the list of Expression Dependencies from the Stack
+
+ @param Pointer Pointer to the list of map expression to be pop.
+
+ @retval EFI_SUCCESS The value was pushed onto the stack.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
+
+**/
+EFI_STATUS
+PopDependencyExpDes (
+ OUT HII_DEPENDENCY_EXPRESSION **Pointer
+ )
+{
+ return PopDependencyStack (
+ mExpressionDependencyStack,
+ &mExpressionDependencyPointer,
+ Pointer
+ );
+}
+
+/**
+ Retrieve dependencies within an expression. These dependencies can express how
+ this expression will be evaluated.
+
+ @param[in,out] Expression Expression to retrieve dependencies.
+
+ @retval EFI_SUCCESS The dependencies were successfully retrieved.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory.
+
+**/
+EFI_STATUS
+GetHiiExpressionDependency (
+ IN OUT HII_EXPRESSION *Expression
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ HII_EXPRESSION_OPCODE *ExpressionOpCode;
+ HII_DEPENDENCY_EXPRESSION *DepExpressionOpCode;
+ LIST_ENTRY *SubExpressionLink;
+ HII_EXPRESSION *SubExpression;
+ UINT8 MapPairCount;
+
+ Link = GetFirstNode (&Expression->OpCodeListHead);
+ while (!IsNull (&Expression->OpCodeListHead, Link)) {
+ ExpressionOpCode = HII_EXPRESSION_OPCODE_FROM_LINK (Link);
+ Link = GetNextNode (&Expression->OpCodeListHead, Link);
+ Status = EFI_SUCCESS;
+
+ DepExpressionOpCode = (HII_DEPENDENCY_EXPRESSION *)AllocateZeroPool (sizeof (HII_DEPENDENCY_EXPRESSION));
+ if (DepExpressionOpCode == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ switch (ExpressionOpCode->Operand) {
+ //
+ // Constant
+ //
+ case EFI_IFR_FALSE_OP:
+ case EFI_IFR_ONE_OP:
+ case EFI_IFR_ONES_OP:
+ case EFI_IFR_TRUE_OP:
+ case EFI_IFR_UINT8_OP:
+ case EFI_IFR_UINT16_OP:
+ case EFI_IFR_UINT32_OP:
+ case EFI_IFR_UINT64_OP:
+ case EFI_IFR_UNDEFINED_OP:
+ case EFI_IFR_VERSION_OP:
+ case EFI_IFR_ZERO_OP:
+ DepExpressionOpCode->ConstantExp.Operand = ExpressionOpCode->Operand;
+ CopyMem (&DepExpressionOpCode->ConstantExp.Value, &ExpressionOpCode->ExtraData.Value, sizeof (EFI_HII_VALUE));
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ //
+ // Built-in functions
+ //
+ case EFI_IFR_DUP_OP:
+ DepExpressionOpCode->DupExp.Operand = ExpressionOpCode->Operand;
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_EQ_ID_VAL_OP:
+ DepExpressionOpCode->EqIdValExp.Operand = ExpressionOpCode->Operand;
+ CopyMem (&DepExpressionOpCode->EqIdValExp.QuestionId, &ExpressionOpCode->ExtraData.EqIdValData.QuestionId, sizeof (EFI_QUESTION_ID));
+ CopyMem (&DepExpressionOpCode->EqIdValExp.Value, &ExpressionOpCode->ExtraData.EqIdValData.Value, sizeof (EFI_HII_VALUE));
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_EQ_ID_ID_OP:
+ DepExpressionOpCode->EqIdIdExp.Operand = ExpressionOpCode->Operand;
+ CopyMem (&DepExpressionOpCode->EqIdIdExp.QuestionId1, &ExpressionOpCode->ExtraData.EqIdIdData.QuestionId1, sizeof (EFI_QUESTION_ID));
+ CopyMem (&DepExpressionOpCode->EqIdIdExp.QuestionId2, &ExpressionOpCode->ExtraData.EqIdIdData.QuestionId2, sizeof (EFI_QUESTION_ID));
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_EQ_ID_VAL_LIST_OP:
+ DepExpressionOpCode->EqIdListExp.Operand = ExpressionOpCode->Operand;
+ DepExpressionOpCode->EqIdListExp.ListLength = ExpressionOpCode->ExtraData.EqIdListData.ListLength;
+ CopyMem (&DepExpressionOpCode->EqIdListExp.QuestionId, &ExpressionOpCode->ExtraData.EqIdListData.QuestionId, sizeof (EFI_QUESTION_ID));
+ PushDependencyExpDes (&DepExpressionOpCode);
+ DepExpressionOpCode->EqIdListExp.ValueList = AllocateCopyPool (
+ DepExpressionOpCode->EqIdListExp.ListLength * sizeof (UINT16),
+ ExpressionOpCode->ExtraData.EqIdListData.ValueList
+ );
+ if (DepExpressionOpCode->EqIdListExp.ValueList == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_GET_OP:
+ DepExpressionOpCode->GetExp.Operand = ExpressionOpCode->Operand;
+ DepExpressionOpCode->GetExp.VarStorage = ExpressionOpCode->ExtraData.GetSetData.VarStorage;
+ CopyMem (&DepExpressionOpCode->GetExp.VarStoreInfo.VarName, &ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo.VarName, sizeof (EFI_STRING_ID));
+ CopyMem (&DepExpressionOpCode->GetExp.VarStoreInfo.VarOffset, &ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset, sizeof (UINT16));
+ DepExpressionOpCode->GetExp.VarStoreInfo = ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo;
+ if (ExpressionOpCode->ExtraData.GetSetData.ValueName != NULL) {
+ DepExpressionOpCode->GetExp.ValueName = (CHAR16 *)AllocateCopyPool (sizeof (ExpressionOpCode->ExtraData.GetSetData.ValueName), ExpressionOpCode->ExtraData.GetSetData.ValueName);
+ if (DepExpressionOpCode->GetExp.ValueName == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ DepExpressionOpCode->GetExp.ValueType = ExpressionOpCode->ExtraData.GetSetData.ValueType;
+ DepExpressionOpCode->GetExp.ValueWidth = ExpressionOpCode->ExtraData.GetSetData.ValueWidth;
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_QUESTION_REF1_OP:
+ DepExpressionOpCode->QuestionRef1Exp.Operand = ExpressionOpCode->Operand;
+ CopyMem (&DepExpressionOpCode->QuestionRef1Exp.QuestionId, &ExpressionOpCode->ExtraData.QuestionRef1Data.QuestionId, sizeof (EFI_QUESTION_ID));
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_RULE_REF_OP:
+ DepExpressionOpCode->RuleRefExp.Operand = ExpressionOpCode->Operand;
+ DepExpressionOpCode->RuleRefExp.RuleId = ExpressionOpCode->ExtraData.RuleId;
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_STRING_REF1_OP:
+ DepExpressionOpCode->StringRef1Exp.Operand = ExpressionOpCode->Operand;
+ CopyMem (&DepExpressionOpCode->StringRef1Exp.Value.Value.string, &ExpressionOpCode->ExtraData.Value.Value.string, sizeof (EFI_STRING_ID));
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_THIS_OP:
+ DepExpressionOpCode->ThisExp.Operand = ExpressionOpCode->Operand;
+ CopyMem (&DepExpressionOpCode->ThisExp.QuestionId, &ExpressionOpCode->ExtraData.QuestionRef1Data.QuestionId, sizeof (EFI_QUESTION_ID));
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_SECURITY_OP:
+ DepExpressionOpCode->SecurityExp.Operand = ExpressionOpCode->Operand;
+ CopyMem (&DepExpressionOpCode->SecurityExp.Permissions, &ExpressionOpCode->ExtraData.Guid, sizeof (EFI_GUID));
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ //
+ // unary-op
+ //
+ case EFI_IFR_LENGTH_OP:
+ DepExpressionOpCode->LengthExp.Operand = ExpressionOpCode->Operand;
+ PopDependencyExpDes (&DepExpressionOpCode->LengthExp.SubExpression);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_NOT_OP:
+ DepExpressionOpCode->NotExp.Operand = ExpressionOpCode->Operand;
+ PopDependencyExpDes (&DepExpressionOpCode->NotExp.SubExpression);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_BITWISE_NOT_OP:
+ DepExpressionOpCode->BitWiseNotExp.Operand = ExpressionOpCode->Operand;
+ PopDependencyExpDes (&DepExpressionOpCode->BitWiseNotExp.SubExpression);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_QUESTION_REF2_OP:
+ DepExpressionOpCode->QuestionRef2Exp.Operand = ExpressionOpCode->Operand;
+ PopDependencyExpDes (&DepExpressionOpCode->QuestionRef2Exp.SubExpression);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_QUESTION_REF3_OP:
+ DepExpressionOpCode->QuestionRef3Exp.Operand = ExpressionOpCode->Operand;
+ CopyMem (&DepExpressionOpCode->QuestionRef3Exp.DevicePath, &ExpressionOpCode->ExtraData.QuestionRef3Data.DevicePath, sizeof (EFI_DEVICE_PATH));
+ CopyMem (&DepExpressionOpCode->QuestionRef3Exp.Guid, &ExpressionOpCode->ExtraData.QuestionRef3Data.Guid, sizeof (EFI_GUID));
+ PopDependencyExpDes (&DepExpressionOpCode->QuestionRef3Exp.SubExpression);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_SET_OP:
+ DepExpressionOpCode->SetExp.Operand = ExpressionOpCode->Operand;
+ DepExpressionOpCode->SetExp.VarStorage = ExpressionOpCode->ExtraData.GetSetData.VarStorage;
+ CopyMem (&DepExpressionOpCode->SetExp.VarStoreInfo.VarName, &ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo.VarName, sizeof (EFI_STRING_ID));
+ CopyMem (&DepExpressionOpCode->SetExp.VarStoreInfo.VarOffset, &ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset, sizeof (UINT16));
+ DepExpressionOpCode->SetExp.VarStoreInfo = ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo;
+ if (ExpressionOpCode->ExtraData.GetSetData.ValueName != NULL) {
+ DepExpressionOpCode->SetExp.ValueName = (CHAR16 *)AllocateCopyPool (sizeof (ExpressionOpCode->ExtraData.GetSetData.ValueName), ExpressionOpCode->ExtraData.GetSetData.ValueName);
+ if (DepExpressionOpCode->SetExp.ValueName == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ DepExpressionOpCode->SetExp.ValueType = ExpressionOpCode->ExtraData.GetSetData.ValueType;
+ DepExpressionOpCode->SetExp.ValueWidth = ExpressionOpCode->ExtraData.GetSetData.ValueWidth;
+ PopDependencyExpDes (&DepExpressionOpCode->SetExp.SubExpression);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_STRING_REF2_OP:
+ DepExpressionOpCode->StringRef2Exp.Operand = ExpressionOpCode->Operand;
+ PopDependencyExpDes (&DepExpressionOpCode->StringRef2Exp.SubExpression);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_TO_BOOLEAN_OP:
+ DepExpressionOpCode->ToBooleanExp.Operand = ExpressionOpCode->Operand;
+ PopDependencyExpDes (&DepExpressionOpCode->ToBooleanExp.SubExpression);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_TO_STRING_OP:
+ DepExpressionOpCode->ToStringExp.Operand = ExpressionOpCode->Operand;
+ DepExpressionOpCode->ToStringExp.Format = ExpressionOpCode->ExtraData.Format;
+ PopDependencyExpDes (&DepExpressionOpCode->ToStringExp.SubExpression);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_TO_UINT_OP:
+ DepExpressionOpCode->ToUintExp.Operand = ExpressionOpCode->Operand;
+ PopDependencyExpDes (&DepExpressionOpCode->ToUintExp.SubExpression);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_TO_LOWER_OP:
+ DepExpressionOpCode->ToLowerExp.Operand = ExpressionOpCode->Operand;
+ PopDependencyExpDes (&DepExpressionOpCode->ToLowerExp.SubExpression);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_TO_UPPER_OP:
+ DepExpressionOpCode->ToUpperExp.Operand = ExpressionOpCode->Operand;
+ PopDependencyExpDes (&DepExpressionOpCode->ToUpperExp.SubExpression);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ //
+ // binary-op
+ //
+ case EFI_IFR_ADD_OP:
+ DepExpressionOpCode->AddExp.Operand = ExpressionOpCode->Operand;
+ PopDependencyExpDes (&DepExpressionOpCode->AddExp.LeftHandExp);
+ PopDependencyExpDes (&DepExpressionOpCode->AddExp.RightHandExp);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_AND_OP:
+ DepExpressionOpCode->AndExp.Operand = ExpressionOpCode->Operand;
+ PopDependencyExpDes (&DepExpressionOpCode->AndExp.SubExpression1);
+ PopDependencyExpDes (&DepExpressionOpCode->AndExp.SubExpression2);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_BITWISE_AND_OP:
+ DepExpressionOpCode->BitwiseAndExp.Operand = ExpressionOpCode->Operand;
+ PopDependencyExpDes (&DepExpressionOpCode->BitwiseAndExp.SubExpression1);
+ PopDependencyExpDes (&DepExpressionOpCode->BitwiseAndExp.SubExpression2);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_BITWISE_OR_OP:
+ DepExpressionOpCode->BitwiseOrExp.Operand = ExpressionOpCode->Operand;
+ PopDependencyExpDes (&DepExpressionOpCode->BitwiseOrExp.SubExpression1);
+ PopDependencyExpDes (&DepExpressionOpCode->BitwiseOrExp.SubExpression2);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_CATENATE_OP:
+ DepExpressionOpCode->CatenateExp.Operand = ExpressionOpCode->Operand;
+ PopDependencyExpDes (&DepExpressionOpCode->CatenateExp.LeftStringExp);
+ PopDependencyExpDes (&DepExpressionOpCode->CatenateExp.RightStringExp);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_DIVIDE_OP:
+ DepExpressionOpCode->DivExp.Operand = ExpressionOpCode->Operand;
+ PopDependencyExpDes (&DepExpressionOpCode->DivExp.LeftHandExp);
+ PopDependencyExpDes (&DepExpressionOpCode->DivExp.RightHandExp);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_EQUAL_OP:
+ DepExpressionOpCode->EqualExp.Operand = ExpressionOpCode->Operand;
+ PopDependencyExpDes (&DepExpressionOpCode->EqualExp.SubExpression1);
+ PopDependencyExpDes (&DepExpressionOpCode->EqualExp.SubExpression2);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_GREATER_EQUAL_OP:
+ DepExpressionOpCode->GreaterEqualExp.Operand = ExpressionOpCode->Operand;
+ PopDependencyExpDes (&DepExpressionOpCode->GreaterEqualExp.LeftHandExp);
+ PopDependencyExpDes (&DepExpressionOpCode->GreaterEqualExp.RightHandExp);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_GREATER_THAN_OP:
+ DepExpressionOpCode->GreaterThanExp.Operand = ExpressionOpCode->Operand;
+ PopDependencyExpDes (&DepExpressionOpCode->GreaterThanExp.LeftHandExp);
+ PopDependencyExpDes (&DepExpressionOpCode->GreaterThanExp.RightHandExp);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_LESS_EQUAL_OP:
+ DepExpressionOpCode->LessEqualExp.Operand = ExpressionOpCode->Operand;
+ PopDependencyExpDes (&DepExpressionOpCode->LessEqualExp.LeftHandExp);
+ PopDependencyExpDes (&DepExpressionOpCode->LessEqualExp.RightHandExp);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_LESS_THAN_OP:
+ DepExpressionOpCode->LessThanExp.Operand = ExpressionOpCode->Operand;
+ PopDependencyExpDes (&DepExpressionOpCode->LessThanExp.LeftHandExp);
+ PopDependencyExpDes (&DepExpressionOpCode->LessThanExp.RightHandExp);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_MATCH_OP:
+ DepExpressionOpCode->MatchExp.Operand = ExpressionOpCode->Operand;
+ PopDependencyExpDes (&DepExpressionOpCode->MatchExp.PatternExp);
+ PopDependencyExpDes (&DepExpressionOpCode->MatchExp.StringExp);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_MATCH2_OP:
+ DepExpressionOpCode->Match2Exp.Operand = ExpressionOpCode->Operand;
+ CopyMem (&DepExpressionOpCode->Match2Exp.SyntaxType, &ExpressionOpCode->ExtraData.Guid, sizeof (EFI_GUID));
+ PopDependencyExpDes (&DepExpressionOpCode->Match2Exp.PatternExp);
+ PopDependencyExpDes (&DepExpressionOpCode->Match2Exp.StringExp);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_MODULO_OP:
+ DepExpressionOpCode->ModExp.Operand = ExpressionOpCode->Operand;
+ PopDependencyExpDes (&DepExpressionOpCode->ModExp.LeftHandExp);
+ PopDependencyExpDes (&DepExpressionOpCode->ModExp.RightHandExp);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_MULTIPLY_OP:
+ DepExpressionOpCode->MultExp.Operand = ExpressionOpCode->Operand;
+ PopDependencyExpDes (&DepExpressionOpCode->MultExp.LeftHandExp);
+ PopDependencyExpDes (&DepExpressionOpCode->MultExp.RightHandExp);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_NOT_EQUAL_OP:
+ DepExpressionOpCode->NotEqualExp.Operand = ExpressionOpCode->Operand;
+ PopDependencyExpDes (&DepExpressionOpCode->NotEqualExp.SubExpression1);
+ PopDependencyExpDes (&DepExpressionOpCode->NotEqualExp.SubExpression2);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_OR_OP:
+ DepExpressionOpCode->OrExp.Operand = ExpressionOpCode->Operand;
+ PopDependencyExpDes (&DepExpressionOpCode->OrExp.SubExpression1);
+ PopDependencyExpDes (&DepExpressionOpCode->OrExp.SubExpression2);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_SHIFT_LEFT_OP:
+ DepExpressionOpCode->ShiftLeftExp.Operand = ExpressionOpCode->Operand;
+ PopDependencyExpDes (&DepExpressionOpCode->ShiftLeftExp.LeftHandExp);
+ PopDependencyExpDes (&DepExpressionOpCode->ShiftLeftExp.RightHandExp);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_SHIFT_RIGHT_OP:
+ DepExpressionOpCode->ShiftRightExp.Operand = ExpressionOpCode->Operand;
+ PopDependencyExpDes (&DepExpressionOpCode->ShiftRightExp.LeftHandExp);
+ PopDependencyExpDes (&DepExpressionOpCode->ShiftRightExp.RightHandExp);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_SUBTRACT_OP:
+ DepExpressionOpCode->SubtractExp.Operand = ExpressionOpCode->Operand;
+ PopDependencyExpDes (&DepExpressionOpCode->SubtractExp.LeftHandExp);
+ PopDependencyExpDes (&DepExpressionOpCode->SubtractExp.RightHandExp);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ //
+ // ternary-op
+ //
+ case EFI_IFR_CONDITIONAL_OP:
+ DepExpressionOpCode->ConditionalExp.Operand = ExpressionOpCode->Operand;
+ PopDependencyExpDes (&DepExpressionOpCode->ConditionalExp.CondTrueValExp);
+ PopDependencyExpDes (&DepExpressionOpCode->ConditionalExp.CondFalseValExp);
+ PopDependencyExpDes (&DepExpressionOpCode->ConditionalExp.ConditionExp);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_FIND_OP:
+ DepExpressionOpCode->FindExp.Operand = ExpressionOpCode->Operand;
+ PopDependencyExpDes (&DepExpressionOpCode->FindExp.StringToSearchExp);
+ PopDependencyExpDes (&DepExpressionOpCode->FindExp.StringToCompWithExp);
+ PopDependencyExpDes (&DepExpressionOpCode->FindExp.IndexExp);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_MID_OP:
+ DepExpressionOpCode->MidExp.Operand = ExpressionOpCode->Operand;
+ PopDependencyExpDes (&DepExpressionOpCode->MidExp.StringOrBufferExp);
+ PopDependencyExpDes (&DepExpressionOpCode->MidExp.IndexExp);
+ PopDependencyExpDes (&DepExpressionOpCode->MidExp.LengthExp);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_TOKEN_OP:
+ DepExpressionOpCode->TokenExp.Operand = ExpressionOpCode->Operand;
+ PopDependencyExpDes (&DepExpressionOpCode->TokenExp.StringToSearchExp);
+ PopDependencyExpDes (&DepExpressionOpCode->TokenExp.DelimiterExp);
+ PopDependencyExpDes (&DepExpressionOpCode->TokenExp.IndexExp);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ case EFI_IFR_SPAN_OP:
+ DepExpressionOpCode->SpanExp.Operand = ExpressionOpCode->Operand;
+ PopDependencyExpDes (&DepExpressionOpCode->SpanExp.StringToSearchExp);
+ PopDependencyExpDes (&DepExpressionOpCode->SpanExp.CharsetExp);
+ PopDependencyExpDes (&DepExpressionOpCode->SpanExp.IndexExp);
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ //
+ // Map
+ //
+ case EFI_IFR_MAP_OP:
+ //
+ // Go through map expression list.
+ //
+ DepExpressionOpCode->MapExp.Operand = ExpressionOpCode->Operand;
+ MapPairCount = 0;
+ SubExpressionLink = GetFirstNode (&ExpressionOpCode->MapExpressionList);
+ while (!IsNull (&ExpressionOpCode->MapExpressionList, SubExpressionLink)) {
+ MapPairCount++;
+ SubExpressionLink = GetNextNode (&ExpressionOpCode->MapExpressionList, SubExpressionLink);
+ if (IsNull (&ExpressionOpCode->MapExpressionList, SubExpressionLink)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ //
+ // Goto the first expression on next pair.
+ //
+ SubExpressionLink = GetNextNode (&ExpressionOpCode->MapExpressionList, SubExpressionLink);
+ }
+
+ DepExpressionOpCode->MapExp.ExpPair = (HII_DEPENDENCY_EXPRESSION_PAIR *)AllocateZeroPool (
+ MapPairCount * sizeof (HII_DEPENDENCY_EXPRESSION_PAIR)
+ );
+ if (DepExpressionOpCode->MapExp.ExpPair == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ DepExpressionOpCode->MapExp.ExpPairNo = MapPairCount;
+ MapPairCount = 0;
+ PopDependencyExpDes (&DepExpressionOpCode->MapExp.SubExp);
+
+ //
+ // Go through map expression list.
+ //
+ SubExpressionLink = GetFirstNode (&ExpressionOpCode->MapExpressionList);
+ while (!IsNull (&ExpressionOpCode->MapExpressionList, SubExpressionLink)) {
+ SubExpression = HII_EXPRESSION_FROM_LINK (SubExpressionLink);
+ //
+ // Get the first expression description in this pair.
+ //
+ GetHiiExpressionDependency (SubExpression);
+ DepExpressionOpCode->MapExp.ExpPair[MapPairCount].MatchExp = SubExpression->RootDependencyExp;
+
+ //
+ // Get the second expression description in this pair.
+ //
+ SubExpressionLink = GetNextNode (&ExpressionOpCode->MapExpressionList, SubExpressionLink);
+ SubExpression = HII_EXPRESSION_FROM_LINK (SubExpressionLink);
+ GetHiiExpressionDependency (SubExpression);
+ DepExpressionOpCode->MapExp.ExpPair[MapPairCount].ReturnExp = SubExpression->RootDependencyExp;
+ //
+ // Goto the first expression on next pair.
+ //
+ SubExpressionLink = GetNextNode (&ExpressionOpCode->MapExpressionList, SubExpressionLink);
+ MapPairCount++;
+ }
+
+ PushDependencyExpDes (&DepExpressionOpCode);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ PopDependencyExpDes (&Expression->RootDependencyExp);
+
+Done:
+ return Status;
+}
+
+/**
+ Return the result of the expression list. Check the expression list and
+ return the highest priority express result.
+ Priority: DisableIf > SuppressIf > GrayOutIf > FALSE
+
+ @param[in] ExpList The input expression list.
+ @param[in] Evaluate Whether need to evaluate the expression first.
+ @param[in] FormSet FormSet associated with this expression.
+ @param[in] Form Form associated with this expression.
+
+ @retval EXPRESS_RESULT Return the higher priority express result.
+ DisableIf > SuppressIf > GrayOutIf > FALSE
+
+**/
+EXPRESS_RESULT
+EvaluateExpressionList (
+ IN HII_EXPRESSION_LIST *ExpList,
+ IN BOOLEAN Evaluate,
+ IN HII_FORMSET *FormSet OPTIONAL,
+ IN HII_FORM *Form OPTIONAL
+ )
+{
+ UINTN Index;
+ EXPRESS_RESULT ReturnVal;
+ EXPRESS_RESULT CompareOne;
+ EFI_STATUS Status;
+
+ if (ExpList == NULL) {
+ return ExpressFalse;
+ }
+
+ ASSERT (ExpList->Signature == HII_EXPRESSION_LIST_SIGNATURE);
+ Index = 0;
+
+ //
+ // Check whether need to evaluate the expression first.
+ //
+ if (Evaluate) {
+ while (ExpList->Count > Index) {
+ Status = EvaluateHiiExpression (FormSet, Form, ExpList->Expression[Index++]);
+ if (EFI_ERROR (Status)) {
+ return ExpressFalse;
+ }
+ }
+ }
+
+ //
+ // Run the list of expressions.
+ //
+ ReturnVal = ExpressFalse;
+ for (Index = 0; Index < ExpList->Count; Index++) {
+ if (IsHiiValueTrue (&ExpList->Expression[Index]->Result)) {
+ switch (ExpList->Expression[Index]->Type) {
+ case EFI_HII_EXPRESSION_SUPPRESS_IF:
+ CompareOne = ExpressSuppress;
+ break;
+
+ case EFI_HII_EXPRESSION_GRAY_OUT_IF:
+ CompareOne = ExpressGrayOut;
+ break;
+
+ case EFI_HII_EXPRESSION_DISABLE_IF:
+ CompareOne = ExpressDisable;
+ break;
+
+ default:
+ return ExpressFalse;
+ }
+
+ ReturnVal = ReturnVal < CompareOne ? CompareOne : ReturnVal;
+ }
+ }
+
+ return ReturnVal;
+}
diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiIfrParse.c b/RedfishPkg/Library/HiiUtilityLib/HiiIfrParse.c
new file mode 100644
index 000000000000..a51d7b9c6d24
--- /dev/null
+++ b/RedfishPkg/Library/HiiUtilityLib/HiiIfrParse.c
@@ -0,0 +1,2715 @@
+/** @file
+ The implementation of HII IFR parser.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+ Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "HiiInternal.h"
+
+/**
+ Initialize Statement header members.
+
+ @param[in] OpCodeData Pointer of the raw OpCode data.
+ @param[in,out] FormSet Pointer of the current FormSet.
+ @param[in,out] Form Pointer of the current Form.
+
+ @return The Statement.
+
+**/
+HII_STATEMENT *
+CreateStatement (
+ IN UINT8 *OpCodeData,
+ IN OUT HII_FORMSET *FormSet,
+ IN OUT HII_FORM *Form
+ )
+{
+ HII_STATEMENT *Statement;
+ EFI_IFR_STATEMENT_HEADER *StatementHdr;
+ INTN ConditionalExprCount;
+
+ if (Form == NULL) {
+ //
+ // Only guid op may out side the form level.
+ //
+ if (((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode != EFI_IFR_GUID_OP) {
+ return NULL;
+ }
+ }
+
+ Statement = (HII_STATEMENT *)AllocateZeroPool (sizeof (HII_STATEMENT));
+ if (Statement == NULL) {
+ return NULL;
+ }
+
+ InitializeListHead (&Statement->DefaultListHead);
+ InitializeListHead (&Statement->OptionListHead);
+ InitializeListHead (&Statement->InconsistentListHead);
+ InitializeListHead (&Statement->NoSubmitListHead);
+ InitializeListHead (&Statement->WarningListHead);
+
+ Statement->Signature = HII_STATEMENT_SIGNATURE;
+ Statement->Operand = ((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode;
+ Statement->OpCode = (EFI_IFR_OP_HEADER *)OpCodeData;
+ Statement->QuestionReferToBitField = FALSE;
+
+ StatementHdr = (EFI_IFR_STATEMENT_HEADER *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER));
+ CopyMem (&Statement->Prompt, &StatementHdr->Prompt, sizeof (EFI_STRING_ID));
+ CopyMem (&Statement->Help, &StatementHdr->Help, sizeof (EFI_STRING_ID));
+
+ ConditionalExprCount = GetConditionalExpressionCount (ExpressStatement);
+ if (ConditionalExprCount > 0) {
+ //
+ // Form is inside of suppressif
+ //
+ Statement->ExpressionList = (HII_EXPRESSION_LIST *)AllocatePool (
+ (UINTN)(sizeof (HII_EXPRESSION_LIST) + ((ConditionalExprCount - 1) * sizeof (HII_EXPRESSION *)))
+ );
+ if (Statement->ExpressionList == NULL) {
+ return NULL;
+ }
+
+ Statement->ExpressionList->Count = (UINTN)ConditionalExprCount;
+ Statement->ExpressionList->Signature = HII_EXPRESSION_LIST_SIGNATURE;
+ CopyMem (
+ Statement->ExpressionList->Expression,
+ GetConditionalExpressionList (ExpressStatement),
+ (UINTN)(sizeof (HII_EXPRESSION *) * ConditionalExprCount)
+ );
+ }
+
+ //
+ // Insert this Statement into current Form
+ //
+ if (Form == NULL) {
+ InsertTailList (&FormSet->StatementListOSF, &Statement->Link);
+ } else {
+ InsertTailList (&Form->StatementListHead, &Statement->Link);
+ }
+
+ return Statement;
+}
+
+/**
+ Initialize Question's members.
+
+ @param[in] OpCodeData Pointer of the raw OpCode data.
+ @param[in,out] FormSet Pointer of the current FormSet.
+ @param[in,out] Form Pointer of the current Form.
+
+ @return The Question.
+
+**/
+HII_STATEMENT *
+CreateQuestion (
+ IN UINT8 *OpCodeData,
+ IN OUT HII_FORMSET *FormSet,
+ IN OUT HII_FORM *Form
+ )
+{
+ HII_STATEMENT *Statement;
+ EFI_IFR_QUESTION_HEADER *QuestionHdr;
+ LIST_ENTRY *Link;
+ HII_FORMSET_STORAGE *Storage;
+ HII_NAME_VALUE_NODE *NameValueNode;
+ BOOLEAN Find;
+
+ Statement = CreateStatement (OpCodeData, FormSet, Form);
+ if (Statement == NULL) {
+ return NULL;
+ }
+
+ QuestionHdr = (EFI_IFR_QUESTION_HEADER *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER));
+ CopyMem (&Statement->QuestionId, &QuestionHdr->QuestionId, sizeof (EFI_QUESTION_ID));
+ CopyMem (&Statement->VarStoreId, &QuestionHdr->VarStoreId, sizeof (EFI_VARSTORE_ID));
+ CopyMem (&Statement->VarStoreInfo.VarOffset, &QuestionHdr->VarStoreInfo.VarOffset, sizeof (UINT16));
+
+ Statement->QuestionFlags = QuestionHdr->Flags;
+
+ if (Statement->VarStoreId == 0) {
+ //
+ // VarStoreId of zero indicates no variable storage
+ //
+ return Statement;
+ }
+
+ //
+ // Find Storage for this Question
+ //
+ Link = GetFirstNode (&FormSet->StorageListHead);
+ while (!IsNull (&FormSet->StorageListHead, Link)) {
+ Storage = HII_STORAGE_FROM_LINK (Link);
+
+ if (Statement->VarStoreId == Storage->VarStoreId) {
+ Statement->Storage = Storage;
+ break;
+ }
+
+ Link = GetNextNode (&FormSet->StorageListHead, Link);
+ }
+
+ if (Statement->Storage == NULL) {
+ return NULL;
+ }
+
+ //
+ // Initialize varname for Name/Value or EFI Variable
+ //
+ if ((Statement->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) ||
+ (Statement->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE))
+ {
+ Statement->VariableName = GetTokenString (Statement->VarStoreInfo.VarName, FormSet->HiiHandle);
+ if (Statement->VariableName == NULL) {
+ return NULL;
+ }
+
+ if (Statement->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
+ //
+ // Check whether old string node already exist.
+ //
+ Find = FALSE;
+ if (!IsListEmpty (&Statement->Storage->NameValueList)) {
+ Link = GetFirstNode (&Statement->Storage->NameValueList);
+ while (!IsNull (&Statement->Storage->NameValueList, Link)) {
+ NameValueNode = HII_NAME_VALUE_NODE_FROM_LINK (Link);
+
+ if (StrCmp (Statement->VariableName, NameValueNode->Name) == 0) {
+ Find = TRUE;
+ break;
+ }
+
+ Link = GetNextNode (&Statement->Storage->NameValueList, Link);
+ }
+ }
+
+ if (!Find) {
+ //
+ // Insert to Name/Value varstore list
+ //
+ NameValueNode = AllocateZeroPool (sizeof (HII_NAME_VALUE_NODE));
+ if (NameValueNode == NULL) {
+ return NULL;
+ }
+
+ NameValueNode->Signature = HII_NAME_VALUE_NODE_SIGNATURE;
+ NameValueNode->Name = AllocateCopyPool (StrSize (Statement->VariableName), Statement->VariableName);
+ if (NameValueNode->Name == NULL) {
+ FreePool (NameValueNode);
+ return NULL;
+ }
+
+ NameValueNode->Value = AllocateZeroPool (0x10);
+ if (NameValueNode->Value == NULL) {
+ FreePool (NameValueNode->Name);
+ FreePool (NameValueNode);
+ return NULL;
+ }
+
+ InsertTailList (&Statement->Storage->NameValueList, &NameValueNode->Link);
+ }
+ }
+ }
+
+ return Statement;
+}
+
+/**
+ Allocate a HII_EXPRESSION node.
+
+ @param[in,out] Form The Form associated with this Expression
+ @param[in] OpCode The binary opcode data.
+
+ @return Pointer to a HII_EXPRESSION data structure.
+
+**/
+HII_EXPRESSION *
+CreateExpression (
+ IN OUT HII_FORM *Form,
+ IN UINT8 *OpCode
+ )
+{
+ HII_EXPRESSION *Expression;
+
+ Expression = AllocateZeroPool (sizeof (HII_EXPRESSION));
+ if (Expression == NULL) {
+ return NULL;
+ }
+
+ Expression->Signature = HII_EXPRESSION_SIGNATURE;
+ InitializeListHead (&Expression->OpCodeListHead);
+ Expression->OpCode = (EFI_IFR_OP_HEADER *)OpCode;
+
+ return Expression;
+}
+
+/**
+ Create ConfigHdr string for a storage.
+
+ @param[in] FormSet Pointer of the current FormSet
+ @param[in,out] Storage Pointer of the storage
+
+ @retval EFI_SUCCESS Initialize ConfigHdr success
+
+**/
+EFI_STATUS
+InitializeConfigHdr (
+ IN HII_FORMSET *FormSet,
+ IN OUT HII_FORMSET_STORAGE *Storage
+ )
+{
+ CHAR16 *Name;
+
+ if ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ||
+ (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER))
+ {
+ Name = Storage->Name;
+ } else {
+ Name = NULL;
+ }
+
+ Storage->ConfigHdr = HiiConstructConfigHdr (
+ &Storage->Guid,
+ Name,
+ FormSet->DriverHandle
+ );
+
+ if (Storage->ConfigHdr == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Convert Ascii string to Unicode.
+
+ This is an internal function.
+
+ @param[in] AsciiString The Ascii string to be converted.
+ @param[out] UnicodeString The Unicode string retrieved.
+
+**/
+VOID
+AsciiToUnicode (
+ IN CHAR8 *AsciiString,
+ OUT CHAR16 *UnicodeString
+ )
+{
+ UINT8 Index;
+
+ Index = 0;
+ while (AsciiString[Index] != 0) {
+ UnicodeString[Index] = (CHAR16)AsciiString[Index];
+ Index++;
+ }
+
+ UnicodeString[Index] = L'\0';
+}
+
+/**
+ Allocate a HII_FORMSET_STORAGE data structure and insert to FormSet Storage List.
+
+ @param[in] FormSet Pointer of the current FormSet
+ @param[in] StorageType Storage type.
+ @param[in] OpCodeData Binary data for this opcode.
+
+ @return Pointer to a HII_FORMSET_STORAGE data structure.
+
+**/
+HII_FORMSET_STORAGE *
+CreateStorage (
+ IN HII_FORMSET *FormSet,
+ IN UINT8 StorageType,
+ IN UINT8 *OpCodeData
+ )
+{
+ HII_FORMSET_STORAGE *Storage;
+ CHAR8 *AsciiStorageName;
+
+ AsciiStorageName = NULL;
+
+ Storage = AllocateZeroPool (sizeof (HII_FORMSET_STORAGE));
+ if (Storage == NULL) {
+ return NULL;
+ }
+
+ Storage->Signature = HII_STORAGE_SIGNATURE;
+ Storage->Type = StorageType;
+
+ switch (StorageType) {
+ case EFI_HII_VARSTORE_BUFFER:
+
+ CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE *)OpCodeData)->Guid, sizeof (EFI_GUID));
+ CopyMem (&Storage->Size, &((EFI_IFR_VARSTORE *)OpCodeData)->Size, sizeof (UINT16));
+
+ Storage->Buffer = AllocateZeroPool (Storage->Size);
+ if (Storage->Buffer == NULL) {
+ FreePool (Storage);
+ return NULL;
+ }
+
+ AsciiStorageName = (CHAR8 *)((EFI_IFR_VARSTORE *)OpCodeData)->Name;
+ Storage->Name = AllocatePool (sizeof (CHAR16) * (AsciiStrLen (AsciiStorageName) + 1));
+ if (Storage->Name == NULL) {
+ FreePool (Storage);
+ return NULL;
+ }
+
+ AsciiToUnicode (AsciiStorageName, Storage->Name);
+
+ break;
+
+ case EFI_HII_VARSTORE_EFI_VARIABLE:
+ case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
+ CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_EFI *)OpCodeData)->Guid, sizeof (EFI_GUID));
+ CopyMem (&Storage->Attributes, &((EFI_IFR_VARSTORE_EFI *)OpCodeData)->Attributes, sizeof (UINT32));
+ CopyMem (&Storage->Size, &((EFI_IFR_VARSTORE_EFI *)OpCodeData)->Size, sizeof (UINT16));
+
+ if (StorageType == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {
+ Storage->Buffer = AllocateZeroPool (Storage->Size);
+ if (Storage->Buffer == NULL) {
+ FreePool (Storage);
+ return NULL;
+ }
+ }
+
+ AsciiStorageName = (CHAR8 *)((EFI_IFR_VARSTORE_EFI *)OpCodeData)->Name;
+ Storage->Name = AllocatePool (sizeof (CHAR16) * (AsciiStrLen (AsciiStorageName) + 1));
+ if (Storage->Name == NULL) {
+ FreePool (Storage);
+ return NULL;
+ }
+
+ AsciiToUnicode (AsciiStorageName, Storage->Name);
+
+ break;
+
+ case EFI_HII_VARSTORE_NAME_VALUE:
+ CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_NAME_VALUE *)OpCodeData)->Guid, sizeof (EFI_GUID));
+ InitializeListHead (&Storage->NameValueList);
+
+ break;
+
+ default:
+ break;
+ }
+
+ InitializeConfigHdr (FormSet, Storage);
+ InsertTailList (&FormSet->StorageListHead, &Storage->Link);
+
+ return Storage;
+}
+
+/**
+ Get formset storage based on the input varstoreid info.
+
+ @param[in] FormSet Pointer of the current FormSet.
+ @param[in] VarStoreId Varstore ID info.
+
+ @return Pointer to a HII_FORMSET_STORAGE data structure.
+
+**/
+HII_FORMSET_STORAGE *
+GetFstStgFromVarId (
+ IN HII_FORMSET *FormSet,
+ IN EFI_VARSTORE_ID VarStoreId
+ )
+{
+ HII_FORMSET_STORAGE *Storage;
+ LIST_ENTRY *Link;
+ BOOLEAN Found;
+
+ Found = FALSE;
+ Storage = NULL;
+ //
+ // Find Formset Storage for this Question
+ //
+ Link = GetFirstNode (&FormSet->StorageListHead);
+ while (!IsNull (&FormSet->StorageListHead, Link)) {
+ Storage = HII_STORAGE_FROM_LINK (Link);
+
+ if (Storage->VarStoreId == VarStoreId) {
+ Found = TRUE;
+ break;
+ }
+
+ Link = GetNextNode (&FormSet->StorageListHead, Link);
+ }
+
+ return Found ? Storage : NULL;
+}
+
+/**
+ Initialize Request Element of a Question. <RequestElement> ::= '&'<BlockName> | '&'<Label>
+
+ @param[in,out] FormSet Pointer of the current FormSet.
+ @param[in,out] Question The Question to be initialized.
+ @param[in,out] Form Pointer of the current form.
+
+ @retval EFI_SUCCESS Function success.
+ @retval EFI_INVALID_PARAMETER No storage associated with the Question.
+
+**/
+EFI_STATUS
+InitializeRequestElement (
+ IN OUT HII_FORMSET *FormSet,
+ IN OUT HII_STATEMENT *Question,
+ IN OUT HII_FORM *Form
+ )
+{
+ HII_FORMSET_STORAGE *Storage;
+ HII_FORM_CONFIG_REQUEST *ConfigInfo;
+ UINTN StrLen;
+ UINTN StringSize;
+ CHAR16 *NewStr;
+ CHAR16 RequestElement[30];
+ LIST_ENTRY *Link;
+ BOOLEAN Find;
+ UINTN MaxLen;
+
+ Storage = Question->Storage;
+ if (Storage == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
+ //
+ // <ConfigRequest> is unnecessary for EFI variable storage,
+ // GetVariable()/SetVariable() will be used to retrieve/save values
+ //
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Prepare <RequestElement>
+ //
+ if ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ||
+ (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER))
+ {
+ StrLen = UnicodeSPrint (
+ RequestElement,
+ 30 * sizeof (CHAR16),
+ L"&OFFSET=%04x&WIDTH=%04x",
+ Question->VarStoreInfo.VarOffset,
+ Question->StorageWidth
+ );
+ HiiStringToLowercase (RequestElement);
+ Question->BlockName = AllocateCopyPool ((StrLen + 1) * sizeof (CHAR16), RequestElement);
+ if (Question->BlockName == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ } else {
+ StrLen = UnicodeSPrint (RequestElement, 30 * sizeof (CHAR16), L"&%s", Question->VariableName);
+ }
+
+ if ((Question->Operand == EFI_IFR_PASSWORD_OP) &&
+ ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK))
+ {
+ //
+ // Password with CALLBACK flag is stored in encoded format,
+ // so don't need to append it to <ConfigRequest>
+ //
+ return EFI_SUCCESS;
+ }
+
+ StringSize = (Storage->ConfigRequest != NULL) ? StrSize (Storage->ConfigRequest) : sizeof (CHAR16);
+ MaxLen = StringSize / sizeof (CHAR16) + Storage->SpareStrLen;
+
+ //
+ // Append <RequestElement> to <ConfigRequest>
+ //
+ if (StrLen > Storage->SpareStrLen) {
+ //
+ // Old String buffer is not sufficient for RequestElement, allocate a new one
+ //
+ MaxLen = StringSize / sizeof (CHAR16) + CONFIG_REQUEST_STRING_INCREMENTAL;
+ NewStr = AllocatePool (MaxLen * sizeof (CHAR16));
+ if (NewStr == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (Storage->ConfigRequest != NULL) {
+ CopyMem (NewStr, Storage->ConfigRequest, StringSize);
+ FreePool (Storage->ConfigRequest);
+ } else {
+ NewStr[0] = L'\0';
+ }
+
+ Storage->ConfigRequest = NewStr;
+ Storage->SpareStrLen = CONFIG_REQUEST_STRING_INCREMENTAL;
+ }
+
+ StrCatS (Storage->ConfigRequest, MaxLen, RequestElement);
+ Storage->ElementCount++;
+ Storage->SpareStrLen -= StrLen;
+
+ //
+ // Update the Config Request info saved in the form.
+ //
+ ConfigInfo = NULL;
+ Find = FALSE;
+ Link = GetFirstNode (&Form->ConfigRequestHead);
+ while (!IsNull (&Form->ConfigRequestHead, Link)) {
+ ConfigInfo = HII_FORM_CONFIG_REQUEST_FROM_LINK (Link);
+ if ((ConfigInfo != NULL) && (ConfigInfo->Storage == Storage)) {
+ Find = TRUE;
+ break;
+ }
+
+ Link = GetNextNode (&Form->ConfigRequestHead, Link);
+ }
+
+ if (!Find) {
+ ConfigInfo = AllocateZeroPool (sizeof (HII_FORM_CONFIG_REQUEST));
+ if (ConfigInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ConfigInfo->Signature = HII_FORM_CONFIG_REQUEST_SIGNATURE;
+ ConfigInfo->ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigHdr), Storage->ConfigHdr);
+ if (ConfigInfo->ConfigRequest == NULL) {
+ FreePool (ConfigInfo);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ConfigInfo->SpareStrLen = 0;
+ ConfigInfo->Storage = Storage;
+ InsertTailList (&Form->ConfigRequestHead, &ConfigInfo->Link);
+ }
+
+ StringSize = (ConfigInfo->ConfigRequest != NULL) ? StrSize (ConfigInfo->ConfigRequest) : sizeof (CHAR16);
+ MaxLen = StringSize / sizeof (CHAR16) + ConfigInfo->SpareStrLen;
+
+ //
+ // Append <RequestElement> to <ConfigRequest>
+ //
+ if (StrLen > ConfigInfo->SpareStrLen) {
+ //
+ // Old String buffer is not sufficient for RequestElement, allocate a new one
+ //
+ MaxLen = StringSize / sizeof (CHAR16) + CONFIG_REQUEST_STRING_INCREMENTAL;
+ NewStr = AllocatePool (MaxLen * sizeof (CHAR16));
+ if (NewStr == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (ConfigInfo->ConfigRequest != NULL) {
+ CopyMem (NewStr, ConfigInfo->ConfigRequest, StringSize);
+ FreePool (ConfigInfo->ConfigRequest);
+ } else {
+ NewStr[0] = L'\0';
+ }
+
+ ConfigInfo->ConfigRequest = NewStr;
+ ConfigInfo->SpareStrLen = CONFIG_REQUEST_STRING_INCREMENTAL;
+ }
+
+ StrCatS (ConfigInfo->ConfigRequest, MaxLen, RequestElement);
+ ConfigInfo->ElementCount++;
+ ConfigInfo->SpareStrLen -= StrLen;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Free resources of a Expression.
+
+ @param[in] FormSet Pointer of the Expression
+
+**/
+VOID
+DestroyExpression (
+ IN HII_EXPRESSION *Expression
+ )
+{
+ LIST_ENTRY *Link;
+ HII_EXPRESSION_OPCODE *OpCode;
+ LIST_ENTRY *SubExpressionLink;
+ HII_EXPRESSION *SubExpression;
+
+ while (!IsListEmpty (&Expression->OpCodeListHead)) {
+ Link = GetFirstNode (&Expression->OpCodeListHead);
+ OpCode = HII_EXPRESSION_OPCODE_FROM_LINK (Link);
+
+ RemoveEntryList (&OpCode->Link);
+ if ((OpCode->Operand == EFI_IFR_EQ_ID_VAL_LIST_OP) && (OpCode->ExtraData.EqIdListData.ValueList != NULL)) {
+ FreePool (OpCode->ExtraData.EqIdListData.ValueList);
+ }
+
+ if (((OpCode->Operand == EFI_IFR_GET_OP) || (OpCode->Operand == EFI_IFR_SET_OP)) &&
+ (OpCode->ExtraData.GetSetData.ValueName != NULL))
+ {
+ FreePool (OpCode->ExtraData.GetSetData.ValueName);
+ }
+
+ if (OpCode->MapExpressionList.ForwardLink != NULL) {
+ while (!IsListEmpty (&OpCode->MapExpressionList)) {
+ SubExpressionLink = GetFirstNode (&OpCode->MapExpressionList);
+ SubExpression = HII_EXPRESSION_FROM_LINK (SubExpressionLink);
+ RemoveEntryList (&SubExpression->Link);
+ DestroyExpression (SubExpression);
+ }
+ }
+ }
+
+ //
+ // Free this Expression
+ //
+ FreePool (Expression);
+}
+
+/**
+ Delete a string from HII Package List.
+
+ @param[in] StringId Id of the string in HII database.
+ @param[in] HiiHandle The HII package list handle.
+
+ @retval EFI_SUCCESS The string was deleted successfully.
+
+**/
+EFI_STATUS
+DeleteString (
+ IN EFI_STRING_ID StringId,
+ IN EFI_HII_HANDLE HiiHandle
+ )
+{
+ CHAR16 NullChar;
+
+ NullChar = CHAR_NULL;
+ HiiSetString (HiiHandle, StringId, &NullChar, NULL);
+ return EFI_SUCCESS;
+}
+
+/**
+ Free resources of a Statement.
+
+ @param[in] FormSet Pointer of the FormSet
+ @param[in,out] Statement Pointer of the Statement
+
+**/
+VOID
+DestroyStatement (
+ IN HII_FORMSET *FormSet,
+ IN OUT HII_STATEMENT *Statement
+ )
+{
+ LIST_ENTRY *Link;
+ HII_QUESTION_DEFAULT *Default;
+ HII_QUESTION_OPTION *Option;
+ HII_EXPRESSION *Expression;
+
+ //
+ // Free Default value List
+ //
+ while (!IsListEmpty (&Statement->DefaultListHead)) {
+ Link = GetFirstNode (&Statement->DefaultListHead);
+ Default = HII_QUESTION_DEFAULT_FROM_LINK (Link);
+ RemoveEntryList (&Default->Link);
+
+ if (Default->Value.Buffer != NULL) {
+ FreePool (Default->Value.Buffer);
+ }
+
+ FreePool (Default);
+ }
+
+ //
+ // Free Options List
+ //
+ while (!IsListEmpty (&Statement->OptionListHead)) {
+ Link = GetFirstNode (&Statement->OptionListHead);
+ Option = HII_QUESTION_OPTION_FROM_LINK (Link);
+
+ if (Option->SuppressExpression != NULL) {
+ FreePool (Option->SuppressExpression);
+ }
+
+ RemoveEntryList (&Option->Link);
+
+ FreePool (Option);
+ }
+
+ //
+ // Free Inconsistent List
+ //
+ while (!IsListEmpty (&Statement->InconsistentListHead)) {
+ Link = GetFirstNode (&Statement->InconsistentListHead);
+ Expression = HII_EXPRESSION_FROM_LINK (Link);
+ RemoveEntryList (&Expression->Link);
+
+ DestroyExpression (Expression);
+ }
+
+ //
+ // Free NoSubmit List
+ //
+ while (!IsListEmpty (&Statement->NoSubmitListHead)) {
+ Link = GetFirstNode (&Statement->NoSubmitListHead);
+ Expression = HII_EXPRESSION_FROM_LINK (Link);
+ RemoveEntryList (&Expression->Link);
+
+ DestroyExpression (Expression);
+ }
+
+ //
+ // Free WarningIf List
+ //
+ while (!IsListEmpty (&Statement->WarningListHead)) {
+ Link = GetFirstNode (&Statement->WarningListHead);
+ Expression = HII_EXPRESSION_FROM_LINK (Link);
+ RemoveEntryList (&Expression->Link);
+
+ DestroyExpression (Expression);
+ }
+
+ if (Statement->ExpressionList != NULL) {
+ FreePool (Statement->ExpressionList);
+ }
+
+ if (Statement->VariableName != NULL) {
+ FreePool (Statement->VariableName);
+ }
+
+ if (Statement->BlockName != NULL) {
+ FreePool (Statement->BlockName);
+ }
+
+ if (Statement->Value.Buffer != NULL) {
+ FreePool (Statement->Value.Buffer);
+ }
+
+ if ((Statement->Operand == EFI_IFR_STRING_OP) || (Statement->Operand == EFI_IFR_PASSWORD_OP)) {
+ DeleteString (Statement->Value.Value.string, FormSet->HiiHandle);
+ }
+}
+
+/**
+ Free resources of a Form.
+
+ @param[in] FormSet Pointer of the FormSet
+ @param[in,out] Form Pointer of the Form.
+
+**/
+VOID
+DestroyForm (
+ IN HII_FORMSET *FormSet,
+ IN OUT HII_FORM *Form
+ )
+{
+ LIST_ENTRY *Link;
+ HII_EXPRESSION *Expression;
+ HII_STATEMENT *Statement;
+ HII_FORM_CONFIG_REQUEST *ConfigInfo;
+
+ //
+ // Free Rule Expressions
+ //
+ while (!IsListEmpty (&Form->RuleListHead)) {
+ Link = GetFirstNode (&Form->RuleListHead);
+ Expression = HII_EXPRESSION_FROM_LINK (Link);
+ RemoveEntryList (&Expression->Link);
+ DestroyExpression (Expression);
+ }
+
+ //
+ // Free Statements/Questions
+ //
+ while (!IsListEmpty (&Form->StatementListHead)) {
+ Link = GetFirstNode (&Form->StatementListHead);
+ Statement = HII_STATEMENT_FROM_LINK (Link);
+ RemoveEntryList (&Statement->Link);
+ DestroyStatement (FormSet, Statement);
+ }
+
+ //
+ // Free ConfigRequest string.
+ //
+ while (!IsListEmpty (&Form->ConfigRequestHead)) {
+ Link = GetFirstNode (&Form->ConfigRequestHead);
+ ConfigInfo = HII_FORM_CONFIG_REQUEST_FROM_LINK (Link);
+
+ RemoveEntryList (&ConfigInfo->Link);
+
+ FreePool (ConfigInfo->ConfigRequest);
+ FreePool (ConfigInfo);
+ }
+
+ if (Form->SuppressExpression != NULL) {
+ FreePool (Form->SuppressExpression);
+ }
+
+ //
+ // Free this Form
+ //
+ FreePool (Form);
+}
+
+/**
+ Tell whether this Operand is an Expression OpCode or not
+
+ @param[in] Operand Operand of an IFR OpCode.
+
+ @retval TRUE This is an Expression OpCode.
+ @retval FALSE Not an Expression OpCode.
+
+**/
+BOOLEAN
+IsExpressionOpCode (
+ IN UINT8 Operand
+ )
+{
+ if (((Operand >= EFI_IFR_EQ_ID_VAL_OP) && (Operand <= EFI_IFR_NOT_OP)) ||
+ ((Operand >= EFI_IFR_MATCH_OP) && (Operand <= EFI_IFR_SET_OP)) ||
+ ((Operand >= EFI_IFR_EQUAL_OP) && (Operand <= EFI_IFR_SPAN_OP)) ||
+ (Operand == EFI_IFR_CATENATE_OP) ||
+ (Operand == EFI_IFR_TO_LOWER_OP) ||
+ (Operand == EFI_IFR_TO_UPPER_OP) ||
+ (Operand == EFI_IFR_MAP_OP) ||
+ (Operand == EFI_IFR_VERSION_OP) ||
+ (Operand == EFI_IFR_SECURITY_OP) ||
+ (Operand == EFI_IFR_MATCH2_OP))
+ {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ Tell whether this Operand is an Statement OpCode.
+
+ @param[in] Operand Operand of an IFR OpCode.
+
+ @retval TRUE This is an Statement OpCode.
+ @retval FALSE Not an Statement OpCode.
+
+**/
+BOOLEAN
+IsStatementOpCode (
+ IN UINT8 Operand
+ )
+{
+ if ((Operand == EFI_IFR_SUBTITLE_OP) ||
+ (Operand == EFI_IFR_TEXT_OP) ||
+ (Operand == EFI_IFR_RESET_BUTTON_OP) ||
+ (Operand == EFI_IFR_REF_OP) ||
+ (Operand == EFI_IFR_ACTION_OP) ||
+ (Operand == EFI_IFR_NUMERIC_OP) ||
+ (Operand == EFI_IFR_ORDERED_LIST_OP) ||
+ (Operand == EFI_IFR_CHECKBOX_OP) ||
+ (Operand == EFI_IFR_STRING_OP) ||
+ (Operand == EFI_IFR_PASSWORD_OP) ||
+ (Operand == EFI_IFR_DATE_OP) ||
+ (Operand == EFI_IFR_TIME_OP) ||
+ (Operand == EFI_IFR_GUID_OP) ||
+ (Operand == EFI_IFR_ONE_OF_OP))
+ {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ Tell whether this Operand is an known OpCode.
+
+ @param[in] Operand Operand of an IFR OpCode.
+
+ @retval TRUE This is an Statement OpCode.
+ @retval FALSE Not an Statement OpCode.
+
+**/
+BOOLEAN
+IsUnKnownOpCode (
+ IN UINT8 Operand
+ )
+{
+ return Operand > EFI_IFR_MATCH2_OP ? TRUE : FALSE;
+}
+
+/**
+ Calculate number of Statements(Questions) and Expression OpCodes.
+
+ @param[in] FormSet The FormSet to be counted.
+ @param[in,out] NumberOfStatement Number of Statements(Questions)
+ @param[in,out] NumberOfExpression Number of Expression OpCodes
+
+**/
+VOID
+CountOpCodes (
+ IN HII_FORMSET *FormSet,
+ IN OUT UINT16 *NumberOfStatement,
+ IN OUT UINT16 *NumberOfExpression
+ )
+{
+ UINT16 StatementCount;
+ UINT16 ExpressionCount;
+ UINT8 *OpCodeData;
+ UINTN Offset;
+ UINTN OpCodeLen;
+
+ Offset = 0;
+ StatementCount = 0;
+ ExpressionCount = 0;
+
+ while (Offset < FormSet->IfrBinaryLength) {
+ OpCodeData = FormSet->IfrBinaryData + Offset;
+ OpCodeLen = ((EFI_IFR_OP_HEADER *)OpCodeData)->Length;
+ Offset += OpCodeLen;
+
+ if (IsExpressionOpCode (((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode)) {
+ ExpressionCount++;
+ } else {
+ StatementCount++;
+ }
+ }
+
+ *NumberOfStatement = StatementCount;
+ *NumberOfExpression = ExpressionCount;
+}
+
+/**
+ Parse opcodes in the formset IFR binary.
+
+ @param[in] FormSet Pointer of the FormSet data structure.
+
+ @retval EFI_SUCCESS Opcode parse success.
+ @retval Other Opcode parse fail.
+
+**/
+EFI_STATUS
+ParseOpCodes (
+ IN HII_FORMSET *FormSet
+ )
+{
+ EFI_STATUS Status;
+ HII_FORM *CurrentForm;
+ HII_STATEMENT *CurrentStatement;
+ HII_STATEMENT *ParentStatement;
+ HII_EXPRESSION_OPCODE *ExpressionOpCode;
+ HII_EXPRESSION *CurrentExpression;
+ UINT8 Operand;
+ UINT8 Scope;
+ UINTN OpCodeOffset;
+ UINTN OpCodeLength;
+ UINT8 *OpCodeData;
+ UINT8 ScopeOpCode;
+ HII_FORMSET_DEFAULTSTORE *DefaultStore;
+ HII_QUESTION_DEFAULT *CurrentDefault;
+ HII_QUESTION_OPTION *CurrentOption;
+ UINT8 Width;
+ UINT16 NumberOfStatement;
+ UINT16 NumberOfExpression;
+ EFI_IMAGE_ID *ImageId;
+ BOOLEAN SuppressForQuestion;
+ BOOLEAN SuppressForOption;
+ UINT16 DepthOfDisable;
+ BOOLEAN OpCodeDisabled;
+ BOOLEAN SingleOpCodeExpression;
+ BOOLEAN InScopeDefault;
+ EFI_HII_VALUE *ExpressionValue;
+ HII_STATEMENT_VALUE *StatementValue;
+ EFI_IFR_FORM_MAP_METHOD *MapMethod;
+ UINT8 MapScopeDepth;
+ LIST_ENTRY *Link;
+ HII_FORMSET_STORAGE *Storage;
+ LIST_ENTRY *MapExpressionList;
+ EFI_VARSTORE_ID TempVarstoreId;
+ BOOLEAN InScopeDisable;
+ INTN ConditionalExprCount;
+ BOOLEAN InUnknownScope;
+ UINT8 UnknownDepth;
+ HII_FORMSET_DEFAULTSTORE *PreDefaultStore;
+ LIST_ENTRY *DefaultLink;
+ BOOLEAN HaveInserted;
+ UINT16 TotalBits;
+ BOOLEAN QuestionReferBitField;
+
+ SuppressForQuestion = FALSE;
+ SuppressForOption = FALSE;
+ InScopeDisable = FALSE;
+ DepthOfDisable = 0;
+ OpCodeDisabled = FALSE;
+ SingleOpCodeExpression = FALSE;
+ InScopeDefault = FALSE;
+ CurrentExpression = NULL;
+ CurrentDefault = NULL;
+ CurrentOption = NULL;
+ ImageId = NULL;
+ MapMethod = NULL;
+ MapScopeDepth = 0;
+ Link = NULL;
+ MapExpressionList = NULL;
+ TempVarstoreId = 0;
+ ConditionalExprCount = 0;
+ InUnknownScope = FALSE;
+ UnknownDepth = 0;
+ QuestionReferBitField = FALSE;
+
+ //
+ // Get the number of Statements and Expressions
+ //
+ CountOpCodes (FormSet, &NumberOfStatement, &NumberOfExpression);
+
+ InitializeListHead (&FormSet->StatementListOSF);
+ InitializeListHead (&FormSet->StorageListHead);
+ InitializeListHead (&FormSet->DefaultStoreListHead);
+ InitializeListHead (&FormSet->FormListHead);
+ ResetCurrentExpressionStack ();
+ ResetMapExpressionListStack ();
+
+ CurrentForm = NULL;
+ CurrentStatement = NULL;
+ ParentStatement = NULL;
+
+ ResetScopeStack ();
+
+ OpCodeOffset = 0;
+ while (OpCodeOffset < FormSet->IfrBinaryLength) {
+ OpCodeData = FormSet->IfrBinaryData + OpCodeOffset;
+
+ OpCodeLength = ((EFI_IFR_OP_HEADER *)OpCodeData)->Length;
+ OpCodeOffset += OpCodeLength;
+ Operand = ((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode;
+ Scope = ((EFI_IFR_OP_HEADER *)OpCodeData)->Scope;
+ if (InUnknownScope) {
+ if (Operand == EFI_IFR_END_OP) {
+ UnknownDepth--;
+
+ if (UnknownDepth == 0) {
+ InUnknownScope = FALSE;
+ }
+ } else {
+ if (Scope != 0) {
+ UnknownDepth++;
+ }
+ }
+
+ continue;
+ }
+
+ if (IsUnKnownOpCode (Operand)) {
+ if (Scope != 0) {
+ InUnknownScope = TRUE;
+ UnknownDepth++;
+ }
+
+ continue;
+ }
+
+ //
+ // If scope bit set, push onto scope stack
+ //
+ if (Scope != 0) {
+ PushScope (Operand);
+ }
+
+ if (OpCodeDisabled) {
+ //
+ // DisableIf Expression is evaluated to be TRUE, try to find its end.
+ // Here only cares the EFI_IFR_DISABLE_IF and EFI_IFR_END
+ //
+ if (Operand == EFI_IFR_DISABLE_IF_OP) {
+ DepthOfDisable++;
+ } else if (Operand == EFI_IFR_END_OP) {
+ Status = PopScope (&ScopeOpCode);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (ScopeOpCode == EFI_IFR_DISABLE_IF_OP) {
+ if (DepthOfDisable == 0) {
+ InScopeDisable = FALSE;
+ OpCodeDisabled = FALSE;
+ } else {
+ DepthOfDisable--;
+ }
+ }
+ }
+
+ continue;
+ }
+
+ if (IsExpressionOpCode (Operand)) {
+ ExpressionOpCode = (HII_EXPRESSION_OPCODE *)AllocateZeroPool (sizeof (HII_EXPRESSION_OPCODE));
+ if (ExpressionOpCode == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ExpressionOpCode->Signature = HII_EXPRESSION_OPCODE_SIGNATURE;
+ ExpressionOpCode->Operand = Operand;
+
+ switch (Operand) {
+ case EFI_IFR_EQ_ID_VAL_OP:
+
+ CopyMem (&ExpressionOpCode->ExtraData.EqIdValData.QuestionId, &((EFI_IFR_EQ_ID_VAL *)OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
+
+ ExpressionValue = &ExpressionOpCode->ExtraData.EqIdValData.Value;
+ ExpressionValue->Type = EFI_IFR_TYPE_NUM_SIZE_16;
+ CopyMem (&ExpressionValue->Value.u16, &((EFI_IFR_EQ_ID_VAL *)OpCodeData)->Value, sizeof (UINT16));
+ break;
+
+ case EFI_IFR_EQ_ID_ID_OP:
+ CopyMem (&ExpressionOpCode->ExtraData.EqIdIdData.QuestionId1, &((EFI_IFR_EQ_ID_ID *)OpCodeData)->QuestionId1, sizeof (EFI_QUESTION_ID));
+ CopyMem (&ExpressionOpCode->ExtraData.EqIdIdData.QuestionId2, &((EFI_IFR_EQ_ID_ID *)OpCodeData)->QuestionId2, sizeof (EFI_QUESTION_ID));
+ break;
+
+ case EFI_IFR_EQ_ID_VAL_LIST_OP:
+
+ CopyMem (&ExpressionOpCode->ExtraData.EqIdListData.QuestionId, &((EFI_IFR_EQ_ID_VAL_LIST *)OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
+ CopyMem (&ExpressionOpCode->ExtraData.EqIdListData.ListLength, &((EFI_IFR_EQ_ID_VAL_LIST *)OpCodeData)->ListLength, sizeof (UINT16));
+ ExpressionOpCode->ExtraData.EqIdListData.ValueList = AllocateCopyPool (
+ ExpressionOpCode->ExtraData.EqIdListData.ListLength * sizeof (UINT16),
+ &((EFI_IFR_EQ_ID_VAL_LIST *)OpCodeData)->ValueList
+ );
+ if (ExpressionOpCode->ExtraData.EqIdListData.ValueList == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ break;
+
+ case EFI_IFR_TO_STRING_OP:
+ case EFI_IFR_FIND_OP:
+
+ ExpressionOpCode->ExtraData.Format = ((EFI_IFR_TO_STRING *)OpCodeData)->Format;
+ break;
+
+ case EFI_IFR_STRING_REF1_OP:
+
+ ExpressionValue = &ExpressionOpCode->ExtraData.Value;
+ ExpressionValue->Type = EFI_IFR_TYPE_STRING;
+ CopyMem (&ExpressionValue->Value.string, &((EFI_IFR_STRING_REF1 *)OpCodeData)->StringId, sizeof (EFI_STRING_ID));
+ break;
+
+ case EFI_IFR_RULE_REF_OP:
+
+ ExpressionOpCode->ExtraData.RuleId = ((EFI_IFR_RULE_REF *)OpCodeData)->RuleId;
+ break;
+
+ case EFI_IFR_SPAN_OP:
+
+ ExpressionOpCode->ExtraData.Flags = ((EFI_IFR_SPAN *)OpCodeData)->Flags;
+ break;
+
+ case EFI_IFR_THIS_OP:
+
+ if (ParentStatement != NULL) {
+ ExpressionOpCode->ExtraData.QuestionRef1Data.QuestionId = ParentStatement->QuestionId;
+ }
+
+ break;
+
+ case EFI_IFR_SECURITY_OP:
+
+ CopyMem (&ExpressionOpCode->ExtraData.Guid, &((EFI_IFR_SECURITY *)OpCodeData)->Permissions, sizeof (EFI_GUID));
+ break;
+
+ case EFI_IFR_MATCH2_OP:
+
+ CopyMem (&ExpressionOpCode->ExtraData.Guid, &((EFI_IFR_MATCH2 *)OpCodeData)->SyntaxType, sizeof (EFI_GUID));
+ break;
+
+ case EFI_IFR_GET_OP:
+ case EFI_IFR_SET_OP:
+
+ CopyMem (&TempVarstoreId, &((EFI_IFR_GET *)OpCodeData)->VarStoreId, sizeof (TempVarstoreId));
+ if (TempVarstoreId != 0) {
+ if (FormSet->StorageListHead.ForwardLink != NULL) {
+ Link = GetFirstNode (&FormSet->StorageListHead);
+ while (!IsNull (&FormSet->StorageListHead, Link)) {
+ Storage = HII_STORAGE_FROM_LINK (Link);
+ if (Storage->VarStoreId == ((EFI_IFR_GET *)OpCodeData)->VarStoreId) {
+ ExpressionOpCode->ExtraData.GetSetData.VarStorage = Storage;
+ break;
+ }
+
+ Link = GetNextNode (&FormSet->StorageListHead, Link);
+ }
+ }
+
+ if (ExpressionOpCode->ExtraData.GetSetData.VarStorage == NULL) {
+ //
+ // VarStorage is not found.
+ //
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ ExpressionOpCode->ExtraData.GetSetData.ValueType = ((EFI_IFR_GET *)OpCodeData)->VarStoreType;
+ switch (ExpressionOpCode->ExtraData.GetSetData.ValueType) {
+ case EFI_IFR_TYPE_BOOLEAN:
+ case EFI_IFR_TYPE_NUM_SIZE_8:
+ ExpressionOpCode->ExtraData.GetSetData.ValueWidth = 1;
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_16:
+ case EFI_IFR_TYPE_STRING:
+ ExpressionOpCode->ExtraData.GetSetData.ValueWidth = 2;
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_32:
+ ExpressionOpCode->ExtraData.GetSetData.ValueWidth = 4;
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_64:
+ ExpressionOpCode->ExtraData.GetSetData.ValueWidth = 8;
+ break;
+
+ case EFI_IFR_TYPE_DATE:
+ ExpressionOpCode->ExtraData.GetSetData.ValueWidth = (UINT8)sizeof (EFI_IFR_DATE);
+ break;
+
+ case EFI_IFR_TYPE_TIME:
+ ExpressionOpCode->ExtraData.GetSetData.ValueWidth = (UINT8)sizeof (EFI_IFR_TIME);
+ break;
+
+ case EFI_IFR_TYPE_REF:
+ ExpressionOpCode->ExtraData.GetSetData.ValueWidth = (UINT8)sizeof (EFI_IFR_REF);
+ break;
+
+ case EFI_IFR_TYPE_OTHER:
+ case EFI_IFR_TYPE_UNDEFINED:
+ case EFI_IFR_TYPE_ACTION:
+ case EFI_IFR_TYPE_BUFFER:
+ default:
+ //
+ // Invalid value type for Get/Set opcode.
+ //
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CopyMem (
+ &ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo.VarName,
+ &((EFI_IFR_GET *)OpCodeData)->VarStoreInfo.VarName,
+ sizeof (EFI_STRING_ID)
+ );
+ CopyMem (
+ &ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset,
+ &((EFI_IFR_GET *)OpCodeData)->VarStoreInfo.VarOffset,
+ sizeof (UINT16)
+ );
+ if ((ExpressionOpCode->ExtraData.GetSetData.VarStorage != NULL) &&
+ ((ExpressionOpCode->ExtraData.GetSetData.VarStorage->Type == EFI_HII_VARSTORE_NAME_VALUE) ||
+ (ExpressionOpCode->ExtraData.GetSetData.VarStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)))
+ {
+ ExpressionOpCode->ExtraData.GetSetData.ValueName = GetTokenString (ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo.VarName, FormSet->HiiHandle);
+ if (ExpressionOpCode->ExtraData.GetSetData.ValueName == NULL) {
+ //
+ // String ID is invalid.
+ //
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ break;
+
+ case EFI_IFR_QUESTION_REF1_OP:
+
+ CopyMem (&ExpressionOpCode->ExtraData.QuestionRef1Data.QuestionId, &((EFI_IFR_EQ_ID_VAL_LIST *)OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
+ break;
+
+ case EFI_IFR_QUESTION_REF3_OP:
+
+ if (OpCodeLength >= sizeof (EFI_IFR_QUESTION_REF3_2)) {
+ CopyMem (&ExpressionOpCode->ExtraData.QuestionRef3Data.DevicePath, &((EFI_IFR_QUESTION_REF3_2 *)OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));
+
+ if (OpCodeLength >= sizeof (EFI_IFR_QUESTION_REF3_3)) {
+ CopyMem (&ExpressionOpCode->ExtraData.QuestionRef3Data.Guid, &((EFI_IFR_QUESTION_REF3_3 *)OpCodeData)->Guid, sizeof (EFI_GUID));
+ }
+ }
+
+ break;
+
+ //
+ // constant
+ //
+ case EFI_IFR_TRUE_OP:
+
+ ExpressionValue = &ExpressionOpCode->ExtraData.Value;
+ ExpressionValue->Type = EFI_IFR_TYPE_BOOLEAN;
+ ExpressionValue->Value.b = TRUE;
+ break;
+
+ case EFI_IFR_FALSE_OP:
+
+ ExpressionValue = &ExpressionOpCode->ExtraData.Value;
+ ExpressionValue->Type = EFI_IFR_TYPE_BOOLEAN;
+ ExpressionValue->Value.b = FALSE;
+ break;
+
+ case EFI_IFR_ONE_OP:
+
+ ExpressionValue = &ExpressionOpCode->ExtraData.Value;
+ ExpressionValue->Type = EFI_IFR_TYPE_NUM_SIZE_8;
+ ExpressionValue->Value.u8 = 1;
+ break;
+
+ case EFI_IFR_ZERO_OP:
+
+ ExpressionValue = &ExpressionOpCode->ExtraData.Value;
+ ExpressionValue->Type = EFI_IFR_TYPE_NUM_SIZE_8;
+ ExpressionValue->Value.u8 = 0;
+ break;
+
+ case EFI_IFR_ONES_OP:
+
+ ExpressionValue = &ExpressionOpCode->ExtraData.Value;
+ ExpressionValue->Type = EFI_IFR_TYPE_NUM_SIZE_64;
+ ExpressionValue->Value.u64 = 0xffffffffffffffffULL;
+ break;
+
+ case EFI_IFR_UINT8_OP:
+
+ ExpressionValue = &ExpressionOpCode->ExtraData.Value;
+ ExpressionValue->Type = EFI_IFR_TYPE_NUM_SIZE_8;
+ ExpressionValue->Value.u8 = ((EFI_IFR_UINT8 *)OpCodeData)->Value;
+ break;
+
+ case EFI_IFR_UINT16_OP:
+
+ ExpressionValue = &ExpressionOpCode->ExtraData.Value;
+ ExpressionValue->Type = EFI_IFR_TYPE_NUM_SIZE_16;
+ CopyMem (&ExpressionValue->Value.u16, &((EFI_IFR_UINT16 *)OpCodeData)->Value, sizeof (UINT16));
+ break;
+
+ case EFI_IFR_UINT32_OP:
+
+ ExpressionValue = &ExpressionOpCode->ExtraData.Value;
+ ExpressionValue->Type = EFI_IFR_TYPE_NUM_SIZE_32;
+ CopyMem (&ExpressionValue->Value.u32, &((EFI_IFR_UINT32 *)OpCodeData)->Value, sizeof (UINT32));
+ break;
+
+ case EFI_IFR_UINT64_OP:
+
+ ExpressionValue = &ExpressionOpCode->ExtraData.Value;
+ ExpressionValue->Type = EFI_IFR_TYPE_NUM_SIZE_64;
+ CopyMem (&ExpressionValue->Value.u64, &((EFI_IFR_UINT64 *)OpCodeData)->Value, sizeof (UINT64));
+ break;
+
+ case EFI_IFR_UNDEFINED_OP:
+ ExpressionValue = &ExpressionOpCode->ExtraData.Value;
+ ExpressionValue->Type = EFI_IFR_TYPE_UNDEFINED;
+ break;
+
+ case EFI_IFR_VERSION_OP:
+ ExpressionValue = &ExpressionOpCode->ExtraData.Value;
+ ExpressionValue->Type = EFI_IFR_TYPE_NUM_SIZE_16;
+ ExpressionValue->Value.u16 = EFI_IFR_SPECIFICATION_VERSION;
+ break;
+
+ default:
+ break;
+ }
+
+ //
+ // Create sub expression nested in MAP opcode
+ //
+ if ((CurrentExpression == NULL) && (MapScopeDepth > 0)) {
+ CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
+ if (CurrentExpression == NULL) {
+ continue;
+ }
+
+ InsertTailList (MapExpressionList, &CurrentExpression->Link);
+ if (Scope == 0) {
+ SingleOpCodeExpression = TRUE;
+ }
+ }
+
+ InsertTailList (&CurrentExpression->OpCodeListHead, &ExpressionOpCode->Link);
+ if (Operand == EFI_IFR_MAP_OP) {
+ //
+ // Store current Map Expression List.
+ //
+ if (MapExpressionList != NULL) {
+ PushMapExpressionList (MapExpressionList);
+ }
+
+ //
+ // Initialize new Map Expression List.
+ //
+ MapExpressionList = &ExpressionOpCode->MapExpressionList;
+ InitializeListHead (MapExpressionList);
+ //
+ // Store current expression.
+ //
+ PushCurrentExpression (CurrentExpression);
+ CurrentExpression = NULL;
+ MapScopeDepth++;
+ } else if (SingleOpCodeExpression) {
+ //
+ // There are two cases to indicate the end of an Expression:
+ // for single OpCode expression: one Expression OpCode
+ // for expression consists of more than one OpCode: EFI_IFR_END
+ //
+ SingleOpCodeExpression = FALSE;
+
+ if (InScopeDisable && (CurrentForm == NULL)) {
+ //
+ // This is DisableIf expression for Form, it should be a constant expression
+ //
+ Status = EvaluateHiiExpression (FormSet, CurrentForm, CurrentExpression);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ OpCodeDisabled = IsHiiValueTrue (&CurrentExpression->Result);
+ }
+
+ CurrentExpression = NULL;
+ }
+
+ continue;
+ }
+
+ //
+ // Parse the Opcode
+ //
+ switch (Operand) {
+ case EFI_IFR_FORM_SET_OP:
+ //
+ // Check the formset GUID
+ //
+
+ if (CompareMem (&FormSet->Guid, &((EFI_IFR_FORM_SET *)OpCodeData)->Guid, sizeof (EFI_GUID)) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CopyMem (&FormSet->FormSetTitle, &((EFI_IFR_FORM_SET *)OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID));
+ CopyMem (&FormSet->Help, &((EFI_IFR_FORM_SET *)OpCodeData)->Help, sizeof (EFI_STRING_ID));
+
+ if (OpCodeLength > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) {
+ //
+ // The formset OpCode contains ClassGuid
+ //
+ FormSet->NumberOfClassGuid = (UINT8)(((EFI_IFR_FORM_SET *)OpCodeData)->Flags & 0x3);
+ CopyMem (FormSet->ClassGuid, OpCodeData + sizeof (EFI_IFR_FORM_SET), FormSet->NumberOfClassGuid * sizeof (EFI_GUID));
+ }
+
+ break;
+
+ case EFI_IFR_FORM_OP:
+
+ //
+ // Create a new Form for this FormSet
+ //
+ CurrentForm = AllocateZeroPool (sizeof (HII_FORM));
+ if (CurrentForm == NULL) {
+ break;
+ }
+
+ CurrentForm->Signature = HII_FORM_SIGNATURE;
+ InitializeListHead (&CurrentForm->StatementListHead);
+ InitializeListHead (&CurrentForm->ConfigRequestHead);
+ InitializeListHead (&CurrentForm->RuleListHead);
+
+ CurrentForm->FormType = STANDARD_MAP_FORM_TYPE;
+ CopyMem (&CurrentForm->FormId, &((EFI_IFR_FORM *)OpCodeData)->FormId, sizeof (UINT16));
+ CopyMem (&CurrentForm->FormTitle, &((EFI_IFR_FORM *)OpCodeData)->FormTitle, sizeof (EFI_STRING_ID));
+
+ ConditionalExprCount = GetConditionalExpressionCount (ExpressForm);
+ if ( ConditionalExprCount > 0) {
+ //
+ // Form is inside of suppressif
+ //
+ CurrentForm->SuppressExpression = (HII_EXPRESSION_LIST *)AllocatePool (
+ (UINTN)(sizeof (HII_EXPRESSION_LIST) + ((ConditionalExprCount -1) * sizeof (HII_EXPRESSION *)))
+ );
+ if (CurrentForm->SuppressExpression == NULL) {
+ break;
+ }
+
+ CurrentForm->SuppressExpression->Count = (UINTN)ConditionalExprCount;
+ CurrentForm->SuppressExpression->Signature = HII_EXPRESSION_LIST_SIGNATURE;
+ CopyMem (CurrentForm->SuppressExpression->Expression, GetConditionalExpressionList (ExpressForm), (UINTN)(sizeof (HII_EXPRESSION *) * ConditionalExprCount));
+ }
+
+ if (Scope != 0) {
+ //
+ // Enter scope of a Form, suppressif will be used for Question or Option
+ //
+ SuppressForQuestion = TRUE;
+ }
+
+ //
+ // Insert into Form list of this FormSet
+ //
+ InsertTailList (&FormSet->FormListHead, &CurrentForm->Link);
+ break;
+
+ case EFI_IFR_FORM_MAP_OP:
+
+ //
+ // Create a new Form for this FormSet
+ //
+ CurrentForm = AllocateZeroPool (sizeof (HII_FORM));
+ if (CurrentForm == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CurrentForm->Signature = HII_FORM_SIGNATURE;
+ InitializeListHead (&CurrentForm->StatementListHead);
+ InitializeListHead (&CurrentForm->ConfigRequestHead);
+ InitializeListHead (&CurrentForm->RuleListHead);
+
+ CopyMem (&CurrentForm->FormId, &((EFI_IFR_FORM *)OpCodeData)->FormId, sizeof (UINT16));
+
+ MapMethod = (EFI_IFR_FORM_MAP_METHOD *)(OpCodeData + sizeof (EFI_IFR_FORM_MAP));
+ //
+ // FormMap Form must contain at least one Map Method.
+ //
+ if (((EFI_IFR_OP_HEADER *)OpCodeData)->Length < ((UINTN)(UINT8 *)(MapMethod + 1) - (UINTN)OpCodeData)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Try to find the standard form map method.
+ //
+ while (((UINTN)(UINT8 *)MapMethod - (UINTN)OpCodeData) < ((EFI_IFR_OP_HEADER *)OpCodeData)->Length) {
+ if (CompareGuid ((EFI_GUID *)(VOID *)&MapMethod->MethodIdentifier, &gEfiHiiStandardFormGuid)) {
+ CopyMem (&CurrentForm->FormTitle, &MapMethod->MethodTitle, sizeof (EFI_STRING_ID));
+ CurrentForm->FormType = STANDARD_MAP_FORM_TYPE;
+ break;
+ }
+
+ MapMethod++;
+ }
+
+ //
+ // If the standard form map method is not found, the first map method title will be used.
+ //
+ if (CurrentForm->FormTitle == 0) {
+ MapMethod = (EFI_IFR_FORM_MAP_METHOD *)(OpCodeData + sizeof (EFI_IFR_FORM_MAP));
+ CopyMem (&CurrentForm->FormTitle, &MapMethod->MethodTitle, sizeof (EFI_STRING_ID));
+ }
+
+ ConditionalExprCount = GetConditionalExpressionCount (ExpressForm);
+ if ( ConditionalExprCount > 0) {
+ //
+ // Form is inside of suppressif
+ //
+ CurrentForm->SuppressExpression = (HII_EXPRESSION_LIST *)AllocateZeroPool (
+ (UINTN)(sizeof (HII_EXPRESSION_LIST) + ((ConditionalExprCount -1) * sizeof (HII_EXPRESSION *)))
+ );
+ if (CurrentForm->SuppressExpression == NULL) {
+ FreePool (CurrentForm);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CurrentForm->SuppressExpression->Count = (UINTN)ConditionalExprCount;
+ CurrentForm->SuppressExpression->Signature = HII_EXPRESSION_LIST_SIGNATURE;
+ CopyMem (CurrentForm->SuppressExpression->Expression, GetConditionalExpressionList (ExpressForm), (UINTN)(sizeof (HII_EXPRESSION *) * ConditionalExprCount));
+ }
+
+ if (Scope != 0) {
+ //
+ // Enter scope of a Form, suppressif will be used for Question or Option
+ //
+ SuppressForQuestion = TRUE;
+ }
+
+ //
+ // Insert into Form list of this FormSet
+ //
+ InsertTailList (&FormSet->FormListHead, &CurrentForm->Link);
+ break;
+
+ //
+ // Storage
+ //
+ case EFI_IFR_VARSTORE_OP:
+
+ //
+ // Create a buffer Storage for this FormSet
+ //
+ Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_BUFFER, OpCodeData);
+ CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE *)OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
+ break;
+
+ case EFI_IFR_VARSTORE_NAME_VALUE_OP:
+
+ //
+ // Create a name/value Storage for this FormSet
+ //
+ Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_NAME_VALUE, OpCodeData);
+ CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_NAME_VALUE *)OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
+ break;
+
+ case EFI_IFR_VARSTORE_EFI_OP:
+
+ //
+ // Create a EFI variable Storage for this FormSet
+ //
+ if (OpCodeLength < sizeof (EFI_IFR_VARSTORE_EFI)) {
+ //
+ // Create efi varstore with format follow UEFI spec before 2.3.1.
+ //
+ Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_EFI_VARIABLE, OpCodeData);
+ } else {
+ //
+ // Create efi varstore with format follow UEFI spec 2.3.1 and later.
+ //
+ Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER, OpCodeData);
+ }
+
+ CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_EFI *)OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
+ break;
+
+ //
+ // DefaultStore
+ //
+ case EFI_IFR_DEFAULTSTORE_OP:
+
+ HaveInserted = FALSE;
+ DefaultStore = AllocateZeroPool (sizeof (HII_FORMSET_DEFAULTSTORE));
+ if (DefaultStore == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ DefaultStore->Signature = HII_FORMSET_DEFAULTSTORE_SIGNATURE;
+
+ CopyMem (&DefaultStore->DefaultId, &((EFI_IFR_DEFAULTSTORE *)OpCodeData)->DefaultId, sizeof (UINT16));
+ CopyMem (&DefaultStore->DefaultName, &((EFI_IFR_DEFAULTSTORE *)OpCodeData)->DefaultName, sizeof (EFI_STRING_ID));
+ //
+ // Insert it to the DefaultStore list of this Formset with ascending order.
+ //
+ if (!IsListEmpty (&FormSet->DefaultStoreListHead)) {
+ DefaultLink = GetFirstNode (&FormSet->DefaultStoreListHead);
+ while (!IsNull (&FormSet->DefaultStoreListHead, DefaultLink)) {
+ PreDefaultStore = HII_FORMSET_DEFAULTSTORE_FROM_LINK (DefaultLink);
+ DefaultLink = GetNextNode (&FormSet->DefaultStoreListHead, DefaultLink);
+ if (DefaultStore->DefaultId < PreDefaultStore->DefaultId) {
+ InsertTailList (&PreDefaultStore->Link, &DefaultStore->Link);
+ HaveInserted = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (!HaveInserted) {
+ InsertTailList (&FormSet->DefaultStoreListHead, &DefaultStore->Link);
+ }
+
+ break;
+
+ //
+ // Statements
+ //
+ case EFI_IFR_SUBTITLE_OP:
+
+ CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
+ break;
+
+ case EFI_IFR_TEXT_OP:
+
+ CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
+ CopyMem (&CurrentStatement->ExtraData.TextTwo, &((EFI_IFR_TEXT *)OpCodeData)->TextTwo, sizeof (EFI_STRING_ID));
+ break;
+
+ case EFI_IFR_RESET_BUTTON_OP:
+
+ CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
+ CopyMem (&CurrentStatement->ExtraData.DefaultId, &((EFI_IFR_RESET_BUTTON *)OpCodeData)->DefaultId, sizeof (EFI_DEFAULT_ID));
+ break;
+
+ //
+ // Questions
+ //
+ case EFI_IFR_ACTION_OP:
+
+ CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
+ CurrentStatement->Value.Type = EFI_IFR_TYPE_ACTION;
+
+ if (OpCodeLength == sizeof (EFI_IFR_ACTION_1)) {
+ //
+ // No QuestionConfig present, so no configuration string will be processed
+ //
+ CurrentStatement->ExtraData.QuestionConfig = 0;
+ } else {
+ CopyMem (&CurrentStatement->ExtraData.QuestionConfig, &((EFI_IFR_ACTION *)OpCodeData)->QuestionConfig, sizeof (EFI_STRING_ID));
+ }
+
+ break;
+
+ case EFI_IFR_REF_OP:
+
+ CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
+ StatementValue = &CurrentStatement->Value;
+ StatementValue->Type = EFI_IFR_TYPE_REF;
+ if (OpCodeLength >= sizeof (EFI_IFR_REF)) {
+ CopyMem (&StatementValue->Value.ref.FormId, &((EFI_IFR_REF *)OpCodeData)->FormId, sizeof (EFI_FORM_ID));
+
+ if (OpCodeLength >= sizeof (EFI_IFR_REF2)) {
+ CopyMem (&StatementValue->Value.ref.QuestionId, &((EFI_IFR_REF2 *)OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
+
+ if (OpCodeLength >= sizeof (EFI_IFR_REF3)) {
+ CopyMem (&StatementValue->Value.ref.FormSetGuid, &((EFI_IFR_REF3 *)OpCodeData)->FormSetId, sizeof (EFI_GUID));
+
+ if (OpCodeLength >= sizeof (EFI_IFR_REF4)) {
+ CopyMem (&StatementValue->Value.ref.DevicePath, &((EFI_IFR_REF4 *)OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));
+ }
+ }
+ }
+ }
+
+ CurrentStatement->StorageWidth = (UINT16)sizeof (EFI_HII_REF);
+ InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
+ break;
+
+ case EFI_IFR_ONE_OF_OP:
+ case EFI_IFR_NUMERIC_OP:
+
+ CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
+ CurrentStatement->ExtraData.NumData.Flags = ((EFI_IFR_ONE_OF *)OpCodeData)->Flags;
+ StatementValue = &CurrentStatement->Value;
+
+ if (QuestionReferBitField) {
+ //
+ // Get the bit var store info (bit/byte offset, bit/byte offset)
+ //
+ CurrentStatement->QuestionReferToBitField = TRUE;
+ CurrentStatement->BitStorageWidth = CurrentStatement->ExtraData.NumData.Flags & EDKII_IFR_NUMERIC_SIZE_BIT;
+ CurrentStatement->BitVarOffset = CurrentStatement->VarStoreInfo.VarOffset;
+ CurrentStatement->VarStoreInfo.VarOffset = CurrentStatement->BitVarOffset / 8;
+ TotalBits = CurrentStatement->BitVarOffset % 8 + CurrentStatement->BitStorageWidth;
+ CurrentStatement->StorageWidth = (TotalBits % 8 == 0 ? TotalBits / 8 : TotalBits / 8 + 1);
+
+ //
+ // Get the Minimum/Maximum/Step value(Note: bit field type has been stored as UINT32 type)
+ //
+ CurrentStatement->ExtraData.NumData.Minimum = ((EFI_IFR_NUMERIC *)OpCodeData)->data.u32.MinValue;
+ CurrentStatement->ExtraData.NumData.Maximum = ((EFI_IFR_NUMERIC *)OpCodeData)->data.u32.MaxValue;
+ CurrentStatement->ExtraData.NumData.Step = ((EFI_IFR_NUMERIC *)OpCodeData)->data.u32.Step;
+
+ //
+ // Update the Flag and type of Minimum/Maximum/Step according to the actual width of bit field,
+ // in order to make Browser handle these question with bit varstore correctly.
+ //
+ ((EFI_IFR_NUMERIC *)OpCodeData)->Flags &= EDKII_IFR_DISPLAY_BIT;
+ ((EFI_IFR_NUMERIC *)OpCodeData)->Flags >>= 2;
+ switch (CurrentStatement->StorageWidth) {
+ case 1:
+ ((EFI_IFR_NUMERIC *)OpCodeData)->Flags |= EFI_IFR_TYPE_NUM_SIZE_8;
+ ((EFI_IFR_NUMERIC *)OpCodeData)->data.u8.MinValue = (UINT8)CurrentStatement->ExtraData.NumData.Minimum;
+ ((EFI_IFR_NUMERIC *)OpCodeData)->data.u8.MaxValue = (UINT8)CurrentStatement->ExtraData.NumData.Maximum;
+ ((EFI_IFR_NUMERIC *)OpCodeData)->data.u8.Step = (UINT8)CurrentStatement->ExtraData.NumData.Step;
+ StatementValue->Type = EFI_IFR_TYPE_NUM_SIZE_8;
+ break;
+ case 2:
+ ((EFI_IFR_NUMERIC *)OpCodeData)->Flags |= EFI_IFR_TYPE_NUM_SIZE_16;
+ ((EFI_IFR_NUMERIC *)OpCodeData)->data.u16.MinValue = (UINT16)CurrentStatement->ExtraData.NumData.Minimum;
+ ((EFI_IFR_NUMERIC *)OpCodeData)->data.u16.MaxValue = (UINT16)CurrentStatement->ExtraData.NumData.Maximum;
+ ((EFI_IFR_NUMERIC *)OpCodeData)->data.u16.Step = (UINT16)CurrentStatement->ExtraData.NumData.Step;
+ StatementValue->Type = EFI_IFR_TYPE_NUM_SIZE_16;
+ break;
+ case 3:
+ case 4:
+ ((EFI_IFR_NUMERIC *)OpCodeData)->Flags |= EFI_IFR_TYPE_NUM_SIZE_32;
+ ((EFI_IFR_NUMERIC *)OpCodeData)->data.u32.MinValue = (UINT32)CurrentStatement->ExtraData.NumData.Minimum;
+ ((EFI_IFR_NUMERIC *)OpCodeData)->data.u32.MaxValue = (UINT32)CurrentStatement->ExtraData.NumData.Maximum;
+ ((EFI_IFR_NUMERIC *)OpCodeData)->data.u32.Step = (UINT32)CurrentStatement->ExtraData.NumData.Step;
+ StatementValue->Type = EFI_IFR_TYPE_NUM_SIZE_32;
+ break;
+ default:
+ break;
+ }
+ } else {
+ switch (CurrentStatement->ExtraData.NumData.Flags & EFI_IFR_NUMERIC_SIZE) {
+ case EFI_IFR_NUMERIC_SIZE_1:
+ CurrentStatement->ExtraData.NumData.Minimum = ((EFI_IFR_NUMERIC *)OpCodeData)->data.u8.MinValue;
+ CurrentStatement->ExtraData.NumData.Maximum = ((EFI_IFR_NUMERIC *)OpCodeData)->data.u8.MaxValue;
+ CurrentStatement->ExtraData.NumData.Step = ((EFI_IFR_NUMERIC *)OpCodeData)->data.u8.Step;
+ CurrentStatement->StorageWidth = (UINT16)sizeof (UINT8);
+ StatementValue->Type = EFI_IFR_TYPE_NUM_SIZE_8;
+
+ break;
+
+ case EFI_IFR_NUMERIC_SIZE_2:
+ CopyMem (&CurrentStatement->ExtraData.NumData.Minimum, &((EFI_IFR_NUMERIC *)OpCodeData)->data.u16.MinValue, sizeof (UINT16));
+ CopyMem (&CurrentStatement->ExtraData.NumData.Maximum, &((EFI_IFR_NUMERIC *)OpCodeData)->data.u16.MaxValue, sizeof (UINT16));
+ CopyMem (&CurrentStatement->ExtraData.NumData.Step, &((EFI_IFR_NUMERIC *)OpCodeData)->data.u16.Step, sizeof (UINT16));
+ CurrentStatement->StorageWidth = (UINT16)sizeof (UINT16);
+ StatementValue->Type = EFI_IFR_TYPE_NUM_SIZE_16;
+
+ break;
+
+ case EFI_IFR_NUMERIC_SIZE_4:
+ CopyMem (&CurrentStatement->ExtraData.NumData.Minimum, &((EFI_IFR_NUMERIC *)OpCodeData)->data.u32.MinValue, sizeof (UINT32));
+ CopyMem (&CurrentStatement->ExtraData.NumData.Maximum, &((EFI_IFR_NUMERIC *)OpCodeData)->data.u32.MaxValue, sizeof (UINT32));
+ CopyMem (&CurrentStatement->ExtraData.NumData.Step, &((EFI_IFR_NUMERIC *)OpCodeData)->data.u32.Step, sizeof (UINT32));
+ CurrentStatement->StorageWidth = (UINT16)sizeof (UINT32);
+ StatementValue->Type = EFI_IFR_TYPE_NUM_SIZE_32;
+
+ break;
+
+ case EFI_IFR_NUMERIC_SIZE_8:
+ CopyMem (&CurrentStatement->ExtraData.NumData.Minimum, &((EFI_IFR_NUMERIC *)OpCodeData)->data.u64.MinValue, sizeof (UINT64));
+ CopyMem (&CurrentStatement->ExtraData.NumData.Maximum, &((EFI_IFR_NUMERIC *)OpCodeData)->data.u64.MaxValue, sizeof (UINT64));
+ CopyMem (&CurrentStatement->ExtraData.NumData.Step, &((EFI_IFR_NUMERIC *)OpCodeData)->data.u64.Step, sizeof (UINT64));
+ CurrentStatement->StorageWidth = (UINT16)sizeof (UINT64);
+ StatementValue->Type = EFI_IFR_TYPE_NUM_SIZE_64;
+
+ break;
+
+ default:
+
+ break;
+ }
+ }
+
+ InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
+
+ if ((Operand == EFI_IFR_ONE_OF_OP) && (Scope != 0)) {
+ SuppressForOption = TRUE;
+ }
+
+ break;
+
+ case EFI_IFR_ORDERED_LIST_OP:
+
+ CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
+ CurrentStatement->ExtraData.OrderListData.Flags = ((EFI_IFR_ORDERED_LIST *)OpCodeData)->Flags;
+ CurrentStatement->ExtraData.OrderListData.MaxContainers = ((EFI_IFR_ORDERED_LIST *)OpCodeData)->MaxContainers;
+ CurrentStatement->Value.Type = EFI_IFR_TYPE_BUFFER;
+ CurrentStatement->Value.Buffer = NULL;
+
+ if (Scope != 0) {
+ SuppressForOption = TRUE;
+ }
+
+ break;
+
+ case EFI_IFR_CHECKBOX_OP:
+
+ CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
+ CurrentStatement->ExtraData.Flags = ((EFI_IFR_CHECKBOX *)OpCodeData)->Flags;
+ CurrentStatement->StorageWidth = (UINT16)sizeof (BOOLEAN);
+ CurrentStatement->Value.Type = EFI_IFR_TYPE_BOOLEAN;
+
+ if (QuestionReferBitField) {
+ //
+ // Get the bit var store info (bit/byte offset, bit/byte offset)
+ //
+ CurrentStatement->QuestionReferToBitField = TRUE;
+ CurrentStatement->BitStorageWidth = 1;
+ CurrentStatement->BitVarOffset = CurrentStatement->VarStoreInfo.VarOffset;
+ CurrentStatement->VarStoreInfo.VarOffset = CurrentStatement->BitVarOffset / 8;
+ TotalBits = CurrentStatement->BitVarOffset % 8 + CurrentStatement->BitStorageWidth;
+ CurrentStatement->StorageWidth = (TotalBits % 8 == 0 ? TotalBits / 8 : TotalBits / 8 + 1);
+ }
+
+ InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
+
+ break;
+
+ case EFI_IFR_STRING_OP:
+
+ CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
+
+ //
+ // MinSize is the minimum number of characters that can be accepted for this opcode,
+ // MaxSize is the maximum number of characters that can be accepted for this opcode.
+ // The characters are stored as Unicode, so the storage width should multiply 2.
+ //
+ CurrentStatement->ExtraData.StrData.MinSize = ((EFI_IFR_STRING *)OpCodeData)->MinSize;
+ CurrentStatement->ExtraData.StrData.MaxSize = ((EFI_IFR_STRING *)OpCodeData)->MaxSize;
+ CurrentStatement->ExtraData.StrData.Flags = ((EFI_IFR_STRING *)OpCodeData)->Flags;
+ CurrentStatement->StorageWidth = (UINT16)((UINTN)CurrentStatement->ExtraData.StrData.MaxSize * sizeof (CHAR16));
+
+ CurrentStatement->Value.Type = EFI_IFR_TYPE_STRING;
+ CurrentStatement->Value.Buffer = AllocateZeroPool (CurrentStatement->StorageWidth + sizeof (CHAR16));
+ if (CurrentStatement->Value.Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CurrentStatement->Value.Value.string = NewHiiString ((CHAR16 *)CurrentStatement->Value.Buffer, FormSet->HiiHandle);
+
+ InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
+ break;
+
+ case EFI_IFR_PASSWORD_OP:
+
+ CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
+
+ //
+ // MinSize is the minimum number of characters that can be accepted for this opcode,
+ // MaxSize is the maximum number of characters that can be accepted for this opcode.
+ // The characters are stored as Unicode, so the storage width should multiply 2.
+ //
+ CopyMem (&CurrentStatement->ExtraData.PwdData.MinSize, &((EFI_IFR_PASSWORD *)OpCodeData)->MinSize, sizeof (UINT16));
+ CopyMem (&CurrentStatement->ExtraData.PwdData.MaxSize, &((EFI_IFR_PASSWORD *)OpCodeData)->MaxSize, sizeof (UINT16));
+ CurrentStatement->StorageWidth = (UINT16)((UINTN)CurrentStatement->ExtraData.PwdData.MaxSize * sizeof (CHAR16));
+
+ CurrentStatement->Value.Type = EFI_IFR_TYPE_STRING;
+ CurrentStatement->Value.Buffer = AllocateZeroPool ((CurrentStatement->StorageWidth + sizeof (CHAR16)));
+ if (CurrentStatement->Value.Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CurrentStatement->Value.Value.string = NewHiiString ((CHAR16 *)CurrentStatement->Value.Buffer, FormSet->HiiHandle);
+
+ InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
+ break;
+
+ case EFI_IFR_DATE_OP:
+
+ CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
+ CurrentStatement->ExtraData.Flags = ((EFI_IFR_DATE *)OpCodeData)->Flags;
+ CurrentStatement->Value.Type = EFI_IFR_TYPE_DATE;
+
+ if ((CurrentStatement->ExtraData.Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_NORMAL) {
+ CurrentStatement->StorageWidth = (UINT16)sizeof (EFI_HII_DATE);
+
+ InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
+ } else {
+ //
+ // Don't assign storage for RTC type of date/time
+ //
+ CurrentStatement->Storage = NULL;
+ CurrentStatement->StorageWidth = 0;
+ }
+
+ break;
+
+ case EFI_IFR_TIME_OP:
+
+ CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
+ CurrentStatement->ExtraData.Flags = ((EFI_IFR_TIME *)OpCodeData)->Flags;
+ CurrentStatement->Value.Type = EFI_IFR_TYPE_TIME;
+
+ if ((CurrentStatement->ExtraData.Flags & QF_TIME_STORAGE) == QF_TIME_STORAGE_NORMAL) {
+ CurrentStatement->StorageWidth = (UINT16)sizeof (EFI_HII_TIME);
+
+ InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
+ } else {
+ //
+ // Don't assign storage for RTC type of date/time
+ //
+ CurrentStatement->Storage = NULL;
+ CurrentStatement->StorageWidth = 0;
+ }
+
+ break;
+
+ //
+ // Default
+ //
+ case EFI_IFR_DEFAULT_OP:
+
+ //
+ // EFI_IFR_DEFAULT appear in scope of a Question,
+ // It creates a default value for the current question.
+ // A Question may have more than one Default value which have different default types.
+ //
+ CurrentDefault = AllocateZeroPool (sizeof (HII_QUESTION_DEFAULT));
+ if (CurrentDefault == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CurrentDefault->Signature = HII_QUESTION_DEFAULT_SIGNATURE;
+
+ CurrentDefault->Value.Type = ((EFI_IFR_DEFAULT *)OpCodeData)->Type;
+ CopyMem (&CurrentDefault->DefaultId, &((EFI_IFR_DEFAULT *)OpCodeData)->DefaultId, sizeof (UINT16));
+ if (CurrentDefault->Value.Type == EFI_IFR_TYPE_BUFFER) {
+ CurrentDefault->Value.BufferLen = (UINT16)(OpCodeLength - OFFSET_OF (EFI_IFR_DEFAULT, Value));
+ CurrentDefault->Value.Buffer = AllocateCopyPool (CurrentDefault->Value.BufferLen, &((EFI_IFR_DEFAULT *)OpCodeData)->Value);
+ if (CurrentDefault->Value.Buffer == NULL) {
+ FreePool (CurrentDefault);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (ParentStatement->Operand == EFI_IFR_ORDERED_LIST_OP) {
+ ParentStatement->Value.BufferLen = CurrentDefault->Value.BufferLen;
+ CopyMem (ParentStatement->Value.Buffer, CurrentDefault->Value.Buffer, ParentStatement->Value.BufferLen);
+ }
+ } else {
+ CopyMem (&CurrentDefault->Value.Value, &((EFI_IFR_DEFAULT *)OpCodeData)->Value, OpCodeLength - OFFSET_OF (EFI_IFR_DEFAULT, Value));
+ ExtendValueToU64 (&CurrentDefault->Value);
+
+ CopyMem (&ParentStatement->Value.Value, &((EFI_IFR_DEFAULT *)OpCodeData)->Value, OpCodeLength - OFFSET_OF (EFI_IFR_DEFAULT, Value));
+ ExtendValueToU64 (&ParentStatement->Value);
+ }
+
+ //
+ // Insert to Default Value list of current Question
+ //
+ InsertTailList (&ParentStatement->DefaultListHead, &CurrentDefault->Link);
+
+ if (Scope != 0) {
+ InScopeDefault = TRUE;
+ }
+
+ break;
+
+ //
+ // Option
+ //
+ case EFI_IFR_ONE_OF_OPTION_OP:
+
+ if (ParentStatement == NULL) {
+ break;
+ }
+
+ CurrentDefault = NULL;
+ if (((ParentStatement->Operand == EFI_IFR_ORDERED_LIST_OP) || (ParentStatement->Operand == EFI_IFR_ONE_OF_OP)) &&
+ ((((EFI_IFR_ONE_OF_OPTION *)OpCodeData)->Flags & (EFI_IFR_OPTION_DEFAULT | EFI_IFR_OPTION_DEFAULT_MFG)) != 0))
+ {
+ CurrentDefault = AllocateZeroPool (sizeof (HII_QUESTION_DEFAULT));
+ if (CurrentDefault == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CurrentDefault->Signature = HII_QUESTION_DEFAULT_SIGNATURE;
+ if ((((EFI_IFR_ONE_OF_OPTION *)OpCodeData)->Flags & EFI_IFR_OPTION_DEFAULT) != 0) {
+ CurrentDefault->DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
+ } else {
+ CurrentDefault->DefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
+ }
+
+ if (ParentStatement->Operand == EFI_IFR_ORDERED_LIST_OP) {
+ CurrentDefault->Value.Type = EFI_IFR_TYPE_BUFFER;
+ CurrentDefault->Value.BufferLen = (UINT16)(OpCodeLength - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
+ CurrentDefault->Value.Buffer = AllocateCopyPool (CurrentDefault->Value.BufferLen, &((EFI_IFR_ONE_OF_OPTION *)OpCodeData)->Value);
+ if (CurrentDefault->Value.Buffer == NULL) {
+ FreePool (CurrentDefault);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ } else {
+ CurrentDefault->Value.Type = ((EFI_IFR_ONE_OF_OPTION *)OpCodeData)->Type;
+ CopyMem (&CurrentDefault->Value.Value, &((EFI_IFR_ONE_OF_OPTION *)OpCodeData)->Value, sizeof (EFI_IFR_TYPE_VALUE));
+ ExtendValueToU64 (&CurrentDefault->Value);
+ }
+
+ //
+ // Insert to Default Value list of current Question
+ //
+ InsertTailList (&ParentStatement->DefaultListHead, &CurrentDefault->Link);
+ }
+
+ //
+ // EFI_IFR_ONE_OF_OPTION appear in scope of a Question.
+ // It create a selection for use in current Question.
+ //
+ CurrentOption = AllocateZeroPool (sizeof (HII_QUESTION_OPTION));
+ if (CurrentOption == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CurrentOption->Signature = HII_QUESTION_OPTION_SIGNATURE;
+ CurrentOption->OpCode = (EFI_IFR_ONE_OF_OPTION *)OpCodeData;
+ CurrentOption->Flags = ((EFI_IFR_ONE_OF_OPTION *)OpCodeData)->Flags;
+ CurrentOption->Value.Type = ((EFI_IFR_ONE_OF_OPTION *)OpCodeData)->Type;
+ CopyMem (&CurrentOption->Text, &((EFI_IFR_ONE_OF_OPTION *)OpCodeData)->Option, sizeof (EFI_STRING_ID));
+ CopyMem (&CurrentOption->Value.Value, &((EFI_IFR_ONE_OF_OPTION *)OpCodeData)->Value, OpCodeLength - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
+ ExtendValueToU64 (&CurrentOption->Value);
+
+ ConditionalExprCount = GetConditionalExpressionCount (ExpressOption);
+ if ( ConditionalExprCount > 0) {
+ //
+ // Form is inside of suppressif
+ //
+ CurrentOption->SuppressExpression = (HII_EXPRESSION_LIST *)AllocatePool (
+ (UINTN)(sizeof (HII_EXPRESSION_LIST) + ((ConditionalExprCount -1) * sizeof (HII_EXPRESSION *)))
+ );
+ if (CurrentOption->SuppressExpression == NULL) {
+ FreePool (CurrentOption);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CurrentOption->SuppressExpression->Count = (UINTN)ConditionalExprCount;
+ CurrentOption->SuppressExpression->Signature = HII_EXPRESSION_LIST_SIGNATURE;
+ CopyMem (CurrentOption->SuppressExpression->Expression, GetConditionalExpressionList (ExpressOption), (UINTN)(sizeof (HII_EXPRESSION *) * ConditionalExprCount));
+ }
+
+ //
+ // Insert to Option list of current Question
+ //
+ InsertTailList (&ParentStatement->OptionListHead, &CurrentOption->Link);
+
+ //
+ // Now we know the Storage width of nested Ordered List
+ //
+ if ((ParentStatement->Operand == EFI_IFR_ORDERED_LIST_OP) && (ParentStatement->Value.Buffer == NULL)) {
+ Width = 1;
+ switch (CurrentOption->Value.Type) {
+ case EFI_IFR_TYPE_NUM_SIZE_8:
+ Width = 1;
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_16:
+ Width = 2;
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_32:
+ Width = 4;
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_64:
+ Width = 8;
+ break;
+
+ default:
+ //
+ // Invalid type for Ordered List
+ //
+ break;
+ }
+
+ ParentStatement->StorageWidth = (UINT16)(ParentStatement->ExtraData.OrderListData.MaxContainers * Width);
+ ParentStatement->Value.Buffer = AllocateZeroPool (ParentStatement->StorageWidth);
+ if (ParentStatement->Value.Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ParentStatement->Value.BufferLen = 0;
+ ParentStatement->Value.BufferValueType = CurrentOption->Value.Type;
+ InitializeRequestElement (FormSet, ParentStatement, CurrentForm);
+ }
+
+ break;
+
+ //
+ // Conditional
+ //
+ case EFI_IFR_NO_SUBMIT_IF_OP:
+ case EFI_IFR_INCONSISTENT_IF_OP:
+
+ //
+ // Create an Expression node
+ //
+ CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
+ CopyMem (&CurrentExpression->ExtraData.Error, &((EFI_IFR_INCONSISTENT_IF *)OpCodeData)->Error, sizeof (EFI_STRING_ID));
+
+ if (Operand == EFI_IFR_NO_SUBMIT_IF_OP) {
+ CurrentExpression->Type = EFI_HII_EXPRESSION_NO_SUBMIT_IF;
+ InsertTailList (&ParentStatement->NoSubmitListHead, &CurrentExpression->Link);
+ } else {
+ CurrentExpression->Type = EFI_HII_EXPRESSION_INCONSISTENT_IF;
+ InsertTailList (&ParentStatement->InconsistentListHead, &CurrentExpression->Link);
+ }
+
+ //
+ // Take a look at next OpCode to see whether current expression consists
+ // of single OpCode
+ //
+ if (((EFI_IFR_OP_HEADER *)(OpCodeData + OpCodeLength))->Scope == 0) {
+ SingleOpCodeExpression = TRUE;
+ }
+
+ break;
+
+ case EFI_IFR_WARNING_IF_OP:
+
+ //
+ // Create an Expression node
+ //
+ CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
+ CopyMem (&CurrentExpression->ExtraData.WarningIfData.WarningIfError, &((EFI_IFR_WARNING_IF *)OpCodeData)->Warning, sizeof (EFI_STRING_ID));
+ CurrentExpression->ExtraData.WarningIfData.TimeOut = ((EFI_IFR_WARNING_IF *)OpCodeData)->TimeOut;
+ CurrentExpression->Type = EFI_HII_EXPRESSION_WARNING_IF;
+ InsertTailList (&ParentStatement->WarningListHead, &CurrentExpression->Link);
+
+ //
+ // Take a look at next OpCode to see whether current expression consists
+ // of single OpCode
+ //
+ if (((EFI_IFR_OP_HEADER *)(OpCodeData + OpCodeLength))->Scope == 0) {
+ SingleOpCodeExpression = TRUE;
+ }
+
+ break;
+
+ case EFI_IFR_SUPPRESS_IF_OP:
+
+ //
+ // Question and Option will appear in scope of this OpCode
+ //
+ CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
+ CurrentExpression->Type = EFI_HII_EXPRESSION_SUPPRESS_IF;
+
+ if (SuppressForOption) {
+ PushConditionalExpression (CurrentExpression, ExpressOption);
+ } else if (SuppressForQuestion) {
+ PushConditionalExpression (CurrentExpression, ExpressStatement);
+ } else {
+ PushConditionalExpression (CurrentExpression, ExpressForm);
+ }
+
+ //
+ // Take a look at next OpCode to see whether current expression consists
+ // of single OpCode
+ //
+ if (((EFI_IFR_OP_HEADER *)(OpCodeData + OpCodeLength))->Scope == 0) {
+ SingleOpCodeExpression = TRUE;
+ }
+
+ break;
+
+ case EFI_IFR_GRAY_OUT_IF_OP:
+
+ //
+ // Questions will appear in scope of this OpCode
+ //
+ CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
+ CurrentExpression->Type = EFI_HII_EXPRESSION_GRAY_OUT_IF;
+ PushConditionalExpression (CurrentExpression, ExpressStatement);
+
+ //
+ // Take a look at next OpCode to see whether current expression consists
+ // of single OpCode
+ //
+ if (((EFI_IFR_OP_HEADER *)(OpCodeData + OpCodeLength))->Scope == 0) {
+ SingleOpCodeExpression = TRUE;
+ }
+
+ break;
+
+ case EFI_IFR_DISABLE_IF_OP:
+
+ //
+ // The DisableIf expression should only rely on constant, so it could be
+ // evaluated at initialization and it will not be queued
+ //
+ CurrentExpression = AllocateZeroPool (sizeof (HII_EXPRESSION));
+ if (CurrentExpression == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CurrentExpression->Signature = HII_EXPRESSION_SIGNATURE;
+ CurrentExpression->Type = EFI_HII_EXPRESSION_DISABLE_IF;
+ InitializeListHead (&CurrentExpression->OpCodeListHead);
+
+ if (CurrentForm != NULL) {
+ //
+ // This is DisableIf for Question, enqueue it to Form expression list
+ //
+ PushConditionalExpression (CurrentExpression, ExpressStatement);
+ }
+
+ OpCodeDisabled = FALSE;
+ InScopeDisable = TRUE;
+ //
+ // Take a look at next OpCode to see whether current expression consists
+ // of single OpCode
+ //
+ if (((EFI_IFR_OP_HEADER *)(OpCodeData + OpCodeLength))->Scope == 0) {
+ SingleOpCodeExpression = TRUE;
+ }
+
+ break;
+
+ //
+ // Expression
+ //
+ case EFI_IFR_VALUE_OP:
+
+ CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
+ CurrentExpression->Type = EFI_HII_EXPRESSION_VALUE;
+
+ if (InScopeDefault) {
+ //
+ // Used for default (EFI_IFR_DEFAULT)
+ //
+ CurrentDefault->ValueExpression = CurrentExpression;
+ } else {
+ //
+ // If used for a question, then the question will be read-only
+ //
+ // Make sure CurrentStatement is not NULL.
+ // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
+ // file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler.
+ //
+ if (ParentStatement == NULL) {
+ break;
+ }
+
+ ParentStatement->ValueExpression = CurrentExpression;
+ }
+
+ //
+ // Take a look at next OpCode to see whether current expression consists
+ // of single OpCode
+ //
+ if (((EFI_IFR_OP_HEADER *)(OpCodeData + OpCodeLength))->Scope == 0) {
+ SingleOpCodeExpression = TRUE;
+ }
+
+ break;
+
+ case EFI_IFR_RULE_OP:
+
+ CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
+ CurrentExpression->Type = EFI_HII_EXPRESSION_RULE;
+
+ CurrentExpression->ExtraData.RuleId = ((EFI_IFR_RULE *)OpCodeData)->RuleId;
+ InsertTailList (&CurrentForm->RuleListHead, &CurrentExpression->Link);
+
+ //
+ // Take a look at next OpCode to see whether current expression consists
+ // of single OpCode
+ //
+ if (((EFI_IFR_OP_HEADER *)(OpCodeData + OpCodeLength))->Scope == 0) {
+ SingleOpCodeExpression = TRUE;
+ }
+
+ break;
+
+ case EFI_IFR_READ_OP:
+
+ CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
+ CurrentExpression->Type = EFI_HII_EXPRESSION_READ;
+
+ //
+ // Make sure CurrentStatement is not NULL.
+ // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
+ // file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler.
+ //
+ if (ParentStatement == NULL) {
+ break;
+ }
+
+ ParentStatement->ReadExpression = CurrentExpression;
+
+ //
+ // Take a look at next OpCode to see whether current expression consists
+ // of single OpCode
+ //
+ if (((EFI_IFR_OP_HEADER *)(OpCodeData + OpCodeLength))->Scope == 0) {
+ SingleOpCodeExpression = TRUE;
+ }
+
+ break;
+
+ case EFI_IFR_WRITE_OP:
+
+ CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
+ CurrentExpression->Type = EFI_HII_EXPRESSION_WRITE;
+
+ //
+ // Make sure CurrentStatement is not NULL.
+ // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
+ // file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler.
+ //
+ if (ParentStatement == NULL) {
+ break;
+ }
+
+ ParentStatement->WriteExpression = CurrentExpression;
+
+ //
+ // Take a look at next OpCode to see whether current expression consists
+ // of single OpCode
+ //
+ if (((EFI_IFR_OP_HEADER *)(OpCodeData + OpCodeLength))->Scope == 0) {
+ SingleOpCodeExpression = TRUE;
+ }
+
+ break;
+
+ //
+ // Image
+ //
+ case EFI_IFR_IMAGE_OP:
+ //
+ // Get ScopeOpcode from top of stack
+ //
+ PopScope (&ScopeOpCode);
+ PushScope (ScopeOpCode);
+
+ switch (ScopeOpCode) {
+ case EFI_IFR_FORM_SET_OP:
+
+ ImageId = &FormSet->ImageId;
+ break;
+
+ case EFI_IFR_FORM_OP:
+ case EFI_IFR_FORM_MAP_OP:
+
+ if (CurrentForm != NULL) {
+ ImageId = &CurrentForm->ImageId;
+ }
+
+ break;
+
+ case EFI_IFR_ONE_OF_OPTION_OP:
+
+ if (CurrentOption != NULL) {
+ ImageId = &CurrentOption->ImageId;
+ }
+
+ break;
+
+ default:
+
+ //
+ // Make sure CurrentStatement is not NULL.
+ // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
+ // file is wrongly generated by tools such as VFR Compiler.
+ //
+ if (ParentStatement != NULL) {
+ ImageId = &ParentStatement->ImageId;
+ }
+
+ break;
+ }
+
+ CopyMem (ImageId, &((EFI_IFR_IMAGE *)OpCodeData)->Id, sizeof (EFI_IMAGE_ID));
+ break;
+
+ //
+ // Refresh
+ //
+ case EFI_IFR_REFRESH_OP:
+
+ if (ParentStatement != NULL) {
+ ParentStatement->RefreshInterval = ((EFI_IFR_REFRESH *)OpCodeData)->RefreshInterval;
+ }
+
+ break;
+
+ //
+ // Refresh guid.
+ //
+ case EFI_IFR_REFRESH_ID_OP:
+ //
+ // Get ScopeOpcode from top of stack
+ //
+ PopScope (&ScopeOpCode);
+ PushScope (ScopeOpCode);
+
+ switch (ScopeOpCode) {
+ case EFI_IFR_FORM_OP:
+ case EFI_IFR_FORM_MAP_OP:
+
+ if (CurrentForm != NULL) {
+ CopyMem (&CurrentForm->RefreshGuid, &((EFI_IFR_REFRESH_ID *)OpCodeData)->RefreshEventGroupId, sizeof (EFI_GUID));
+ }
+
+ break;
+
+ default:
+
+ if (ParentStatement != NULL) {
+ if (ParentStatement->Operand == EFI_IFR_NUMERIC_OP) {
+ CopyMem (&ParentStatement->ExtraData.NumData.Guid, &((EFI_IFR_REFRESH_ID *)OpCodeData)->RefreshEventGroupId, sizeof (EFI_GUID));
+ }
+ }
+
+ break;
+ }
+
+ break;
+
+ //
+ // Modal tag
+ //
+ case EFI_IFR_MODAL_TAG_OP:
+
+ if (CurrentForm != NULL) {
+ CurrentForm->ModalForm = TRUE;
+ }
+
+ break;
+
+ //
+ // Lock tag, used by form and statement.
+ //
+ case EFI_IFR_LOCKED_OP:
+ //
+ // Get ScopeOpcode from top of stack
+ //
+ PopScope (&ScopeOpCode);
+ PushScope (ScopeOpCode);
+
+ switch (ScopeOpCode) {
+ case EFI_IFR_FORM_OP:
+ case EFI_IFR_FORM_MAP_OP:
+
+ if (CurrentForm != NULL) {
+ CurrentForm->Locked = TRUE;
+ }
+
+ break;
+
+ default:
+
+ if (ParentStatement != NULL) {
+ ParentStatement->Locked = TRUE;
+ }
+ }
+
+ break;
+
+ //
+ // Vendor specific
+ //
+ case EFI_IFR_GUID_OP:
+ CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
+ if (CompareGuid ((EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)), &gEdkiiIfrBitVarstoreGuid)) {
+ Scope = 0;
+ QuestionReferBitField = TRUE;
+ }
+
+ break;
+
+ //
+ // Scope End
+ //
+ case EFI_IFR_END_OP:
+ QuestionReferBitField = FALSE;
+ Status = PopScope (&ScopeOpCode);
+ if (EFI_ERROR (Status)) {
+ ResetScopeStack ();
+ return Status;
+ }
+
+ //
+ // Parent statement end tag found, update ParentStatement info.
+ //
+ if (IsStatementOpCode (ScopeOpCode) && (ParentStatement != NULL) && (ParentStatement->Operand == ScopeOpCode)) {
+ ParentStatement = ParentStatement->ParentStatement;
+ }
+
+ switch (ScopeOpCode) {
+ case EFI_IFR_FORM_SET_OP:
+ //
+ // End of FormSet, update FormSet IFR binary length
+ // to stop parsing substantial OpCodes
+ //
+ FormSet->IfrBinaryLength = OpCodeOffset;
+ break;
+
+ case EFI_IFR_FORM_OP:
+ case EFI_IFR_FORM_MAP_OP:
+ //
+ // End of Form
+ //
+ CurrentForm = NULL;
+ SuppressForQuestion = FALSE;
+ break;
+
+ case EFI_IFR_ONE_OF_OPTION_OP:
+ //
+ // End of Option
+ //
+ CurrentOption = NULL;
+ break;
+
+ case EFI_IFR_NO_SUBMIT_IF_OP:
+ case EFI_IFR_INCONSISTENT_IF_OP:
+ case EFI_IFR_WARNING_IF_OP:
+ //
+ // Ignore end of EFI_IFR_NO_SUBMIT_IF and EFI_IFR_INCONSISTENT_IF
+ //
+ break;
+
+ case EFI_IFR_SUPPRESS_IF_OP:
+ if (SuppressForOption) {
+ PopConditionalExpression (ExpressOption);
+ } else if (SuppressForQuestion) {
+ PopConditionalExpression (ExpressStatement);
+ } else {
+ PopConditionalExpression (ExpressForm);
+ }
+
+ break;
+
+ case EFI_IFR_GRAY_OUT_IF_OP:
+ PopConditionalExpression (ExpressStatement);
+ break;
+
+ case EFI_IFR_DISABLE_IF_OP:
+ if (CurrentForm != NULL) {
+ PopConditionalExpression (ExpressStatement);
+ }
+
+ InScopeDisable = FALSE;
+ OpCodeDisabled = FALSE;
+ break;
+
+ case EFI_IFR_ONE_OF_OP:
+ case EFI_IFR_ORDERED_LIST_OP:
+ SuppressForOption = FALSE;
+ break;
+
+ case EFI_IFR_DEFAULT_OP:
+ InScopeDefault = FALSE;
+ break;
+
+ case EFI_IFR_MAP_OP:
+
+ //
+ // Get current Map Expression List.
+ //
+ Status = PopMapExpressionList ((VOID **)&MapExpressionList);
+ if (Status == EFI_ACCESS_DENIED) {
+ MapExpressionList = NULL;
+ }
+
+ //
+ // Get current expression.
+ //
+ Status = PopCurrentExpression ((VOID **)&CurrentExpression);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (MapScopeDepth > 0) {
+ MapScopeDepth--;
+ }
+
+ break;
+
+ default:
+
+ if (IsExpressionOpCode (ScopeOpCode)) {
+ if (InScopeDisable && (CurrentForm == NULL)) {
+ //
+ // This is DisableIf expression for Form, it should be a constant expression
+ //
+ Status = EvaluateHiiExpression (FormSet, CurrentForm, CurrentExpression);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ OpCodeDisabled = IsHiiValueTrue (&CurrentExpression->Result);
+
+ //
+ // DisableIf Expression is only used once and not queued, free it
+ //
+ DestroyExpression (CurrentExpression);
+ }
+
+ //
+ // End of current Expression
+ //
+ CurrentExpression = NULL;
+ }
+
+ break;
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ if (IsStatementOpCode (Operand)) {
+ CurrentStatement->ParentStatement = ParentStatement;
+ if (Scope != 0) {
+ //
+ // Scope != 0, other statements or options may nest in this statement.
+ // Update the ParentStatement info.
+ //
+ ParentStatement = CurrentStatement;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiUtilityInternal.c b/RedfishPkg/Library/HiiUtilityLib/HiiUtilityInternal.c
new file mode 100644
index 000000000000..80b93beae999
--- /dev/null
+++ b/RedfishPkg/Library/HiiUtilityLib/HiiUtilityInternal.c
@@ -0,0 +1,5770 @@
+/** @file
+ HII utility internal functions.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+ Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "HiiInternal.h"
+
+CHAR16 *mUnknownString = L"!";
+CHAR16 *gEmptyString = L"";
+
+EFI_HII_VALUE *mExpressionEvaluationStack = NULL;
+EFI_HII_VALUE *mExpressionEvaluationStackEnd = NULL;
+EFI_HII_VALUE *mExpressionEvaluationStackPointer = NULL;
+UINTN mExpressionEvaluationStackOffset = 0;
+
+//
+// Unicode collation protocol interface
+//
+EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollation = NULL;
+EFI_USER_MANAGER_PROTOCOL *mUserManager = NULL;
+
+/**
+ Allocate new memory and then copy the Unicode string Source to Destination.
+
+ @param[in,out] Dest Location to copy string
+ @param[in] Src String to copy
+
+**/
+VOID
+NewStringCopy (
+ IN OUT CHAR16 **Dest,
+ IN CHAR16 *Src
+ )
+{
+ if (*Dest != NULL) {
+ FreePool (*Dest);
+ }
+
+ *Dest = AllocateCopyPool (StrSize (Src), Src);
+}
+
+/**
+ Set Value of given Name in a NameValue Storage.
+
+ @param[in] Storage The NameValue Storage.
+ @param[in] Name The Name.
+ @param[in] Value The Value to set.
+ @param[out] ReturnNode The node use the input name.
+
+ @retval EFI_SUCCESS Value found for given Name.
+ @retval EFI_NOT_FOUND No such Name found in NameValue storage.
+
+**/
+EFI_STATUS
+SetValueByName (
+ IN HII_FORMSET_STORAGE *Storage,
+ IN CHAR16 *Name,
+ IN CHAR16 *Value,
+ OUT HII_NAME_VALUE_NODE **ReturnNode
+ )
+{
+ LIST_ENTRY *Link;
+ HII_NAME_VALUE_NODE *Node;
+ CHAR16 *Buffer;
+
+ Link = GetFirstNode (&Storage->NameValueList);
+ while (!IsNull (&Storage->NameValueList, Link)) {
+ Node = HII_NAME_VALUE_NODE_FROM_LINK (Link);
+
+ if (StrCmp (Name, Node->Name) == 0) {
+ Buffer = Node->Value;
+ if (Buffer != NULL) {
+ FreePool (Buffer);
+ }
+
+ Buffer = AllocateCopyPool (StrSize (Value), Value);
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Node->Value = Buffer;
+
+ if (ReturnNode != NULL) {
+ *ReturnNode = Node;
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ Link = GetNextNode (&Storage->NameValueList, Link);
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Get bit field value from the buffer and then set the value for the question.
+ Note: Data type UINT32 can cover all the bit field value.
+
+ @param[in] Question The question refer to bit field.
+ @param[in] Buffer Point to the buffer which the question value get from.
+ @param[out] QuestionValue The Question Value retrieved from Bits.
+
+**/
+VOID
+GetBitsQuestionValue (
+ IN HII_STATEMENT *Question,
+ IN UINT8 *Buffer,
+ OUT HII_STATEMENT_VALUE *QuestionValue
+ )
+{
+ UINTN StartBit;
+ UINTN EndBit;
+ UINT32 RetVal;
+ UINT32 BufferValue;
+
+ StartBit = Question->BitVarOffset % 8;
+ EndBit = StartBit + Question->BitStorageWidth - 1;
+
+ CopyMem ((UINT8 *)&BufferValue, Buffer, Question->StorageWidth);
+
+ RetVal = BitFieldRead32 (BufferValue, StartBit, EndBit);
+
+ //
+ // Set question value.
+ // Note: Since Question with BufferValue (orderedlist, password, string)are not supported to refer bit field.
+ // Only oneof/checkbox/oneof can support bit field.So we can copy the value to the HiiValue of Question directly.
+ //
+ CopyMem ((UINT8 *)&QuestionValue->Value, (UINT8 *)&RetVal, Question->StorageWidth);
+}
+
+/**
+ Set bit field value to the buffer.
+ Note: Data type UINT32 can cover all the bit field value.
+
+ @param[in] Question The question refer to bit field.
+ @param[in,out] Buffer Point to the buffer which the question value set to.
+ @param[in] Value The bit field value need to set.
+
+**/
+VOID
+SetBitsQuestionValue (
+ IN HII_STATEMENT *Question,
+ IN OUT UINT8 *Buffer,
+ IN UINT32 Value
+ )
+{
+ UINT32 Operand;
+ UINTN StartBit;
+ UINTN EndBit;
+ UINT32 RetVal;
+
+ StartBit = Question->BitVarOffset % 8;
+ EndBit = StartBit + Question->BitStorageWidth - 1;
+
+ CopyMem ((UINT8 *)&Operand, Buffer, Question->StorageWidth);
+ RetVal = BitFieldWrite32 (Operand, StartBit, EndBit, Value);
+ CopyMem (Buffer, (UINT8 *)&RetVal, Question->StorageWidth);
+}
+
+/**
+ Convert the buffer value to HiiValue.
+
+ @param[in] Question The question.
+ @param[in] Value Unicode buffer save the question value.
+ @param[out] QuestionValue The Question Value retrieved from Buffer.
+
+ @retval Status whether convert the value success.
+
+**/
+EFI_STATUS
+BufferToQuestionValue (
+ IN HII_STATEMENT *Question,
+ IN CHAR16 *Value,
+ OUT HII_STATEMENT_VALUE *QuestionValue
+ )
+{
+ CHAR16 *StringPtr;
+ BOOLEAN IsBufferStorage;
+ CHAR16 *DstBuf;
+ CHAR16 TempChar;
+ UINTN LengthStr;
+ UINT8 *Dst;
+ CHAR16 TemStr[5];
+ UINTN Index;
+ UINT8 DigitUint8;
+ BOOLEAN IsString;
+ UINTN Length;
+ EFI_STATUS Status;
+ UINT8 *Buffer;
+
+ Buffer = NULL;
+
+ IsString = (BOOLEAN)((QuestionValue->Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);
+ if ((Question->Storage->Type == EFI_HII_VARSTORE_BUFFER) ||
+ (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER))
+ {
+ IsBufferStorage = TRUE;
+ } else {
+ IsBufferStorage = FALSE;
+ }
+
+ //
+ // Question Value is provided by Buffer Storage or NameValue Storage
+ //
+ if ((QuestionValue->Type == EFI_IFR_TYPE_STRING) || (QuestionValue->Type == EFI_IFR_TYPE_BUFFER)) {
+ //
+ // This Question is password or orderedlist
+ //
+ if (QuestionValue->Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Dst = QuestionValue->Buffer;
+ } else {
+ //
+ // Other type of Questions
+ //
+ if (Question->QuestionReferToBitField) {
+ Buffer = (UINT8 *)AllocateZeroPool (Question->StorageWidth);
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Dst = Buffer;
+ } else {
+ Dst = (UINT8 *)&QuestionValue->Value;
+ }
+ }
+
+ //
+ // Temp cut at the end of this section, end with '\0' or '&'.
+ //
+ StringPtr = Value;
+ while (*StringPtr != L'\0' && *StringPtr != L'&') {
+ StringPtr++;
+ }
+
+ TempChar = *StringPtr;
+ *StringPtr = L'\0';
+
+ LengthStr = StrLen (Value);
+
+ //
+ // Value points to a Unicode hexadecimal string, we need to convert the string to the value with CHAR16/UINT8...type.
+ // When generating the Value string, we follow this rule: 1 byte -> 2 Unicode characters (for string: 2 byte(CHAR16) ->4 Unicode characters).
+ // So the maximum value string length of a question is : Question->StorageWidth * 2.
+ // If the value string length > Question->StorageWidth * 2, only set the string length as Question->StorageWidth * 2, then convert.
+ //
+ if (LengthStr > (UINTN)Question->StorageWidth * 2) {
+ Length = (UINTN)Question->StorageWidth * 2;
+ } else {
+ Length = LengthStr;
+ }
+
+ Status = EFI_SUCCESS;
+ if (!IsBufferStorage && IsString) {
+ //
+ // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
+ // Add string tail char L'\0' into Length
+ //
+ DstBuf = (CHAR16 *)Dst;
+ ZeroMem (TemStr, sizeof (TemStr));
+ for (Index = 0; Index < Length; Index += 4) {
+ StrnCpyS (TemStr, sizeof (TemStr) / sizeof (CHAR16), Value + Index, 4);
+ DstBuf[Index/4] = (CHAR16)StrHexToUint64 (TemStr);
+ }
+
+ //
+ // Add tailing L'\0' character
+ //
+ DstBuf[Index/4] = L'\0';
+ } else {
+ ZeroMem (TemStr, sizeof (TemStr));
+ for (Index = 0; Index < Length; Index++) {
+ TemStr[0] = Value[LengthStr - Index - 1];
+ DigitUint8 = (UINT8)StrHexToUint64 (TemStr);
+ if ((Index & 1) == 0) {
+ Dst[Index/2] = DigitUint8;
+ } else {
+ Dst[Index/2] = (UINT8)((DigitUint8 << 4) + Dst[Index/2]);
+ }
+ }
+ }
+
+ *StringPtr = TempChar;
+
+ if ((Buffer != NULL) && Question->QuestionReferToBitField) {
+ GetBitsQuestionValue (Question, Buffer, QuestionValue);
+ FreePool (Buffer);
+ }
+
+ return Status;
+}
+
+/**
+ Get the string based on the StringId and HII Package List Handle.
+
+ @param[in] Token The String's ID.
+ @param[in] HiiHandle The package list in the HII database to search for
+ the specified string.
+
+ @return The output string.
+
+**/
+CHAR16 *
+GetTokenString (
+ IN EFI_STRING_ID Token,
+ IN EFI_HII_HANDLE HiiHandle
+ )
+{
+ EFI_STRING String;
+
+ if (HiiHandle == NULL) {
+ return NULL;
+ }
+
+ String = HiiGetString (HiiHandle, Token, NULL);
+ if (String == NULL) {
+ String = AllocateCopyPool (StrSize (mUnknownString), mUnknownString);
+ if (String == NULL) {
+ return NULL;
+ }
+ }
+
+ return (CHAR16 *)String;
+}
+
+/**
+ Converts the unicode character of the string from uppercase to lowercase.
+ This is a internal function.
+
+ @param[in] ConfigString String to be converted
+
+**/
+VOID
+EFIAPI
+HiiStringToLowercase (
+ IN EFI_STRING ConfigString
+ )
+{
+ EFI_STRING String;
+ BOOLEAN Lower;
+
+ //
+ // Convert all hex digits in range [A-F] in the configuration header to [a-f]
+ //
+ for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {
+ if (*String == L'=') {
+ Lower = TRUE;
+ } else if (*String == L'&') {
+ Lower = FALSE;
+ } else if (Lower && (*String >= L'A') && (*String <= L'F')) {
+ *String = (CHAR16)(*String - L'A' + L'a');
+ }
+ }
+}
+
+/**
+ Evaluate if the result is a non-zero value.
+
+ @param[in] Result The result to be evaluated.
+
+ @retval TRUE It is a non-zero value.
+ @retval FALSE It is a zero value.
+
+**/
+BOOLEAN
+IsHiiValueTrue (
+ IN EFI_HII_VALUE *Result
+ )
+{
+ switch (Result->Type) {
+ case EFI_IFR_TYPE_BOOLEAN:
+ return Result->Value.b;
+
+ case EFI_IFR_TYPE_NUM_SIZE_8:
+ return (BOOLEAN)(Result->Value.u8 != 0);
+
+ case EFI_IFR_TYPE_NUM_SIZE_16:
+ return (BOOLEAN)(Result->Value.u16 != 0);
+
+ case EFI_IFR_TYPE_NUM_SIZE_32:
+ return (BOOLEAN)(Result->Value.u32 != 0);
+
+ case EFI_IFR_TYPE_NUM_SIZE_64:
+ return (BOOLEAN)(Result->Value.u64 != 0);
+
+ default:
+ return FALSE;
+ }
+}
+
+/**
+ Set a new string to string package.
+
+ @param[in] String A pointer to the Null-terminated Unicode string
+ to add or update in the String Package associated
+ with HiiHandle.
+ @param[in] HiiHandle A handle that was previously registered in the
+ HII Database.
+
+ @return the Id for this new string.
+
+**/
+EFI_STRING_ID
+NewHiiString (
+ IN CHAR16 *String,
+ IN EFI_HII_HANDLE HiiHandle
+ )
+{
+ EFI_STRING_ID StringId;
+
+ StringId = HiiSetString (HiiHandle, 0, String, NULL);
+ return StringId;
+}
+
+/**
+ Perform nosubmitif check for a Form.
+
+ @param[in] FormSet FormSet data structure.
+ @param[in] Form Form data structure.
+ @param[in] Question The Question to be validated.
+
+ @retval EFI_SUCCESS Form validation pass.
+ @retval other Form validation failed.
+
+**/
+EFI_STATUS
+ValidateNoSubmit (
+ IN HII_FORMSET *FormSet,
+ IN HII_FORM *Form,
+ IN HII_STATEMENT *Question
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ LIST_ENTRY *ListHead;
+ HII_EXPRESSION *Expression;
+
+ ListHead = &Question->NoSubmitListHead;
+ Link = GetFirstNode (ListHead);
+ while (!IsNull (ListHead, Link)) {
+ Expression = HII_EXPRESSION_FROM_LINK (Link);
+
+ //
+ // Evaluate the expression
+ //
+ Status = EvaluateHiiExpression (FormSet, Form, Expression);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (IsHiiValueTrue (&Expression->Result)) {
+ return EFI_NOT_READY;
+ }
+
+ Link = GetNextNode (ListHead, Link);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Perform NoSubmit check for each Form in FormSet.
+
+ @param[in] FormSet FormSet data structure.
+ @param[in,out] CurrentForm Current input form data structure.
+ @param[out] Statement The statement for this check.
+
+ @retval EFI_SUCCESS Form validation pass.
+ @retval other Form validation failed.
+
+**/
+EFI_STATUS
+NoSubmitCheck (
+ IN HII_FORMSET *FormSet,
+ IN OUT HII_FORM **CurrentForm,
+ OUT HII_STATEMENT **Statement
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ HII_STATEMENT *Question;
+ HII_FORM *Form;
+ LIST_ENTRY *LinkForm;
+
+ LinkForm = GetFirstNode (&FormSet->FormListHead);
+ while (!IsNull (&FormSet->FormListHead, LinkForm)) {
+ Form = HII_FORM_FROM_LINK (LinkForm);
+ LinkForm = GetNextNode (&FormSet->FormListHead, LinkForm);
+
+ if ((*CurrentForm != NULL) && (*CurrentForm != Form)) {
+ continue;
+ }
+
+ Link = GetFirstNode (&Form->StatementListHead);
+ while (!IsNull (&Form->StatementListHead, Link)) {
+ Question = HII_STATEMENT_FROM_LINK (Link);
+ Status = ValidateNoSubmit (FormSet, Form, Question);
+ if (EFI_ERROR (Status)) {
+ if (*CurrentForm == NULL) {
+ *CurrentForm = Form;
+ }
+
+ if (Statement != NULL) {
+ *Statement = Question;
+ }
+
+ return Status;
+ }
+
+ Link = GetNextNode (&Form->StatementListHead, Link);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Allocate new memory and concatenate Source on the end of Destination.
+
+ @param Dest String to added to the end of.
+ @param Src String to concatenate.
+
+**/
+VOID
+NewStringCat (
+ IN OUT CHAR16 **Dest,
+ IN CHAR16 *Src
+ )
+{
+ CHAR16 *NewHiiString;
+ UINTN MaxLen;
+
+ if (*Dest == NULL) {
+ NewStringCopy (Dest, Src);
+ return;
+ }
+
+ MaxLen = (StrSize (*Dest) + StrSize (Src) - 2) / sizeof (CHAR16);
+ NewHiiString = AllocatePool (MaxLen * sizeof (CHAR16));
+ if (NewHiiString == NULL) {
+ return;
+ }
+
+ StrCpyS (NewHiiString, MaxLen, *Dest);
+ StrCatS (NewHiiString, MaxLen, Src);
+
+ FreePool (*Dest);
+ *Dest = NewHiiString;
+}
+
+/**
+ Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
+
+ @param[in] Storage The Storage to be converted.
+ @param[in] ConfigResp The returned <ConfigResp>.
+ @param[in] ConfigRequest The ConfigRequest string.
+
+ @retval EFI_SUCCESS Convert success.
+ @retval EFI_INVALID_PARAMETER Incorrect storage type.
+
+**/
+EFI_STATUS
+StorageToConfigResp (
+ IN HII_FORMSET_STORAGE *Storage,
+ IN CHAR16 **ConfigResp,
+ IN CHAR16 *ConfigRequest
+ )
+{
+ EFI_STATUS Status;
+ EFI_STRING Progress;
+ LIST_ENTRY *Link;
+ HII_NAME_VALUE_NODE *Node;
+ UINT8 *SourceBuf;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+ EFI_STRING TempConfigRequest;
+ UINTN RequestStrSize;
+
+ Status = EFI_SUCCESS;
+
+ if (Storage->ConfigHdr == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (ConfigRequest != NULL) {
+ TempConfigRequest = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);
+ if (TempConfigRequest == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ } else {
+ RequestStrSize = (StrLen (Storage->ConfigHdr) + StrLen (Storage->ConfigRequest) + 1) * sizeof (CHAR16);
+ TempConfigRequest = AllocatePool (RequestStrSize);
+ if (TempConfigRequest == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ UnicodeSPrint (
+ TempConfigRequest,
+ RequestStrSize,
+ L"%s%s",
+ Storage->ConfigHdr,
+ Storage->ConfigRequest
+ );
+ }
+
+ switch (Storage->Type) {
+ case EFI_HII_VARSTORE_BUFFER:
+ case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
+
+ Status = gBS->LocateProtocol (
+ &gEfiHiiConfigRoutingProtocolGuid,
+ NULL,
+ (VOID **)&HiiConfigRouting
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ SourceBuf = Storage->Buffer;
+ Status = HiiConfigRouting->BlockToConfig (
+ HiiConfigRouting,
+ TempConfigRequest,
+ SourceBuf,
+ Storage->Size,
+ ConfigResp,
+ &Progress
+ );
+ break;
+
+ case EFI_HII_VARSTORE_NAME_VALUE:
+
+ *ConfigResp = NULL;
+ NewStringCat (ConfigResp, Storage->ConfigHdr);
+
+ Link = GetFirstNode (&Storage->NameValueList);
+ while (!IsNull (&Storage->NameValueList, Link)) {
+ Node = HII_NAME_VALUE_NODE_FROM_LINK (Link);
+
+ if (StrStr (TempConfigRequest, Node->Name) != NULL) {
+ NewStringCat (ConfigResp, L"&");
+ NewStringCat (ConfigResp, Node->Name);
+ NewStringCat (ConfigResp, L"=");
+ NewStringCat (ConfigResp, Node->Value);
+ }
+
+ Link = GetNextNode (&Storage->NameValueList, Link);
+ }
+
+ break;
+
+ case EFI_HII_VARSTORE_EFI_VARIABLE:
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ return Status;
+}
+
+/**
+ Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
+
+ @param[in] Storage The Storage to receive the settings.
+ @param[in] ConfigResp The <ConfigResp> to be converted.
+
+ @retval EFI_SUCCESS Convert success.
+ @retval EFI_INVALID_PARAMETER Incorrect storage type.
+
+**/
+EFI_STATUS
+ConfigRespToStorage (
+ IN HII_FORMSET_STORAGE *Storage,
+ IN CHAR16 *ConfigResp
+ )
+{
+ EFI_STATUS Status;
+ EFI_STRING Progress;
+ UINTN BufferSize;
+ CHAR16 *StrPtr;
+ CHAR16 *Name;
+ CHAR16 *Value;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+
+ Status = EFI_SUCCESS;
+
+ switch (Storage->Type) {
+ case EFI_HII_VARSTORE_BUFFER:
+ case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
+
+ Status = gBS->LocateProtocol (
+ &gEfiHiiConfigRoutingProtocolGuid,
+ NULL,
+ (VOID **)&HiiConfigRouting
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ BufferSize = Storage->Size;
+ Status = HiiConfigRouting->ConfigToBlock (
+ HiiConfigRouting,
+ ConfigResp,
+ Storage->Buffer,
+ &BufferSize,
+ &Progress
+ );
+ break;
+
+ case EFI_HII_VARSTORE_NAME_VALUE:
+ StrPtr = StrStr (ConfigResp, L"PATH");
+ if (StrPtr == NULL) {
+ break;
+ }
+
+ StrPtr = StrStr (ConfigResp, L"&");
+ while (StrPtr != NULL) {
+ //
+ // Skip '&'
+ //
+ StrPtr = StrPtr + 1;
+ Name = StrPtr;
+ StrPtr = StrStr (StrPtr, L"=");
+ if (StrPtr == NULL) {
+ break;
+ }
+
+ *StrPtr = 0;
+
+ //
+ // Skip '='
+ //
+ StrPtr = StrPtr + 1;
+ Value = StrPtr;
+ StrPtr = StrStr (StrPtr, L"&");
+ if (StrPtr != NULL) {
+ *StrPtr = 0;
+ }
+
+ SetValueByName (Storage, Name, Value, NULL);
+ }
+
+ break;
+
+ case EFI_HII_VARSTORE_EFI_VARIABLE:
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ return Status;
+}
+
+/**
+ Fetch the Ifr binary data of a FormSet.
+
+ @param[in] Handle PackageList Handle
+ @param[in,out] FormSetGuid On input, GUID or class GUID of a formset. If not
+ specified (NULL or zero GUID), take the first
+ FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
+ found in package list.
+ On output, GUID of the formset found(if not NULL).
+ @param[out] BinaryLength The length of the FormSet IFR binary.
+ @param[out] BinaryData The buffer designed to receive the FormSet.
+
+ @retval EFI_SUCCESS Buffer filled with the requested FormSet.
+ BufferLength was updated.
+ @retval EFI_INVALID_PARAMETER The handle is unknown.
+ @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
+ be found with the requested FormId.
+
+**/
+EFI_STATUS
+GetIfrBinaryData (
+ IN EFI_HII_HANDLE Handle,
+ IN OUT EFI_GUID *FormSetGuid,
+ OUT UINTN *BinaryLength,
+ OUT UINT8 **BinaryData
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
+ UINTN BufferSize;
+ UINT8 *Package;
+ UINT8 *OpCodeData;
+ UINT32 Offset;
+ UINT32 Offset2;
+ UINT32 PackageListLength;
+ EFI_HII_PACKAGE_HEADER PackageHeader;
+ UINT8 Index;
+ UINT8 NumberOfClassGuid;
+ BOOLEAN ClassGuidMatch;
+ EFI_GUID *ClassGuid;
+ EFI_GUID *ComparingGuid;
+ EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
+
+ OpCodeData = NULL;
+ Package = NULL;
+ ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));
+
+ //
+ // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
+ //
+ if (FormSetGuid == NULL) {
+ ComparingGuid = &gZeroGuid;
+ } else {
+ ComparingGuid = FormSetGuid;
+ }
+
+ //
+ // Get HII PackageList
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiHiiDatabaseProtocolGuid,
+ NULL,
+ (VOID **)&HiiDatabase
+ );
+ if (EFI_ERROR (Status)) {
+ *BinaryData = NULL;
+ return Status;
+ }
+
+ BufferSize = 0;
+ HiiPackageList = NULL;
+ Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ HiiPackageList = AllocatePool (BufferSize);
+ if (HiiPackageList == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList);
+ }
+
+ if (EFI_ERROR (Status)) {
+ if (HiiPackageList != NULL) {
+ FreePool (HiiPackageList);
+ }
+
+ *BinaryData = NULL;
+ return Status;
+ }
+
+ //
+ // Get Form package from this HII package List
+ //
+ Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
+ Offset2 = 0;
+ CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));
+
+ ClassGuidMatch = FALSE;
+ while (Offset < PackageListLength) {
+ Package = ((UINT8 *)HiiPackageList) + Offset;
+ CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
+
+ if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {
+ //
+ // Search FormSet in this Form Package
+ //
+
+ Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);
+ while (Offset2 < PackageHeader.Length) {
+ OpCodeData = Package + Offset2;
+
+ if (((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {
+ //
+ // Try to compare against formset GUID
+ //
+
+ if (IsZeroGuid (FormSetGuid) ||
+ CompareGuid (ComparingGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER))))
+ {
+ break;
+ }
+
+ if (((EFI_IFR_OP_HEADER *)OpCodeData)->Length > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) {
+ //
+ // Try to compare against formset class GUID
+ //
+ NumberOfClassGuid = (UINT8)(((EFI_IFR_FORM_SET *)OpCodeData)->Flags & 0x3);
+ ClassGuid = (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_FORM_SET));
+ for (Index = 0; Index < NumberOfClassGuid; Index++) {
+ if (CompareGuid (ComparingGuid, ClassGuid + Index)) {
+ ClassGuidMatch = TRUE;
+ break;
+ }
+ }
+
+ if (ClassGuidMatch) {
+ break;
+ }
+ } else if (ComparingGuid == &gEfiHiiPlatformSetupFormsetGuid) {
+ ClassGuidMatch = TRUE;
+ break;
+ }
+ }
+
+ Offset2 += ((EFI_IFR_OP_HEADER *)OpCodeData)->Length;
+ }
+
+ if (Offset2 < PackageHeader.Length) {
+ //
+ // Target formset found
+ //
+ break;
+ }
+ }
+
+ Offset += PackageHeader.Length;
+ }
+
+ if (Offset >= PackageListLength) {
+ //
+ // Form package not found in this Package List
+ //
+ FreePool (HiiPackageList);
+ *BinaryData = NULL;
+ return EFI_NOT_FOUND;
+ }
+
+ if (FormSetGuid != NULL) {
+ //
+ // Return the FormSet GUID
+ //
+ CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *)OpCodeData)->Guid, sizeof (EFI_GUID));
+ }
+
+ //
+ // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
+ // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
+ // of the Form Package.
+ //
+
+ *BinaryLength = PackageHeader.Length - Offset2;
+ *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);
+ FreePool (HiiPackageList);
+ if (*BinaryData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Check if the requested element is in storage.
+
+ @param Storage The storage contains elements.
+ @param RequestElement The element to be searched.
+
+**/
+BOOLEAN
+ElementValidation (
+ IN HII_FORMSET_STORAGE *Storage,
+ IN CHAR16 *RequestElement
+ )
+{
+ return StrStr (Storage->ConfigRequest, RequestElement) != NULL ? TRUE : FALSE;
+}
+
+/**
+ Append the Request element to the Config Request.
+
+ @param ConfigRequest Current ConfigRequest info.
+ @param SpareStrLen Current remain free buffer for config request.
+ @param RequestElement New Request element.
+
+**/
+VOID
+AppendConfigRequest (
+ IN OUT CHAR16 **ConfigRequest,
+ IN OUT UINTN *SpareStrLen,
+ IN CHAR16 *RequestElement
+ )
+{
+ CHAR16 *NewStr;
+ UINTN StringSize;
+ UINTN StrLength;
+ UINTN MaxLen;
+
+ StrLength = StrLen (RequestElement);
+ StringSize = (*ConfigRequest != NULL) ? StrSize (*ConfigRequest) : sizeof (CHAR16);
+ MaxLen = StringSize / sizeof (CHAR16) + *SpareStrLen;
+
+ //
+ // Append <RequestElement> to <ConfigRequest>
+ //
+ if (StrLength > *SpareStrLen) {
+ //
+ // Old String buffer is not sufficient for RequestElement, allocate a new one
+ //
+ MaxLen = StringSize / sizeof (CHAR16) + CONFIG_REQUEST_STRING_INCREMENTAL;
+ NewStr = AllocatePool (MaxLen * sizeof (CHAR16));
+ if (NewStr == NULL) {
+ return;
+ }
+
+ if (*ConfigRequest != NULL) {
+ CopyMem (NewStr, *ConfigRequest, StringSize);
+ FreePool (*ConfigRequest);
+ } else {
+ NewStr[0] = L'\0';
+ }
+
+ *ConfigRequest = NewStr;
+ *SpareStrLen = CONFIG_REQUEST_STRING_INCREMENTAL;
+ }
+
+ StrCatS (*ConfigRequest, MaxLen, RequestElement);
+ *SpareStrLen -= StrLength;
+}
+
+/**
+ Adjust the config request info, remove the request elements which already in AllConfigRequest string.
+
+ @param Storage Form set Storage.
+ @param Request The input request string.
+ @param RespString Whether the input is ConfigRequest or ConfigResp format.
+
+ @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig
+ @retval FALSE All elements covered by current used elements.
+
+**/
+BOOLEAN
+ConfigRequestAdjust (
+ IN HII_FORMSET_STORAGE *Storage,
+ IN CHAR16 *Request,
+ IN BOOLEAN RespString
+ )
+{
+ CHAR16 *RequestElement;
+ CHAR16 *NextRequestElement;
+ CHAR16 *NextElementBackup;
+ CHAR16 *SearchKey;
+ CHAR16 *ValueKey;
+ BOOLEAN RetVal;
+ CHAR16 *ConfigRequest;
+
+ RetVal = FALSE;
+ NextElementBackup = NULL;
+ ValueKey = NULL;
+
+ if (Request != NULL) {
+ ConfigRequest = Request;
+ } else {
+ ConfigRequest = Storage->ConfigRequest;
+ }
+
+ if (Storage->ConfigRequest == NULL) {
+ Storage->ConfigRequest = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);
+ if (Storage->ConfigRequest == NULL) {
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
+ //
+ // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
+ //
+ SearchKey = L"&";
+ } else {
+ //
+ // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
+ //
+ SearchKey = L"&OFFSET";
+ ValueKey = L"&VALUE";
+ }
+
+ //
+ // Find SearchKey storage
+ //
+ if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
+ RequestElement = StrStr (ConfigRequest, L"PATH");
+ if (RequestElement == NULL) {
+ return FALSE;
+ }
+
+ RequestElement = StrStr (RequestElement, SearchKey);
+ } else {
+ RequestElement = StrStr (ConfigRequest, SearchKey);
+ }
+
+ while (RequestElement != NULL) {
+ //
+ // +1 to avoid find header itself.
+ //
+ NextRequestElement = StrStr (RequestElement + 1, SearchKey);
+
+ //
+ // The last Request element in configRequest string.
+ //
+ if (NextRequestElement != NULL) {
+ if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {
+ NextElementBackup = NextRequestElement;
+ NextRequestElement = StrStr (RequestElement, ValueKey);
+ if (NextRequestElement == NULL) {
+ return FALSE;
+ }
+ }
+
+ //
+ // Replace "&" with '\0'.
+ //
+ *NextRequestElement = L'\0';
+ } else {
+ if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {
+ NextElementBackup = NextRequestElement;
+ NextRequestElement = StrStr (RequestElement, ValueKey);
+ if (NextRequestElement == NULL) {
+ return FALSE;
+ }
+
+ //
+ // Replace "&" with '\0'.
+ //
+ *NextRequestElement = L'\0';
+ }
+ }
+
+ if (!ElementValidation (Storage, RequestElement)) {
+ //
+ // Add this element to the Storage->BrowserStorage->AllRequestElement.
+ //
+ AppendConfigRequest (&Storage->ConfigRequest, &Storage->SpareStrLen, RequestElement);
+ RetVal = TRUE;
+ }
+
+ if (NextRequestElement != NULL) {
+ //
+ // Restore '&' with '\0' for later used.
+ //
+ *NextRequestElement = L'&';
+ }
+
+ if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {
+ RequestElement = NextElementBackup;
+ } else {
+ RequestElement = NextRequestElement;
+ }
+ }
+
+ return RetVal;
+}
+
+/**
+ Fill storage with settings requested from Configuration Driver.
+
+ @param[in] FormSet FormSet data structure.
+ @param[in] Storage Buffer Storage.
+
+**/
+VOID
+LoadFormSetStorage (
+ IN HII_FORMSET *FormSet,
+ IN HII_FORMSET_STORAGE *Storage
+ )
+{
+ EFI_STATUS Status;
+ EFI_STRING Progress;
+ EFI_STRING Result;
+ CHAR16 *StrPtr;
+ EFI_STRING ConfigRequest;
+ UINTN RequestStrSize;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+
+ ConfigRequest = NULL;
+
+ switch (Storage->Type) {
+ case EFI_HII_VARSTORE_EFI_VARIABLE:
+ return;
+
+ case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
+ #if 0 // bug fix for efivarstore
+ if (Storage->ConfigRequest != NULL) {
+ ConfigRequestAdjust (Storage, Storage->ConfigRequest, FALSE);
+ return;
+ }
+
+ #endif
+ break;
+
+ case EFI_HII_VARSTORE_BUFFER:
+ case EFI_HII_VARSTORE_NAME_VALUE:
+ //
+ // Skip if there is no RequestElement.
+ //
+ if (Storage->ElementCount == 0) {
+ return;
+ }
+
+ break;
+
+ default:
+ return;
+ }
+
+ if (Storage->Type != EFI_HII_VARSTORE_NAME_VALUE) {
+ //
+ // Create the config request string to get all fields for this storage.
+ // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
+ // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator
+ //
+ RequestStrSize = StrSize (Storage->ConfigHdr) + 20 * sizeof (CHAR16);
+ ConfigRequest = AllocatePool (RequestStrSize);
+ if (ConfigRequest == NULL) {
+ return;
+ }
+
+ UnicodeSPrint (
+ ConfigRequest,
+ RequestStrSize,
+ L"%s&OFFSET=0&WIDTH=%04x",
+ Storage->ConfigHdr,
+ Storage->Size
+ );
+ } else {
+ RequestStrSize = (StrLen (Storage->ConfigHdr) + StrLen (Storage->ConfigRequest) + 1) * sizeof (CHAR16);
+ ConfigRequest = AllocatePool (RequestStrSize);
+ if (ConfigRequest == NULL) {
+ return;
+ }
+
+ UnicodeSPrint (
+ ConfigRequest,
+ RequestStrSize,
+ L"%s%s",
+ Storage->ConfigHdr,
+ Storage->ConfigRequest
+ );
+ }
+
+ //
+ // Request current settings from Configuration Driver
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiHiiConfigRoutingProtocolGuid,
+ NULL,
+ (VOID **)&HiiConfigRouting
+ );
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ Status = HiiConfigRouting->ExtractConfig (
+ HiiConfigRouting,
+ ConfigRequest,
+ &Progress,
+ &Result
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Convert Result from <ConfigAltResp> to <ConfigResp>
+ //
+ StrPtr = StrStr (Result, L"&GUID=");
+ if (StrPtr != NULL) {
+ *StrPtr = L'\0';
+ }
+
+ Status = ConfigRespToStorage (Storage, Result);
+ FreePool (Result);
+ }
+
+ Storage->ConfigRequest = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);
+ if (Storage->ConfigRequest == NULL) {
+ if (ConfigRequest != NULL) {
+ FreePool (ConfigRequest);
+ }
+
+ return;
+ }
+
+ if (Storage->Type != EFI_HII_VARSTORE_NAME_VALUE) {
+ if (ConfigRequest != NULL) {
+ FreePool (ConfigRequest);
+ }
+ }
+}
+
+/**
+ Zero extend integer/boolean/date/time to UINT64 for comparing.
+
+ @param[in] Value HII Value to be converted.
+
+**/
+VOID
+ExtendValueToU64 (
+ IN HII_STATEMENT_VALUE *Value
+ )
+{
+ UINT64 Temp;
+
+ Temp = 0;
+ switch (Value->Type) {
+ case EFI_IFR_TYPE_NUM_SIZE_8:
+ Temp = Value->Value.u8;
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_16:
+ Temp = Value->Value.u16;
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_32:
+ Temp = Value->Value.u32;
+ break;
+
+ case EFI_IFR_TYPE_BOOLEAN:
+ Temp = Value->Value.b;
+ break;
+
+ case EFI_IFR_TYPE_TIME:
+ Temp = Value->Value.u32 & 0xffffff;
+ break;
+
+ case EFI_IFR_TYPE_DATE:
+ Temp = Value->Value.u32;
+ break;
+
+ default:
+ return;
+ }
+
+ Value->Value.u64 = Temp;
+}
+
+/**
+ Pop an element from the stack.
+
+ @param Stack On input: old stack
+ @param StackPtr On input: old stack pointer; On output: new stack pointer
+ @param Data Data to pop.
+
+ @retval EFI_SUCCESS The value was popped onto the stack.
+ @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
+
+**/
+EFI_STATUS
+PopStack (
+ IN EFI_HII_VALUE *Stack,
+ IN OUT EFI_HII_VALUE **StackPtr,
+ OUT EFI_HII_VALUE *Data
+ );
+
+/**
+ Push an element onto the Boolean Stack.
+
+ @param Stack On input: old stack; On output: new stack
+ @param StackPtr On input: old stack pointer; On output: new stack
+ pointer
+ @param StackEnd On input: old stack end; On output: new stack end
+ @param Data Data to push.
+
+ @retval EFI_SUCCESS Push stack success.
+
+**/
+EFI_STATUS
+PushStack (
+ IN OUT EFI_HII_VALUE **Stack,
+ IN OUT EFI_HII_VALUE **StackPtr,
+ IN OUT EFI_HII_VALUE **StackEnd,
+ IN EFI_HII_VALUE *Data
+ );
+
+/**
+ Initialize the internal data structure of a FormSet.
+
+ @param[in] Handle PackageList Handle
+ @param[in,out] FormSetGuid On input, GUID or class GUID of a formset. If not
+ specified (NULL or zero GUID), take the first
+ FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
+ found in package list.
+ On output, GUID of the formset found(if not NULL).
+ @param[out] FormSet FormSet data structure.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_NOT_FOUND The specified FormSet could not be found.
+
+**/
+EFI_STATUS
+CreateFormSetFromHiiHandle (
+ IN EFI_HII_HANDLE Handle,
+ IN OUT EFI_GUID *FormSetGuid,
+ OUT HII_FORMSET *FormSet
+ );
+
+/**
+ Initialize a Formset and get current setting for Questions.
+
+ @param[in,out] FormSet FormSet data structure.
+
+**/
+VOID
+InitializeFormSet (
+ IN OUT HII_FORMSET *FormSet
+ );
+
+/**
+ Get Value for given Name from a NameValue Storage.
+
+ @param[in] Storage The NameValue Storage.
+ @param[in] Name The Name.
+ @param[in,out] Value The returned Value.
+
+ @retval EFI_SUCCESS Value found for given Name.
+ @retval EFI_NOT_FOUND No such Name found in NameValue storage.
+ @retval EFI_INVALID_PARAMETER Storage or Value is NULL.
+
+**/
+EFI_STATUS
+GetValueByName (
+ IN HII_FORMSET_STORAGE *Storage,
+ IN CHAR16 *Name,
+ IN OUT CHAR16 **Value
+ )
+{
+ LIST_ENTRY *Link;
+ HII_NAME_VALUE_NODE *Node;
+
+ if ((Storage == NULL) || (Value == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Value = NULL;
+
+ Link = GetFirstNode (&Storage->NameValueList);
+ while (!IsNull (&Storage->NameValueList, Link)) {
+ Node = HII_NAME_VALUE_NODE_FROM_LINK (Link);
+
+ if (StrCmp (Name, Node->Name) == 0) {
+ NewStringCopy (Value, Node->Value);
+ return EFI_SUCCESS;
+ }
+
+ Link = GetNextNode (&Storage->NameValueList, Link);
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Get Question's current Value.
+
+ @param[in] FormSet FormSet data structure.
+ @param[in] Form Form data structure.
+ @param[in,out] Question Question to be initialized.
+ @param[in] GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Formset, Form or Question is NULL.
+
+**/
+EFI_STATUS
+GetQuestionValue (
+ IN HII_FORMSET *FormSet,
+ IN HII_FORM *Form,
+ IN OUT HII_STATEMENT *Question,
+ IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN Enabled;
+ BOOLEAN Pending;
+ UINT8 *Dst;
+ UINTN StorageWidth;
+ EFI_TIME EfiTime;
+ HII_FORMSET_STORAGE *Storage;
+ HII_FORMSET_STORAGE *FormsetStorage;
+ EFI_IFR_TYPE_VALUE *QuestionValue;
+ CHAR16 *ConfigRequest;
+ CHAR16 *Progress;
+ CHAR16 *Result;
+ CHAR16 *Value;
+ UINTN Length;
+ BOOLEAN IsBufferStorage;
+ UINTN MaxLen;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+
+ if ((FormSet == NULL) || (Form == NULL) || (Question == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+ Value = NULL;
+ Result = NULL;
+
+ if (GetValueFrom >= GetSetValueWithMax) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Question value is provided by an Expression, evaluate it
+ //
+ if (Question->ValueExpression != NULL) {
+ Status = EvaluateHiiExpression (FormSet, Form, Question->ValueExpression);
+ if (!EFI_ERROR (Status)) {
+ if (Question->ValueExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {
+ ASSERT (Question->Value.Type == EFI_IFR_TYPE_BUFFER && Question->Value.Buffer != NULL);
+ if (Question->StorageWidth > Question->ValueExpression->Result.BufferLen) {
+ CopyMem (Question->Value.Buffer, Question->ValueExpression->Result.Buffer, Question->ValueExpression->Result.BufferLen);
+ Question->Value.BufferLen = Question->ValueExpression->Result.BufferLen;
+ } else {
+ CopyMem (Question->Value.Buffer, Question->ValueExpression->Result.Buffer, Question->StorageWidth);
+ Question->Value.BufferLen = Question->StorageWidth;
+ }
+
+ FreePool (Question->ValueExpression->Result.Buffer);
+ }
+
+ Question->Value.Type = Question->ValueExpression->Result.Type;
+ CopyMem (&Question->Value.Value, &Question->ValueExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE));
+ }
+
+ return Status;
+ }
+
+ //
+ // Get question value by read expression.
+ //
+ if ((Question->ReadExpression != NULL) && (Form->FormType == STANDARD_MAP_FORM_TYPE)) {
+ Status = EvaluateHiiExpression (FormSet, Form, Question->ReadExpression);
+ if (!EFI_ERROR (Status) &&
+ ((Question->ReadExpression->Result.Type < EFI_IFR_TYPE_OTHER) || (Question->ReadExpression->Result.Type == EFI_IFR_TYPE_BUFFER)))
+ {
+ //
+ // Only update question value to the valid result.
+ //
+ if (Question->ReadExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {
+ ASSERT (Question->Value.Type == EFI_IFR_TYPE_BUFFER && Question->Value.Buffer != NULL);
+ if (Question->StorageWidth > Question->ReadExpression->Result.BufferLen) {
+ CopyMem (Question->Value.Buffer, Question->ReadExpression->Result.Buffer, Question->ReadExpression->Result.BufferLen);
+ Question->Value.BufferLen = Question->ReadExpression->Result.BufferLen;
+ } else {
+ CopyMem (Question->Value.Buffer, Question->ReadExpression->Result.Buffer, Question->StorageWidth);
+ Question->Value.BufferLen = Question->StorageWidth;
+ }
+
+ FreePool (Question->ReadExpression->Result.Buffer);
+ }
+
+ Question->Value.Type = Question->ReadExpression->Result.Type;
+ CopyMem (&Question->Value.Value, &Question->ReadExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE));
+ return EFI_SUCCESS;
+ }
+ }
+
+ //
+ // Question value is provided by RTC
+ //
+ Storage = Question->Storage;
+ QuestionValue = &Question->Value.Value;
+ if (Storage == NULL) {
+ //
+ // It's a Question without storage, or RTC date/time
+ //
+ if ((Question->Operand == EFI_IFR_DATE_OP) || (Question->Operand == EFI_IFR_TIME_OP)) {
+ //
+ // Date and time define the same Flags bit
+ //
+ switch (Question->ExtraData.Flags & EFI_QF_DATE_STORAGE) {
+ case QF_DATE_STORAGE_TIME:
+ Status = gRT->GetTime (&EfiTime, NULL);
+ break;
+
+ case QF_DATE_STORAGE_WAKEUP:
+ Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);
+ break;
+
+ case QF_DATE_STORAGE_NORMAL:
+ default:
+ //
+ // For date/time without storage
+ //
+ return EFI_SUCCESS;
+ }
+
+ if (EFI_ERROR (Status)) {
+ if (Question->Operand == EFI_IFR_DATE_OP) {
+ QuestionValue->date.Year = 0xff;
+ QuestionValue->date.Month = 0xff;
+ QuestionValue->date.Day = 0xff;
+ } else {
+ QuestionValue->time.Hour = 0xff;
+ QuestionValue->time.Minute = 0xff;
+ QuestionValue->time.Second = 0xff;
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ if (Question->Operand == EFI_IFR_DATE_OP) {
+ QuestionValue->date.Year = EfiTime.Year;
+ QuestionValue->date.Month = EfiTime.Month;
+ QuestionValue->date.Day = EfiTime.Day;
+ } else {
+ QuestionValue->time.Hour = EfiTime.Hour;
+ QuestionValue->time.Minute = EfiTime.Minute;
+ QuestionValue->time.Second = EfiTime.Second;
+ }
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Question value is provided by EFI variable
+ //
+ StorageWidth = Question->StorageWidth;
+ if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
+ if (Question->Value.Buffer != NULL) {
+ Dst = Question->Value.Buffer;
+ } else {
+ Dst = (UINT8 *)QuestionValue;
+ }
+
+ Status = gRT->GetVariable (
+ Question->VariableName,
+ &Storage->Guid,
+ NULL,
+ &StorageWidth,
+ Dst
+ );
+ //
+ // Always return success, even this EFI variable doesn't exist
+ //
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Question Value is provided by Buffer Storage or NameValue Storage
+ //
+ if (Question->Value.Buffer != NULL) {
+ //
+ // This Question is password or orderedlist
+ //
+ Dst = Question->Value.Buffer;
+ } else {
+ //
+ // Other type of Questions
+ //
+ Dst = (UINT8 *)&Question->Value.Value;
+ }
+
+ if ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ||
+ (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER))
+ {
+ IsBufferStorage = TRUE;
+ } else {
+ IsBufferStorage = FALSE;
+ }
+
+ if (GetValueFrom == GetSetValueWithBuffer ) {
+ if (IsBufferStorage) {
+ //
+ // Copy from storage Edit buffer
+ // If the Question refer to bit filed, get the value in the related bit filed.
+ //
+ if (Question->QuestionReferToBitField) {
+ GetBitsQuestionValue (Question, Storage->Buffer + Question->VarStoreInfo.VarOffset, &Question->Value);
+ } else {
+ CopyMem (Dst, Storage->Buffer + Question->VarStoreInfo.VarOffset, StorageWidth);
+ }
+ } else {
+ Value = NULL;
+ Status = GetValueByName (Storage, Question->VariableName, &Value);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ASSERT (Value != NULL);
+ Status = BufferToQuestionValue (Question, Value, &Question->Value);
+ FreePool (Value);
+ }
+ } else {
+ FormsetStorage = GetFstStgFromVarId (FormSet, Question->VarStoreId);
+ ASSERT (FormsetStorage != NULL);
+ //
+ // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
+ // <ConfigHdr> + "&" + <VariableName>
+ //
+ if (IsBufferStorage) {
+ Length = StrLen (FormsetStorage->ConfigHdr);
+ Length += StrLen (Question->BlockName);
+ } else {
+ Length = StrLen (FormsetStorage->ConfigHdr);
+ Length += StrLen (Question->VariableName) + 1;
+ }
+
+ // Allocate buffer include '\0'
+ MaxLen = Length + 1;
+ ConfigRequest = AllocatePool (MaxLen * sizeof (CHAR16));
+ ASSERT (ConfigRequest != NULL);
+
+ StrCpyS (ConfigRequest, MaxLen, FormsetStorage->ConfigHdr);
+ if (IsBufferStorage) {
+ StrCatS (ConfigRequest, MaxLen, Question->BlockName);
+ } else {
+ StrCatS (ConfigRequest, MaxLen, L"&");
+ StrCatS (ConfigRequest, MaxLen, Question->VariableName);
+ }
+
+ Status = gBS->LocateProtocol (
+ &gEfiHiiConfigRoutingProtocolGuid,
+ NULL,
+ (VOID **)&HiiConfigRouting
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Request current settings from Configuration Driver
+ //
+ Status = HiiConfigRouting->ExtractConfig (
+ HiiConfigRouting,
+ ConfigRequest,
+ &Progress,
+ &Result
+ );
+ FreePool (ConfigRequest);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Skip <ConfigRequest>
+ //
+ if (IsBufferStorage) {
+ Value = StrStr (Result, L"&VALUE");
+ if (Value == NULL) {
+ FreePool (Result);
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Skip "&VALUE"
+ //
+ Value = Value + 6;
+ } else {
+ Value = Result + Length;
+ }
+
+ if (*Value != '=') {
+ FreePool (Result);
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Skip '=', point to value
+ //
+ Value = Value + 1;
+
+ Status = BufferToQuestionValue (Question, Value, &Question->Value);
+ if (EFI_ERROR (Status)) {
+ FreePool (Result);
+ return Status;
+ }
+
+ //
+ // Synchronize Buffer
+ //
+ if (IsBufferStorage) {
+ CopyMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth);
+ } else {
+ SetValueByName (Storage, Question->VariableName, Value, NULL);
+ }
+
+ if (Result != NULL) {
+ FreePool (Result);
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Convert the input Unicode character to upper.
+
+ @param[in] String Th Unicode character to be converted.
+
+**/
+VOID
+IfrStrToUpper (
+ IN CHAR16 *String
+ )
+{
+ if (String == NULL) {
+ return;
+ }
+
+ while (*String != 0) {
+ if ((*String >= 'a') && (*String <= 'z')) {
+ *String = (UINT16)((*String) & ((UINT16) ~0x20));
+ }
+
+ String++;
+ }
+}
+
+/**
+ Check whether this value type can be transfer to EFI_IFR_TYPE_BUFFER type.
+
+ EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to
+ EFI_IFR_TYPE_BUFFER when do the value compare.
+
+ @param[in] Value Expression value to compare on.
+
+ @retval TRUE This value type can be transferred to EFI_IFR_TYPE_BUFFER type.
+ @retval FALSE This value type can't be transferred to EFI_IFR_TYPE_BUFFER type.
+
+**/
+BOOLEAN
+IsTypeInBuffer (
+ IN EFI_HII_VALUE *Value
+ )
+{
+ if (Value == NULL) {
+ return FALSE;
+ }
+
+ switch (Value->Type) {
+ case EFI_IFR_TYPE_BUFFER:
+ case EFI_IFR_TYPE_DATE:
+ case EFI_IFR_TYPE_TIME:
+ case EFI_IFR_TYPE_REF:
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
+/**
+ Check whether this value type can be transfer to EFI_IFR_TYPE_UINT64
+
+ @param[in] Value Expression value to compare on.
+
+ @retval TRUE This value type can be transferred to EFI_IFR_TYPE_BUFFER type.
+ @retval FALSE This value type can't be transferred to EFI_IFR_TYPE_BUFFER type.
+
+**/
+BOOLEAN
+IsTypeInUINT64 (
+ IN EFI_HII_VALUE *Value
+ )
+{
+ if (Value == NULL) {
+ return FALSE;
+ }
+
+ switch (Value->Type) {
+ case EFI_IFR_TYPE_NUM_SIZE_8:
+ case EFI_IFR_TYPE_NUM_SIZE_16:
+ case EFI_IFR_TYPE_NUM_SIZE_32:
+ case EFI_IFR_TYPE_NUM_SIZE_64:
+ case EFI_IFR_TYPE_BOOLEAN:
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
+/**
+ Return the buffer pointer for this value.
+
+ EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to
+ EFI_IFR_TYPE_BUFFER when do the value compare.
+
+ @param[in] Value Expression value to compare on.
+
+ @retval Buf Return the buffer pointer.
+
+**/
+UINT8 *
+GetBufferForValue (
+ IN EFI_HII_VALUE *Value
+ )
+{
+ if (Value == NULL) {
+ return NULL;
+ }
+
+ switch (Value->Type) {
+ case EFI_IFR_TYPE_BUFFER:
+ return Value->Buffer;
+
+ case EFI_IFR_TYPE_DATE:
+ return (UINT8 *)(&Value->Value.date);
+
+ case EFI_IFR_TYPE_TIME:
+ return (UINT8 *)(&Value->Value.time);
+
+ case EFI_IFR_TYPE_REF:
+ return (UINT8 *)(&Value->Value.ref);
+
+ default:
+ return NULL;
+ }
+}
+
+/**
+ Return the buffer length for this value.
+
+ EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to
+ EFI_IFR_TYPE_BUFFER when do the value compare.
+
+ @param[in] Value Expression value to compare on.
+
+ @retval BufLen Return the buffer length.
+
+**/
+UINT16
+GetLengthForValue (
+ IN EFI_HII_VALUE *Value
+ )
+{
+ if (Value == NULL) {
+ return 0;
+ }
+
+ switch (Value->Type) {
+ case EFI_IFR_TYPE_BUFFER:
+ return Value->BufferLen;
+
+ case EFI_IFR_TYPE_DATE:
+ return (UINT16)sizeof (EFI_HII_DATE);
+
+ case EFI_IFR_TYPE_TIME:
+ return (UINT16)sizeof (EFI_HII_TIME);
+
+ case EFI_IFR_TYPE_REF:
+ return (UINT16)sizeof (EFI_HII_REF);
+
+ default:
+ return 0;
+ }
+}
+
+/**
+ Get UINT64 type value.
+
+ @param[in] Value Input Hii value.
+
+ @retval UINT64 Return the UINT64 type value.
+
+**/
+UINT64
+HiiValueToUINT64 (
+ IN EFI_HII_VALUE *Value
+ )
+{
+ UINT64 RetVal;
+
+ if (Value == NULL) {
+ return 0;
+ }
+
+ RetVal = 0;
+
+ switch (Value->Type) {
+ case EFI_IFR_TYPE_NUM_SIZE_8:
+ RetVal = Value->Value.u8;
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_16:
+ RetVal = Value->Value.u16;
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_32:
+ RetVal = Value->Value.u32;
+ break;
+
+ case EFI_IFR_TYPE_BOOLEAN:
+ RetVal = Value->Value.b;
+ break;
+
+ case EFI_IFR_TYPE_DATE:
+ RetVal = *(UINT64 *)&Value->Value.date;
+ break;
+
+ case EFI_IFR_TYPE_TIME:
+ RetVal = (*(UINT64 *)&Value->Value.time) & 0xffffff;
+ break;
+
+ default:
+ RetVal = Value->Value.u64;
+ break;
+ }
+
+ return RetVal;
+}
+
+/**
+ Compare two Hii value.
+
+ @param[in] Value1 Expression value to compare on left-hand.
+ @param[in] Value2 Expression value to compare on right-hand.
+ @param[out] Result Return value after compare.
+ retval 0 Two operators equal.
+ return Positive value if Value1 is greater than Value2.
+ retval Negative value if Value1 is less than Value2.
+ @param[in] HiiHandle Only required for string compare.
+
+ @retval other Could not perform compare on two values.
+ @retval EFI_SUCCESS Compare the value success.
+ @retval EFI_INVALID_PARAMETER Value1, Value2 or Result is NULL.
+
+**/
+EFI_STATUS
+CompareHiiValue (
+ IN EFI_HII_VALUE *Value1,
+ IN EFI_HII_VALUE *Value2,
+ OUT INTN *Result,
+ IN EFI_HII_HANDLE HiiHandle OPTIONAL
+ )
+{
+ INT64 Temp64;
+ CHAR16 *Str1;
+ CHAR16 *Str2;
+ UINTN Len;
+ UINT8 *Buf1;
+ UINT16 Buf1Len;
+ UINT8 *Buf2;
+ UINT16 Buf2Len;
+
+ if ((Value1 == NULL) || (Value2 == NULL) || (Result == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Value1->Type == EFI_IFR_TYPE_STRING) && (Value2->Type == EFI_IFR_TYPE_STRING)) {
+ if ((Value1->Value.string == 0) || (Value2->Value.string == 0)) {
+ //
+ // StringId 0 is reserved
+ //
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Value1->Value.string == Value2->Value.string) {
+ *Result = 0;
+ return EFI_SUCCESS;
+ }
+
+ Str1 = GetTokenString (Value1->Value.string, HiiHandle);
+ if (Str1 == NULL) {
+ //
+ // String not found
+ //
+ return EFI_NOT_FOUND;
+ }
+
+ Str2 = GetTokenString (Value2->Value.string, HiiHandle);
+ if (Str2 == NULL) {
+ FreePool (Str1);
+ return EFI_NOT_FOUND;
+ }
+
+ *Result = StrCmp (Str1, Str2);
+
+ FreePool (Str1);
+ FreePool (Str2);
+
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Take types(date, time, ref, buffer) as buffer
+ //
+ if (IsTypeInBuffer (Value1) && IsTypeInBuffer (Value2)) {
+ Buf1 = GetBufferForValue (Value1);
+ Buf1Len = GetLengthForValue (Value1);
+ Buf2 = GetBufferForValue (Value2);
+ Buf2Len = GetLengthForValue (Value2);
+
+ Len = Buf1Len > Buf2Len ? Buf2Len : Buf1Len;
+ *Result = CompareMem (Buf1, Buf2, Len);
+ if ((*Result == 0) && (Buf1Len != Buf2Len)) {
+ //
+ // In this case, means base on small number buffer, the data is same
+ // So which value has more data, which value is bigger.
+ //
+ *Result = Buf1Len > Buf2Len ? 1 : -1;
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Take types(integer, boolean) as integer
+ //
+ if (IsTypeInUINT64 (Value1) && IsTypeInUINT64 (Value2)) {
+ Temp64 = HiiValueToUINT64 (Value1) - HiiValueToUINT64 (Value2);
+ if (Temp64 > 0) {
+ *Result = 1;
+ } else if (Temp64 < 0) {
+ *Result = -1;
+ } else {
+ *Result = 0;
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Check if current user has the privilege specified by the permissions GUID.
+
+ @param[in] Guid A GUID specifying setup access permissions.
+
+ @retval TRUE Current user has the privilege.
+ @retval FALSE Current user does not have the privilege.
+**/
+BOOLEAN
+CheckUserPrivilege (
+ IN EFI_GUID *Guid
+ )
+{
+ EFI_STATUS Status;
+ EFI_USER_PROFILE_HANDLE UserProfileHandle;
+ EFI_USER_INFO_HANDLE UserInfoHandle;
+ EFI_USER_INFO *UserInfo;
+ EFI_GUID *UserPermissionsGuid;
+ UINTN UserInfoSize;
+ UINTN AccessControlDataSize;
+ EFI_USER_INFO_ACCESS_CONTROL *AccessControl;
+ UINTN RemainSize;
+
+ if (mUserManager == NULL) {
+ Status = gBS->LocateProtocol (
+ &gEfiUserManagerProtocolGuid,
+ NULL,
+ (VOID **)&mUserManager
+ );
+ if (EFI_ERROR (Status)) {
+ ///
+ /// If the system does not support user management, then it is assumed that
+ /// all users have admin privilege and evaluation of each EFI_IFR_SECURITY
+ /// op-code is always TRUE.
+ ///
+ return TRUE;
+ }
+ }
+
+ Status = mUserManager->Current (mUserManager, &UserProfileHandle);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Enumerate all user information of the current user profile
+ /// to look for any EFI_USER_INFO_ACCESS_SETUP record.
+ ///
+
+ for (UserInfoHandle = NULL; ;) {
+ Status = mUserManager->GetNextInfo (mUserManager, UserProfileHandle, &UserInfoHandle);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ UserInfoSize = 0;
+ Status = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, NULL, &UserInfoSize);
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ continue;
+ }
+
+ UserInfo = (EFI_USER_INFO *)AllocatePool (UserInfoSize);
+ if (UserInfo == NULL) {
+ break;
+ }
+
+ Status = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, UserInfo, &UserInfoSize);
+ if (EFI_ERROR (Status) ||
+ (UserInfo->InfoType != EFI_USER_INFO_ACCESS_POLICY_RECORD) ||
+ (UserInfo->InfoSize <= sizeof (EFI_USER_INFO)))
+ {
+ FreePool (UserInfo);
+ continue;
+ }
+
+ RemainSize = UserInfo->InfoSize - sizeof (EFI_USER_INFO);
+ AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)(UserInfo + 1);
+ while (RemainSize >= sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {
+ if ((RemainSize < AccessControl->Size) || (AccessControl->Size < sizeof (EFI_USER_INFO_ACCESS_CONTROL))) {
+ break;
+ }
+
+ if (AccessControl->Type == EFI_USER_INFO_ACCESS_SETUP) {
+ ///
+ /// Check if current user has the privilege specified by the permissions GUID.
+ ///
+
+ UserPermissionsGuid = (EFI_GUID *)(AccessControl + 1);
+ AccessControlDataSize = AccessControl->Size - sizeof (EFI_USER_INFO_ACCESS_CONTROL);
+ while (AccessControlDataSize >= sizeof (EFI_GUID)) {
+ if (CompareGuid (Guid, UserPermissionsGuid)) {
+ FreePool (UserInfo);
+ return TRUE;
+ }
+
+ UserPermissionsGuid++;
+ AccessControlDataSize -= sizeof (EFI_GUID);
+ }
+ }
+
+ RemainSize -= AccessControl->Size;
+ AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)((UINT8 *)AccessControl + AccessControl->Size);
+ }
+
+ FreePool (UserInfo);
+ }
+
+ return FALSE;
+}
+
+/**
+ Search a Question in Form scope using its QuestionId.
+
+ @param[in] Form The form which contains this Question.
+ @param[in] QuestionId Id of this Question.
+
+ @retval Pointer The Question.
+ @retval NULL Specified Question not found in the form.
+
+**/
+HII_STATEMENT *
+QuestionIdInForm (
+ IN HII_FORM *Form,
+ IN UINT16 QuestionId
+ )
+{
+ LIST_ENTRY *Link;
+ HII_STATEMENT *Question;
+
+ if ((QuestionId == 0) || (Form == NULL)) {
+ //
+ // The value of zero is reserved
+ //
+ return NULL;
+ }
+
+ Link = GetFirstNode (&Form->StatementListHead);
+ while (!IsNull (&Form->StatementListHead, Link)) {
+ Question = HII_STATEMENT_FROM_LINK (Link);
+
+ if (Question->QuestionId == QuestionId) {
+ return Question;
+ }
+
+ Link = GetNextNode (&Form->StatementListHead, Link);
+ }
+
+ return NULL;
+}
+
+/**
+ Search a Question in Formset scope using its QuestionId.
+
+ @param[in] FormSet The formset which contains this form.
+ @param[in] Form The form which contains this Question.
+ @param[in] QuestionId Id of this Question.
+
+ @retval Pointer The Question.
+ @retval NULL Specified Question not found in the form.
+
+**/
+HII_STATEMENT *
+QuestionIdInFormset (
+ IN HII_FORMSET *FormSet,
+ IN HII_FORM *Form,
+ IN UINT16 QuestionId
+ )
+{
+ LIST_ENTRY *Link;
+ HII_STATEMENT *Question;
+
+ if ((FormSet == NULL) || (Form == NULL)) {
+ return NULL;
+ }
+
+ //
+ // Search in the form scope first
+ //
+ Question = QuestionIdInForm (Form, QuestionId);
+ if (Question != NULL) {
+ return Question;
+ }
+
+ //
+ // Search in the formset scope
+ //
+ Link = GetFirstNode (&FormSet->FormListHead);
+ while (!IsNull (&FormSet->FormListHead, Link)) {
+ Form = HII_FORM_FROM_LINK (Link);
+
+ Question = QuestionIdInForm (Form, QuestionId);
+ if (Question != NULL) {
+ //
+ // EFI variable storage may be updated by Callback() asynchronous,
+ // to keep synchronous, always reload the Question Value.
+ //
+ if (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
+ GetQuestionValue (FormSet, Form, Question, GetSetValueWithHiiDriver);
+ }
+
+ return Question;
+ }
+
+ Link = GetNextNode (&FormSet->FormListHead, Link);
+ }
+
+ return NULL;
+}
+
+/**
+ Push an Expression value onto the Stack
+
+ @param[in] Value Expression value to push.
+
+ @retval EFI_SUCCESS The value was pushed onto the stack.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
+ stack.
+ @retval EFI_INVALID_PARAMETER Value is NULL.
+
+**/
+EFI_STATUS
+PushExpression (
+ IN EFI_HII_VALUE *Value
+ )
+{
+ if (Value == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return PushStack (
+ &mExpressionEvaluationStack,
+ &mExpressionEvaluationStackPointer,
+ &mExpressionEvaluationStackEnd,
+ Value
+ );
+}
+
+/**
+ Pop an Expression value from the stack.
+
+ @param[out] Value Expression value to pop.
+
+ @retval EFI_SUCCESS The value was popped onto the stack.
+ @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
+ @retval EFI_INVALID_PARAMETER Value is NULL.
+
+**/
+EFI_STATUS
+PopExpression (
+ OUT EFI_HII_VALUE *Value
+ )
+{
+ if (Value == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return PopStack (
+ mExpressionEvaluationStack + mExpressionEvaluationStackOffset,
+ &mExpressionEvaluationStackPointer,
+ Value
+ );
+}
+
+/**
+ Get current stack offset from stack start.
+
+ @return Stack offset to stack start.
+**/
+UINTN
+SaveExpressionEvaluationStackOffset (
+ VOID
+ )
+{
+ UINTN TempStackOffset;
+
+ TempStackOffset = mExpressionEvaluationStackOffset;
+ mExpressionEvaluationStackOffset = mExpressionEvaluationStackPointer - mExpressionEvaluationStack;
+ return TempStackOffset;
+}
+
+/**
+ Restore stack offset based on input stack offset
+
+ @param[in] StackOffset Offset to stack start.
+
+**/
+VOID
+RestoreExpressionEvaluationStackOffset (
+ UINTN StackOffset
+ )
+{
+ mExpressionEvaluationStackOffset = StackOffset;
+}
+
+/**
+ Evaluate opcode EFI_IFR_TO_STRING.
+
+ @param[in] FormSet Formset which contains this opcode.
+ @param[in] Format String format in EFI_IFR_TO_STRING.
+ @param[out] Result Evaluation result for this opcode.
+
+ @retval EFI_SUCCESS Opcode evaluation success.
+ @retval Other Opcode evaluation failed.
+
+**/
+EFI_STATUS
+IfrToString (
+ IN HII_FORMSET *FormSet,
+ IN UINT8 Format,
+ OUT EFI_HII_VALUE *Result
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_VALUE Value;
+ CHAR16 *String;
+ CHAR16 *PrintFormat;
+ CHAR16 Buffer[MAXIMUM_VALUE_CHARACTERS];
+ UINT8 *SrcBuf;
+ UINTN BufferSize;
+
+ if ((FormSet == NULL) || (Result == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = PopExpression (&Value);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ switch (Value.Type) {
+ case EFI_IFR_TYPE_NUM_SIZE_8:
+ case EFI_IFR_TYPE_NUM_SIZE_16:
+ case EFI_IFR_TYPE_NUM_SIZE_32:
+ case EFI_IFR_TYPE_NUM_SIZE_64:
+ BufferSize = MAXIMUM_VALUE_CHARACTERS * sizeof (CHAR16);
+ switch (Format) {
+ case EFI_IFR_STRING_UNSIGNED_DEC:
+ case EFI_IFR_STRING_SIGNED_DEC:
+ PrintFormat = L"%ld";
+ break;
+
+ case EFI_IFR_STRING_LOWERCASE_HEX:
+ PrintFormat = L"%lx";
+ break;
+
+ case EFI_IFR_STRING_UPPERCASE_HEX:
+ PrintFormat = L"%lX";
+ break;
+
+ default:
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;
+ return EFI_SUCCESS;
+ }
+
+ UnicodeSPrint (Buffer, BufferSize, PrintFormat, Value.Value.u64);
+ String = Buffer;
+ break;
+
+ case EFI_IFR_TYPE_STRING:
+ CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));
+ return EFI_SUCCESS;
+
+ case EFI_IFR_TYPE_BOOLEAN:
+ String = (Value.Value.b) ? L"True" : L"False";
+ break;
+
+ case EFI_IFR_TYPE_BUFFER:
+ case EFI_IFR_TYPE_DATE:
+ case EFI_IFR_TYPE_TIME:
+ case EFI_IFR_TYPE_REF:
+ //
+ // + 3 is base on the unicode format, the length may be odd number,
+ // so need 1 byte to align, also need 2 bytes for L'\0'.
+ //
+ if (Value.Type == EFI_IFR_TYPE_BUFFER) {
+ SrcBuf = Value.Buffer;
+ } else {
+ SrcBuf = GetBufferForValue (&Value);
+ }
+
+ if (Format == EFI_IFR_STRING_ASCII) {
+ PrintFormat = L"%a";
+ } else {
+ // Format == EFI_IFR_STRING_UNICODE
+ PrintFormat = L"%s";
+ }
+
+ UnicodeSPrint (Buffer, sizeof (Buffer), PrintFormat, SrcBuf);
+ String = Buffer;
+ if (Value.Type == EFI_IFR_TYPE_BUFFER) {
+ FreePool (Value.Buffer);
+ }
+
+ break;
+
+ default:
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;
+ return EFI_SUCCESS;
+ }
+
+ Result->Type = EFI_IFR_TYPE_STRING;
+ Result->Value.string = NewHiiString (String, FormSet->HiiHandle);
+ return EFI_SUCCESS;
+}
+
+/**
+ Evaluate opcode EFI_IFR_TO_UINT.
+
+ @param[in] FormSet Formset which contains this opcode.
+ @param[out] Result Evaluation result for this opcode.
+
+ @retval EFI_SUCCESS Opcode evaluation success.
+ @retval Other Opcode evaluation failed.
+
+**/
+EFI_STATUS
+IfrToUint (
+ IN HII_FORMSET *FormSet,
+ OUT EFI_HII_VALUE *Result
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_VALUE Value;
+ CHAR16 *String;
+ CHAR16 *StringPtr;
+
+ if ((FormSet == NULL) || (Result == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = PopExpression (&Value);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if ((Value.Type >= EFI_IFR_TYPE_OTHER) && !IsTypeInBuffer (&Value)) {
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;
+ return EFI_SUCCESS;
+ }
+
+ Status = EFI_SUCCESS;
+ if (Value.Type == EFI_IFR_TYPE_STRING) {
+ String = GetTokenString (Value.Value.string, FormSet->HiiHandle);
+ if (String == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ IfrStrToUpper (String);
+ StringPtr = StrStr (String, L"0X");
+ if (StringPtr != NULL) {
+ //
+ // Hex string
+ //
+ Result->Value.u64 = StrHexToUint64 (String);
+ } else {
+ //
+ // decimal string
+ //
+ Result->Value.u64 = StrDecimalToUint64 (String);
+ }
+
+ FreePool (String);
+ } else if (IsTypeInBuffer (&Value)) {
+ if (GetLengthForValue (&Value) > 8) {
+ if (Value.Type == EFI_IFR_TYPE_BUFFER) {
+ FreePool (Value.Buffer);
+ }
+
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;
+ return EFI_SUCCESS;
+ }
+
+ Result->Value.u64 = *(UINT64 *)GetBufferForValue (&Value);
+ if (Value.Type == EFI_IFR_TYPE_BUFFER) {
+ FreePool (Value.Buffer);
+ }
+ } else {
+ CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));
+ }
+
+ Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
+ return Status;
+}
+
+/**
+ Evaluate opcode EFI_IFR_CATENATE.
+
+ @param[in] FormSet Formset which contains this opcode.
+ @param[out] Result Evaluation result for this opcode.
+
+ @retval EFI_SUCCESS Opcode evaluation success.
+ @retval Other Opcode evaluation failed.
+
+**/
+EFI_STATUS
+IfrCatenate (
+ IN HII_FORMSET *FormSet,
+ OUT EFI_HII_VALUE *Result
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_VALUE Value[2];
+ CHAR16 *String[2];
+ UINTN Index;
+ CHAR16 *StringPtr;
+ UINTN Size;
+ UINT16 Length0;
+ UINT16 Length1;
+ UINT8 *TmpBuf;
+ UINTN MaxLen;
+
+ if ((FormSet == NULL) || (Result == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // String[0] - The second string
+ // String[1] - The first string
+ //
+ String[0] = NULL;
+ String[1] = NULL;
+ StringPtr = NULL;
+ Status = EFI_SUCCESS;
+ ZeroMem (Value, sizeof (Value));
+
+ Status = PopExpression (&Value[0]);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Status = PopExpression (&Value[1]);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ for (Index = 0; Index < 2; Index++) {
+ if ((Value[Index].Type != EFI_IFR_TYPE_STRING) && !IsTypeInBuffer (&Value[Index])) {
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ if (Value[Index].Type == EFI_IFR_TYPE_STRING) {
+ String[Index] = GetTokenString (Value[Index].Value.string, FormSet->HiiHandle);
+ if (String[Index] == NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+ }
+ }
+
+ if (Value[0].Type == EFI_IFR_TYPE_STRING) {
+ Size = StrSize (String[0]);
+ MaxLen = (StrSize (String[1]) + Size) / sizeof (CHAR16);
+ StringPtr = AllocatePool (MaxLen * sizeof (CHAR16));
+ ASSERT (StringPtr != NULL);
+ StrCpyS (StringPtr, MaxLen, String[1]);
+ StrCatS (StringPtr, MaxLen, String[0]);
+
+ Result->Type = EFI_IFR_TYPE_STRING;
+ Result->Value.string = NewHiiString (StringPtr, FormSet->HiiHandle);
+ } else {
+ Result->Type = EFI_IFR_TYPE_BUFFER;
+ Length0 = GetLengthForValue (&Value[0]);
+ Length1 = GetLengthForValue (&Value[1]);
+ Result->BufferLen = (UINT16)(Length0 + Length1);
+
+ Result->Buffer = AllocatePool (Result->BufferLen);
+ ASSERT (Result->Buffer != NULL);
+
+ TmpBuf = GetBufferForValue (&Value[0]);
+ ASSERT (TmpBuf != NULL);
+ CopyMem (Result->Buffer, TmpBuf, Length0);
+ TmpBuf = GetBufferForValue (&Value[1]);
+ ASSERT (TmpBuf != NULL);
+ CopyMem (&Result->Buffer[Length0], TmpBuf, Length1);
+ }
+
+Done:
+ if (Value[0].Buffer != NULL) {
+ FreePool (Value[0].Buffer);
+ }
+
+ if (Value[1].Buffer != NULL) {
+ FreePool (Value[1].Buffer);
+ }
+
+ if (String[0] != NULL) {
+ FreePool (String[0]);
+ }
+
+ if (String[1] != NULL) {
+ FreePool (String[1]);
+ }
+
+ if (StringPtr != NULL) {
+ FreePool (StringPtr);
+ }
+
+ return Status;
+}
+
+/**
+ Evaluate opcode EFI_IFR_MATCH.
+
+ @param[in] FormSet Formset which contains this opcode.
+ @param[out] Result Evaluation result for this opcode.
+
+ @retval EFI_SUCCESS Opcode evaluation success.
+ @retval Other Opcode evaluation failed.
+
+**/
+EFI_STATUS
+IfrMatch (
+ IN HII_FORMSET *FormSet,
+ OUT EFI_HII_VALUE *Result
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_VALUE Value[2];
+ CHAR16 *String[2];
+ UINTN Index;
+
+ if ((FormSet == NULL) || (Result == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // String[0] - The string to search
+ // String[1] - pattern
+ //
+ String[0] = NULL;
+ String[1] = NULL;
+ Status = EFI_SUCCESS;
+ ZeroMem (Value, sizeof (Value));
+
+ Status = PopExpression (&Value[0]);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Status = PopExpression (&Value[1]);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ for (Index = 0; Index < 2; Index++) {
+ if (Value[Index].Type != EFI_IFR_TYPE_STRING) {
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ String[Index] = GetTokenString (Value[Index].Value.string, FormSet->HiiHandle);
+ if (String[Index] == NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+ }
+
+ Result->Type = EFI_IFR_TYPE_BOOLEAN;
+ Result->Value.b = mUnicodeCollation->MetaiMatch (mUnicodeCollation, String[0], String[1]);
+
+Done:
+ if (String[0] != NULL) {
+ FreePool (String[0]);
+ }
+
+ if (String[1] != NULL) {
+ FreePool (String[1]);
+ }
+
+ return Status;
+}
+
+/**
+ Evaluate opcode EFI_IFR_MATCH2.
+
+ @param[in] FormSet Formset which contains this opcode.
+ @param[in] SyntaxType Syntax type for match2.
+ @param[out] Result Evaluation result for this opcode.
+
+ @retval EFI_SUCCESS Opcode evaluation success.
+ @retval Other Opcode evaluation failed.
+
+**/
+EFI_STATUS
+IfrMatch2 (
+ IN HII_FORMSET *FormSet,
+ IN EFI_GUID *SyntaxType,
+ OUT EFI_HII_VALUE *Result
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_VALUE Value[2];
+ CHAR16 *String[2];
+ UINTN Index;
+ UINTN GuidIndex;
+ EFI_HANDLE *HandleBuffer;
+ UINTN BufferSize;
+ EFI_REGULAR_EXPRESSION_PROTOCOL *RegularExpressionProtocol;
+ UINTN RegExSyntaxTypeListSize;
+ EFI_REGEX_SYNTAX_TYPE *RegExSyntaxTypeList;
+ UINTN CapturesCount;
+
+ if ((FormSet == NULL) || (SyntaxType == NULL) || (Result == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // String[0] - The string to search
+ // String[1] - pattern
+ //
+ String[0] = NULL;
+ String[1] = NULL;
+ HandleBuffer = NULL;
+ RegExSyntaxTypeList = NULL;
+ Status = EFI_SUCCESS;
+ ZeroMem (Value, sizeof (Value));
+
+ Status = PopExpression (&Value[0]);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Status = PopExpression (&Value[1]);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ for (Index = 0; Index < 2; Index++) {
+ if (Value[Index].Type != EFI_IFR_TYPE_STRING) {
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ String[Index] = GetTokenString (Value[Index].Value.string, FormSet->HiiHandle);
+ if (String[Index] == NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+ }
+
+ BufferSize = 0;
+ HandleBuffer = NULL;
+ Status = gBS->LocateHandle (
+ ByProtocol,
+ &gEfiRegularExpressionProtocolGuid,
+ NULL,
+ &BufferSize,
+ HandleBuffer
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ HandleBuffer = AllocatePool (BufferSize);
+ if (HandleBuffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ Status = gBS->LocateHandle (
+ ByProtocol,
+ &gEfiRegularExpressionProtocolGuid,
+ NULL,
+ &BufferSize,
+ HandleBuffer
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ ASSERT (HandleBuffer != NULL);
+ for ( Index = 0; Index < BufferSize / sizeof (EFI_HANDLE); Index++) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiRegularExpressionProtocolGuid,
+ (VOID **)&RegularExpressionProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ RegExSyntaxTypeListSize = 0;
+ RegExSyntaxTypeList = NULL;
+
+ Status = RegularExpressionProtocol->GetInfo (
+ RegularExpressionProtocol,
+ &RegExSyntaxTypeListSize,
+ RegExSyntaxTypeList
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ RegExSyntaxTypeList = AllocatePool (RegExSyntaxTypeListSize);
+ if (RegExSyntaxTypeList == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ Status = RegularExpressionProtocol->GetInfo (
+ RegularExpressionProtocol,
+ &RegExSyntaxTypeListSize,
+ RegExSyntaxTypeList
+ );
+ } else if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ for (GuidIndex = 0; GuidIndex < RegExSyntaxTypeListSize / sizeof (EFI_GUID); GuidIndex++) {
+ if (CompareGuid (&RegExSyntaxTypeList[GuidIndex], SyntaxType)) {
+ //
+ // Find the match type, return the value.
+ //
+ Result->Type = EFI_IFR_TYPE_BOOLEAN;
+ Status = RegularExpressionProtocol->MatchString (
+ RegularExpressionProtocol,
+ String[0],
+ String[1],
+ SyntaxType,
+ &Result->Value.b,
+ NULL,
+ &CapturesCount
+ );
+ goto Done;
+ }
+ }
+
+ if (RegExSyntaxTypeList != NULL) {
+ FreePool (RegExSyntaxTypeList);
+ }
+ }
+
+ //
+ // Type specified by SyntaxType is not supported
+ // in any of the EFI_REGULAR_EXPRESSION_PROTOCOL instances.
+ //
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;
+ Status = EFI_SUCCESS;
+
+Done:
+ if (String[0] != NULL) {
+ FreePool (String[0]);
+ }
+
+ if (String[1] != NULL) {
+ FreePool (String[1]);
+ }
+
+ if (RegExSyntaxTypeList != NULL) {
+ FreePool (RegExSyntaxTypeList);
+ }
+
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+
+ return Status;
+}
+
+/**
+ Evaluate opcode EFI_IFR_FIND.
+
+ @param[in] FormSet Formset which contains this opcode.
+ @param[in] Format Case sensitive or insensitive.
+ @param[out] Result Evaluation result for this opcode.
+
+ @retval EFI_SUCCESS Opcode evaluation success.
+ @retval Other Opcode evaluation failed.
+
+**/
+EFI_STATUS
+IfrFind (
+ IN HII_FORMSET *FormSet,
+ IN UINT8 Format,
+ OUT EFI_HII_VALUE *Result
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_VALUE Value[3];
+ CHAR16 *String[2];
+ UINTN Base;
+ CHAR16 *StringPtr;
+ UINTN Index;
+
+ if ((FormSet == NULL) || (Result == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (Value, sizeof (Value));
+
+ if (Format > EFI_IFR_FF_CASE_INSENSITIVE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = PopExpression (&Value[0]);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = PopExpression (&Value[1]);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = PopExpression (&Value[2]);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;
+ return EFI_SUCCESS;
+ }
+
+ Base = (UINTN)Value[0].Value.u64;
+
+ //
+ // String[0] - sub-string
+ // String[1] - The string to search
+ //
+ String[0] = NULL;
+ String[1] = NULL;
+ for (Index = 0; Index < 2; Index++) {
+ if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ String[Index] = GetTokenString (Value[Index + 1].Value.string, FormSet->HiiHandle);
+ if (String[Index] == NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+
+ if (Format == EFI_IFR_FF_CASE_INSENSITIVE) {
+ //
+ // Case insensitive, convert both string to upper case
+ //
+ IfrStrToUpper (String[Index]);
+ }
+ }
+
+ Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
+ if (Base >= StrLen (String[1])) {
+ Result->Value.u64 = 0xFFFFFFFFFFFFFFFFULL;
+ } else {
+ StringPtr = StrStr (String[1] + Base, String[0]);
+ Result->Value.u64 = (StringPtr == NULL) ? 0xFFFFFFFFFFFFFFFFULL : (StringPtr - String[1]);
+ }
+
+Done:
+ if (String[0] != NULL) {
+ FreePool (String[0]);
+ }
+
+ if (String[1] != NULL) {
+ FreePool (String[1]);
+ }
+
+ return Status;
+}
+
+/**
+ Evaluate opcode EFI_IFR_MID.
+
+ @param[in] FormSet Formset which contains this opcode.
+ @param[out] Result Evaluation result for this opcode.
+
+ @retval EFI_SUCCESS Opcode evaluation success.
+ @retval Other Opcode evaluation failed.
+
+**/
+EFI_STATUS
+IfrMid (
+ IN HII_FORMSET *FormSet,
+ OUT EFI_HII_VALUE *Result
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_VALUE Value[3];
+ CHAR16 *String;
+ UINTN Base;
+ UINTN Length;
+ CHAR16 *SubString;
+ UINT16 BufferLen;
+ UINT8 *Buffer;
+
+ if ((FormSet == NULL) || (Result == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (Value, sizeof (Value));
+
+ Status = PopExpression (&Value[0]);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = PopExpression (&Value[1]);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = PopExpression (&Value[2]);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;
+ return EFI_SUCCESS;
+ }
+
+ Length = (UINTN)Value[0].Value.u64;
+
+ if (Value[1].Type > EFI_IFR_TYPE_NUM_SIZE_64) {
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;
+ return EFI_SUCCESS;
+ }
+
+ Base = (UINTN)Value[1].Value.u64;
+
+ if ((Value[2].Type != EFI_IFR_TYPE_STRING) && !IsTypeInBuffer (&Value[2])) {
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;
+ return EFI_SUCCESS;
+ }
+
+ if (Value[2].Type == EFI_IFR_TYPE_STRING) {
+ String = GetTokenString (Value[2].Value.string, FormSet->HiiHandle);
+ if (String == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ if ((Length == 0) || (Base >= StrLen (String))) {
+ SubString = gEmptyString;
+ } else {
+ SubString = String + Base;
+ if ((Base + Length) < StrLen (String)) {
+ SubString[Length] = L'\0';
+ }
+ }
+
+ Result->Type = EFI_IFR_TYPE_STRING;
+ Result->Value.string = NewHiiString (SubString, FormSet->HiiHandle);
+
+ FreePool (String);
+ } else {
+ BufferLen = GetLengthForValue (&Value[2]);
+ Buffer = GetBufferForValue (&Value[2]);
+
+ Result->Type = EFI_IFR_TYPE_BUFFER;
+ if ((Length == 0) || (Base >= BufferLen)) {
+ Result->BufferLen = 0;
+ Result->Buffer = NULL;
+ } else {
+ Result->BufferLen = (UINT16)((BufferLen - Base) < Length ? (BufferLen - Base) : Length);
+ Result->Buffer = AllocatePool (Result->BufferLen);
+ ASSERT (Result->Buffer != NULL);
+ CopyMem (Result->Buffer, &Buffer[Base], Result->BufferLen);
+ }
+
+ if (Value[2].Type == EFI_IFR_TYPE_BUFFER) {
+ FreePool (Value[2].Buffer);
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Evaluate opcode EFI_IFR_TOKEN.
+
+ @param[in] FormSet Formset which contains this opcode.
+ @param[out] Result Evaluation result for this opcode.
+
+ @retval EFI_SUCCESS Opcode evaluation success.
+ @retval Other Opcode evaluation failed.
+
+**/
+EFI_STATUS
+IfrToken (
+ IN HII_FORMSET *FormSet,
+ OUT EFI_HII_VALUE *Result
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_VALUE Value[3];
+ CHAR16 *String[2];
+ UINTN Count;
+ CHAR16 *Delimiter;
+ CHAR16 *SubString;
+ CHAR16 *StringPtr;
+ UINTN Index;
+
+ if ((FormSet == NULL) || (Result == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (Value, sizeof (Value));
+
+ Status = PopExpression (&Value[0]);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = PopExpression (&Value[1]);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = PopExpression (&Value[2]);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;
+ return EFI_SUCCESS;
+ }
+
+ Count = (UINTN)Value[0].Value.u64;
+
+ //
+ // String[0] - Delimiter
+ // String[1] - The string to search
+ //
+ String[0] = NULL;
+ String[1] = NULL;
+ for (Index = 0; Index < 2; Index++) {
+ if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ String[Index] = GetTokenString (Value[Index + 1].Value.string, FormSet->HiiHandle);
+ if (String[Index] == NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+ }
+
+ Delimiter = String[0];
+ SubString = String[1];
+ while (Count > 0) {
+ SubString = StrStr (SubString, Delimiter);
+ if (SubString != NULL) {
+ //
+ // Skip over the delimiter
+ //
+ SubString = SubString + StrLen (Delimiter);
+ } else {
+ break;
+ }
+
+ Count--;
+ }
+
+ if (SubString == NULL) {
+ //
+ // nth delimited sub-string not found, push an empty string
+ //
+ SubString = gEmptyString;
+ } else {
+ //
+ // Put a NULL terminator for nth delimited sub-string
+ //
+ StringPtr = StrStr (SubString, Delimiter);
+ if (StringPtr != NULL) {
+ *StringPtr = L'\0';
+ }
+ }
+
+ Result->Type = EFI_IFR_TYPE_STRING;
+ Result->Value.string = NewHiiString (SubString, FormSet->HiiHandle);
+
+Done:
+ if (String[0] != NULL) {
+ FreePool (String[0]);
+ }
+
+ if (String[1] != NULL) {
+ FreePool (String[1]);
+ }
+
+ return Status;
+}
+
+/**
+ Evaluate opcode EFI_IFR_SPAN.
+
+ @param[in] FormSet Formset which contains this opcode.
+ @param[in] Flags FIRST_MATCHING or FIRST_NON_MATCHING.
+ @param[out] Result Evaluation result for this opcode.
+
+ @retval EFI_SUCCESS Opcode evaluation success.
+ @retval Other Opcode evaluation failed.
+
+**/
+EFI_STATUS
+IfrSpan (
+ IN HII_FORMSET *FormSet,
+ IN UINT8 Flags,
+ OUT EFI_HII_VALUE *Result
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_VALUE Value[3];
+ CHAR16 *String[2];
+ CHAR16 *Charset;
+ UINTN Base;
+ UINTN Index;
+ CHAR16 *StringPtr;
+ BOOLEAN Found;
+
+ if ((FormSet == NULL) || (Result == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (Value, sizeof (Value));
+
+ Status = PopExpression (&Value[0]);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = PopExpression (&Value[1]);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = PopExpression (&Value[2]);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;
+ return EFI_SUCCESS;
+ }
+
+ Base = (UINTN)Value[0].Value.u64;
+
+ //
+ // String[0] - Charset
+ // String[1] - The string to search
+ //
+ String[0] = NULL;
+ String[1] = NULL;
+ for (Index = 0; Index < 2; Index++) {
+ if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ String[Index] = GetTokenString (Value[Index + 1].Value.string, FormSet->HiiHandle);
+ if (String[Index] == NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+ }
+
+ if (Base >= StrLen (String[1])) {
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ Found = FALSE;
+ StringPtr = String[1] + Base;
+ Charset = String[0];
+ while (*StringPtr != 0 && !Found) {
+ Index = 0;
+ while (Charset[Index] != 0) {
+ if ((*StringPtr >= Charset[Index]) && (*StringPtr <= Charset[Index + 1])) {
+ if (Flags == EFI_IFR_FLAGS_FIRST_MATCHING) {
+ Found = TRUE;
+ break;
+ }
+ } else {
+ if (Flags == EFI_IFR_FLAGS_FIRST_NON_MATCHING) {
+ Found = TRUE;
+ break;
+ }
+ }
+
+ //
+ // Skip characters pair representing low-end of a range and high-end of a range
+ //
+ Index += 2;
+ }
+
+ if (!Found) {
+ StringPtr++;
+ }
+ }
+
+ Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
+ Result->Value.u64 = StringPtr - String[1];
+
+Done:
+ if (String[0] != NULL) {
+ FreePool (String[0]);
+ }
+
+ if (String[1] != NULL) {
+ FreePool (String[1]);
+ }
+
+ return Status;
+}
+
+/**
+ Get Expression given its RuleId.
+
+ @param[in] Form The form which contains this Expression.
+ @param[in] RuleId Id of this Expression.
+
+ @retval Pointer The Expression.
+ @retval NULL Specified Expression not found in the form.
+
+**/
+HII_EXPRESSION *
+RuleIdToExpression (
+ IN HII_FORM *Form,
+ IN UINT8 RuleId
+ )
+{
+ LIST_ENTRY *Link;
+ HII_EXPRESSION *Expression;
+
+ if (Form == NULL) {
+ return NULL;
+ }
+
+ Link = GetFirstNode (&Form->RuleListHead);
+ while (!IsNull (&Form->RuleListHead, Link)) {
+ Expression = HII_EXPRESSION_FROM_LINK (Link);
+
+ if ((Expression->Type == EFI_HII_EXPRESSION_RULE) && (Expression->ExtraData.RuleId == RuleId)) {
+ return Expression;
+ }
+
+ Link = GetNextNode (&Form->RuleListHead, Link);
+ }
+
+ return NULL;
+}
+
+/**
+ Locate the Unicode Collation Protocol interface for later use.
+
+ @retval EFI_SUCCESS Protocol interface initialize success.
+ @retval Other Protocol interface initialize failed.
+
+**/
+EFI_STATUS
+InitializeUnicodeCollationProtocol (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ if (mUnicodeCollation != NULL) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // BUGBUG: Proper implementation is to locate all Unicode Collation Protocol
+ // instances first and then select one which support English language.
+ // Current implementation just pick the first instance.
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiUnicodeCollation2ProtocolGuid,
+ NULL,
+ (VOID **)&mUnicodeCollation
+ );
+ return Status;
+}
+
+/**
+ Check whether the formset guid is in this Hii package list.
+
+ @param[in] HiiHandle The HiiHandle for this HII package list.
+ @param[in] FormSetGuid The formset guid for the request formset.
+
+ @retval TRUE Find the formset guid.
+ @retval FALSE Not found the formset guid.
+
+**/
+BOOLEAN
+IsFormsetGuidInHiiHandle (
+ IN EFI_HII_HANDLE HiiHandle,
+ IN EFI_GUID *FormSetGuid
+ )
+{
+ EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
+ UINTN BufferSize;
+ UINT32 Offset;
+ UINT32 Offset2;
+ UINT32 PackageListLength;
+ EFI_HII_PACKAGE_HEADER *PackageHeader;
+ UINT8 *Package;
+ UINT8 *OpCodeData;
+ EFI_STATUS Status;
+ BOOLEAN FindGuid;
+ EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
+
+ if (FormSetGuid == NULL) {
+ return FALSE;
+ }
+
+ BufferSize = 0;
+ HiiPackageList = NULL;
+ FindGuid = FALSE;
+
+ //
+ // Locate required Hii Database protocol
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiHiiDatabaseProtocolGuid,
+ NULL,
+ (VOID **)&HiiDatabase
+ );
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ Status = HiiDatabase->ExportPackageLists (HiiDatabase, HiiHandle, &BufferSize, HiiPackageList);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ HiiPackageList = AllocatePool (BufferSize);
+ if (HiiPackageList == NULL) {
+ ASSERT (HiiPackageList != NULL);
+ return FALSE;
+ }
+
+ Status = HiiDatabase->ExportPackageLists (HiiDatabase, HiiHandle, &BufferSize, HiiPackageList);
+ } else {
+ //
+ // Fix coverity: 14253 Explicit null dereferenced.
+ // When calling ExportPackageLists with BufferSize = 0, only EFI_BUFFER_TOO_SMALL is expected.
+ // Otherwise, return FALSE immediately.
+ //
+ return FALSE;
+ }
+
+ if (EFI_ERROR (Status)) {
+ if (HiiPackageList != NULL) {
+ FreePool (HiiPackageList);
+ }
+
+ return FALSE;
+ }
+
+ //
+ // Get Form package from this HII package List
+ //
+ Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
+ Offset2 = 0;
+ PackageListLength = HiiPackageList->PackageLength;
+
+ while (Offset < PackageListLength) {
+ Package = ((UINT8 *)HiiPackageList) + Offset;
+ PackageHeader = (EFI_HII_PACKAGE_HEADER *)Package;
+ Offset += PackageHeader->Length;
+
+ if (PackageHeader->Type == EFI_HII_PACKAGE_FORMS) {
+ //
+ // Search FormSet in this Form Package
+ //
+ Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);
+ while (Offset2 < PackageHeader->Length) {
+ OpCodeData = Package + Offset2;
+
+ if (((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {
+ if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {
+ FindGuid = TRUE;
+ break;
+ }
+ }
+
+ Offset2 += ((EFI_IFR_OP_HEADER *)OpCodeData)->Length;
+ }
+ }
+
+ if (FindGuid) {
+ break;
+ }
+ }
+
+ FreePool (HiiPackageList);
+
+ return FindGuid;
+}
+
+/**
+ Find HII Handle in the HII database associated with given Device Path.
+
+ If DevicePath is NULL, then ASSERT.
+
+ @param[in] DevicePath Device Path associated with the HII package list
+ handle.
+ @param[in] FormsetGuid The formset guid for this formset.
+
+ @retval Handle HII package list Handle associated with the Device
+ Path.
+ @retval NULL Hii Package list handle is not found.
+
+**/
+EFI_HII_HANDLE
+DevicePathToHiiHandle (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN EFI_GUID *FormsetGuid
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;
+ UINTN Index;
+ EFI_HANDLE Handle;
+ EFI_HANDLE DriverHandle;
+ EFI_HII_HANDLE *HiiHandles;
+ EFI_HII_HANDLE HiiHandle;
+ EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
+
+ if ((DevicePath == NULL) || (FormsetGuid == NULL)) {
+ return NULL;
+ }
+
+ TmpDevicePath = DevicePath;
+ //
+ // Locate Device Path Protocol handle buffer
+ //
+ Status = gBS->LocateDevicePath (
+ &gEfiDevicePathProtocolGuid,
+ &TmpDevicePath,
+ &DriverHandle
+ );
+ if (EFI_ERROR (Status) || !IsDevicePathEnd (TmpDevicePath)) {
+ return NULL;
+ }
+
+ //
+ // Locate required Hii Database protocol
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiHiiDatabaseProtocolGuid,
+ NULL,
+ (VOID **)&HiiDatabase
+ );
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ //
+ // Retrieve all HII Handles from HII database
+ //
+ HiiHandles = HiiGetHiiHandles (NULL);
+ if (HiiHandles == NULL) {
+ return NULL;
+ }
+
+ //
+ // Search Hii Handle by Driver Handle
+ //
+ HiiHandle = NULL;
+ for (Index = 0; HiiHandles[Index] != NULL; Index++) {
+ Status = HiiDatabase->GetPackageListHandle (
+ HiiDatabase,
+ HiiHandles[Index],
+ &Handle
+ );
+ if (!EFI_ERROR (Status) && (Handle == DriverHandle)) {
+ if (IsFormsetGuidInHiiHandle (HiiHandles[Index], FormsetGuid)) {
+ HiiHandle = HiiHandles[Index];
+ break;
+ }
+
+ if (HiiHandle != NULL) {
+ break;
+ }
+ }
+ }
+
+ FreePool (HiiHandles);
+ return HiiHandle;
+}
+
+/**
+ Get question value from the predefined formset.
+
+ @param[in] DevicePath The driver's device path which produce the formset data.
+ @param[in] InputHiiHandle The hii handle associate with the formset data.
+ @param[in] FormSetGuid The formset guid which include the question.
+ @param[in] QuestionId The question id which need to get value from.
+ @param[out] Value The return data about question's value.
+
+ @retval TRUE Get the question value success.
+ @retval FALSE Get the question value failed.
+**/
+BOOLEAN
+GetQuestionValueFromForm (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN EFI_HII_HANDLE InputHiiHandle,
+ IN EFI_GUID *FormSetGuid,
+ IN EFI_QUESTION_ID QuestionId,
+ OUT EFI_HII_VALUE *Value
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_HANDLE HiiHandle;
+ HII_STATEMENT *Question;
+ HII_FORMSET *FormSet;
+ HII_FORM *Form;
+ BOOLEAN GetTheVal;
+ LIST_ENTRY *Link;
+
+ //
+ // The input parameter DevicePath or InputHiiHandle must have one valid input.
+ //
+ if ((DevicePath == NULL) && (InputHiiHandle == NULL)) {
+ ASSERT (
+ (DevicePath != NULL && InputHiiHandle == NULL) ||
+ (DevicePath == NULL && InputHiiHandle != NULL)
+ );
+ return FALSE;
+ }
+
+ if ((FormSetGuid == NULL) || (Value == NULL)) {
+ return FALSE;
+ }
+
+ GetTheVal = TRUE;
+ HiiHandle = NULL;
+ Question = NULL;
+ Form = NULL;
+
+ //
+ // Get HiiHandle.
+ //
+ if (DevicePath != NULL) {
+ HiiHandle = DevicePathToHiiHandle (DevicePath, FormSetGuid);
+ if (HiiHandle == NULL) {
+ return FALSE;
+ }
+ } else {
+ HiiHandle = InputHiiHandle;
+ }
+
+ ASSERT (HiiHandle != NULL);
+
+ //
+ // Get the formset data include this question.
+ //
+ FormSet = AllocateZeroPool (sizeof (HII_FORMSET));
+ ASSERT (FormSet != NULL);
+
+ Status = CreateFormSetFromHiiHandle (HiiHandle, FormSetGuid, FormSet);
+ if (EFI_ERROR (Status)) {
+ GetTheVal = FALSE;
+ goto Done;
+ }
+
+ InitializeFormSet (FormSet);
+
+ //
+ // Base on the Question Id to get the question info.
+ //
+ Question = QuestionIdInFormset (FormSet, NULL, QuestionId);
+ if (Question == NULL) {
+ GetTheVal = FALSE;
+ goto Done;
+ }
+
+ //
+ // Search form in the formset scope
+ //
+ Link = GetFirstNode (&FormSet->FormListHead);
+ while (!IsNull (&FormSet->FormListHead, Link)) {
+ Form = HII_FORM_FROM_LINK (Link);
+
+ Question = QuestionIdInForm (Form, QuestionId);
+ if (Question != NULL) {
+ break;
+ }
+
+ Link = GetNextNode (&FormSet->FormListHead, Link);
+ Form = NULL;
+ }
+
+ ASSERT (Form != NULL);
+
+ //
+ // Get the question value.
+ //
+ Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);
+ if (EFI_ERROR (Status)) {
+ GetTheVal = FALSE;
+ goto Done;
+ }
+
+ CopyMem (Value, &Question->Value, sizeof (EFI_HII_VALUE));
+
+Done:
+ //
+ // Clean the formset structure and restore the global parameter.
+ //
+ if (FormSet != NULL) {
+ DestroyFormSet (FormSet);
+ }
+
+ return GetTheVal;
+}
+
+/**
+ Covert HII_STATEMENT_VALUE to EFI_HII_VALUE.
+
+ The HiiValue->Buffer is allocated from EFI boot services memory. It is the
+ responsibility of the caller to free the memory allocated.
+
+ @param[in] StatementValue Source to be converted.
+ @param[out] HiiValue The buffer that is converted from StatementValue
+
+ @retval EFI_SUCCESS Convert successfully.
+ @retval EFI_INVALID_PARAMETER StatementValue is NULL or HiiValue is NULL.
+
+**/
+EFI_STATUS
+HiiStatementValueToHiiValue (
+ IN HII_STATEMENT_VALUE *StatementValue,
+ OUT EFI_HII_VALUE *HiiValue
+ )
+{
+ if ((StatementValue == NULL) || (HiiValue == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (HiiValue, sizeof (EFI_HII_VALUE));
+
+ HiiValue->Type = StatementValue->Type;
+ HiiValue->BufferLen = StatementValue->BufferLen;
+ if ((StatementValue->Buffer != NULL) && (StatementValue->BufferLen > 0)) {
+ HiiValue->Buffer = AllocateCopyPool (HiiValue->BufferLen, StatementValue->Buffer);
+ }
+
+ CopyMem (&HiiValue->Value, &StatementValue->Value, sizeof (EFI_IFR_TYPE_VALUE));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Release the buffer in EFI_HII_VALUE if the buffer is not NULL.
+
+ @param[in] HiiValue The buffer to be released.
+
+ @retval EFI_SUCCESS release HiiValue successfully.
+ @retval EFI_INVALID_PARAMETER HiiValue is NULL.
+
+**/
+EFI_STATUS
+ReleaseHiiValue (
+ IN EFI_HII_VALUE *HiiValue
+ )
+{
+ if (HiiValue == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (HiiValue->Buffer == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ FreePool (HiiValue->Buffer);
+ ZeroMem (HiiValue, sizeof (EFI_HII_VALUE));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Evaluate the result of a HII expression.
+
+ If Expression is NULL, then ASSERT.
+
+ @param[in] FormSet FormSet associated with this expression.
+ @param[in] Form Form associated with this expression.
+ @param[in,out] Expression Expression to be evaluated.
+
+ @retval EFI_SUCCESS The expression evaluated successfully.
+ @retval EFI_NOT_FOUND The Question which referenced by a QuestionId
+ could not be found.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
+ stack.
+ @retval EFI_ACCESS_DENIED The pop operation underflowed the stack.
+ @retval EFI_INVALID_PARAMETER Syntax error with the Expression.
+ @retval EFI_INVALID_PARAMETER Formset, Form or Expression is NULL.
+
+**/
+EFI_STATUS
+EvaluateHiiExpression (
+ IN HII_FORMSET *FormSet,
+ IN HII_FORM *Form,
+ IN OUT HII_EXPRESSION *Expression
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ HII_EXPRESSION_OPCODE *OpCode;
+ HII_STATEMENT *Question;
+ HII_STATEMENT *Question2;
+ UINT16 Index;
+ EFI_HII_VALUE Data1;
+ EFI_HII_VALUE Data2;
+ EFI_HII_VALUE Data3;
+ HII_EXPRESSION *RuleExpression;
+ EFI_HII_VALUE *Value;
+ INTN Result;
+ CHAR16 *StrPtr;
+ CHAR16 *NameValue;
+ UINT32 TempValue;
+ LIST_ENTRY *SubExpressionLink;
+ HII_EXPRESSION *SubExpression;
+ UINTN StackOffset;
+ UINTN TempLength;
+ CHAR16 TempStr[5];
+ UINT8 DigitUint8;
+ UINT8 *TempBuffer;
+ EFI_TIME EfiTime;
+ EFI_HII_VALUE QuestionVal;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *PathFromText;
+
+ if ((FormSet == NULL) || (Form == NULL) || (Expression == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ StrPtr = NULL;
+ DevicePath = NULL;
+ PathFromText = NULL;
+
+ //
+ // Save current stack offset.
+ //
+ StackOffset = SaveExpressionEvaluationStackOffset ();
+
+ ASSERT (Expression != NULL);
+ Expression->Result.Type = EFI_IFR_TYPE_OTHER;
+
+ Link = GetFirstNode (&Expression->OpCodeListHead);
+ while (!IsNull (&Expression->OpCodeListHead, Link)) {
+ OpCode = HII_EXPRESSION_OPCODE_FROM_LINK (Link);
+
+ Link = GetNextNode (&Expression->OpCodeListHead, Link);
+
+ ZeroMem (&Data1, sizeof (EFI_HII_VALUE));
+ ZeroMem (&Data2, sizeof (EFI_HII_VALUE));
+ ZeroMem (&Data3, sizeof (EFI_HII_VALUE));
+
+ Value = &Data3;
+ Value->Type = EFI_IFR_TYPE_BOOLEAN;
+ Status = EFI_SUCCESS;
+
+ switch (OpCode->Operand) {
+ //
+ // Built-in functions
+ //
+ case EFI_IFR_EQ_ID_VAL_OP:
+ Question = QuestionIdInFormset (FormSet, Form, OpCode->ExtraData.EqIdValData.QuestionId);
+ if (Question == NULL) {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ break;
+ }
+
+ //
+ // Load value from storage.
+ //
+ Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);
+ if (EFI_ERROR (Status)) {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ break;
+ }
+
+ Status = HiiStatementValueToHiiValue (&Question->Value, &Data1);
+ if (EFI_ERROR (Status)) {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ break;
+ }
+
+ Status = CompareHiiValue (&Data1, &OpCode->ExtraData.EqIdValData.Value, &Result, NULL);
+ ReleaseHiiValue (&Data1);
+ if (Status == EFI_UNSUPPORTED) {
+ Status = EFI_SUCCESS;
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ break;
+ }
+
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Value->Value.b = (BOOLEAN)((Result == 0) ? TRUE : FALSE);
+ break;
+
+ case EFI_IFR_EQ_ID_ID_OP:
+ Question = QuestionIdInFormset (FormSet, Form, OpCode->ExtraData.EqIdIdData.QuestionId1);
+ if (Question == NULL) {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ break;
+ }
+
+ //
+ // Load value from storage.
+ //
+ Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);
+ if (EFI_ERROR (Status)) {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ break;
+ }
+
+ Status = HiiStatementValueToHiiValue (&Question->Value, &Data1);
+ if (EFI_ERROR (Status)) {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ break;
+ }
+
+ Question2 = QuestionIdInFormset (FormSet, Form, OpCode->ExtraData.EqIdIdData.QuestionId2);
+ if (Question2 == NULL) {
+ ReleaseHiiValue (&Data1);
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ break;
+ }
+
+ //
+ // Load value from storage.
+ //
+ Status = GetQuestionValue (FormSet, Form, Question2, GetSetValueWithBuffer);
+ if (EFI_ERROR (Status)) {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ break;
+ }
+
+ Status = HiiStatementValueToHiiValue (&Question2->Value, &Data2);
+ if (EFI_ERROR (Status)) {
+ ReleaseHiiValue (&Data1);
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ break;
+ }
+
+ Status = CompareHiiValue (&Data1, &Data2, &Result, FormSet->HiiHandle);
+ ReleaseHiiValue (&Data1);
+ ReleaseHiiValue (&Data2);
+ if (Status == EFI_UNSUPPORTED) {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ Status = EFI_SUCCESS;
+ break;
+ }
+
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Value->Value.b = (BOOLEAN)((Result == 0) ? TRUE : FALSE);
+ break;
+
+ case EFI_IFR_EQ_ID_VAL_LIST_OP:
+ Question = QuestionIdInFormset (FormSet, Form, OpCode->ExtraData.EqIdListData.QuestionId);
+ if (Question == NULL) {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ break;
+ }
+
+ //
+ // Load value from storage.
+ //
+ Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);
+ if (EFI_ERROR (Status)) {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ break;
+ }
+
+ Value->Value.b = FALSE;
+ for (Index = 0; Index < OpCode->ExtraData.EqIdListData.ListLength; Index++) {
+ if (Question->Value.Value.u16 == OpCode->ExtraData.EqIdListData.ValueList[Index]) {
+ Value->Value.b = TRUE;
+ break;
+ }
+ }
+
+ break;
+
+ case EFI_IFR_DUP_OP:
+ Status = PopExpression (Value);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Status = PushExpression (Value);
+ break;
+
+ case EFI_IFR_QUESTION_REF1_OP:
+ case EFI_IFR_THIS_OP:
+ Question = QuestionIdInFormset (FormSet, Form, OpCode->ExtraData.QuestionRef1Data.QuestionId);
+ if (Question == NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+
+ //
+ // Load value from storage.
+ //
+ Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Value = (EFI_HII_VALUE *)&Question->Value;
+ break;
+
+ case EFI_IFR_SECURITY_OP:
+ Value->Value.b = CheckUserPrivilege (&OpCode->ExtraData.Guid);
+ break;
+
+ case EFI_IFR_GET_OP:
+ //
+ // Get Value from VarStore buffer, EFI VarStore, Name/Value VarStore.
+ //
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ Value->Value.u8 = 0;
+ if (OpCode->ExtraData.GetSetData.VarStorage != NULL) {
+ switch (OpCode->ExtraData.GetSetData.VarStorage->Type) {
+ case EFI_HII_VARSTORE_BUFFER:
+ case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
+ //
+ // Get value from Edit Buffer
+ //
+ Value->Type = OpCode->ExtraData.GetSetData.ValueType;
+ CopyMem (&Value->Value, OpCode->ExtraData.GetSetData.VarStorage->EditBuffer + OpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset, OpCode->ExtraData.GetSetData.ValueWidth);
+ break;
+ case EFI_HII_VARSTORE_NAME_VALUE:
+ if (OpCode->ExtraData.GetSetData.ValueType != EFI_IFR_TYPE_STRING) {
+ //
+ // Get value from string except for STRING value.
+ //
+ Status = GetValueByName (OpCode->ExtraData.GetSetData.VarStorage, OpCode->ExtraData.GetSetData.ValueName, &StrPtr);
+ if (!EFI_ERROR (Status)) {
+ ASSERT (StrPtr != NULL);
+ TempLength = StrLen (StrPtr);
+ if (OpCode->ExtraData.GetSetData.ValueWidth >= ((TempLength + 1) / 2)) {
+ Value->Type = OpCode->ExtraData.GetSetData.ValueType;
+ TempBuffer = (UINT8 *)&Value->Value;
+ ZeroMem (TempStr, sizeof (TempStr));
+ for (Index = 0; Index < TempLength; Index++) {
+ TempStr[0] = StrPtr[TempLength - Index - 1];
+ DigitUint8 = (UINT8)StrHexToUint64 (TempStr);
+ if ((Index & 1) == 0) {
+ TempBuffer[Index/2] = DigitUint8;
+ } else {
+ TempBuffer[Index/2] = (UINT8)((DigitUint8 << 4) + TempBuffer[Index/2]);
+ }
+ }
+ }
+ }
+ }
+
+ break;
+ case EFI_HII_VARSTORE_EFI_VARIABLE:
+ //
+ // Get value from variable.
+ //
+ TempLength = OpCode->ExtraData.GetSetData.ValueWidth;
+ Value->Type = OpCode->ExtraData.GetSetData.ValueType;
+ Status = gRT->GetVariable (
+ OpCode->ExtraData.GetSetData.ValueName,
+ &OpCode->ExtraData.GetSetData.VarStorage->Guid,
+ NULL,
+ &TempLength,
+ &Value->Value
+ );
+ if (EFI_ERROR (Status)) {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ Value->Value.u8 = 0;
+ }
+
+ break;
+ default:
+ //
+ // Not recognize storage.
+ //
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+ } else {
+ //
+ // For Time/Date Data
+ //
+ if ((OpCode->ExtraData.GetSetData.ValueType != EFI_IFR_TYPE_DATE) && (OpCode->ExtraData.GetSetData.ValueType != EFI_IFR_TYPE_TIME)) {
+ //
+ // Only support Data/Time data when storage doesn't exist.
+ //
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ Status = gRT->GetTime (&EfiTime, NULL);
+ if (!EFI_ERROR (Status)) {
+ if (OpCode->ExtraData.GetSetData.ValueType == EFI_IFR_TYPE_DATE) {
+ switch (OpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset) {
+ case 0x00:
+ Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
+ Value->Value.u16 = EfiTime.Year;
+ break;
+ case 0x02:
+ Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
+ Value->Value.u8 = EfiTime.Month;
+ break;
+ case 0x03:
+ Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
+ Value->Value.u8 = EfiTime.Day;
+ break;
+ default:
+ //
+ // Invalid Date field.
+ //
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+ } else {
+ switch (OpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset) {
+ case 0x00:
+ Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
+ Value->Value.u8 = EfiTime.Hour;
+ break;
+ case 0x01:
+ Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
+ Value->Value.u8 = EfiTime.Minute;
+ break;
+ case 0x02:
+ Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
+ Value->Value.u8 = EfiTime.Second;
+ break;
+ default:
+ //
+ // Invalid Time field.
+ //
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+ }
+ }
+ }
+
+ break;
+
+ case EFI_IFR_QUESTION_REF3_OP:
+ //
+ // EFI_IFR_QUESTION_REF3
+ // Pop an expression from the expression stack
+ //
+ Status = PopExpression (Value);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Validate the expression value
+ //
+ if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ break;
+ }
+
+ if (OpCode->ExtraData.QuestionRef3Data.DevicePath != 0) {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+
+ Status = gBS->LocateProtocol (
+ &gEfiDevicePathFromTextProtocolGuid,
+ NULL,
+ (VOID **)&PathFromText
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ StrPtr = GetTokenString (OpCode->ExtraData.QuestionRef3Data.DevicePath, FormSet->HiiHandle);
+ if ((StrPtr != NULL) && (PathFromText != NULL)) {
+ DevicePath = PathFromText->ConvertTextToDevicePath (StrPtr);
+ if ((DevicePath != NULL) && GetQuestionValueFromForm (DevicePath, NULL, &OpCode->ExtraData.Guid, Value->Value.u16, &QuestionVal)) {
+ Value = &QuestionVal;
+ }
+
+ if (DevicePath != NULL) {
+ FreePool (DevicePath);
+ }
+ }
+
+ if (StrPtr != NULL) {
+ FreePool (StrPtr);
+ }
+ } else if (IsZeroGuid (&OpCode->ExtraData.Guid)) {
+ if (!GetQuestionValueFromForm (NULL, FormSet->HiiHandle, &OpCode->ExtraData.Guid, Value->Value.u16, &QuestionVal)) {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ break;
+ }
+
+ Value = &QuestionVal;
+ } else {
+ Question = QuestionIdInFormset (FormSet, Form, Value->Value.u16);
+ if (Question == NULL) {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ break;
+ }
+
+ //
+ // Load value from storage.
+ //
+ Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);
+ if (EFI_ERROR (Status)) {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ break;
+ }
+
+ //
+ // push the questions' value on to the expression stack
+ //
+ Value = (EFI_HII_VALUE *)&Question->Value;
+ }
+
+ break;
+
+ case EFI_IFR_RULE_REF_OP:
+ //
+ // Find expression for this rule
+ //
+ RuleExpression = RuleIdToExpression (Form, OpCode->ExtraData.RuleId);
+ if (RuleExpression == NULL) {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ break;
+ }
+
+ //
+ // Evaluate this rule expression
+ //
+ Status = EvaluateHiiExpression (FormSet, Form, RuleExpression);
+ if (EFI_ERROR (Status) || (RuleExpression->Result.Type == EFI_IFR_TYPE_UNDEFINED)) {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ break;
+ }
+
+ Value = &RuleExpression->Result;
+ break;
+
+ case EFI_IFR_STRING_REF1_OP:
+ Value->Type = EFI_IFR_TYPE_STRING;
+ Value->Value.string = OpCode->ExtraData.Value.Value.string;
+ break;
+
+ //
+ // Constant
+ //
+ case EFI_IFR_TRUE_OP:
+ case EFI_IFR_FALSE_OP:
+ case EFI_IFR_ONE_OP:
+ case EFI_IFR_ONES_OP:
+ case EFI_IFR_UINT8_OP:
+ case EFI_IFR_UINT16_OP:
+ case EFI_IFR_UINT32_OP:
+ case EFI_IFR_UINT64_OP:
+ case EFI_IFR_UNDEFINED_OP:
+ case EFI_IFR_VERSION_OP:
+ case EFI_IFR_ZERO_OP:
+ Value = &OpCode->ExtraData.Value;
+ break;
+
+ //
+ // unary-op
+ //
+ case EFI_IFR_LENGTH_OP:
+ Status = PopExpression (Value);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if ((Value->Type != EFI_IFR_TYPE_STRING) && !IsTypeInBuffer (Value)) {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ break;
+ }
+
+ if (Value->Type == EFI_IFR_TYPE_STRING) {
+ StrPtr = GetTokenString (Value->Value.string, FormSet->HiiHandle);
+ if (StrPtr == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
+ Value->Value.u64 = StrLen (StrPtr);
+ FreePool (StrPtr);
+ } else {
+ Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
+ Value->Value.u64 = GetLengthForValue (Value);
+ FreePool (Value->Buffer);
+ }
+
+ break;
+
+ case EFI_IFR_NOT_OP:
+ Status = PopExpression (Value);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ break;
+ }
+
+ Value->Value.b = (BOOLEAN)(!Value->Value.b);
+ break;
+
+ case EFI_IFR_QUESTION_REF2_OP:
+ //
+ // Pop an expression from the expression stack
+ //
+ Status = PopExpression (Value);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Validate the expression value
+ //
+ if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ break;
+ }
+
+ Question = QuestionIdInFormset (FormSet, Form, Value->Value.u16);
+ if (Question == NULL) {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ break;
+ }
+
+ //
+ // Load value from storage.
+ //
+ Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);
+ if (EFI_ERROR (Status)) {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ break;
+ }
+
+ Value = (EFI_HII_VALUE *)&Question->Value;
+ break;
+
+ case EFI_IFR_STRING_REF2_OP:
+ //
+ // Pop an expression from the expression stack
+ //
+ Status = PopExpression (Value);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Validate the expression value
+ //
+ if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ break;
+ }
+
+ Value->Type = EFI_IFR_TYPE_STRING;
+ StrPtr = GetTokenString (Value->Value.u16, FormSet->HiiHandle);
+ if (StrPtr == NULL) {
+ //
+ // If String not exit, push an empty string
+ //
+ Value->Value.string = NewHiiString (gEmptyString, FormSet->HiiHandle);
+ } else {
+ Index = (UINT16)Value->Value.u64;
+ Value->Value.string = Index;
+ FreePool (StrPtr);
+ }
+
+ break;
+
+ case EFI_IFR_TO_BOOLEAN_OP:
+ //
+ // Pop an expression from the expression stack
+ //
+ Status = PopExpression (Value);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Convert an expression to a Boolean
+ //
+ if (Value->Type <= EFI_IFR_TYPE_DATE) {
+ //
+ // When converting from an unsigned integer, zero will be converted to
+ // FALSE and any other value will be converted to TRUE.
+ //
+ Value->Value.b = (BOOLEAN)(HiiValueToUINT64 (Value) != 0);
+
+ Value->Type = EFI_IFR_TYPE_BOOLEAN;
+ } else if (Value->Type == EFI_IFR_TYPE_STRING) {
+ //
+ // When converting from a string, if case-insensitive compare
+ // with "true" is True, then push True. If a case-insensitive compare
+ // with "false" is True, then push False. Otherwise, push Undefined.
+ //
+ StrPtr = GetTokenString (Value->Value.string, FormSet->HiiHandle);
+ if (StrPtr == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ IfrStrToUpper (StrPtr);
+ if (StrCmp (StrPtr, L"TRUE") == 0) {
+ Value->Value.b = TRUE;
+ Value->Type = EFI_IFR_TYPE_BOOLEAN;
+ } else if (StrCmp (StrPtr, L"FALSE") == 0) {
+ Value->Value.b = FALSE;
+ Value->Type = EFI_IFR_TYPE_BOOLEAN;
+ } else {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ }
+
+ FreePool (StrPtr);
+ } else if (Value->Type == EFI_IFR_TYPE_BUFFER) {
+ //
+ // When converting from a buffer, if the buffer is all zeroes,
+ // then push False. Otherwise push True.
+ //
+ for (Index = 0; Index < Value->BufferLen; Index++) {
+ if (Value->Buffer[Index] != 0) {
+ break;
+ }
+ }
+
+ if (Index >= Value->BufferLen) {
+ Value->Value.b = FALSE;
+ } else {
+ Value->Value.b = TRUE;
+ }
+
+ Value->Type = EFI_IFR_TYPE_BOOLEAN;
+ FreePool (Value->Buffer);
+ }
+
+ break;
+
+ case EFI_IFR_TO_STRING_OP:
+ Status = IfrToString (FormSet, OpCode->ExtraData.Format, Value);
+ break;
+
+ case EFI_IFR_TO_UINT_OP:
+ Status = IfrToUint (FormSet, Value);
+ break;
+
+ case EFI_IFR_TO_LOWER_OP:
+ case EFI_IFR_TO_UPPER_OP:
+ Status = InitializeUnicodeCollationProtocol ();
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Status = PopExpression (Value);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (Value->Type != EFI_IFR_TYPE_STRING) {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ break;
+ }
+
+ StrPtr = GetTokenString (Value->Value.string, FormSet->HiiHandle);
+ if (StrPtr == NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+
+ if (OpCode->Operand == EFI_IFR_TO_LOWER_OP) {
+ mUnicodeCollation->StrLwr (mUnicodeCollation, StrPtr);
+ } else {
+ mUnicodeCollation->StrUpr (mUnicodeCollation, StrPtr);
+ }
+
+ Value->Value.string = NewHiiString (StrPtr, FormSet->HiiHandle);
+ FreePool (StrPtr);
+ break;
+
+ case EFI_IFR_BITWISE_NOT_OP:
+ //
+ // Pop an expression from the expression stack
+ //
+ Status = PopExpression (Value);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (Value->Type > EFI_IFR_TYPE_DATE) {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ break;
+ }
+
+ Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
+ Value->Value.u64 = ~HiiValueToUINT64(Value);
+ break;
+
+ case EFI_IFR_SET_OP:
+ //
+ // Pop an expression from the expression stack
+ //
+ Status = PopExpression (Value);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Data1.Type = EFI_IFR_TYPE_BOOLEAN;
+ Data1.Value.b = FALSE;
+ //
+ // Set value to var storage buffer
+ //
+ if (OpCode->ExtraData.GetSetData.VarStorage != NULL) {
+ switch (OpCode->ExtraData.GetSetData.VarStorage->Type) {
+ case EFI_HII_VARSTORE_BUFFER:
+ case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
+ CopyMem (OpCode->ExtraData.GetSetData.VarStorage->EditBuffer + OpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset, &Value->Value, OpCode->ExtraData.GetSetData.ValueWidth);
+ Data1.Value.b = TRUE;
+ break;
+ case EFI_HII_VARSTORE_NAME_VALUE:
+ if (OpCode->ExtraData.GetSetData.ValueType != EFI_IFR_TYPE_STRING) {
+ NameValue = AllocatePool ((OpCode->ExtraData.GetSetData.ValueWidth * 2 + 1) * sizeof (CHAR16));
+ ASSERT (NameValue != NULL);
+ //
+ // Convert Buffer to Hex String
+ //
+ TempBuffer = (UINT8 *)&Value->Value + OpCode->ExtraData.GetSetData.ValueWidth - 1;
+ StrPtr = NameValue;
+ for (Index = 0; Index < OpCode->ExtraData.GetSetData.ValueWidth; Index++, TempBuffer--) {
+ UnicodeValueToStringS (
+ StrPtr,
+ (OpCode->ExtraData.GetSetData.ValueWidth * 2 + 1) * sizeof (CHAR16) - ((UINTN)StrPtr - (UINTN)NameValue),
+ PREFIX_ZERO | RADIX_HEX,
+ *TempBuffer,
+ 2
+ );
+ StrPtr += StrnLenS (StrPtr, OpCode->ExtraData.GetSetData.ValueWidth * 2 + 1 - ((UINTN)StrPtr - (UINTN)NameValue) / sizeof (CHAR16));
+ }
+
+ Status = SetValueByName (OpCode->ExtraData.GetSetData.VarStorage, OpCode->ExtraData.GetSetData.ValueName, NameValue, NULL);
+ FreePool (NameValue);
+ if (!EFI_ERROR (Status)) {
+ Data1.Value.b = TRUE;
+ }
+ }
+
+ break;
+ case EFI_HII_VARSTORE_EFI_VARIABLE:
+ Status = gRT->SetVariable (
+ OpCode->ExtraData.GetSetData.ValueName,
+ &OpCode->ExtraData.GetSetData.VarStorage->Guid,
+ OpCode->ExtraData.GetSetData.VarStorage->Attributes,
+ OpCode->ExtraData.GetSetData.ValueWidth,
+ &Value->Value
+ );
+ if (!EFI_ERROR (Status)) {
+ Data1.Value.b = TRUE;
+ }
+
+ break;
+ default:
+ //
+ // Not recognize storage.
+ //
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+ } else {
+ //
+ // For Time/Date Data
+ //
+ if ((OpCode->ExtraData.GetSetData.ValueType != EFI_IFR_TYPE_DATE) && (OpCode->ExtraData.GetSetData.ValueType != EFI_IFR_TYPE_TIME)) {
+ //
+ // Only support Data/Time data when storage doesn't exist.
+ //
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ Status = gRT->GetTime (&EfiTime, NULL);
+ if (!EFI_ERROR (Status)) {
+ if (OpCode->ExtraData.GetSetData.ValueType == EFI_IFR_TYPE_DATE) {
+ switch (OpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset) {
+ case 0x00:
+ EfiTime.Year = Value->Value.u16;
+ break;
+ case 0x02:
+ EfiTime.Month = Value->Value.u8;
+ break;
+ case 0x03:
+ EfiTime.Day = Value->Value.u8;
+ break;
+ default:
+ //
+ // Invalid Date field.
+ //
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+ } else {
+ switch (OpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset) {
+ case 0x00:
+ EfiTime.Hour = Value->Value.u8;
+ break;
+ case 0x01:
+ EfiTime.Minute = Value->Value.u8;
+ break;
+ case 0x02:
+ EfiTime.Second = Value->Value.u8;
+ break;
+ default:
+ //
+ // Invalid Time field.
+ //
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+ }
+
+ Status = gRT->SetTime (&EfiTime);
+ if (!EFI_ERROR (Status)) {
+ Data1.Value.b = TRUE;
+ }
+ }
+ }
+
+ Value = &Data1;
+ break;
+
+ //
+ // binary-op
+ //
+ case EFI_IFR_ADD_OP:
+ case EFI_IFR_SUBTRACT_OP:
+ case EFI_IFR_MULTIPLY_OP:
+ case EFI_IFR_DIVIDE_OP:
+ case EFI_IFR_MODULO_OP:
+ case EFI_IFR_BITWISE_AND_OP:
+ case EFI_IFR_BITWISE_OR_OP:
+ case EFI_IFR_SHIFT_LEFT_OP:
+ case EFI_IFR_SHIFT_RIGHT_OP:
+ //
+ // Pop an expression from the expression stack
+ //
+ Status = PopExpression (&Data2);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Pop another expression from the expression stack
+ //
+ Status = PopExpression (&Data1);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (Data2.Type > EFI_IFR_TYPE_DATE) {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ break;
+ }
+
+ if (Data1.Type > EFI_IFR_TYPE_DATE) {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ break;
+ }
+
+ Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
+
+ switch (OpCode->Operand) {
+ case EFI_IFR_ADD_OP:
+ Value->Value.u64 = HiiValueToUINT64 (&Data1) + HiiValueToUINT64 (&Data2);
+ break;
+
+ case EFI_IFR_SUBTRACT_OP:
+ Value->Value.u64 = HiiValueToUINT64 (&Data1) - HiiValueToUINT64 (&Data2);
+ break;
+
+ case EFI_IFR_MULTIPLY_OP:
+ Value->Value.u64 = MultU64x32 (HiiValueToUINT64 (&Data1), (UINT32)HiiValueToUINT64 (&Data2));
+ break;
+
+ case EFI_IFR_DIVIDE_OP:
+ Value->Value.u64 = DivU64x32 (HiiValueToUINT64 (&Data1), (UINT32)HiiValueToUINT64 (&Data2));
+ break;
+
+ case EFI_IFR_MODULO_OP:
+ DivU64x32Remainder (HiiValueToUINT64 (&Data1), (UINT32)HiiValueToUINT64 (&Data2), &TempValue);
+ Value->Value.u64 = TempValue;
+ break;
+
+ case EFI_IFR_BITWISE_AND_OP:
+ Value->Value.u64 = HiiValueToUINT64 (&Data1) & HiiValueToUINT64 (&Data2);
+ break;
+
+ case EFI_IFR_BITWISE_OR_OP:
+ Value->Value.u64 = HiiValueToUINT64 (&Data1) | HiiValueToUINT64 (&Data2);
+ break;
+
+ case EFI_IFR_SHIFT_LEFT_OP:
+ Value->Value.u64 = LShiftU64 (HiiValueToUINT64 (&Data1), (UINTN)HiiValueToUINT64 (&Data2));
+ break;
+
+ case EFI_IFR_SHIFT_RIGHT_OP:
+ Value->Value.u64 = RShiftU64 (HiiValueToUINT64 (&Data1), (UINTN)HiiValueToUINT64 (&Data2));
+ break;
+
+ default:
+ break;
+ }
+
+ break;
+
+ case EFI_IFR_AND_OP:
+ case EFI_IFR_OR_OP:
+ //
+ // Two Boolean operator
+ //
+ Status = PopExpression (&Data2);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Pop another expression from the expression stack
+ //
+ Status = PopExpression (&Data1);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ break;
+ }
+
+ if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ break;
+ }
+
+ if (OpCode->Operand == EFI_IFR_AND_OP) {
+ Value->Value.b = (BOOLEAN)(Data1.Value.b && Data2.Value.b);
+ } else {
+ Value->Value.b = (BOOLEAN)(Data1.Value.b || Data2.Value.b);
+ }
+
+ break;
+
+ case EFI_IFR_EQUAL_OP:
+ case EFI_IFR_NOT_EQUAL_OP:
+ case EFI_IFR_GREATER_EQUAL_OP:
+ case EFI_IFR_GREATER_THAN_OP:
+ case EFI_IFR_LESS_EQUAL_OP:
+ case EFI_IFR_LESS_THAN_OP:
+ //
+ // Compare two integer, string, boolean or date/time
+ //
+ Status = PopExpression (&Data2);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Pop another expression from the expression stack
+ //
+ Status = PopExpression (&Data1);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if ((Data2.Type > EFI_IFR_TYPE_BOOLEAN) &&
+ (Data2.Type != EFI_IFR_TYPE_STRING) &&
+ !IsTypeInBuffer (&Data2))
+ {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ break;
+ }
+
+ if ((Data1.Type > EFI_IFR_TYPE_BOOLEAN) &&
+ (Data1.Type != EFI_IFR_TYPE_STRING) &&
+ !IsTypeInBuffer (&Data1))
+ {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ break;
+ }
+
+ Status = CompareHiiValue (&Data1, &Data2, &Result, FormSet->HiiHandle);
+ if (Data1.Type == EFI_IFR_TYPE_BUFFER) {
+ FreePool (Data1.Buffer);
+ }
+
+ if (Data2.Type == EFI_IFR_TYPE_BUFFER) {
+ FreePool (Data2.Buffer);
+ }
+
+ if (Status == EFI_UNSUPPORTED) {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ Status = EFI_SUCCESS;
+ break;
+ }
+
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ switch (OpCode->Operand) {
+ case EFI_IFR_EQUAL_OP:
+ Value->Value.b = (BOOLEAN)((Result == 0) ? TRUE : FALSE);
+ break;
+
+ case EFI_IFR_NOT_EQUAL_OP:
+ Value->Value.b = (BOOLEAN)((Result != 0) ? TRUE : FALSE);
+ break;
+
+ case EFI_IFR_GREATER_EQUAL_OP:
+ Value->Value.b = (BOOLEAN)((Result >= 0) ? TRUE : FALSE);
+ break;
+
+ case EFI_IFR_GREATER_THAN_OP:
+ Value->Value.b = (BOOLEAN)((Result > 0) ? TRUE : FALSE);
+ break;
+
+ case EFI_IFR_LESS_EQUAL_OP:
+ Value->Value.b = (BOOLEAN)((Result <= 0) ? TRUE : FALSE);
+ break;
+
+ case EFI_IFR_LESS_THAN_OP:
+ Value->Value.b = (BOOLEAN)((Result < 0) ? TRUE : FALSE);
+ break;
+
+ default:
+ break;
+ }
+
+ break;
+
+ case EFI_IFR_MATCH_OP:
+ Status = InitializeUnicodeCollationProtocol ();
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Status = IfrMatch (FormSet, Value);
+ break;
+
+ case EFI_IFR_MATCH2_OP:
+ Status = IfrMatch2 (FormSet, &OpCode->ExtraData.Guid, Value);
+ break;
+
+ case EFI_IFR_CATENATE_OP:
+ Status = IfrCatenate (FormSet, Value);
+ break;
+
+ //
+ // ternary-op
+ //
+ case EFI_IFR_CONDITIONAL_OP:
+ //
+ // Pop third expression from the expression stack
+ //
+ Status = PopExpression (&Data3);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Pop second expression from the expression stack
+ //
+ Status = PopExpression (&Data2);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Pop first expression from the expression stack
+ //
+ Status = PopExpression (&Data1);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ break;
+ }
+
+ if (Data1.Value.b) {
+ Value = &Data3;
+ } else {
+ Value = &Data2;
+ }
+
+ break;
+
+ case EFI_IFR_FIND_OP:
+ Status = IfrFind (FormSet, OpCode->ExtraData.Format, Value);
+ break;
+
+ case EFI_IFR_MID_OP:
+ Status = IfrMid (FormSet, Value);
+ break;
+
+ case EFI_IFR_TOKEN_OP:
+ Status = IfrToken (FormSet, Value);
+ break;
+
+ case EFI_IFR_SPAN_OP:
+ Status = IfrSpan (FormSet, OpCode->ExtraData.Flags, Value);
+ break;
+
+ case EFI_IFR_MAP_OP:
+ //
+ // Pop the check value
+ //
+ Status = PopExpression (&Data1);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Check MapExpression list is valid.
+ //
+ if (OpCode->MapExpressionList.ForwardLink == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ //
+ // Go through map expression list.
+ //
+ SubExpressionLink = GetFirstNode (&OpCode->MapExpressionList);
+ while (!IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
+ SubExpression = HII_EXPRESSION_FROM_LINK (SubExpressionLink);
+ //
+ // Evaluate the first expression in this pair.
+ //
+ Status = EvaluateHiiExpression (FormSet, Form, SubExpression);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Compare the expression value with current value
+ //
+ if ((CompareHiiValue (&Data1, &SubExpression->Result, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {
+ //
+ // Try get the map value.
+ //
+ SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);
+ if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ SubExpression = HII_EXPRESSION_FROM_LINK (SubExpressionLink);
+ Status = EvaluateHiiExpression (FormSet, Form, SubExpression);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Value = &SubExpression->Result;
+ break;
+ }
+
+ //
+ // Skip the second expression on this pair.
+ //
+ SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);
+ if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ //
+ // Goto the first expression on next pair.
+ //
+ SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);
+ }
+
+ //
+ // No map value is found.
+ //
+ if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;
+ Value->Value.u8 = 0;
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ if (EFI_ERROR (Status) || (Value->Type == EFI_IFR_TYPE_UNDEFINED)) {
+ goto Done;
+ }
+
+ Status = PushExpression (Value);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ }
+
+ //
+ // Pop the final result from expression stack
+ //
+ Value = &Data1;
+ Status = PopExpression (Value);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // After evaluating an expression, there should be only one value left on the expression stack
+ //
+ if (PopExpression (Value) != EFI_ACCESS_DENIED) {
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+Done:
+ RestoreExpressionEvaluationStackOffset (StackOffset);
+ if (!EFI_ERROR (Status)) {
+ CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));
+ }
+
+ return Status;
+}
+
+/**
+ Set value of a data element in an Array by its Index.
+
+ @param[in] Array The data array.
+ @param[in] Type Type of the data in this array.
+ @param[in] Index Zero based index for data in this array.
+ @param[in] Value The value to be set.
+
+**/
+VOID
+SetArrayData (
+ IN VOID *Array,
+ IN UINT8 Type,
+ IN UINTN Index,
+ IN UINT64 Value
+ )
+{
+ ASSERT (Array != NULL);
+
+ switch (Type) {
+ case EFI_IFR_TYPE_NUM_SIZE_8:
+ *(((UINT8 *)Array) + Index) = (UINT8)Value;
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_16:
+ *(((UINT16 *)Array) + Index) = (UINT16)Value;
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_32:
+ *(((UINT32 *)Array) + Index) = (UINT32)Value;
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_64:
+ *(((UINT64 *)Array) + Index) = (UINT64)Value;
+ break;
+
+ default:
+ break;
+ }
+}
+
+/**
+ Search an Option of a Question by its value.
+
+ @param[in] Question The Question
+ @param[in] OptionValue Value for Option to be searched.
+
+ @retval Pointer Pointer to the found Option.
+ @retval NULL Option not found.
+
+**/
+HII_QUESTION_OPTION *
+ValueToOption (
+ IN HII_STATEMENT *Question,
+ IN HII_STATEMENT_VALUE *OptionValue
+ )
+{
+ LIST_ENTRY *Link;
+ HII_QUESTION_OPTION *Option;
+ EFI_HII_VALUE Data1;
+ EFI_HII_VALUE Data2;
+ INTN Result;
+ EFI_STATUS Status;
+
+ Result = 0;
+ ZeroMem (&Data1, sizeof (EFI_HII_VALUE));
+ ZeroMem (&Data2, sizeof (EFI_HII_VALUE));
+
+ Status = HiiStatementValueToHiiValue (OptionValue, &Data1);
+ ASSERT_EFI_ERROR (Status);
+
+ Link = GetFirstNode (&Question->OptionListHead);
+ while (!IsNull (&Question->OptionListHead, Link)) {
+ Option = HII_QUESTION_OPTION_FROM_LINK (Link);
+
+ Status = HiiStatementValueToHiiValue (&Option->Value, &Data2);
+ ASSERT_EFI_ERROR (Status);
+
+ if ((CompareHiiValue (&Data1, &Data2, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {
+ //
+ // Check the suppressif condition, only a valid option can be return.
+ //
+ if ((Option->SuppressExpression == NULL) ||
+ ((EvaluateExpressionList (Option->SuppressExpression, FALSE, NULL, NULL) == ExpressFalse)))
+ {
+ return Option;
+ }
+ }
+
+ Link = GetNextNode (&Question->OptionListHead, Link);
+ }
+
+ return NULL;
+}
+
+/**
+ Find the point in the ConfigResp string for this question.
+
+ @param[in] Question The question.
+ @param[in] ConfigResp Get ConfigResp string.
+
+ @retval point to the offset where is for this question.
+
+**/
+CHAR16 *
+GetOffsetFromConfigResp (
+ IN HII_STATEMENT *Question,
+ IN CHAR16 *ConfigResp
+ )
+{
+ CHAR16 *RequestElement;
+ CHAR16 *BlockData;
+
+ //
+ // Type is EFI_HII_VARSTORE_NAME_VALUE.
+ //
+ if (Question->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
+ RequestElement = StrStr (ConfigResp, Question->VariableName);
+ if (RequestElement != NULL) {
+ //
+ // Skip the "VariableName=" field.
+ //
+ RequestElement += StrLen (Question->VariableName) + 1;
+ }
+
+ return RequestElement;
+ }
+
+ //
+ // Type is EFI_HII_VARSTORE_EFI_VARIABLE or EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
+ //
+
+ //
+ // Convert all hex digits in ConfigResp to lower case before searching.
+ //
+ HiiStringToLowercase (ConfigResp);
+
+ //
+ // 1. Directly use Question->BlockName to find.
+ //
+ RequestElement = StrStr (ConfigResp, Question->BlockName);
+ if (RequestElement != NULL) {
+ //
+ // Skip the "Question->BlockName&VALUE=" field.
+ //
+ RequestElement += StrLen (Question->BlockName) + StrLen (L"&VALUE=");
+ return RequestElement;
+ }
+
+ //
+ // 2. Change all hex digits in Question->BlockName to lower and compare again.
+ //
+ BlockData = AllocateCopyPool (StrSize (Question->BlockName), Question->BlockName);
+ ASSERT (BlockData != NULL);
+ HiiStringToLowercase (BlockData);
+ RequestElement = StrStr (ConfigResp, BlockData);
+ FreePool (BlockData);
+
+ if (RequestElement != NULL) {
+ //
+ // Skip the "Question->BlockName&VALUE=" field.
+ //
+ RequestElement += StrLen (Question->BlockName) + StrLen (L"&VALUE=");
+ }
+
+ return RequestElement;
+}
+
+/**
+ Get Question default value from AltCfg string.
+
+ @param[in] FormSet The form set.
+ @param[in] Form The form
+ @param[in] Question The question.
+ @param[out] DefaultValue Default value.
+
+ @retval EFI_SUCCESS Question is reset to default value.
+
+**/
+EFI_STATUS
+GetDefaultValueFromAltCfg (
+ IN HII_FORMSET *FormSet,
+ IN HII_FORM *Form,
+ IN HII_STATEMENT *Question,
+ OUT HII_STATEMENT_VALUE *DefaultValue
+ )
+{
+ HII_FORMSET_STORAGE *Storage;
+ CHAR16 *ConfigResp;
+ CHAR16 *Value;
+ LIST_ENTRY *Link;
+ HII_FORM_CONFIG_REQUEST *ConfigInfo;
+
+ Storage = Question->Storage;
+ if ((Storage == NULL) || (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Try to get AltCfg string from form. If not found it, then
+ // try to get it from formset.
+ //
+ ConfigResp = NULL;
+ Link = GetFirstNode (&Form->ConfigRequestHead);
+ while (!IsNull (&Form->ConfigRequestHead, Link)) {
+ ConfigInfo = HII_FORM_CONFIG_REQUEST_FROM_LINK (Link);
+ Link = GetNextNode (&Form->ConfigRequestHead, Link);
+
+ if (Storage == ConfigInfo->Storage) {
+ ConfigResp = ConfigInfo->ConfigAltResp;
+ break;
+ }
+ }
+
+ if (ConfigResp == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ Value = GetOffsetFromConfigResp (Question, ConfigResp);
+ if (Value == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ return BufferToQuestionValue (Question, Value, DefaultValue);
+}
+
+/**
+ Get default Id value used for browser.
+
+ @param[in] DefaultId The default id value used by hii.
+
+ @retval Browser used default value.
+
+**/
+INTN
+GetDefaultIdForCallBack (
+ IN UINTN DefaultId
+ )
+{
+ if (DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) {
+ return EFI_BROWSER_ACTION_DEFAULT_STANDARD;
+ } else if (DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
+ return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING;
+ } else if (DefaultId == EFI_HII_DEFAULT_CLASS_SAFE) {
+ return EFI_BROWSER_ACTION_DEFAULT_SAFE;
+ } else if ((DefaultId >= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN) && (DefaultId < EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN + 0x1000)) {
+ return EFI_BROWSER_ACTION_DEFAULT_PLATFORM + DefaultId - EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN;
+ } else if ((DefaultId >= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN) && (DefaultId < EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN + 0x1000)) {
+ return EFI_BROWSER_ACTION_DEFAULT_HARDWARE + DefaultId - EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN;
+ } else if ((DefaultId >= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN) && (DefaultId < EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN + 0x1000)) {
+ return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE + DefaultId - EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN;
+ } else {
+ return -1;
+ }
+}
+
+/**
+ Get default value of question.
+
+ @param[in] FormSet The form set.
+ @param[in] Form The form.
+ @param[in] Question The question.
+ @param[in] DefaultId The Class of the default.
+ @param[out] DefaultValue The default value of given question.
+
+ @retval EFI_SUCCESS Question is reset to default value.
+
+**/
+EFI_STATUS
+GetQuestionDefault (
+ IN HII_FORMSET *FormSet,
+ IN HII_FORM *Form,
+ IN HII_STATEMENT *Question,
+ IN UINT16 DefaultId,
+ OUT HII_STATEMENT_VALUE *DefaultValue
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ HII_QUESTION_DEFAULT *Default;
+ HII_QUESTION_OPTION *Option;
+ HII_STATEMENT_VALUE *HiiValue;
+ UINT8 Index;
+ EFI_STRING StrValue;
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;
+ INTN Action;
+ EFI_IFR_TYPE_VALUE *TypeValue;
+ UINT16 OriginalDefaultId;
+ HII_FORMSET_DEFAULTSTORE *DefaultStore;
+ LIST_ENTRY *DefaultLink;
+
+ if ((FormSet == NULL) || (Form == NULL) || (Question == NULL) || (DefaultValue == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_NOT_FOUND;
+ StrValue = NULL;
+ OriginalDefaultId = DefaultId;
+ DefaultLink = GetFirstNode (&FormSet->DefaultStoreListHead);
+
+ //
+ // Statement don't have storage, skip them
+ //
+ if (Question->QuestionId == 0) {
+ DEBUG ((DEBUG_ERROR, "%a: Question has no storage, skip it\n", __func__));
+ return Status;
+ }
+
+ //
+ // There are Five ways to specify default value for a Question:
+ // 1, use call back function (highest priority)
+ // 2, use ExtractConfig function
+ // 3, use nested EFI_IFR_DEFAULT
+ // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
+ // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
+ //
+ CopyMem (DefaultValue, &Question->Value, sizeof (HII_STATEMENT_VALUE));
+ReGetDefault:
+ HiiValue = DefaultValue;
+ TypeValue = &HiiValue->Value;
+ if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {
+ //
+ // For orderedlist, need to pass the BufferValue to Callback function.
+ //
+ DefaultValue->BufferLen = Question->Value.BufferLen;
+ DefaultValue->Buffer = AllocateZeroPool (DefaultValue->BufferLen);
+ ASSERT (DefaultValue->Buffer != NULL);
+ if (DefaultValue->Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ TypeValue = (EFI_IFR_TYPE_VALUE *)DefaultValue->Buffer;
+ }
+
+ //
+ // Get Question default value from call back function.
+ // The string type of question cause HII driver to set string to its default value.
+ // So, we don't do this otherwise it will actually set question to default value.
+ // We only want to get default value of question.
+ //
+ if (HiiValue->Type != EFI_IFR_TYPE_STRING) {
+ ConfigAccess = FormSet->ConfigAccess;
+ Action = GetDefaultIdForCallBack (DefaultId);
+ if ((Action > 0) && ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) && (ConfigAccess != NULL)) {
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
+ Status = ConfigAccess->Callback (
+ ConfigAccess,
+ Action,
+ Question->QuestionId,
+ HiiValue->Type,
+ TypeValue,
+ &ActionRequest
+ );
+ if (!EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ }
+
+ //
+ // Get default value from altcfg string.
+ //
+ if (ConfigAccess != NULL) {
+ Status = GetDefaultValueFromAltCfg (FormSet, Form, Question, DefaultValue);
+ if (!EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // EFI_IFR_DEFAULT has highest priority
+ //
+ if (!IsListEmpty (&Question->DefaultListHead)) {
+ Link = GetFirstNode (&Question->DefaultListHead);
+ while (!IsNull (&Question->DefaultListHead, Link)) {
+ Default = HII_QUESTION_DEFAULT_FROM_LINK (Link);
+
+ if (Default->DefaultId == DefaultId) {
+ if (Default->ValueExpression != NULL) {
+ //
+ // Default is provided by an Expression, evaluate it
+ //
+ Status = EvaluateHiiExpression (FormSet, Form, Default->ValueExpression);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (Default->ValueExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {
+ ASSERT (HiiValue->Type == EFI_IFR_TYPE_BUFFER && DefaultValue->Buffer != NULL);
+ if (DefaultValue->BufferLen > Default->ValueExpression->Result.BufferLen) {
+ CopyMem (DefaultValue->Buffer, Default->ValueExpression->Result.Buffer, Default->ValueExpression->Result.BufferLen);
+ DefaultValue->BufferLen = Default->ValueExpression->Result.BufferLen;
+ } else {
+ CopyMem (DefaultValue->Buffer, Default->ValueExpression->Result.Buffer, DefaultValue->BufferLen);
+ }
+
+ FreePool (Default->ValueExpression->Result.Buffer);
+ }
+
+ HiiValue->Type = Default->ValueExpression->Result.Type;
+ CopyMem (&HiiValue->Value, &Default->ValueExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE));
+ } else {
+ //
+ // Default value is embedded in EFI_IFR_DEFAULT
+ //
+ if (Default->Value.Type == EFI_IFR_TYPE_BUFFER) {
+ ASSERT (HiiValue->Buffer != NULL);
+ CopyMem (HiiValue->Buffer, Default->Value.Buffer, Default->Value.BufferLen);
+ } else {
+ CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));
+ }
+ }
+
+ if (HiiValue->Type == EFI_IFR_TYPE_STRING) {
+ StrValue = HiiGetString (FormSet->HiiHandle, HiiValue->Value.string, NULL);
+ if (StrValue == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (DefaultValue->BufferLen > StrSize (StrValue)) {
+ ZeroMem (DefaultValue->Buffer, DefaultValue->BufferLen);
+ CopyMem (DefaultValue->Buffer, StrValue, StrSize (StrValue));
+ } else {
+ CopyMem (DefaultValue->Buffer, StrValue, DefaultValue->BufferLen);
+ }
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ Link = GetNextNode (&Question->DefaultListHead, Link);
+ }
+ }
+
+ //
+ // EFI_ONE_OF_OPTION
+ //
+ if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {
+ if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
+ //
+ // OneOfOption could only provide Standard and Manufacturing default
+ //
+ Link = GetFirstNode (&Question->OptionListHead);
+ while (!IsNull (&Question->OptionListHead, Link)) {
+ Option = HII_QUESTION_OPTION_FROM_LINK (Link);
+ Link = GetNextNode (&Question->OptionListHead, Link);
+
+ if ((Option->SuppressExpression != NULL) &&
+ (EvaluateExpressionList (Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse))
+ {
+ continue;
+ }
+
+ if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||
+ ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))
+ )
+ {
+ CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));
+
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ }
+
+ //
+ // EFI_IFR_CHECKBOX - lowest priority
+ //
+ if (Question->Operand == EFI_IFR_CHECKBOX_OP) {
+ if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
+ //
+ // Checkbox could only provide Standard and Manufacturing default
+ //
+ if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Question->ExtraData.Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0)) ||
+ ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Question->ExtraData.Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0))
+ )
+ {
+ HiiValue->Value.b = TRUE;
+ }
+
+ return EFI_SUCCESS;
+ }
+ }
+
+ //
+ // For question without default value for current default Id, we try to re-get the default value form other default id in the DefaultStoreList.
+ // If get, will exit the function, if not, will choose next default id in the DefaultStoreList.
+ // The default id in DefaultStoreList are in ascending order to make sure choose the smallest default id every time.
+ //
+ while (!IsNull (&FormSet->DefaultStoreListHead, DefaultLink)) {
+ DefaultStore = HII_FORMSET_DEFAULTSTORE_FROM_LINK (DefaultLink);
+ DefaultLink = GetNextNode (&FormSet->DefaultStoreListHead, DefaultLink);
+ DefaultId = DefaultStore->DefaultId;
+ if (DefaultId == OriginalDefaultId) {
+ continue;
+ }
+
+ goto ReGetDefault;
+ }
+
+ //
+ // For Questions without default value for all the default id in the DefaultStoreList.
+ //
+ Status = EFI_NOT_FOUND;
+ switch (Question->Operand) {
+ case EFI_IFR_CHECKBOX_OP:
+ HiiValue->Value.b = FALSE;
+ Status = EFI_SUCCESS;
+ break;
+
+ case EFI_IFR_NUMERIC_OP:
+ //
+ // Take minimum value as numeric default value
+ //
+ if ((Question->ExtraData.NumData.Flags & EFI_IFR_DISPLAY) == 0) {
+ //
+ // In EFI_IFR_DISPLAY_INT_DEC type, should check value with int* type.
+ //
+ switch (Question->ExtraData.NumData.Flags & EFI_IFR_NUMERIC_SIZE) {
+ case EFI_IFR_NUMERIC_SIZE_1:
+ if (((INT8)HiiValue->Value.u8 < (INT8)Question->ExtraData.NumData.Minimum) || ((INT8)HiiValue->Value.u8 > (INT8)Question->ExtraData.NumData.Maximum)) {
+ HiiValue->Value.u8 = (UINT8)Question->ExtraData.NumData.Minimum;
+ Status = EFI_SUCCESS;
+ }
+
+ break;
+ case EFI_IFR_NUMERIC_SIZE_2:
+ if (((INT16)HiiValue->Value.u16 < (INT16)Question->ExtraData.NumData.Minimum) || ((INT16)HiiValue->Value.u16 > (INT16)Question->ExtraData.NumData.Maximum)) {
+ HiiValue->Value.u16 = (UINT16)Question->ExtraData.NumData.Minimum;
+ Status = EFI_SUCCESS;
+ }
+
+ break;
+ case EFI_IFR_NUMERIC_SIZE_4:
+ if (((INT32)HiiValue->Value.u32 < (INT32)Question->ExtraData.NumData.Minimum) || ((INT32)HiiValue->Value.u32 > (INT32)Question->ExtraData.NumData.Maximum)) {
+ HiiValue->Value.u32 = (UINT32)Question->ExtraData.NumData.Minimum;
+ Status = EFI_SUCCESS;
+ }
+
+ break;
+ case EFI_IFR_NUMERIC_SIZE_8:
+ if (((INT64)HiiValue->Value.u64 < (INT64)Question->ExtraData.NumData.Minimum) || ((INT64)HiiValue->Value.u64 > (INT64)Question->ExtraData.NumData.Maximum)) {
+ HiiValue->Value.u64 = Question->ExtraData.NumData.Minimum;
+ Status = EFI_SUCCESS;
+ }
+
+ break;
+ default:
+ break;
+ }
+ } else {
+ if ((HiiValue->Value.u64 < Question->ExtraData.NumData.Minimum) || (HiiValue->Value.u64 > Question->ExtraData.NumData.Maximum)) {
+ HiiValue->Value.u64 = Question->ExtraData.NumData.Minimum;
+ Status = EFI_SUCCESS;
+ }
+ }
+
+ break;
+
+ case EFI_IFR_ONE_OF_OP:
+ //
+ // Take first oneof option as oneof's default value
+ //
+ Link = GetFirstNode (&Question->OptionListHead);
+ while (!IsNull (&Question->OptionListHead, Link)) {
+ Option = HII_QUESTION_OPTION_FROM_LINK (Link);
+ Link = GetNextNode (&Question->OptionListHead, Link);
+
+ if ((Option->SuppressExpression != NULL) &&
+ (EvaluateExpressionList (Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse))
+ {
+ continue;
+ }
+
+ CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));
+ Status = EFI_SUCCESS;
+ break;
+ }
+
+ break;
+
+ case EFI_IFR_ORDERED_LIST_OP:
+ //
+ // Take option sequence in IFR as ordered list's default value
+ //
+ Index = 0;
+ Link = GetFirstNode (&Question->OptionListHead);
+ while (!IsNull (&Question->OptionListHead, Link)) {
+ Status = EFI_SUCCESS;
+ Option = HII_QUESTION_OPTION_FROM_LINK (Link);
+ Link = GetNextNode (&Question->OptionListHead, Link);
+
+ if ((Option->SuppressExpression != NULL) &&
+ (EvaluateExpressionList (Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse))
+ {
+ continue;
+ }
+
+ SetArrayData (DefaultValue->Buffer, Question->Value.Type, Index, Option->Value.Value.u64);
+
+ Index++;
+ if (Index >= Question->ExtraData.OrderListData.MaxContainers) {
+ break;
+ }
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ return Status;
+}
diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.c b/RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.c
new file mode 100644
index 000000000000..168b4459844f
--- /dev/null
+++ b/RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.c
@@ -0,0 +1,810 @@
+/** @file
+ Implementation of HII utility library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+ Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "HiiInternal.h"
+
+/**
+ Initialize the internal data structure of a FormSet.
+
+ @param Handle PackageList Handle
+ @param FormSetGuid On input, GUID or class GUID of a formset. If not
+ specified (NULL or zero GUID), take the first
+ FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
+ found in package list.
+ On output, GUID of the formset found(if not NULL).
+ @param FormSet FormSet data structure.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_NOT_FOUND The specified FormSet could not be found.
+
+**/
+EFI_STATUS
+CreateFormSetFromHiiHandle (
+ IN EFI_HII_HANDLE Handle,
+ IN OUT EFI_GUID *FormSetGuid,
+ OUT HII_FORMSET *FormSet
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE DriverHandle;
+ EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
+
+ if ((FormSetGuid == NULL) || (FormSet == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Locate required Hii Database protocol
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiHiiDatabaseProtocolGuid,
+ NULL,
+ (VOID **)&HiiDatabase
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ FormSet->Signature = HII_FORMSET_SIGNATURE;
+ FormSet->HiiHandle = Handle;
+ CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));
+ //
+ // Retrieve ConfigAccess Protocol associated with this HiiPackageList
+ //
+ Status = HiiDatabase->GetPackageListHandle (HiiDatabase, Handle, &DriverHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ FormSet->DriverHandle = DriverHandle;
+ Status = gBS->HandleProtocol (
+ DriverHandle,
+ &gEfiHiiConfigAccessProtocolGuid,
+ (VOID **)&FormSet->ConfigAccess
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // Configuration Driver don't attach ConfigAccess protocol to its HII package
+ // list, then there will be no configuration action required
+ //
+ FormSet->ConfigAccess = NULL;
+ }
+
+ Status = gBS->HandleProtocol (
+ DriverHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **)&FormSet->DevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // Configuration Driver don't attach ConfigAccess protocol to its HII package
+ // list, then there will be no configuration action required
+ //
+ FormSet->DevicePath = NULL;
+ }
+
+ //
+ // Parse the IFR binary OpCodes
+ //
+ Status = ParseOpCodes (FormSet);
+
+ return Status;
+}
+
+/**
+ Initialize a Formset and get current setting for Questions.
+
+ @param FormSet FormSet data structure.
+
+**/
+VOID
+InitializeFormSet (
+ IN OUT HII_FORMSET *FormSet
+ )
+{
+ LIST_ENTRY *Link;
+ HII_FORMSET_STORAGE *Storage;
+ LIST_ENTRY *FormLink;
+ HII_STATEMENT *Question;
+ HII_FORM *Form;
+
+ if (FormSet == NULL) {
+ return;
+ }
+
+ //
+ // Load Storage for all questions with storage
+ //
+ Link = GetFirstNode (&FormSet->StorageListHead);
+ while (!IsNull (&FormSet->StorageListHead, Link)) {
+ Storage = HII_STORAGE_FROM_LINK (Link);
+ LoadFormSetStorage (FormSet, Storage);
+ Link = GetNextNode (&FormSet->StorageListHead, Link);
+ }
+
+ //
+ // Get Current Value for all no storage questions
+ //
+ FormLink = GetFirstNode (&FormSet->FormListHead);
+ while (!IsNull (&FormSet->FormListHead, FormLink)) {
+ Form = HII_FORM_FROM_LINK (FormLink);
+ Link = GetFirstNode (&Form->StatementListHead);
+ while (!IsNull (&Form->StatementListHead, Link)) {
+ Question = HII_STATEMENT_FROM_LINK (Link);
+ if (Question->Storage == NULL) {
+ RetrieveQuestion (FormSet, Form, Question);
+ }
+
+ Link = GetNextNode (&Form->StatementListHead, Link);
+ }
+
+ FormLink = GetNextNode (&FormSet->FormListHead, FormLink);
+ }
+}
+
+/**
+ Free resources allocated for a FormSet.
+
+ @param[in,out] FormSet Pointer of the FormSet
+
+**/
+VOID
+DestroyFormSet (
+ IN OUT HII_FORMSET *FormSet
+ )
+{
+ LIST_ENTRY *Link;
+ HII_FORMSET_STORAGE *Storage;
+ HII_FORMSET_DEFAULTSTORE *DefaultStore;
+ HII_FORM *Form;
+
+ if (FormSet->IfrBinaryData == NULL) {
+ //
+ // Uninitialized FormSet
+ //
+ FreePool (FormSet);
+ return;
+ }
+
+ //
+ // Free IFR binary buffer
+ //
+ FreePool (FormSet->IfrBinaryData);
+
+ //
+ // Free FormSet Storage
+ //
+ if (FormSet->StorageListHead.ForwardLink != NULL) {
+ while (!IsListEmpty (&FormSet->StorageListHead)) {
+ Link = GetFirstNode (&FormSet->StorageListHead);
+ Storage = HII_STORAGE_FROM_LINK (Link);
+ RemoveEntryList (&Storage->Link);
+
+ if (Storage != NULL) {
+ FreePool (Storage);
+ }
+ }
+ }
+
+ //
+ // Free FormSet Default Store
+ //
+ if (FormSet->DefaultStoreListHead.ForwardLink != NULL) {
+ while (!IsListEmpty (&FormSet->DefaultStoreListHead)) {
+ Link = GetFirstNode (&FormSet->DefaultStoreListHead);
+ DefaultStore = HII_FORMSET_DEFAULTSTORE_FROM_LINK (Link);
+ RemoveEntryList (&DefaultStore->Link);
+
+ FreePool (DefaultStore);
+ }
+ }
+
+ //
+ // Free Forms
+ //
+ if (FormSet->FormListHead.ForwardLink != NULL) {
+ while (!IsListEmpty (&FormSet->FormListHead)) {
+ Link = GetFirstNode (&FormSet->FormListHead);
+ Form = HII_FORM_FROM_LINK (Link);
+ RemoveEntryList (&Form->Link);
+
+ DestroyForm (FormSet, Form);
+ }
+ }
+
+ FreePool (FormSet);
+}
+
+/**
+ Submit data for a form.
+
+ @param[in] FormSet FormSet which contains the Form.
+ @param[in] Form Form to submit.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval Others Other errors occur.
+
+**/
+EFI_STATUS
+SubmitForm (
+ IN HII_FORMSET *FormSet,
+ IN HII_FORM *Form
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+ LIST_ENTRY *Link;
+ EFI_STRING ConfigResp;
+ EFI_STRING Progress;
+ HII_FORMSET_STORAGE *Storage;
+ HII_FORM_CONFIG_REQUEST *ConfigInfo;
+
+ if ((FormSet == NULL) || (Form == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = NoSubmitCheck (FormSet, &Form, NULL);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Link = GetFirstNode (&Form->ConfigRequestHead);
+ while (!IsNull (&Form->ConfigRequestHead, Link)) {
+ ConfigInfo = HII_FORM_CONFIG_REQUEST_FROM_LINK (Link);
+ Link = GetNextNode (&Form->ConfigRequestHead, Link);
+
+ Storage = ConfigInfo->Storage;
+ if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
+ continue;
+ }
+
+ //
+ // Skip if there is no RequestElement
+ //
+ if (ConfigInfo->ElementCount == 0) {
+ continue;
+ }
+
+ Status = StorageToConfigResp (ConfigInfo->Storage, &ConfigResp, ConfigInfo->ConfigRequest);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->LocateProtocol (
+ &gEfiHiiConfigRoutingProtocolGuid,
+ NULL,
+ (VOID **)&HiiConfigRouting
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = HiiConfigRouting->RouteConfig (
+ HiiConfigRouting,
+ ConfigResp,
+ &Progress
+ );
+
+ if (EFI_ERROR (Status)) {
+ FreePool (ConfigResp);
+ continue;
+ }
+
+ FreePool (ConfigResp);
+ }
+
+ return Status;
+}
+
+/**
+ Save Question Value to the memory, but not to storage.
+
+ @param[in] FormSet FormSet data structure.
+ @param[in] Form Form data structure.
+ @param[in,out] Question Pointer to the Question.
+ @param[in] QuestionValue New Question Value to be set.
+
+ @retval EFI_SUCCESS The question value has been set successfully.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+EFI_STATUS
+SetQuestionValue (
+ IN HII_FORMSET *FormSet,
+ IN HII_FORM *Form,
+ IN OUT HII_STATEMENT *Question,
+ IN HII_STATEMENT_VALUE *QuestionValue
+ )
+{
+ UINT8 *Src;
+ UINTN BufferLen;
+ UINTN StorageWidth;
+ HII_FORMSET_STORAGE *Storage;
+ CHAR16 *ValueStr;
+ BOOLEAN IsBufferStorage;
+ UINT8 *TemBuffer;
+ CHAR16 *TemName;
+ CHAR16 *TemString;
+ UINTN Index;
+ HII_NAME_VALUE_NODE *Node;
+ EFI_STATUS Status;
+
+ if ((FormSet == NULL) || (Form == NULL) || (Question == NULL) || (QuestionValue == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+ Node = NULL;
+
+ //
+ // If Question value is provided by an Expression, then it is read only
+ //
+ if ((Question->ValueExpression != NULL) || (Question->Value.Type != QuestionValue->Type)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Before set question value, evaluate its write expression.
+ //
+ if ((Question->WriteExpression != NULL) && (Form->FormType == STANDARD_MAP_FORM_TYPE)) {
+ Status = EvaluateHiiExpression (FormSet, Form, Question->WriteExpression);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ Storage = Question->Storage;
+ if (Storage != NULL) {
+ StorageWidth = Question->StorageWidth;
+ if (Question->Value.Type == EFI_IFR_TYPE_BUFFER) {
+ Question->Value.BufferLen = QuestionValue->BufferLen;
+ Question->Value.Buffer = AllocateCopyPool (QuestionValue->BufferLen, QuestionValue->Buffer);
+ if (Question->Value.Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Question->Value.BufferValueType = QuestionValue->BufferValueType;
+ Src = Question->Value.Buffer;
+ } else if (Question->Value.Type == EFI_IFR_TYPE_STRING) {
+ Question->Value.Value.string = QuestionValue->Value.string;
+ TemString = HiiGetString (FormSet->HiiHandle, QuestionValue->Value.string, NULL);
+ if (TemString == NULL) {
+ return EFI_ABORTED;
+ }
+
+ Question->Value.BufferLen = Question->StorageWidth;
+ Question->Value.Buffer = AllocateZeroPool (Question->StorageWidth);
+ if (Question->Value.Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CopyMem (Question->Value.Buffer, TemString, StrSize (TemString));
+ Src = Question->Value.Buffer;
+ } else {
+ CopyMem (&Question->Value.Value, &QuestionValue->Value, sizeof (EFI_IFR_TYPE_VALUE));
+ Src = (UINT8 *)&Question->Value.Value;
+ }
+
+ if ((Storage->Type == EFI_HII_VARSTORE_BUFFER) || (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {
+ IsBufferStorage = TRUE;
+ } else {
+ IsBufferStorage = FALSE;
+ }
+
+ if (IsBufferStorage) {
+ //
+ // If the Question refer to bit filed, copy the value in related bit filed to storage edit buffer.
+ //
+ if (Question->QuestionReferToBitField) {
+ SetBitsQuestionValue (Question, Storage->Buffer + Question->VarStoreInfo.VarOffset, (UINT32)(*Src));
+ } else {
+ CopyMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);
+ }
+ } else {
+ if (Question->Value.Type == EFI_IFR_TYPE_STRING) {
+ //
+ // Allocate enough string buffer.
+ //
+ ValueStr = NULL;
+ BufferLen = ((StrLen ((CHAR16 *)Src) * 4) + 1) * sizeof (CHAR16);
+ ValueStr = AllocatePool (BufferLen);
+ if (ValueStr == NULL) {
+ if (Question->Value.Buffer != NULL) {
+ FreePool (Question->Value.Buffer);
+ }
+
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
+ //
+ TemName = (CHAR16 *)Src;
+ TemString = ValueStr;
+ for ( ; *TemName != L'\0'; TemName++) {
+ UnicodeValueToStringS (
+ TemString,
+ BufferLen - ((UINTN)TemString - (UINTN)ValueStr),
+ PREFIX_ZERO | RADIX_HEX,
+ *TemName,
+ 4
+ );
+ TemString += StrnLenS (TemString, (BufferLen - ((UINTN)TemString - (UINTN)ValueStr)) / sizeof (CHAR16));
+ }
+ } else {
+ BufferLen = StorageWidth * 2 + 1;
+ ValueStr = AllocateZeroPool (BufferLen * sizeof (CHAR16));
+ if (ValueStr == NULL) {
+ if (Question->Value.Buffer != NULL) {
+ FreePool (Question->Value.Buffer);
+ }
+
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Convert Buffer to Hex String
+ //
+ TemBuffer = Src + StorageWidth - 1;
+ TemString = ValueStr;
+ for (Index = 0; Index < StorageWidth; Index++, TemBuffer--) {
+ UnicodeValueToStringS (
+ TemString,
+ BufferLen * sizeof (CHAR16) - ((UINTN)TemString - (UINTN)ValueStr),
+ PREFIX_ZERO | RADIX_HEX,
+ *TemBuffer,
+ 2
+ );
+ TemString += StrnLenS (TemString, BufferLen - ((UINTN)TemString - (UINTN)ValueStr) / sizeof (CHAR16));
+ }
+ }
+
+ Status = SetValueByName (Storage, Question->VariableName, ValueStr, &Node);
+ FreePool (ValueStr);
+ if (EFI_ERROR (Status)) {
+ if (Question->Value.Buffer != NULL) {
+ FreePool (Question->Value.Buffer);
+ }
+
+ return Status;
+ }
+ }
+ } else {
+ if (Question->Value.Type == EFI_IFR_TYPE_BUFFER) {
+ Question->Value.BufferLen = QuestionValue->BufferLen;
+ Question->Value.Buffer = AllocateCopyPool (QuestionValue->BufferLen, QuestionValue->Buffer);
+ if (Question->Value.Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Question->Value.BufferValueType = QuestionValue->BufferValueType;
+ } else if (Question->Value.Type == EFI_IFR_TYPE_STRING) {
+ Question->Value.Value.string = QuestionValue->Value.string;
+ TemString = HiiGetString (FormSet->HiiHandle, QuestionValue->Value.string, NULL);
+ if (TemString == NULL) {
+ return EFI_ABORTED;
+ }
+
+ Question->Value.BufferLen = (UINT16)StrSize (TemString);
+ Question->Value.Buffer = AllocateZeroPool (QuestionValue->BufferLen);
+ if (Question->Value.Buffer == NULL) {
+ FreePool (TemString);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CopyMem (Question->Value.Buffer, TemString, StrSize (TemString));
+ FreePool (TemString);
+ } else {
+ CopyMem (&Question->Value.Value, &QuestionValue->Value, sizeof (EFI_IFR_TYPE_VALUE));
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Get Question's current Value from storage.
+
+ @param[in] FormSet FormSet data structure.
+ @param[in] Form Form data structure.
+ @param[in,out] Question Question to be initialized.
+
+ @return the current Question Value in storage if success.
+ @return NULL if Question is not found or any error occurs.
+
+**/
+HII_STATEMENT_VALUE *
+RetrieveQuestion (
+ IN HII_FORMSET *FormSet,
+ IN HII_FORM *Form,
+ IN OUT HII_STATEMENT *Question
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;
+ HII_FORMSET_STORAGE *Storage;
+ HII_STATEMENT_VALUE *QuestionValue;
+ EFI_IFR_TYPE_VALUE *TypeValue;
+ EFI_TIME EfiTime;
+ BOOLEAN Enabled;
+ BOOLEAN Pending;
+ UINT8 *Dst;
+ UINTN StorageWidth;
+ CHAR16 *ConfigRequest;
+ CHAR16 *Progress;
+ CHAR16 *Result;
+ CHAR16 *ValueStr;
+ UINTN Length;
+ BOOLEAN IsBufferStorage;
+ CHAR16 *NewHiiString;
+
+ if ((FormSet == NULL) || (Form == NULL) || (Question == NULL)) {
+ return NULL;
+ }
+
+ Status = EFI_SUCCESS;
+ ValueStr = NULL;
+ Result = NULL;
+
+ QuestionValue = AllocateZeroPool (sizeof (HII_STATEMENT_VALUE));
+ if (QuestionValue == NULL) {
+ return NULL;
+ }
+
+ QuestionValue->Type = Question->Value.Type;
+ QuestionValue->BufferLen = Question->Value.BufferLen;
+ if (QuestionValue->BufferLen != 0) {
+ QuestionValue->Buffer = AllocateZeroPool (QuestionValue->BufferLen);
+ if (QuestionValue->Buffer == NULL) {
+ FreePool (QuestionValue);
+ return NULL;
+ }
+ }
+
+ //
+ // Question value is provided by RTC
+ //
+ Storage = Question->Storage;
+ StorageWidth = Question->StorageWidth;
+
+ if (Storage == NULL) {
+ //
+ // It's a Question without storage, or RTC date/time
+ //
+ if ((Question->Operand == EFI_IFR_DATE_OP) || (Question->Operand == EFI_IFR_TIME_OP)) {
+ //
+ // Date and time define the same Flags bit
+ //
+ switch (Question->ExtraData.Flags & EFI_QF_DATE_STORAGE) {
+ case QF_DATE_STORAGE_TIME:
+
+ Status = gRT->GetTime (&EfiTime, NULL);
+ break;
+
+ case QF_DATE_STORAGE_WAKEUP:
+
+ Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);
+ break;
+
+ case QF_DATE_STORAGE_NORMAL:
+ default:
+
+ goto ON_ERROR;
+ }
+
+ if (EFI_ERROR (Status)) {
+ if (Question->Operand == EFI_IFR_DATE_OP) {
+ QuestionValue->Value.date.Year = 0xff;
+ QuestionValue->Value.date.Month = 0xff;
+ QuestionValue->Value.date.Day = 0xff;
+ } else {
+ QuestionValue->Value.time.Hour = 0xff;
+ QuestionValue->Value.time.Minute = 0xff;
+ QuestionValue->Value.time.Second = 0xff;
+ }
+
+ return QuestionValue;
+ }
+
+ if (Question->Operand == EFI_IFR_DATE_OP) {
+ QuestionValue->Value.date.Year = EfiTime.Year;
+ QuestionValue->Value.date.Month = EfiTime.Month;
+ QuestionValue->Value.date.Day = EfiTime.Day;
+ } else {
+ QuestionValue->Value.time.Hour = EfiTime.Hour;
+ QuestionValue->Value.time.Minute = EfiTime.Minute;
+ QuestionValue->Value.time.Second = EfiTime.Second;
+ }
+ } else {
+ if (((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) ||
+ (FormSet->ConfigAccess == NULL))
+ {
+ goto ON_ERROR;
+ }
+
+ if (QuestionValue->Type == EFI_IFR_TYPE_BUFFER) {
+ //
+ // For OrderedList, passing in the value buffer to Callback()
+ //
+ TypeValue = (EFI_IFR_TYPE_VALUE *)QuestionValue->Buffer;
+ } else {
+ TypeValue = &QuestionValue->Value;
+ }
+
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
+ Status = FormSet->ConfigAccess->Callback (
+ FormSet->ConfigAccess,
+ EFI_BROWSER_ACTION_RETRIEVE,
+ Question->QuestionId,
+ QuestionValue->Type,
+ TypeValue,
+ &ActionRequest
+ );
+
+ if (!EFI_ERROR (Status) && (QuestionValue->Type == EFI_IFR_TYPE_STRING)) {
+ if (TypeValue->string == 0) {
+ goto ON_ERROR;
+ }
+
+ NewHiiString = GetTokenString (TypeValue->string, FormSet->HiiHandle);
+ if (NewHiiString == NULL) {
+ goto ON_ERROR;
+ }
+
+ QuestionValue->Buffer = AllocatePool (StrSize (NewHiiString));
+ if (QuestionValue->Buffer == NULL) {
+ FreePool (NewHiiString);
+ goto ON_ERROR;
+ }
+
+ CopyMem (QuestionValue->Buffer, NewHiiString, StrSize (NewHiiString));
+ QuestionValue->BufferLen = (UINT16)StrSize (NewHiiString);
+
+ FreePool (NewHiiString);
+ }
+ }
+
+ return QuestionValue;
+ }
+
+ //
+ // Question value is provided by EFI variable
+ //
+ if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
+ if ((QuestionValue->Type != EFI_IFR_TYPE_BUFFER) && (QuestionValue->Type != EFI_IFR_TYPE_STRING)) {
+ Dst = QuestionValue->Buffer;
+ StorageWidth = QuestionValue->BufferLen;
+ } else {
+ Dst = (UINT8 *)&QuestionValue->Value;
+ StorageWidth = sizeof (EFI_IFR_TYPE_VALUE);
+ }
+
+ Status = gRT->GetVariable (
+ Question->VariableName,
+ &Storage->Guid,
+ NULL,
+ &StorageWidth,
+ Dst
+ );
+
+ return QuestionValue;
+ }
+
+ Status = gBS->LocateProtocol (
+ &gEfiHiiConfigRoutingProtocolGuid,
+ NULL,
+ (VOID **)&HiiConfigRouting
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ if (QuestionValue->BufferLen != 0) {
+ Dst = QuestionValue->Buffer;
+ } else {
+ Dst = (UINT8 *)&QuestionValue->Value;
+ }
+
+ if ((Storage->Type == EFI_HII_VARSTORE_BUFFER) || (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {
+ IsBufferStorage = TRUE;
+ } else {
+ IsBufferStorage = FALSE;
+ }
+
+ Storage = GetFstStgFromVarId (FormSet, Question->VarStoreId);
+ if (Storage == NULL) {
+ goto ON_ERROR;
+ }
+
+ //
+ // <ConfigRequest> ::= <ConfigHdr> + <BlockName> || <ConfigHdr> + "&" + <VariableName>
+ //
+ if (IsBufferStorage) {
+ Length = StrLen (Storage->ConfigHdr);
+ Length += StrLen (Question->BlockName);
+ } else {
+ Length = StrLen (Storage->ConfigHdr);
+ Length += StrLen (Question->VariableName) + 1;
+ }
+
+ ConfigRequest = AllocatePool ((Length + 1) * sizeof (CHAR16));
+ if (ConfigRequest == NULL) {
+ goto ON_ERROR;
+ }
+
+ StrCpyS (ConfigRequest, Length + 1, Storage->ConfigHdr);
+ if (IsBufferStorage) {
+ StrCatS (ConfigRequest, Length + 1, Question->BlockName);
+ } else {
+ StrCatS (ConfigRequest, Length + 1, L"&");
+ StrCatS (ConfigRequest, Length + 1, Question->VariableName);
+ }
+
+ //
+ // Request current settings from Configuration Driver
+ //
+ Status = HiiConfigRouting->ExtractConfig (
+ HiiConfigRouting,
+ ConfigRequest,
+ &Progress,
+ &Result
+ );
+ FreePool (ConfigRequest);
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ if (IsBufferStorage) {
+ ValueStr = StrStr (Result, L"&VALUE");
+ if (ValueStr == NULL) {
+ FreePool (Result);
+ goto ON_ERROR;
+ }
+
+ ValueStr = ValueStr + 6;
+ } else {
+ ValueStr = Result + Length;
+ }
+
+ if (*ValueStr != '=') {
+ FreePool (Result);
+ goto ON_ERROR;
+ }
+
+ ValueStr++;
+ Status = BufferToQuestionValue (Question, ValueStr, QuestionValue);
+ if (EFI_ERROR (Status)) {
+ FreePool (Result);
+ goto ON_ERROR;
+ }
+
+ if (Result != NULL) {
+ FreePool (Result);
+ }
+
+ return QuestionValue;
+
+ON_ERROR:
+
+ if (QuestionValue->Buffer != NULL) {
+ FreePool (QuestionValue->Buffer);
+ }
+
+ FreePool (QuestionValue);
+
+ return NULL;
+}
--
2.17.1
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH v3 2/5] RedfishPkg: introduce HII utility helper library
2023-04-19 9:09 [PATCH v3 2/5] RedfishPkg: introduce HII utility helper library Nickle Wang
@ 2023-04-19 9:48 ` Chang, Abner
0 siblings, 0 replies; 2+ messages in thread
From: Chang, Abner @ 2023-04-19 9:48 UTC (permalink / raw)
To: Nickle Wang, devel@edk2.groups.io; +Cc: Igor Kulchytskyy, Nick Ramirez
[AMD Official Use Only - General]
Reviewed-by: Abner Chang <abner.chang@amd.com>
> -----Original Message-----
> From: Nickle Wang <nicklew@nvidia.com>
> Sent: Wednesday, April 19, 2023 5:09 PM
> To: devel@edk2.groups.io
> Cc: Chang, Abner <Abner.Chang@amd.com>; Igor Kulchytskyy
> <igork@ami.com>; Nick Ramirez <nramirez@nvidia.com>
> Subject: [PATCH v3 2/5] RedfishPkg: introduce HII utility helper library
>
> Caution: This message originated from an External Source. Use proper
> caution when opening attachments, clicking links, or responding.
>
>
> HiiUtilityLib is a helper library that provides the
> functions to manipulate HII options.
>
> Signed-off-by: Nickle Wang <nicklew@nvidia.com>
> Cc: Abner Chang <abner.chang@amd.com>
> Cc: Igor Kulchytskyy <igork@ami.com>
> Cc: Nick Ramirez <nramirez@nvidia.com>
> ---
> RedfishPkg/RedfishPkg.dec | 4 +
> .../Library/HiiUtilityLib/HiiUtilityLib.inf | 62 +
> RedfishPkg/Include/Library/HiiUtilityLib.h | 1204 ++++
> .../Library/HiiUtilityLib/HiiExpression.h | 191 +
> .../Library/HiiUtilityLib/HiiInternal.h | 376 ++
> .../Library/HiiUtilityLib/HiiExpression.c | 1439 ++++
> .../Library/HiiUtilityLib/HiiIfrParse.c | 2715 ++++++++
> .../HiiUtilityLib/HiiUtilityInternal.c | 5770 +++++++++++++++++
> .../Library/HiiUtilityLib/HiiUtilityLib.c | 810 +++
> 9 files changed, 12571 insertions(+)
> create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.inf
> create mode 100644 RedfishPkg/Include/Library/HiiUtilityLib.h
> create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiExpression.h
> create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiInternal.h
> create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiExpression.c
> create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiIfrParse.c
> create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiUtilityInternal.c
> create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.c
>
> diff --git a/RedfishPkg/RedfishPkg.dec b/RedfishPkg/RedfishPkg.dec
> index 904630ae4be6..e2892ce9cec1 100644
> --- a/RedfishPkg/RedfishPkg.dec
> +++ b/RedfishPkg/RedfishPkg.dec
> @@ -60,6 +60,10 @@
> # Library provides Redfish debug functions.
> RedfishDebugLib|Include/Library/RedfishDebugLib.h
>
> + ## @libraryclass Provides the library functions to parse IFR binary data.
> + #
> + HiiUtilityLib|Include/Library/HiiUtilityLib.h
> +
> [LibraryClasses.Common.Private]
> ## @libraryclass Provides the private C runtime library functions.
> # CRT library is currently used by edk2 JsonLib (open source
> diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.inf
> b/RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.inf
> new file mode 100644
> index 000000000000..cab3f8a0ee68
> --- /dev/null
> +++ b/RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.inf
> @@ -0,0 +1,62 @@
> +## @file
> +# Library to handle HII IFR data.
> +#
> +# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> +# (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
> +# Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights
> reserved.
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> + INF_VERSION = 0x00010005
> + BASE_NAME = HiiUtilityLib
> + FILE_GUID = D00DA028-F19A-47AF-B22A-6EE9E8BD7335
> + MODULE_TYPE = UEFI_DRIVER
> + VERSION_STRING = 1.0
> + LIBRARY_CLASS = HiiUtilityLib|DXE_DRIVER UEFI_DRIVER
> UEFI_APPLICATION
> +
> +#
> +# VALID_ARCHITECTURES = IA32 X64 EBC
> +#
> +
> +[Sources]
> + HiiUtilityLib.c
> + HiiExpression.c
> + HiiUtilityInternal.c
> + HiiIfrParse.c
> + HiiInternal.h
> + HiiExpression.h
> +
> +[Packages]
> + MdePkg/MdePkg.dec
> + MdeModulePkg/MdeModulePkg.dec
> + RedfishPkg/RedfishPkg.dec
> +
> +[LibraryClasses]
> + PrintLib
> + DebugLib
> + BaseMemoryLib
> + UefiRuntimeServicesTableLib
> + UefiBootServicesTableLib
> + MemoryAllocationLib
> + HiiLib
> +
> +[Guids]
> + gZeroGuid
> + gEdkiiIfrBitVarstoreGuid
> + gEfiHiiPlatformSetupFormsetGuid
> + gEfiHiiStandardFormGuid
> +
> +[Protocols]
> + gEfiHiiDatabaseProtocolGuid
> + gEfiHiiConfigRoutingProtocolGuid
> + gEfiHiiConfigAccessProtocolGuid
> + gEfiDevicePathFromTextProtocolGuid
> + gEfiUnicodeCollation2ProtocolGuid
> + gEfiRegularExpressionProtocolGuid
> + gEfiUserManagerProtocolGuid
> +
> +[Depex]
> + TRUE
> diff --git a/RedfishPkg/Include/Library/HiiUtilityLib.h
> b/RedfishPkg/Include/Library/HiiUtilityLib.h
> new file mode 100644
> index 000000000000..0999ef77fe8c
> --- /dev/null
> +++ b/RedfishPkg/Include/Library/HiiUtilityLib.h
> @@ -0,0 +1,1204 @@
> +/** @file
> + Definitions of RedfishPlatformConfigLib.
> +
> + Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> + (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
> + Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights
> reserved.
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef HII_UTILITY_LIB_
> +#define HII_UTILITY_LIB_
> +
> +#include <Protocol/DisplayProtocol.h>
> +#include <Protocol/HiiConfigAccess.h>
> +
> +//
> +// IFR relative definition
> +//
> +#define EFI_HII_EXPRESSION_INCONSISTENT_IF 0
> +#define EFI_HII_EXPRESSION_NO_SUBMIT_IF 1
> +#define EFI_HII_EXPRESSION_GRAY_OUT_IF 2
> +#define EFI_HII_EXPRESSION_SUPPRESS_IF 3
> +#define EFI_HII_EXPRESSION_DISABLE_IF 4
> +#define EFI_HII_EXPRESSION_VALUE 5
> +#define EFI_HII_EXPRESSION_RULE 6
> +#define EFI_HII_EXPRESSION_READ 7
> +#define EFI_HII_EXPRESSION_WRITE 8
> +#define EFI_HII_EXPRESSION_WARNING_IF 9
> +
> +#define EFI_HII_VARSTORE_BUFFER 0
> +#define EFI_HII_VARSTORE_NAME_VALUE 1
> +#define EFI_HII_VARSTORE_EFI_VARIABLE 2 // EFI Varstore type
> follow UEFI spec before 2.3.1.
> +#define EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER 3 // EFI varstore type
> follow UEFI spec 2.3.1 and later.
> +
> +///
> +/// HII_NAME_VALUE_NODE for name/value storage
> +///
> +typedef struct {
> + UINTN Signature;
> + LIST_ENTRY Link;
> + CHAR16 *Name;
> + CHAR16 *Value;
> +} HII_NAME_VALUE_NODE;
> +
> +#define HII_NAME_VALUE_NODE_SIGNATURE SIGNATURE_32 ('N', 'V', 'S',
> 'T')
> +#define HII_NAME_VALUE_NODE_FROM_LINK(a) CR (a,
> HII_NAME_VALUE_NODE, Link, HII_NAME_VALUE_NODE_SIGNATURE)
> +
> +///
> +/// Storage info
> +///
> +typedef union {
> + EFI_STRING_ID VarName;
> + UINT16 VarOffset;
> +} HII_VAR_STORE_INFO;
> +
> +///
> +/// FormSet storage
> +///
> +typedef struct {
> + UINTN Signature;
> + LIST_ENTRY Link;
> +
> + UINT8 Type; ///< Storage type
> + EFI_HII_HANDLE HiiHandle; ///< HiiHandle for this varstore.
> +
> + ///
> + /// For all type of storages.
> + ///
> + UINT16 VarStoreId; ///< VarStore ID.
> + EFI_GUID Guid; ///< VarStore Guid.
> +
> + ///
> + /// For EFI_IFR_VARSTORE, EFI_IFR_VARSTORE_EFI
> + ///
> + CHAR16 *Name; ///< VarStore name
> + UINT16 Size; ///< VarStore size.
> + UINT8 *Buffer; ///< Buffer storage.
> + UINT8 *EditBuffer; ///< Edit copy for Buffer Storage
> +
> + ///
> + /// For EFI_IFR_VARSTORE_EFI: EFI Variable.
> + ///
> + UINT32 Attributes;
> +
> + ///
> + /// For EFI_IFR_VARSTORE_NAME_VALUE.
> + ///
> + LIST_ENTRY NameValueList; ///< List of NAME_VALUE_NODE
> +
> + CHAR16 *ConfigHdr; ///< <ConfigHdr>
> + CHAR16 *ConfigRequest; ///< <ConfigRequest> = <ConfigHdr> +
> <RequestElement>
> + UINTN ElementCount; ///< Number of <RequestElement> in the
> <ConfigRequest>
> + UINTN SpareStrLen; ///< Spare length of ConfigRequest string
> buffer
> +} HII_FORMSET_STORAGE;
> +
> +#define HII_STORAGE_SIGNATURE SIGNATURE_32 ('B', 'S', 'T', 'G')
> +#define HII_STORAGE_FROM_LINK(a) CR (a, HII_FORMSET_STORAGE, Link,
> HII_STORAGE_SIGNATURE)
> +
> +///
> +/// Definition of EXPRESS_RESULT
> +///
> +typedef enum {
> + ExpressFalse = 0,
> + ExpressGrayOut,
> + ExpressSuppress,
> + ExpressDisable
> +} EXPRESS_RESULT;
> +
> +///
> +/// Definition of EXPRESS_LEVEL
> +///
> +typedef enum {
> + ExpressNone = 0,
> + ExpressForm,
> + ExpressStatement,
> + ExpressOption
> +} EXPRESS_LEVEL;
> +
> +///
> +/// Definition of HII_EXPRESSION_OPCODE_EXTRA
> +///
> +typedef union {
> + EFI_HII_VALUE Value; ///< EFI_IFR_UINT64, EFI_IFR_UINT32,
> EFI_IFR_UINT16, EFI_IFR_UINT8, EFI_IFR_STRING_REF1
> + UINT8 Format; ///< For EFI_IFR_TO_STRING, EFI_IFR_FIND
> + UINT8 Flags; ///< For EFI_IFR_SPAN
> + UINT8 RuleId; ///< For EFI_IFR_RULE_REF
> + EFI_GUID Guid; ///< For EFI_IFR_SECURITY, EFI_IFR_MATCH2
> +
> + struct {
> + EFI_QUESTION_ID QuestionId;
> + EFI_HII_VALUE Value;
> + } EqIdValData;
> +
> + struct {
> + EFI_QUESTION_ID QuestionId1;
> + EFI_QUESTION_ID QuestionId2;
> + } EqIdIdData;
> +
> + struct {
> + EFI_QUESTION_ID QuestionId; ///< For EFI_IFR_EQ_ID_VAL_LIST
> + UINT16 ListLength;
> + UINT16 *ValueList;
> + } EqIdListData;
> +
> + struct {
> + EFI_QUESTION_ID QuestionId;
> + } QuestionRef1Data;
> +
> + struct {
> + EFI_STRING_ID DevicePath; ///< For EFI_IFR_QUESTION_REF3_3
> + EFI_GUID Guid;
> + } QuestionRef3Data;
> +
> + struct {
> + HII_FORMSET_STORAGE *VarStorage;
> + HII_VAR_STORE_INFO VarStoreInfo;
> + UINT8 ValueType;
> + UINT8 ValueWidth;
> + CHAR16 *ValueName;
> + } GetSetData;
> +} HII_EXPRESSION_OPCODE_EXTRA;
> +
> +typedef union _HII_DEPENDENCY_EXPRESSION
> HII_DEPENDENCY_EXPRESSION;
> +
> +///
> +/// Definition of HII_EXPRESSION_CONSTANT
> +///
> +/// Operand:
> +///
> +/// EFI_IFR_TRUE
> +/// EFI_IFR_FALSE
> +/// EFI_IFR_ONE
> +/// EFI_IFR_ONES
> +/// EFI_IFR_ZERO
> +/// EFI_IFR_UNDEFINED
> +/// EFI_IFR_VERSION
> +/// EFI_IFR_UINT8
> +/// EFI_IFR_UINT16
> +/// EFI_IFR_UINT32
> +/// EFI_IFR_UINT64
> +///
> +typedef struct {
> + UINT8 Operand;
> + EFI_HII_VALUE Value;
> +} HII_EXPRESSION_CONSTANT;
> +
> +///
> +/// Definition of HII_DEPENDENCY_DUP
> +///
> +typedef struct {
> + UINT8 Operand;
> +} HII_DEPENDENCY_DUP;
> +
> +///
> +/// Definition of HII_DEPENDENCY_EQ_ID_VAL
> +///
> +typedef struct {
> + UINT8 Operand;
> + EFI_QUESTION_ID QuestionId;
> + EFI_HII_VALUE Value;
> +} HII_DEPENDENCY_EQ_ID_VAL;
> +
> +///
> +/// Definition of HII_DEPENDENCY_EQ_ID_VAL
> +///
> +typedef struct {
> + UINT8 Operand;
> + EFI_QUESTION_ID QuestionId1;
> + EFI_QUESTION_ID QuestionId2;
> +} HII_DEPENDENCY_EQ_ID_ID;
> +
> +///
> +/// Definition of HII_DEPENDENCY_EQ_ID_VAL_LIST
> +///
> +typedef struct {
> + UINT8 Operand;
> + EFI_QUESTION_ID QuestionId;
> + UINT16 ListLength;
> + UINT16 *ValueList;
> +} HII_DEPENDENCY_EQ_ID_VAL_LIST;
> +
> +///
> +/// Definition of HII_DEPENDENCY_QUESTION_REF1
> +///
> +typedef struct {
> + UINT8 Operand;
> + EFI_QUESTION_ID QuestionId;
> +} HII_DEPENDENCY_QUESTION_REF1;
> +
> +///
> +/// Definition of HII_DEPENDENCY_RULE_REF
> +///
> +typedef struct {
> + UINT8 Operand;
> + UINT8 RuleId;
> +} HII_DEPENDENCY_RULE_REF;
> +
> +///
> +/// Definition of HII_DEPENDENCY_STRING_REF1
> +///
> +typedef struct {
> + UINT8 Operand;
> + EFI_HII_VALUE Value;
> +} HII_DEPENDENCY_STRING_REF1;
> +
> +///
> +/// Definition of HII_DEPENDENCY_THIS
> +///
> +typedef struct {
> + UINT8 Operand;
> + EFI_QUESTION_ID QuestionId;
> +} HII_DEPENDENCY_THIS;
> +
> +///
> +/// Definition of HII_DEPENDENCY_SECURITY
> +///
> +typedef struct {
> + UINT8 Operand;
> + EFI_GUID Permissions;
> +} HII_DEPENDENCY_SECURITY;
> +
> +///
> +/// Definition of HII_DEPENDENCY_GET
> +///
> +typedef struct {
> + UINT8 Operand;
> + HII_FORMSET_STORAGE *VarStorage;
> + HII_VAR_STORE_INFO VarStoreInfo;
> + UINT8 ValueType;
> + UINT8 ValueWidth;
> + CHAR16 *ValueName;
> +} HII_DEPENDENCY_GET;
> +
> +///
> +/// Definition of HII_DEPENDENCY_LENGTH
> +///
> +typedef struct {
> + UINT8 Operand;
> + HII_DEPENDENCY_EXPRESSION *SubExpression;
> +} HII_DEPENDENCY_LENGTH;
> +
> +///
> +/// Definition of HII_DEPENDENCY_BITWISE_NOT
> +///
> +typedef struct {
> + UINT8 Operand;
> + HII_DEPENDENCY_EXPRESSION *SubExpression;
> +} HII_DEPENDENCY_BITWISE_NOT;
> +
> +///
> +/// Definition of HII_DEPENDENCY_STRING_REF2
> +///
> +typedef struct {
> + UINT8 Operand;
> + HII_DEPENDENCY_EXPRESSION *SubExpression;
> +} HII_DEPENDENCY_STRING_REF2;
> +
> +///
> +/// Definition of HII_DEPENDENCY_QUESTION_REF2
> +///
> +typedef struct {
> + UINT8 Operand;
> + HII_DEPENDENCY_EXPRESSION *SubExpression;
> +} HII_DEPENDENCY_QUESTION_REF2;
> +
> +///
> +/// Definition of HII_DEPENDENCY_QUESTION_REF3
> +///
> +typedef struct {
> + UINT8 Operand;
> + EFI_STRING_ID DevicePath;
> + EFI_GUID Guid;
> + HII_DEPENDENCY_EXPRESSION *SubExpression;
> +} HII_DEPENDENCY_QUESTION_REF3;
> +
> +///
> +/// Definition of HII_DEPENDENCY_TO_BOOLEAN
> +///
> +typedef struct {
> + UINT8 Operand;
> + HII_DEPENDENCY_EXPRESSION *SubExpression;
> +} HII_DEPENDENCY_TO_BOOLEAN;
> +
> +///
> +/// Definition of HII_DEPENDENCY_TO_STRING
> +///
> +typedef struct {
> + UINT8 Operand;
> + UINT8 Format;
> + HII_DEPENDENCY_EXPRESSION *SubExpression;
> +} HII_DEPENDENCY_TO_STRING;
> +
> +///
> +/// Definition of HII_DEPENDENCY_TO_UINT
> +///
> +typedef struct {
> + UINT8 Operand;
> + HII_DEPENDENCY_EXPRESSION *SubExpression;
> +} HII_DEPENDENCY_TO_UINT;
> +
> +///
> +/// Definition of HII_DEPENDENCY_TO_UPPER
> +///
> +typedef struct {
> + UINT8 Operand;
> + HII_DEPENDENCY_EXPRESSION *SubExpression;
> +} HII_DEPENDENCY_TO_UPPER;
> +
> +///
> +/// Definition of HII_DEPENDENCY_TO_LOWER
> +///
> +typedef struct {
> + UINT8 Operand;
> + HII_DEPENDENCY_EXPRESSION *SubExpression;
> +} HII_DEPENDENCY_TO_LOWER;
> +
> +///
> +/// Definition of HII_DEPENDENCY_SET
> +///
> +typedef struct {
> + UINT8 Operand;
> + HII_FORMSET_STORAGE *VarStorage;
> + HII_VAR_STORE_INFO VarStoreInfo;
> + UINT8 ValueType;
> + UINT8 ValueWidth;
> + CHAR16 *ValueName;
> + HII_DEPENDENCY_EXPRESSION *SubExpression;
> +} HII_DEPENDENCY_SET;
> +
> +///
> +/// Definition of HII_DEPENDENCY_NOT
> +///
> +typedef struct {
> + UINT8 Operand;
> + HII_DEPENDENCY_EXPRESSION *SubExpression;
> +} HII_DEPENDENCY_NOT;
> +
> +///
> +/// Definition of HII_DEPENDENCY_CATENATE
> +///
> +typedef struct {
> + UINT8 Operand;
> + HII_DEPENDENCY_EXPRESSION *LeftStringExp;
> + HII_DEPENDENCY_EXPRESSION *RightStringExp;
> +} HII_DEPENDENCY_CATENATE;
> +
> +///
> +/// Definition of HII_DEPENDENCY_MATCH
> +///
> +typedef struct {
> + UINT8 Operand;
> + HII_DEPENDENCY_EXPRESSION *StringExp;
> + HII_DEPENDENCY_EXPRESSION *PatternExp;
> +} HII_DEPENDENCY_MATCH;
> +
> +///
> +/// Definition of HII_DEPENDENCY_MATCH2
> +///
> +typedef struct {
> + UINT8 Operand;
> + EFI_GUID SyntaxType;
> + HII_DEPENDENCY_EXPRESSION *StringExp;
> + HII_DEPENDENCY_EXPRESSION *PatternExp;
> +} HII_DEPENDENCY_MATCH2;
> +
> +///
> +/// Definition of HII_DEPENDENCY_MULT
> +///
> +typedef struct {
> + UINT8 Operand;
> + HII_DEPENDENCY_EXPRESSION *RightHandExp;
> + HII_DEPENDENCY_EXPRESSION *LeftHandExp;
> +} HII_DEPENDENCY_MULT;
> +
> +///
> +/// Definition of HII_DEPENDENCY_DIV
> +///
> +typedef struct {
> + UINT8 Operand;
> + HII_DEPENDENCY_EXPRESSION *RightHandExp; ///< right value
> + HII_DEPENDENCY_EXPRESSION *LeftHandExp; ///< left value
> +} HII_DEPENDENCY_DIV;
> +
> +///
> +/// Definition of HII_DEPENDENCY_MOD
> +///
> +typedef struct {
> + UINT8 Operand;
> + HII_DEPENDENCY_EXPRESSION *RightHandExp; ///< right value
> + HII_DEPENDENCY_EXPRESSION *LeftHandExp; ///< left value
> +} HII_DEPENDENCY_MOD;
> +
> +///
> +/// Definition of HII_DEPENDENCY_ADD
> +///
> +typedef struct {
> + UINT8 Operand;
> + HII_DEPENDENCY_EXPRESSION *RightHandExp; ///< right value
> + HII_DEPENDENCY_EXPRESSION *LeftHandExp; ///< left value
> +} HII_DEPENDENCY_ADD;
> +
> +///
> +/// Definition of HII_DEPENDENCY_SUBTRACT
> +///
> +typedef struct {
> + UINT8 Operand;
> + HII_DEPENDENCY_EXPRESSION *RightHandExp; ///< right value
> + HII_DEPENDENCY_EXPRESSION *LeftHandExp; ///< left value
> +} HII_DEPENDENCY_SUBTRACT;
> +
> +///
> +/// Definition of HII_DEPENDENCY_SHIFT_LEFT
> +///
> +typedef struct {
> + UINT8 Operand;
> + HII_DEPENDENCY_EXPRESSION *RightHandExp;
> + HII_DEPENDENCY_EXPRESSION *LeftHandExp;
> +} HII_DEPENDENCY_SHIFT_LEFT;
> +
> +///
> +/// Definition of HII_DEPENDENCY_SHIFT_RIGHT
> +///
> +typedef struct {
> + UINT8 Operand;
> + HII_DEPENDENCY_EXPRESSION *RightHandExp;
> + HII_DEPENDENCY_EXPRESSION *LeftHandExp;
> +} HII_DEPENDENCY_SHIFT_RIGHT;
> +
> +///
> +/// Definition of HII_DEPENDENCY_GREATER_THAN
> +///
> +typedef struct {
> + UINT8 Operand;
> + HII_DEPENDENCY_EXPRESSION *RightHandExp;
> + HII_DEPENDENCY_EXPRESSION *LeftHandExp;
> +} HII_DEPENDENCY_GREATER_THAN;
> +
> +///
> +/// Definition of HII_DEPENDENCY_GREATER_EQUAL
> +///
> +typedef struct {
> + UINT8 Operand;
> + HII_DEPENDENCY_EXPRESSION *RightHandExp;
> + HII_DEPENDENCY_EXPRESSION *LeftHandExp;
> +} HII_DEPENDENCY_GREATER_EQUAL;
> +
> +///
> +/// Definition of HII_DEPENDENCY_LESS_THAN
> +///
> +typedef struct {
> + UINT8 Operand;
> + HII_DEPENDENCY_EXPRESSION *RightHandExp;
> + HII_DEPENDENCY_EXPRESSION *LeftHandExp;
> +} HII_DEPENDENCY_LESS_THAN;
> +
> +///
> +/// Definition of HII_DEPENDENCY_LESS_EQUAL
> +///
> +typedef struct {
> + UINT8 Operand;
> + HII_DEPENDENCY_EXPRESSION *RightHandExp;
> + HII_DEPENDENCY_EXPRESSION *LeftHandExp;
> +} HII_DEPENDENCY_LESS_EQUAL;
> +
> +///
> +/// Definition of HII_DEPENDENCY_EQUAL
> +///
> +typedef struct {
> + UINT8 Operand;
> + HII_DEPENDENCY_EXPRESSION *SubExpression1;
> + HII_DEPENDENCY_EXPRESSION *SubExpression2;
> +} HII_DEPENDENCY_EQUAL;
> +
> +///
> +/// Definition of HII_DEPENDENCY_NOT_EQUAL
> +///
> +typedef struct {
> + UINT8 Operand;
> + HII_DEPENDENCY_EXPRESSION *SubExpression1;
> + HII_DEPENDENCY_EXPRESSION *SubExpression2;
> +} HII_DEPENDENCY_NOT_EQUAL;
> +
> +///
> +/// Definition of HII_DEPENDENCY_BITWISE_AND
> +///
> +typedef struct {
> + UINT8 Operand;
> + HII_DEPENDENCY_EXPRESSION *SubExpression1;
> + HII_DEPENDENCY_EXPRESSION *SubExpression2;
> +} HII_DEPENDENCY_BITWISE_AND;
> +
> +///
> +/// Definition of HII_DEPENDENCY_BITWISE_OR
> +///
> +typedef struct {
> + UINT8 Operand;
> + HII_DEPENDENCY_EXPRESSION *SubExpression1;
> + HII_DEPENDENCY_EXPRESSION *SubExpression2;
> +} HII_DEPENDENCY_BITWISE_OR;
> +
> +///
> +/// Definition of HII_DEPENDENCY_AND
> +///
> +typedef struct {
> + UINT8 Operand;
> + HII_DEPENDENCY_EXPRESSION *SubExpression1;
> + HII_DEPENDENCY_EXPRESSION *SubExpression2;
> +} HII_DEPENDENCY_AND;
> +
> +///
> +/// Definition of HII_DEPENDENCY_OR
> +///
> +typedef struct {
> + UINT8 Operand;
> + HII_DEPENDENCY_EXPRESSION *SubExpression1;
> + HII_DEPENDENCY_EXPRESSION *SubExpression2;
> +} HII_DEPENDENCY_OR;
> +
> +///
> +/// Definition of HII_DEPENDENCY_CONDITIONAL
> +///
> +/// Ternary expression
> +///
> +typedef struct {
> + UINT8 Operand;
> + HII_DEPENDENCY_EXPRESSION *CondTrueValExp; ///< right value
> + HII_DEPENDENCY_EXPRESSION *CondFalseValExp; ///< middle value
> + HII_DEPENDENCY_EXPRESSION *ConditionExp; ///< left value
> +} HII_DEPENDENCY_CONDITIONAL;
> +
> +///
> +/// Definition of HII_DEPENDENCY_FIND
> +///
> +typedef struct {
> + UINT8 Operand;
> + UINT8 Format;
> + HII_DEPENDENCY_EXPRESSION *IndexExp; ///< right value
> + HII_DEPENDENCY_EXPRESSION *StringToCompWithExp; ///< middle
> value
> + HII_DEPENDENCY_EXPRESSION *StringToSearchExp; ///< left value
> +} HII_DEPENDENCY_FIND;
> +
> +///
> +/// Definition of HII_DEPENDENCY_MID
> +///
> +typedef struct {
> + UINT8 Operand;
> + HII_DEPENDENCY_EXPRESSION *LengthExp; ///< right value
> + HII_DEPENDENCY_EXPRESSION *IndexExp; ///< middle value
> + HII_DEPENDENCY_EXPRESSION *StringOrBufferExp; ///< left value
> +} HII_DEPENDENCY_MID;
> +
> +///
> +/// Definition of HII_DEPENDENCY_TOKEN
> +///
> +typedef struct {
> + UINT8 Operand;
> + HII_DEPENDENCY_EXPRESSION *IndexExp; ///< right value
> + HII_DEPENDENCY_EXPRESSION *DelimiterExp; ///< middle value
> + HII_DEPENDENCY_EXPRESSION *StringToSearchExp; ///< left value
> +} HII_DEPENDENCY_TOKEN;
> +
> +///
> +/// Definition of HII_DEPENDENCY_SPAN
> +///
> +typedef struct {
> + UINT8 Operand;
> + UINT8 Flags;
> + HII_DEPENDENCY_EXPRESSION *IndexExp; ///< right value
> + HII_DEPENDENCY_EXPRESSION *CharsetExp; ///< middle value
> + HII_DEPENDENCY_EXPRESSION *StringToSearchExp; ///< left value
> +} HII_DEPENDENCY_SPAN;
> +
> +///
> +/// Map expression
> +///
> +typedef struct {
> + HII_DEPENDENCY_EXPRESSION *MatchExp;
> + HII_DEPENDENCY_EXPRESSION *ReturnExp;
> +} HII_DEPENDENCY_EXPRESSION_PAIR;
> +
> +///
> +/// Definition of HII_DEPENDENCY_MAP
> +///
> +typedef struct {
> + UINT8 Operand;
> + HII_DEPENDENCY_EXPRESSION *SubExp;
> + HII_DEPENDENCY_EXPRESSION_PAIR *ExpPair;
> + UINT8 ExpPairNo;
> +} HII_DEPENDENCY_MAP;
> +
> +///
> +/// Definition of HII_DEPENDENCY_EXPRESSION
> +///
> +union _HII_DEPENDENCY_EXPRESSION {
> + ///
> + /// Constant
> + ///
> + HII_EXPRESSION_CONSTANT ConstantExp;
> + ///
> + /// build-in expression
> + ///
> + HII_DEPENDENCY_DUP DupExp;
> + HII_DEPENDENCY_EQ_ID_VAL EqIdValExp;
> + HII_DEPENDENCY_EQ_ID_ID EqIdIdExp;
> + HII_DEPENDENCY_EQ_ID_VAL_LIST EqIdListExp;
> + HII_DEPENDENCY_QUESTION_REF1 QuestionRef1Exp;
> + HII_DEPENDENCY_RULE_REF RuleRefExp;
> + HII_DEPENDENCY_STRING_REF1 StringRef1Exp;
> + HII_DEPENDENCY_THIS ThisExp;
> + HII_DEPENDENCY_SECURITY SecurityExp;
> + HII_DEPENDENCY_GET GetExp;
> +
> + ///
> + /// unary expression
> + ///
> + HII_DEPENDENCY_LENGTH LengthExp;
> + HII_DEPENDENCY_BITWISE_NOT BitWiseNotExp;
> + HII_DEPENDENCY_STRING_REF2 StringRef2Exp;
> + HII_DEPENDENCY_QUESTION_REF2 QuestionRef2Exp;
> + HII_DEPENDENCY_QUESTION_REF3 QuestionRef3Exp;
> + HII_DEPENDENCY_TO_BOOLEAN ToBooleanExp;
> + HII_DEPENDENCY_TO_STRING ToStringExp;
> + HII_DEPENDENCY_TO_UINT ToUintExp;
> + HII_DEPENDENCY_TO_UPPER ToUpperExp;
> + HII_DEPENDENCY_TO_LOWER ToLowerExp;
> + HII_DEPENDENCY_SET SetExp;
> + HII_DEPENDENCY_NOT NotExp;
> +
> + ///
> + /// Binary expression
> + ///
> + HII_DEPENDENCY_CATENATE CatenateExp;
> + HII_DEPENDENCY_MATCH MatchExp;
> + HII_DEPENDENCY_MATCH2 Match2Exp;
> + HII_DEPENDENCY_MULT MultExp;
> + HII_DEPENDENCY_DIV DivExp;
> + HII_DEPENDENCY_MOD ModExp;
> + HII_DEPENDENCY_ADD AddExp;
> + HII_DEPENDENCY_SUBTRACT SubtractExp;
> + HII_DEPENDENCY_SHIFT_LEFT ShiftLeftExp;
> + HII_DEPENDENCY_SHIFT_RIGHT ShiftRightExp;
> + HII_DEPENDENCY_GREATER_THAN GreaterThanExp;
> + HII_DEPENDENCY_GREATER_EQUAL GreaterEqualExp;
> + HII_DEPENDENCY_LESS_THAN LessThanExp;
> + HII_DEPENDENCY_LESS_EQUAL LessEqualExp;
> + HII_DEPENDENCY_EQUAL EqualExp;
> + HII_DEPENDENCY_NOT_EQUAL NotEqualExp;
> + HII_DEPENDENCY_BITWISE_AND BitwiseAndExp;
> + HII_DEPENDENCY_BITWISE_OR BitwiseOrExp;
> + HII_DEPENDENCY_AND AndExp;
> + HII_DEPENDENCY_OR OrExp;
> +
> + ///
> + /// ternary expression
> + ///
> + HII_DEPENDENCY_CONDITIONAL ConditionalExp;
> + HII_DEPENDENCY_FIND FindExp;
> + HII_DEPENDENCY_MID MidExp;
> + HII_DEPENDENCY_TOKEN TokenExp;
> + HII_DEPENDENCY_SPAN SpanExp;
> + HII_DEPENDENCY_MAP MapExp;
> +};
> +
> +///
> +/// Definition of HII_EXPRESSION_OPCODE
> +///
> +typedef struct {
> + UINTN Signature;
> + LIST_ENTRY Link;
> + UINT8 Operand;
> + HII_EXPRESSION_OPCODE_EXTRA ExtraData;
> + LIST_ENTRY MapExpressionList; ///< nested expressions inside
> of Map opcode.
> +} HII_EXPRESSION_OPCODE;
> +
> +#define HII_EXPRESSION_OPCODE_SIGNATURE SIGNATURE_32 ('E', 'X', 'O',
> 'P')
> +#define HII_EXPRESSION_OPCODE_FROM_LINK(a) CR (a,
> HII_EXPRESSION_OPCODE, Link, HII_EXPRESSION_OPCODE_SIGNATURE)
> +
> +///
> +/// Definition of HII_WARNING_IF_DATA
> +///
> +typedef struct {
> + EFI_STRING_ID WarningIfError;
> + UINT8 TimeOut;
> +} HII_WARNING_IF_DATA;
> +
> +///
> +/// Definition of HII_EXTRA_DATA
> +///
> +typedef union {
> + UINT8 RuleId; ///< For EFI_IFR_RULE only
> + EFI_STRING_ID Error; ///< For EFI_IFR_NO_SUBMIT_IF,
> EFI_IFR_INCONSISTENT_IF only
> + HII_WARNING_IF_DATA WarningIfData;
> +} HII_EXTRA_DATA;
> +
> +///
> +/// Definition of HII_EXPRESSION
> +///
> +typedef struct {
> + UINTN Signature;
> + LIST_ENTRY Link;
> + UINT8 Type; ///< Type for this expression
> + EFI_IFR_OP_HEADER *OpCode; ///< Save the opcode buffer.
> + LIST_ENTRY OpCodeListHead; ///< OpCodes consist of this
> expression (HII_EXPRESSION_OPCODE)
> + HII_DEPENDENCY_EXPRESSION *RootDependencyExp; ///< Expression
> OpCodes tree layout to describe dependency of this expression.
> + HII_EXTRA_DATA ExtraData;
> + EFI_HII_VALUE Result; ///< Expression evaluation result
> +} HII_EXPRESSION;
> +
> +#define HII_EXPRESSION_SIGNATURE SIGNATURE_32 ('F', 'E', 'X', 'P')
> +#define HII_EXPRESSION_FROM_LINK(a) CR (a, HII_EXPRESSION, Link,
> HII_EXPRESSION_SIGNATURE)
> +
> +///
> +/// Definition of HII_EXPRESSION_LIST
> +///
> +typedef struct {
> + UINTN Signature;
> + UINTN Count;
> + HII_EXPRESSION *Expression[1]; ///< Array[Count] of expressions
> +} HII_EXPRESSION_LIST;
> +
> +#define HII_EXPRESSION_LIST_SIGNATURE SIGNATURE_32 ('F', 'E', 'X', 'R')
> +
> +///
> +/// Definition of HII_STATEMENT_VALUE
> +///
> +typedef struct {
> + ///
> + /// HII Data Type
> + ///
> + UINT8 Type;
> + EFI_IFR_TYPE_VALUE Value;
> + ///
> + /// Buffer Data and Length if Type is EFI_IFR_TYPE_BUFFER or
> EFI_IFR_TYPE_STRING
> + ///
> + UINT8 *Buffer;
> + UINT16 BufferLen;
> + UINT8 BufferValueType; ///< Data type for buffer internal data,
> currently only for orderedlist
> +} HII_STATEMENT_VALUE;
> +
> +///
> +/// Default value
> +///
> +typedef struct {
> + UINTN Signature;
> + LIST_ENTRY Link;
> +
> + UINT16 DefaultId;
> + HII_STATEMENT_VALUE Value; ///< Default value
> +
> + HII_EXPRESSION *ValueExpression; ///< Not-NULL indicates default
> value is provided by EFI_IFR_VALUE
> +} HII_QUESTION_DEFAULT;
> +
> +#define HII_QUESTION_DEFAULT_SIGNATURE SIGNATURE_32 ('Q', 'D', 'F',
> 'T')
> +#define HII_QUESTION_DEFAULT_FROM_LINK(a) CR (a,
> HII_QUESTION_DEFAULT, Link, HII_QUESTION_DEFAULT_SIGNATURE)
> +
> +#define HII_QUESTION_OPTION_SIGNATURE SIGNATURE_32 ('Q', 'O', 'P',
> 'T')
> +
> +///
> +/// Option value
> +///
> +typedef struct {
> + UINTN Signature;
> + LIST_ENTRY Link;
> +
> + EFI_IFR_ONE_OF_OPTION *OpCode; ///< OneOfOption Data
> +
> + EFI_STRING_ID Text;
> + UINT8 Flags;
> + HII_STATEMENT_VALUE Value;
> + EFI_IMAGE_ID ImageId;
> +
> + HII_EXPRESSION_LIST *SuppressExpression; ///< Non-NULL indicates
> nested inside of SuppressIf
> +} HII_QUESTION_OPTION;
> +
> +#define HII_QUESTION_OPTION_FROM_LINK(a) CR (a,
> HII_QUESTION_OPTION, Link, HII_QUESTION_OPTION_SIGNATURE)
> +
> +///
> +/// class of default
> +///
> +typedef struct {
> + UINTN Signature;
> + LIST_ENTRY Link;
> +
> + UINT16 DefaultId;
> + EFI_STRING_ID DefaultName;
> +} HII_FORMSET_DEFAULTSTORE;
> +
> +#define HII_FORMSET_DEFAULTSTORE_SIGNATURE SIGNATURE_32 ('F', 'D',
> 'F', 'S')
> +#define HII_FORMSET_DEFAULTSTORE_FROM_LINK(a) CR (a,
> HII_FORMSET_DEFAULTSTORE, Link,
> HII_FORMSET_DEFAULTSTORE_SIGNATURE)
> +
> +///
> +/// Definition of HII_STATEMENT_EXTRA
> +///
> +typedef union {
> + UINT8 Flags;
> + EFI_STRING_ID TextTwo;
> + EFI_DEFAULT_ID DefaultId;
> + EFI_STRING_ID QuestionConfig;
> + EFI_GUID Guid;
> +
> + struct {
> + UINT8 Flags;
> + UINT64 Minimum; ///< for EFI_IFR_ONE_OF/EFI_IFR_NUMERIC,
> it's Min/Max value
> + UINT64 Maximum; ///< for EFI_IFR_STRING/EFI_IFR_PASSWORD,
> it's Min/Max length
> + UINT64 Step;
> + EFI_GUID Guid;
> + } NumData;
> +
> + struct {
> + UINT8 Flags;
> + UINT8 MaxContainers; ///< for EFI_IFR_ORDERED_LIST
> + } OrderListData;
> +
> + struct {
> + UINT8 Flags;
> + UINT8 MinSize;
> + UINT8 MaxSize;
> + } StrData;
> +
> + struct {
> + UINT16 MinSize;
> + UINT16 MaxSize;
> + } PwdData;
> +} HII_STATEMENT_EXTRA;
> +
> +///
> +/// Statement (Question)
> +///
> +typedef struct _HII_STATEMENT HII_STATEMENT;
> +struct _HII_STATEMENT {
> + UINTN Signature;
> + LIST_ENTRY Link;
> +
> + UINT8 Operand; ///< The operand (first byte) of this
> Statement or Question
> + EFI_IFR_OP_HEADER *OpCode;
> +
> + ///
> + /// Statement Header
> + ///
> + EFI_STRING_ID Prompt;
> + EFI_STRING_ID Help;
> +
> + ///
> + /// Question Header
> + ///
> + EFI_QUESTION_ID QuestionId; ///< Question id, the value of zero is
> reserved
> + EFI_VARSTORE_ID VarStoreId; ///< VarStore id, a value of zero
> indicates no variable storage
> + HII_VAR_STORE_INFO VarStoreInfo; ///< VarStoreInfoIf VarStoreId
> refers to Buffer Storage (EFI_IFR_VARSTORE or EFI_IFR_VARSTORE_EFI),
> then VarStoreInfo contains a 16-bit Buffer Storage offset (VarOffset).
> + ///< If VarStoreId refers to Name/Value Storage
> (EFI_IFR_VARSTORE_NAME_VALUE), then VarStoreInfo contains the String
> ID of the name (VarName) for this name/value pair.
> + UINT8 QuestionFlags; ///< The flag of this Question.(Readonly,
> reset required, callback attribute....)
> +
> + BOOLEAN QuestionReferToBitField; ///< Whether the question is
> stored in a bit field.
> + UINT16 StorageWidth; ///< The storage width of this
> Question.
> + UINT16 BitStorageWidth; ///< The Storage width of this
> Question in bit level.
> + UINT16 BitVarOffset; ///< The storage offset of this
> Question in bit level.
> + CHAR16 *VariableName; ///< Name/Value or EFI Variable
> name
> + CHAR16 *BlockName; ///< Buffer storage block name:
> "OFFSET=...WIDTH=..."
> +
> + HII_FORMSET_STORAGE *Storage; ///< Point to the storage that
> store this question.
> + HII_STATEMENT_EXTRA ExtraData;
> +
> + BOOLEAN Locked; ///< Whether this statement is locked.
> +
> + HII_STATEMENT_VALUE Value;
> +
> + ///
> + /// Get from IFR parsing
> + ///
> +
> + HII_STATEMENT *ParentStatement; ///< Parent Statement of
> current statement.
> + HII_EXPRESSION_LIST *ExpressionList; ///< nesting inside of
> GrayedOutIf/DisableIf/SuppressIf
> + HII_EXPRESSION *ValueExpression; ///< nested EFI_IFR_VALUE,
> provide Question value and indicate Question is ReadOnly
> +
> + EFI_IMAGE_ID ImageId; ///< nested EFI_IFR_IMAGE
> + UINT8 RefreshInterval; ///< nested EFI_IFR_REFRESH, refresh
> interval(in seconds) for Question value, 0 means no refresh
> +
> + LIST_ENTRY DefaultListHead; ///< nested EFI_IFR_DEFAULT list
> (HII_QUESTION_DEFAULT), provide default values
> + LIST_ENTRY OptionListHead; ///< nested
> EFI_IFR_ONE_OF_OPTION list (HII_QUESTION_OPTION)
> + LIST_ENTRY InconsistentListHead; ///< nested inconsistent
> expression list (HII_EXPRESSION)
> + LIST_ENTRY NoSubmitListHead; ///< nested nosubmit expression
> list (HII_EXPRESSION)
> + LIST_ENTRY WarningListHead; ///< nested warning expression list
> (HII_EXPRESSION)
> +
> + HII_EXPRESSION *ReadExpression; ///< nested EFI_IFR_READ,
> provide this question value by read expression.
> + HII_EXPRESSION *WriteExpression; ///< nested EFI_IFR_WRITE,
> evaluate write expression after this question value is set.
> +};
> +
> +#define HII_STATEMENT_SIGNATURE SIGNATURE_32 ('H', 'S', 'T', 'A')
> +#define HII_STATEMENT_FROM_LINK(a) CR (a, HII_STATEMENT, Link,
> HII_STATEMENT_SIGNATURE)
> +
> +///
> +/// Form
> +///
> +#define STANDARD_MAP_FORM_TYPE 0x01
> +
> +typedef struct {
> + UINTN Signature;
> + LIST_ENTRY Link;
> +
> + UINT16 FormId; ///< FormId of normal form or formmap
> form.
> + EFI_STRING_ID FormTitle; ///< FormTile of normal form, or
> FormMapMethod title of formmap form.
> + UINT16 FormType; ///< Specific form type for the different
> form.
> +
> + EFI_IMAGE_ID ImageId; ///< The image id.
> +
> + BOOLEAN ModalForm; ///< Whether this is a modal form.
> + BOOLEAN Locked; ///< Whether this form is locked.
> + EFI_GUID RefreshGuid; ///< Form refresh event guid.
> +
> + LIST_ENTRY StatementListHead; ///< List of Statements and
> Questions (HII_STATEMENT)
> + LIST_ENTRY ConfigRequestHead; ///< List of configrequest for all
> storage.
> + LIST_ENTRY RuleListHead; ///< nested EFI_IFR_RULE list, pre-
> defined expressions attached to the form.
> + HII_EXPRESSION_LIST *SuppressExpression; ///< nesting inside of
> SuppressIf
> +} HII_FORM;
> +
> +#define HII_FORM_SIGNATURE SIGNATURE_32 ('F', 'F', 'R', 'M')
> +#define HII_FORM_FROM_LINK(a) CR (a, HII_FORM, Link,
> HII_FORM_SIGNATURE)
> +
> +///
> +/// FormSet
> +///
> +typedef struct {
> + UINTN Signature;
> + LIST_ENTRY Link;
> +
> + EFI_HII_HANDLE HiiHandle; ///< Unique id for formset, HII
> Handle of this FormSet package.
> + EFI_HANDLE DriverHandle; ///< EFI_HANDLE which was
> registered with the package list in NewPackageList().
> + EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess; ///<
> ConfigAccess Protocol associated with this HiiPackageList
> + EFI_DEVICE_PATH_PROTOCOL *DevicePath;
> +
> + UINTN IfrBinaryLength; ///< Ifr binary data length of this
> formset.
> + UINT8 *IfrBinaryData; ///< Point to the Ifr binary data.
> +
> + EFI_GUID Guid; ///< Formset Guid.
> + EFI_STRING_ID FormSetTitle; ///< String Id of Formset title.
> + EFI_STRING_ID Help; ///< String Id of Formset title.
> +
> + UINT8 NumberOfClassGuid; ///< Class Guid name
> + EFI_GUID ClassGuid[3]; ///< Up to three ClassGuid
> +
> + EFI_IMAGE_ID ImageId; ///< The image id.
> +
> + LIST_ENTRY StatementListOSF; ///< Statement list out side of
> the form.
> + LIST_ENTRY StorageListHead; ///< Storage list
> (HII_FORMSET_STORAGE)
> + LIST_ENTRY DefaultStoreListHead; ///< DefaultStore list
> (HII_FORMSET_DEFAULTSTORE)
> + LIST_ENTRY FormListHead; ///< Form list
> (HII_FORM_BROWSER_FORM)
> +} HII_FORMSET;
> +
> +#define HII_FORMSET_SIGNATURE SIGNATURE_32 ('H', 'I', 'F', 'S')
> +#define HII_FORMSET_FROM_LINK(a) CR (a, HII_FORMSET, Link,
> HII_FORMSET_SIGNATURE)
> +
> +///
> +/// Get/set question value from/to.
> +///
> +typedef enum {
> + GetSetValueWithBuffer = 0, ///< Get/Set question value from/to
> buffer in the storage.
> + GetSetValueWithHiiDriver, ///< Get/Set question value from/to hii
> driver.
> + GetSetValueWithBoth, ///< Compare the editbuffer with buffer for
> this question, not use the question value.
> + GetSetValueWithMax ///< Invalid value.
> +} GET_SET_QUESTION_VALUE_WITH;
> +
> +/**
> + Initialize the internal data structure of a FormSet.
> +
> + @param[in] Handle PackageList Handle
> + @param[in,out] FormSetGuid On input, GUID or class GUID of a formset.
> If not
> + specified (NULL or zero GUID), take the first
> + FormSet with class GUID
> EFI_HII_PLATFORM_SETUP_FORMSET_GUID
> + found in package list.
> + On output, GUID of the formset found(if not NULL).
> + @param[out] FormSet FormSet data structure.
> +
> + @retval EFI_SUCCESS The function completed successfully.
> + @retval EFI_NOT_FOUND The specified FormSet could not be found.
> +
> +**/
> +EFI_STATUS
> +CreateFormSetFromHiiHandle (
> + IN EFI_HII_HANDLE Handle,
> + IN OUT EFI_GUID *FormSetGuid,
> + OUT HII_FORMSET *FormSet
> + );
> +
> +/**
> + Initialize a Formset and get current setting for Questions.
> +
> + @param[in,out] FormSet FormSet data structure.
> +
> +**/
> +VOID
> +InitializeFormSet (
> + IN OUT HII_FORMSET *FormSet
> + );
> +
> +/**
> + Free resources allocated for a FormSet.
> +
> + @param[in,out] FormSet Pointer of the FormSet
> +
> +**/
> +VOID
> +DestroyFormSet (
> + IN OUT HII_FORMSET *FormSet
> + );
> +
> +/**
> + Save Question Value to the memory, but not to storage.
> +
> + @param[in] FormSet FormSet data structure.
> + @param[in] Form Form data structure.
> + @param[in,out] Question Pointer to the Question.
> + @param[in] QuestionValue New Question Value to be set.
> +
> + @retval EFI_SUCCESS The question value has been set successfully.
> + @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
> +
> +**/
> +EFI_STATUS
> +SetQuestionValue (
> + IN HII_FORMSET *FormSet,
> + IN HII_FORM *Form,
> + IN OUT HII_STATEMENT *Question,
> + IN HII_STATEMENT_VALUE *QuestionValue
> + );
> +
> +/**
> + Get Question's current Value from storage.
> +
> + @param[in] FormSet FormSet data structure.
> + @param[in] Form Form data structure.
> + @param[in,out] Question Question to be initialized.
> +
> + @return the current Question Value in storage if success.
> + @return NULL if Question is not found or any error occurs.
> +
> +**/
> +HII_STATEMENT_VALUE *
> +RetrieveQuestion (
> + IN HII_FORMSET *FormSet,
> + IN HII_FORM *Form,
> + IN OUT HII_STATEMENT *Question
> + );
> +
> +/**
> + Get Question's current Value.
> +
> + @param[in] FormSet FormSet data structure.
> + @param[in] Form Form data structure.
> + @param[out] Question Question to be initialized.
> + @param[in] GetValueFrom Where to get value, may from editbuffer,
> buffer or hii driver.
> +
> + @retval EFI_SUCCESS The function completed successfully.
> + @retval EFI_INVALID_PARAMETER Formset, Form or Question is NULL.
> +
> +**/
> +EFI_STATUS
> +GetQuestionValue (
> + IN HII_FORMSET *FormSet,
> + IN HII_FORM *Form,
> + IN OUT HII_STATEMENT *Question,
> + IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
> + );
> +
> +/**
> + Submit data for a form.
> +
> + @param[in] FormSet FormSet which contains the Form.
> + @param[in] Form Form to submit.
> +
> + @retval EFI_SUCCESS The function completed successfully.
> + @retval Others Other errors occur.
> +
> +**/
> +EFI_STATUS
> +SubmitForm (
> + IN HII_FORMSET *FormSet,
> + IN HII_FORM *Form
> + );
> +
> +/**
> + Evaluate the result of a HII expression.
> +
> + If Expression is NULL, then ASSERT.
> +
> + @param[in] FormSet FormSet associated with this expression.
> + @param[in] Form Form associated with this expression.
> + @param[in,out] Expression Expression to be evaluated.
> +
> + @retval EFI_SUCCESS The expression evaluated successfully
> + @retval EFI_NOT_FOUND The Question which referenced by a
> QuestionId
> + could not be found.
> + @retval EFI_OUT_OF_RESOURCES There is not enough system memory
> to grow the
> + stack.
> + @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
> + @retval EFI_INVALID_PARAMETER Syntax error with the Expression
> +
> +**/
> +EFI_STATUS
> +EvaluateHiiExpression (
> + IN HII_FORMSET *FormSet,
> + IN HII_FORM *Form,
> + IN OUT HII_EXPRESSION *Expression
> + );
> +
> +/**
> + Retrieve dependencies within an expression. These dependencies can
> express how
> + this expression will be evaluated.
> +
> + @param[in] Expression Expression to retrieve dependencies.
> +
> + @retval EFI_SUCCESS The dependencies were successfully retrieved.
> + @retval EFI_OUT_OF_RESOURCES There is not enough system memory.
> +
> +**/
> +EFI_STATUS
> +GetHiiExpressionDependency (
> + IN HII_EXPRESSION *Expression
> + );
> +
> +/**
> + Get default value of question.
> +
> + @param[in] FormSet The form set.
> + @param[in] Form The form.
> + @param[in] Question The question.
> + @param[in] DefaultId The Class of the default.
> + @param[out] DefaultValue The default value of given question.
> +
> + @retval EFI_SUCCESS Question is reset to default value.
> +
> +**/
> +EFI_STATUS
> +GetQuestionDefault (
> + IN HII_FORMSET *FormSet,
> + IN HII_FORM *Form,
> + IN HII_STATEMENT *Question,
> + IN UINT16 DefaultId,
> + OUT HII_STATEMENT_VALUE *DefaultValue
> + );
> +
> +/**
> + Return the result of the expression list. Check the expression list and
> + return the highest priority express result.
> + Priority: DisableIf > SuppressIf > GrayOutIf > FALSE
> +
> + @param[in] ExpList The input expression list.
> + @param[in] Evaluate Whether need to evaluate the expression first.
> + @param[in] FormSet FormSet associated with this expression.
> + @param[in] Form Form associated with this expression.
> +
> + @retval EXPRESS_RESULT Return the higher priority express result.
> + DisableIf > SuppressIf > GrayOutIf > FALSE
> +
> +**/
> +EXPRESS_RESULT
> +EvaluateExpressionList (
> + IN HII_EXPRESSION_LIST *ExpList,
> + IN BOOLEAN Evaluate,
> + IN HII_FORMSET *FormSet OPTIONAL,
> + IN HII_FORM *Form OPTIONAL
> + );
> +
> +#endif // HII_UTILITY_LIB_
> diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiExpression.h
> b/RedfishPkg/Library/HiiUtilityLib/HiiExpression.h
> new file mode 100644
> index 000000000000..dda96ada607e
> --- /dev/null
> +++ b/RedfishPkg/Library/HiiUtilityLib/HiiExpression.h
> @@ -0,0 +1,191 @@
> +/** @file
> + Definitions of Hii Expression.
> +
> + Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> + (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
> + Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights
> reserved.
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef HII_EXPRESSION_H_
> +#define HII_EXPRESSION_H_
> +
> +#include <Library/HiiUtilityLib.h>
> +
> +/**
> + Get the expression list count.
> +
> + @param[in] Level Which type this expression belong to. Form,
> + statement or option?
> +
> + @retval >=0 The expression count
> + @retval -1 Input parameter error.
> +
> +**/
> +INTN
> +GetConditionalExpressionCount (
> + IN EXPRESS_LEVEL Level
> + );
> +
> +/**
> + Get the expression Buffer pointer.
> +
> + @param[in] Level Which type this expression belong to. Form,
> + statement or option?
> +
> + @retval The start pointer of the expression buffer or NULL.
> +
> +**/
> +HII_EXPRESSION **
> +GetConditionalExpressionList (
> + IN EXPRESS_LEVEL Level
> + );
> +
> +/**
> + Push the expression options onto the Stack.
> +
> + @param[in] Pointer Pointer to the current expression.
> + @param[in] Level Which type this expression belong to. Form,
> + statement or option?
> +
> + @retval EFI_SUCCESS The value was pushed onto the stack.
> + @retval EFI_OUT_OF_RESOURCES There is not enough system memory
> to grow the stack.
> +
> +**/
> +EFI_STATUS
> +PushConditionalExpression (
> + IN HII_EXPRESSION *Pointer,
> + IN EXPRESS_LEVEL Level
> + );
> +
> +/**
> + Pop the expression options from the Stack
> +
> + @param[in] Level Which type this expression belong to. Form,
> + statement or option?
> +
> + @retval EFI_SUCCESS The value was pushed onto the stack.
> + @retval EFI_OUT_OF_RESOURCES There is not enough system memory
> to grow the stack.
> +
> +**/
> +EFI_STATUS
> +PopConditionalExpression (
> + IN EXPRESS_LEVEL Level
> + );
> +
> +/**
> + Reset stack pointer to begin of the stack.
> +
> +**/
> +VOID
> +ResetCurrentExpressionStack (
> + VOID
> + );
> +
> +/**
> + Push current expression onto the Stack
> +
> + @param[in] Pointer Pointer to current expression.
> +
> + @retval EFI_SUCCESS The value was pushed onto the stack.
> + @retval EFI_OUT_OF_RESOURCES There is not enough system memory
> to grow the stack.
> +
> +**/
> +EFI_STATUS
> +PushCurrentExpression (
> + IN VOID *Pointer
> + );
> +
> +/**
> + Pop current expression from the Stack
> +
> + @param[in] Pointer Pointer to current expression to be pop.
> +
> + @retval EFI_SUCCESS The value was pushed onto the stack.
> + @retval EFI_OUT_OF_RESOURCES There is not enough system memory
> to grow the stack.
> +
> +**/
> +EFI_STATUS
> +PopCurrentExpression (
> + OUT VOID **Pointer
> + );
> +
> +/**
> + Reset stack pointer to begin of the stack.
> +
> +**/
> +VOID
> +ResetMapExpressionListStack (
> + VOID
> + );
> +
> +/**
> + Push the list of map expression onto the Stack
> +
> + @param[in] Pointer Pointer to the list of map expression to be
> pushed.
> +
> + @retval EFI_SUCCESS The value was pushed onto the stack.
> + @retval EFI_OUT_OF_RESOURCES There is not enough system memory
> to grow the stack.
> +
> +**/
> +EFI_STATUS
> +PushMapExpressionList (
> + IN VOID *Pointer
> + );
> +
> +/**
> + Pop the list of map expression from the Stack
> +
> + @param[in] Pointer Pointer to the list of map expression to be pop.
> +
> + @retval EFI_SUCCESS The value was pushed onto the stack.
> + @retval EFI_OUT_OF_RESOURCES There is not enough system memory
> to grow the stack.
> +
> +**/
> +EFI_STATUS
> +PopMapExpressionList (
> + OUT VOID **Pointer
> + );
> +
> +/**
> + Reset stack pointer to begin of the stack.
> +
> +**/
> +VOID
> +ResetScopeStack (
> + VOID
> + );
> +
> +/**
> + Push an Operand onto the Stack
> +
> + @param[in] Operand Operand to push.
> +
> + @retval EFI_SUCCESS The value was pushed onto the stack.
> + @retval EFI_OUT_OF_RESOURCES There is not enough system memory
> to grow the
> + stack.
> +
> +**/
> +EFI_STATUS
> +PushScope (
> + IN UINT8 Operand
> + );
> +
> +/**
> + Pop an Operand from the Stack
> +
> + @param[out] Operand Operand to pop.
> +
> + @retval EFI_SUCCESS The value was pushed onto the stack.
> + @retval EFI_OUT_OF_RESOURCES There is not enough system memory
> to grow the
> + stack.
> +
> +**/
> +EFI_STATUS
> +PopScope (
> + OUT UINT8 *Operand
> + );
> +
> +#endif
> diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiInternal.h
> b/RedfishPkg/Library/HiiUtilityLib/HiiInternal.h
> new file mode 100644
> index 000000000000..e68a61f8b27d
> --- /dev/null
> +++ b/RedfishPkg/Library/HiiUtilityLib/HiiInternal.h
> @@ -0,0 +1,376 @@
> +/** @file
> + HII internal header file.
> +
> + Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> + (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
> + Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef HII_INTERNAL_H_
> +#define HII_INTERNAL_H_
> +
> +#include <Uefi.h>
> +
> +#include <Protocol/UnicodeCollation.h>
> +#include <Protocol/HiiConfigRouting.h>
> +#include <Protocol/HiiDatabase.h>
> +#include <Protocol/UserManager.h>
> +#include <Protocol/DevicePathFromText.h>
> +#include <Protocol/RegularExpressionProtocol.h>
> +
> +#include <Guid/MdeModuleHii.h>
> +#include <Guid/ZeroGuid.h>
> +#include <Guid/HiiPlatformSetupFormset.h>
> +#include <Guid/HiiFormMapMethodGuid.h>
> +
> +#include <Library/PrintLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/HiiLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/UefiLib.h>
> +
> +#include "HiiExpression.h"
> +#include <Library/HiiUtilityLib.h>
> +
> +#define EXPRESSION_STACK_SIZE_INCREMENT 0x100
> +#define EFI_IFR_SPECIFICATION_VERSION (UINT16)
> (((EFI_SYSTEM_TABLE_REVISION >> 16) << 8) |
> (((EFI_SYSTEM_TABLE_REVISION & 0xFFFF) / 10) << 4) |
> ((EFI_SYSTEM_TABLE_REVISION & 0xFFFF) % 10))
> +
> +///
> +/// Definition of HII_FORM_CONFIG_REQUEST
> +//
> +typedef struct {
> + UINTN Signature;
> + LIST_ENTRY Link;
> +
> + CHAR16 *ConfigRequest; ///< <ConfigRequest> = <ConfigHdr> +
> <RequestElement>
> + CHAR16 *ConfigAltResp; ///< Alt config response string for this
> ConfigRequest.
> + UINTN ElementCount; ///< Number of <RequestElement> in the
> <ConfigRequest>
> + UINTN SpareStrLen;
> + CHAR16 *RestoreConfigRequest; ///< When submit form fail, the
> element need to be restored
> + CHAR16 *SyncConfigRequest; ///< When submit form fail, the
> element need to be synced
> +
> + HII_FORMSET_STORAGE *Storage;
> +} HII_FORM_CONFIG_REQUEST;
> +
> +#define HII_FORM_CONFIG_REQUEST_SIGNATURE SIGNATURE_32 ('F', 'C',
> 'R', 'S')
> +#define HII_FORM_CONFIG_REQUEST_FROM_LINK(a) CR (a,
> HII_FORM_CONFIG_REQUEST, Link,
> HII_FORM_CONFIG_REQUEST_SIGNATURE)
> +
> +///
> +/// Incremental string length of ConfigRequest
> +///
> +#define CONFIG_REQUEST_STRING_INCREMENTAL 1024
> +
> +/**
> + Allocate new memory and then copy the Unicode string Source to
> Destination.
> +
> + @param[in,out] Dest Location to copy string
> + @param[in] Src String to copy
> +
> +**/
> +VOID
> +NewStringCopy (
> + IN OUT CHAR16 **Dest,
> + IN CHAR16 *Src
> + );
> +
> +/**
> + Set Value of given Name in a NameValue Storage.
> +
> + @param[in] Storage The NameValue Storage.
> + @param[in] Name The Name.
> + @param[in] Value The Value to set.
> + @param[out] ReturnNode The node use the input name.
> +
> + @retval EFI_SUCCESS Value found for given Name.
> + @retval EFI_NOT_FOUND No such Name found in NameValue storage.
> +
> +**/
> +EFI_STATUS
> +SetValueByName (
> + IN HII_FORMSET_STORAGE *Storage,
> + IN CHAR16 *Name,
> + IN CHAR16 *Value,
> + OUT HII_NAME_VALUE_NODE **ReturnNode
> + );
> +
> +/**
> + Get bit field value from the buffer and then set the value for the question.
> + Note: Data type UINT32 can cover all the bit field value.
> +
> + @param[in] Question The question refer to bit field.
> + @param[in] Buffer Point to the buffer which the question value get
> from.
> + @param[out] QuestionValue The Question Value retrieved from Bits.
> +
> +**/
> +VOID
> +GetBitsQuestionValue (
> + IN HII_STATEMENT *Question,
> + IN UINT8 *Buffer,
> + OUT HII_STATEMENT_VALUE *QuestionValue
> + );
> +
> +/**
> + Set bit field value to the buffer.
> + Note: Data type UINT32 can cover all the bit field value.
> +
> + @param[in] Question The question refer to bit field.
> + @param[in,out] Buffer Point to the buffer which the question value
> set to.
> + @param[in] Value The bit field value need to set.
> +
> +**/
> +VOID
> +SetBitsQuestionValue (
> + IN HII_STATEMENT *Question,
> + IN OUT UINT8 *Buffer,
> + IN UINT32 Value
> + );
> +
> +/**
> + Convert the buffer value to HiiValue.
> +
> + @param[in] Question The question.
> + @param[in] Value Unicode buffer save the question value.
> + @param[out] QuestionValue The Question Value retrieved from
> Buffer.
> +
> + @retval Status whether convert the value success.
> +
> +**/
> +EFI_STATUS
> +BufferToQuestionValue (
> + IN HII_STATEMENT *Question,
> + IN CHAR16 *Value,
> + OUT HII_STATEMENT_VALUE *QuestionValue
> + );
> +
> +/**
> + Get the string based on the StringId and HII Package List Handle.
> +
> + @param[in] Token The String's ID.
> + @param[in] HiiHandle The package list in the HII database to search
> for
> + the specified string.
> +
> + @return The output string.
> +
> +**/
> +CHAR16 *
> +GetTokenString (
> + IN EFI_STRING_ID Token,
> + IN EFI_HII_HANDLE HiiHandle
> + );
> +
> +/**
> + Converts the unicode character of the string from uppercase to lowercase.
> + This is a internal function.
> +
> + @param[in] ConfigString String to be converted
> +
> +**/
> +VOID
> +EFIAPI
> +HiiStringToLowercase (
> + IN EFI_STRING ConfigString
> + );
> +
> +/**
> + Evaluate if the result is a non-zero value.
> +
> + @param[in] Result The result to be evaluated.
> +
> + @retval TRUE It is a non-zero value.
> + @retval FALSE It is a zero value.
> +
> +**/
> +BOOLEAN
> +IsHiiValueTrue (
> + IN EFI_HII_VALUE *Result
> + );
> +
> +/**
> + Set a new string to string package.
> +
> + @param[in] String A pointer to the Null-terminated Unicode string
> + to add or update in the String Package associated
> + with HiiHandle.
> + @param[in] HiiHandle A handle that was previously registered in the
> + HII Database.
> +
> + @return the Id for this new string.
> +
> +**/
> +EFI_STRING_ID
> +NewHiiString (
> + IN CHAR16 *String,
> + IN EFI_HII_HANDLE HiiHandle
> + );
> +
> +/**
> + Perform nosubmitif check for a Form.
> +
> + @param[in] FormSet FormSet data structure.
> + @param[in] Form Form data structure.
> + @param[in] Question The Question to be validated.
> +
> + @retval EFI_SUCCESS Form validation pass.
> + @retval other Form validation failed.
> +
> +**/
> +EFI_STATUS
> +ValidateNoSubmit (
> + IN HII_FORMSET *FormSet,
> + IN HII_FORM *Form,
> + IN HII_STATEMENT *Question
> + );
> +
> +/**
> + Perform NoSubmit check for each Form in FormSet.
> +
> + @param[in] FormSet FormSet data structure.
> + @param[in,out] CurrentForm Current input form data structure.
> + @param[out] Statement The statement for this check.
> +
> + @retval EFI_SUCCESS Form validation pass.
> + @retval other Form validation failed.
> +
> +**/
> +EFI_STATUS
> +NoSubmitCheck (
> + IN HII_FORMSET *FormSet,
> + IN OUT HII_FORM **CurrentForm,
> + OUT HII_STATEMENT **Statement
> + );
> +
> +/**
> + Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
> +
> + @param[in] Storage The Storage to be converted.
> + @param[in] ConfigResp The returned <ConfigResp>.
> + @param[in] ConfigRequest The ConfigRequest string.
> +
> + @retval EFI_SUCCESS Convert success.
> + @retval EFI_INVALID_PARAMETER Incorrect storage type.
> +
> +**/
> +EFI_STATUS
> +StorageToConfigResp (
> + IN HII_FORMSET_STORAGE *Storage,
> + IN CHAR16 **ConfigResp,
> + IN CHAR16 *ConfigRequest
> + );
> +
> +/**
> + Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
> +
> + @param[in] Storage The Storage to receive the settings.
> + @param[in] ConfigResp The <ConfigResp> to be converted.
> +
> + @retval EFI_SUCCESS Convert success.
> + @retval EFI_INVALID_PARAMETER Incorrect storage type.
> +
> +**/
> +EFI_STATUS
> +ConfigRespToStorage (
> + IN HII_FORMSET_STORAGE *Storage,
> + IN CHAR16 *ConfigResp
> + );
> +
> +/**
> + Fetch the Ifr binary data of a FormSet.
> +
> + @param[in] Handle PackageList Handle
> + @param[in,out] FormSetGuid On input, GUID or class GUID of a formset.
> If not
> + specified (NULL or zero GUID), take the first
> + FormSet with class GUID
> EFI_HII_PLATFORM_SETUP_FORMSET_GUID
> + found in package list.
> + On output, GUID of the formset found(if not NULL).
> + @param[out] BinaryLength The length of the FormSet IFR binary.
> + @param[out] BinaryData The buffer designed to receive the FormSet.
> +
> + @retval EFI_SUCCESS Buffer filled with the requested FormSet.
> + BufferLength was updated.
> + @retval EFI_INVALID_PARAMETER The handle is unknown.
> + @retval EFI_NOT_FOUND A form or FormSet on the requested handle
> cannot
> + be found with the requested FormId.
> +
> +**/
> +EFI_STATUS
> +GetIfrBinaryData (
> + IN EFI_HII_HANDLE Handle,
> + IN OUT EFI_GUID *FormSetGuid,
> + OUT UINTN *BinaryLength,
> + OUT UINT8 **BinaryData
> + );
> +
> +/**
> + Fill storage with settings requested from Configuration Driver.
> +
> + @param[in] FormSet FormSet data structure.
> + @param[in] Storage Buffer Storage.
> +
> +**/
> +VOID
> +LoadFormSetStorage (
> + IN HII_FORMSET *FormSet,
> + IN HII_FORMSET_STORAGE *Storage
> + );
> +
> +/**
> + Free resources of a Form.
> +
> + @param[in] FormSet Pointer of the FormSet
> + @param[in,out] Form Pointer of the Form.
> +
> +**/
> +VOID
> +DestroyForm (
> + IN HII_FORMSET *FormSet,
> + IN OUT HII_FORM *Form
> + );
> +
> +/**
> + Get formset storage based on the input varstoreid info.
> +
> + @param[in] FormSet Pointer of the current FormSet.
> + @param[in] VarStoreId Varstore ID info.
> +
> + @return Pointer to a HII_FORMSET_STORAGE data structure.
> +
> +**/
> +HII_FORMSET_STORAGE *
> +GetFstStgFromVarId (
> + IN HII_FORMSET *FormSet,
> + IN EFI_VARSTORE_ID VarStoreId
> + );
> +
> +/**
> + Zero extend integer/boolean/date/time to UINT64 for comparing.
> +
> + @param[in] Value HII Value to be converted.
> +
> +**/
> +VOID
> +ExtendValueToU64 (
> + IN HII_STATEMENT_VALUE *Value
> + );
> +
> +/**
> + Parse opcodes in the formset IFR binary.
> +
> + @param[in] FormSet Pointer of the FormSet data structure.
> +
> + @retval EFI_SUCCESS Opcode parse success.
> + @retval Other Opcode parse fail.
> +
> +**/
> +EFI_STATUS
> +ParseOpCodes (
> + IN HII_FORMSET *FormSet
> + );
> +
> +#endif // HII_INTERNAL_H_
> diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiExpression.c
> b/RedfishPkg/Library/HiiUtilityLib/HiiExpression.c
> new file mode 100644
> index 000000000000..c36c2416426b
> --- /dev/null
> +++ b/RedfishPkg/Library/HiiUtilityLib/HiiExpression.c
> @@ -0,0 +1,1439 @@
> +/** @file
> + The implementation of HII expression.
> +
> + Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> + (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
> + Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights
> reserved.
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +#include "HiiInternal.h"
> +
> +//
> +// Global stack used to evaluate boolean expressions
> +//
> +EFI_HII_VALUE *mOpCodeScopeStack = NULL;
> +EFI_HII_VALUE *mOpCodeScopeStackEnd = NULL;
> +EFI_HII_VALUE *mOpCodeScopeStackPointer = NULL;
> +
> +//
> +// Stack used for Suppressif/grayoutif/disableif expression list.
> +//
> +HII_EXPRESSION **mFormExpressionStack = NULL;
> +HII_EXPRESSION **mFormExpressionEnd = NULL;
> +HII_EXPRESSION **mFormExpressionPointer = NULL;
> +
> +HII_EXPRESSION **mStatementExpressionStack = NULL;
> +HII_EXPRESSION **mStatementExpressionEnd = NULL;
> +HII_EXPRESSION **mStatementExpressionPointer = NULL;
> +
> +HII_EXPRESSION **mOptionExpressionStack = NULL;
> +HII_EXPRESSION **mOptionExpressionEnd = NULL;
> +HII_EXPRESSION **mOptionExpressionPointer = NULL;
> +
> +//
> +// Stack used for the sub expresion in map expression.
> +//
> +EFI_HII_VALUE *mCurrentExpressionStack = NULL;
> +EFI_HII_VALUE *mCurrentExpressionEnd = NULL;
> +EFI_HII_VALUE *mCurrentExpressionPointer = NULL;
> +
> +//
> +// Stack used for the map expression list.
> +//
> +EFI_HII_VALUE *mMapExpressionListStack = NULL;
> +EFI_HII_VALUE *mMapExpressionListEnd = NULL;
> +EFI_HII_VALUE *mMapExpressionListPointer = NULL;
> +
> +//
> +// Stack used for dependency expression.
> +//
> +HII_DEPENDENCY_EXPRESSION **mExpressionDependencyStack = NULL;
> +HII_DEPENDENCY_EXPRESSION **mExpressionDependencyEnd = NULL;
> +HII_DEPENDENCY_EXPRESSION **mExpressionDependencyPointer = NULL;
> +
> +/**
> + Grow size of the stack.
> +
> + This is an internal function.
> +
> + @param Stack On input: old stack; On output: new stack
> + @param StackPtr On input: old stack pointer; On output: new stack
> + pointer
> + @param StackEnd On input: old stack end; On output: new stack
> end
> +
> + @retval EFI_SUCCESS Grow stack success.
> + @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.
> +
> +**/
> +EFI_STATUS
> +GrowStack (
> + IN OUT EFI_HII_VALUE **Stack,
> + IN OUT EFI_HII_VALUE **StackPtr,
> + IN OUT EFI_HII_VALUE **StackEnd
> + )
> +{
> + UINTN Size;
> + EFI_HII_VALUE *NewStack;
> +
> + Size = EXPRESSION_STACK_SIZE_INCREMENT;
> + if (*StackPtr != NULL) {
> + Size = Size + (*StackEnd - *Stack);
> + }
> +
> + NewStack = AllocatePool (Size * sizeof (EFI_HII_VALUE));
> + if (NewStack == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + if (*StackPtr != NULL) {
> + //
> + // Copy from Old Stack to the New Stack
> + //
> + CopyMem (
> + NewStack,
> + *Stack,
> + (*StackEnd - *Stack) * sizeof (EFI_HII_VALUE)
> + );
> +
> + //
> + // Free The Old Stack
> + //
> + FreePool (*Stack);
> + }
> +
> + //
> + // Make the Stack pointer point to the old data in the new stack
> + //
> + *StackPtr = NewStack + (*StackPtr - *Stack);
> + *Stack = NewStack;
> + *StackEnd = NewStack + Size;
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Push an element onto the Boolean Stack.
> +
> + @param Stack On input: old stack; On output: new stack
> + @param StackPtr On input: old stack pointer; On output: new stack
> + pointer
> + @param StackEnd On input: old stack end; On output: new stack
> end
> + @param Data Data to push.
> +
> + @retval EFI_SUCCESS Push stack success.
> +
> +**/
> +EFI_STATUS
> +PushStack (
> + IN OUT EFI_HII_VALUE **Stack,
> + IN OUT EFI_HII_VALUE **StackPtr,
> + IN OUT EFI_HII_VALUE **StackEnd,
> + IN EFI_HII_VALUE *Data
> + )
> +{
> + EFI_STATUS Status;
> +
> + //
> + // Check for a stack overflow condition
> + //
> + if (*StackPtr >= *StackEnd) {
> + //
> + // Grow the stack
> + //
> + Status = GrowStack (Stack, StackPtr, StackEnd);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> + }
> +
> + //
> + // Push the item onto the stack
> + //
> + CopyMem (*StackPtr, Data, sizeof (EFI_HII_VALUE));
> + if (Data->Type == EFI_IFR_TYPE_BUFFER) {
> + (*StackPtr)->Buffer = AllocateCopyPool (Data->BufferLen, Data->Buffer);
> + if ((*StackPtr)->Buffer == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> + }
> +
> + *StackPtr = *StackPtr + 1;
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Pop an element from the stack.
> +
> + @param Stack On input: old stack
> + @param StackPtr On input: old stack pointer; On output: new stack
> pointer
> + @param Data Data to pop.
> +
> + @retval EFI_SUCCESS The value was popped onto the stack.
> + @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
> +
> +**/
> +EFI_STATUS
> +PopStack (
> + IN EFI_HII_VALUE *Stack,
> + IN OUT EFI_HII_VALUE **StackPtr,
> + OUT EFI_HII_VALUE *Data
> + )
> +{
> + //
> + // Check for a stack underflow condition
> + //
> + if (*StackPtr == Stack) {
> + return EFI_ACCESS_DENIED;
> + }
> +
> + //
> + // Pop the item off the stack
> + //
> + *StackPtr = *StackPtr - 1;
> + CopyMem (Data, *StackPtr, sizeof (EFI_HII_VALUE));
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Reset stack pointer to begin of the stack.
> +
> +**/
> +VOID
> +ResetCurrentExpressionStack (
> + VOID
> + )
> +{
> + mCurrentExpressionPointer = mCurrentExpressionStack;
> + mFormExpressionPointer = mFormExpressionStack;
> + mStatementExpressionPointer = mStatementExpressionStack;
> + mOptionExpressionPointer = mOptionExpressionStack;
> +}
> +
> +/**
> + Push current expression onto the Stack
> +
> + @param Pointer Pointer to current expression.
> +
> + @retval EFI_SUCCESS The value was pushed onto the stack.
> + @retval EFI_OUT_OF_RESOURCES There is not enough system memory
> to grow the stack.
> +
> +**/
> +EFI_STATUS
> +PushCurrentExpression (
> + IN VOID *Pointer
> + )
> +{
> + EFI_HII_VALUE Data;
> +
> + Data.Type = EFI_IFR_TYPE_NUM_SIZE_64;
> + Data.Value.u64 = (UINT64)(UINTN)Pointer;
> +
> + return PushStack (
> + &mCurrentExpressionStack,
> + &mCurrentExpressionPointer,
> + &mCurrentExpressionEnd,
> + &Data
> + );
> +}
> +
> +/**
> + Pop current expression from the Stack
> +
> + @param Pointer Pointer to current expression to be pop.
> +
> + @retval EFI_SUCCESS The value was pushed onto the stack.
> + @retval EFI_OUT_OF_RESOURCES There is not enough system memory
> to grow the stack.
> +
> +**/
> +EFI_STATUS
> +PopCurrentExpression (
> + OUT VOID **Pointer
> + )
> +{
> + EFI_STATUS Status;
> + EFI_HII_VALUE Data;
> +
> + Status = PopStack (
> + mCurrentExpressionStack,
> + &mCurrentExpressionPointer,
> + &Data
> + );
> +
> + *Pointer = (VOID *)(UINTN)Data.Value.u64;
> +
> + return Status;
> +}
> +
> +/**
> + Reset stack pointer to begin of the stack.
> +
> +**/
> +VOID
> +ResetMapExpressionListStack (
> + VOID
> + )
> +{
> + mMapExpressionListPointer = mMapExpressionListStack;
> +}
> +
> +/**
> + Grow size of the stack.
> +
> + This is an internal function.
> +
> + @param Stack On input: old stack; On output: new stack
> + @param StackPtr On input: old stack pointer; On output: new stack
> + pointer
> + @param StackEnd On input: old stack end; On output: new stack
> end
> + @param MemberSize The stack member size.
> +
> + @retval EFI_SUCCESS Grow stack success.
> + @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.
> +
> +**/
> +EFI_STATUS
> +GrowConditionalStack (
> + IN OUT HII_EXPRESSION ***Stack,
> + IN OUT HII_EXPRESSION ***StackPtr,
> + IN OUT HII_EXPRESSION ***StackEnd,
> + IN UINTN MemberSize
> + )
> +{
> + UINTN Size;
> + HII_EXPRESSION **NewStack;
> +
> + Size = EXPRESSION_STACK_SIZE_INCREMENT;
> + if (*StackPtr != NULL) {
> + Size = Size + (*StackEnd - *Stack);
> + }
> +
> + NewStack = AllocatePool (Size * MemberSize);
> + if (NewStack == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + if (*StackPtr != NULL) {
> + //
> + // Copy from Old Stack to the New Stack
> + //
> + CopyMem (
> + NewStack,
> + *Stack,
> + (*StackEnd - *Stack) * MemberSize
> + );
> +
> + //
> + // Free The Old Stack
> + //
> + FreePool (*Stack);
> + }
> +
> + //
> + // Make the Stack pointer point to the old data in the new stack
> + //
> + *StackPtr = NewStack + (*StackPtr - *Stack);
> + *Stack = NewStack;
> + *StackEnd = NewStack + Size;
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Push an element onto the Stack.
> +
> + @param Stack On input: old stack; On output: new stack
> + @param StackPtr On input: old stack pointer; On output: new stack
> + pointer
> + @param StackEnd On input: old stack end; On output: new stack
> end
> + @param Data Data to push.
> +
> + @retval EFI_SUCCESS Push stack success.
> +
> +**/
> +EFI_STATUS
> +PushConditionalStack (
> + IN OUT HII_EXPRESSION ***Stack,
> + IN OUT HII_EXPRESSION ***StackPtr,
> + IN OUT HII_EXPRESSION ***StackEnd,
> + IN HII_EXPRESSION **Data
> + )
> +{
> + EFI_STATUS Status;
> +
> + //
> + // Check for a stack overflow condition
> + //
> + if (*StackPtr >= *StackEnd) {
> + //
> + // Grow the stack
> + //
> + Status = GrowConditionalStack (Stack, StackPtr, StackEnd, sizeof
> (HII_EXPRESSION *));
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> + }
> +
> + //
> + // Push the item onto the stack
> + //
> + CopyMem (*StackPtr, Data, sizeof (HII_EXPRESSION *));
> + *StackPtr = *StackPtr + 1;
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Pop an element from the stack.
> +
> + @param Stack On input: old stack
> + @param StackPtr On input: old stack pointer; On output: new stack
> pointer
> + @param Data Data to pop.
> +
> + @retval EFI_SUCCESS The value was popped onto the stack.
> + @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
> +
> +**/
> +EFI_STATUS
> +PopConditionalStack (
> + IN HII_EXPRESSION **Stack,
> + IN OUT HII_EXPRESSION ***StackPtr,
> + OUT HII_EXPRESSION **Data
> + )
> +{
> + //
> + // Check for a stack underflow condition
> + //
> + if (*StackPtr == Stack) {
> + return EFI_ACCESS_DENIED;
> + }
> +
> + //
> + // Pop the item off the stack
> + //
> + *StackPtr = *StackPtr - 1;
> + CopyMem (Data, *StackPtr, sizeof (HII_EXPRESSION *));
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Get the expression list count.
> +
> + @param Level Which type this expression belong to. Form,
> + statement or option?
> +
> + @retval >=0 The expression count
> + @retval -1 Input parameter error.
> +
> +**/
> +INTN
> +GetConditionalExpressionCount (
> + IN EXPRESS_LEVEL Level
> + )
> +{
> + switch (Level) {
> + case ExpressForm:
> + return mFormExpressionPointer - mFormExpressionStack;
> + case ExpressStatement:
> + return mStatementExpressionPointer - mStatementExpressionStack;
> + case ExpressOption:
> + return mOptionExpressionPointer - mOptionExpressionStack;
> + default:
> + ASSERT (FALSE);
> + return -1;
> + }
> +}
> +
> +/**
> + Get the expression Buffer pointer.
> +
> + @param Level Which type this expression belong to. Form,
> + statement or option?
> +
> + @retval The start pointer of the expression buffer or NULL.
> +
> +**/
> +HII_EXPRESSION **
> +GetConditionalExpressionList (
> + IN EXPRESS_LEVEL Level
> + )
> +{
> + switch (Level) {
> + case ExpressForm:
> + return mFormExpressionStack;
> + case ExpressStatement:
> + return mStatementExpressionStack;
> + case ExpressOption:
> + return mOptionExpressionStack;
> + default:
> + ASSERT (FALSE);
> + return NULL;
> + }
> +}
> +
> +/**
> + Push the expression options onto the Stack.
> +
> + @param Pointer Pointer to the current expression.
> + @param Level Which type this expression belong to. Form,
> + statement or option?
> +
> + @retval EFI_SUCCESS The value was pushed onto the stack.
> + @retval EFI_OUT_OF_RESOURCES There is not enough system memory
> to grow the stack.
> +
> +**/
> +EFI_STATUS
> +PushConditionalExpression (
> + IN HII_EXPRESSION *Pointer,
> + IN EXPRESS_LEVEL Level
> + )
> +{
> + switch (Level) {
> + case ExpressForm:
> + return PushConditionalStack (
> + &mFormExpressionStack,
> + &mFormExpressionPointer,
> + &mFormExpressionEnd,
> + &Pointer
> + );
> + case ExpressStatement:
> + return PushConditionalStack (
> + &mStatementExpressionStack,
> + &mStatementExpressionPointer,
> + &mStatementExpressionEnd,
> + &Pointer
> + );
> + case ExpressOption:
> + return PushConditionalStack (
> + &mOptionExpressionStack,
> + &mOptionExpressionPointer,
> + &mOptionExpressionEnd,
> + &Pointer
> + );
> + default:
> + ASSERT (FALSE);
> + return EFI_INVALID_PARAMETER;
> + }
> +}
> +
> +/**
> + Pop the expression options from the Stack
> +
> + @param Level Which type this expression belong to. Form,
> + statement or option?
> +
> + @retval EFI_SUCCESS The value was pushed onto the stack.
> + @retval EFI_OUT_OF_RESOURCES There is not enough system memory
> to grow the stack.
> +
> +**/
> +EFI_STATUS
> +PopConditionalExpression (
> + IN EXPRESS_LEVEL Level
> + )
> +{
> + HII_EXPRESSION *Pointer;
> +
> + switch (Level) {
> + case ExpressForm:
> + return PopConditionalStack (
> + mFormExpressionStack,
> + &mFormExpressionPointer,
> + &Pointer
> + );
> +
> + case ExpressStatement:
> + return PopConditionalStack (
> + mStatementExpressionStack,
> + &mStatementExpressionPointer,
> + &Pointer
> + );
> +
> + case ExpressOption:
> + return PopConditionalStack (
> + mOptionExpressionStack,
> + &mOptionExpressionPointer,
> + &Pointer
> + );
> +
> + default:
> + ASSERT (FALSE);
> + return EFI_INVALID_PARAMETER;
> + }
> +}
> +
> +/**
> + Push the list of map expression onto the Stack
> +
> + @param Pointer Pointer to the list of map expression to be pushed.
> +
> + @retval EFI_SUCCESS The value was pushed onto the stack.
> + @retval EFI_OUT_OF_RESOURCES There is not enough system memory
> to grow the stack.
> +
> +**/
> +EFI_STATUS
> +PushMapExpressionList (
> + IN VOID *Pointer
> + )
> +{
> + EFI_HII_VALUE Data;
> +
> + Data.Type = EFI_IFR_TYPE_NUM_SIZE_64;
> + Data.Value.u64 = (UINT64)(UINTN)Pointer;
> +
> + return PushStack (
> + &mMapExpressionListStack,
> + &mMapExpressionListPointer,
> + &mMapExpressionListEnd,
> + &Data
> + );
> +}
> +
> +/**
> + Pop the list of map expression from the Stack
> +
> + @param Pointer Pointer to the list of map expression to be pop.
> +
> + @retval EFI_SUCCESS The value was pushed onto the stack.
> + @retval EFI_OUT_OF_RESOURCES There is not enough system memory
> to grow the stack.
> +
> +**/
> +EFI_STATUS
> +PopMapExpressionList (
> + OUT VOID **Pointer
> + )
> +{
> + EFI_STATUS Status;
> + EFI_HII_VALUE Data;
> +
> + Status = PopStack (
> + mMapExpressionListStack,
> + &mMapExpressionListPointer,
> + &Data
> + );
> +
> + *Pointer = (VOID *)(UINTN)Data.Value.u64;
> +
> + return Status;
> +}
> +
> +/**
> + Reset stack pointer to begin of the stack.
> +
> +**/
> +VOID
> +ResetScopeStack (
> + VOID
> + )
> +{
> + mOpCodeScopeStackPointer = mOpCodeScopeStack;
> +}
> +
> +/**
> + Push an Operand onto the Stack
> +
> + @param Operand Operand to push.
> +
> + @retval EFI_SUCCESS The value was pushed onto the stack.
> + @retval EFI_OUT_OF_RESOURCES There is not enough system memory
> to grow the
> + stack.
> +
> +**/
> +EFI_STATUS
> +PushScope (
> + IN UINT8 Operand
> + )
> +{
> + EFI_HII_VALUE Data;
> +
> + Data.Type = EFI_IFR_TYPE_NUM_SIZE_8;
> + Data.Value.u8 = Operand;
> +
> + return PushStack (
> + &mOpCodeScopeStack,
> + &mOpCodeScopeStackPointer,
> + &mOpCodeScopeStackEnd,
> + &Data
> + );
> +}
> +
> +/**
> + Pop an Operand from the Stack
> +
> + @param Operand Operand to pop.
> +
> + @retval EFI_SUCCESS The value was pushed onto the stack.
> + @retval EFI_OUT_OF_RESOURCES There is not enough system memory
> to grow the
> + stack.
> +
> +**/
> +EFI_STATUS
> +PopScope (
> + OUT UINT8 *Operand
> + )
> +{
> + EFI_STATUS Status;
> + EFI_HII_VALUE Data;
> +
> + Status = PopStack (
> + mOpCodeScopeStack,
> + &mOpCodeScopeStackPointer,
> + &Data
> + );
> +
> + *Operand = Data.Value.u8;
> +
> + return Status;
> +}
> +
> +/**
> + Grow size of the stack for Expression Dependencies.
> +
> + This is an internal function.
> +
> + @param Stack On input: old stack; On output: new stack
> + @param StackPtr On input: old stack pointer; On output: new stack
> + pointer
> + @param StackEnd On input: old stack end; On output: new stack
> end
> +
> + @retval EFI_SUCCESS Grow Dependency stack success.
> + @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.
> +
> +**/
> +EFI_STATUS
> +GrowDependencyStack (
> + IN OUT HII_DEPENDENCY_EXPRESSION ***Stack,
> + IN OUT HII_DEPENDENCY_EXPRESSION ***StackPtr,
> + IN OUT HII_DEPENDENCY_EXPRESSION ***StackEnd
> + )
> +{
> + UINTN Size;
> + HII_DEPENDENCY_EXPRESSION **NewStack;
> +
> + Size = EXPRESSION_STACK_SIZE_INCREMENT;
> + if (*StackPtr != NULL) {
> + Size = Size + (*StackEnd - *Stack);
> + }
> +
> + NewStack = AllocatePool (Size * sizeof (HII_DEPENDENCY_EXPRESSION *));
> + if (NewStack == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + if (*StackPtr != NULL) {
> + //
> + // Copy from Old Stack to the New Stack
> + //
> + CopyMem (
> + NewStack,
> + *Stack,
> + (*StackEnd - *Stack) * sizeof (HII_DEPENDENCY_EXPRESSION *)
> + );
> +
> + //
> + // Free The Old Stack
> + //
> + FreePool (*Stack);
> + }
> +
> + //
> + // Make the Stack pointer point to the old data in the new stack
> + //
> + *StackPtr = NewStack + (*StackPtr - *Stack);
> + *Stack = NewStack;
> + *StackEnd = NewStack + Size;
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Push an element onto the Stack for Expression Dependencies.
> +
> + @param Stack On input: old stack; On output: new stack
> + @param StackPtr On input: old stack pointer; On output: new stack
> + pointer
> + @param StackEnd On input: old stack end; On output: new stack
> end
> + @param Data Data to push.
> +
> + @retval EFI_SUCCESS Push stack success.
> +
> +**/
> +EFI_STATUS
> +PushDependencyStack (
> + IN OUT HII_DEPENDENCY_EXPRESSION ***Stack,
> + IN OUT HII_DEPENDENCY_EXPRESSION ***StackPtr,
> + IN OUT HII_DEPENDENCY_EXPRESSION ***StackEnd,
> + IN HII_DEPENDENCY_EXPRESSION **Data
> + )
> +{
> + EFI_STATUS Status;
> +
> + //
> + // Check for a stack overflow condition
> + //
> + if (*StackPtr >= *StackEnd) {
> + //
> + // Grow the stack
> + //
> + Status = GrowDependencyStack (Stack, StackPtr, StackEnd);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> + }
> +
> + //
> + // Push the item onto the stack
> + //
> + CopyMem (*StackPtr, Data, sizeof (HII_DEPENDENCY_EXPRESSION *));
> + *StackPtr = *StackPtr + 1;
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Pop the Expression Dependency options from the Stack
> +
> + @param Stack On input: old stack; On output: new stack
> + @param StackPtr On input: old stack pointer; On output: new stack
> + pointer
> + @param Data Data to push.
> +
> + @retval EFI_SUCCESS The value was pushed onto the stack.
> + @retval EFI_OUT_OF_RESOURCES There is not enough system memory
> to grow the stack.
> +
> +**/
> +EFI_STATUS
> +PopDependencyStack (
> + IN HII_DEPENDENCY_EXPRESSION **Stack,
> + IN OUT HII_DEPENDENCY_EXPRESSION ***StackPtr,
> + OUT HII_DEPENDENCY_EXPRESSION **Data
> + )
> +{
> + //
> + // Check for a stack underflow condition
> + //
> + if (*StackPtr == Stack) {
> + return EFI_ACCESS_DENIED;
> + }
> +
> + //
> + // Pop the item off the stack
> + //
> + *StackPtr = *StackPtr - 1;
> + CopyMem (Data, *StackPtr, sizeof (HII_DEPENDENCY_EXPRESSION *));
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Push the list of Expression Dependencies onto the Stack
> +
> + @param Pointer Pointer to the list of map expression to be pushed.
> +
> + @retval EFI_SUCCESS The value was pushed onto the stack.
> + @retval EFI_OUT_OF_RESOURCES There is not enough system memory
> to grow the stack.
> +
> +**/
> +EFI_STATUS
> +PushDependencyExpDes (
> + IN HII_DEPENDENCY_EXPRESSION **Pointer
> + )
> +{
> + return PushDependencyStack (
> + &mExpressionDependencyStack,
> + &mExpressionDependencyPointer,
> + &mExpressionDependencyEnd,
> + Pointer
> + );
> +}
> +
> +/**
> + Pop the list of Expression Dependencies from the Stack
> +
> + @param Pointer Pointer to the list of map expression to be pop.
> +
> + @retval EFI_SUCCESS The value was pushed onto the stack.
> + @retval EFI_OUT_OF_RESOURCES There is not enough system memory
> to grow the stack.
> +
> +**/
> +EFI_STATUS
> +PopDependencyExpDes (
> + OUT HII_DEPENDENCY_EXPRESSION **Pointer
> + )
> +{
> + return PopDependencyStack (
> + mExpressionDependencyStack,
> + &mExpressionDependencyPointer,
> + Pointer
> + );
> +}
> +
> +/**
> + Retrieve dependencies within an expression. These dependencies can
> express how
> + this expression will be evaluated.
> +
> + @param[in,out] Expression Expression to retrieve dependencies.
> +
> + @retval EFI_SUCCESS The dependencies were successfully retrieved.
> + @retval EFI_OUT_OF_RESOURCES There is not enough system memory.
> +
> +**/
> +EFI_STATUS
> +GetHiiExpressionDependency (
> + IN OUT HII_EXPRESSION *Expression
> + )
> +{
> + EFI_STATUS Status;
> + LIST_ENTRY *Link;
> + HII_EXPRESSION_OPCODE *ExpressionOpCode;
> + HII_DEPENDENCY_EXPRESSION *DepExpressionOpCode;
> + LIST_ENTRY *SubExpressionLink;
> + HII_EXPRESSION *SubExpression;
> + UINT8 MapPairCount;
> +
> + Link = GetFirstNode (&Expression->OpCodeListHead);
> + while (!IsNull (&Expression->OpCodeListHead, Link)) {
> + ExpressionOpCode = HII_EXPRESSION_OPCODE_FROM_LINK (Link);
> + Link = GetNextNode (&Expression->OpCodeListHead, Link);
> + Status = EFI_SUCCESS;
> +
> + DepExpressionOpCode = (HII_DEPENDENCY_EXPRESSION
> *)AllocateZeroPool (sizeof (HII_DEPENDENCY_EXPRESSION));
> + if (DepExpressionOpCode == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + switch (ExpressionOpCode->Operand) {
> + //
> + // Constant
> + //
> + case EFI_IFR_FALSE_OP:
> + case EFI_IFR_ONE_OP:
> + case EFI_IFR_ONES_OP:
> + case EFI_IFR_TRUE_OP:
> + case EFI_IFR_UINT8_OP:
> + case EFI_IFR_UINT16_OP:
> + case EFI_IFR_UINT32_OP:
> + case EFI_IFR_UINT64_OP:
> + case EFI_IFR_UNDEFINED_OP:
> + case EFI_IFR_VERSION_OP:
> + case EFI_IFR_ZERO_OP:
> + DepExpressionOpCode->ConstantExp.Operand = ExpressionOpCode-
> >Operand;
> + CopyMem (&DepExpressionOpCode->ConstantExp.Value,
> &ExpressionOpCode->ExtraData.Value, sizeof (EFI_HII_VALUE));
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + //
> + // Built-in functions
> + //
> + case EFI_IFR_DUP_OP:
> + DepExpressionOpCode->DupExp.Operand = ExpressionOpCode-
> >Operand;
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_EQ_ID_VAL_OP:
> + DepExpressionOpCode->EqIdValExp.Operand = ExpressionOpCode-
> >Operand;
> + CopyMem (&DepExpressionOpCode->EqIdValExp.QuestionId,
> &ExpressionOpCode->ExtraData.EqIdValData.QuestionId, sizeof
> (EFI_QUESTION_ID));
> + CopyMem (&DepExpressionOpCode->EqIdValExp.Value,
> &ExpressionOpCode->ExtraData.EqIdValData.Value, sizeof (EFI_HII_VALUE));
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_EQ_ID_ID_OP:
> + DepExpressionOpCode->EqIdIdExp.Operand = ExpressionOpCode-
> >Operand;
> + CopyMem (&DepExpressionOpCode->EqIdIdExp.QuestionId1,
> &ExpressionOpCode->ExtraData.EqIdIdData.QuestionId1, sizeof
> (EFI_QUESTION_ID));
> + CopyMem (&DepExpressionOpCode->EqIdIdExp.QuestionId2,
> &ExpressionOpCode->ExtraData.EqIdIdData.QuestionId2, sizeof
> (EFI_QUESTION_ID));
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_EQ_ID_VAL_LIST_OP:
> + DepExpressionOpCode->EqIdListExp.Operand = ExpressionOpCode-
> >Operand;
> + DepExpressionOpCode->EqIdListExp.ListLength = ExpressionOpCode-
> >ExtraData.EqIdListData.ListLength;
> + CopyMem (&DepExpressionOpCode->EqIdListExp.QuestionId,
> &ExpressionOpCode->ExtraData.EqIdListData.QuestionId, sizeof
> (EFI_QUESTION_ID));
> + PushDependencyExpDes (&DepExpressionOpCode);
> + DepExpressionOpCode->EqIdListExp.ValueList = AllocateCopyPool (
> + DepExpressionOpCode->EqIdListExp.ListLength
> * sizeof (UINT16),
> + ExpressionOpCode-
> >ExtraData.EqIdListData.ValueList
> + );
> + if (DepExpressionOpCode->EqIdListExp.ValueList == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_GET_OP:
> + DepExpressionOpCode->GetExp.Operand = ExpressionOpCode-
> >Operand;
> + DepExpressionOpCode->GetExp.VarStorage = ExpressionOpCode-
> >ExtraData.GetSetData.VarStorage;
> + CopyMem (&DepExpressionOpCode->GetExp.VarStoreInfo.VarName,
> &ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo.VarName, sizeof
> (EFI_STRING_ID));
> + CopyMem (&DepExpressionOpCode->GetExp.VarStoreInfo.VarOffset,
> &ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset, sizeof
> (UINT16));
> + DepExpressionOpCode->GetExp.VarStoreInfo = ExpressionOpCode-
> >ExtraData.GetSetData.VarStoreInfo;
> + if (ExpressionOpCode->ExtraData.GetSetData.ValueName != NULL) {
> + DepExpressionOpCode->GetExp.ValueName = (CHAR16
> *)AllocateCopyPool (sizeof (ExpressionOpCode-
> >ExtraData.GetSetData.ValueName), ExpressionOpCode-
> >ExtraData.GetSetData.ValueName);
> + if (DepExpressionOpCode->GetExp.ValueName == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> + }
> +
> + DepExpressionOpCode->GetExp.ValueType = ExpressionOpCode-
> >ExtraData.GetSetData.ValueType;
> + DepExpressionOpCode->GetExp.ValueWidth = ExpressionOpCode-
> >ExtraData.GetSetData.ValueWidth;
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_QUESTION_REF1_OP:
> + DepExpressionOpCode->QuestionRef1Exp.Operand =
> ExpressionOpCode->Operand;
> + CopyMem (&DepExpressionOpCode->QuestionRef1Exp.QuestionId,
> &ExpressionOpCode->ExtraData.QuestionRef1Data.QuestionId, sizeof
> (EFI_QUESTION_ID));
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_RULE_REF_OP:
> + DepExpressionOpCode->RuleRefExp.Operand = ExpressionOpCode-
> >Operand;
> + DepExpressionOpCode->RuleRefExp.RuleId = ExpressionOpCode-
> >ExtraData.RuleId;
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_STRING_REF1_OP:
> + DepExpressionOpCode->StringRef1Exp.Operand = ExpressionOpCode-
> >Operand;
> + CopyMem (&DepExpressionOpCode->StringRef1Exp.Value.Value.string,
> &ExpressionOpCode->ExtraData.Value.Value.string, sizeof (EFI_STRING_ID));
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_THIS_OP:
> + DepExpressionOpCode->ThisExp.Operand = ExpressionOpCode-
> >Operand;
> + CopyMem (&DepExpressionOpCode->ThisExp.QuestionId,
> &ExpressionOpCode->ExtraData.QuestionRef1Data.QuestionId, sizeof
> (EFI_QUESTION_ID));
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_SECURITY_OP:
> + DepExpressionOpCode->SecurityExp.Operand = ExpressionOpCode-
> >Operand;
> + CopyMem (&DepExpressionOpCode->SecurityExp.Permissions,
> &ExpressionOpCode->ExtraData.Guid, sizeof (EFI_GUID));
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + //
> + // unary-op
> + //
> + case EFI_IFR_LENGTH_OP:
> + DepExpressionOpCode->LengthExp.Operand = ExpressionOpCode-
> >Operand;
> + PopDependencyExpDes (&DepExpressionOpCode-
> >LengthExp.SubExpression);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_NOT_OP:
> + DepExpressionOpCode->NotExp.Operand = ExpressionOpCode-
> >Operand;
> + PopDependencyExpDes (&DepExpressionOpCode-
> >NotExp.SubExpression);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_BITWISE_NOT_OP:
> + DepExpressionOpCode->BitWiseNotExp.Operand = ExpressionOpCode-
> >Operand;
> + PopDependencyExpDes (&DepExpressionOpCode-
> >BitWiseNotExp.SubExpression);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_QUESTION_REF2_OP:
> + DepExpressionOpCode->QuestionRef2Exp.Operand =
> ExpressionOpCode->Operand;
> + PopDependencyExpDes (&DepExpressionOpCode-
> >QuestionRef2Exp.SubExpression);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_QUESTION_REF3_OP:
> + DepExpressionOpCode->QuestionRef3Exp.Operand =
> ExpressionOpCode->Operand;
> + CopyMem (&DepExpressionOpCode->QuestionRef3Exp.DevicePath,
> &ExpressionOpCode->ExtraData.QuestionRef3Data.DevicePath, sizeof
> (EFI_DEVICE_PATH));
> + CopyMem (&DepExpressionOpCode->QuestionRef3Exp.Guid,
> &ExpressionOpCode->ExtraData.QuestionRef3Data.Guid, sizeof (EFI_GUID));
> + PopDependencyExpDes (&DepExpressionOpCode-
> >QuestionRef3Exp.SubExpression);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_SET_OP:
> + DepExpressionOpCode->SetExp.Operand = ExpressionOpCode-
> >Operand;
> + DepExpressionOpCode->SetExp.VarStorage = ExpressionOpCode-
> >ExtraData.GetSetData.VarStorage;
> + CopyMem (&DepExpressionOpCode->SetExp.VarStoreInfo.VarName,
> &ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo.VarName, sizeof
> (EFI_STRING_ID));
> + CopyMem (&DepExpressionOpCode->SetExp.VarStoreInfo.VarOffset,
> &ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset, sizeof
> (UINT16));
> + DepExpressionOpCode->SetExp.VarStoreInfo = ExpressionOpCode-
> >ExtraData.GetSetData.VarStoreInfo;
> + if (ExpressionOpCode->ExtraData.GetSetData.ValueName != NULL) {
> + DepExpressionOpCode->SetExp.ValueName = (CHAR16
> *)AllocateCopyPool (sizeof (ExpressionOpCode-
> >ExtraData.GetSetData.ValueName), ExpressionOpCode-
> >ExtraData.GetSetData.ValueName);
> + if (DepExpressionOpCode->SetExp.ValueName == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> + }
> +
> + DepExpressionOpCode->SetExp.ValueType = ExpressionOpCode-
> >ExtraData.GetSetData.ValueType;
> + DepExpressionOpCode->SetExp.ValueWidth = ExpressionOpCode-
> >ExtraData.GetSetData.ValueWidth;
> + PopDependencyExpDes (&DepExpressionOpCode-
> >SetExp.SubExpression);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_STRING_REF2_OP:
> + DepExpressionOpCode->StringRef2Exp.Operand = ExpressionOpCode-
> >Operand;
> + PopDependencyExpDes (&DepExpressionOpCode-
> >StringRef2Exp.SubExpression);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_TO_BOOLEAN_OP:
> + DepExpressionOpCode->ToBooleanExp.Operand = ExpressionOpCode-
> >Operand;
> + PopDependencyExpDes (&DepExpressionOpCode-
> >ToBooleanExp.SubExpression);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_TO_STRING_OP:
> + DepExpressionOpCode->ToStringExp.Operand = ExpressionOpCode-
> >Operand;
> + DepExpressionOpCode->ToStringExp.Format = ExpressionOpCode-
> >ExtraData.Format;
> + PopDependencyExpDes (&DepExpressionOpCode-
> >ToStringExp.SubExpression);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_TO_UINT_OP:
> + DepExpressionOpCode->ToUintExp.Operand = ExpressionOpCode-
> >Operand;
> + PopDependencyExpDes (&DepExpressionOpCode-
> >ToUintExp.SubExpression);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_TO_LOWER_OP:
> + DepExpressionOpCode->ToLowerExp.Operand = ExpressionOpCode-
> >Operand;
> + PopDependencyExpDes (&DepExpressionOpCode-
> >ToLowerExp.SubExpression);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_TO_UPPER_OP:
> + DepExpressionOpCode->ToUpperExp.Operand = ExpressionOpCode-
> >Operand;
> + PopDependencyExpDes (&DepExpressionOpCode-
> >ToUpperExp.SubExpression);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + //
> + // binary-op
> + //
> + case EFI_IFR_ADD_OP:
> + DepExpressionOpCode->AddExp.Operand = ExpressionOpCode-
> >Operand;
> + PopDependencyExpDes (&DepExpressionOpCode-
> >AddExp.LeftHandExp);
> + PopDependencyExpDes (&DepExpressionOpCode-
> >AddExp.RightHandExp);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_AND_OP:
> + DepExpressionOpCode->AndExp.Operand = ExpressionOpCode-
> >Operand;
> + PopDependencyExpDes (&DepExpressionOpCode-
> >AndExp.SubExpression1);
> + PopDependencyExpDes (&DepExpressionOpCode-
> >AndExp.SubExpression2);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_BITWISE_AND_OP:
> + DepExpressionOpCode->BitwiseAndExp.Operand = ExpressionOpCode-
> >Operand;
> + PopDependencyExpDes (&DepExpressionOpCode-
> >BitwiseAndExp.SubExpression1);
> + PopDependencyExpDes (&DepExpressionOpCode-
> >BitwiseAndExp.SubExpression2);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_BITWISE_OR_OP:
> + DepExpressionOpCode->BitwiseOrExp.Operand = ExpressionOpCode-
> >Operand;
> + PopDependencyExpDes (&DepExpressionOpCode-
> >BitwiseOrExp.SubExpression1);
> + PopDependencyExpDes (&DepExpressionOpCode-
> >BitwiseOrExp.SubExpression2);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_CATENATE_OP:
> + DepExpressionOpCode->CatenateExp.Operand = ExpressionOpCode-
> >Operand;
> + PopDependencyExpDes (&DepExpressionOpCode-
> >CatenateExp.LeftStringExp);
> + PopDependencyExpDes (&DepExpressionOpCode-
> >CatenateExp.RightStringExp);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_DIVIDE_OP:
> + DepExpressionOpCode->DivExp.Operand = ExpressionOpCode-
> >Operand;
> + PopDependencyExpDes (&DepExpressionOpCode-
> >DivExp.LeftHandExp);
> + PopDependencyExpDes (&DepExpressionOpCode-
> >DivExp.RightHandExp);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_EQUAL_OP:
> + DepExpressionOpCode->EqualExp.Operand = ExpressionOpCode-
> >Operand;
> + PopDependencyExpDes (&DepExpressionOpCode-
> >EqualExp.SubExpression1);
> + PopDependencyExpDes (&DepExpressionOpCode-
> >EqualExp.SubExpression2);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_GREATER_EQUAL_OP:
> + DepExpressionOpCode->GreaterEqualExp.Operand =
> ExpressionOpCode->Operand;
> + PopDependencyExpDes (&DepExpressionOpCode-
> >GreaterEqualExp.LeftHandExp);
> + PopDependencyExpDes (&DepExpressionOpCode-
> >GreaterEqualExp.RightHandExp);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_GREATER_THAN_OP:
> + DepExpressionOpCode->GreaterThanExp.Operand =
> ExpressionOpCode->Operand;
> + PopDependencyExpDes (&DepExpressionOpCode-
> >GreaterThanExp.LeftHandExp);
> + PopDependencyExpDes (&DepExpressionOpCode-
> >GreaterThanExp.RightHandExp);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_LESS_EQUAL_OP:
> + DepExpressionOpCode->LessEqualExp.Operand = ExpressionOpCode-
> >Operand;
> + PopDependencyExpDes (&DepExpressionOpCode-
> >LessEqualExp.LeftHandExp);
> + PopDependencyExpDes (&DepExpressionOpCode-
> >LessEqualExp.RightHandExp);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_LESS_THAN_OP:
> + DepExpressionOpCode->LessThanExp.Operand = ExpressionOpCode-
> >Operand;
> + PopDependencyExpDes (&DepExpressionOpCode-
> >LessThanExp.LeftHandExp);
> + PopDependencyExpDes (&DepExpressionOpCode-
> >LessThanExp.RightHandExp);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_MATCH_OP:
> + DepExpressionOpCode->MatchExp.Operand = ExpressionOpCode-
> >Operand;
> + PopDependencyExpDes (&DepExpressionOpCode-
> >MatchExp.PatternExp);
> + PopDependencyExpDes (&DepExpressionOpCode-
> >MatchExp.StringExp);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_MATCH2_OP:
> + DepExpressionOpCode->Match2Exp.Operand = ExpressionOpCode-
> >Operand;
> + CopyMem (&DepExpressionOpCode->Match2Exp.SyntaxType,
> &ExpressionOpCode->ExtraData.Guid, sizeof (EFI_GUID));
> + PopDependencyExpDes (&DepExpressionOpCode-
> >Match2Exp.PatternExp);
> + PopDependencyExpDes (&DepExpressionOpCode-
> >Match2Exp.StringExp);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_MODULO_OP:
> + DepExpressionOpCode->ModExp.Operand = ExpressionOpCode-
> >Operand;
> + PopDependencyExpDes (&DepExpressionOpCode-
> >ModExp.LeftHandExp);
> + PopDependencyExpDes (&DepExpressionOpCode-
> >ModExp.RightHandExp);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_MULTIPLY_OP:
> + DepExpressionOpCode->MultExp.Operand = ExpressionOpCode-
> >Operand;
> + PopDependencyExpDes (&DepExpressionOpCode-
> >MultExp.LeftHandExp);
> + PopDependencyExpDes (&DepExpressionOpCode-
> >MultExp.RightHandExp);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_NOT_EQUAL_OP:
> + DepExpressionOpCode->NotEqualExp.Operand = ExpressionOpCode-
> >Operand;
> + PopDependencyExpDes (&DepExpressionOpCode-
> >NotEqualExp.SubExpression1);
> + PopDependencyExpDes (&DepExpressionOpCode-
> >NotEqualExp.SubExpression2);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_OR_OP:
> + DepExpressionOpCode->OrExp.Operand = ExpressionOpCode-
> >Operand;
> + PopDependencyExpDes (&DepExpressionOpCode-
> >OrExp.SubExpression1);
> + PopDependencyExpDes (&DepExpressionOpCode-
> >OrExp.SubExpression2);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_SHIFT_LEFT_OP:
> + DepExpressionOpCode->ShiftLeftExp.Operand = ExpressionOpCode-
> >Operand;
> + PopDependencyExpDes (&DepExpressionOpCode-
> >ShiftLeftExp.LeftHandExp);
> + PopDependencyExpDes (&DepExpressionOpCode-
> >ShiftLeftExp.RightHandExp);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_SHIFT_RIGHT_OP:
> + DepExpressionOpCode->ShiftRightExp.Operand = ExpressionOpCode-
> >Operand;
> + PopDependencyExpDes (&DepExpressionOpCode-
> >ShiftRightExp.LeftHandExp);
> + PopDependencyExpDes (&DepExpressionOpCode-
> >ShiftRightExp.RightHandExp);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_SUBTRACT_OP:
> + DepExpressionOpCode->SubtractExp.Operand = ExpressionOpCode-
> >Operand;
> + PopDependencyExpDes (&DepExpressionOpCode-
> >SubtractExp.LeftHandExp);
> + PopDependencyExpDes (&DepExpressionOpCode-
> >SubtractExp.RightHandExp);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + //
> + // ternary-op
> + //
> + case EFI_IFR_CONDITIONAL_OP:
> + DepExpressionOpCode->ConditionalExp.Operand = ExpressionOpCode-
> >Operand;
> + PopDependencyExpDes (&DepExpressionOpCode-
> >ConditionalExp.CondTrueValExp);
> + PopDependencyExpDes (&DepExpressionOpCode-
> >ConditionalExp.CondFalseValExp);
> + PopDependencyExpDes (&DepExpressionOpCode-
> >ConditionalExp.ConditionExp);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_FIND_OP:
> + DepExpressionOpCode->FindExp.Operand = ExpressionOpCode-
> >Operand;
> + PopDependencyExpDes (&DepExpressionOpCode-
> >FindExp.StringToSearchExp);
> + PopDependencyExpDes (&DepExpressionOpCode-
> >FindExp.StringToCompWithExp);
> + PopDependencyExpDes (&DepExpressionOpCode->FindExp.IndexExp);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_MID_OP:
> + DepExpressionOpCode->MidExp.Operand = ExpressionOpCode-
> >Operand;
> + PopDependencyExpDes (&DepExpressionOpCode-
> >MidExp.StringOrBufferExp);
> + PopDependencyExpDes (&DepExpressionOpCode->MidExp.IndexExp);
> + PopDependencyExpDes (&DepExpressionOpCode->MidExp.LengthExp);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_TOKEN_OP:
> + DepExpressionOpCode->TokenExp.Operand = ExpressionOpCode-
> >Operand;
> + PopDependencyExpDes (&DepExpressionOpCode-
> >TokenExp.StringToSearchExp);
> + PopDependencyExpDes (&DepExpressionOpCode-
> >TokenExp.DelimiterExp);
> + PopDependencyExpDes (&DepExpressionOpCode-
> >TokenExp.IndexExp);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + case EFI_IFR_SPAN_OP:
> + DepExpressionOpCode->SpanExp.Operand = ExpressionOpCode-
> >Operand;
> + PopDependencyExpDes (&DepExpressionOpCode-
> >SpanExp.StringToSearchExp);
> + PopDependencyExpDes (&DepExpressionOpCode-
> >SpanExp.CharsetExp);
> + PopDependencyExpDes (&DepExpressionOpCode->SpanExp.IndexExp);
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + //
> + // Map
> + //
> + case EFI_IFR_MAP_OP:
> + //
> + // Go through map expression list.
> + //
> + DepExpressionOpCode->MapExp.Operand = ExpressionOpCode-
> >Operand;
> + MapPairCount = 0;
> + SubExpressionLink = GetFirstNode (&ExpressionOpCode-
> >MapExpressionList);
> + while (!IsNull (&ExpressionOpCode->MapExpressionList,
> SubExpressionLink)) {
> + MapPairCount++;
> + SubExpressionLink = GetNextNode (&ExpressionOpCode-
> >MapExpressionList, SubExpressionLink);
> + if (IsNull (&ExpressionOpCode->MapExpressionList,
> SubExpressionLink)) {
> + Status = EFI_INVALID_PARAMETER;
> + goto Done;
> + }
> +
> + //
> + // Goto the first expression on next pair.
> + //
> + SubExpressionLink = GetNextNode (&ExpressionOpCode-
> >MapExpressionList, SubExpressionLink);
> + }
> +
> + DepExpressionOpCode->MapExp.ExpPair =
> (HII_DEPENDENCY_EXPRESSION_PAIR *)AllocateZeroPool (
> + MapPairCount * sizeof
> (HII_DEPENDENCY_EXPRESSION_PAIR)
> + );
> + if (DepExpressionOpCode->MapExp.ExpPair == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + goto Done;
> + }
> +
> + DepExpressionOpCode->MapExp.ExpPairNo = MapPairCount;
> + MapPairCount = 0;
> + PopDependencyExpDes (&DepExpressionOpCode->MapExp.SubExp);
> +
> + //
> + // Go through map expression list.
> + //
> + SubExpressionLink = GetFirstNode (&ExpressionOpCode-
> >MapExpressionList);
> + while (!IsNull (&ExpressionOpCode->MapExpressionList,
> SubExpressionLink)) {
> + SubExpression = HII_EXPRESSION_FROM_LINK (SubExpressionLink);
> + //
> + // Get the first expression description in this pair.
> + //
> + GetHiiExpressionDependency (SubExpression);
> + DepExpressionOpCode->MapExp.ExpPair[MapPairCount].MatchExp =
> SubExpression->RootDependencyExp;
> +
> + //
> + // Get the second expression description in this pair.
> + //
> + SubExpressionLink = GetNextNode (&ExpressionOpCode-
> >MapExpressionList, SubExpressionLink);
> + SubExpression = HII_EXPRESSION_FROM_LINK (SubExpressionLink);
> + GetHiiExpressionDependency (SubExpression);
> + DepExpressionOpCode->MapExp.ExpPair[MapPairCount].ReturnExp =
> SubExpression->RootDependencyExp;
> + //
> + // Goto the first expression on next pair.
> + //
> + SubExpressionLink = GetNextNode (&ExpressionOpCode-
> >MapExpressionList, SubExpressionLink);
> + MapPairCount++;
> + }
> +
> + PushDependencyExpDes (&DepExpressionOpCode);
> + break;
> +
> + default:
> + break;
> + }
> + }
> +
> + PopDependencyExpDes (&Expression->RootDependencyExp);
> +
> +Done:
> + return Status;
> +}
> +
> +/**
> + Return the result of the expression list. Check the expression list and
> + return the highest priority express result.
> + Priority: DisableIf > SuppressIf > GrayOutIf > FALSE
> +
> + @param[in] ExpList The input expression list.
> + @param[in] Evaluate Whether need to evaluate the expression first.
> + @param[in] FormSet FormSet associated with this expression.
> + @param[in] Form Form associated with this expression.
> +
> + @retval EXPRESS_RESULT Return the higher priority express result.
> + DisableIf > SuppressIf > GrayOutIf > FALSE
> +
> +**/
> +EXPRESS_RESULT
> +EvaluateExpressionList (
> + IN HII_EXPRESSION_LIST *ExpList,
> + IN BOOLEAN Evaluate,
> + IN HII_FORMSET *FormSet OPTIONAL,
> + IN HII_FORM *Form OPTIONAL
> + )
> +{
> + UINTN Index;
> + EXPRESS_RESULT ReturnVal;
> + EXPRESS_RESULT CompareOne;
> + EFI_STATUS Status;
> +
> + if (ExpList == NULL) {
> + return ExpressFalse;
> + }
> +
> + ASSERT (ExpList->Signature == HII_EXPRESSION_LIST_SIGNATURE);
> + Index = 0;
> +
> + //
> + // Check whether need to evaluate the expression first.
> + //
> + if (Evaluate) {
> + while (ExpList->Count > Index) {
> + Status = EvaluateHiiExpression (FormSet, Form, ExpList-
> >Expression[Index++]);
> + if (EFI_ERROR (Status)) {
> + return ExpressFalse;
> + }
> + }
> + }
> +
> + //
> + // Run the list of expressions.
> + //
> + ReturnVal = ExpressFalse;
> + for (Index = 0; Index < ExpList->Count; Index++) {
> + if (IsHiiValueTrue (&ExpList->Expression[Index]->Result)) {
> + switch (ExpList->Expression[Index]->Type) {
> + case EFI_HII_EXPRESSION_SUPPRESS_IF:
> + CompareOne = ExpressSuppress;
> + break;
> +
> + case EFI_HII_EXPRESSION_GRAY_OUT_IF:
> + CompareOne = ExpressGrayOut;
> + break;
> +
> + case EFI_HII_EXPRESSION_DISABLE_IF:
> + CompareOne = ExpressDisable;
> + break;
> +
> + default:
> + return ExpressFalse;
> + }
> +
> + ReturnVal = ReturnVal < CompareOne ? CompareOne : ReturnVal;
> + }
> + }
> +
> + return ReturnVal;
> +}
> diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiIfrParse.c
> b/RedfishPkg/Library/HiiUtilityLib/HiiIfrParse.c
> new file mode 100644
> index 000000000000..a51d7b9c6d24
> --- /dev/null
> +++ b/RedfishPkg/Library/HiiUtilityLib/HiiIfrParse.c
> @@ -0,0 +1,2715 @@
> +/** @file
> + The implementation of HII IFR parser.
> +
> + Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> + (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
> + Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include "HiiInternal.h"
> +
> +/**
> + Initialize Statement header members.
> +
> + @param[in] OpCodeData Pointer of the raw OpCode data.
> + @param[in,out] FormSet Pointer of the current FormSet.
> + @param[in,out] Form Pointer of the current Form.
> +
> + @return The Statement.
> +
> +**/
> +HII_STATEMENT *
> +CreateStatement (
> + IN UINT8 *OpCodeData,
> + IN OUT HII_FORMSET *FormSet,
> + IN OUT HII_FORM *Form
> + )
> +{
> + HII_STATEMENT *Statement;
> + EFI_IFR_STATEMENT_HEADER *StatementHdr;
> + INTN ConditionalExprCount;
> +
> + if (Form == NULL) {
> + //
> + // Only guid op may out side the form level.
> + //
> + if (((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode != EFI_IFR_GUID_OP)
> {
> + return NULL;
> + }
> + }
> +
> + Statement = (HII_STATEMENT *)AllocateZeroPool (sizeof
> (HII_STATEMENT));
> + if (Statement == NULL) {
> + return NULL;
> + }
> +
> + InitializeListHead (&Statement->DefaultListHead);
> + InitializeListHead (&Statement->OptionListHead);
> + InitializeListHead (&Statement->InconsistentListHead);
> + InitializeListHead (&Statement->NoSubmitListHead);
> + InitializeListHead (&Statement->WarningListHead);
> +
> + Statement->Signature = HII_STATEMENT_SIGNATURE;
> + Statement->Operand = ((EFI_IFR_OP_HEADER *)OpCodeData)-
> >OpCode;
> + Statement->OpCode = (EFI_IFR_OP_HEADER *)OpCodeData;
> + Statement->QuestionReferToBitField = FALSE;
> +
> + StatementHdr = (EFI_IFR_STATEMENT_HEADER *)(OpCodeData + sizeof
> (EFI_IFR_OP_HEADER));
> + CopyMem (&Statement->Prompt, &StatementHdr->Prompt, sizeof
> (EFI_STRING_ID));
> + CopyMem (&Statement->Help, &StatementHdr->Help, sizeof
> (EFI_STRING_ID));
> +
> + ConditionalExprCount = GetConditionalExpressionCount
> (ExpressStatement);
> + if (ConditionalExprCount > 0) {
> + //
> + // Form is inside of suppressif
> + //
> + Statement->ExpressionList = (HII_EXPRESSION_LIST *)AllocatePool (
> + (UINTN)(sizeof (HII_EXPRESSION_LIST) +
> ((ConditionalExprCount - 1) * sizeof (HII_EXPRESSION *)))
> + );
> + if (Statement->ExpressionList == NULL) {
> + return NULL;
> + }
> +
> + Statement->ExpressionList->Count = (UINTN)ConditionalExprCount;
> + Statement->ExpressionList->Signature =
> HII_EXPRESSION_LIST_SIGNATURE;
> + CopyMem (
> + Statement->ExpressionList->Expression,
> + GetConditionalExpressionList (ExpressStatement),
> + (UINTN)(sizeof (HII_EXPRESSION *) * ConditionalExprCount)
> + );
> + }
> +
> + //
> + // Insert this Statement into current Form
> + //
> + if (Form == NULL) {
> + InsertTailList (&FormSet->StatementListOSF, &Statement->Link);
> + } else {
> + InsertTailList (&Form->StatementListHead, &Statement->Link);
> + }
> +
> + return Statement;
> +}
> +
> +/**
> + Initialize Question's members.
> +
> + @param[in] OpCodeData Pointer of the raw OpCode data.
> + @param[in,out] FormSet Pointer of the current FormSet.
> + @param[in,out] Form Pointer of the current Form.
> +
> + @return The Question.
> +
> +**/
> +HII_STATEMENT *
> +CreateQuestion (
> + IN UINT8 *OpCodeData,
> + IN OUT HII_FORMSET *FormSet,
> + IN OUT HII_FORM *Form
> + )
> +{
> + HII_STATEMENT *Statement;
> + EFI_IFR_QUESTION_HEADER *QuestionHdr;
> + LIST_ENTRY *Link;
> + HII_FORMSET_STORAGE *Storage;
> + HII_NAME_VALUE_NODE *NameValueNode;
> + BOOLEAN Find;
> +
> + Statement = CreateStatement (OpCodeData, FormSet, Form);
> + if (Statement == NULL) {
> + return NULL;
> + }
> +
> + QuestionHdr = (EFI_IFR_QUESTION_HEADER *)(OpCodeData + sizeof
> (EFI_IFR_OP_HEADER));
> + CopyMem (&Statement->QuestionId, &QuestionHdr->QuestionId, sizeof
> (EFI_QUESTION_ID));
> + CopyMem (&Statement->VarStoreId, &QuestionHdr->VarStoreId, sizeof
> (EFI_VARSTORE_ID));
> + CopyMem (&Statement->VarStoreInfo.VarOffset, &QuestionHdr-
> >VarStoreInfo.VarOffset, sizeof (UINT16));
> +
> + Statement->QuestionFlags = QuestionHdr->Flags;
> +
> + if (Statement->VarStoreId == 0) {
> + //
> + // VarStoreId of zero indicates no variable storage
> + //
> + return Statement;
> + }
> +
> + //
> + // Find Storage for this Question
> + //
> + Link = GetFirstNode (&FormSet->StorageListHead);
> + while (!IsNull (&FormSet->StorageListHead, Link)) {
> + Storage = HII_STORAGE_FROM_LINK (Link);
> +
> + if (Statement->VarStoreId == Storage->VarStoreId) {
> + Statement->Storage = Storage;
> + break;
> + }
> +
> + Link = GetNextNode (&FormSet->StorageListHead, Link);
> + }
> +
> + if (Statement->Storage == NULL) {
> + return NULL;
> + }
> +
> + //
> + // Initialize varname for Name/Value or EFI Variable
> + //
> + if ((Statement->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) ||
> + (Statement->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE))
> + {
> + Statement->VariableName = GetTokenString (Statement-
> >VarStoreInfo.VarName, FormSet->HiiHandle);
> + if (Statement->VariableName == NULL) {
> + return NULL;
> + }
> +
> + if (Statement->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
> + //
> + // Check whether old string node already exist.
> + //
> + Find = FALSE;
> + if (!IsListEmpty (&Statement->Storage->NameValueList)) {
> + Link = GetFirstNode (&Statement->Storage->NameValueList);
> + while (!IsNull (&Statement->Storage->NameValueList, Link)) {
> + NameValueNode = HII_NAME_VALUE_NODE_FROM_LINK (Link);
> +
> + if (StrCmp (Statement->VariableName, NameValueNode->Name) == 0)
> {
> + Find = TRUE;
> + break;
> + }
> +
> + Link = GetNextNode (&Statement->Storage->NameValueList, Link);
> + }
> + }
> +
> + if (!Find) {
> + //
> + // Insert to Name/Value varstore list
> + //
> + NameValueNode = AllocateZeroPool (sizeof
> (HII_NAME_VALUE_NODE));
> + if (NameValueNode == NULL) {
> + return NULL;
> + }
> +
> + NameValueNode->Signature = HII_NAME_VALUE_NODE_SIGNATURE;
> + NameValueNode->Name = AllocateCopyPool (StrSize (Statement-
> >VariableName), Statement->VariableName);
> + if (NameValueNode->Name == NULL) {
> + FreePool (NameValueNode);
> + return NULL;
> + }
> +
> + NameValueNode->Value = AllocateZeroPool (0x10);
> + if (NameValueNode->Value == NULL) {
> + FreePool (NameValueNode->Name);
> + FreePool (NameValueNode);
> + return NULL;
> + }
> +
> + InsertTailList (&Statement->Storage->NameValueList,
> &NameValueNode->Link);
> + }
> + }
> + }
> +
> + return Statement;
> +}
> +
> +/**
> + Allocate a HII_EXPRESSION node.
> +
> + @param[in,out] Form The Form associated with this Expression
> + @param[in] OpCode The binary opcode data.
> +
> + @return Pointer to a HII_EXPRESSION data structure.
> +
> +**/
> +HII_EXPRESSION *
> +CreateExpression (
> + IN OUT HII_FORM *Form,
> + IN UINT8 *OpCode
> + )
> +{
> + HII_EXPRESSION *Expression;
> +
> + Expression = AllocateZeroPool (sizeof (HII_EXPRESSION));
> + if (Expression == NULL) {
> + return NULL;
> + }
> +
> + Expression->Signature = HII_EXPRESSION_SIGNATURE;
> + InitializeListHead (&Expression->OpCodeListHead);
> + Expression->OpCode = (EFI_IFR_OP_HEADER *)OpCode;
> +
> + return Expression;
> +}
> +
> +/**
> + Create ConfigHdr string for a storage.
> +
> + @param[in] FormSet Pointer of the current FormSet
> + @param[in,out] Storage Pointer of the storage
> +
> + @retval EFI_SUCCESS Initialize ConfigHdr success
> +
> +**/
> +EFI_STATUS
> +InitializeConfigHdr (
> + IN HII_FORMSET *FormSet,
> + IN OUT HII_FORMSET_STORAGE *Storage
> + )
> +{
> + CHAR16 *Name;
> +
> + if ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ||
> + (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER))
> + {
> + Name = Storage->Name;
> + } else {
> + Name = NULL;
> + }
> +
> + Storage->ConfigHdr = HiiConstructConfigHdr (
> + &Storage->Guid,
> + Name,
> + FormSet->DriverHandle
> + );
> +
> + if (Storage->ConfigHdr == NULL) {
> + return EFI_NOT_FOUND;
> + }
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Convert Ascii string to Unicode.
> +
> + This is an internal function.
> +
> + @param[in] AsciiString The Ascii string to be converted.
> + @param[out] UnicodeString The Unicode string retrieved.
> +
> +**/
> +VOID
> +AsciiToUnicode (
> + IN CHAR8 *AsciiString,
> + OUT CHAR16 *UnicodeString
> + )
> +{
> + UINT8 Index;
> +
> + Index = 0;
> + while (AsciiString[Index] != 0) {
> + UnicodeString[Index] = (CHAR16)AsciiString[Index];
> + Index++;
> + }
> +
> + UnicodeString[Index] = L'\0';
> +}
> +
> +/**
> + Allocate a HII_FORMSET_STORAGE data structure and insert to FormSet
> Storage List.
> +
> + @param[in] FormSet Pointer of the current FormSet
> + @param[in] StorageType Storage type.
> + @param[in] OpCodeData Binary data for this opcode.
> +
> + @return Pointer to a HII_FORMSET_STORAGE data structure.
> +
> +**/
> +HII_FORMSET_STORAGE *
> +CreateStorage (
> + IN HII_FORMSET *FormSet,
> + IN UINT8 StorageType,
> + IN UINT8 *OpCodeData
> + )
> +{
> + HII_FORMSET_STORAGE *Storage;
> + CHAR8 *AsciiStorageName;
> +
> + AsciiStorageName = NULL;
> +
> + Storage = AllocateZeroPool (sizeof (HII_FORMSET_STORAGE));
> + if (Storage == NULL) {
> + return NULL;
> + }
> +
> + Storage->Signature = HII_STORAGE_SIGNATURE;
> + Storage->Type = StorageType;
> +
> + switch (StorageType) {
> + case EFI_HII_VARSTORE_BUFFER:
> +
> + CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE *)OpCodeData)-
> >Guid, sizeof (EFI_GUID));
> + CopyMem (&Storage->Size, &((EFI_IFR_VARSTORE *)OpCodeData)-
> >Size, sizeof (UINT16));
> +
> + Storage->Buffer = AllocateZeroPool (Storage->Size);
> + if (Storage->Buffer == NULL) {
> + FreePool (Storage);
> + return NULL;
> + }
> +
> + AsciiStorageName = (CHAR8 *)((EFI_IFR_VARSTORE *)OpCodeData)-
> >Name;
> + Storage->Name = AllocatePool (sizeof (CHAR16) * (AsciiStrLen
> (AsciiStorageName) + 1));
> + if (Storage->Name == NULL) {
> + FreePool (Storage);
> + return NULL;
> + }
> +
> + AsciiToUnicode (AsciiStorageName, Storage->Name);
> +
> + break;
> +
> + case EFI_HII_VARSTORE_EFI_VARIABLE:
> + case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
> + CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_EFI
> *)OpCodeData)->Guid, sizeof (EFI_GUID));
> + CopyMem (&Storage->Attributes, &((EFI_IFR_VARSTORE_EFI
> *)OpCodeData)->Attributes, sizeof (UINT32));
> + CopyMem (&Storage->Size, &((EFI_IFR_VARSTORE_EFI *)OpCodeData)-
> >Size, sizeof (UINT16));
> +
> + if (StorageType == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {
> + Storage->Buffer = AllocateZeroPool (Storage->Size);
> + if (Storage->Buffer == NULL) {
> + FreePool (Storage);
> + return NULL;
> + }
> + }
> +
> + AsciiStorageName = (CHAR8 *)((EFI_IFR_VARSTORE_EFI
> *)OpCodeData)->Name;
> + Storage->Name = AllocatePool (sizeof (CHAR16) * (AsciiStrLen
> (AsciiStorageName) + 1));
> + if (Storage->Name == NULL) {
> + FreePool (Storage);
> + return NULL;
> + }
> +
> + AsciiToUnicode (AsciiStorageName, Storage->Name);
> +
> + break;
> +
> + case EFI_HII_VARSTORE_NAME_VALUE:
> + CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_NAME_VALUE
> *)OpCodeData)->Guid, sizeof (EFI_GUID));
> + InitializeListHead (&Storage->NameValueList);
> +
> + break;
> +
> + default:
> + break;
> + }
> +
> + InitializeConfigHdr (FormSet, Storage);
> + InsertTailList (&FormSet->StorageListHead, &Storage->Link);
> +
> + return Storage;
> +}
> +
> +/**
> + Get formset storage based on the input varstoreid info.
> +
> + @param[in] FormSet Pointer of the current FormSet.
> + @param[in] VarStoreId Varstore ID info.
> +
> + @return Pointer to a HII_FORMSET_STORAGE data structure.
> +
> +**/
> +HII_FORMSET_STORAGE *
> +GetFstStgFromVarId (
> + IN HII_FORMSET *FormSet,
> + IN EFI_VARSTORE_ID VarStoreId
> + )
> +{
> + HII_FORMSET_STORAGE *Storage;
> + LIST_ENTRY *Link;
> + BOOLEAN Found;
> +
> + Found = FALSE;
> + Storage = NULL;
> + //
> + // Find Formset Storage for this Question
> + //
> + Link = GetFirstNode (&FormSet->StorageListHead);
> + while (!IsNull (&FormSet->StorageListHead, Link)) {
> + Storage = HII_STORAGE_FROM_LINK (Link);
> +
> + if (Storage->VarStoreId == VarStoreId) {
> + Found = TRUE;
> + break;
> + }
> +
> + Link = GetNextNode (&FormSet->StorageListHead, Link);
> + }
> +
> + return Found ? Storage : NULL;
> +}
> +
> +/**
> + Initialize Request Element of a Question. <RequestElement> ::=
> '&'<BlockName> | '&'<Label>
> +
> + @param[in,out] FormSet Pointer of the current FormSet.
> + @param[in,out] Question The Question to be initialized.
> + @param[in,out] Form Pointer of the current form.
> +
> + @retval EFI_SUCCESS Function success.
> + @retval EFI_INVALID_PARAMETER No storage associated with the
> Question.
> +
> +**/
> +EFI_STATUS
> +InitializeRequestElement (
> + IN OUT HII_FORMSET *FormSet,
> + IN OUT HII_STATEMENT *Question,
> + IN OUT HII_FORM *Form
> + )
> +{
> + HII_FORMSET_STORAGE *Storage;
> + HII_FORM_CONFIG_REQUEST *ConfigInfo;
> + UINTN StrLen;
> + UINTN StringSize;
> + CHAR16 *NewStr;
> + CHAR16 RequestElement[30];
> + LIST_ENTRY *Link;
> + BOOLEAN Find;
> + UINTN MaxLen;
> +
> + Storage = Question->Storage;
> + if (Storage == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
> + //
> + // <ConfigRequest> is unnecessary for EFI variable storage,
> + // GetVariable()/SetVariable() will be used to retrieve/save values
> + //
> + return EFI_SUCCESS;
> + }
> +
> + //
> + // Prepare <RequestElement>
> + //
> + if ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ||
> + (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER))
> + {
> + StrLen = UnicodeSPrint (
> + RequestElement,
> + 30 * sizeof (CHAR16),
> + L"&OFFSET=%04x&WIDTH=%04x",
> + Question->VarStoreInfo.VarOffset,
> + Question->StorageWidth
> + );
> + HiiStringToLowercase (RequestElement);
> + Question->BlockName = AllocateCopyPool ((StrLen + 1) * sizeof (CHAR16),
> RequestElement);
> + if (Question->BlockName == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> + } else {
> + StrLen = UnicodeSPrint (RequestElement, 30 * sizeof (CHAR16), L"&%s",
> Question->VariableName);
> + }
> +
> + if ((Question->Operand == EFI_IFR_PASSWORD_OP) &&
> + ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) ==
> EFI_IFR_FLAG_CALLBACK))
> + {
> + //
> + // Password with CALLBACK flag is stored in encoded format,
> + // so don't need to append it to <ConfigRequest>
> + //
> + return EFI_SUCCESS;
> + }
> +
> + StringSize = (Storage->ConfigRequest != NULL) ? StrSize (Storage-
> >ConfigRequest) : sizeof (CHAR16);
> + MaxLen = StringSize / sizeof (CHAR16) + Storage->SpareStrLen;
> +
> + //
> + // Append <RequestElement> to <ConfigRequest>
> + //
> + if (StrLen > Storage->SpareStrLen) {
> + //
> + // Old String buffer is not sufficient for RequestElement, allocate a new
> one
> + //
> + MaxLen = StringSize / sizeof (CHAR16) +
> CONFIG_REQUEST_STRING_INCREMENTAL;
> + NewStr = AllocatePool (MaxLen * sizeof (CHAR16));
> + if (NewStr == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + if (Storage->ConfigRequest != NULL) {
> + CopyMem (NewStr, Storage->ConfigRequest, StringSize);
> + FreePool (Storage->ConfigRequest);
> + } else {
> + NewStr[0] = L'\0';
> + }
> +
> + Storage->ConfigRequest = NewStr;
> + Storage->SpareStrLen = CONFIG_REQUEST_STRING_INCREMENTAL;
> + }
> +
> + StrCatS (Storage->ConfigRequest, MaxLen, RequestElement);
> + Storage->ElementCount++;
> + Storage->SpareStrLen -= StrLen;
> +
> + //
> + // Update the Config Request info saved in the form.
> + //
> + ConfigInfo = NULL;
> + Find = FALSE;
> + Link = GetFirstNode (&Form->ConfigRequestHead);
> + while (!IsNull (&Form->ConfigRequestHead, Link)) {
> + ConfigInfo = HII_FORM_CONFIG_REQUEST_FROM_LINK (Link);
> + if ((ConfigInfo != NULL) && (ConfigInfo->Storage == Storage)) {
> + Find = TRUE;
> + break;
> + }
> +
> + Link = GetNextNode (&Form->ConfigRequestHead, Link);
> + }
> +
> + if (!Find) {
> + ConfigInfo = AllocateZeroPool (sizeof (HII_FORM_CONFIG_REQUEST));
> + if (ConfigInfo == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + ConfigInfo->Signature = HII_FORM_CONFIG_REQUEST_SIGNATURE;
> + ConfigInfo->ConfigRequest = AllocateCopyPool (StrSize (Storage-
> >ConfigHdr), Storage->ConfigHdr);
> + if (ConfigInfo->ConfigRequest == NULL) {
> + FreePool (ConfigInfo);
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + ConfigInfo->SpareStrLen = 0;
> + ConfigInfo->Storage = Storage;
> + InsertTailList (&Form->ConfigRequestHead, &ConfigInfo->Link);
> + }
> +
> + StringSize = (ConfigInfo->ConfigRequest != NULL) ? StrSize (ConfigInfo-
> >ConfigRequest) : sizeof (CHAR16);
> + MaxLen = StringSize / sizeof (CHAR16) + ConfigInfo->SpareStrLen;
> +
> + //
> + // Append <RequestElement> to <ConfigRequest>
> + //
> + if (StrLen > ConfigInfo->SpareStrLen) {
> + //
> + // Old String buffer is not sufficient for RequestElement, allocate a new
> one
> + //
> + MaxLen = StringSize / sizeof (CHAR16) +
> CONFIG_REQUEST_STRING_INCREMENTAL;
> + NewStr = AllocatePool (MaxLen * sizeof (CHAR16));
> + if (NewStr == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + if (ConfigInfo->ConfigRequest != NULL) {
> + CopyMem (NewStr, ConfigInfo->ConfigRequest, StringSize);
> + FreePool (ConfigInfo->ConfigRequest);
> + } else {
> + NewStr[0] = L'\0';
> + }
> +
> + ConfigInfo->ConfigRequest = NewStr;
> + ConfigInfo->SpareStrLen = CONFIG_REQUEST_STRING_INCREMENTAL;
> + }
> +
> + StrCatS (ConfigInfo->ConfigRequest, MaxLen, RequestElement);
> + ConfigInfo->ElementCount++;
> + ConfigInfo->SpareStrLen -= StrLen;
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Free resources of a Expression.
> +
> + @param[in] FormSet Pointer of the Expression
> +
> +**/
> +VOID
> +DestroyExpression (
> + IN HII_EXPRESSION *Expression
> + )
> +{
> + LIST_ENTRY *Link;
> + HII_EXPRESSION_OPCODE *OpCode;
> + LIST_ENTRY *SubExpressionLink;
> + HII_EXPRESSION *SubExpression;
> +
> + while (!IsListEmpty (&Expression->OpCodeListHead)) {
> + Link = GetFirstNode (&Expression->OpCodeListHead);
> + OpCode = HII_EXPRESSION_OPCODE_FROM_LINK (Link);
> +
> + RemoveEntryList (&OpCode->Link);
> + if ((OpCode->Operand == EFI_IFR_EQ_ID_VAL_LIST_OP) && (OpCode-
> >ExtraData.EqIdListData.ValueList != NULL)) {
> + FreePool (OpCode->ExtraData.EqIdListData.ValueList);
> + }
> +
> + if (((OpCode->Operand == EFI_IFR_GET_OP) || (OpCode->Operand ==
> EFI_IFR_SET_OP)) &&
> + (OpCode->ExtraData.GetSetData.ValueName != NULL))
> + {
> + FreePool (OpCode->ExtraData.GetSetData.ValueName);
> + }
> +
> + if (OpCode->MapExpressionList.ForwardLink != NULL) {
> + while (!IsListEmpty (&OpCode->MapExpressionList)) {
> + SubExpressionLink = GetFirstNode (&OpCode->MapExpressionList);
> + SubExpression = HII_EXPRESSION_FROM_LINK (SubExpressionLink);
> + RemoveEntryList (&SubExpression->Link);
> + DestroyExpression (SubExpression);
> + }
> + }
> + }
> +
> + //
> + // Free this Expression
> + //
> + FreePool (Expression);
> +}
> +
> +/**
> + Delete a string from HII Package List.
> +
> + @param[in] StringId Id of the string in HII database.
> + @param[in] HiiHandle The HII package list handle.
> +
> + @retval EFI_SUCCESS The string was deleted successfully.
> +
> +**/
> +EFI_STATUS
> +DeleteString (
> + IN EFI_STRING_ID StringId,
> + IN EFI_HII_HANDLE HiiHandle
> + )
> +{
> + CHAR16 NullChar;
> +
> + NullChar = CHAR_NULL;
> + HiiSetString (HiiHandle, StringId, &NullChar, NULL);
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Free resources of a Statement.
> +
> + @param[in] FormSet Pointer of the FormSet
> + @param[in,out] Statement Pointer of the Statement
> +
> +**/
> +VOID
> +DestroyStatement (
> + IN HII_FORMSET *FormSet,
> + IN OUT HII_STATEMENT *Statement
> + )
> +{
> + LIST_ENTRY *Link;
> + HII_QUESTION_DEFAULT *Default;
> + HII_QUESTION_OPTION *Option;
> + HII_EXPRESSION *Expression;
> +
> + //
> + // Free Default value List
> + //
> + while (!IsListEmpty (&Statement->DefaultListHead)) {
> + Link = GetFirstNode (&Statement->DefaultListHead);
> + Default = HII_QUESTION_DEFAULT_FROM_LINK (Link);
> + RemoveEntryList (&Default->Link);
> +
> + if (Default->Value.Buffer != NULL) {
> + FreePool (Default->Value.Buffer);
> + }
> +
> + FreePool (Default);
> + }
> +
> + //
> + // Free Options List
> + //
> + while (!IsListEmpty (&Statement->OptionListHead)) {
> + Link = GetFirstNode (&Statement->OptionListHead);
> + Option = HII_QUESTION_OPTION_FROM_LINK (Link);
> +
> + if (Option->SuppressExpression != NULL) {
> + FreePool (Option->SuppressExpression);
> + }
> +
> + RemoveEntryList (&Option->Link);
> +
> + FreePool (Option);
> + }
> +
> + //
> + // Free Inconsistent List
> + //
> + while (!IsListEmpty (&Statement->InconsistentListHead)) {
> + Link = GetFirstNode (&Statement->InconsistentListHead);
> + Expression = HII_EXPRESSION_FROM_LINK (Link);
> + RemoveEntryList (&Expression->Link);
> +
> + DestroyExpression (Expression);
> + }
> +
> + //
> + // Free NoSubmit List
> + //
> + while (!IsListEmpty (&Statement->NoSubmitListHead)) {
> + Link = GetFirstNode (&Statement->NoSubmitListHead);
> + Expression = HII_EXPRESSION_FROM_LINK (Link);
> + RemoveEntryList (&Expression->Link);
> +
> + DestroyExpression (Expression);
> + }
> +
> + //
> + // Free WarningIf List
> + //
> + while (!IsListEmpty (&Statement->WarningListHead)) {
> + Link = GetFirstNode (&Statement->WarningListHead);
> + Expression = HII_EXPRESSION_FROM_LINK (Link);
> + RemoveEntryList (&Expression->Link);
> +
> + DestroyExpression (Expression);
> + }
> +
> + if (Statement->ExpressionList != NULL) {
> + FreePool (Statement->ExpressionList);
> + }
> +
> + if (Statement->VariableName != NULL) {
> + FreePool (Statement->VariableName);
> + }
> +
> + if (Statement->BlockName != NULL) {
> + FreePool (Statement->BlockName);
> + }
> +
> + if (Statement->Value.Buffer != NULL) {
> + FreePool (Statement->Value.Buffer);
> + }
> +
> + if ((Statement->Operand == EFI_IFR_STRING_OP) || (Statement-
> >Operand == EFI_IFR_PASSWORD_OP)) {
> + DeleteString (Statement->Value.Value.string, FormSet->HiiHandle);
> + }
> +}
> +
> +/**
> + Free resources of a Form.
> +
> + @param[in] FormSet Pointer of the FormSet
> + @param[in,out] Form Pointer of the Form.
> +
> +**/
> +VOID
> +DestroyForm (
> + IN HII_FORMSET *FormSet,
> + IN OUT HII_FORM *Form
> + )
> +{
> + LIST_ENTRY *Link;
> + HII_EXPRESSION *Expression;
> + HII_STATEMENT *Statement;
> + HII_FORM_CONFIG_REQUEST *ConfigInfo;
> +
> + //
> + // Free Rule Expressions
> + //
> + while (!IsListEmpty (&Form->RuleListHead)) {
> + Link = GetFirstNode (&Form->RuleListHead);
> + Expression = HII_EXPRESSION_FROM_LINK (Link);
> + RemoveEntryList (&Expression->Link);
> + DestroyExpression (Expression);
> + }
> +
> + //
> + // Free Statements/Questions
> + //
> + while (!IsListEmpty (&Form->StatementListHead)) {
> + Link = GetFirstNode (&Form->StatementListHead);
> + Statement = HII_STATEMENT_FROM_LINK (Link);
> + RemoveEntryList (&Statement->Link);
> + DestroyStatement (FormSet, Statement);
> + }
> +
> + //
> + // Free ConfigRequest string.
> + //
> + while (!IsListEmpty (&Form->ConfigRequestHead)) {
> + Link = GetFirstNode (&Form->ConfigRequestHead);
> + ConfigInfo = HII_FORM_CONFIG_REQUEST_FROM_LINK (Link);
> +
> + RemoveEntryList (&ConfigInfo->Link);
> +
> + FreePool (ConfigInfo->ConfigRequest);
> + FreePool (ConfigInfo);
> + }
> +
> + if (Form->SuppressExpression != NULL) {
> + FreePool (Form->SuppressExpression);
> + }
> +
> + //
> + // Free this Form
> + //
> + FreePool (Form);
> +}
> +
> +/**
> + Tell whether this Operand is an Expression OpCode or not
> +
> + @param[in] Operand Operand of an IFR OpCode.
> +
> + @retval TRUE This is an Expression OpCode.
> + @retval FALSE Not an Expression OpCode.
> +
> +**/
> +BOOLEAN
> +IsExpressionOpCode (
> + IN UINT8 Operand
> + )
> +{
> + if (((Operand >= EFI_IFR_EQ_ID_VAL_OP) && (Operand <=
> EFI_IFR_NOT_OP)) ||
> + ((Operand >= EFI_IFR_MATCH_OP) && (Operand <= EFI_IFR_SET_OP))
> ||
> + ((Operand >= EFI_IFR_EQUAL_OP) && (Operand <= EFI_IFR_SPAN_OP))
> ||
> + (Operand == EFI_IFR_CATENATE_OP) ||
> + (Operand == EFI_IFR_TO_LOWER_OP) ||
> + (Operand == EFI_IFR_TO_UPPER_OP) ||
> + (Operand == EFI_IFR_MAP_OP) ||
> + (Operand == EFI_IFR_VERSION_OP) ||
> + (Operand == EFI_IFR_SECURITY_OP) ||
> + (Operand == EFI_IFR_MATCH2_OP))
> + {
> + return TRUE;
> + } else {
> + return FALSE;
> + }
> +}
> +
> +/**
> + Tell whether this Operand is an Statement OpCode.
> +
> + @param[in] Operand Operand of an IFR OpCode.
> +
> + @retval TRUE This is an Statement OpCode.
> + @retval FALSE Not an Statement OpCode.
> +
> +**/
> +BOOLEAN
> +IsStatementOpCode (
> + IN UINT8 Operand
> + )
> +{
> + if ((Operand == EFI_IFR_SUBTITLE_OP) ||
> + (Operand == EFI_IFR_TEXT_OP) ||
> + (Operand == EFI_IFR_RESET_BUTTON_OP) ||
> + (Operand == EFI_IFR_REF_OP) ||
> + (Operand == EFI_IFR_ACTION_OP) ||
> + (Operand == EFI_IFR_NUMERIC_OP) ||
> + (Operand == EFI_IFR_ORDERED_LIST_OP) ||
> + (Operand == EFI_IFR_CHECKBOX_OP) ||
> + (Operand == EFI_IFR_STRING_OP) ||
> + (Operand == EFI_IFR_PASSWORD_OP) ||
> + (Operand == EFI_IFR_DATE_OP) ||
> + (Operand == EFI_IFR_TIME_OP) ||
> + (Operand == EFI_IFR_GUID_OP) ||
> + (Operand == EFI_IFR_ONE_OF_OP))
> + {
> + return TRUE;
> + } else {
> + return FALSE;
> + }
> +}
> +
> +/**
> + Tell whether this Operand is an known OpCode.
> +
> + @param[in] Operand Operand of an IFR OpCode.
> +
> + @retval TRUE This is an Statement OpCode.
> + @retval FALSE Not an Statement OpCode.
> +
> +**/
> +BOOLEAN
> +IsUnKnownOpCode (
> + IN UINT8 Operand
> + )
> +{
> + return Operand > EFI_IFR_MATCH2_OP ? TRUE : FALSE;
> +}
> +
> +/**
> + Calculate number of Statements(Questions) and Expression OpCodes.
> +
> + @param[in] FormSet The FormSet to be counted.
> + @param[in,out] NumberOfStatement Number of
> Statements(Questions)
> + @param[in,out] NumberOfExpression Number of Expression OpCodes
> +
> +**/
> +VOID
> +CountOpCodes (
> + IN HII_FORMSET *FormSet,
> + IN OUT UINT16 *NumberOfStatement,
> + IN OUT UINT16 *NumberOfExpression
> + )
> +{
> + UINT16 StatementCount;
> + UINT16 ExpressionCount;
> + UINT8 *OpCodeData;
> + UINTN Offset;
> + UINTN OpCodeLen;
> +
> + Offset = 0;
> + StatementCount = 0;
> + ExpressionCount = 0;
> +
> + while (Offset < FormSet->IfrBinaryLength) {
> + OpCodeData = FormSet->IfrBinaryData + Offset;
> + OpCodeLen = ((EFI_IFR_OP_HEADER *)OpCodeData)->Length;
> + Offset += OpCodeLen;
> +
> + if (IsExpressionOpCode (((EFI_IFR_OP_HEADER *)OpCodeData)-
> >OpCode)) {
> + ExpressionCount++;
> + } else {
> + StatementCount++;
> + }
> + }
> +
> + *NumberOfStatement = StatementCount;
> + *NumberOfExpression = ExpressionCount;
> +}
> +
> +/**
> + Parse opcodes in the formset IFR binary.
> +
> + @param[in] FormSet Pointer of the FormSet data structure.
> +
> + @retval EFI_SUCCESS Opcode parse success.
> + @retval Other Opcode parse fail.
> +
> +**/
> +EFI_STATUS
> +ParseOpCodes (
> + IN HII_FORMSET *FormSet
> + )
> +{
> + EFI_STATUS Status;
> + HII_FORM *CurrentForm;
> + HII_STATEMENT *CurrentStatement;
> + HII_STATEMENT *ParentStatement;
> + HII_EXPRESSION_OPCODE *ExpressionOpCode;
> + HII_EXPRESSION *CurrentExpression;
> + UINT8 Operand;
> + UINT8 Scope;
> + UINTN OpCodeOffset;
> + UINTN OpCodeLength;
> + UINT8 *OpCodeData;
> + UINT8 ScopeOpCode;
> + HII_FORMSET_DEFAULTSTORE *DefaultStore;
> + HII_QUESTION_DEFAULT *CurrentDefault;
> + HII_QUESTION_OPTION *CurrentOption;
> + UINT8 Width;
> + UINT16 NumberOfStatement;
> + UINT16 NumberOfExpression;
> + EFI_IMAGE_ID *ImageId;
> + BOOLEAN SuppressForQuestion;
> + BOOLEAN SuppressForOption;
> + UINT16 DepthOfDisable;
> + BOOLEAN OpCodeDisabled;
> + BOOLEAN SingleOpCodeExpression;
> + BOOLEAN InScopeDefault;
> + EFI_HII_VALUE *ExpressionValue;
> + HII_STATEMENT_VALUE *StatementValue;
> + EFI_IFR_FORM_MAP_METHOD *MapMethod;
> + UINT8 MapScopeDepth;
> + LIST_ENTRY *Link;
> + HII_FORMSET_STORAGE *Storage;
> + LIST_ENTRY *MapExpressionList;
> + EFI_VARSTORE_ID TempVarstoreId;
> + BOOLEAN InScopeDisable;
> + INTN ConditionalExprCount;
> + BOOLEAN InUnknownScope;
> + UINT8 UnknownDepth;
> + HII_FORMSET_DEFAULTSTORE *PreDefaultStore;
> + LIST_ENTRY *DefaultLink;
> + BOOLEAN HaveInserted;
> + UINT16 TotalBits;
> + BOOLEAN QuestionReferBitField;
> +
> + SuppressForQuestion = FALSE;
> + SuppressForOption = FALSE;
> + InScopeDisable = FALSE;
> + DepthOfDisable = 0;
> + OpCodeDisabled = FALSE;
> + SingleOpCodeExpression = FALSE;
> + InScopeDefault = FALSE;
> + CurrentExpression = NULL;
> + CurrentDefault = NULL;
> + CurrentOption = NULL;
> + ImageId = NULL;
> + MapMethod = NULL;
> + MapScopeDepth = 0;
> + Link = NULL;
> + MapExpressionList = NULL;
> + TempVarstoreId = 0;
> + ConditionalExprCount = 0;
> + InUnknownScope = FALSE;
> + UnknownDepth = 0;
> + QuestionReferBitField = FALSE;
> +
> + //
> + // Get the number of Statements and Expressions
> + //
> + CountOpCodes (FormSet, &NumberOfStatement, &NumberOfExpression);
> +
> + InitializeListHead (&FormSet->StatementListOSF);
> + InitializeListHead (&FormSet->StorageListHead);
> + InitializeListHead (&FormSet->DefaultStoreListHead);
> + InitializeListHead (&FormSet->FormListHead);
> + ResetCurrentExpressionStack ();
> + ResetMapExpressionListStack ();
> +
> + CurrentForm = NULL;
> + CurrentStatement = NULL;
> + ParentStatement = NULL;
> +
> + ResetScopeStack ();
> +
> + OpCodeOffset = 0;
> + while (OpCodeOffset < FormSet->IfrBinaryLength) {
> + OpCodeData = FormSet->IfrBinaryData + OpCodeOffset;
> +
> + OpCodeLength = ((EFI_IFR_OP_HEADER *)OpCodeData)->Length;
> + OpCodeOffset += OpCodeLength;
> + Operand = ((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode;
> + Scope = ((EFI_IFR_OP_HEADER *)OpCodeData)->Scope;
> + if (InUnknownScope) {
> + if (Operand == EFI_IFR_END_OP) {
> + UnknownDepth--;
> +
> + if (UnknownDepth == 0) {
> + InUnknownScope = FALSE;
> + }
> + } else {
> + if (Scope != 0) {
> + UnknownDepth++;
> + }
> + }
> +
> + continue;
> + }
> +
> + if (IsUnKnownOpCode (Operand)) {
> + if (Scope != 0) {
> + InUnknownScope = TRUE;
> + UnknownDepth++;
> + }
> +
> + continue;
> + }
> +
> + //
> + // If scope bit set, push onto scope stack
> + //
> + if (Scope != 0) {
> + PushScope (Operand);
> + }
> +
> + if (OpCodeDisabled) {
> + //
> + // DisableIf Expression is evaluated to be TRUE, try to find its end.
> + // Here only cares the EFI_IFR_DISABLE_IF and EFI_IFR_END
> + //
> + if (Operand == EFI_IFR_DISABLE_IF_OP) {
> + DepthOfDisable++;
> + } else if (Operand == EFI_IFR_END_OP) {
> + Status = PopScope (&ScopeOpCode);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + if (ScopeOpCode == EFI_IFR_DISABLE_IF_OP) {
> + if (DepthOfDisable == 0) {
> + InScopeDisable = FALSE;
> + OpCodeDisabled = FALSE;
> + } else {
> + DepthOfDisable--;
> + }
> + }
> + }
> +
> + continue;
> + }
> +
> + if (IsExpressionOpCode (Operand)) {
> + ExpressionOpCode = (HII_EXPRESSION_OPCODE *)AllocateZeroPool
> (sizeof (HII_EXPRESSION_OPCODE));
> + if (ExpressionOpCode == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + ExpressionOpCode->Signature = HII_EXPRESSION_OPCODE_SIGNATURE;
> + ExpressionOpCode->Operand = Operand;
> +
> + switch (Operand) {
> + case EFI_IFR_EQ_ID_VAL_OP:
> +
> + CopyMem (&ExpressionOpCode->ExtraData.EqIdValData.QuestionId,
> &((EFI_IFR_EQ_ID_VAL *)OpCodeData)->QuestionId, sizeof
> (EFI_QUESTION_ID));
> +
> + ExpressionValue = &ExpressionOpCode-
> >ExtraData.EqIdValData.Value;
> + ExpressionValue->Type = EFI_IFR_TYPE_NUM_SIZE_16;
> + CopyMem (&ExpressionValue->Value.u16, &((EFI_IFR_EQ_ID_VAL
> *)OpCodeData)->Value, sizeof (UINT16));
> + break;
> +
> + case EFI_IFR_EQ_ID_ID_OP:
> + CopyMem (&ExpressionOpCode->ExtraData.EqIdIdData.QuestionId1,
> &((EFI_IFR_EQ_ID_ID *)OpCodeData)->QuestionId1, sizeof
> (EFI_QUESTION_ID));
> + CopyMem (&ExpressionOpCode->ExtraData.EqIdIdData.QuestionId2,
> &((EFI_IFR_EQ_ID_ID *)OpCodeData)->QuestionId2, sizeof
> (EFI_QUESTION_ID));
> + break;
> +
> + case EFI_IFR_EQ_ID_VAL_LIST_OP:
> +
> + CopyMem (&ExpressionOpCode->ExtraData.EqIdListData.QuestionId,
> &((EFI_IFR_EQ_ID_VAL_LIST *)OpCodeData)->QuestionId, sizeof
> (EFI_QUESTION_ID));
> + CopyMem (&ExpressionOpCode->ExtraData.EqIdListData.ListLength,
> &((EFI_IFR_EQ_ID_VAL_LIST *)OpCodeData)->ListLength, sizeof (UINT16));
> + ExpressionOpCode->ExtraData.EqIdListData.ValueList =
> AllocateCopyPool (
> + ExpressionOpCode-
> >ExtraData.EqIdListData.ListLength * sizeof (UINT16),
> + &((EFI_IFR_EQ_ID_VAL_LIST
> *)OpCodeData)->ValueList
> + );
> + if (ExpressionOpCode->ExtraData.EqIdListData.ValueList == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + break;
> +
> + case EFI_IFR_TO_STRING_OP:
> + case EFI_IFR_FIND_OP:
> +
> + ExpressionOpCode->ExtraData.Format = ((EFI_IFR_TO_STRING
> *)OpCodeData)->Format;
> + break;
> +
> + case EFI_IFR_STRING_REF1_OP:
> +
> + ExpressionValue = &ExpressionOpCode->ExtraData.Value;
> + ExpressionValue->Type = EFI_IFR_TYPE_STRING;
> + CopyMem (&ExpressionValue->Value.string, &((EFI_IFR_STRING_REF1
> *)OpCodeData)->StringId, sizeof (EFI_STRING_ID));
> + break;
> +
> + case EFI_IFR_RULE_REF_OP:
> +
> + ExpressionOpCode->ExtraData.RuleId = ((EFI_IFR_RULE_REF
> *)OpCodeData)->RuleId;
> + break;
> +
> + case EFI_IFR_SPAN_OP:
> +
> + ExpressionOpCode->ExtraData.Flags = ((EFI_IFR_SPAN
> *)OpCodeData)->Flags;
> + break;
> +
> + case EFI_IFR_THIS_OP:
> +
> + if (ParentStatement != NULL) {
> + ExpressionOpCode->ExtraData.QuestionRef1Data.QuestionId =
> ParentStatement->QuestionId;
> + }
> +
> + break;
> +
> + case EFI_IFR_SECURITY_OP:
> +
> + CopyMem (&ExpressionOpCode->ExtraData.Guid,
> &((EFI_IFR_SECURITY *)OpCodeData)->Permissions, sizeof (EFI_GUID));
> + break;
> +
> + case EFI_IFR_MATCH2_OP:
> +
> + CopyMem (&ExpressionOpCode->ExtraData.Guid,
> &((EFI_IFR_MATCH2 *)OpCodeData)->SyntaxType, sizeof (EFI_GUID));
> + break;
> +
> + case EFI_IFR_GET_OP:
> + case EFI_IFR_SET_OP:
> +
> + CopyMem (&TempVarstoreId, &((EFI_IFR_GET *)OpCodeData)-
> >VarStoreId, sizeof (TempVarstoreId));
> + if (TempVarstoreId != 0) {
> + if (FormSet->StorageListHead.ForwardLink != NULL) {
> + Link = GetFirstNode (&FormSet->StorageListHead);
> + while (!IsNull (&FormSet->StorageListHead, Link)) {
> + Storage = HII_STORAGE_FROM_LINK (Link);
> + if (Storage->VarStoreId == ((EFI_IFR_GET *)OpCodeData)-
> >VarStoreId) {
> + ExpressionOpCode->ExtraData.GetSetData.VarStorage = Storage;
> + break;
> + }
> +
> + Link = GetNextNode (&FormSet->StorageListHead, Link);
> + }
> + }
> +
> + if (ExpressionOpCode->ExtraData.GetSetData.VarStorage == NULL) {
> + //
> + // VarStorage is not found.
> + //
> + return EFI_INVALID_PARAMETER;
> + }
> + }
> +
> + ExpressionOpCode->ExtraData.GetSetData.ValueType =
> ((EFI_IFR_GET *)OpCodeData)->VarStoreType;
> + switch (ExpressionOpCode->ExtraData.GetSetData.ValueType) {
> + case EFI_IFR_TYPE_BOOLEAN:
> + case EFI_IFR_TYPE_NUM_SIZE_8:
> + ExpressionOpCode->ExtraData.GetSetData.ValueWidth = 1;
> + break;
> +
> + case EFI_IFR_TYPE_NUM_SIZE_16:
> + case EFI_IFR_TYPE_STRING:
> + ExpressionOpCode->ExtraData.GetSetData.ValueWidth = 2;
> + break;
> +
> + case EFI_IFR_TYPE_NUM_SIZE_32:
> + ExpressionOpCode->ExtraData.GetSetData.ValueWidth = 4;
> + break;
> +
> + case EFI_IFR_TYPE_NUM_SIZE_64:
> + ExpressionOpCode->ExtraData.GetSetData.ValueWidth = 8;
> + break;
> +
> + case EFI_IFR_TYPE_DATE:
> + ExpressionOpCode->ExtraData.GetSetData.ValueWidth =
> (UINT8)sizeof (EFI_IFR_DATE);
> + break;
> +
> + case EFI_IFR_TYPE_TIME:
> + ExpressionOpCode->ExtraData.GetSetData.ValueWidth =
> (UINT8)sizeof (EFI_IFR_TIME);
> + break;
> +
> + case EFI_IFR_TYPE_REF:
> + ExpressionOpCode->ExtraData.GetSetData.ValueWidth =
> (UINT8)sizeof (EFI_IFR_REF);
> + break;
> +
> + case EFI_IFR_TYPE_OTHER:
> + case EFI_IFR_TYPE_UNDEFINED:
> + case EFI_IFR_TYPE_ACTION:
> + case EFI_IFR_TYPE_BUFFER:
> + default:
> + //
> + // Invalid value type for Get/Set opcode.
> + //
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + CopyMem (
> + &ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo.VarName,
> + &((EFI_IFR_GET *)OpCodeData)->VarStoreInfo.VarName,
> + sizeof (EFI_STRING_ID)
> + );
> + CopyMem (
> + &ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset,
> + &((EFI_IFR_GET *)OpCodeData)->VarStoreInfo.VarOffset,
> + sizeof (UINT16)
> + );
> + if ((ExpressionOpCode->ExtraData.GetSetData.VarStorage != NULL)
> &&
> + ((ExpressionOpCode->ExtraData.GetSetData.VarStorage->Type ==
> EFI_HII_VARSTORE_NAME_VALUE) ||
> + (ExpressionOpCode->ExtraData.GetSetData.VarStorage->Type ==
> EFI_HII_VARSTORE_EFI_VARIABLE)))
> + {
> + ExpressionOpCode->ExtraData.GetSetData.ValueName =
> GetTokenString (ExpressionOpCode-
> >ExtraData.GetSetData.VarStoreInfo.VarName, FormSet->HiiHandle);
> + if (ExpressionOpCode->ExtraData.GetSetData.ValueName == NULL) {
> + //
> + // String ID is invalid.
> + //
> + return EFI_INVALID_PARAMETER;
> + }
> + }
> +
> + break;
> +
> + case EFI_IFR_QUESTION_REF1_OP:
> +
> + CopyMem (&ExpressionOpCode-
> >ExtraData.QuestionRef1Data.QuestionId, &((EFI_IFR_EQ_ID_VAL_LIST
> *)OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
> + break;
> +
> + case EFI_IFR_QUESTION_REF3_OP:
> +
> + if (OpCodeLength >= sizeof (EFI_IFR_QUESTION_REF3_2)) {
> + CopyMem (&ExpressionOpCode-
> >ExtraData.QuestionRef3Data.DevicePath, &((EFI_IFR_QUESTION_REF3_2
> *)OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));
> +
> + if (OpCodeLength >= sizeof (EFI_IFR_QUESTION_REF3_3)) {
> + CopyMem (&ExpressionOpCode->ExtraData.QuestionRef3Data.Guid,
> &((EFI_IFR_QUESTION_REF3_3 *)OpCodeData)->Guid, sizeof (EFI_GUID));
> + }
> + }
> +
> + break;
> +
> + //
> + // constant
> + //
> + case EFI_IFR_TRUE_OP:
> +
> + ExpressionValue = &ExpressionOpCode->ExtraData.Value;
> + ExpressionValue->Type = EFI_IFR_TYPE_BOOLEAN;
> + ExpressionValue->Value.b = TRUE;
> + break;
> +
> + case EFI_IFR_FALSE_OP:
> +
> + ExpressionValue = &ExpressionOpCode->ExtraData.Value;
> + ExpressionValue->Type = EFI_IFR_TYPE_BOOLEAN;
> + ExpressionValue->Value.b = FALSE;
> + break;
> +
> + case EFI_IFR_ONE_OP:
> +
> + ExpressionValue = &ExpressionOpCode->ExtraData.Value;
> + ExpressionValue->Type = EFI_IFR_TYPE_NUM_SIZE_8;
> + ExpressionValue->Value.u8 = 1;
> + break;
> +
> + case EFI_IFR_ZERO_OP:
> +
> + ExpressionValue = &ExpressionOpCode->ExtraData.Value;
> + ExpressionValue->Type = EFI_IFR_TYPE_NUM_SIZE_8;
> + ExpressionValue->Value.u8 = 0;
> + break;
> +
> + case EFI_IFR_ONES_OP:
> +
> + ExpressionValue = &ExpressionOpCode->ExtraData.Value;
> + ExpressionValue->Type = EFI_IFR_TYPE_NUM_SIZE_64;
> + ExpressionValue->Value.u64 = 0xffffffffffffffffULL;
> + break;
> +
> + case EFI_IFR_UINT8_OP:
> +
> + ExpressionValue = &ExpressionOpCode->ExtraData.Value;
> + ExpressionValue->Type = EFI_IFR_TYPE_NUM_SIZE_8;
> + ExpressionValue->Value.u8 = ((EFI_IFR_UINT8 *)OpCodeData)->Value;
> + break;
> +
> + case EFI_IFR_UINT16_OP:
> +
> + ExpressionValue = &ExpressionOpCode->ExtraData.Value;
> + ExpressionValue->Type = EFI_IFR_TYPE_NUM_SIZE_16;
> + CopyMem (&ExpressionValue->Value.u16, &((EFI_IFR_UINT16
> *)OpCodeData)->Value, sizeof (UINT16));
> + break;
> +
> + case EFI_IFR_UINT32_OP:
> +
> + ExpressionValue = &ExpressionOpCode->ExtraData.Value;
> + ExpressionValue->Type = EFI_IFR_TYPE_NUM_SIZE_32;
> + CopyMem (&ExpressionValue->Value.u32, &((EFI_IFR_UINT32
> *)OpCodeData)->Value, sizeof (UINT32));
> + break;
> +
> + case EFI_IFR_UINT64_OP:
> +
> + ExpressionValue = &ExpressionOpCode->ExtraData.Value;
> + ExpressionValue->Type = EFI_IFR_TYPE_NUM_SIZE_64;
> + CopyMem (&ExpressionValue->Value.u64, &((EFI_IFR_UINT64
> *)OpCodeData)->Value, sizeof (UINT64));
> + break;
> +
> + case EFI_IFR_UNDEFINED_OP:
> + ExpressionValue = &ExpressionOpCode->ExtraData.Value;
> + ExpressionValue->Type = EFI_IFR_TYPE_UNDEFINED;
> + break;
> +
> + case EFI_IFR_VERSION_OP:
> + ExpressionValue = &ExpressionOpCode->ExtraData.Value;
> + ExpressionValue->Type = EFI_IFR_TYPE_NUM_SIZE_16;
> + ExpressionValue->Value.u16 = EFI_IFR_SPECIFICATION_VERSION;
> + break;
> +
> + default:
> + break;
> + }
> +
> + //
> + // Create sub expression nested in MAP opcode
> + //
> + if ((CurrentExpression == NULL) && (MapScopeDepth > 0)) {
> + CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
> + if (CurrentExpression == NULL) {
> + continue;
> + }
> +
> + InsertTailList (MapExpressionList, &CurrentExpression->Link);
> + if (Scope == 0) {
> + SingleOpCodeExpression = TRUE;
> + }
> + }
> +
> + InsertTailList (&CurrentExpression->OpCodeListHead,
> &ExpressionOpCode->Link);
> + if (Operand == EFI_IFR_MAP_OP) {
> + //
> + // Store current Map Expression List.
> + //
> + if (MapExpressionList != NULL) {
> + PushMapExpressionList (MapExpressionList);
> + }
> +
> + //
> + // Initialize new Map Expression List.
> + //
> + MapExpressionList = &ExpressionOpCode->MapExpressionList;
> + InitializeListHead (MapExpressionList);
> + //
> + // Store current expression.
> + //
> + PushCurrentExpression (CurrentExpression);
> + CurrentExpression = NULL;
> + MapScopeDepth++;
> + } else if (SingleOpCodeExpression) {
> + //
> + // There are two cases to indicate the end of an Expression:
> + // for single OpCode expression: one Expression OpCode
> + // for expression consists of more than one OpCode: EFI_IFR_END
> + //
> + SingleOpCodeExpression = FALSE;
> +
> + if (InScopeDisable && (CurrentForm == NULL)) {
> + //
> + // This is DisableIf expression for Form, it should be a constant
> expression
> + //
> + Status = EvaluateHiiExpression (FormSet, CurrentForm,
> CurrentExpression);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + OpCodeDisabled = IsHiiValueTrue (&CurrentExpression->Result);
> + }
> +
> + CurrentExpression = NULL;
> + }
> +
> + continue;
> + }
> +
> + //
> + // Parse the Opcode
> + //
> + switch (Operand) {
> + case EFI_IFR_FORM_SET_OP:
> + //
> + // Check the formset GUID
> + //
> +
> + if (CompareMem (&FormSet->Guid, &((EFI_IFR_FORM_SET
> *)OpCodeData)->Guid, sizeof (EFI_GUID)) != 0) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + CopyMem (&FormSet->FormSetTitle, &((EFI_IFR_FORM_SET
> *)OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID));
> + CopyMem (&FormSet->Help, &((EFI_IFR_FORM_SET *)OpCodeData)-
> >Help, sizeof (EFI_STRING_ID));
> +
> + if (OpCodeLength > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) {
> + //
> + // The formset OpCode contains ClassGuid
> + //
> + FormSet->NumberOfClassGuid = (UINT8)(((EFI_IFR_FORM_SET
> *)OpCodeData)->Flags & 0x3);
> + CopyMem (FormSet->ClassGuid, OpCodeData + sizeof
> (EFI_IFR_FORM_SET), FormSet->NumberOfClassGuid * sizeof (EFI_GUID));
> + }
> +
> + break;
> +
> + case EFI_IFR_FORM_OP:
> +
> + //
> + // Create a new Form for this FormSet
> + //
> + CurrentForm = AllocateZeroPool (sizeof (HII_FORM));
> + if (CurrentForm == NULL) {
> + break;
> + }
> +
> + CurrentForm->Signature = HII_FORM_SIGNATURE;
> + InitializeListHead (&CurrentForm->StatementListHead);
> + InitializeListHead (&CurrentForm->ConfigRequestHead);
> + InitializeListHead (&CurrentForm->RuleListHead);
> +
> + CurrentForm->FormType = STANDARD_MAP_FORM_TYPE;
> + CopyMem (&CurrentForm->FormId, &((EFI_IFR_FORM
> *)OpCodeData)->FormId, sizeof (UINT16));
> + CopyMem (&CurrentForm->FormTitle, &((EFI_IFR_FORM
> *)OpCodeData)->FormTitle, sizeof (EFI_STRING_ID));
> +
> + ConditionalExprCount = GetConditionalExpressionCount (ExpressForm);
> + if ( ConditionalExprCount > 0) {
> + //
> + // Form is inside of suppressif
> + //
> + CurrentForm->SuppressExpression = (HII_EXPRESSION_LIST
> *)AllocatePool (
> + (UINTN)(sizeof (HII_EXPRESSION_LIST) +
> ((ConditionalExprCount -1) * sizeof (HII_EXPRESSION *)))
> + );
> + if (CurrentForm->SuppressExpression == NULL) {
> + break;
> + }
> +
> + CurrentForm->SuppressExpression->Count =
> (UINTN)ConditionalExprCount;
> + CurrentForm->SuppressExpression->Signature =
> HII_EXPRESSION_LIST_SIGNATURE;
> + CopyMem (CurrentForm->SuppressExpression->Expression,
> GetConditionalExpressionList (ExpressForm), (UINTN)(sizeof
> (HII_EXPRESSION *) * ConditionalExprCount));
> + }
> +
> + if (Scope != 0) {
> + //
> + // Enter scope of a Form, suppressif will be used for Question or
> Option
> + //
> + SuppressForQuestion = TRUE;
> + }
> +
> + //
> + // Insert into Form list of this FormSet
> + //
> + InsertTailList (&FormSet->FormListHead, &CurrentForm->Link);
> + break;
> +
> + case EFI_IFR_FORM_MAP_OP:
> +
> + //
> + // Create a new Form for this FormSet
> + //
> + CurrentForm = AllocateZeroPool (sizeof (HII_FORM));
> + if (CurrentForm == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + CurrentForm->Signature = HII_FORM_SIGNATURE;
> + InitializeListHead (&CurrentForm->StatementListHead);
> + InitializeListHead (&CurrentForm->ConfigRequestHead);
> + InitializeListHead (&CurrentForm->RuleListHead);
> +
> + CopyMem (&CurrentForm->FormId, &((EFI_IFR_FORM
> *)OpCodeData)->FormId, sizeof (UINT16));
> +
> + MapMethod = (EFI_IFR_FORM_MAP_METHOD *)(OpCodeData + sizeof
> (EFI_IFR_FORM_MAP));
> + //
> + // FormMap Form must contain at least one Map Method.
> + //
> + if (((EFI_IFR_OP_HEADER *)OpCodeData)->Length < ((UINTN)(UINT8
> *)(MapMethod + 1) - (UINTN)OpCodeData)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + //
> + // Try to find the standard form map method.
> + //
> + while (((UINTN)(UINT8 *)MapMethod - (UINTN)OpCodeData) <
> ((EFI_IFR_OP_HEADER *)OpCodeData)->Length) {
> + if (CompareGuid ((EFI_GUID *)(VOID *)&MapMethod-
> >MethodIdentifier, &gEfiHiiStandardFormGuid)) {
> + CopyMem (&CurrentForm->FormTitle, &MapMethod->MethodTitle,
> sizeof (EFI_STRING_ID));
> + CurrentForm->FormType = STANDARD_MAP_FORM_TYPE;
> + break;
> + }
> +
> + MapMethod++;
> + }
> +
> + //
> + // If the standard form map method is not found, the first map method
> title will be used.
> + //
> + if (CurrentForm->FormTitle == 0) {
> + MapMethod = (EFI_IFR_FORM_MAP_METHOD *)(OpCodeData +
> sizeof (EFI_IFR_FORM_MAP));
> + CopyMem (&CurrentForm->FormTitle, &MapMethod->MethodTitle,
> sizeof (EFI_STRING_ID));
> + }
> +
> + ConditionalExprCount = GetConditionalExpressionCount (ExpressForm);
> + if ( ConditionalExprCount > 0) {
> + //
> + // Form is inside of suppressif
> + //
> + CurrentForm->SuppressExpression = (HII_EXPRESSION_LIST
> *)AllocateZeroPool (
> + (UINTN)(sizeof (HII_EXPRESSION_LIST) +
> ((ConditionalExprCount -1) * sizeof (HII_EXPRESSION *)))
> + );
> + if (CurrentForm->SuppressExpression == NULL) {
> + FreePool (CurrentForm);
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + CurrentForm->SuppressExpression->Count =
> (UINTN)ConditionalExprCount;
> + CurrentForm->SuppressExpression->Signature =
> HII_EXPRESSION_LIST_SIGNATURE;
> + CopyMem (CurrentForm->SuppressExpression->Expression,
> GetConditionalExpressionList (ExpressForm), (UINTN)(sizeof
> (HII_EXPRESSION *) * ConditionalExprCount));
> + }
> +
> + if (Scope != 0) {
> + //
> + // Enter scope of a Form, suppressif will be used for Question or
> Option
> + //
> + SuppressForQuestion = TRUE;
> + }
> +
> + //
> + // Insert into Form list of this FormSet
> + //
> + InsertTailList (&FormSet->FormListHead, &CurrentForm->Link);
> + break;
> +
> + //
> + // Storage
> + //
> + case EFI_IFR_VARSTORE_OP:
> +
> + //
> + // Create a buffer Storage for this FormSet
> + //
> + Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_BUFFER,
> OpCodeData);
> + CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE
> *)OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
> + break;
> +
> + case EFI_IFR_VARSTORE_NAME_VALUE_OP:
> +
> + //
> + // Create a name/value Storage for this FormSet
> + //
> + Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_NAME_VALUE,
> OpCodeData);
> + CopyMem (&Storage->VarStoreId,
> &((EFI_IFR_VARSTORE_NAME_VALUE *)OpCodeData)->VarStoreId, sizeof
> (EFI_VARSTORE_ID));
> + break;
> +
> + case EFI_IFR_VARSTORE_EFI_OP:
> +
> + //
> + // Create a EFI variable Storage for this FormSet
> + //
> + if (OpCodeLength < sizeof (EFI_IFR_VARSTORE_EFI)) {
> + //
> + // Create efi varstore with format follow UEFI spec before 2.3.1.
> + //
> + Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_EFI_VARIABLE,
> OpCodeData);
> + } else {
> + //
> + // Create efi varstore with format follow UEFI spec 2.3.1 and later.
> + //
> + Storage = CreateStorage (FormSet,
> EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER, OpCodeData);
> + }
> +
> + CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_EFI
> *)OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
> + break;
> +
> + //
> + // DefaultStore
> + //
> + case EFI_IFR_DEFAULTSTORE_OP:
> +
> + HaveInserted = FALSE;
> + DefaultStore = AllocateZeroPool (sizeof
> (HII_FORMSET_DEFAULTSTORE));
> + if (DefaultStore == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + DefaultStore->Signature = HII_FORMSET_DEFAULTSTORE_SIGNATURE;
> +
> + CopyMem (&DefaultStore->DefaultId, &((EFI_IFR_DEFAULTSTORE
> *)OpCodeData)->DefaultId, sizeof (UINT16));
> + CopyMem (&DefaultStore->DefaultName, &((EFI_IFR_DEFAULTSTORE
> *)OpCodeData)->DefaultName, sizeof (EFI_STRING_ID));
> + //
> + // Insert it to the DefaultStore list of this Formset with ascending order.
> + //
> + if (!IsListEmpty (&FormSet->DefaultStoreListHead)) {
> + DefaultLink = GetFirstNode (&FormSet->DefaultStoreListHead);
> + while (!IsNull (&FormSet->DefaultStoreListHead, DefaultLink)) {
> + PreDefaultStore = HII_FORMSET_DEFAULTSTORE_FROM_LINK
> (DefaultLink);
> + DefaultLink = GetNextNode (&FormSet->DefaultStoreListHead,
> DefaultLink);
> + if (DefaultStore->DefaultId < PreDefaultStore->DefaultId) {
> + InsertTailList (&PreDefaultStore->Link, &DefaultStore->Link);
> + HaveInserted = TRUE;
> + break;
> + }
> + }
> + }
> +
> + if (!HaveInserted) {
> + InsertTailList (&FormSet->DefaultStoreListHead, &DefaultStore->Link);
> + }
> +
> + break;
> +
> + //
> + // Statements
> + //
> + case EFI_IFR_SUBTITLE_OP:
> +
> + CurrentStatement = CreateStatement (OpCodeData, FormSet,
> CurrentForm);
> + break;
> +
> + case EFI_IFR_TEXT_OP:
> +
> + CurrentStatement = CreateStatement (OpCodeData, FormSet,
> CurrentForm);
> + CopyMem (&CurrentStatement->ExtraData.TextTwo, &((EFI_IFR_TEXT
> *)OpCodeData)->TextTwo, sizeof (EFI_STRING_ID));
> + break;
> +
> + case EFI_IFR_RESET_BUTTON_OP:
> +
> + CurrentStatement = CreateStatement (OpCodeData, FormSet,
> CurrentForm);
> + CopyMem (&CurrentStatement->ExtraData.DefaultId,
> &((EFI_IFR_RESET_BUTTON *)OpCodeData)->DefaultId, sizeof
> (EFI_DEFAULT_ID));
> + break;
> +
> + //
> + // Questions
> + //
> + case EFI_IFR_ACTION_OP:
> +
> + CurrentStatement = CreateQuestion (OpCodeData, FormSet,
> CurrentForm);
> + CurrentStatement->Value.Type = EFI_IFR_TYPE_ACTION;
> +
> + if (OpCodeLength == sizeof (EFI_IFR_ACTION_1)) {
> + //
> + // No QuestionConfig present, so no configuration string will be
> processed
> + //
> + CurrentStatement->ExtraData.QuestionConfig = 0;
> + } else {
> + CopyMem (&CurrentStatement->ExtraData.QuestionConfig,
> &((EFI_IFR_ACTION *)OpCodeData)->QuestionConfig, sizeof
> (EFI_STRING_ID));
> + }
> +
> + break;
> +
> + case EFI_IFR_REF_OP:
> +
> + CurrentStatement = CreateQuestion (OpCodeData, FormSet,
> CurrentForm);
> + StatementValue = &CurrentStatement->Value;
> + StatementValue->Type = EFI_IFR_TYPE_REF;
> + if (OpCodeLength >= sizeof (EFI_IFR_REF)) {
> + CopyMem (&StatementValue->Value.ref.FormId, &((EFI_IFR_REF
> *)OpCodeData)->FormId, sizeof (EFI_FORM_ID));
> +
> + if (OpCodeLength >= sizeof (EFI_IFR_REF2)) {
> + CopyMem (&StatementValue->Value.ref.QuestionId,
> &((EFI_IFR_REF2 *)OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
> +
> + if (OpCodeLength >= sizeof (EFI_IFR_REF3)) {
> + CopyMem (&StatementValue->Value.ref.FormSetGuid,
> &((EFI_IFR_REF3 *)OpCodeData)->FormSetId, sizeof (EFI_GUID));
> +
> + if (OpCodeLength >= sizeof (EFI_IFR_REF4)) {
> + CopyMem (&StatementValue->Value.ref.DevicePath,
> &((EFI_IFR_REF4 *)OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));
> + }
> + }
> + }
> + }
> +
> + CurrentStatement->StorageWidth = (UINT16)sizeof (EFI_HII_REF);
> + InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
> + break;
> +
> + case EFI_IFR_ONE_OF_OP:
> + case EFI_IFR_NUMERIC_OP:
> +
> + CurrentStatement = CreateQuestion (OpCodeData,
> FormSet, CurrentForm);
> + CurrentStatement->ExtraData.NumData.Flags = ((EFI_IFR_ONE_OF
> *)OpCodeData)->Flags;
> + StatementValue = &CurrentStatement->Value;
> +
> + if (QuestionReferBitField) {
> + //
> + // Get the bit var store info (bit/byte offset, bit/byte offset)
> + //
> + CurrentStatement->QuestionReferToBitField = TRUE;
> + CurrentStatement->BitStorageWidth = CurrentStatement-
> >ExtraData.NumData.Flags & EDKII_IFR_NUMERIC_SIZE_BIT;
> + CurrentStatement->BitVarOffset = CurrentStatement-
> >VarStoreInfo.VarOffset;
> + CurrentStatement->VarStoreInfo.VarOffset = CurrentStatement-
> >BitVarOffset / 8;
> + TotalBits = CurrentStatement->BitVarOffset % 8 +
> CurrentStatement->BitStorageWidth;
> + CurrentStatement->StorageWidth = (TotalBits % 8 == 0 ? TotalBits
> / 8 : TotalBits / 8 + 1);
> +
> + //
> + // Get the Minimum/Maximum/Step value(Note: bit field type has
> been stored as UINT32 type)
> + //
> + CurrentStatement->ExtraData.NumData.Minimum =
> ((EFI_IFR_NUMERIC *)OpCodeData)->data.u32.MinValue;
> + CurrentStatement->ExtraData.NumData.Maximum =
> ((EFI_IFR_NUMERIC *)OpCodeData)->data.u32.MaxValue;
> + CurrentStatement->ExtraData.NumData.Step = ((EFI_IFR_NUMERIC
> *)OpCodeData)->data.u32.Step;
> +
> + //
> + // Update the Flag and type of Minimum/Maximum/Step according to
> the actual width of bit field,
> + // in order to make Browser handle these question with bit varstore
> correctly.
> + //
> + ((EFI_IFR_NUMERIC *)OpCodeData)->Flags &=
> EDKII_IFR_DISPLAY_BIT;
> + ((EFI_IFR_NUMERIC *)OpCodeData)->Flags >>= 2;
> + switch (CurrentStatement->StorageWidth) {
> + case 1:
> + ((EFI_IFR_NUMERIC *)OpCodeData)->Flags |=
> EFI_IFR_TYPE_NUM_SIZE_8;
> + ((EFI_IFR_NUMERIC *)OpCodeData)->data.u8.MinValue =
> (UINT8)CurrentStatement->ExtraData.NumData.Minimum;
> + ((EFI_IFR_NUMERIC *)OpCodeData)->data.u8.MaxValue =
> (UINT8)CurrentStatement->ExtraData.NumData.Maximum;
> + ((EFI_IFR_NUMERIC *)OpCodeData)->data.u8.Step =
> (UINT8)CurrentStatement->ExtraData.NumData.Step;
> + StatementValue->Type = EFI_IFR_TYPE_NUM_SIZE_8;
> + break;
> + case 2:
> + ((EFI_IFR_NUMERIC *)OpCodeData)->Flags |=
> EFI_IFR_TYPE_NUM_SIZE_16;
> + ((EFI_IFR_NUMERIC *)OpCodeData)->data.u16.MinValue =
> (UINT16)CurrentStatement->ExtraData.NumData.Minimum;
> + ((EFI_IFR_NUMERIC *)OpCodeData)->data.u16.MaxValue =
> (UINT16)CurrentStatement->ExtraData.NumData.Maximum;
> + ((EFI_IFR_NUMERIC *)OpCodeData)->data.u16.Step =
> (UINT16)CurrentStatement->ExtraData.NumData.Step;
> + StatementValue->Type =
> EFI_IFR_TYPE_NUM_SIZE_16;
> + break;
> + case 3:
> + case 4:
> + ((EFI_IFR_NUMERIC *)OpCodeData)->Flags |=
> EFI_IFR_TYPE_NUM_SIZE_32;
> + ((EFI_IFR_NUMERIC *)OpCodeData)->data.u32.MinValue =
> (UINT32)CurrentStatement->ExtraData.NumData.Minimum;
> + ((EFI_IFR_NUMERIC *)OpCodeData)->data.u32.MaxValue =
> (UINT32)CurrentStatement->ExtraData.NumData.Maximum;
> + ((EFI_IFR_NUMERIC *)OpCodeData)->data.u32.Step =
> (UINT32)CurrentStatement->ExtraData.NumData.Step;
> + StatementValue->Type =
> EFI_IFR_TYPE_NUM_SIZE_32;
> + break;
> + default:
> + break;
> + }
> + } else {
> + switch (CurrentStatement->ExtraData.NumData.Flags &
> EFI_IFR_NUMERIC_SIZE) {
> + case EFI_IFR_NUMERIC_SIZE_1:
> + CurrentStatement->ExtraData.NumData.Minimum =
> ((EFI_IFR_NUMERIC *)OpCodeData)->data.u8.MinValue;
> + CurrentStatement->ExtraData.NumData.Maximum =
> ((EFI_IFR_NUMERIC *)OpCodeData)->data.u8.MaxValue;
> + CurrentStatement->ExtraData.NumData.Step =
> ((EFI_IFR_NUMERIC *)OpCodeData)->data.u8.Step;
> + CurrentStatement->StorageWidth = (UINT16)sizeof (UINT8);
> + StatementValue->Type = EFI_IFR_TYPE_NUM_SIZE_8;
> +
> + break;
> +
> + case EFI_IFR_NUMERIC_SIZE_2:
> + CopyMem (&CurrentStatement->ExtraData.NumData.Minimum,
> &((EFI_IFR_NUMERIC *)OpCodeData)->data.u16.MinValue, sizeof (UINT16));
> + CopyMem (&CurrentStatement->ExtraData.NumData.Maximum,
> &((EFI_IFR_NUMERIC *)OpCodeData)->data.u16.MaxValue, sizeof (UINT16));
> + CopyMem (&CurrentStatement->ExtraData.NumData.Step,
> &((EFI_IFR_NUMERIC *)OpCodeData)->data.u16.Step, sizeof (UINT16));
> + CurrentStatement->StorageWidth = (UINT16)sizeof (UINT16);
> + StatementValue->Type = EFI_IFR_TYPE_NUM_SIZE_16;
> +
> + break;
> +
> + case EFI_IFR_NUMERIC_SIZE_4:
> + CopyMem (&CurrentStatement->ExtraData.NumData.Minimum,
> &((EFI_IFR_NUMERIC *)OpCodeData)->data.u32.MinValue, sizeof (UINT32));
> + CopyMem (&CurrentStatement->ExtraData.NumData.Maximum,
> &((EFI_IFR_NUMERIC *)OpCodeData)->data.u32.MaxValue, sizeof (UINT32));
> + CopyMem (&CurrentStatement->ExtraData.NumData.Step,
> &((EFI_IFR_NUMERIC *)OpCodeData)->data.u32.Step, sizeof (UINT32));
> + CurrentStatement->StorageWidth = (UINT16)sizeof (UINT32);
> + StatementValue->Type = EFI_IFR_TYPE_NUM_SIZE_32;
> +
> + break;
> +
> + case EFI_IFR_NUMERIC_SIZE_8:
> + CopyMem (&CurrentStatement->ExtraData.NumData.Minimum,
> &((EFI_IFR_NUMERIC *)OpCodeData)->data.u64.MinValue, sizeof (UINT64));
> + CopyMem (&CurrentStatement->ExtraData.NumData.Maximum,
> &((EFI_IFR_NUMERIC *)OpCodeData)->data.u64.MaxValue, sizeof (UINT64));
> + CopyMem (&CurrentStatement->ExtraData.NumData.Step,
> &((EFI_IFR_NUMERIC *)OpCodeData)->data.u64.Step, sizeof (UINT64));
> + CurrentStatement->StorageWidth = (UINT16)sizeof (UINT64);
> + StatementValue->Type = EFI_IFR_TYPE_NUM_SIZE_64;
> +
> + break;
> +
> + default:
> +
> + break;
> + }
> + }
> +
> + InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
> +
> + if ((Operand == EFI_IFR_ONE_OF_OP) && (Scope != 0)) {
> + SuppressForOption = TRUE;
> + }
> +
> + break;
> +
> + case EFI_IFR_ORDERED_LIST_OP:
> +
> + CurrentStatement = CreateQuestion (OpCodeData,
> FormSet, CurrentForm);
> + CurrentStatement->ExtraData.OrderListData.Flags =
> ((EFI_IFR_ORDERED_LIST *)OpCodeData)->Flags;
> + CurrentStatement->ExtraData.OrderListData.MaxContainers =
> ((EFI_IFR_ORDERED_LIST *)OpCodeData)->MaxContainers;
> + CurrentStatement->Value.Type = EFI_IFR_TYPE_BUFFER;
> + CurrentStatement->Value.Buffer = NULL;
> +
> + if (Scope != 0) {
> + SuppressForOption = TRUE;
> + }
> +
> + break;
> +
> + case EFI_IFR_CHECKBOX_OP:
> +
> + CurrentStatement = CreateQuestion (OpCodeData, FormSet,
> CurrentForm);
> + CurrentStatement->ExtraData.Flags = ((EFI_IFR_CHECKBOX
> *)OpCodeData)->Flags;
> + CurrentStatement->StorageWidth = (UINT16)sizeof (BOOLEAN);
> + CurrentStatement->Value.Type = EFI_IFR_TYPE_BOOLEAN;
> +
> + if (QuestionReferBitField) {
> + //
> + // Get the bit var store info (bit/byte offset, bit/byte offset)
> + //
> + CurrentStatement->QuestionReferToBitField = TRUE;
> + CurrentStatement->BitStorageWidth = 1;
> + CurrentStatement->BitVarOffset = CurrentStatement-
> >VarStoreInfo.VarOffset;
> + CurrentStatement->VarStoreInfo.VarOffset = CurrentStatement-
> >BitVarOffset / 8;
> + TotalBits = CurrentStatement->BitVarOffset % 8 +
> CurrentStatement->BitStorageWidth;
> + CurrentStatement->StorageWidth = (TotalBits % 8 == 0 ? TotalBits
> / 8 : TotalBits / 8 + 1);
> + }
> +
> + InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
> +
> + break;
> +
> + case EFI_IFR_STRING_OP:
> +
> + CurrentStatement = CreateQuestion (OpCodeData, FormSet,
> CurrentForm);
> +
> + //
> + // MinSize is the minimum number of characters that can be accepted
> for this opcode,
> + // MaxSize is the maximum number of characters that can be accepted
> for this opcode.
> + // The characters are stored as Unicode, so the storage width should
> multiply 2.
> + //
> + CurrentStatement->ExtraData.StrData.MinSize = ((EFI_IFR_STRING
> *)OpCodeData)->MinSize;
> + CurrentStatement->ExtraData.StrData.MaxSize = ((EFI_IFR_STRING
> *)OpCodeData)->MaxSize;
> + CurrentStatement->ExtraData.StrData.Flags = ((EFI_IFR_STRING
> *)OpCodeData)->Flags;
> + CurrentStatement->StorageWidth =
> (UINT16)((UINTN)CurrentStatement->ExtraData.StrData.MaxSize * sizeof
> (CHAR16));
> +
> + CurrentStatement->Value.Type = EFI_IFR_TYPE_STRING;
> + CurrentStatement->Value.Buffer = AllocateZeroPool
> (CurrentStatement->StorageWidth + sizeof (CHAR16));
> + if (CurrentStatement->Value.Buffer == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + CurrentStatement->Value.Value.string = NewHiiString ((CHAR16
> *)CurrentStatement->Value.Buffer, FormSet->HiiHandle);
> +
> + InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
> + break;
> +
> + case EFI_IFR_PASSWORD_OP:
> +
> + CurrentStatement = CreateQuestion (OpCodeData, FormSet,
> CurrentForm);
> +
> + //
> + // MinSize is the minimum number of characters that can be accepted
> for this opcode,
> + // MaxSize is the maximum number of characters that can be accepted
> for this opcode.
> + // The characters are stored as Unicode, so the storage width should
> multiply 2.
> + //
> + CopyMem (&CurrentStatement->ExtraData.PwdData.MinSize,
> &((EFI_IFR_PASSWORD *)OpCodeData)->MinSize, sizeof (UINT16));
> + CopyMem (&CurrentStatement->ExtraData.PwdData.MaxSize,
> &((EFI_IFR_PASSWORD *)OpCodeData)->MaxSize, sizeof (UINT16));
> + CurrentStatement->StorageWidth =
> (UINT16)((UINTN)CurrentStatement->ExtraData.PwdData.MaxSize * sizeof
> (CHAR16));
> +
> + CurrentStatement->Value.Type = EFI_IFR_TYPE_STRING;
> + CurrentStatement->Value.Buffer = AllocateZeroPool
> ((CurrentStatement->StorageWidth + sizeof (CHAR16)));
> + if (CurrentStatement->Value.Buffer == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + CurrentStatement->Value.Value.string = NewHiiString ((CHAR16
> *)CurrentStatement->Value.Buffer, FormSet->HiiHandle);
> +
> + InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
> + break;
> +
> + case EFI_IFR_DATE_OP:
> +
> + CurrentStatement = CreateQuestion (OpCodeData, FormSet,
> CurrentForm);
> + CurrentStatement->ExtraData.Flags = ((EFI_IFR_DATE *)OpCodeData)-
> >Flags;
> + CurrentStatement->Value.Type = EFI_IFR_TYPE_DATE;
> +
> + if ((CurrentStatement->ExtraData.Flags & EFI_QF_DATE_STORAGE) ==
> QF_DATE_STORAGE_NORMAL) {
> + CurrentStatement->StorageWidth = (UINT16)sizeof (EFI_HII_DATE);
> +
> + InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
> + } else {
> + //
> + // Don't assign storage for RTC type of date/time
> + //
> + CurrentStatement->Storage = NULL;
> + CurrentStatement->StorageWidth = 0;
> + }
> +
> + break;
> +
> + case EFI_IFR_TIME_OP:
> +
> + CurrentStatement = CreateQuestion (OpCodeData, FormSet,
> CurrentForm);
> + CurrentStatement->ExtraData.Flags = ((EFI_IFR_TIME *)OpCodeData)-
> >Flags;
> + CurrentStatement->Value.Type = EFI_IFR_TYPE_TIME;
> +
> + if ((CurrentStatement->ExtraData.Flags & QF_TIME_STORAGE) ==
> QF_TIME_STORAGE_NORMAL) {
> + CurrentStatement->StorageWidth = (UINT16)sizeof (EFI_HII_TIME);
> +
> + InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
> + } else {
> + //
> + // Don't assign storage for RTC type of date/time
> + //
> + CurrentStatement->Storage = NULL;
> + CurrentStatement->StorageWidth = 0;
> + }
> +
> + break;
> +
> + //
> + // Default
> + //
> + case EFI_IFR_DEFAULT_OP:
> +
> + //
> + // EFI_IFR_DEFAULT appear in scope of a Question,
> + // It creates a default value for the current question.
> + // A Question may have more than one Default value which have
> different default types.
> + //
> + CurrentDefault = AllocateZeroPool (sizeof (HII_QUESTION_DEFAULT));
> + if (CurrentDefault == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + CurrentDefault->Signature = HII_QUESTION_DEFAULT_SIGNATURE;
> +
> + CurrentDefault->Value.Type = ((EFI_IFR_DEFAULT *)OpCodeData)-
> >Type;
> + CopyMem (&CurrentDefault->DefaultId, &((EFI_IFR_DEFAULT
> *)OpCodeData)->DefaultId, sizeof (UINT16));
> + if (CurrentDefault->Value.Type == EFI_IFR_TYPE_BUFFER) {
> + CurrentDefault->Value.BufferLen = (UINT16)(OpCodeLength -
> OFFSET_OF (EFI_IFR_DEFAULT, Value));
> + CurrentDefault->Value.Buffer = AllocateCopyPool (CurrentDefault-
> >Value.BufferLen, &((EFI_IFR_DEFAULT *)OpCodeData)->Value);
> + if (CurrentDefault->Value.Buffer == NULL) {
> + FreePool (CurrentDefault);
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + if (ParentStatement->Operand == EFI_IFR_ORDERED_LIST_OP) {
> + ParentStatement->Value.BufferLen = CurrentDefault-
> >Value.BufferLen;
> + CopyMem (ParentStatement->Value.Buffer, CurrentDefault-
> >Value.Buffer, ParentStatement->Value.BufferLen);
> + }
> + } else {
> + CopyMem (&CurrentDefault->Value.Value, &((EFI_IFR_DEFAULT
> *)OpCodeData)->Value, OpCodeLength - OFFSET_OF (EFI_IFR_DEFAULT,
> Value));
> + ExtendValueToU64 (&CurrentDefault->Value);
> +
> + CopyMem (&ParentStatement->Value.Value, &((EFI_IFR_DEFAULT
> *)OpCodeData)->Value, OpCodeLength - OFFSET_OF (EFI_IFR_DEFAULT,
> Value));
> + ExtendValueToU64 (&ParentStatement->Value);
> + }
> +
> + //
> + // Insert to Default Value list of current Question
> + //
> + InsertTailList (&ParentStatement->DefaultListHead, &CurrentDefault-
> >Link);
> +
> + if (Scope != 0) {
> + InScopeDefault = TRUE;
> + }
> +
> + break;
> +
> + //
> + // Option
> + //
> + case EFI_IFR_ONE_OF_OPTION_OP:
> +
> + if (ParentStatement == NULL) {
> + break;
> + }
> +
> + CurrentDefault = NULL;
> + if (((ParentStatement->Operand == EFI_IFR_ORDERED_LIST_OP) ||
> (ParentStatement->Operand == EFI_IFR_ONE_OF_OP)) &&
> + ((((EFI_IFR_ONE_OF_OPTION *)OpCodeData)->Flags &
> (EFI_IFR_OPTION_DEFAULT | EFI_IFR_OPTION_DEFAULT_MFG)) != 0))
> + {
> + CurrentDefault = AllocateZeroPool (sizeof (HII_QUESTION_DEFAULT));
> + if (CurrentDefault == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + CurrentDefault->Signature = HII_QUESTION_DEFAULT_SIGNATURE;
> + if ((((EFI_IFR_ONE_OF_OPTION *)OpCodeData)->Flags &
> EFI_IFR_OPTION_DEFAULT) != 0) {
> + CurrentDefault->DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
> + } else {
> + CurrentDefault->DefaultId =
> EFI_HII_DEFAULT_CLASS_MANUFACTURING;
> + }
> +
> + if (ParentStatement->Operand == EFI_IFR_ORDERED_LIST_OP) {
> + CurrentDefault->Value.Type = EFI_IFR_TYPE_BUFFER;
> + CurrentDefault->Value.BufferLen = (UINT16)(OpCodeLength -
> OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
> + CurrentDefault->Value.Buffer = AllocateCopyPool (CurrentDefault-
> >Value.BufferLen, &((EFI_IFR_ONE_OF_OPTION *)OpCodeData)->Value);
> + if (CurrentDefault->Value.Buffer == NULL) {
> + FreePool (CurrentDefault);
> + return EFI_OUT_OF_RESOURCES;
> + }
> + } else {
> + CurrentDefault->Value.Type = ((EFI_IFR_ONE_OF_OPTION
> *)OpCodeData)->Type;
> + CopyMem (&CurrentDefault->Value.Value,
> &((EFI_IFR_ONE_OF_OPTION *)OpCodeData)->Value, sizeof
> (EFI_IFR_TYPE_VALUE));
> + ExtendValueToU64 (&CurrentDefault->Value);
> + }
> +
> + //
> + // Insert to Default Value list of current Question
> + //
> + InsertTailList (&ParentStatement->DefaultListHead, &CurrentDefault-
> >Link);
> + }
> +
> + //
> + // EFI_IFR_ONE_OF_OPTION appear in scope of a Question.
> + // It create a selection for use in current Question.
> + //
> + CurrentOption = AllocateZeroPool (sizeof (HII_QUESTION_OPTION));
> + if (CurrentOption == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + CurrentOption->Signature = HII_QUESTION_OPTION_SIGNATURE;
> + CurrentOption->OpCode = (EFI_IFR_ONE_OF_OPTION
> *)OpCodeData;
> + CurrentOption->Flags = ((EFI_IFR_ONE_OF_OPTION *)OpCodeData)-
> >Flags;
> + CurrentOption->Value.Type = ((EFI_IFR_ONE_OF_OPTION
> *)OpCodeData)->Type;
> + CopyMem (&CurrentOption->Text, &((EFI_IFR_ONE_OF_OPTION
> *)OpCodeData)->Option, sizeof (EFI_STRING_ID));
> + CopyMem (&CurrentOption->Value.Value,
> &((EFI_IFR_ONE_OF_OPTION *)OpCodeData)->Value, OpCodeLength -
> OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
> + ExtendValueToU64 (&CurrentOption->Value);
> +
> + ConditionalExprCount = GetConditionalExpressionCount
> (ExpressOption);
> + if ( ConditionalExprCount > 0) {
> + //
> + // Form is inside of suppressif
> + //
> + CurrentOption->SuppressExpression = (HII_EXPRESSION_LIST
> *)AllocatePool (
> + (UINTN)(sizeof (HII_EXPRESSION_LIST) +
> ((ConditionalExprCount -1) * sizeof (HII_EXPRESSION *)))
> + );
> + if (CurrentOption->SuppressExpression == NULL) {
> + FreePool (CurrentOption);
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + CurrentOption->SuppressExpression->Count =
> (UINTN)ConditionalExprCount;
> + CurrentOption->SuppressExpression->Signature =
> HII_EXPRESSION_LIST_SIGNATURE;
> + CopyMem (CurrentOption->SuppressExpression->Expression,
> GetConditionalExpressionList (ExpressOption), (UINTN)(sizeof
> (HII_EXPRESSION *) * ConditionalExprCount));
> + }
> +
> + //
> + // Insert to Option list of current Question
> + //
> + InsertTailList (&ParentStatement->OptionListHead, &CurrentOption-
> >Link);
> +
> + //
> + // Now we know the Storage width of nested Ordered List
> + //
> + if ((ParentStatement->Operand == EFI_IFR_ORDERED_LIST_OP) &&
> (ParentStatement->Value.Buffer == NULL)) {
> + Width = 1;
> + switch (CurrentOption->Value.Type) {
> + case EFI_IFR_TYPE_NUM_SIZE_8:
> + Width = 1;
> + break;
> +
> + case EFI_IFR_TYPE_NUM_SIZE_16:
> + Width = 2;
> + break;
> +
> + case EFI_IFR_TYPE_NUM_SIZE_32:
> + Width = 4;
> + break;
> +
> + case EFI_IFR_TYPE_NUM_SIZE_64:
> + Width = 8;
> + break;
> +
> + default:
> + //
> + // Invalid type for Ordered List
> + //
> + break;
> + }
> +
> + ParentStatement->StorageWidth = (UINT16)(ParentStatement-
> >ExtraData.OrderListData.MaxContainers * Width);
> + ParentStatement->Value.Buffer = AllocateZeroPool
> (ParentStatement->StorageWidth);
> + if (ParentStatement->Value.Buffer == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + ParentStatement->Value.BufferLen = 0;
> + ParentStatement->Value.BufferValueType = CurrentOption-
> >Value.Type;
> + InitializeRequestElement (FormSet, ParentStatement, CurrentForm);
> + }
> +
> + break;
> +
> + //
> + // Conditional
> + //
> + case EFI_IFR_NO_SUBMIT_IF_OP:
> + case EFI_IFR_INCONSISTENT_IF_OP:
> +
> + //
> + // Create an Expression node
> + //
> + CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
> + CopyMem (&CurrentExpression->ExtraData.Error,
> &((EFI_IFR_INCONSISTENT_IF *)OpCodeData)->Error, sizeof
> (EFI_STRING_ID));
> +
> + if (Operand == EFI_IFR_NO_SUBMIT_IF_OP) {
> + CurrentExpression->Type = EFI_HII_EXPRESSION_NO_SUBMIT_IF;
> + InsertTailList (&ParentStatement->NoSubmitListHead,
> &CurrentExpression->Link);
> + } else {
> + CurrentExpression->Type = EFI_HII_EXPRESSION_INCONSISTENT_IF;
> + InsertTailList (&ParentStatement->InconsistentListHead,
> &CurrentExpression->Link);
> + }
> +
> + //
> + // Take a look at next OpCode to see whether current expression
> consists
> + // of single OpCode
> + //
> + if (((EFI_IFR_OP_HEADER *)(OpCodeData + OpCodeLength))->Scope ==
> 0) {
> + SingleOpCodeExpression = TRUE;
> + }
> +
> + break;
> +
> + case EFI_IFR_WARNING_IF_OP:
> +
> + //
> + // Create an Expression node
> + //
> + CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
> + CopyMem (&CurrentExpression-
> >ExtraData.WarningIfData.WarningIfError, &((EFI_IFR_WARNING_IF
> *)OpCodeData)->Warning, sizeof (EFI_STRING_ID));
> + CurrentExpression->ExtraData.WarningIfData.TimeOut =
> ((EFI_IFR_WARNING_IF *)OpCodeData)->TimeOut;
> + CurrentExpression->Type =
> EFI_HII_EXPRESSION_WARNING_IF;
> + InsertTailList (&ParentStatement->WarningListHead,
> &CurrentExpression->Link);
> +
> + //
> + // Take a look at next OpCode to see whether current expression
> consists
> + // of single OpCode
> + //
> + if (((EFI_IFR_OP_HEADER *)(OpCodeData + OpCodeLength))->Scope ==
> 0) {
> + SingleOpCodeExpression = TRUE;
> + }
> +
> + break;
> +
> + case EFI_IFR_SUPPRESS_IF_OP:
> +
> + //
> + // Question and Option will appear in scope of this OpCode
> + //
> + CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
> + CurrentExpression->Type = EFI_HII_EXPRESSION_SUPPRESS_IF;
> +
> + if (SuppressForOption) {
> + PushConditionalExpression (CurrentExpression, ExpressOption);
> + } else if (SuppressForQuestion) {
> + PushConditionalExpression (CurrentExpression, ExpressStatement);
> + } else {
> + PushConditionalExpression (CurrentExpression, ExpressForm);
> + }
> +
> + //
> + // Take a look at next OpCode to see whether current expression
> consists
> + // of single OpCode
> + //
> + if (((EFI_IFR_OP_HEADER *)(OpCodeData + OpCodeLength))->Scope ==
> 0) {
> + SingleOpCodeExpression = TRUE;
> + }
> +
> + break;
> +
> + case EFI_IFR_GRAY_OUT_IF_OP:
> +
> + //
> + // Questions will appear in scope of this OpCode
> + //
> + CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
> + CurrentExpression->Type = EFI_HII_EXPRESSION_GRAY_OUT_IF;
> + PushConditionalExpression (CurrentExpression, ExpressStatement);
> +
> + //
> + // Take a look at next OpCode to see whether current expression
> consists
> + // of single OpCode
> + //
> + if (((EFI_IFR_OP_HEADER *)(OpCodeData + OpCodeLength))->Scope ==
> 0) {
> + SingleOpCodeExpression = TRUE;
> + }
> +
> + break;
> +
> + case EFI_IFR_DISABLE_IF_OP:
> +
> + //
> + // The DisableIf expression should only rely on constant, so it could be
> + // evaluated at initialization and it will not be queued
> + //
> + CurrentExpression = AllocateZeroPool (sizeof (HII_EXPRESSION));
> + if (CurrentExpression == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + CurrentExpression->Signature = HII_EXPRESSION_SIGNATURE;
> + CurrentExpression->Type = EFI_HII_EXPRESSION_DISABLE_IF;
> + InitializeListHead (&CurrentExpression->OpCodeListHead);
> +
> + if (CurrentForm != NULL) {
> + //
> + // This is DisableIf for Question, enqueue it to Form expression list
> + //
> + PushConditionalExpression (CurrentExpression, ExpressStatement);
> + }
> +
> + OpCodeDisabled = FALSE;
> + InScopeDisable = TRUE;
> + //
> + // Take a look at next OpCode to see whether current expression
> consists
> + // of single OpCode
> + //
> + if (((EFI_IFR_OP_HEADER *)(OpCodeData + OpCodeLength))->Scope ==
> 0) {
> + SingleOpCodeExpression = TRUE;
> + }
> +
> + break;
> +
> + //
> + // Expression
> + //
> + case EFI_IFR_VALUE_OP:
> +
> + CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
> + CurrentExpression->Type = EFI_HII_EXPRESSION_VALUE;
> +
> + if (InScopeDefault) {
> + //
> + // Used for default (EFI_IFR_DEFAULT)
> + //
> + CurrentDefault->ValueExpression = CurrentExpression;
> + } else {
> + //
> + // If used for a question, then the question will be read-only
> + //
> + // Make sure CurrentStatement is not NULL.
> + // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly.
> Or 2) the IFR
> + // file is wrongly generated by tools such as VFR Compiler. There may
> be a bug in VFR Compiler.
> + //
> + if (ParentStatement == NULL) {
> + break;
> + }
> +
> + ParentStatement->ValueExpression = CurrentExpression;
> + }
> +
> + //
> + // Take a look at next OpCode to see whether current expression
> consists
> + // of single OpCode
> + //
> + if (((EFI_IFR_OP_HEADER *)(OpCodeData + OpCodeLength))->Scope ==
> 0) {
> + SingleOpCodeExpression = TRUE;
> + }
> +
> + break;
> +
> + case EFI_IFR_RULE_OP:
> +
> + CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
> + CurrentExpression->Type = EFI_HII_EXPRESSION_RULE;
> +
> + CurrentExpression->ExtraData.RuleId = ((EFI_IFR_RULE
> *)OpCodeData)->RuleId;
> + InsertTailList (&CurrentForm->RuleListHead, &CurrentExpression->Link);
> +
> + //
> + // Take a look at next OpCode to see whether current expression
> consists
> + // of single OpCode
> + //
> + if (((EFI_IFR_OP_HEADER *)(OpCodeData + OpCodeLength))->Scope ==
> 0) {
> + SingleOpCodeExpression = TRUE;
> + }
> +
> + break;
> +
> + case EFI_IFR_READ_OP:
> +
> + CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
> + CurrentExpression->Type = EFI_HII_EXPRESSION_READ;
> +
> + //
> + // Make sure CurrentStatement is not NULL.
> + // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly.
> Or 2) the IFR
> + // file is wrongly generated by tools such as VFR Compiler. There may
> be a bug in VFR Compiler.
> + //
> + if (ParentStatement == NULL) {
> + break;
> + }
> +
> + ParentStatement->ReadExpression = CurrentExpression;
> +
> + //
> + // Take a look at next OpCode to see whether current expression
> consists
> + // of single OpCode
> + //
> + if (((EFI_IFR_OP_HEADER *)(OpCodeData + OpCodeLength))->Scope ==
> 0) {
> + SingleOpCodeExpression = TRUE;
> + }
> +
> + break;
> +
> + case EFI_IFR_WRITE_OP:
> +
> + CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
> + CurrentExpression->Type = EFI_HII_EXPRESSION_WRITE;
> +
> + //
> + // Make sure CurrentStatement is not NULL.
> + // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly.
> Or 2) the IFR
> + // file is wrongly generated by tools such as VFR Compiler. There may
> be a bug in VFR Compiler.
> + //
> + if (ParentStatement == NULL) {
> + break;
> + }
> +
> + ParentStatement->WriteExpression = CurrentExpression;
> +
> + //
> + // Take a look at next OpCode to see whether current expression
> consists
> + // of single OpCode
> + //
> + if (((EFI_IFR_OP_HEADER *)(OpCodeData + OpCodeLength))->Scope ==
> 0) {
> + SingleOpCodeExpression = TRUE;
> + }
> +
> + break;
> +
> + //
> + // Image
> + //
> + case EFI_IFR_IMAGE_OP:
> + //
> + // Get ScopeOpcode from top of stack
> + //
> + PopScope (&ScopeOpCode);
> + PushScope (ScopeOpCode);
> +
> + switch (ScopeOpCode) {
> + case EFI_IFR_FORM_SET_OP:
> +
> + ImageId = &FormSet->ImageId;
> + break;
> +
> + case EFI_IFR_FORM_OP:
> + case EFI_IFR_FORM_MAP_OP:
> +
> + if (CurrentForm != NULL) {
> + ImageId = &CurrentForm->ImageId;
> + }
> +
> + break;
> +
> + case EFI_IFR_ONE_OF_OPTION_OP:
> +
> + if (CurrentOption != NULL) {
> + ImageId = &CurrentOption->ImageId;
> + }
> +
> + break;
> +
> + default:
> +
> + //
> + // Make sure CurrentStatement is not NULL.
> + // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly.
> Or 2) the IFR
> + // file is wrongly generated by tools such as VFR Compiler.
> + //
> + if (ParentStatement != NULL) {
> + ImageId = &ParentStatement->ImageId;
> + }
> +
> + break;
> + }
> +
> + CopyMem (ImageId, &((EFI_IFR_IMAGE *)OpCodeData)->Id, sizeof
> (EFI_IMAGE_ID));
> + break;
> +
> + //
> + // Refresh
> + //
> + case EFI_IFR_REFRESH_OP:
> +
> + if (ParentStatement != NULL) {
> + ParentStatement->RefreshInterval = ((EFI_IFR_REFRESH
> *)OpCodeData)->RefreshInterval;
> + }
> +
> + break;
> +
> + //
> + // Refresh guid.
> + //
> + case EFI_IFR_REFRESH_ID_OP:
> + //
> + // Get ScopeOpcode from top of stack
> + //
> + PopScope (&ScopeOpCode);
> + PushScope (ScopeOpCode);
> +
> + switch (ScopeOpCode) {
> + case EFI_IFR_FORM_OP:
> + case EFI_IFR_FORM_MAP_OP:
> +
> + if (CurrentForm != NULL) {
> + CopyMem (&CurrentForm->RefreshGuid, &((EFI_IFR_REFRESH_ID
> *)OpCodeData)->RefreshEventGroupId, sizeof (EFI_GUID));
> + }
> +
> + break;
> +
> + default:
> +
> + if (ParentStatement != NULL) {
> + if (ParentStatement->Operand == EFI_IFR_NUMERIC_OP) {
> + CopyMem (&ParentStatement->ExtraData.NumData.Guid,
> &((EFI_IFR_REFRESH_ID *)OpCodeData)->RefreshEventGroupId, sizeof
> (EFI_GUID));
> + }
> + }
> +
> + break;
> + }
> +
> + break;
> +
> + //
> + // Modal tag
> + //
> + case EFI_IFR_MODAL_TAG_OP:
> +
> + if (CurrentForm != NULL) {
> + CurrentForm->ModalForm = TRUE;
> + }
> +
> + break;
> +
> + //
> + // Lock tag, used by form and statement.
> + //
> + case EFI_IFR_LOCKED_OP:
> + //
> + // Get ScopeOpcode from top of stack
> + //
> + PopScope (&ScopeOpCode);
> + PushScope (ScopeOpCode);
> +
> + switch (ScopeOpCode) {
> + case EFI_IFR_FORM_OP:
> + case EFI_IFR_FORM_MAP_OP:
> +
> + if (CurrentForm != NULL) {
> + CurrentForm->Locked = TRUE;
> + }
> +
> + break;
> +
> + default:
> +
> + if (ParentStatement != NULL) {
> + ParentStatement->Locked = TRUE;
> + }
> + }
> +
> + break;
> +
> + //
> + // Vendor specific
> + //
> + case EFI_IFR_GUID_OP:
> + CurrentStatement = CreateStatement (OpCodeData, FormSet,
> CurrentForm);
> + if (CompareGuid ((EFI_GUID *)(OpCodeData + sizeof
> (EFI_IFR_OP_HEADER)), &gEdkiiIfrBitVarstoreGuid)) {
> + Scope = 0;
> + QuestionReferBitField = TRUE;
> + }
> +
> + break;
> +
> + //
> + // Scope End
> + //
> + case EFI_IFR_END_OP:
> + QuestionReferBitField = FALSE;
> + Status = PopScope (&ScopeOpCode);
> + if (EFI_ERROR (Status)) {
> + ResetScopeStack ();
> + return Status;
> + }
> +
> + //
> + // Parent statement end tag found, update ParentStatement info.
> + //
> + if (IsStatementOpCode (ScopeOpCode) && (ParentStatement != NULL)
> && (ParentStatement->Operand == ScopeOpCode)) {
> + ParentStatement = ParentStatement->ParentStatement;
> + }
> +
> + switch (ScopeOpCode) {
> + case EFI_IFR_FORM_SET_OP:
> + //
> + // End of FormSet, update FormSet IFR binary length
> + // to stop parsing substantial OpCodes
> + //
> + FormSet->IfrBinaryLength = OpCodeOffset;
> + break;
> +
> + case EFI_IFR_FORM_OP:
> + case EFI_IFR_FORM_MAP_OP:
> + //
> + // End of Form
> + //
> + CurrentForm = NULL;
> + SuppressForQuestion = FALSE;
> + break;
> +
> + case EFI_IFR_ONE_OF_OPTION_OP:
> + //
> + // End of Option
> + //
> + CurrentOption = NULL;
> + break;
> +
> + case EFI_IFR_NO_SUBMIT_IF_OP:
> + case EFI_IFR_INCONSISTENT_IF_OP:
> + case EFI_IFR_WARNING_IF_OP:
> + //
> + // Ignore end of EFI_IFR_NO_SUBMIT_IF and
> EFI_IFR_INCONSISTENT_IF
> + //
> + break;
> +
> + case EFI_IFR_SUPPRESS_IF_OP:
> + if (SuppressForOption) {
> + PopConditionalExpression (ExpressOption);
> + } else if (SuppressForQuestion) {
> + PopConditionalExpression (ExpressStatement);
> + } else {
> + PopConditionalExpression (ExpressForm);
> + }
> +
> + break;
> +
> + case EFI_IFR_GRAY_OUT_IF_OP:
> + PopConditionalExpression (ExpressStatement);
> + break;
> +
> + case EFI_IFR_DISABLE_IF_OP:
> + if (CurrentForm != NULL) {
> + PopConditionalExpression (ExpressStatement);
> + }
> +
> + InScopeDisable = FALSE;
> + OpCodeDisabled = FALSE;
> + break;
> +
> + case EFI_IFR_ONE_OF_OP:
> + case EFI_IFR_ORDERED_LIST_OP:
> + SuppressForOption = FALSE;
> + break;
> +
> + case EFI_IFR_DEFAULT_OP:
> + InScopeDefault = FALSE;
> + break;
> +
> + case EFI_IFR_MAP_OP:
> +
> + //
> + // Get current Map Expression List.
> + //
> + Status = PopMapExpressionList ((VOID **)&MapExpressionList);
> + if (Status == EFI_ACCESS_DENIED) {
> + MapExpressionList = NULL;
> + }
> +
> + //
> + // Get current expression.
> + //
> + Status = PopCurrentExpression ((VOID **)&CurrentExpression);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + if (MapScopeDepth > 0) {
> + MapScopeDepth--;
> + }
> +
> + break;
> +
> + default:
> +
> + if (IsExpressionOpCode (ScopeOpCode)) {
> + if (InScopeDisable && (CurrentForm == NULL)) {
> + //
> + // This is DisableIf expression for Form, it should be a constant
> expression
> + //
> + Status = EvaluateHiiExpression (FormSet, CurrentForm,
> CurrentExpression);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + OpCodeDisabled = IsHiiValueTrue (&CurrentExpression->Result);
> +
> + //
> + // DisableIf Expression is only used once and not queued, free it
> + //
> + DestroyExpression (CurrentExpression);
> + }
> +
> + //
> + // End of current Expression
> + //
> + CurrentExpression = NULL;
> + }
> +
> + break;
> + }
> +
> + break;
> +
> + default:
> + break;
> + }
> +
> + if (IsStatementOpCode (Operand)) {
> + CurrentStatement->ParentStatement = ParentStatement;
> + if (Scope != 0) {
> + //
> + // Scope != 0, other statements or options may nest in this statement.
> + // Update the ParentStatement info.
> + //
> + ParentStatement = CurrentStatement;
> + }
> + }
> + }
> +
> + return EFI_SUCCESS;
> +}
> diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiUtilityInternal.c
> b/RedfishPkg/Library/HiiUtilityLib/HiiUtilityInternal.c
> new file mode 100644
> index 000000000000..80b93beae999
> --- /dev/null
> +++ b/RedfishPkg/Library/HiiUtilityLib/HiiUtilityInternal.c
> @@ -0,0 +1,5770 @@
> +/** @file
> + HII utility internal functions.
> +
> + Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> + (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
> + Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights
> reserved.
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include "HiiInternal.h"
> +
> +CHAR16 *mUnknownString = L"!";
> +CHAR16 *gEmptyString = L"";
> +
> +EFI_HII_VALUE *mExpressionEvaluationStack = NULL;
> +EFI_HII_VALUE *mExpressionEvaluationStackEnd = NULL;
> +EFI_HII_VALUE *mExpressionEvaluationStackPointer = NULL;
> +UINTN mExpressionEvaluationStackOffset = 0;
> +
> +//
> +// Unicode collation protocol interface
> +//
> +EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollation = NULL;
> +EFI_USER_MANAGER_PROTOCOL *mUserManager = NULL;
> +
> +/**
> + Allocate new memory and then copy the Unicode string Source to
> Destination.
> +
> + @param[in,out] Dest Location to copy string
> + @param[in] Src String to copy
> +
> +**/
> +VOID
> +NewStringCopy (
> + IN OUT CHAR16 **Dest,
> + IN CHAR16 *Src
> + )
> +{
> + if (*Dest != NULL) {
> + FreePool (*Dest);
> + }
> +
> + *Dest = AllocateCopyPool (StrSize (Src), Src);
> +}
> +
> +/**
> + Set Value of given Name in a NameValue Storage.
> +
> + @param[in] Storage The NameValue Storage.
> + @param[in] Name The Name.
> + @param[in] Value The Value to set.
> + @param[out] ReturnNode The node use the input name.
> +
> + @retval EFI_SUCCESS Value found for given Name.
> + @retval EFI_NOT_FOUND No such Name found in NameValue storage.
> +
> +**/
> +EFI_STATUS
> +SetValueByName (
> + IN HII_FORMSET_STORAGE *Storage,
> + IN CHAR16 *Name,
> + IN CHAR16 *Value,
> + OUT HII_NAME_VALUE_NODE **ReturnNode
> + )
> +{
> + LIST_ENTRY *Link;
> + HII_NAME_VALUE_NODE *Node;
> + CHAR16 *Buffer;
> +
> + Link = GetFirstNode (&Storage->NameValueList);
> + while (!IsNull (&Storage->NameValueList, Link)) {
> + Node = HII_NAME_VALUE_NODE_FROM_LINK (Link);
> +
> + if (StrCmp (Name, Node->Name) == 0) {
> + Buffer = Node->Value;
> + if (Buffer != NULL) {
> + FreePool (Buffer);
> + }
> +
> + Buffer = AllocateCopyPool (StrSize (Value), Value);
> + if (Buffer == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + Node->Value = Buffer;
> +
> + if (ReturnNode != NULL) {
> + *ReturnNode = Node;
> + }
> +
> + return EFI_SUCCESS;
> + }
> +
> + Link = GetNextNode (&Storage->NameValueList, Link);
> + }
> +
> + return EFI_NOT_FOUND;
> +}
> +
> +/**
> + Get bit field value from the buffer and then set the value for the question.
> + Note: Data type UINT32 can cover all the bit field value.
> +
> + @param[in] Question The question refer to bit field.
> + @param[in] Buffer Point to the buffer which the question value get
> from.
> + @param[out] QuestionValue The Question Value retrieved from Bits.
> +
> +**/
> +VOID
> +GetBitsQuestionValue (
> + IN HII_STATEMENT *Question,
> + IN UINT8 *Buffer,
> + OUT HII_STATEMENT_VALUE *QuestionValue
> + )
> +{
> + UINTN StartBit;
> + UINTN EndBit;
> + UINT32 RetVal;
> + UINT32 BufferValue;
> +
> + StartBit = Question->BitVarOffset % 8;
> + EndBit = StartBit + Question->BitStorageWidth - 1;
> +
> + CopyMem ((UINT8 *)&BufferValue, Buffer, Question->StorageWidth);
> +
> + RetVal = BitFieldRead32 (BufferValue, StartBit, EndBit);
> +
> + //
> + // Set question value.
> + // Note: Since Question with BufferValue (orderedlist, password,
> string)are not supported to refer bit field.
> + // Only oneof/checkbox/oneof can support bit field.So we can copy the
> value to the HiiValue of Question directly.
> + //
> + CopyMem ((UINT8 *)&QuestionValue->Value, (UINT8 *)&RetVal,
> Question->StorageWidth);
> +}
> +
> +/**
> + Set bit field value to the buffer.
> + Note: Data type UINT32 can cover all the bit field value.
> +
> + @param[in] Question The question refer to bit field.
> + @param[in,out] Buffer Point to the buffer which the question value
> set to.
> + @param[in] Value The bit field value need to set.
> +
> +**/
> +VOID
> +SetBitsQuestionValue (
> + IN HII_STATEMENT *Question,
> + IN OUT UINT8 *Buffer,
> + IN UINT32 Value
> + )
> +{
> + UINT32 Operand;
> + UINTN StartBit;
> + UINTN EndBit;
> + UINT32 RetVal;
> +
> + StartBit = Question->BitVarOffset % 8;
> + EndBit = StartBit + Question->BitStorageWidth - 1;
> +
> + CopyMem ((UINT8 *)&Operand, Buffer, Question->StorageWidth);
> + RetVal = BitFieldWrite32 (Operand, StartBit, EndBit, Value);
> + CopyMem (Buffer, (UINT8 *)&RetVal, Question->StorageWidth);
> +}
> +
> +/**
> + Convert the buffer value to HiiValue.
> +
> + @param[in] Question The question.
> + @param[in] Value Unicode buffer save the question value.
> + @param[out] QuestionValue The Question Value retrieved from
> Buffer.
> +
> + @retval Status whether convert the value success.
> +
> +**/
> +EFI_STATUS
> +BufferToQuestionValue (
> + IN HII_STATEMENT *Question,
> + IN CHAR16 *Value,
> + OUT HII_STATEMENT_VALUE *QuestionValue
> + )
> +{
> + CHAR16 *StringPtr;
> + BOOLEAN IsBufferStorage;
> + CHAR16 *DstBuf;
> + CHAR16 TempChar;
> + UINTN LengthStr;
> + UINT8 *Dst;
> + CHAR16 TemStr[5];
> + UINTN Index;
> + UINT8 DigitUint8;
> + BOOLEAN IsString;
> + UINTN Length;
> + EFI_STATUS Status;
> + UINT8 *Buffer;
> +
> + Buffer = NULL;
> +
> + IsString = (BOOLEAN)((QuestionValue->Type == EFI_IFR_TYPE_STRING) ?
> TRUE : FALSE);
> + if ((Question->Storage->Type == EFI_HII_VARSTORE_BUFFER) ||
> + (Question->Storage->Type ==
> EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER))
> + {
> + IsBufferStorage = TRUE;
> + } else {
> + IsBufferStorage = FALSE;
> + }
> +
> + //
> + // Question Value is provided by Buffer Storage or NameValue Storage
> + //
> + if ((QuestionValue->Type == EFI_IFR_TYPE_STRING) || (QuestionValue-
> >Type == EFI_IFR_TYPE_BUFFER)) {
> + //
> + // This Question is password or orderedlist
> + //
> + if (QuestionValue->Buffer == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + Dst = QuestionValue->Buffer;
> + } else {
> + //
> + // Other type of Questions
> + //
> + if (Question->QuestionReferToBitField) {
> + Buffer = (UINT8 *)AllocateZeroPool (Question->StorageWidth);
> + if (Buffer == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + Dst = Buffer;
> + } else {
> + Dst = (UINT8 *)&QuestionValue->Value;
> + }
> + }
> +
> + //
> + // Temp cut at the end of this section, end with '\0' or '&'.
> + //
> + StringPtr = Value;
> + while (*StringPtr != L'\0' && *StringPtr != L'&') {
> + StringPtr++;
> + }
> +
> + TempChar = *StringPtr;
> + *StringPtr = L'\0';
> +
> + LengthStr = StrLen (Value);
> +
> + //
> + // Value points to a Unicode hexadecimal string, we need to convert the
> string to the value with CHAR16/UINT8...type.
> + // When generating the Value string, we follow this rule: 1 byte -> 2
> Unicode characters (for string: 2 byte(CHAR16) ->4 Unicode characters).
> + // So the maximum value string length of a question is : Question-
> >StorageWidth * 2.
> + // If the value string length > Question->StorageWidth * 2, only set the
> string length as Question->StorageWidth * 2, then convert.
> + //
> + if (LengthStr > (UINTN)Question->StorageWidth * 2) {
> + Length = (UINTN)Question->StorageWidth * 2;
> + } else {
> + Length = LengthStr;
> + }
> +
> + Status = EFI_SUCCESS;
> + if (!IsBufferStorage && IsString) {
> + //
> + // Convert Config String to Unicode String, e.g "0041004200430044" =>
> "ABCD"
> + // Add string tail char L'\0' into Length
> + //
> + DstBuf = (CHAR16 *)Dst;
> + ZeroMem (TemStr, sizeof (TemStr));
> + for (Index = 0; Index < Length; Index += 4) {
> + StrnCpyS (TemStr, sizeof (TemStr) / sizeof (CHAR16), Value + Index, 4);
> + DstBuf[Index/4] = (CHAR16)StrHexToUint64 (TemStr);
> + }
> +
> + //
> + // Add tailing L'\0' character
> + //
> + DstBuf[Index/4] = L'\0';
> + } else {
> + ZeroMem (TemStr, sizeof (TemStr));
> + for (Index = 0; Index < Length; Index++) {
> + TemStr[0] = Value[LengthStr - Index - 1];
> + DigitUint8 = (UINT8)StrHexToUint64 (TemStr);
> + if ((Index & 1) == 0) {
> + Dst[Index/2] = DigitUint8;
> + } else {
> + Dst[Index/2] = (UINT8)((DigitUint8 << 4) + Dst[Index/2]);
> + }
> + }
> + }
> +
> + *StringPtr = TempChar;
> +
> + if ((Buffer != NULL) && Question->QuestionReferToBitField) {
> + GetBitsQuestionValue (Question, Buffer, QuestionValue);
> + FreePool (Buffer);
> + }
> +
> + return Status;
> +}
> +
> +/**
> + Get the string based on the StringId and HII Package List Handle.
> +
> + @param[in] Token The String's ID.
> + @param[in] HiiHandle The package list in the HII database to search
> for
> + the specified string.
> +
> + @return The output string.
> +
> +**/
> +CHAR16 *
> +GetTokenString (
> + IN EFI_STRING_ID Token,
> + IN EFI_HII_HANDLE HiiHandle
> + )
> +{
> + EFI_STRING String;
> +
> + if (HiiHandle == NULL) {
> + return NULL;
> + }
> +
> + String = HiiGetString (HiiHandle, Token, NULL);
> + if (String == NULL) {
> + String = AllocateCopyPool (StrSize (mUnknownString), mUnknownString);
> + if (String == NULL) {
> + return NULL;
> + }
> + }
> +
> + return (CHAR16 *)String;
> +}
> +
> +/**
> + Converts the unicode character of the string from uppercase to lowercase.
> + This is a internal function.
> +
> + @param[in] ConfigString String to be converted
> +
> +**/
> +VOID
> +EFIAPI
> +HiiStringToLowercase (
> + IN EFI_STRING ConfigString
> + )
> +{
> + EFI_STRING String;
> + BOOLEAN Lower;
> +
> + //
> + // Convert all hex digits in range [A-F] in the configuration header to [a-f]
> + //
> + for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {
> + if (*String == L'=') {
> + Lower = TRUE;
> + } else if (*String == L'&') {
> + Lower = FALSE;
> + } else if (Lower && (*String >= L'A') && (*String <= L'F')) {
> + *String = (CHAR16)(*String - L'A' + L'a');
> + }
> + }
> +}
> +
> +/**
> + Evaluate if the result is a non-zero value.
> +
> + @param[in] Result The result to be evaluated.
> +
> + @retval TRUE It is a non-zero value.
> + @retval FALSE It is a zero value.
> +
> +**/
> +BOOLEAN
> +IsHiiValueTrue (
> + IN EFI_HII_VALUE *Result
> + )
> +{
> + switch (Result->Type) {
> + case EFI_IFR_TYPE_BOOLEAN:
> + return Result->Value.b;
> +
> + case EFI_IFR_TYPE_NUM_SIZE_8:
> + return (BOOLEAN)(Result->Value.u8 != 0);
> +
> + case EFI_IFR_TYPE_NUM_SIZE_16:
> + return (BOOLEAN)(Result->Value.u16 != 0);
> +
> + case EFI_IFR_TYPE_NUM_SIZE_32:
> + return (BOOLEAN)(Result->Value.u32 != 0);
> +
> + case EFI_IFR_TYPE_NUM_SIZE_64:
> + return (BOOLEAN)(Result->Value.u64 != 0);
> +
> + default:
> + return FALSE;
> + }
> +}
> +
> +/**
> + Set a new string to string package.
> +
> + @param[in] String A pointer to the Null-terminated Unicode string
> + to add or update in the String Package associated
> + with HiiHandle.
> + @param[in] HiiHandle A handle that was previously registered in the
> + HII Database.
> +
> + @return the Id for this new string.
> +
> +**/
> +EFI_STRING_ID
> +NewHiiString (
> + IN CHAR16 *String,
> + IN EFI_HII_HANDLE HiiHandle
> + )
> +{
> + EFI_STRING_ID StringId;
> +
> + StringId = HiiSetString (HiiHandle, 0, String, NULL);
> + return StringId;
> +}
> +
> +/**
> + Perform nosubmitif check for a Form.
> +
> + @param[in] FormSet FormSet data structure.
> + @param[in] Form Form data structure.
> + @param[in] Question The Question to be validated.
> +
> + @retval EFI_SUCCESS Form validation pass.
> + @retval other Form validation failed.
> +
> +**/
> +EFI_STATUS
> +ValidateNoSubmit (
> + IN HII_FORMSET *FormSet,
> + IN HII_FORM *Form,
> + IN HII_STATEMENT *Question
> + )
> +{
> + EFI_STATUS Status;
> + LIST_ENTRY *Link;
> + LIST_ENTRY *ListHead;
> + HII_EXPRESSION *Expression;
> +
> + ListHead = &Question->NoSubmitListHead;
> + Link = GetFirstNode (ListHead);
> + while (!IsNull (ListHead, Link)) {
> + Expression = HII_EXPRESSION_FROM_LINK (Link);
> +
> + //
> + // Evaluate the expression
> + //
> + Status = EvaluateHiiExpression (FormSet, Form, Expression);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + if (IsHiiValueTrue (&Expression->Result)) {
> + return EFI_NOT_READY;
> + }
> +
> + Link = GetNextNode (ListHead, Link);
> + }
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Perform NoSubmit check for each Form in FormSet.
> +
> + @param[in] FormSet FormSet data structure.
> + @param[in,out] CurrentForm Current input form data structure.
> + @param[out] Statement The statement for this check.
> +
> + @retval EFI_SUCCESS Form validation pass.
> + @retval other Form validation failed.
> +
> +**/
> +EFI_STATUS
> +NoSubmitCheck (
> + IN HII_FORMSET *FormSet,
> + IN OUT HII_FORM **CurrentForm,
> + OUT HII_STATEMENT **Statement
> + )
> +{
> + EFI_STATUS Status;
> + LIST_ENTRY *Link;
> + HII_STATEMENT *Question;
> + HII_FORM *Form;
> + LIST_ENTRY *LinkForm;
> +
> + LinkForm = GetFirstNode (&FormSet->FormListHead);
> + while (!IsNull (&FormSet->FormListHead, LinkForm)) {
> + Form = HII_FORM_FROM_LINK (LinkForm);
> + LinkForm = GetNextNode (&FormSet->FormListHead, LinkForm);
> +
> + if ((*CurrentForm != NULL) && (*CurrentForm != Form)) {
> + continue;
> + }
> +
> + Link = GetFirstNode (&Form->StatementListHead);
> + while (!IsNull (&Form->StatementListHead, Link)) {
> + Question = HII_STATEMENT_FROM_LINK (Link);
> + Status = ValidateNoSubmit (FormSet, Form, Question);
> + if (EFI_ERROR (Status)) {
> + if (*CurrentForm == NULL) {
> + *CurrentForm = Form;
> + }
> +
> + if (Statement != NULL) {
> + *Statement = Question;
> + }
> +
> + return Status;
> + }
> +
> + Link = GetNextNode (&Form->StatementListHead, Link);
> + }
> + }
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Allocate new memory and concatenate Source on the end of Destination.
> +
> + @param Dest String to added to the end of.
> + @param Src String to concatenate.
> +
> +**/
> +VOID
> +NewStringCat (
> + IN OUT CHAR16 **Dest,
> + IN CHAR16 *Src
> + )
> +{
> + CHAR16 *NewHiiString;
> + UINTN MaxLen;
> +
> + if (*Dest == NULL) {
> + NewStringCopy (Dest, Src);
> + return;
> + }
> +
> + MaxLen = (StrSize (*Dest) + StrSize (Src) - 2) / sizeof (CHAR16);
> + NewHiiString = AllocatePool (MaxLen * sizeof (CHAR16));
> + if (NewHiiString == NULL) {
> + return;
> + }
> +
> + StrCpyS (NewHiiString, MaxLen, *Dest);
> + StrCatS (NewHiiString, MaxLen, Src);
> +
> + FreePool (*Dest);
> + *Dest = NewHiiString;
> +}
> +
> +/**
> + Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
> +
> + @param[in] Storage The Storage to be converted.
> + @param[in] ConfigResp The returned <ConfigResp>.
> + @param[in] ConfigRequest The ConfigRequest string.
> +
> + @retval EFI_SUCCESS Convert success.
> + @retval EFI_INVALID_PARAMETER Incorrect storage type.
> +
> +**/
> +EFI_STATUS
> +StorageToConfigResp (
> + IN HII_FORMSET_STORAGE *Storage,
> + IN CHAR16 **ConfigResp,
> + IN CHAR16 *ConfigRequest
> + )
> +{
> + EFI_STATUS Status;
> + EFI_STRING Progress;
> + LIST_ENTRY *Link;
> + HII_NAME_VALUE_NODE *Node;
> + UINT8 *SourceBuf;
> + EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
> + EFI_STRING TempConfigRequest;
> + UINTN RequestStrSize;
> +
> + Status = EFI_SUCCESS;
> +
> + if (Storage->ConfigHdr == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + if (ConfigRequest != NULL) {
> + TempConfigRequest = AllocateCopyPool (StrSize (ConfigRequest),
> ConfigRequest);
> + if (TempConfigRequest == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> + } else {
> + RequestStrSize = (StrLen (Storage->ConfigHdr) + StrLen (Storage-
> >ConfigRequest) + 1) * sizeof (CHAR16);
> + TempConfigRequest = AllocatePool (RequestStrSize);
> + if (TempConfigRequest == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + UnicodeSPrint (
> + TempConfigRequest,
> + RequestStrSize,
> + L"%s%s",
> + Storage->ConfigHdr,
> + Storage->ConfigRequest
> + );
> + }
> +
> + switch (Storage->Type) {
> + case EFI_HII_VARSTORE_BUFFER:
> + case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
> +
> + Status = gBS->LocateProtocol (
> + &gEfiHiiConfigRoutingProtocolGuid,
> + NULL,
> + (VOID **)&HiiConfigRouting
> + );
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + SourceBuf = Storage->Buffer;
> + Status = HiiConfigRouting->BlockToConfig (
> + HiiConfigRouting,
> + TempConfigRequest,
> + SourceBuf,
> + Storage->Size,
> + ConfigResp,
> + &Progress
> + );
> + break;
> +
> + case EFI_HII_VARSTORE_NAME_VALUE:
> +
> + *ConfigResp = NULL;
> + NewStringCat (ConfigResp, Storage->ConfigHdr);
> +
> + Link = GetFirstNode (&Storage->NameValueList);
> + while (!IsNull (&Storage->NameValueList, Link)) {
> + Node = HII_NAME_VALUE_NODE_FROM_LINK (Link);
> +
> + if (StrStr (TempConfigRequest, Node->Name) != NULL) {
> + NewStringCat (ConfigResp, L"&");
> + NewStringCat (ConfigResp, Node->Name);
> + NewStringCat (ConfigResp, L"=");
> + NewStringCat (ConfigResp, Node->Value);
> + }
> +
> + Link = GetNextNode (&Storage->NameValueList, Link);
> + }
> +
> + break;
> +
> + case EFI_HII_VARSTORE_EFI_VARIABLE:
> + default:
> + Status = EFI_INVALID_PARAMETER;
> + break;
> + }
> +
> + return Status;
> +}
> +
> +/**
> + Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
> +
> + @param[in] Storage The Storage to receive the settings.
> + @param[in] ConfigResp The <ConfigResp> to be converted.
> +
> + @retval EFI_SUCCESS Convert success.
> + @retval EFI_INVALID_PARAMETER Incorrect storage type.
> +
> +**/
> +EFI_STATUS
> +ConfigRespToStorage (
> + IN HII_FORMSET_STORAGE *Storage,
> + IN CHAR16 *ConfigResp
> + )
> +{
> + EFI_STATUS Status;
> + EFI_STRING Progress;
> + UINTN BufferSize;
> + CHAR16 *StrPtr;
> + CHAR16 *Name;
> + CHAR16 *Value;
> + EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
> +
> + Status = EFI_SUCCESS;
> +
> + switch (Storage->Type) {
> + case EFI_HII_VARSTORE_BUFFER:
> + case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
> +
> + Status = gBS->LocateProtocol (
> + &gEfiHiiConfigRoutingProtocolGuid,
> + NULL,
> + (VOID **)&HiiConfigRouting
> + );
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + BufferSize = Storage->Size;
> + Status = HiiConfigRouting->ConfigToBlock (
> + HiiConfigRouting,
> + ConfigResp,
> + Storage->Buffer,
> + &BufferSize,
> + &Progress
> + );
> + break;
> +
> + case EFI_HII_VARSTORE_NAME_VALUE:
> + StrPtr = StrStr (ConfigResp, L"PATH");
> + if (StrPtr == NULL) {
> + break;
> + }
> +
> + StrPtr = StrStr (ConfigResp, L"&");
> + while (StrPtr != NULL) {
> + //
> + // Skip '&'
> + //
> + StrPtr = StrPtr + 1;
> + Name = StrPtr;
> + StrPtr = StrStr (StrPtr, L"=");
> + if (StrPtr == NULL) {
> + break;
> + }
> +
> + *StrPtr = 0;
> +
> + //
> + // Skip '='
> + //
> + StrPtr = StrPtr + 1;
> + Value = StrPtr;
> + StrPtr = StrStr (StrPtr, L"&");
> + if (StrPtr != NULL) {
> + *StrPtr = 0;
> + }
> +
> + SetValueByName (Storage, Name, Value, NULL);
> + }
> +
> + break;
> +
> + case EFI_HII_VARSTORE_EFI_VARIABLE:
> + default:
> + Status = EFI_INVALID_PARAMETER;
> + break;
> + }
> +
> + return Status;
> +}
> +
> +/**
> + Fetch the Ifr binary data of a FormSet.
> +
> + @param[in] Handle PackageList Handle
> + @param[in,out] FormSetGuid On input, GUID or class GUID of a formset.
> If not
> + specified (NULL or zero GUID), take the first
> + FormSet with class GUID
> EFI_HII_PLATFORM_SETUP_FORMSET_GUID
> + found in package list.
> + On output, GUID of the formset found(if not NULL).
> + @param[out] BinaryLength The length of the FormSet IFR binary.
> + @param[out] BinaryData The buffer designed to receive the FormSet.
> +
> + @retval EFI_SUCCESS Buffer filled with the requested FormSet.
> + BufferLength was updated.
> + @retval EFI_INVALID_PARAMETER The handle is unknown.
> + @retval EFI_NOT_FOUND A form or FormSet on the requested handle
> cannot
> + be found with the requested FormId.
> +
> +**/
> +EFI_STATUS
> +GetIfrBinaryData (
> + IN EFI_HII_HANDLE Handle,
> + IN OUT EFI_GUID *FormSetGuid,
> + OUT UINTN *BinaryLength,
> + OUT UINT8 **BinaryData
> + )
> +{
> + EFI_STATUS Status;
> + EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
> + UINTN BufferSize;
> + UINT8 *Package;
> + UINT8 *OpCodeData;
> + UINT32 Offset;
> + UINT32 Offset2;
> + UINT32 PackageListLength;
> + EFI_HII_PACKAGE_HEADER PackageHeader;
> + UINT8 Index;
> + UINT8 NumberOfClassGuid;
> + BOOLEAN ClassGuidMatch;
> + EFI_GUID *ClassGuid;
> + EFI_GUID *ComparingGuid;
> + EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
> +
> + OpCodeData = NULL;
> + Package = NULL;
> + ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));
> +
> + //
> + // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the
> package list
> + //
> + if (FormSetGuid == NULL) {
> + ComparingGuid = &gZeroGuid;
> + } else {
> + ComparingGuid = FormSetGuid;
> + }
> +
> + //
> + // Get HII PackageList
> + //
> + Status = gBS->LocateProtocol (
> + &gEfiHiiDatabaseProtocolGuid,
> + NULL,
> + (VOID **)&HiiDatabase
> + );
> + if (EFI_ERROR (Status)) {
> + *BinaryData = NULL;
> + return Status;
> + }
> +
> + BufferSize = 0;
> + HiiPackageList = NULL;
> + Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle,
> &BufferSize, HiiPackageList);
> + if (Status == EFI_BUFFER_TOO_SMALL) {
> + HiiPackageList = AllocatePool (BufferSize);
> + if (HiiPackageList == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle,
> &BufferSize, HiiPackageList);
> + }
> +
> + if (EFI_ERROR (Status)) {
> + if (HiiPackageList != NULL) {
> + FreePool (HiiPackageList);
> + }
> +
> + *BinaryData = NULL;
> + return Status;
> + }
> +
> + //
> + // Get Form package from this HII package List
> + //
> + Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
> + Offset2 = 0;
> + CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof
> (UINT32));
> +
> + ClassGuidMatch = FALSE;
> + while (Offset < PackageListLength) {
> + Package = ((UINT8 *)HiiPackageList) + Offset;
> + CopyMem (&PackageHeader, Package, sizeof
> (EFI_HII_PACKAGE_HEADER));
> +
> + if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {
> + //
> + // Search FormSet in this Form Package
> + //
> +
> + Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);
> + while (Offset2 < PackageHeader.Length) {
> + OpCodeData = Package + Offset2;
> +
> + if (((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode ==
> EFI_IFR_FORM_SET_OP) {
> + //
> + // Try to compare against formset GUID
> + //
> +
> + if (IsZeroGuid (FormSetGuid) ||
> + CompareGuid (ComparingGuid, (EFI_GUID *)(OpCodeData + sizeof
> (EFI_IFR_OP_HEADER))))
> + {
> + break;
> + }
> +
> + if (((EFI_IFR_OP_HEADER *)OpCodeData)->Length > OFFSET_OF
> (EFI_IFR_FORM_SET, Flags)) {
> + //
> + // Try to compare against formset class GUID
> + //
> + NumberOfClassGuid = (UINT8)(((EFI_IFR_FORM_SET *)OpCodeData)-
> >Flags & 0x3);
> + ClassGuid = (EFI_GUID *)(OpCodeData + sizeof
> (EFI_IFR_FORM_SET));
> + for (Index = 0; Index < NumberOfClassGuid; Index++) {
> + if (CompareGuid (ComparingGuid, ClassGuid + Index)) {
> + ClassGuidMatch = TRUE;
> + break;
> + }
> + }
> +
> + if (ClassGuidMatch) {
> + break;
> + }
> + } else if (ComparingGuid == &gEfiHiiPlatformSetupFormsetGuid) {
> + ClassGuidMatch = TRUE;
> + break;
> + }
> + }
> +
> + Offset2 += ((EFI_IFR_OP_HEADER *)OpCodeData)->Length;
> + }
> +
> + if (Offset2 < PackageHeader.Length) {
> + //
> + // Target formset found
> + //
> + break;
> + }
> + }
> +
> + Offset += PackageHeader.Length;
> + }
> +
> + if (Offset >= PackageListLength) {
> + //
> + // Form package not found in this Package List
> + //
> + FreePool (HiiPackageList);
> + *BinaryData = NULL;
> + return EFI_NOT_FOUND;
> + }
> +
> + if (FormSetGuid != NULL) {
> + //
> + // Return the FormSet GUID
> + //
> + CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *)OpCodeData)->Guid,
> sizeof (EFI_GUID));
> + }
> +
> + //
> + // To determine the length of a whole FormSet IFR binary, one have to
> parse all the Opcodes
> + // in this FormSet; So, here just simply copy the data from start of a
> FormSet to the end
> + // of the Form Package.
> + //
> +
> + *BinaryLength = PackageHeader.Length - Offset2;
> + *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);
> + FreePool (HiiPackageList);
> + if (*BinaryData == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Check if the requested element is in storage.
> +
> + @param Storage The storage contains elements.
> + @param RequestElement The element to be searched.
> +
> +**/
> +BOOLEAN
> +ElementValidation (
> + IN HII_FORMSET_STORAGE *Storage,
> + IN CHAR16 *RequestElement
> + )
> +{
> + return StrStr (Storage->ConfigRequest, RequestElement) != NULL ? TRUE :
> FALSE;
> +}
> +
> +/**
> + Append the Request element to the Config Request.
> +
> + @param ConfigRequest Current ConfigRequest info.
> + @param SpareStrLen Current remain free buffer for config request.
> + @param RequestElement New Request element.
> +
> +**/
> +VOID
> +AppendConfigRequest (
> + IN OUT CHAR16 **ConfigRequest,
> + IN OUT UINTN *SpareStrLen,
> + IN CHAR16 *RequestElement
> + )
> +{
> + CHAR16 *NewStr;
> + UINTN StringSize;
> + UINTN StrLength;
> + UINTN MaxLen;
> +
> + StrLength = StrLen (RequestElement);
> + StringSize = (*ConfigRequest != NULL) ? StrSize (*ConfigRequest) : sizeof
> (CHAR16);
> + MaxLen = StringSize / sizeof (CHAR16) + *SpareStrLen;
> +
> + //
> + // Append <RequestElement> to <ConfigRequest>
> + //
> + if (StrLength > *SpareStrLen) {
> + //
> + // Old String buffer is not sufficient for RequestElement, allocate a new
> one
> + //
> + MaxLen = StringSize / sizeof (CHAR16) +
> CONFIG_REQUEST_STRING_INCREMENTAL;
> + NewStr = AllocatePool (MaxLen * sizeof (CHAR16));
> + if (NewStr == NULL) {
> + return;
> + }
> +
> + if (*ConfigRequest != NULL) {
> + CopyMem (NewStr, *ConfigRequest, StringSize);
> + FreePool (*ConfigRequest);
> + } else {
> + NewStr[0] = L'\0';
> + }
> +
> + *ConfigRequest = NewStr;
> + *SpareStrLen = CONFIG_REQUEST_STRING_INCREMENTAL;
> + }
> +
> + StrCatS (*ConfigRequest, MaxLen, RequestElement);
> + *SpareStrLen -= StrLength;
> +}
> +
> +/**
> + Adjust the config request info, remove the request elements which
> already in AllConfigRequest string.
> +
> + @param Storage Form set Storage.
> + @param Request The input request string.
> + @param RespString Whether the input is ConfigRequest or
> ConfigResp format.
> +
> + @retval TRUE Has element not covered by current used elements,
> need to continue to call ExtractConfig
> + @retval FALSE All elements covered by current used elements.
> +
> +**/
> +BOOLEAN
> +ConfigRequestAdjust (
> + IN HII_FORMSET_STORAGE *Storage,
> + IN CHAR16 *Request,
> + IN BOOLEAN RespString
> + )
> +{
> + CHAR16 *RequestElement;
> + CHAR16 *NextRequestElement;
> + CHAR16 *NextElementBackup;
> + CHAR16 *SearchKey;
> + CHAR16 *ValueKey;
> + BOOLEAN RetVal;
> + CHAR16 *ConfigRequest;
> +
> + RetVal = FALSE;
> + NextElementBackup = NULL;
> + ValueKey = NULL;
> +
> + if (Request != NULL) {
> + ConfigRequest = Request;
> + } else {
> + ConfigRequest = Storage->ConfigRequest;
> + }
> +
> + if (Storage->ConfigRequest == NULL) {
> + Storage->ConfigRequest = AllocateCopyPool (StrSize (ConfigRequest),
> ConfigRequest);
> + if (Storage->ConfigRequest == NULL) {
> + return FALSE;
> + }
> +
> + return TRUE;
> + }
> +
> + if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
> + //
> + // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE
> storage
> + //
> + SearchKey = L"&";
> + } else {
> + //
> + // "&OFFSET=####&WIDTH=####" section for
> EFI_HII_VARSTORE_BUFFER storage
> + //
> + SearchKey = L"&OFFSET";
> + ValueKey = L"&VALUE";
> + }
> +
> + //
> + // Find SearchKey storage
> + //
> + if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
> + RequestElement = StrStr (ConfigRequest, L"PATH");
> + if (RequestElement == NULL) {
> + return FALSE;
> + }
> +
> + RequestElement = StrStr (RequestElement, SearchKey);
> + } else {
> + RequestElement = StrStr (ConfigRequest, SearchKey);
> + }
> +
> + while (RequestElement != NULL) {
> + //
> + // +1 to avoid find header itself.
> + //
> + NextRequestElement = StrStr (RequestElement + 1, SearchKey);
> +
> + //
> + // The last Request element in configRequest string.
> + //
> + if (NextRequestElement != NULL) {
> + if (RespString && (Storage->Type ==
> EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {
> + NextElementBackup = NextRequestElement;
> + NextRequestElement = StrStr (RequestElement, ValueKey);
> + if (NextRequestElement == NULL) {
> + return FALSE;
> + }
> + }
> +
> + //
> + // Replace "&" with '\0'.
> + //
> + *NextRequestElement = L'\0';
> + } else {
> + if (RespString && (Storage->Type ==
> EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {
> + NextElementBackup = NextRequestElement;
> + NextRequestElement = StrStr (RequestElement, ValueKey);
> + if (NextRequestElement == NULL) {
> + return FALSE;
> + }
> +
> + //
> + // Replace "&" with '\0'.
> + //
> + *NextRequestElement = L'\0';
> + }
> + }
> +
> + if (!ElementValidation (Storage, RequestElement)) {
> + //
> + // Add this element to the Storage->BrowserStorage-
> >AllRequestElement.
> + //
> + AppendConfigRequest (&Storage->ConfigRequest, &Storage-
> >SpareStrLen, RequestElement);
> + RetVal = TRUE;
> + }
> +
> + if (NextRequestElement != NULL) {
> + //
> + // Restore '&' with '\0' for later used.
> + //
> + *NextRequestElement = L'&';
> + }
> +
> + if (RespString && (Storage->Type ==
> EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {
> + RequestElement = NextElementBackup;
> + } else {
> + RequestElement = NextRequestElement;
> + }
> + }
> +
> + return RetVal;
> +}
> +
> +/**
> + Fill storage with settings requested from Configuration Driver.
> +
> + @param[in] FormSet FormSet data structure.
> + @param[in] Storage Buffer Storage.
> +
> +**/
> +VOID
> +LoadFormSetStorage (
> + IN HII_FORMSET *FormSet,
> + IN HII_FORMSET_STORAGE *Storage
> + )
> +{
> + EFI_STATUS Status;
> + EFI_STRING Progress;
> + EFI_STRING Result;
> + CHAR16 *StrPtr;
> + EFI_STRING ConfigRequest;
> + UINTN RequestStrSize;
> + EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
> +
> + ConfigRequest = NULL;
> +
> + switch (Storage->Type) {
> + case EFI_HII_VARSTORE_EFI_VARIABLE:
> + return;
> +
> + case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
> + #if 0 // bug fix for efivarstore
> + if (Storage->ConfigRequest != NULL) {
> + ConfigRequestAdjust (Storage, Storage->ConfigRequest, FALSE);
> + return;
> + }
> +
> + #endif
> + break;
> +
> + case EFI_HII_VARSTORE_BUFFER:
> + case EFI_HII_VARSTORE_NAME_VALUE:
> + //
> + // Skip if there is no RequestElement.
> + //
> + if (Storage->ElementCount == 0) {
> + return;
> + }
> +
> + break;
> +
> + default:
> + return;
> + }
> +
> + if (Storage->Type != EFI_HII_VARSTORE_NAME_VALUE) {
> + //
> + // Create the config request string to get all fields for this storage.
> + // Allocate and fill a buffer large enough to hold the <ConfigHdr>
> template
> + // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-
> terminator
> + //
> + RequestStrSize = StrSize (Storage->ConfigHdr) + 20 * sizeof (CHAR16);
> + ConfigRequest = AllocatePool (RequestStrSize);
> + if (ConfigRequest == NULL) {
> + return;
> + }
> +
> + UnicodeSPrint (
> + ConfigRequest,
> + RequestStrSize,
> + L"%s&OFFSET=0&WIDTH=%04x",
> + Storage->ConfigHdr,
> + Storage->Size
> + );
> + } else {
> + RequestStrSize = (StrLen (Storage->ConfigHdr) + StrLen (Storage-
> >ConfigRequest) + 1) * sizeof (CHAR16);
> + ConfigRequest = AllocatePool (RequestStrSize);
> + if (ConfigRequest == NULL) {
> + return;
> + }
> +
> + UnicodeSPrint (
> + ConfigRequest,
> + RequestStrSize,
> + L"%s%s",
> + Storage->ConfigHdr,
> + Storage->ConfigRequest
> + );
> + }
> +
> + //
> + // Request current settings from Configuration Driver
> + //
> + Status = gBS->LocateProtocol (
> + &gEfiHiiConfigRoutingProtocolGuid,
> + NULL,
> + (VOID **)&HiiConfigRouting
> + );
> + if (EFI_ERROR (Status)) {
> + return;
> + }
> +
> + Status = HiiConfigRouting->ExtractConfig (
> + HiiConfigRouting,
> + ConfigRequest,
> + &Progress,
> + &Result
> + );
> + if (!EFI_ERROR (Status)) {
> + //
> + // Convert Result from <ConfigAltResp> to <ConfigResp>
> + //
> + StrPtr = StrStr (Result, L"&GUID=");
> + if (StrPtr != NULL) {
> + *StrPtr = L'\0';
> + }
> +
> + Status = ConfigRespToStorage (Storage, Result);
> + FreePool (Result);
> + }
> +
> + Storage->ConfigRequest = AllocateCopyPool (StrSize (ConfigRequest),
> ConfigRequest);
> + if (Storage->ConfigRequest == NULL) {
> + if (ConfigRequest != NULL) {
> + FreePool (ConfigRequest);
> + }
> +
> + return;
> + }
> +
> + if (Storage->Type != EFI_HII_VARSTORE_NAME_VALUE) {
> + if (ConfigRequest != NULL) {
> + FreePool (ConfigRequest);
> + }
> + }
> +}
> +
> +/**
> + Zero extend integer/boolean/date/time to UINT64 for comparing.
> +
> + @param[in] Value HII Value to be converted.
> +
> +**/
> +VOID
> +ExtendValueToU64 (
> + IN HII_STATEMENT_VALUE *Value
> + )
> +{
> + UINT64 Temp;
> +
> + Temp = 0;
> + switch (Value->Type) {
> + case EFI_IFR_TYPE_NUM_SIZE_8:
> + Temp = Value->Value.u8;
> + break;
> +
> + case EFI_IFR_TYPE_NUM_SIZE_16:
> + Temp = Value->Value.u16;
> + break;
> +
> + case EFI_IFR_TYPE_NUM_SIZE_32:
> + Temp = Value->Value.u32;
> + break;
> +
> + case EFI_IFR_TYPE_BOOLEAN:
> + Temp = Value->Value.b;
> + break;
> +
> + case EFI_IFR_TYPE_TIME:
> + Temp = Value->Value.u32 & 0xffffff;
> + break;
> +
> + case EFI_IFR_TYPE_DATE:
> + Temp = Value->Value.u32;
> + break;
> +
> + default:
> + return;
> + }
> +
> + Value->Value.u64 = Temp;
> +}
> +
> +/**
> + Pop an element from the stack.
> +
> + @param Stack On input: old stack
> + @param StackPtr On input: old stack pointer; On output: new stack
> pointer
> + @param Data Data to pop.
> +
> + @retval EFI_SUCCESS The value was popped onto the stack.
> + @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
> +
> +**/
> +EFI_STATUS
> +PopStack (
> + IN EFI_HII_VALUE *Stack,
> + IN OUT EFI_HII_VALUE **StackPtr,
> + OUT EFI_HII_VALUE *Data
> + );
> +
> +/**
> + Push an element onto the Boolean Stack.
> +
> + @param Stack On input: old stack; On output: new stack
> + @param StackPtr On input: old stack pointer; On output: new stack
> + pointer
> + @param StackEnd On input: old stack end; On output: new stack
> end
> + @param Data Data to push.
> +
> + @retval EFI_SUCCESS Push stack success.
> +
> +**/
> +EFI_STATUS
> +PushStack (
> + IN OUT EFI_HII_VALUE **Stack,
> + IN OUT EFI_HII_VALUE **StackPtr,
> + IN OUT EFI_HII_VALUE **StackEnd,
> + IN EFI_HII_VALUE *Data
> + );
> +
> +/**
> + Initialize the internal data structure of a FormSet.
> +
> + @param[in] Handle PackageList Handle
> + @param[in,out] FormSetGuid On input, GUID or class GUID of a formset.
> If not
> + specified (NULL or zero GUID), take the first
> + FormSet with class GUID
> EFI_HII_PLATFORM_SETUP_FORMSET_GUID
> + found in package list.
> + On output, GUID of the formset found(if not NULL).
> + @param[out] FormSet FormSet data structure.
> +
> + @retval EFI_SUCCESS The function completed successfully.
> + @retval EFI_NOT_FOUND The specified FormSet could not be found.
> +
> +**/
> +EFI_STATUS
> +CreateFormSetFromHiiHandle (
> + IN EFI_HII_HANDLE Handle,
> + IN OUT EFI_GUID *FormSetGuid,
> + OUT HII_FORMSET *FormSet
> + );
> +
> +/**
> + Initialize a Formset and get current setting for Questions.
> +
> + @param[in,out] FormSet FormSet data structure.
> +
> +**/
> +VOID
> +InitializeFormSet (
> + IN OUT HII_FORMSET *FormSet
> + );
> +
> +/**
> + Get Value for given Name from a NameValue Storage.
> +
> + @param[in] Storage The NameValue Storage.
> + @param[in] Name The Name.
> + @param[in,out] Value The returned Value.
> +
> + @retval EFI_SUCCESS Value found for given Name.
> + @retval EFI_NOT_FOUND No such Name found in NameValue storage.
> + @retval EFI_INVALID_PARAMETER Storage or Value is NULL.
> +
> +**/
> +EFI_STATUS
> +GetValueByName (
> + IN HII_FORMSET_STORAGE *Storage,
> + IN CHAR16 *Name,
> + IN OUT CHAR16 **Value
> + )
> +{
> + LIST_ENTRY *Link;
> + HII_NAME_VALUE_NODE *Node;
> +
> + if ((Storage == NULL) || (Value == NULL)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + *Value = NULL;
> +
> + Link = GetFirstNode (&Storage->NameValueList);
> + while (!IsNull (&Storage->NameValueList, Link)) {
> + Node = HII_NAME_VALUE_NODE_FROM_LINK (Link);
> +
> + if (StrCmp (Name, Node->Name) == 0) {
> + NewStringCopy (Value, Node->Value);
> + return EFI_SUCCESS;
> + }
> +
> + Link = GetNextNode (&Storage->NameValueList, Link);
> + }
> +
> + return EFI_NOT_FOUND;
> +}
> +
> +/**
> + Get Question's current Value.
> +
> + @param[in] FormSet FormSet data structure.
> + @param[in] Form Form data structure.
> + @param[in,out] Question Question to be initialized.
> + @param[in] GetValueFrom Where to get value, may from editbuffer,
> buffer or hii driver.
> +
> + @retval EFI_SUCCESS The function completed successfully.
> + @retval EFI_INVALID_PARAMETER Formset, Form or Question is NULL.
> +
> +**/
> +EFI_STATUS
> +GetQuestionValue (
> + IN HII_FORMSET *FormSet,
> + IN HII_FORM *Form,
> + IN OUT HII_STATEMENT *Question,
> + IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
> + )
> +{
> + EFI_STATUS Status;
> + BOOLEAN Enabled;
> + BOOLEAN Pending;
> + UINT8 *Dst;
> + UINTN StorageWidth;
> + EFI_TIME EfiTime;
> + HII_FORMSET_STORAGE *Storage;
> + HII_FORMSET_STORAGE *FormsetStorage;
> + EFI_IFR_TYPE_VALUE *QuestionValue;
> + CHAR16 *ConfigRequest;
> + CHAR16 *Progress;
> + CHAR16 *Result;
> + CHAR16 *Value;
> + UINTN Length;
> + BOOLEAN IsBufferStorage;
> + UINTN MaxLen;
> + EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
> +
> + if ((FormSet == NULL) || (Form == NULL) || (Question == NULL)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + Status = EFI_SUCCESS;
> + Value = NULL;
> + Result = NULL;
> +
> + if (GetValueFrom >= GetSetValueWithMax) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + //
> + // Question value is provided by an Expression, evaluate it
> + //
> + if (Question->ValueExpression != NULL) {
> + Status = EvaluateHiiExpression (FormSet, Form, Question-
> >ValueExpression);
> + if (!EFI_ERROR (Status)) {
> + if (Question->ValueExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {
> + ASSERT (Question->Value.Type == EFI_IFR_TYPE_BUFFER && Question-
> >Value.Buffer != NULL);
> + if (Question->StorageWidth > Question->ValueExpression-
> >Result.BufferLen) {
> + CopyMem (Question->Value.Buffer, Question->ValueExpression-
> >Result.Buffer, Question->ValueExpression->Result.BufferLen);
> + Question->Value.BufferLen = Question->ValueExpression-
> >Result.BufferLen;
> + } else {
> + CopyMem (Question->Value.Buffer, Question->ValueExpression-
> >Result.Buffer, Question->StorageWidth);
> + Question->Value.BufferLen = Question->StorageWidth;
> + }
> +
> + FreePool (Question->ValueExpression->Result.Buffer);
> + }
> +
> + Question->Value.Type = Question->ValueExpression->Result.Type;
> + CopyMem (&Question->Value.Value, &Question->ValueExpression-
> >Result.Value, sizeof (EFI_IFR_TYPE_VALUE));
> + }
> +
> + return Status;
> + }
> +
> + //
> + // Get question value by read expression.
> + //
> + if ((Question->ReadExpression != NULL) && (Form->FormType ==
> STANDARD_MAP_FORM_TYPE)) {
> + Status = EvaluateHiiExpression (FormSet, Form, Question-
> >ReadExpression);
> + if (!EFI_ERROR (Status) &&
> + ((Question->ReadExpression->Result.Type < EFI_IFR_TYPE_OTHER) ||
> (Question->ReadExpression->Result.Type == EFI_IFR_TYPE_BUFFER)))
> + {
> + //
> + // Only update question value to the valid result.
> + //
> + if (Question->ReadExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {
> + ASSERT (Question->Value.Type == EFI_IFR_TYPE_BUFFER && Question-
> >Value.Buffer != NULL);
> + if (Question->StorageWidth > Question->ReadExpression-
> >Result.BufferLen) {
> + CopyMem (Question->Value.Buffer, Question->ReadExpression-
> >Result.Buffer, Question->ReadExpression->Result.BufferLen);
> + Question->Value.BufferLen = Question->ReadExpression-
> >Result.BufferLen;
> + } else {
> + CopyMem (Question->Value.Buffer, Question->ReadExpression-
> >Result.Buffer, Question->StorageWidth);
> + Question->Value.BufferLen = Question->StorageWidth;
> + }
> +
> + FreePool (Question->ReadExpression->Result.Buffer);
> + }
> +
> + Question->Value.Type = Question->ReadExpression->Result.Type;
> + CopyMem (&Question->Value.Value, &Question->ReadExpression-
> >Result.Value, sizeof (EFI_IFR_TYPE_VALUE));
> + return EFI_SUCCESS;
> + }
> + }
> +
> + //
> + // Question value is provided by RTC
> + //
> + Storage = Question->Storage;
> + QuestionValue = &Question->Value.Value;
> + if (Storage == NULL) {
> + //
> + // It's a Question without storage, or RTC date/time
> + //
> + if ((Question->Operand == EFI_IFR_DATE_OP) || (Question->Operand ==
> EFI_IFR_TIME_OP)) {
> + //
> + // Date and time define the same Flags bit
> + //
> + switch (Question->ExtraData.Flags & EFI_QF_DATE_STORAGE) {
> + case QF_DATE_STORAGE_TIME:
> + Status = gRT->GetTime (&EfiTime, NULL);
> + break;
> +
> + case QF_DATE_STORAGE_WAKEUP:
> + Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);
> + break;
> +
> + case QF_DATE_STORAGE_NORMAL:
> + default:
> + //
> + // For date/time without storage
> + //
> + return EFI_SUCCESS;
> + }
> +
> + if (EFI_ERROR (Status)) {
> + if (Question->Operand == EFI_IFR_DATE_OP) {
> + QuestionValue->date.Year = 0xff;
> + QuestionValue->date.Month = 0xff;
> + QuestionValue->date.Day = 0xff;
> + } else {
> + QuestionValue->time.Hour = 0xff;
> + QuestionValue->time.Minute = 0xff;
> + QuestionValue->time.Second = 0xff;
> + }
> +
> + return EFI_SUCCESS;
> + }
> +
> + if (Question->Operand == EFI_IFR_DATE_OP) {
> + QuestionValue->date.Year = EfiTime.Year;
> + QuestionValue->date.Month = EfiTime.Month;
> + QuestionValue->date.Day = EfiTime.Day;
> + } else {
> + QuestionValue->time.Hour = EfiTime.Hour;
> + QuestionValue->time.Minute = EfiTime.Minute;
> + QuestionValue->time.Second = EfiTime.Second;
> + }
> + }
> +
> + return EFI_SUCCESS;
> + }
> +
> + //
> + // Question value is provided by EFI variable
> + //
> + StorageWidth = Question->StorageWidth;
> + if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
> + if (Question->Value.Buffer != NULL) {
> + Dst = Question->Value.Buffer;
> + } else {
> + Dst = (UINT8 *)QuestionValue;
> + }
> +
> + Status = gRT->GetVariable (
> + Question->VariableName,
> + &Storage->Guid,
> + NULL,
> + &StorageWidth,
> + Dst
> + );
> + //
> + // Always return success, even this EFI variable doesn't exist
> + //
> + return EFI_SUCCESS;
> + }
> +
> + //
> + // Question Value is provided by Buffer Storage or NameValue Storage
> + //
> + if (Question->Value.Buffer != NULL) {
> + //
> + // This Question is password or orderedlist
> + //
> + Dst = Question->Value.Buffer;
> + } else {
> + //
> + // Other type of Questions
> + //
> + Dst = (UINT8 *)&Question->Value.Value;
> + }
> +
> + if ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ||
> + (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER))
> + {
> + IsBufferStorage = TRUE;
> + } else {
> + IsBufferStorage = FALSE;
> + }
> +
> + if (GetValueFrom == GetSetValueWithBuffer ) {
> + if (IsBufferStorage) {
> + //
> + // Copy from storage Edit buffer
> + // If the Question refer to bit filed, get the value in the related bit filed.
> + //
> + if (Question->QuestionReferToBitField) {
> + GetBitsQuestionValue (Question, Storage->Buffer + Question-
> >VarStoreInfo.VarOffset, &Question->Value);
> + } else {
> + CopyMem (Dst, Storage->Buffer + Question->VarStoreInfo.VarOffset,
> StorageWidth);
> + }
> + } else {
> + Value = NULL;
> + Status = GetValueByName (Storage, Question->VariableName, &Value);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + ASSERT (Value != NULL);
> + Status = BufferToQuestionValue (Question, Value, &Question->Value);
> + FreePool (Value);
> + }
> + } else {
> + FormsetStorage = GetFstStgFromVarId (FormSet, Question->VarStoreId);
> + ASSERT (FormsetStorage != NULL);
> + //
> + // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
> + // <ConfigHdr> + "&" + <VariableName>
> + //
> + if (IsBufferStorage) {
> + Length = StrLen (FormsetStorage->ConfigHdr);
> + Length += StrLen (Question->BlockName);
> + } else {
> + Length = StrLen (FormsetStorage->ConfigHdr);
> + Length += StrLen (Question->VariableName) + 1;
> + }
> +
> + // Allocate buffer include '\0'
> + MaxLen = Length + 1;
> + ConfigRequest = AllocatePool (MaxLen * sizeof (CHAR16));
> + ASSERT (ConfigRequest != NULL);
> +
> + StrCpyS (ConfigRequest, MaxLen, FormsetStorage->ConfigHdr);
> + if (IsBufferStorage) {
> + StrCatS (ConfigRequest, MaxLen, Question->BlockName);
> + } else {
> + StrCatS (ConfigRequest, MaxLen, L"&");
> + StrCatS (ConfigRequest, MaxLen, Question->VariableName);
> + }
> +
> + Status = gBS->LocateProtocol (
> + &gEfiHiiConfigRoutingProtocolGuid,
> + NULL,
> + (VOID **)&HiiConfigRouting
> + );
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + //
> + // Request current settings from Configuration Driver
> + //
> + Status = HiiConfigRouting->ExtractConfig (
> + HiiConfigRouting,
> + ConfigRequest,
> + &Progress,
> + &Result
> + );
> + FreePool (ConfigRequest);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + //
> + // Skip <ConfigRequest>
> + //
> + if (IsBufferStorage) {
> + Value = StrStr (Result, L"&VALUE");
> + if (Value == NULL) {
> + FreePool (Result);
> + return EFI_NOT_FOUND;
> + }
> +
> + //
> + // Skip "&VALUE"
> + //
> + Value = Value + 6;
> + } else {
> + Value = Result + Length;
> + }
> +
> + if (*Value != '=') {
> + FreePool (Result);
> + return EFI_NOT_FOUND;
> + }
> +
> + //
> + // Skip '=', point to value
> + //
> + Value = Value + 1;
> +
> + Status = BufferToQuestionValue (Question, Value, &Question->Value);
> + if (EFI_ERROR (Status)) {
> + FreePool (Result);
> + return Status;
> + }
> +
> + //
> + // Synchronize Buffer
> + //
> + if (IsBufferStorage) {
> + CopyMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Dst,
> StorageWidth);
> + } else {
> + SetValueByName (Storage, Question->VariableName, Value, NULL);
> + }
> +
> + if (Result != NULL) {
> + FreePool (Result);
> + }
> + }
> +
> + return Status;
> +}
> +
> +/**
> + Convert the input Unicode character to upper.
> +
> + @param[in] String Th Unicode character to be converted.
> +
> +**/
> +VOID
> +IfrStrToUpper (
> + IN CHAR16 *String
> + )
> +{
> + if (String == NULL) {
> + return;
> + }
> +
> + while (*String != 0) {
> + if ((*String >= 'a') && (*String <= 'z')) {
> + *String = (UINT16)((*String) & ((UINT16) ~0x20));
> + }
> +
> + String++;
> + }
> +}
> +
> +/**
> + Check whether this value type can be transfer to EFI_IFR_TYPE_BUFFER
> type.
> +
> + EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are
> converted to
> + EFI_IFR_TYPE_BUFFER when do the value compare.
> +
> + @param[in] Value Expression value to compare on.
> +
> + @retval TRUE This value type can be transferred to
> EFI_IFR_TYPE_BUFFER type.
> + @retval FALSE This value type can't be transferred to
> EFI_IFR_TYPE_BUFFER type.
> +
> +**/
> +BOOLEAN
> +IsTypeInBuffer (
> + IN EFI_HII_VALUE *Value
> + )
> +{
> + if (Value == NULL) {
> + return FALSE;
> + }
> +
> + switch (Value->Type) {
> + case EFI_IFR_TYPE_BUFFER:
> + case EFI_IFR_TYPE_DATE:
> + case EFI_IFR_TYPE_TIME:
> + case EFI_IFR_TYPE_REF:
> + return TRUE;
> +
> + default:
> + return FALSE;
> + }
> +}
> +
> +/**
> + Check whether this value type can be transfer to EFI_IFR_TYPE_UINT64
> +
> + @param[in] Value Expression value to compare on.
> +
> + @retval TRUE This value type can be transferred to
> EFI_IFR_TYPE_BUFFER type.
> + @retval FALSE This value type can't be transferred to
> EFI_IFR_TYPE_BUFFER type.
> +
> +**/
> +BOOLEAN
> +IsTypeInUINT64 (
> + IN EFI_HII_VALUE *Value
> + )
> +{
> + if (Value == NULL) {
> + return FALSE;
> + }
> +
> + switch (Value->Type) {
> + case EFI_IFR_TYPE_NUM_SIZE_8:
> + case EFI_IFR_TYPE_NUM_SIZE_16:
> + case EFI_IFR_TYPE_NUM_SIZE_32:
> + case EFI_IFR_TYPE_NUM_SIZE_64:
> + case EFI_IFR_TYPE_BOOLEAN:
> + return TRUE;
> +
> + default:
> + return FALSE;
> + }
> +}
> +
> +/**
> + Return the buffer pointer for this value.
> +
> + EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are
> converted to
> + EFI_IFR_TYPE_BUFFER when do the value compare.
> +
> + @param[in] Value Expression value to compare on.
> +
> + @retval Buf Return the buffer pointer.
> +
> +**/
> +UINT8 *
> +GetBufferForValue (
> + IN EFI_HII_VALUE *Value
> + )
> +{
> + if (Value == NULL) {
> + return NULL;
> + }
> +
> + switch (Value->Type) {
> + case EFI_IFR_TYPE_BUFFER:
> + return Value->Buffer;
> +
> + case EFI_IFR_TYPE_DATE:
> + return (UINT8 *)(&Value->Value.date);
> +
> + case EFI_IFR_TYPE_TIME:
> + return (UINT8 *)(&Value->Value.time);
> +
> + case EFI_IFR_TYPE_REF:
> + return (UINT8 *)(&Value->Value.ref);
> +
> + default:
> + return NULL;
> + }
> +}
> +
> +/**
> + Return the buffer length for this value.
> +
> + EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are
> converted to
> + EFI_IFR_TYPE_BUFFER when do the value compare.
> +
> + @param[in] Value Expression value to compare on.
> +
> + @retval BufLen Return the buffer length.
> +
> +**/
> +UINT16
> +GetLengthForValue (
> + IN EFI_HII_VALUE *Value
> + )
> +{
> + if (Value == NULL) {
> + return 0;
> + }
> +
> + switch (Value->Type) {
> + case EFI_IFR_TYPE_BUFFER:
> + return Value->BufferLen;
> +
> + case EFI_IFR_TYPE_DATE:
> + return (UINT16)sizeof (EFI_HII_DATE);
> +
> + case EFI_IFR_TYPE_TIME:
> + return (UINT16)sizeof (EFI_HII_TIME);
> +
> + case EFI_IFR_TYPE_REF:
> + return (UINT16)sizeof (EFI_HII_REF);
> +
> + default:
> + return 0;
> + }
> +}
> +
> +/**
> + Get UINT64 type value.
> +
> + @param[in] Value Input Hii value.
> +
> + @retval UINT64 Return the UINT64 type value.
> +
> +**/
> +UINT64
> +HiiValueToUINT64 (
> + IN EFI_HII_VALUE *Value
> + )
> +{
> + UINT64 RetVal;
> +
> + if (Value == NULL) {
> + return 0;
> + }
> +
> + RetVal = 0;
> +
> + switch (Value->Type) {
> + case EFI_IFR_TYPE_NUM_SIZE_8:
> + RetVal = Value->Value.u8;
> + break;
> +
> + case EFI_IFR_TYPE_NUM_SIZE_16:
> + RetVal = Value->Value.u16;
> + break;
> +
> + case EFI_IFR_TYPE_NUM_SIZE_32:
> + RetVal = Value->Value.u32;
> + break;
> +
> + case EFI_IFR_TYPE_BOOLEAN:
> + RetVal = Value->Value.b;
> + break;
> +
> + case EFI_IFR_TYPE_DATE:
> + RetVal = *(UINT64 *)&Value->Value.date;
> + break;
> +
> + case EFI_IFR_TYPE_TIME:
> + RetVal = (*(UINT64 *)&Value->Value.time) & 0xffffff;
> + break;
> +
> + default:
> + RetVal = Value->Value.u64;
> + break;
> + }
> +
> + return RetVal;
> +}
> +
> +/**
> + Compare two Hii value.
> +
> + @param[in] Value1 Expression value to compare on left-hand.
> + @param[in] Value2 Expression value to compare on right-hand.
> + @param[out] Result Return value after compare.
> + retval 0 Two operators equal.
> + return Positive value if Value1 is greater than Value2.
> + retval Negative value if Value1 is less than Value2.
> + @param[in] HiiHandle Only required for string compare.
> +
> + @retval other Could not perform compare on two values.
> + @retval EFI_SUCCESS Compare the value success.
> + @retval EFI_INVALID_PARAMETER Value1, Value2 or Result is NULL.
> +
> +**/
> +EFI_STATUS
> +CompareHiiValue (
> + IN EFI_HII_VALUE *Value1,
> + IN EFI_HII_VALUE *Value2,
> + OUT INTN *Result,
> + IN EFI_HII_HANDLE HiiHandle OPTIONAL
> + )
> +{
> + INT64 Temp64;
> + CHAR16 *Str1;
> + CHAR16 *Str2;
> + UINTN Len;
> + UINT8 *Buf1;
> + UINT16 Buf1Len;
> + UINT8 *Buf2;
> + UINT16 Buf2Len;
> +
> + if ((Value1 == NULL) || (Value2 == NULL) || (Result == NULL)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + if ((Value1->Type == EFI_IFR_TYPE_STRING) && (Value2->Type ==
> EFI_IFR_TYPE_STRING)) {
> + if ((Value1->Value.string == 0) || (Value2->Value.string == 0)) {
> + //
> + // StringId 0 is reserved
> + //
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + if (Value1->Value.string == Value2->Value.string) {
> + *Result = 0;
> + return EFI_SUCCESS;
> + }
> +
> + Str1 = GetTokenString (Value1->Value.string, HiiHandle);
> + if (Str1 == NULL) {
> + //
> + // String not found
> + //
> + return EFI_NOT_FOUND;
> + }
> +
> + Str2 = GetTokenString (Value2->Value.string, HiiHandle);
> + if (Str2 == NULL) {
> + FreePool (Str1);
> + return EFI_NOT_FOUND;
> + }
> +
> + *Result = StrCmp (Str1, Str2);
> +
> + FreePool (Str1);
> + FreePool (Str2);
> +
> + return EFI_SUCCESS;
> + }
> +
> + //
> + // Take types(date, time, ref, buffer) as buffer
> + //
> + if (IsTypeInBuffer (Value1) && IsTypeInBuffer (Value2)) {
> + Buf1 = GetBufferForValue (Value1);
> + Buf1Len = GetLengthForValue (Value1);
> + Buf2 = GetBufferForValue (Value2);
> + Buf2Len = GetLengthForValue (Value2);
> +
> + Len = Buf1Len > Buf2Len ? Buf2Len : Buf1Len;
> + *Result = CompareMem (Buf1, Buf2, Len);
> + if ((*Result == 0) && (Buf1Len != Buf2Len)) {
> + //
> + // In this case, means base on small number buffer, the data is same
> + // So which value has more data, which value is bigger.
> + //
> + *Result = Buf1Len > Buf2Len ? 1 : -1;
> + }
> +
> + return EFI_SUCCESS;
> + }
> +
> + //
> + // Take types(integer, boolean) as integer
> + //
> + if (IsTypeInUINT64 (Value1) && IsTypeInUINT64 (Value2)) {
> + Temp64 = HiiValueToUINT64 (Value1) - HiiValueToUINT64 (Value2);
> + if (Temp64 > 0) {
> + *Result = 1;
> + } else if (Temp64 < 0) {
> + *Result = -1;
> + } else {
> + *Result = 0;
> + }
> +
> + return EFI_SUCCESS;
> + }
> +
> + return EFI_UNSUPPORTED;
> +}
> +
> +/**
> + Check if current user has the privilege specified by the permissions GUID.
> +
> + @param[in] Guid A GUID specifying setup access permissions.
> +
> + @retval TRUE Current user has the privilege.
> + @retval FALSE Current user does not have the privilege.
> +**/
> +BOOLEAN
> +CheckUserPrivilege (
> + IN EFI_GUID *Guid
> + )
> +{
> + EFI_STATUS Status;
> + EFI_USER_PROFILE_HANDLE UserProfileHandle;
> + EFI_USER_INFO_HANDLE UserInfoHandle;
> + EFI_USER_INFO *UserInfo;
> + EFI_GUID *UserPermissionsGuid;
> + UINTN UserInfoSize;
> + UINTN AccessControlDataSize;
> + EFI_USER_INFO_ACCESS_CONTROL *AccessControl;
> + UINTN RemainSize;
> +
> + if (mUserManager == NULL) {
> + Status = gBS->LocateProtocol (
> + &gEfiUserManagerProtocolGuid,
> + NULL,
> + (VOID **)&mUserManager
> + );
> + if (EFI_ERROR (Status)) {
> + ///
> + /// If the system does not support user management, then it is assumed
> that
> + /// all users have admin privilege and evaluation of each
> EFI_IFR_SECURITY
> + /// op-code is always TRUE.
> + ///
> + return TRUE;
> + }
> + }
> +
> + Status = mUserManager->Current (mUserManager, &UserProfileHandle);
> + ASSERT_EFI_ERROR (Status);
> +
> + ///
> + /// Enumerate all user information of the current user profile
> + /// to look for any EFI_USER_INFO_ACCESS_SETUP record.
> + ///
> +
> + for (UserInfoHandle = NULL; ;) {
> + Status = mUserManager->GetNextInfo (mUserManager,
> UserProfileHandle, &UserInfoHandle);
> + if (EFI_ERROR (Status)) {
> + break;
> + }
> +
> + UserInfoSize = 0;
> + Status = mUserManager->GetInfo (mUserManager, UserProfileHandle,
> UserInfoHandle, NULL, &UserInfoSize);
> + if (Status != EFI_BUFFER_TOO_SMALL) {
> + continue;
> + }
> +
> + UserInfo = (EFI_USER_INFO *)AllocatePool (UserInfoSize);
> + if (UserInfo == NULL) {
> + break;
> + }
> +
> + Status = mUserManager->GetInfo (mUserManager, UserProfileHandle,
> UserInfoHandle, UserInfo, &UserInfoSize);
> + if (EFI_ERROR (Status) ||
> + (UserInfo->InfoType != EFI_USER_INFO_ACCESS_POLICY_RECORD) ||
> + (UserInfo->InfoSize <= sizeof (EFI_USER_INFO)))
> + {
> + FreePool (UserInfo);
> + continue;
> + }
> +
> + RemainSize = UserInfo->InfoSize - sizeof (EFI_USER_INFO);
> + AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)(UserInfo + 1);
> + while (RemainSize >= sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {
> + if ((RemainSize < AccessControl->Size) || (AccessControl->Size < sizeof
> (EFI_USER_INFO_ACCESS_CONTROL))) {
> + break;
> + }
> +
> + if (AccessControl->Type == EFI_USER_INFO_ACCESS_SETUP) {
> + ///
> + /// Check if current user has the privilege specified by the permissions
> GUID.
> + ///
> +
> + UserPermissionsGuid = (EFI_GUID *)(AccessControl + 1);
> + AccessControlDataSize = AccessControl->Size - sizeof
> (EFI_USER_INFO_ACCESS_CONTROL);
> + while (AccessControlDataSize >= sizeof (EFI_GUID)) {
> + if (CompareGuid (Guid, UserPermissionsGuid)) {
> + FreePool (UserInfo);
> + return TRUE;
> + }
> +
> + UserPermissionsGuid++;
> + AccessControlDataSize -= sizeof (EFI_GUID);
> + }
> + }
> +
> + RemainSize -= AccessControl->Size;
> + AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)((UINT8
> *)AccessControl + AccessControl->Size);
> + }
> +
> + FreePool (UserInfo);
> + }
> +
> + return FALSE;
> +}
> +
> +/**
> + Search a Question in Form scope using its QuestionId.
> +
> + @param[in] Form The form which contains this Question.
> + @param[in] QuestionId Id of this Question.
> +
> + @retval Pointer The Question.
> + @retval NULL Specified Question not found in the form.
> +
> +**/
> +HII_STATEMENT *
> +QuestionIdInForm (
> + IN HII_FORM *Form,
> + IN UINT16 QuestionId
> + )
> +{
> + LIST_ENTRY *Link;
> + HII_STATEMENT *Question;
> +
> + if ((QuestionId == 0) || (Form == NULL)) {
> + //
> + // The value of zero is reserved
> + //
> + return NULL;
> + }
> +
> + Link = GetFirstNode (&Form->StatementListHead);
> + while (!IsNull (&Form->StatementListHead, Link)) {
> + Question = HII_STATEMENT_FROM_LINK (Link);
> +
> + if (Question->QuestionId == QuestionId) {
> + return Question;
> + }
> +
> + Link = GetNextNode (&Form->StatementListHead, Link);
> + }
> +
> + return NULL;
> +}
> +
> +/**
> + Search a Question in Formset scope using its QuestionId.
> +
> + @param[in] FormSet The formset which contains this form.
> + @param[in] Form The form which contains this Question.
> + @param[in] QuestionId Id of this Question.
> +
> + @retval Pointer The Question.
> + @retval NULL Specified Question not found in the form.
> +
> +**/
> +HII_STATEMENT *
> +QuestionIdInFormset (
> + IN HII_FORMSET *FormSet,
> + IN HII_FORM *Form,
> + IN UINT16 QuestionId
> + )
> +{
> + LIST_ENTRY *Link;
> + HII_STATEMENT *Question;
> +
> + if ((FormSet == NULL) || (Form == NULL)) {
> + return NULL;
> + }
> +
> + //
> + // Search in the form scope first
> + //
> + Question = QuestionIdInForm (Form, QuestionId);
> + if (Question != NULL) {
> + return Question;
> + }
> +
> + //
> + // Search in the formset scope
> + //
> + Link = GetFirstNode (&FormSet->FormListHead);
> + while (!IsNull (&FormSet->FormListHead, Link)) {
> + Form = HII_FORM_FROM_LINK (Link);
> +
> + Question = QuestionIdInForm (Form, QuestionId);
> + if (Question != NULL) {
> + //
> + // EFI variable storage may be updated by Callback() asynchronous,
> + // to keep synchronous, always reload the Question Value.
> + //
> + if (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
> + GetQuestionValue (FormSet, Form, Question,
> GetSetValueWithHiiDriver);
> + }
> +
> + return Question;
> + }
> +
> + Link = GetNextNode (&FormSet->FormListHead, Link);
> + }
> +
> + return NULL;
> +}
> +
> +/**
> + Push an Expression value onto the Stack
> +
> + @param[in] Value Expression value to push.
> +
> + @retval EFI_SUCCESS The value was pushed onto the stack.
> + @retval EFI_OUT_OF_RESOURCES There is not enough system memory
> to grow the
> + stack.
> + @retval EFI_INVALID_PARAMETER Value is NULL.
> +
> +**/
> +EFI_STATUS
> +PushExpression (
> + IN EFI_HII_VALUE *Value
> + )
> +{
> + if (Value == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + return PushStack (
> + &mExpressionEvaluationStack,
> + &mExpressionEvaluationStackPointer,
> + &mExpressionEvaluationStackEnd,
> + Value
> + );
> +}
> +
> +/**
> + Pop an Expression value from the stack.
> +
> + @param[out] Value Expression value to pop.
> +
> + @retval EFI_SUCCESS The value was popped onto the stack.
> + @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
> + @retval EFI_INVALID_PARAMETER Value is NULL.
> +
> +**/
> +EFI_STATUS
> +PopExpression (
> + OUT EFI_HII_VALUE *Value
> + )
> +{
> + if (Value == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + return PopStack (
> + mExpressionEvaluationStack + mExpressionEvaluationStackOffset,
> + &mExpressionEvaluationStackPointer,
> + Value
> + );
> +}
> +
> +/**
> + Get current stack offset from stack start.
> +
> + @return Stack offset to stack start.
> +**/
> +UINTN
> +SaveExpressionEvaluationStackOffset (
> + VOID
> + )
> +{
> + UINTN TempStackOffset;
> +
> + TempStackOffset = mExpressionEvaluationStackOffset;
> + mExpressionEvaluationStackOffset = mExpressionEvaluationStackPointer -
> mExpressionEvaluationStack;
> + return TempStackOffset;
> +}
> +
> +/**
> + Restore stack offset based on input stack offset
> +
> + @param[in] StackOffset Offset to stack start.
> +
> +**/
> +VOID
> +RestoreExpressionEvaluationStackOffset (
> + UINTN StackOffset
> + )
> +{
> + mExpressionEvaluationStackOffset = StackOffset;
> +}
> +
> +/**
> + Evaluate opcode EFI_IFR_TO_STRING.
> +
> + @param[in] FormSet Formset which contains this opcode.
> + @param[in] Format String format in EFI_IFR_TO_STRING.
> + @param[out] Result Evaluation result for this opcode.
> +
> + @retval EFI_SUCCESS Opcode evaluation success.
> + @retval Other Opcode evaluation failed.
> +
> +**/
> +EFI_STATUS
> +IfrToString (
> + IN HII_FORMSET *FormSet,
> + IN UINT8 Format,
> + OUT EFI_HII_VALUE *Result
> + )
> +{
> + EFI_STATUS Status;
> + EFI_HII_VALUE Value;
> + CHAR16 *String;
> + CHAR16 *PrintFormat;
> + CHAR16 Buffer[MAXIMUM_VALUE_CHARACTERS];
> + UINT8 *SrcBuf;
> + UINTN BufferSize;
> +
> + if ((FormSet == NULL) || (Result == NULL)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + Status = PopExpression (&Value);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + switch (Value.Type) {
> + case EFI_IFR_TYPE_NUM_SIZE_8:
> + case EFI_IFR_TYPE_NUM_SIZE_16:
> + case EFI_IFR_TYPE_NUM_SIZE_32:
> + case EFI_IFR_TYPE_NUM_SIZE_64:
> + BufferSize = MAXIMUM_VALUE_CHARACTERS * sizeof (CHAR16);
> + switch (Format) {
> + case EFI_IFR_STRING_UNSIGNED_DEC:
> + case EFI_IFR_STRING_SIGNED_DEC:
> + PrintFormat = L"%ld";
> + break;
> +
> + case EFI_IFR_STRING_LOWERCASE_HEX:
> + PrintFormat = L"%lx";
> + break;
> +
> + case EFI_IFR_STRING_UPPERCASE_HEX:
> + PrintFormat = L"%lX";
> + break;
> +
> + default:
> + Result->Type = EFI_IFR_TYPE_UNDEFINED;
> + return EFI_SUCCESS;
> + }
> +
> + UnicodeSPrint (Buffer, BufferSize, PrintFormat, Value.Value.u64);
> + String = Buffer;
> + break;
> +
> + case EFI_IFR_TYPE_STRING:
> + CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));
> + return EFI_SUCCESS;
> +
> + case EFI_IFR_TYPE_BOOLEAN:
> + String = (Value.Value.b) ? L"True" : L"False";
> + break;
> +
> + case EFI_IFR_TYPE_BUFFER:
> + case EFI_IFR_TYPE_DATE:
> + case EFI_IFR_TYPE_TIME:
> + case EFI_IFR_TYPE_REF:
> + //
> + // + 3 is base on the unicode format, the length may be odd number,
> + // so need 1 byte to align, also need 2 bytes for L'\0'.
> + //
> + if (Value.Type == EFI_IFR_TYPE_BUFFER) {
> + SrcBuf = Value.Buffer;
> + } else {
> + SrcBuf = GetBufferForValue (&Value);
> + }
> +
> + if (Format == EFI_IFR_STRING_ASCII) {
> + PrintFormat = L"%a";
> + } else {
> + // Format == EFI_IFR_STRING_UNICODE
> + PrintFormat = L"%s";
> + }
> +
> + UnicodeSPrint (Buffer, sizeof (Buffer), PrintFormat, SrcBuf);
> + String = Buffer;
> + if (Value.Type == EFI_IFR_TYPE_BUFFER) {
> + FreePool (Value.Buffer);
> + }
> +
> + break;
> +
> + default:
> + Result->Type = EFI_IFR_TYPE_UNDEFINED;
> + return EFI_SUCCESS;
> + }
> +
> + Result->Type = EFI_IFR_TYPE_STRING;
> + Result->Value.string = NewHiiString (String, FormSet->HiiHandle);
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Evaluate opcode EFI_IFR_TO_UINT.
> +
> + @param[in] FormSet Formset which contains this opcode.
> + @param[out] Result Evaluation result for this opcode.
> +
> + @retval EFI_SUCCESS Opcode evaluation success.
> + @retval Other Opcode evaluation failed.
> +
> +**/
> +EFI_STATUS
> +IfrToUint (
> + IN HII_FORMSET *FormSet,
> + OUT EFI_HII_VALUE *Result
> + )
> +{
> + EFI_STATUS Status;
> + EFI_HII_VALUE Value;
> + CHAR16 *String;
> + CHAR16 *StringPtr;
> +
> + if ((FormSet == NULL) || (Result == NULL)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + Status = PopExpression (&Value);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + if ((Value.Type >= EFI_IFR_TYPE_OTHER) && !IsTypeInBuffer (&Value)) {
> + Result->Type = EFI_IFR_TYPE_UNDEFINED;
> + return EFI_SUCCESS;
> + }
> +
> + Status = EFI_SUCCESS;
> + if (Value.Type == EFI_IFR_TYPE_STRING) {
> + String = GetTokenString (Value.Value.string, FormSet->HiiHandle);
> + if (String == NULL) {
> + return EFI_NOT_FOUND;
> + }
> +
> + IfrStrToUpper (String);
> + StringPtr = StrStr (String, L"0X");
> + if (StringPtr != NULL) {
> + //
> + // Hex string
> + //
> + Result->Value.u64 = StrHexToUint64 (String);
> + } else {
> + //
> + // decimal string
> + //
> + Result->Value.u64 = StrDecimalToUint64 (String);
> + }
> +
> + FreePool (String);
> + } else if (IsTypeInBuffer (&Value)) {
> + if (GetLengthForValue (&Value) > 8) {
> + if (Value.Type == EFI_IFR_TYPE_BUFFER) {
> + FreePool (Value.Buffer);
> + }
> +
> + Result->Type = EFI_IFR_TYPE_UNDEFINED;
> + return EFI_SUCCESS;
> + }
> +
> + Result->Value.u64 = *(UINT64 *)GetBufferForValue (&Value);
> + if (Value.Type == EFI_IFR_TYPE_BUFFER) {
> + FreePool (Value.Buffer);
> + }
> + } else {
> + CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));
> + }
> +
> + Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
> + return Status;
> +}
> +
> +/**
> + Evaluate opcode EFI_IFR_CATENATE.
> +
> + @param[in] FormSet Formset which contains this opcode.
> + @param[out] Result Evaluation result for this opcode.
> +
> + @retval EFI_SUCCESS Opcode evaluation success.
> + @retval Other Opcode evaluation failed.
> +
> +**/
> +EFI_STATUS
> +IfrCatenate (
> + IN HII_FORMSET *FormSet,
> + OUT EFI_HII_VALUE *Result
> + )
> +{
> + EFI_STATUS Status;
> + EFI_HII_VALUE Value[2];
> + CHAR16 *String[2];
> + UINTN Index;
> + CHAR16 *StringPtr;
> + UINTN Size;
> + UINT16 Length0;
> + UINT16 Length1;
> + UINT8 *TmpBuf;
> + UINTN MaxLen;
> +
> + if ((FormSet == NULL) || (Result == NULL)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + //
> + // String[0] - The second string
> + // String[1] - The first string
> + //
> + String[0] = NULL;
> + String[1] = NULL;
> + StringPtr = NULL;
> + Status = EFI_SUCCESS;
> + ZeroMem (Value, sizeof (Value));
> +
> + Status = PopExpression (&Value[0]);
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + Status = PopExpression (&Value[1]);
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + for (Index = 0; Index < 2; Index++) {
> + if ((Value[Index].Type != EFI_IFR_TYPE_STRING) && !IsTypeInBuffer
> (&Value[Index])) {
> + Result->Type = EFI_IFR_TYPE_UNDEFINED;
> + Status = EFI_SUCCESS;
> + goto Done;
> + }
> +
> + if (Value[Index].Type == EFI_IFR_TYPE_STRING) {
> + String[Index] = GetTokenString (Value[Index].Value.string, FormSet-
> >HiiHandle);
> + if (String[Index] == NULL) {
> + Status = EFI_NOT_FOUND;
> + goto Done;
> + }
> + }
> + }
> +
> + if (Value[0].Type == EFI_IFR_TYPE_STRING) {
> + Size = StrSize (String[0]);
> + MaxLen = (StrSize (String[1]) + Size) / sizeof (CHAR16);
> + StringPtr = AllocatePool (MaxLen * sizeof (CHAR16));
> + ASSERT (StringPtr != NULL);
> + StrCpyS (StringPtr, MaxLen, String[1]);
> + StrCatS (StringPtr, MaxLen, String[0]);
> +
> + Result->Type = EFI_IFR_TYPE_STRING;
> + Result->Value.string = NewHiiString (StringPtr, FormSet->HiiHandle);
> + } else {
> + Result->Type = EFI_IFR_TYPE_BUFFER;
> + Length0 = GetLengthForValue (&Value[0]);
> + Length1 = GetLengthForValue (&Value[1]);
> + Result->BufferLen = (UINT16)(Length0 + Length1);
> +
> + Result->Buffer = AllocatePool (Result->BufferLen);
> + ASSERT (Result->Buffer != NULL);
> +
> + TmpBuf = GetBufferForValue (&Value[0]);
> + ASSERT (TmpBuf != NULL);
> + CopyMem (Result->Buffer, TmpBuf, Length0);
> + TmpBuf = GetBufferForValue (&Value[1]);
> + ASSERT (TmpBuf != NULL);
> + CopyMem (&Result->Buffer[Length0], TmpBuf, Length1);
> + }
> +
> +Done:
> + if (Value[0].Buffer != NULL) {
> + FreePool (Value[0].Buffer);
> + }
> +
> + if (Value[1].Buffer != NULL) {
> + FreePool (Value[1].Buffer);
> + }
> +
> + if (String[0] != NULL) {
> + FreePool (String[0]);
> + }
> +
> + if (String[1] != NULL) {
> + FreePool (String[1]);
> + }
> +
> + if (StringPtr != NULL) {
> + FreePool (StringPtr);
> + }
> +
> + return Status;
> +}
> +
> +/**
> + Evaluate opcode EFI_IFR_MATCH.
> +
> + @param[in] FormSet Formset which contains this opcode.
> + @param[out] Result Evaluation result for this opcode.
> +
> + @retval EFI_SUCCESS Opcode evaluation success.
> + @retval Other Opcode evaluation failed.
> +
> +**/
> +EFI_STATUS
> +IfrMatch (
> + IN HII_FORMSET *FormSet,
> + OUT EFI_HII_VALUE *Result
> + )
> +{
> + EFI_STATUS Status;
> + EFI_HII_VALUE Value[2];
> + CHAR16 *String[2];
> + UINTN Index;
> +
> + if ((FormSet == NULL) || (Result == NULL)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + //
> + // String[0] - The string to search
> + // String[1] - pattern
> + //
> + String[0] = NULL;
> + String[1] = NULL;
> + Status = EFI_SUCCESS;
> + ZeroMem (Value, sizeof (Value));
> +
> + Status = PopExpression (&Value[0]);
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + Status = PopExpression (&Value[1]);
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + for (Index = 0; Index < 2; Index++) {
> + if (Value[Index].Type != EFI_IFR_TYPE_STRING) {
> + Result->Type = EFI_IFR_TYPE_UNDEFINED;
> + Status = EFI_SUCCESS;
> + goto Done;
> + }
> +
> + String[Index] = GetTokenString (Value[Index].Value.string, FormSet-
> >HiiHandle);
> + if (String[Index] == NULL) {
> + Status = EFI_NOT_FOUND;
> + goto Done;
> + }
> + }
> +
> + Result->Type = EFI_IFR_TYPE_BOOLEAN;
> + Result->Value.b = mUnicodeCollation->MetaiMatch (mUnicodeCollation,
> String[0], String[1]);
> +
> +Done:
> + if (String[0] != NULL) {
> + FreePool (String[0]);
> + }
> +
> + if (String[1] != NULL) {
> + FreePool (String[1]);
> + }
> +
> + return Status;
> +}
> +
> +/**
> + Evaluate opcode EFI_IFR_MATCH2.
> +
> + @param[in] FormSet Formset which contains this opcode.
> + @param[in] SyntaxType Syntax type for match2.
> + @param[out] Result Evaluation result for this opcode.
> +
> + @retval EFI_SUCCESS Opcode evaluation success.
> + @retval Other Opcode evaluation failed.
> +
> +**/
> +EFI_STATUS
> +IfrMatch2 (
> + IN HII_FORMSET *FormSet,
> + IN EFI_GUID *SyntaxType,
> + OUT EFI_HII_VALUE *Result
> + )
> +{
> + EFI_STATUS Status;
> + EFI_HII_VALUE Value[2];
> + CHAR16 *String[2];
> + UINTN Index;
> + UINTN GuidIndex;
> + EFI_HANDLE *HandleBuffer;
> + UINTN BufferSize;
> + EFI_REGULAR_EXPRESSION_PROTOCOL *RegularExpressionProtocol;
> + UINTN RegExSyntaxTypeListSize;
> + EFI_REGEX_SYNTAX_TYPE *RegExSyntaxTypeList;
> + UINTN CapturesCount;
> +
> + if ((FormSet == NULL) || (SyntaxType == NULL) || (Result == NULL)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + //
> + // String[0] - The string to search
> + // String[1] - pattern
> + //
> + String[0] = NULL;
> + String[1] = NULL;
> + HandleBuffer = NULL;
> + RegExSyntaxTypeList = NULL;
> + Status = EFI_SUCCESS;
> + ZeroMem (Value, sizeof (Value));
> +
> + Status = PopExpression (&Value[0]);
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + Status = PopExpression (&Value[1]);
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + for (Index = 0; Index < 2; Index++) {
> + if (Value[Index].Type != EFI_IFR_TYPE_STRING) {
> + Result->Type = EFI_IFR_TYPE_UNDEFINED;
> + Status = EFI_SUCCESS;
> + goto Done;
> + }
> +
> + String[Index] = GetTokenString (Value[Index].Value.string, FormSet-
> >HiiHandle);
> + if (String[Index] == NULL) {
> + Status = EFI_NOT_FOUND;
> + goto Done;
> + }
> + }
> +
> + BufferSize = 0;
> + HandleBuffer = NULL;
> + Status = gBS->LocateHandle (
> + ByProtocol,
> + &gEfiRegularExpressionProtocolGuid,
> + NULL,
> + &BufferSize,
> + HandleBuffer
> + );
> + if (Status == EFI_BUFFER_TOO_SMALL) {
> + HandleBuffer = AllocatePool (BufferSize);
> + if (HandleBuffer == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + goto Done;
> + }
> +
> + Status = gBS->LocateHandle (
> + ByProtocol,
> + &gEfiRegularExpressionProtocolGuid,
> + NULL,
> + &BufferSize,
> + HandleBuffer
> + );
> + }
> +
> + if (EFI_ERROR (Status)) {
> + Result->Type = EFI_IFR_TYPE_UNDEFINED;
> + Status = EFI_SUCCESS;
> + goto Done;
> + }
> +
> + ASSERT (HandleBuffer != NULL);
> + for ( Index = 0; Index < BufferSize / sizeof (EFI_HANDLE); Index++) {
> + Status = gBS->HandleProtocol (
> + HandleBuffer[Index],
> + &gEfiRegularExpressionProtocolGuid,
> + (VOID **)&RegularExpressionProtocol
> + );
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + RegExSyntaxTypeListSize = 0;
> + RegExSyntaxTypeList = NULL;
> +
> + Status = RegularExpressionProtocol->GetInfo (
> + RegularExpressionProtocol,
> + &RegExSyntaxTypeListSize,
> + RegExSyntaxTypeList
> + );
> + if (Status == EFI_BUFFER_TOO_SMALL) {
> + RegExSyntaxTypeList = AllocatePool (RegExSyntaxTypeListSize);
> + if (RegExSyntaxTypeList == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + goto Done;
> + }
> +
> + Status = RegularExpressionProtocol->GetInfo (
> + RegularExpressionProtocol,
> + &RegExSyntaxTypeListSize,
> + RegExSyntaxTypeList
> + );
> + } else if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + for (GuidIndex = 0; GuidIndex < RegExSyntaxTypeListSize / sizeof
> (EFI_GUID); GuidIndex++) {
> + if (CompareGuid (&RegExSyntaxTypeList[GuidIndex], SyntaxType)) {
> + //
> + // Find the match type, return the value.
> + //
> + Result->Type = EFI_IFR_TYPE_BOOLEAN;
> + Status = RegularExpressionProtocol->MatchString (
> + RegularExpressionProtocol,
> + String[0],
> + String[1],
> + SyntaxType,
> + &Result->Value.b,
> + NULL,
> + &CapturesCount
> + );
> + goto Done;
> + }
> + }
> +
> + if (RegExSyntaxTypeList != NULL) {
> + FreePool (RegExSyntaxTypeList);
> + }
> + }
> +
> + //
> + // Type specified by SyntaxType is not supported
> + // in any of the EFI_REGULAR_EXPRESSION_PROTOCOL instances.
> + //
> + Result->Type = EFI_IFR_TYPE_UNDEFINED;
> + Status = EFI_SUCCESS;
> +
> +Done:
> + if (String[0] != NULL) {
> + FreePool (String[0]);
> + }
> +
> + if (String[1] != NULL) {
> + FreePool (String[1]);
> + }
> +
> + if (RegExSyntaxTypeList != NULL) {
> + FreePool (RegExSyntaxTypeList);
> + }
> +
> + if (HandleBuffer != NULL) {
> + FreePool (HandleBuffer);
> + }
> +
> + return Status;
> +}
> +
> +/**
> + Evaluate opcode EFI_IFR_FIND.
> +
> + @param[in] FormSet Formset which contains this opcode.
> + @param[in] Format Case sensitive or insensitive.
> + @param[out] Result Evaluation result for this opcode.
> +
> + @retval EFI_SUCCESS Opcode evaluation success.
> + @retval Other Opcode evaluation failed.
> +
> +**/
> +EFI_STATUS
> +IfrFind (
> + IN HII_FORMSET *FormSet,
> + IN UINT8 Format,
> + OUT EFI_HII_VALUE *Result
> + )
> +{
> + EFI_STATUS Status;
> + EFI_HII_VALUE Value[3];
> + CHAR16 *String[2];
> + UINTN Base;
> + CHAR16 *StringPtr;
> + UINTN Index;
> +
> + if ((FormSet == NULL) || (Result == NULL)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + ZeroMem (Value, sizeof (Value));
> +
> + if (Format > EFI_IFR_FF_CASE_INSENSITIVE) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + Status = PopExpression (&Value[0]);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + Status = PopExpression (&Value[1]);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + Status = PopExpression (&Value[2]);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {
> + Result->Type = EFI_IFR_TYPE_UNDEFINED;
> + return EFI_SUCCESS;
> + }
> +
> + Base = (UINTN)Value[0].Value.u64;
> +
> + //
> + // String[0] - sub-string
> + // String[1] - The string to search
> + //
> + String[0] = NULL;
> + String[1] = NULL;
> + for (Index = 0; Index < 2; Index++) {
> + if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {
> + Result->Type = EFI_IFR_TYPE_UNDEFINED;
> + Status = EFI_SUCCESS;
> + goto Done;
> + }
> +
> + String[Index] = GetTokenString (Value[Index + 1].Value.string, FormSet-
> >HiiHandle);
> + if (String[Index] == NULL) {
> + Status = EFI_NOT_FOUND;
> + goto Done;
> + }
> +
> + if (Format == EFI_IFR_FF_CASE_INSENSITIVE) {
> + //
> + // Case insensitive, convert both string to upper case
> + //
> + IfrStrToUpper (String[Index]);
> + }
> + }
> +
> + Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
> + if (Base >= StrLen (String[1])) {
> + Result->Value.u64 = 0xFFFFFFFFFFFFFFFFULL;
> + } else {
> + StringPtr = StrStr (String[1] + Base, String[0]);
> + Result->Value.u64 = (StringPtr == NULL) ? 0xFFFFFFFFFFFFFFFFULL :
> (StringPtr - String[1]);
> + }
> +
> +Done:
> + if (String[0] != NULL) {
> + FreePool (String[0]);
> + }
> +
> + if (String[1] != NULL) {
> + FreePool (String[1]);
> + }
> +
> + return Status;
> +}
> +
> +/**
> + Evaluate opcode EFI_IFR_MID.
> +
> + @param[in] FormSet Formset which contains this opcode.
> + @param[out] Result Evaluation result for this opcode.
> +
> + @retval EFI_SUCCESS Opcode evaluation success.
> + @retval Other Opcode evaluation failed.
> +
> +**/
> +EFI_STATUS
> +IfrMid (
> + IN HII_FORMSET *FormSet,
> + OUT EFI_HII_VALUE *Result
> + )
> +{
> + EFI_STATUS Status;
> + EFI_HII_VALUE Value[3];
> + CHAR16 *String;
> + UINTN Base;
> + UINTN Length;
> + CHAR16 *SubString;
> + UINT16 BufferLen;
> + UINT8 *Buffer;
> +
> + if ((FormSet == NULL) || (Result == NULL)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + ZeroMem (Value, sizeof (Value));
> +
> + Status = PopExpression (&Value[0]);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + Status = PopExpression (&Value[1]);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + Status = PopExpression (&Value[2]);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {
> + Result->Type = EFI_IFR_TYPE_UNDEFINED;
> + return EFI_SUCCESS;
> + }
> +
> + Length = (UINTN)Value[0].Value.u64;
> +
> + if (Value[1].Type > EFI_IFR_TYPE_NUM_SIZE_64) {
> + Result->Type = EFI_IFR_TYPE_UNDEFINED;
> + return EFI_SUCCESS;
> + }
> +
> + Base = (UINTN)Value[1].Value.u64;
> +
> + if ((Value[2].Type != EFI_IFR_TYPE_STRING) && !IsTypeInBuffer
> (&Value[2])) {
> + Result->Type = EFI_IFR_TYPE_UNDEFINED;
> + return EFI_SUCCESS;
> + }
> +
> + if (Value[2].Type == EFI_IFR_TYPE_STRING) {
> + String = GetTokenString (Value[2].Value.string, FormSet->HiiHandle);
> + if (String == NULL) {
> + return EFI_NOT_FOUND;
> + }
> +
> + if ((Length == 0) || (Base >= StrLen (String))) {
> + SubString = gEmptyString;
> + } else {
> + SubString = String + Base;
> + if ((Base + Length) < StrLen (String)) {
> + SubString[Length] = L'\0';
> + }
> + }
> +
> + Result->Type = EFI_IFR_TYPE_STRING;
> + Result->Value.string = NewHiiString (SubString, FormSet->HiiHandle);
> +
> + FreePool (String);
> + } else {
> + BufferLen = GetLengthForValue (&Value[2]);
> + Buffer = GetBufferForValue (&Value[2]);
> +
> + Result->Type = EFI_IFR_TYPE_BUFFER;
> + if ((Length == 0) || (Base >= BufferLen)) {
> + Result->BufferLen = 0;
> + Result->Buffer = NULL;
> + } else {
> + Result->BufferLen = (UINT16)((BufferLen - Base) < Length ? (BufferLen -
> Base) : Length);
> + Result->Buffer = AllocatePool (Result->BufferLen);
> + ASSERT (Result->Buffer != NULL);
> + CopyMem (Result->Buffer, &Buffer[Base], Result->BufferLen);
> + }
> +
> + if (Value[2].Type == EFI_IFR_TYPE_BUFFER) {
> + FreePool (Value[2].Buffer);
> + }
> + }
> +
> + return Status;
> +}
> +
> +/**
> + Evaluate opcode EFI_IFR_TOKEN.
> +
> + @param[in] FormSet Formset which contains this opcode.
> + @param[out] Result Evaluation result for this opcode.
> +
> + @retval EFI_SUCCESS Opcode evaluation success.
> + @retval Other Opcode evaluation failed.
> +
> +**/
> +EFI_STATUS
> +IfrToken (
> + IN HII_FORMSET *FormSet,
> + OUT EFI_HII_VALUE *Result
> + )
> +{
> + EFI_STATUS Status;
> + EFI_HII_VALUE Value[3];
> + CHAR16 *String[2];
> + UINTN Count;
> + CHAR16 *Delimiter;
> + CHAR16 *SubString;
> + CHAR16 *StringPtr;
> + UINTN Index;
> +
> + if ((FormSet == NULL) || (Result == NULL)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + ZeroMem (Value, sizeof (Value));
> +
> + Status = PopExpression (&Value[0]);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + Status = PopExpression (&Value[1]);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + Status = PopExpression (&Value[2]);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {
> + Result->Type = EFI_IFR_TYPE_UNDEFINED;
> + return EFI_SUCCESS;
> + }
> +
> + Count = (UINTN)Value[0].Value.u64;
> +
> + //
> + // String[0] - Delimiter
> + // String[1] - The string to search
> + //
> + String[0] = NULL;
> + String[1] = NULL;
> + for (Index = 0; Index < 2; Index++) {
> + if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {
> + Result->Type = EFI_IFR_TYPE_UNDEFINED;
> + Status = EFI_SUCCESS;
> + goto Done;
> + }
> +
> + String[Index] = GetTokenString (Value[Index + 1].Value.string, FormSet-
> >HiiHandle);
> + if (String[Index] == NULL) {
> + Status = EFI_NOT_FOUND;
> + goto Done;
> + }
> + }
> +
> + Delimiter = String[0];
> + SubString = String[1];
> + while (Count > 0) {
> + SubString = StrStr (SubString, Delimiter);
> + if (SubString != NULL) {
> + //
> + // Skip over the delimiter
> + //
> + SubString = SubString + StrLen (Delimiter);
> + } else {
> + break;
> + }
> +
> + Count--;
> + }
> +
> + if (SubString == NULL) {
> + //
> + // nth delimited sub-string not found, push an empty string
> + //
> + SubString = gEmptyString;
> + } else {
> + //
> + // Put a NULL terminator for nth delimited sub-string
> + //
> + StringPtr = StrStr (SubString, Delimiter);
> + if (StringPtr != NULL) {
> + *StringPtr = L'\0';
> + }
> + }
> +
> + Result->Type = EFI_IFR_TYPE_STRING;
> + Result->Value.string = NewHiiString (SubString, FormSet->HiiHandle);
> +
> +Done:
> + if (String[0] != NULL) {
> + FreePool (String[0]);
> + }
> +
> + if (String[1] != NULL) {
> + FreePool (String[1]);
> + }
> +
> + return Status;
> +}
> +
> +/**
> + Evaluate opcode EFI_IFR_SPAN.
> +
> + @param[in] FormSet Formset which contains this opcode.
> + @param[in] Flags FIRST_MATCHING or FIRST_NON_MATCHING.
> + @param[out] Result Evaluation result for this opcode.
> +
> + @retval EFI_SUCCESS Opcode evaluation success.
> + @retval Other Opcode evaluation failed.
> +
> +**/
> +EFI_STATUS
> +IfrSpan (
> + IN HII_FORMSET *FormSet,
> + IN UINT8 Flags,
> + OUT EFI_HII_VALUE *Result
> + )
> +{
> + EFI_STATUS Status;
> + EFI_HII_VALUE Value[3];
> + CHAR16 *String[2];
> + CHAR16 *Charset;
> + UINTN Base;
> + UINTN Index;
> + CHAR16 *StringPtr;
> + BOOLEAN Found;
> +
> + if ((FormSet == NULL) || (Result == NULL)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + ZeroMem (Value, sizeof (Value));
> +
> + Status = PopExpression (&Value[0]);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + Status = PopExpression (&Value[1]);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + Status = PopExpression (&Value[2]);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {
> + Result->Type = EFI_IFR_TYPE_UNDEFINED;
> + return EFI_SUCCESS;
> + }
> +
> + Base = (UINTN)Value[0].Value.u64;
> +
> + //
> + // String[0] - Charset
> + // String[1] - The string to search
> + //
> + String[0] = NULL;
> + String[1] = NULL;
> + for (Index = 0; Index < 2; Index++) {
> + if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {
> + Result->Type = EFI_IFR_TYPE_UNDEFINED;
> + Status = EFI_SUCCESS;
> + goto Done;
> + }
> +
> + String[Index] = GetTokenString (Value[Index + 1].Value.string, FormSet-
> >HiiHandle);
> + if (String[Index] == NULL) {
> + Status = EFI_NOT_FOUND;
> + goto Done;
> + }
> + }
> +
> + if (Base >= StrLen (String[1])) {
> + Result->Type = EFI_IFR_TYPE_UNDEFINED;
> + Status = EFI_SUCCESS;
> + goto Done;
> + }
> +
> + Found = FALSE;
> + StringPtr = String[1] + Base;
> + Charset = String[0];
> + while (*StringPtr != 0 && !Found) {
> + Index = 0;
> + while (Charset[Index] != 0) {
> + if ((*StringPtr >= Charset[Index]) && (*StringPtr <= Charset[Index + 1]))
> {
> + if (Flags == EFI_IFR_FLAGS_FIRST_MATCHING) {
> + Found = TRUE;
> + break;
> + }
> + } else {
> + if (Flags == EFI_IFR_FLAGS_FIRST_NON_MATCHING) {
> + Found = TRUE;
> + break;
> + }
> + }
> +
> + //
> + // Skip characters pair representing low-end of a range and high-end of a
> range
> + //
> + Index += 2;
> + }
> +
> + if (!Found) {
> + StringPtr++;
> + }
> + }
> +
> + Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
> + Result->Value.u64 = StringPtr - String[1];
> +
> +Done:
> + if (String[0] != NULL) {
> + FreePool (String[0]);
> + }
> +
> + if (String[1] != NULL) {
> + FreePool (String[1]);
> + }
> +
> + return Status;
> +}
> +
> +/**
> + Get Expression given its RuleId.
> +
> + @param[in] Form The form which contains this Expression.
> + @param[in] RuleId Id of this Expression.
> +
> + @retval Pointer The Expression.
> + @retval NULL Specified Expression not found in the form.
> +
> +**/
> +HII_EXPRESSION *
> +RuleIdToExpression (
> + IN HII_FORM *Form,
> + IN UINT8 RuleId
> + )
> +{
> + LIST_ENTRY *Link;
> + HII_EXPRESSION *Expression;
> +
> + if (Form == NULL) {
> + return NULL;
> + }
> +
> + Link = GetFirstNode (&Form->RuleListHead);
> + while (!IsNull (&Form->RuleListHead, Link)) {
> + Expression = HII_EXPRESSION_FROM_LINK (Link);
> +
> + if ((Expression->Type == EFI_HII_EXPRESSION_RULE) && (Expression-
> >ExtraData.RuleId == RuleId)) {
> + return Expression;
> + }
> +
> + Link = GetNextNode (&Form->RuleListHead, Link);
> + }
> +
> + return NULL;
> +}
> +
> +/**
> + Locate the Unicode Collation Protocol interface for later use.
> +
> + @retval EFI_SUCCESS Protocol interface initialize success.
> + @retval Other Protocol interface initialize failed.
> +
> +**/
> +EFI_STATUS
> +InitializeUnicodeCollationProtocol (
> + VOID
> + )
> +{
> + EFI_STATUS Status;
> +
> + if (mUnicodeCollation != NULL) {
> + return EFI_SUCCESS;
> + }
> +
> + //
> + // BUGBUG: Proper implementation is to locate all Unicode Collation
> Protocol
> + // instances first and then select one which support English language.
> + // Current implementation just pick the first instance.
> + //
> + Status = gBS->LocateProtocol (
> + &gEfiUnicodeCollation2ProtocolGuid,
> + NULL,
> + (VOID **)&mUnicodeCollation
> + );
> + return Status;
> +}
> +
> +/**
> + Check whether the formset guid is in this Hii package list.
> +
> + @param[in] HiiHandle The HiiHandle for this HII package list.
> + @param[in] FormSetGuid The formset guid for the request formset.
> +
> + @retval TRUE Find the formset guid.
> + @retval FALSE Not found the formset guid.
> +
> +**/
> +BOOLEAN
> +IsFormsetGuidInHiiHandle (
> + IN EFI_HII_HANDLE HiiHandle,
> + IN EFI_GUID *FormSetGuid
> + )
> +{
> + EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
> + UINTN BufferSize;
> + UINT32 Offset;
> + UINT32 Offset2;
> + UINT32 PackageListLength;
> + EFI_HII_PACKAGE_HEADER *PackageHeader;
> + UINT8 *Package;
> + UINT8 *OpCodeData;
> + EFI_STATUS Status;
> + BOOLEAN FindGuid;
> + EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
> +
> + if (FormSetGuid == NULL) {
> + return FALSE;
> + }
> +
> + BufferSize = 0;
> + HiiPackageList = NULL;
> + FindGuid = FALSE;
> +
> + //
> + // Locate required Hii Database protocol
> + //
> + Status = gBS->LocateProtocol (
> + &gEfiHiiDatabaseProtocolGuid,
> + NULL,
> + (VOID **)&HiiDatabase
> + );
> + if (EFI_ERROR (Status)) {
> + return FALSE;
> + }
> +
> + Status = HiiDatabase->ExportPackageLists (HiiDatabase, HiiHandle,
> &BufferSize, HiiPackageList);
> + if (Status == EFI_BUFFER_TOO_SMALL) {
> + HiiPackageList = AllocatePool (BufferSize);
> + if (HiiPackageList == NULL) {
> + ASSERT (HiiPackageList != NULL);
> + return FALSE;
> + }
> +
> + Status = HiiDatabase->ExportPackageLists (HiiDatabase, HiiHandle,
> &BufferSize, HiiPackageList);
> + } else {
> + //
> + // Fix coverity: 14253 Explicit null dereferenced.
> + // When calling ExportPackageLists with BufferSize = 0, only
> EFI_BUFFER_TOO_SMALL is expected.
> + // Otherwise, return FALSE immediately.
> + //
> + return FALSE;
> + }
> +
> + if (EFI_ERROR (Status)) {
> + if (HiiPackageList != NULL) {
> + FreePool (HiiPackageList);
> + }
> +
> + return FALSE;
> + }
> +
> + //
> + // Get Form package from this HII package List
> + //
> + Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
> + Offset2 = 0;
> + PackageListLength = HiiPackageList->PackageLength;
> +
> + while (Offset < PackageListLength) {
> + Package = ((UINT8 *)HiiPackageList) + Offset;
> + PackageHeader = (EFI_HII_PACKAGE_HEADER *)Package;
> + Offset += PackageHeader->Length;
> +
> + if (PackageHeader->Type == EFI_HII_PACKAGE_FORMS) {
> + //
> + // Search FormSet in this Form Package
> + //
> + Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);
> + while (Offset2 < PackageHeader->Length) {
> + OpCodeData = Package + Offset2;
> +
> + if (((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode ==
> EFI_IFR_FORM_SET_OP) {
> + if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof
> (EFI_IFR_OP_HEADER)))) {
> + FindGuid = TRUE;
> + break;
> + }
> + }
> +
> + Offset2 += ((EFI_IFR_OP_HEADER *)OpCodeData)->Length;
> + }
> + }
> +
> + if (FindGuid) {
> + break;
> + }
> + }
> +
> + FreePool (HiiPackageList);
> +
> + return FindGuid;
> +}
> +
> +/**
> + Find HII Handle in the HII database associated with given Device Path.
> +
> + If DevicePath is NULL, then ASSERT.
> +
> + @param[in] DevicePath Device Path associated with the HII package
> list
> + handle.
> + @param[in] FormsetGuid The formset guid for this formset.
> +
> + @retval Handle HII package list Handle associated with the Device
> + Path.
> + @retval NULL Hii Package list handle is not found.
> +
> +**/
> +EFI_HII_HANDLE
> +DevicePathToHiiHandle (
> + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
> + IN EFI_GUID *FormsetGuid
> + )
> +{
> + EFI_STATUS Status;
> + EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;
> + UINTN Index;
> + EFI_HANDLE Handle;
> + EFI_HANDLE DriverHandle;
> + EFI_HII_HANDLE *HiiHandles;
> + EFI_HII_HANDLE HiiHandle;
> + EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
> +
> + if ((DevicePath == NULL) || (FormsetGuid == NULL)) {
> + return NULL;
> + }
> +
> + TmpDevicePath = DevicePath;
> + //
> + // Locate Device Path Protocol handle buffer
> + //
> + Status = gBS->LocateDevicePath (
> + &gEfiDevicePathProtocolGuid,
> + &TmpDevicePath,
> + &DriverHandle
> + );
> + if (EFI_ERROR (Status) || !IsDevicePathEnd (TmpDevicePath)) {
> + return NULL;
> + }
> +
> + //
> + // Locate required Hii Database protocol
> + //
> + Status = gBS->LocateProtocol (
> + &gEfiHiiDatabaseProtocolGuid,
> + NULL,
> + (VOID **)&HiiDatabase
> + );
> + if (EFI_ERROR (Status)) {
> + return NULL;
> + }
> +
> + //
> + // Retrieve all HII Handles from HII database
> + //
> + HiiHandles = HiiGetHiiHandles (NULL);
> + if (HiiHandles == NULL) {
> + return NULL;
> + }
> +
> + //
> + // Search Hii Handle by Driver Handle
> + //
> + HiiHandle = NULL;
> + for (Index = 0; HiiHandles[Index] != NULL; Index++) {
> + Status = HiiDatabase->GetPackageListHandle (
> + HiiDatabase,
> + HiiHandles[Index],
> + &Handle
> + );
> + if (!EFI_ERROR (Status) && (Handle == DriverHandle)) {
> + if (IsFormsetGuidInHiiHandle (HiiHandles[Index], FormsetGuid)) {
> + HiiHandle = HiiHandles[Index];
> + break;
> + }
> +
> + if (HiiHandle != NULL) {
> + break;
> + }
> + }
> + }
> +
> + FreePool (HiiHandles);
> + return HiiHandle;
> +}
> +
> +/**
> + Get question value from the predefined formset.
> +
> + @param[in] DevicePath The driver's device path which produce the
> formset data.
> + @param[in] InputHiiHandle The hii handle associate with the formset
> data.
> + @param[in] FormSetGuid The formset guid which include the question.
> + @param[in] QuestionId The question id which need to get value from.
> + @param[out] Value The return data about question's value.
> +
> + @retval TRUE Get the question value success.
> + @retval FALSE Get the question value failed.
> +**/
> +BOOLEAN
> +GetQuestionValueFromForm (
> + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
> + IN EFI_HII_HANDLE InputHiiHandle,
> + IN EFI_GUID *FormSetGuid,
> + IN EFI_QUESTION_ID QuestionId,
> + OUT EFI_HII_VALUE *Value
> + )
> +{
> + EFI_STATUS Status;
> + EFI_HII_HANDLE HiiHandle;
> + HII_STATEMENT *Question;
> + HII_FORMSET *FormSet;
> + HII_FORM *Form;
> + BOOLEAN GetTheVal;
> + LIST_ENTRY *Link;
> +
> + //
> + // The input parameter DevicePath or InputHiiHandle must have one valid
> input.
> + //
> + if ((DevicePath == NULL) && (InputHiiHandle == NULL)) {
> + ASSERT (
> + (DevicePath != NULL && InputHiiHandle == NULL) ||
> + (DevicePath == NULL && InputHiiHandle != NULL)
> + );
> + return FALSE;
> + }
> +
> + if ((FormSetGuid == NULL) || (Value == NULL)) {
> + return FALSE;
> + }
> +
> + GetTheVal = TRUE;
> + HiiHandle = NULL;
> + Question = NULL;
> + Form = NULL;
> +
> + //
> + // Get HiiHandle.
> + //
> + if (DevicePath != NULL) {
> + HiiHandle = DevicePathToHiiHandle (DevicePath, FormSetGuid);
> + if (HiiHandle == NULL) {
> + return FALSE;
> + }
> + } else {
> + HiiHandle = InputHiiHandle;
> + }
> +
> + ASSERT (HiiHandle != NULL);
> +
> + //
> + // Get the formset data include this question.
> + //
> + FormSet = AllocateZeroPool (sizeof (HII_FORMSET));
> + ASSERT (FormSet != NULL);
> +
> + Status = CreateFormSetFromHiiHandle (HiiHandle, FormSetGuid, FormSet);
> + if (EFI_ERROR (Status)) {
> + GetTheVal = FALSE;
> + goto Done;
> + }
> +
> + InitializeFormSet (FormSet);
> +
> + //
> + // Base on the Question Id to get the question info.
> + //
> + Question = QuestionIdInFormset (FormSet, NULL, QuestionId);
> + if (Question == NULL) {
> + GetTheVal = FALSE;
> + goto Done;
> + }
> +
> + //
> + // Search form in the formset scope
> + //
> + Link = GetFirstNode (&FormSet->FormListHead);
> + while (!IsNull (&FormSet->FormListHead, Link)) {
> + Form = HII_FORM_FROM_LINK (Link);
> +
> + Question = QuestionIdInForm (Form, QuestionId);
> + if (Question != NULL) {
> + break;
> + }
> +
> + Link = GetNextNode (&FormSet->FormListHead, Link);
> + Form = NULL;
> + }
> +
> + ASSERT (Form != NULL);
> +
> + //
> + // Get the question value.
> + //
> + Status = GetQuestionValue (FormSet, Form, Question,
> GetSetValueWithBuffer);
> + if (EFI_ERROR (Status)) {
> + GetTheVal = FALSE;
> + goto Done;
> + }
> +
> + CopyMem (Value, &Question->Value, sizeof (EFI_HII_VALUE));
> +
> +Done:
> + //
> + // Clean the formset structure and restore the global parameter.
> + //
> + if (FormSet != NULL) {
> + DestroyFormSet (FormSet);
> + }
> +
> + return GetTheVal;
> +}
> +
> +/**
> + Covert HII_STATEMENT_VALUE to EFI_HII_VALUE.
> +
> + The HiiValue->Buffer is allocated from EFI boot services memory. It is the
> + responsibility of the caller to free the memory allocated.
> +
> + @param[in] StatementValue Source to be converted.
> + @param[out] HiiValue The buffer that is converted from
> StatementValue
> +
> + @retval EFI_SUCCESS Convert successfully.
> + @retval EFI_INVALID_PARAMETER StatementValue is NULL or HiiValue is
> NULL.
> +
> +**/
> +EFI_STATUS
> +HiiStatementValueToHiiValue (
> + IN HII_STATEMENT_VALUE *StatementValue,
> + OUT EFI_HII_VALUE *HiiValue
> + )
> +{
> + if ((StatementValue == NULL) || (HiiValue == NULL)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + ZeroMem (HiiValue, sizeof (EFI_HII_VALUE));
> +
> + HiiValue->Type = StatementValue->Type;
> + HiiValue->BufferLen = StatementValue->BufferLen;
> + if ((StatementValue->Buffer != NULL) && (StatementValue->BufferLen >
> 0)) {
> + HiiValue->Buffer = AllocateCopyPool (HiiValue->BufferLen,
> StatementValue->Buffer);
> + }
> +
> + CopyMem (&HiiValue->Value, &StatementValue->Value, sizeof
> (EFI_IFR_TYPE_VALUE));
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Release the buffer in EFI_HII_VALUE if the buffer is not NULL.
> +
> + @param[in] HiiValue The buffer to be released.
> +
> + @retval EFI_SUCCESS release HiiValue successfully.
> + @retval EFI_INVALID_PARAMETER HiiValue is NULL.
> +
> +**/
> +EFI_STATUS
> +ReleaseHiiValue (
> + IN EFI_HII_VALUE *HiiValue
> + )
> +{
> + if (HiiValue == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + if (HiiValue->Buffer == NULL) {
> + return EFI_SUCCESS;
> + }
> +
> + FreePool (HiiValue->Buffer);
> + ZeroMem (HiiValue, sizeof (EFI_HII_VALUE));
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Evaluate the result of a HII expression.
> +
> + If Expression is NULL, then ASSERT.
> +
> + @param[in] FormSet FormSet associated with this expression.
> + @param[in] Form Form associated with this expression.
> + @param[in,out] Expression Expression to be evaluated.
> +
> + @retval EFI_SUCCESS The expression evaluated successfully.
> + @retval EFI_NOT_FOUND The Question which referenced by a
> QuestionId
> + could not be found.
> + @retval EFI_OUT_OF_RESOURCES There is not enough system memory
> to grow the
> + stack.
> + @retval EFI_ACCESS_DENIED The pop operation underflowed the stack.
> + @retval EFI_INVALID_PARAMETER Syntax error with the Expression.
> + @retval EFI_INVALID_PARAMETER Formset, Form or Expression is NULL.
> +
> +**/
> +EFI_STATUS
> +EvaluateHiiExpression (
> + IN HII_FORMSET *FormSet,
> + IN HII_FORM *Form,
> + IN OUT HII_EXPRESSION *Expression
> + )
> +{
> + EFI_STATUS Status;
> + LIST_ENTRY *Link;
> + HII_EXPRESSION_OPCODE *OpCode;
> + HII_STATEMENT *Question;
> + HII_STATEMENT *Question2;
> + UINT16 Index;
> + EFI_HII_VALUE Data1;
> + EFI_HII_VALUE Data2;
> + EFI_HII_VALUE Data3;
> + HII_EXPRESSION *RuleExpression;
> + EFI_HII_VALUE *Value;
> + INTN Result;
> + CHAR16 *StrPtr;
> + CHAR16 *NameValue;
> + UINT32 TempValue;
> + LIST_ENTRY *SubExpressionLink;
> + HII_EXPRESSION *SubExpression;
> + UINTN StackOffset;
> + UINTN TempLength;
> + CHAR16 TempStr[5];
> + UINT8 DigitUint8;
> + UINT8 *TempBuffer;
> + EFI_TIME EfiTime;
> + EFI_HII_VALUE QuestionVal;
> + EFI_DEVICE_PATH_PROTOCOL *DevicePath;
> + EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *PathFromText;
> +
> + if ((FormSet == NULL) || (Form == NULL) || (Expression == NULL)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + StrPtr = NULL;
> + DevicePath = NULL;
> + PathFromText = NULL;
> +
> + //
> + // Save current stack offset.
> + //
> + StackOffset = SaveExpressionEvaluationStackOffset ();
> +
> + ASSERT (Expression != NULL);
> + Expression->Result.Type = EFI_IFR_TYPE_OTHER;
> +
> + Link = GetFirstNode (&Expression->OpCodeListHead);
> + while (!IsNull (&Expression->OpCodeListHead, Link)) {
> + OpCode = HII_EXPRESSION_OPCODE_FROM_LINK (Link);
> +
> + Link = GetNextNode (&Expression->OpCodeListHead, Link);
> +
> + ZeroMem (&Data1, sizeof (EFI_HII_VALUE));
> + ZeroMem (&Data2, sizeof (EFI_HII_VALUE));
> + ZeroMem (&Data3, sizeof (EFI_HII_VALUE));
> +
> + Value = &Data3;
> + Value->Type = EFI_IFR_TYPE_BOOLEAN;
> + Status = EFI_SUCCESS;
> +
> + switch (OpCode->Operand) {
> + //
> + // Built-in functions
> + //
> + case EFI_IFR_EQ_ID_VAL_OP:
> + Question = QuestionIdInFormset (FormSet, Form, OpCode-
> >ExtraData.EqIdValData.QuestionId);
> + if (Question == NULL) {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + break;
> + }
> +
> + //
> + // Load value from storage.
> + //
> + Status = GetQuestionValue (FormSet, Form, Question,
> GetSetValueWithBuffer);
> + if (EFI_ERROR (Status)) {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + break;
> + }
> +
> + Status = HiiStatementValueToHiiValue (&Question->Value, &Data1);
> + if (EFI_ERROR (Status)) {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + break;
> + }
> +
> + Status = CompareHiiValue (&Data1, &OpCode-
> >ExtraData.EqIdValData.Value, &Result, NULL);
> + ReleaseHiiValue (&Data1);
> + if (Status == EFI_UNSUPPORTED) {
> + Status = EFI_SUCCESS;
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + break;
> + }
> +
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + Value->Value.b = (BOOLEAN)((Result == 0) ? TRUE : FALSE);
> + break;
> +
> + case EFI_IFR_EQ_ID_ID_OP:
> + Question = QuestionIdInFormset (FormSet, Form, OpCode-
> >ExtraData.EqIdIdData.QuestionId1);
> + if (Question == NULL) {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + break;
> + }
> +
> + //
> + // Load value from storage.
> + //
> + Status = GetQuestionValue (FormSet, Form, Question,
> GetSetValueWithBuffer);
> + if (EFI_ERROR (Status)) {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + break;
> + }
> +
> + Status = HiiStatementValueToHiiValue (&Question->Value, &Data1);
> + if (EFI_ERROR (Status)) {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + break;
> + }
> +
> + Question2 = QuestionIdInFormset (FormSet, Form, OpCode-
> >ExtraData.EqIdIdData.QuestionId2);
> + if (Question2 == NULL) {
> + ReleaseHiiValue (&Data1);
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + break;
> + }
> +
> + //
> + // Load value from storage.
> + //
> + Status = GetQuestionValue (FormSet, Form, Question2,
> GetSetValueWithBuffer);
> + if (EFI_ERROR (Status)) {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + break;
> + }
> +
> + Status = HiiStatementValueToHiiValue (&Question2->Value, &Data2);
> + if (EFI_ERROR (Status)) {
> + ReleaseHiiValue (&Data1);
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + break;
> + }
> +
> + Status = CompareHiiValue (&Data1, &Data2, &Result, FormSet-
> >HiiHandle);
> + ReleaseHiiValue (&Data1);
> + ReleaseHiiValue (&Data2);
> + if (Status == EFI_UNSUPPORTED) {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + Status = EFI_SUCCESS;
> + break;
> + }
> +
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + Value->Value.b = (BOOLEAN)((Result == 0) ? TRUE : FALSE);
> + break;
> +
> + case EFI_IFR_EQ_ID_VAL_LIST_OP:
> + Question = QuestionIdInFormset (FormSet, Form, OpCode-
> >ExtraData.EqIdListData.QuestionId);
> + if (Question == NULL) {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + break;
> + }
> +
> + //
> + // Load value from storage.
> + //
> + Status = GetQuestionValue (FormSet, Form, Question,
> GetSetValueWithBuffer);
> + if (EFI_ERROR (Status)) {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + break;
> + }
> +
> + Value->Value.b = FALSE;
> + for (Index = 0; Index < OpCode->ExtraData.EqIdListData.ListLength;
> Index++) {
> + if (Question->Value.Value.u16 == OpCode-
> >ExtraData.EqIdListData.ValueList[Index]) {
> + Value->Value.b = TRUE;
> + break;
> + }
> + }
> +
> + break;
> +
> + case EFI_IFR_DUP_OP:
> + Status = PopExpression (Value);
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + Status = PushExpression (Value);
> + break;
> +
> + case EFI_IFR_QUESTION_REF1_OP:
> + case EFI_IFR_THIS_OP:
> + Question = QuestionIdInFormset (FormSet, Form, OpCode-
> >ExtraData.QuestionRef1Data.QuestionId);
> + if (Question == NULL) {
> + Status = EFI_NOT_FOUND;
> + goto Done;
> + }
> +
> + //
> + // Load value from storage.
> + //
> + Status = GetQuestionValue (FormSet, Form, Question,
> GetSetValueWithBuffer);
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + Value = (EFI_HII_VALUE *)&Question->Value;
> + break;
> +
> + case EFI_IFR_SECURITY_OP:
> + Value->Value.b = CheckUserPrivilege (&OpCode->ExtraData.Guid);
> + break;
> +
> + case EFI_IFR_GET_OP:
> + //
> + // Get Value from VarStore buffer, EFI VarStore, Name/Value VarStore.
> + //
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + Value->Value.u8 = 0;
> + if (OpCode->ExtraData.GetSetData.VarStorage != NULL) {
> + switch (OpCode->ExtraData.GetSetData.VarStorage->Type) {
> + case EFI_HII_VARSTORE_BUFFER:
> + case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
> + //
> + // Get value from Edit Buffer
> + //
> + Value->Type = OpCode->ExtraData.GetSetData.ValueType;
> + CopyMem (&Value->Value, OpCode-
> >ExtraData.GetSetData.VarStorage->EditBuffer + OpCode-
> >ExtraData.GetSetData.VarStoreInfo.VarOffset, OpCode-
> >ExtraData.GetSetData.ValueWidth);
> + break;
> + case EFI_HII_VARSTORE_NAME_VALUE:
> + if (OpCode->ExtraData.GetSetData.ValueType !=
> EFI_IFR_TYPE_STRING) {
> + //
> + // Get value from string except for STRING value.
> + //
> + Status = GetValueByName (OpCode-
> >ExtraData.GetSetData.VarStorage, OpCode-
> >ExtraData.GetSetData.ValueName, &StrPtr);
> + if (!EFI_ERROR (Status)) {
> + ASSERT (StrPtr != NULL);
> + TempLength = StrLen (StrPtr);
> + if (OpCode->ExtraData.GetSetData.ValueWidth >= ((TempLength
> + 1) / 2)) {
> + Value->Type = OpCode->ExtraData.GetSetData.ValueType;
> + TempBuffer = (UINT8 *)&Value->Value;
> + ZeroMem (TempStr, sizeof (TempStr));
> + for (Index = 0; Index < TempLength; Index++) {
> + TempStr[0] = StrPtr[TempLength - Index - 1];
> + DigitUint8 = (UINT8)StrHexToUint64 (TempStr);
> + if ((Index & 1) == 0) {
> + TempBuffer[Index/2] = DigitUint8;
> + } else {
> + TempBuffer[Index/2] = (UINT8)((DigitUint8 << 4) +
> TempBuffer[Index/2]);
> + }
> + }
> + }
> + }
> + }
> +
> + break;
> + case EFI_HII_VARSTORE_EFI_VARIABLE:
> + //
> + // Get value from variable.
> + //
> + TempLength = OpCode->ExtraData.GetSetData.ValueWidth;
> + Value->Type = OpCode->ExtraData.GetSetData.ValueType;
> + Status = gRT->GetVariable (
> + OpCode->ExtraData.GetSetData.ValueName,
> + &OpCode->ExtraData.GetSetData.VarStorage->Guid,
> + NULL,
> + &TempLength,
> + &Value->Value
> + );
> + if (EFI_ERROR (Status)) {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + Value->Value.u8 = 0;
> + }
> +
> + break;
> + default:
> + //
> + // Not recognize storage.
> + //
> + Status = EFI_UNSUPPORTED;
> + goto Done;
> + }
> + } else {
> + //
> + // For Time/Date Data
> + //
> + if ((OpCode->ExtraData.GetSetData.ValueType != EFI_IFR_TYPE_DATE)
> && (OpCode->ExtraData.GetSetData.ValueType != EFI_IFR_TYPE_TIME)) {
> + //
> + // Only support Data/Time data when storage doesn't exist.
> + //
> + Status = EFI_UNSUPPORTED;
> + goto Done;
> + }
> +
> + Status = gRT->GetTime (&EfiTime, NULL);
> + if (!EFI_ERROR (Status)) {
> + if (OpCode->ExtraData.GetSetData.ValueType == EFI_IFR_TYPE_DATE)
> {
> + switch (OpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset) {
> + case 0x00:
> + Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
> + Value->Value.u16 = EfiTime.Year;
> + break;
> + case 0x02:
> + Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
> + Value->Value.u8 = EfiTime.Month;
> + break;
> + case 0x03:
> + Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
> + Value->Value.u8 = EfiTime.Day;
> + break;
> + default:
> + //
> + // Invalid Date field.
> + //
> + Status = EFI_INVALID_PARAMETER;
> + goto Done;
> + }
> + } else {
> + switch (OpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset) {
> + case 0x00:
> + Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
> + Value->Value.u8 = EfiTime.Hour;
> + break;
> + case 0x01:
> + Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
> + Value->Value.u8 = EfiTime.Minute;
> + break;
> + case 0x02:
> + Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
> + Value->Value.u8 = EfiTime.Second;
> + break;
> + default:
> + //
> + // Invalid Time field.
> + //
> + Status = EFI_INVALID_PARAMETER;
> + goto Done;
> + }
> + }
> + }
> + }
> +
> + break;
> +
> + case EFI_IFR_QUESTION_REF3_OP:
> + //
> + // EFI_IFR_QUESTION_REF3
> + // Pop an expression from the expression stack
> + //
> + Status = PopExpression (Value);
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + //
> + // Validate the expression value
> + //
> + if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64
> > 0xffff)) {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + break;
> + }
> +
> + if (OpCode->ExtraData.QuestionRef3Data.DevicePath != 0) {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> +
> + Status = gBS->LocateProtocol (
> + &gEfiDevicePathFromTextProtocolGuid,
> + NULL,
> + (VOID **)&PathFromText
> + );
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + StrPtr = GetTokenString (OpCode-
> >ExtraData.QuestionRef3Data.DevicePath, FormSet->HiiHandle);
> + if ((StrPtr != NULL) && (PathFromText != NULL)) {
> + DevicePath = PathFromText->ConvertTextToDevicePath (StrPtr);
> + if ((DevicePath != NULL) && GetQuestionValueFromForm
> (DevicePath, NULL, &OpCode->ExtraData.Guid, Value->Value.u16,
> &QuestionVal)) {
> + Value = &QuestionVal;
> + }
> +
> + if (DevicePath != NULL) {
> + FreePool (DevicePath);
> + }
> + }
> +
> + if (StrPtr != NULL) {
> + FreePool (StrPtr);
> + }
> + } else if (IsZeroGuid (&OpCode->ExtraData.Guid)) {
> + if (!GetQuestionValueFromForm (NULL, FormSet->HiiHandle,
> &OpCode->ExtraData.Guid, Value->Value.u16, &QuestionVal)) {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + break;
> + }
> +
> + Value = &QuestionVal;
> + } else {
> + Question = QuestionIdInFormset (FormSet, Form, Value->Value.u16);
> + if (Question == NULL) {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + break;
> + }
> +
> + //
> + // Load value from storage.
> + //
> + Status = GetQuestionValue (FormSet, Form, Question,
> GetSetValueWithBuffer);
> + if (EFI_ERROR (Status)) {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + break;
> + }
> +
> + //
> + // push the questions' value on to the expression stack
> + //
> + Value = (EFI_HII_VALUE *)&Question->Value;
> + }
> +
> + break;
> +
> + case EFI_IFR_RULE_REF_OP:
> + //
> + // Find expression for this rule
> + //
> + RuleExpression = RuleIdToExpression (Form, OpCode-
> >ExtraData.RuleId);
> + if (RuleExpression == NULL) {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + break;
> + }
> +
> + //
> + // Evaluate this rule expression
> + //
> + Status = EvaluateHiiExpression (FormSet, Form, RuleExpression);
> + if (EFI_ERROR (Status) || (RuleExpression->Result.Type ==
> EFI_IFR_TYPE_UNDEFINED)) {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + break;
> + }
> +
> + Value = &RuleExpression->Result;
> + break;
> +
> + case EFI_IFR_STRING_REF1_OP:
> + Value->Type = EFI_IFR_TYPE_STRING;
> + Value->Value.string = OpCode->ExtraData.Value.Value.string;
> + break;
> +
> + //
> + // Constant
> + //
> + case EFI_IFR_TRUE_OP:
> + case EFI_IFR_FALSE_OP:
> + case EFI_IFR_ONE_OP:
> + case EFI_IFR_ONES_OP:
> + case EFI_IFR_UINT8_OP:
> + case EFI_IFR_UINT16_OP:
> + case EFI_IFR_UINT32_OP:
> + case EFI_IFR_UINT64_OP:
> + case EFI_IFR_UNDEFINED_OP:
> + case EFI_IFR_VERSION_OP:
> + case EFI_IFR_ZERO_OP:
> + Value = &OpCode->ExtraData.Value;
> + break;
> +
> + //
> + // unary-op
> + //
> + case EFI_IFR_LENGTH_OP:
> + Status = PopExpression (Value);
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + if ((Value->Type != EFI_IFR_TYPE_STRING) && !IsTypeInBuffer (Value))
> {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + break;
> + }
> +
> + if (Value->Type == EFI_IFR_TYPE_STRING) {
> + StrPtr = GetTokenString (Value->Value.string, FormSet->HiiHandle);
> + if (StrPtr == NULL) {
> + Status = EFI_INVALID_PARAMETER;
> + goto Done;
> + }
> +
> + Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
> + Value->Value.u64 = StrLen (StrPtr);
> + FreePool (StrPtr);
> + } else {
> + Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
> + Value->Value.u64 = GetLengthForValue (Value);
> + FreePool (Value->Buffer);
> + }
> +
> + break;
> +
> + case EFI_IFR_NOT_OP:
> + Status = PopExpression (Value);
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + break;
> + }
> +
> + Value->Value.b = (BOOLEAN)(!Value->Value.b);
> + break;
> +
> + case EFI_IFR_QUESTION_REF2_OP:
> + //
> + // Pop an expression from the expression stack
> + //
> + Status = PopExpression (Value);
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + //
> + // Validate the expression value
> + //
> + if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64
> > 0xffff)) {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + break;
> + }
> +
> + Question = QuestionIdInFormset (FormSet, Form, Value->Value.u16);
> + if (Question == NULL) {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + break;
> + }
> +
> + //
> + // Load value from storage.
> + //
> + Status = GetQuestionValue (FormSet, Form, Question,
> GetSetValueWithBuffer);
> + if (EFI_ERROR (Status)) {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + break;
> + }
> +
> + Value = (EFI_HII_VALUE *)&Question->Value;
> + break;
> +
> + case EFI_IFR_STRING_REF2_OP:
> + //
> + // Pop an expression from the expression stack
> + //
> + Status = PopExpression (Value);
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + //
> + // Validate the expression value
> + //
> + if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64
> > 0xffff)) {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + break;
> + }
> +
> + Value->Type = EFI_IFR_TYPE_STRING;
> + StrPtr = GetTokenString (Value->Value.u16, FormSet->HiiHandle);
> + if (StrPtr == NULL) {
> + //
> + // If String not exit, push an empty string
> + //
> + Value->Value.string = NewHiiString (gEmptyString, FormSet-
> >HiiHandle);
> + } else {
> + Index = (UINT16)Value->Value.u64;
> + Value->Value.string = Index;
> + FreePool (StrPtr);
> + }
> +
> + break;
> +
> + case EFI_IFR_TO_BOOLEAN_OP:
> + //
> + // Pop an expression from the expression stack
> + //
> + Status = PopExpression (Value);
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + //
> + // Convert an expression to a Boolean
> + //
> + if (Value->Type <= EFI_IFR_TYPE_DATE) {
> + //
> + // When converting from an unsigned integer, zero will be converted
> to
> + // FALSE and any other value will be converted to TRUE.
> + //
> + Value->Value.b = (BOOLEAN)(HiiValueToUINT64 (Value) != 0);
> +
> + Value->Type = EFI_IFR_TYPE_BOOLEAN;
> + } else if (Value->Type == EFI_IFR_TYPE_STRING) {
> + //
> + // When converting from a string, if case-insensitive compare
> + // with "true" is True, then push True. If a case-insensitive compare
> + // with "false" is True, then push False. Otherwise, push Undefined.
> + //
> + StrPtr = GetTokenString (Value->Value.string, FormSet->HiiHandle);
> + if (StrPtr == NULL) {
> + Status = EFI_INVALID_PARAMETER;
> + goto Done;
> + }
> +
> + IfrStrToUpper (StrPtr);
> + if (StrCmp (StrPtr, L"TRUE") == 0) {
> + Value->Value.b = TRUE;
> + Value->Type = EFI_IFR_TYPE_BOOLEAN;
> + } else if (StrCmp (StrPtr, L"FALSE") == 0) {
> + Value->Value.b = FALSE;
> + Value->Type = EFI_IFR_TYPE_BOOLEAN;
> + } else {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + }
> +
> + FreePool (StrPtr);
> + } else if (Value->Type == EFI_IFR_TYPE_BUFFER) {
> + //
> + // When converting from a buffer, if the buffer is all zeroes,
> + // then push False. Otherwise push True.
> + //
> + for (Index = 0; Index < Value->BufferLen; Index++) {
> + if (Value->Buffer[Index] != 0) {
> + break;
> + }
> + }
> +
> + if (Index >= Value->BufferLen) {
> + Value->Value.b = FALSE;
> + } else {
> + Value->Value.b = TRUE;
> + }
> +
> + Value->Type = EFI_IFR_TYPE_BOOLEAN;
> + FreePool (Value->Buffer);
> + }
> +
> + break;
> +
> + case EFI_IFR_TO_STRING_OP:
> + Status = IfrToString (FormSet, OpCode->ExtraData.Format, Value);
> + break;
> +
> + case EFI_IFR_TO_UINT_OP:
> + Status = IfrToUint (FormSet, Value);
> + break;
> +
> + case EFI_IFR_TO_LOWER_OP:
> + case EFI_IFR_TO_UPPER_OP:
> + Status = InitializeUnicodeCollationProtocol ();
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + Status = PopExpression (Value);
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + if (Value->Type != EFI_IFR_TYPE_STRING) {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + break;
> + }
> +
> + StrPtr = GetTokenString (Value->Value.string, FormSet->HiiHandle);
> + if (StrPtr == NULL) {
> + Status = EFI_NOT_FOUND;
> + goto Done;
> + }
> +
> + if (OpCode->Operand == EFI_IFR_TO_LOWER_OP) {
> + mUnicodeCollation->StrLwr (mUnicodeCollation, StrPtr);
> + } else {
> + mUnicodeCollation->StrUpr (mUnicodeCollation, StrPtr);
> + }
> +
> + Value->Value.string = NewHiiString (StrPtr, FormSet->HiiHandle);
> + FreePool (StrPtr);
> + break;
> +
> + case EFI_IFR_BITWISE_NOT_OP:
> + //
> + // Pop an expression from the expression stack
> + //
> + Status = PopExpression (Value);
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + if (Value->Type > EFI_IFR_TYPE_DATE) {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + break;
> + }
> +
> + Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
> + Value->Value.u64 = ~HiiValueToUINT64(Value);
> + break;
> +
> + case EFI_IFR_SET_OP:
> + //
> + // Pop an expression from the expression stack
> + //
> + Status = PopExpression (Value);
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + Data1.Type = EFI_IFR_TYPE_BOOLEAN;
> + Data1.Value.b = FALSE;
> + //
> + // Set value to var storage buffer
> + //
> + if (OpCode->ExtraData.GetSetData.VarStorage != NULL) {
> + switch (OpCode->ExtraData.GetSetData.VarStorage->Type) {
> + case EFI_HII_VARSTORE_BUFFER:
> + case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
> + CopyMem (OpCode->ExtraData.GetSetData.VarStorage->EditBuffer
> + OpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset, &Value->Value,
> OpCode->ExtraData.GetSetData.ValueWidth);
> + Data1.Value.b = TRUE;
> + break;
> + case EFI_HII_VARSTORE_NAME_VALUE:
> + if (OpCode->ExtraData.GetSetData.ValueType !=
> EFI_IFR_TYPE_STRING) {
> + NameValue = AllocatePool ((OpCode-
> >ExtraData.GetSetData.ValueWidth * 2 + 1) * sizeof (CHAR16));
> + ASSERT (NameValue != NULL);
> + //
> + // Convert Buffer to Hex String
> + //
> + TempBuffer = (UINT8 *)&Value->Value + OpCode-
> >ExtraData.GetSetData.ValueWidth - 1;
> + StrPtr = NameValue;
> + for (Index = 0; Index < OpCode->ExtraData.GetSetData.ValueWidth;
> Index++, TempBuffer--) {
> + UnicodeValueToStringS (
> + StrPtr,
> + (OpCode->ExtraData.GetSetData.ValueWidth * 2 + 1) * sizeof
> (CHAR16) - ((UINTN)StrPtr - (UINTN)NameValue),
> + PREFIX_ZERO | RADIX_HEX,
> + *TempBuffer,
> + 2
> + );
> + StrPtr += StrnLenS (StrPtr, OpCode-
> >ExtraData.GetSetData.ValueWidth * 2 + 1 - ((UINTN)StrPtr -
> (UINTN)NameValue) / sizeof (CHAR16));
> + }
> +
> + Status = SetValueByName (OpCode-
> >ExtraData.GetSetData.VarStorage, OpCode-
> >ExtraData.GetSetData.ValueName, NameValue, NULL);
> + FreePool (NameValue);
> + if (!EFI_ERROR (Status)) {
> + Data1.Value.b = TRUE;
> + }
> + }
> +
> + break;
> + case EFI_HII_VARSTORE_EFI_VARIABLE:
> + Status = gRT->SetVariable (
> + OpCode->ExtraData.GetSetData.ValueName,
> + &OpCode->ExtraData.GetSetData.VarStorage->Guid,
> + OpCode->ExtraData.GetSetData.VarStorage->Attributes,
> + OpCode->ExtraData.GetSetData.ValueWidth,
> + &Value->Value
> + );
> + if (!EFI_ERROR (Status)) {
> + Data1.Value.b = TRUE;
> + }
> +
> + break;
> + default:
> + //
> + // Not recognize storage.
> + //
> + Status = EFI_UNSUPPORTED;
> + goto Done;
> + }
> + } else {
> + //
> + // For Time/Date Data
> + //
> + if ((OpCode->ExtraData.GetSetData.ValueType != EFI_IFR_TYPE_DATE)
> && (OpCode->ExtraData.GetSetData.ValueType != EFI_IFR_TYPE_TIME)) {
> + //
> + // Only support Data/Time data when storage doesn't exist.
> + //
> + Status = EFI_UNSUPPORTED;
> + goto Done;
> + }
> +
> + Status = gRT->GetTime (&EfiTime, NULL);
> + if (!EFI_ERROR (Status)) {
> + if (OpCode->ExtraData.GetSetData.ValueType == EFI_IFR_TYPE_DATE)
> {
> + switch (OpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset) {
> + case 0x00:
> + EfiTime.Year = Value->Value.u16;
> + break;
> + case 0x02:
> + EfiTime.Month = Value->Value.u8;
> + break;
> + case 0x03:
> + EfiTime.Day = Value->Value.u8;
> + break;
> + default:
> + //
> + // Invalid Date field.
> + //
> + Status = EFI_INVALID_PARAMETER;
> + goto Done;
> + }
> + } else {
> + switch (OpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset) {
> + case 0x00:
> + EfiTime.Hour = Value->Value.u8;
> + break;
> + case 0x01:
> + EfiTime.Minute = Value->Value.u8;
> + break;
> + case 0x02:
> + EfiTime.Second = Value->Value.u8;
> + break;
> + default:
> + //
> + // Invalid Time field.
> + //
> + Status = EFI_INVALID_PARAMETER;
> + goto Done;
> + }
> + }
> +
> + Status = gRT->SetTime (&EfiTime);
> + if (!EFI_ERROR (Status)) {
> + Data1.Value.b = TRUE;
> + }
> + }
> + }
> +
> + Value = &Data1;
> + break;
> +
> + //
> + // binary-op
> + //
> + case EFI_IFR_ADD_OP:
> + case EFI_IFR_SUBTRACT_OP:
> + case EFI_IFR_MULTIPLY_OP:
> + case EFI_IFR_DIVIDE_OP:
> + case EFI_IFR_MODULO_OP:
> + case EFI_IFR_BITWISE_AND_OP:
> + case EFI_IFR_BITWISE_OR_OP:
> + case EFI_IFR_SHIFT_LEFT_OP:
> + case EFI_IFR_SHIFT_RIGHT_OP:
> + //
> + // Pop an expression from the expression stack
> + //
> + Status = PopExpression (&Data2);
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + //
> + // Pop another expression from the expression stack
> + //
> + Status = PopExpression (&Data1);
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + if (Data2.Type > EFI_IFR_TYPE_DATE) {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + break;
> + }
> +
> + if (Data1.Type > EFI_IFR_TYPE_DATE) {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + break;
> + }
> +
> + Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
> +
> + switch (OpCode->Operand) {
> + case EFI_IFR_ADD_OP:
> + Value->Value.u64 = HiiValueToUINT64 (&Data1) + HiiValueToUINT64
> (&Data2);
> + break;
> +
> + case EFI_IFR_SUBTRACT_OP:
> + Value->Value.u64 = HiiValueToUINT64 (&Data1) - HiiValueToUINT64
> (&Data2);
> + break;
> +
> + case EFI_IFR_MULTIPLY_OP:
> + Value->Value.u64 = MultU64x32 (HiiValueToUINT64 (&Data1),
> (UINT32)HiiValueToUINT64 (&Data2));
> + break;
> +
> + case EFI_IFR_DIVIDE_OP:
> + Value->Value.u64 = DivU64x32 (HiiValueToUINT64 (&Data1),
> (UINT32)HiiValueToUINT64 (&Data2));
> + break;
> +
> + case EFI_IFR_MODULO_OP:
> + DivU64x32Remainder (HiiValueToUINT64 (&Data1),
> (UINT32)HiiValueToUINT64 (&Data2), &TempValue);
> + Value->Value.u64 = TempValue;
> + break;
> +
> + case EFI_IFR_BITWISE_AND_OP:
> + Value->Value.u64 = HiiValueToUINT64 (&Data1) & HiiValueToUINT64
> (&Data2);
> + break;
> +
> + case EFI_IFR_BITWISE_OR_OP:
> + Value->Value.u64 = HiiValueToUINT64 (&Data1) | HiiValueToUINT64
> (&Data2);
> + break;
> +
> + case EFI_IFR_SHIFT_LEFT_OP:
> + Value->Value.u64 = LShiftU64 (HiiValueToUINT64 (&Data1),
> (UINTN)HiiValueToUINT64 (&Data2));
> + break;
> +
> + case EFI_IFR_SHIFT_RIGHT_OP:
> + Value->Value.u64 = RShiftU64 (HiiValueToUINT64 (&Data1),
> (UINTN)HiiValueToUINT64 (&Data2));
> + break;
> +
> + default:
> + break;
> + }
> +
> + break;
> +
> + case EFI_IFR_AND_OP:
> + case EFI_IFR_OR_OP:
> + //
> + // Two Boolean operator
> + //
> + Status = PopExpression (&Data2);
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + //
> + // Pop another expression from the expression stack
> + //
> + Status = PopExpression (&Data1);
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + break;
> + }
> +
> + if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + break;
> + }
> +
> + if (OpCode->Operand == EFI_IFR_AND_OP) {
> + Value->Value.b = (BOOLEAN)(Data1.Value.b && Data2.Value.b);
> + } else {
> + Value->Value.b = (BOOLEAN)(Data1.Value.b || Data2.Value.b);
> + }
> +
> + break;
> +
> + case EFI_IFR_EQUAL_OP:
> + case EFI_IFR_NOT_EQUAL_OP:
> + case EFI_IFR_GREATER_EQUAL_OP:
> + case EFI_IFR_GREATER_THAN_OP:
> + case EFI_IFR_LESS_EQUAL_OP:
> + case EFI_IFR_LESS_THAN_OP:
> + //
> + // Compare two integer, string, boolean or date/time
> + //
> + Status = PopExpression (&Data2);
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + //
> + // Pop another expression from the expression stack
> + //
> + Status = PopExpression (&Data1);
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + if ((Data2.Type > EFI_IFR_TYPE_BOOLEAN) &&
> + (Data2.Type != EFI_IFR_TYPE_STRING) &&
> + !IsTypeInBuffer (&Data2))
> + {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + break;
> + }
> +
> + if ((Data1.Type > EFI_IFR_TYPE_BOOLEAN) &&
> + (Data1.Type != EFI_IFR_TYPE_STRING) &&
> + !IsTypeInBuffer (&Data1))
> + {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + break;
> + }
> +
> + Status = CompareHiiValue (&Data1, &Data2, &Result, FormSet-
> >HiiHandle);
> + if (Data1.Type == EFI_IFR_TYPE_BUFFER) {
> + FreePool (Data1.Buffer);
> + }
> +
> + if (Data2.Type == EFI_IFR_TYPE_BUFFER) {
> + FreePool (Data2.Buffer);
> + }
> +
> + if (Status == EFI_UNSUPPORTED) {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + Status = EFI_SUCCESS;
> + break;
> + }
> +
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + switch (OpCode->Operand) {
> + case EFI_IFR_EQUAL_OP:
> + Value->Value.b = (BOOLEAN)((Result == 0) ? TRUE : FALSE);
> + break;
> +
> + case EFI_IFR_NOT_EQUAL_OP:
> + Value->Value.b = (BOOLEAN)((Result != 0) ? TRUE : FALSE);
> + break;
> +
> + case EFI_IFR_GREATER_EQUAL_OP:
> + Value->Value.b = (BOOLEAN)((Result >= 0) ? TRUE : FALSE);
> + break;
> +
> + case EFI_IFR_GREATER_THAN_OP:
> + Value->Value.b = (BOOLEAN)((Result > 0) ? TRUE : FALSE);
> + break;
> +
> + case EFI_IFR_LESS_EQUAL_OP:
> + Value->Value.b = (BOOLEAN)((Result <= 0) ? TRUE : FALSE);
> + break;
> +
> + case EFI_IFR_LESS_THAN_OP:
> + Value->Value.b = (BOOLEAN)((Result < 0) ? TRUE : FALSE);
> + break;
> +
> + default:
> + break;
> + }
> +
> + break;
> +
> + case EFI_IFR_MATCH_OP:
> + Status = InitializeUnicodeCollationProtocol ();
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + Status = IfrMatch (FormSet, Value);
> + break;
> +
> + case EFI_IFR_MATCH2_OP:
> + Status = IfrMatch2 (FormSet, &OpCode->ExtraData.Guid, Value);
> + break;
> +
> + case EFI_IFR_CATENATE_OP:
> + Status = IfrCatenate (FormSet, Value);
> + break;
> +
> + //
> + // ternary-op
> + //
> + case EFI_IFR_CONDITIONAL_OP:
> + //
> + // Pop third expression from the expression stack
> + //
> + Status = PopExpression (&Data3);
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + //
> + // Pop second expression from the expression stack
> + //
> + Status = PopExpression (&Data2);
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + //
> + // Pop first expression from the expression stack
> + //
> + Status = PopExpression (&Data1);
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + break;
> + }
> +
> + if (Data1.Value.b) {
> + Value = &Data3;
> + } else {
> + Value = &Data2;
> + }
> +
> + break;
> +
> + case EFI_IFR_FIND_OP:
> + Status = IfrFind (FormSet, OpCode->ExtraData.Format, Value);
> + break;
> +
> + case EFI_IFR_MID_OP:
> + Status = IfrMid (FormSet, Value);
> + break;
> +
> + case EFI_IFR_TOKEN_OP:
> + Status = IfrToken (FormSet, Value);
> + break;
> +
> + case EFI_IFR_SPAN_OP:
> + Status = IfrSpan (FormSet, OpCode->ExtraData.Flags, Value);
> + break;
> +
> + case EFI_IFR_MAP_OP:
> + //
> + // Pop the check value
> + //
> + Status = PopExpression (&Data1);
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + //
> + // Check MapExpression list is valid.
> + //
> + if (OpCode->MapExpressionList.ForwardLink == NULL) {
> + Status = EFI_INVALID_PARAMETER;
> + goto Done;
> + }
> +
> + //
> + // Go through map expression list.
> + //
> + SubExpressionLink = GetFirstNode (&OpCode->MapExpressionList);
> + while (!IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
> + SubExpression = HII_EXPRESSION_FROM_LINK (SubExpressionLink);
> + //
> + // Evaluate the first expression in this pair.
> + //
> + Status = EvaluateHiiExpression (FormSet, Form, SubExpression);
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + //
> + // Compare the expression value with current value
> + //
> + if ((CompareHiiValue (&Data1, &SubExpression->Result, &Result, NULL)
> == EFI_SUCCESS) && (Result == 0)) {
> + //
> + // Try get the map value.
> + //
> + SubExpressionLink = GetNextNode (&OpCode->MapExpressionList,
> SubExpressionLink);
> + if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
> + Status = EFI_INVALID_PARAMETER;
> + goto Done;
> + }
> +
> + SubExpression = HII_EXPRESSION_FROM_LINK (SubExpressionLink);
> + Status = EvaluateHiiExpression (FormSet, Form, SubExpression);
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + Value = &SubExpression->Result;
> + break;
> + }
> +
> + //
> + // Skip the second expression on this pair.
> + //
> + SubExpressionLink = GetNextNode (&OpCode->MapExpressionList,
> SubExpressionLink);
> + if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
> + Status = EFI_INVALID_PARAMETER;
> + goto Done;
> + }
> +
> + //
> + // Goto the first expression on next pair.
> + //
> + SubExpressionLink = GetNextNode (&OpCode->MapExpressionList,
> SubExpressionLink);
> + }
> +
> + //
> + // No map value is found.
> + //
> + if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
> + Value->Type = EFI_IFR_TYPE_UNDEFINED;
> + Value->Value.u8 = 0;
> + }
> +
> + break;
> +
> + default:
> + break;
> + }
> +
> + if (EFI_ERROR (Status) || (Value->Type == EFI_IFR_TYPE_UNDEFINED)) {
> + goto Done;
> + }
> +
> + Status = PushExpression (Value);
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> + }
> +
> + //
> + // Pop the final result from expression stack
> + //
> + Value = &Data1;
> + Status = PopExpression (Value);
> + if (EFI_ERROR (Status)) {
> + goto Done;
> + }
> +
> + //
> + // After evaluating an expression, there should be only one value left on
> the expression stack
> + //
> + if (PopExpression (Value) != EFI_ACCESS_DENIED) {
> + Status = EFI_INVALID_PARAMETER;
> + }
> +
> +Done:
> + RestoreExpressionEvaluationStackOffset (StackOffset);
> + if (!EFI_ERROR (Status)) {
> + CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));
> + }
> +
> + return Status;
> +}
> +
> +/**
> + Set value of a data element in an Array by its Index.
> +
> + @param[in] Array The data array.
> + @param[in] Type Type of the data in this array.
> + @param[in] Index Zero based index for data in this array.
> + @param[in] Value The value to be set.
> +
> +**/
> +VOID
> +SetArrayData (
> + IN VOID *Array,
> + IN UINT8 Type,
> + IN UINTN Index,
> + IN UINT64 Value
> + )
> +{
> + ASSERT (Array != NULL);
> +
> + switch (Type) {
> + case EFI_IFR_TYPE_NUM_SIZE_8:
> + *(((UINT8 *)Array) + Index) = (UINT8)Value;
> + break;
> +
> + case EFI_IFR_TYPE_NUM_SIZE_16:
> + *(((UINT16 *)Array) + Index) = (UINT16)Value;
> + break;
> +
> + case EFI_IFR_TYPE_NUM_SIZE_32:
> + *(((UINT32 *)Array) + Index) = (UINT32)Value;
> + break;
> +
> + case EFI_IFR_TYPE_NUM_SIZE_64:
> + *(((UINT64 *)Array) + Index) = (UINT64)Value;
> + break;
> +
> + default:
> + break;
> + }
> +}
> +
> +/**
> + Search an Option of a Question by its value.
> +
> + @param[in] Question The Question
> + @param[in] OptionValue Value for Option to be searched.
> +
> + @retval Pointer Pointer to the found Option.
> + @retval NULL Option not found.
> +
> +**/
> +HII_QUESTION_OPTION *
> +ValueToOption (
> + IN HII_STATEMENT *Question,
> + IN HII_STATEMENT_VALUE *OptionValue
> + )
> +{
> + LIST_ENTRY *Link;
> + HII_QUESTION_OPTION *Option;
> + EFI_HII_VALUE Data1;
> + EFI_HII_VALUE Data2;
> + INTN Result;
> + EFI_STATUS Status;
> +
> + Result = 0;
> + ZeroMem (&Data1, sizeof (EFI_HII_VALUE));
> + ZeroMem (&Data2, sizeof (EFI_HII_VALUE));
> +
> + Status = HiiStatementValueToHiiValue (OptionValue, &Data1);
> + ASSERT_EFI_ERROR (Status);
> +
> + Link = GetFirstNode (&Question->OptionListHead);
> + while (!IsNull (&Question->OptionListHead, Link)) {
> + Option = HII_QUESTION_OPTION_FROM_LINK (Link);
> +
> + Status = HiiStatementValueToHiiValue (&Option->Value, &Data2);
> + ASSERT_EFI_ERROR (Status);
> +
> + if ((CompareHiiValue (&Data1, &Data2, &Result, NULL) == EFI_SUCCESS)
> && (Result == 0)) {
> + //
> + // Check the suppressif condition, only a valid option can be return.
> + //
> + if ((Option->SuppressExpression == NULL) ||
> + ((EvaluateExpressionList (Option->SuppressExpression, FALSE, NULL,
> NULL) == ExpressFalse)))
> + {
> + return Option;
> + }
> + }
> +
> + Link = GetNextNode (&Question->OptionListHead, Link);
> + }
> +
> + return NULL;
> +}
> +
> +/**
> + Find the point in the ConfigResp string for this question.
> +
> + @param[in] Question The question.
> + @param[in] ConfigResp Get ConfigResp string.
> +
> + @retval point to the offset where is for this question.
> +
> +**/
> +CHAR16 *
> +GetOffsetFromConfigResp (
> + IN HII_STATEMENT *Question,
> + IN CHAR16 *ConfigResp
> + )
> +{
> + CHAR16 *RequestElement;
> + CHAR16 *BlockData;
> +
> + //
> + // Type is EFI_HII_VARSTORE_NAME_VALUE.
> + //
> + if (Question->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
> + RequestElement = StrStr (ConfigResp, Question->VariableName);
> + if (RequestElement != NULL) {
> + //
> + // Skip the "VariableName=" field.
> + //
> + RequestElement += StrLen (Question->VariableName) + 1;
> + }
> +
> + return RequestElement;
> + }
> +
> + //
> + // Type is EFI_HII_VARSTORE_EFI_VARIABLE or
> EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
> + //
> +
> + //
> + // Convert all hex digits in ConfigResp to lower case before searching.
> + //
> + HiiStringToLowercase (ConfigResp);
> +
> + //
> + // 1. Directly use Question->BlockName to find.
> + //
> + RequestElement = StrStr (ConfigResp, Question->BlockName);
> + if (RequestElement != NULL) {
> + //
> + // Skip the "Question->BlockName&VALUE=" field.
> + //
> + RequestElement += StrLen (Question->BlockName) + StrLen
> (L"&VALUE=");
> + return RequestElement;
> + }
> +
> + //
> + // 2. Change all hex digits in Question->BlockName to lower and compare
> again.
> + //
> + BlockData = AllocateCopyPool (StrSize (Question->BlockName), Question-
> >BlockName);
> + ASSERT (BlockData != NULL);
> + HiiStringToLowercase (BlockData);
> + RequestElement = StrStr (ConfigResp, BlockData);
> + FreePool (BlockData);
> +
> + if (RequestElement != NULL) {
> + //
> + // Skip the "Question->BlockName&VALUE=" field.
> + //
> + RequestElement += StrLen (Question->BlockName) + StrLen
> (L"&VALUE=");
> + }
> +
> + return RequestElement;
> +}
> +
> +/**
> + Get Question default value from AltCfg string.
> +
> + @param[in] FormSet The form set.
> + @param[in] Form The form
> + @param[in] Question The question.
> + @param[out] DefaultValue Default value.
> +
> + @retval EFI_SUCCESS Question is reset to default value.
> +
> +**/
> +EFI_STATUS
> +GetDefaultValueFromAltCfg (
> + IN HII_FORMSET *FormSet,
> + IN HII_FORM *Form,
> + IN HII_STATEMENT *Question,
> + OUT HII_STATEMENT_VALUE *DefaultValue
> + )
> +{
> + HII_FORMSET_STORAGE *Storage;
> + CHAR16 *ConfigResp;
> + CHAR16 *Value;
> + LIST_ENTRY *Link;
> + HII_FORM_CONFIG_REQUEST *ConfigInfo;
> +
> + Storage = Question->Storage;
> + if ((Storage == NULL) || (Storage->Type ==
> EFI_HII_VARSTORE_EFI_VARIABLE)) {
> + return EFI_NOT_FOUND;
> + }
> +
> + //
> + // Try to get AltCfg string from form. If not found it, then
> + // try to get it from formset.
> + //
> + ConfigResp = NULL;
> + Link = GetFirstNode (&Form->ConfigRequestHead);
> + while (!IsNull (&Form->ConfigRequestHead, Link)) {
> + ConfigInfo = HII_FORM_CONFIG_REQUEST_FROM_LINK (Link);
> + Link = GetNextNode (&Form->ConfigRequestHead, Link);
> +
> + if (Storage == ConfigInfo->Storage) {
> + ConfigResp = ConfigInfo->ConfigAltResp;
> + break;
> + }
> + }
> +
> + if (ConfigResp == NULL) {
> + return EFI_NOT_FOUND;
> + }
> +
> + Value = GetOffsetFromConfigResp (Question, ConfigResp);
> + if (Value == NULL) {
> + return EFI_NOT_FOUND;
> + }
> +
> + return BufferToQuestionValue (Question, Value, DefaultValue);
> +}
> +
> +/**
> + Get default Id value used for browser.
> +
> + @param[in] DefaultId The default id value used by hii.
> +
> + @retval Browser used default value.
> +
> +**/
> +INTN
> +GetDefaultIdForCallBack (
> + IN UINTN DefaultId
> + )
> +{
> + if (DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) {
> + return EFI_BROWSER_ACTION_DEFAULT_STANDARD;
> + } else if (DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
> + return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING;
> + } else if (DefaultId == EFI_HII_DEFAULT_CLASS_SAFE) {
> + return EFI_BROWSER_ACTION_DEFAULT_SAFE;
> + } else if ((DefaultId >= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN) &&
> (DefaultId < EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN + 0x1000)) {
> + return EFI_BROWSER_ACTION_DEFAULT_PLATFORM + DefaultId -
> EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN;
> + } else if ((DefaultId >= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN) &&
> (DefaultId < EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN + 0x1000)) {
> + return EFI_BROWSER_ACTION_DEFAULT_HARDWARE + DefaultId -
> EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN;
> + } else if ((DefaultId >= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN) &&
> (DefaultId < EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN + 0x1000)) {
> + return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE + DefaultId -
> EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN;
> + } else {
> + return -1;
> + }
> +}
> +
> +/**
> + Get default value of question.
> +
> + @param[in] FormSet The form set.
> + @param[in] Form The form.
> + @param[in] Question The question.
> + @param[in] DefaultId The Class of the default.
> + @param[out] DefaultValue The default value of given question.
> +
> + @retval EFI_SUCCESS Question is reset to default value.
> +
> +**/
> +EFI_STATUS
> +GetQuestionDefault (
> + IN HII_FORMSET *FormSet,
> + IN HII_FORM *Form,
> + IN HII_STATEMENT *Question,
> + IN UINT16 DefaultId,
> + OUT HII_STATEMENT_VALUE *DefaultValue
> + )
> +{
> + EFI_STATUS Status;
> + LIST_ENTRY *Link;
> + HII_QUESTION_DEFAULT *Default;
> + HII_QUESTION_OPTION *Option;
> + HII_STATEMENT_VALUE *HiiValue;
> + UINT8 Index;
> + EFI_STRING StrValue;
> + EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
> + EFI_BROWSER_ACTION_REQUEST ActionRequest;
> + INTN Action;
> + EFI_IFR_TYPE_VALUE *TypeValue;
> + UINT16 OriginalDefaultId;
> + HII_FORMSET_DEFAULTSTORE *DefaultStore;
> + LIST_ENTRY *DefaultLink;
> +
> + if ((FormSet == NULL) || (Form == NULL) || (Question == NULL) ||
> (DefaultValue == NULL)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + Status = EFI_NOT_FOUND;
> + StrValue = NULL;
> + OriginalDefaultId = DefaultId;
> + DefaultLink = GetFirstNode (&FormSet->DefaultStoreListHead);
> +
> + //
> + // Statement don't have storage, skip them
> + //
> + if (Question->QuestionId == 0) {
> + DEBUG ((DEBUG_ERROR, "%a: Question has no storage, skip it\n",
> __func__));
> + return Status;
> + }
> +
> + //
> + // There are Five ways to specify default value for a Question:
> + // 1, use call back function (highest priority)
> + // 2, use ExtractConfig function
> + // 3, use nested EFI_IFR_DEFAULT
> + // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and
> Manufacturing default)
> + // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing
> default) (lowest priority)
> + //
> + CopyMem (DefaultValue, &Question->Value, sizeof
> (HII_STATEMENT_VALUE));
> +ReGetDefault:
> + HiiValue = DefaultValue;
> + TypeValue = &HiiValue->Value;
> + if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {
> + //
> + // For orderedlist, need to pass the BufferValue to Callback function.
> + //
> + DefaultValue->BufferLen = Question->Value.BufferLen;
> + DefaultValue->Buffer = AllocateZeroPool (DefaultValue->BufferLen);
> + ASSERT (DefaultValue->Buffer != NULL);
> + if (DefaultValue->Buffer == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + TypeValue = (EFI_IFR_TYPE_VALUE *)DefaultValue->Buffer;
> + }
> +
> + //
> + // Get Question default value from call back function.
> + // The string type of question cause HII driver to set string to its default
> value.
> + // So, we don't do this otherwise it will actually set question to default
> value.
> + // We only want to get default value of question.
> + //
> + if (HiiValue->Type != EFI_IFR_TYPE_STRING) {
> + ConfigAccess = FormSet->ConfigAccess;
> + Action = GetDefaultIdForCallBack (DefaultId);
> + if ((Action > 0) && ((Question->QuestionFlags &
> EFI_IFR_FLAG_CALLBACK) != 0) && (ConfigAccess != NULL)) {
> + ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
> + Status = ConfigAccess->Callback (
> + ConfigAccess,
> + Action,
> + Question->QuestionId,
> + HiiValue->Type,
> + TypeValue,
> + &ActionRequest
> + );
> + if (!EFI_ERROR (Status)) {
> + return Status;
> + }
> + }
> + }
> +
> + //
> + // Get default value from altcfg string.
> + //
> + if (ConfigAccess != NULL) {
> + Status = GetDefaultValueFromAltCfg (FormSet, Form, Question,
> DefaultValue);
> + if (!EFI_ERROR (Status)) {
> + return Status;
> + }
> + }
> +
> + //
> + // EFI_IFR_DEFAULT has highest priority
> + //
> + if (!IsListEmpty (&Question->DefaultListHead)) {
> + Link = GetFirstNode (&Question->DefaultListHead);
> + while (!IsNull (&Question->DefaultListHead, Link)) {
> + Default = HII_QUESTION_DEFAULT_FROM_LINK (Link);
> +
> + if (Default->DefaultId == DefaultId) {
> + if (Default->ValueExpression != NULL) {
> + //
> + // Default is provided by an Expression, evaluate it
> + //
> + Status = EvaluateHiiExpression (FormSet, Form, Default-
> >ValueExpression);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + if (Default->ValueExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {
> + ASSERT (HiiValue->Type == EFI_IFR_TYPE_BUFFER && DefaultValue-
> >Buffer != NULL);
> + if (DefaultValue->BufferLen > Default->ValueExpression-
> >Result.BufferLen) {
> + CopyMem (DefaultValue->Buffer, Default->ValueExpression-
> >Result.Buffer, Default->ValueExpression->Result.BufferLen);
> + DefaultValue->BufferLen = Default->ValueExpression-
> >Result.BufferLen;
> + } else {
> + CopyMem (DefaultValue->Buffer, Default->ValueExpression-
> >Result.Buffer, DefaultValue->BufferLen);
> + }
> +
> + FreePool (Default->ValueExpression->Result.Buffer);
> + }
> +
> + HiiValue->Type = Default->ValueExpression->Result.Type;
> + CopyMem (&HiiValue->Value, &Default->ValueExpression-
> >Result.Value, sizeof (EFI_IFR_TYPE_VALUE));
> + } else {
> + //
> + // Default value is embedded in EFI_IFR_DEFAULT
> + //
> + if (Default->Value.Type == EFI_IFR_TYPE_BUFFER) {
> + ASSERT (HiiValue->Buffer != NULL);
> + CopyMem (HiiValue->Buffer, Default->Value.Buffer, Default-
> >Value.BufferLen);
> + } else {
> + CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));
> + }
> + }
> +
> + if (HiiValue->Type == EFI_IFR_TYPE_STRING) {
> + StrValue = HiiGetString (FormSet->HiiHandle, HiiValue->Value.string,
> NULL);
> + if (StrValue == NULL) {
> + return EFI_NOT_FOUND;
> + }
> +
> + if (DefaultValue->BufferLen > StrSize (StrValue)) {
> + ZeroMem (DefaultValue->Buffer, DefaultValue->BufferLen);
> + CopyMem (DefaultValue->Buffer, StrValue, StrSize (StrValue));
> + } else {
> + CopyMem (DefaultValue->Buffer, StrValue, DefaultValue-
> >BufferLen);
> + }
> + }
> +
> + return EFI_SUCCESS;
> + }
> +
> + Link = GetNextNode (&Question->DefaultListHead, Link);
> + }
> + }
> +
> + //
> + // EFI_ONE_OF_OPTION
> + //
> + if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty
> (&Question->OptionListHead)) {
> + if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
> + //
> + // OneOfOption could only provide Standard and Manufacturing default
> + //
> + Link = GetFirstNode (&Question->OptionListHead);
> + while (!IsNull (&Question->OptionListHead, Link)) {
> + Option = HII_QUESTION_OPTION_FROM_LINK (Link);
> + Link = GetNextNode (&Question->OptionListHead, Link);
> +
> + if ((Option->SuppressExpression != NULL) &&
> + (EvaluateExpressionList (Option->SuppressExpression, FALSE, NULL,
> NULL) != ExpressFalse))
> + {
> + continue;
> + }
> +
> + if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option-
> >Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||
> + ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) &&
> ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))
> + )
> + {
> + CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));
> +
> + return EFI_SUCCESS;
> + }
> + }
> + }
> + }
> +
> + //
> + // EFI_IFR_CHECKBOX - lowest priority
> + //
> + if (Question->Operand == EFI_IFR_CHECKBOX_OP) {
> + if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
> + //
> + // Checkbox could only provide Standard and Manufacturing default
> + //
> + if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Question-
> >ExtraData.Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0)) ||
> + ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) &&
> ((Question->ExtraData.Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0))
> + )
> + {
> + HiiValue->Value.b = TRUE;
> + }
> +
> + return EFI_SUCCESS;
> + }
> + }
> +
> + //
> + // For question without default value for current default Id, we try to re-
> get the default value form other default id in the DefaultStoreList.
> + // If get, will exit the function, if not, will choose next default id in the
> DefaultStoreList.
> + // The default id in DefaultStoreList are in ascending order to make sure
> choose the smallest default id every time.
> + //
> + while (!IsNull (&FormSet->DefaultStoreListHead, DefaultLink)) {
> + DefaultStore = HII_FORMSET_DEFAULTSTORE_FROM_LINK (DefaultLink);
> + DefaultLink = GetNextNode (&FormSet->DefaultStoreListHead,
> DefaultLink);
> + DefaultId = DefaultStore->DefaultId;
> + if (DefaultId == OriginalDefaultId) {
> + continue;
> + }
> +
> + goto ReGetDefault;
> + }
> +
> + //
> + // For Questions without default value for all the default id in the
> DefaultStoreList.
> + //
> + Status = EFI_NOT_FOUND;
> + switch (Question->Operand) {
> + case EFI_IFR_CHECKBOX_OP:
> + HiiValue->Value.b = FALSE;
> + Status = EFI_SUCCESS;
> + break;
> +
> + case EFI_IFR_NUMERIC_OP:
> + //
> + // Take minimum value as numeric default value
> + //
> + if ((Question->ExtraData.NumData.Flags & EFI_IFR_DISPLAY) == 0) {
> + //
> + // In EFI_IFR_DISPLAY_INT_DEC type, should check value with int* type.
> + //
> + switch (Question->ExtraData.NumData.Flags & EFI_IFR_NUMERIC_SIZE)
> {
> + case EFI_IFR_NUMERIC_SIZE_1:
> + if (((INT8)HiiValue->Value.u8 < (INT8)Question-
> >ExtraData.NumData.Minimum) || ((INT8)HiiValue->Value.u8 >
> (INT8)Question->ExtraData.NumData.Maximum)) {
> + HiiValue->Value.u8 = (UINT8)Question-
> >ExtraData.NumData.Minimum;
> + Status = EFI_SUCCESS;
> + }
> +
> + break;
> + case EFI_IFR_NUMERIC_SIZE_2:
> + if (((INT16)HiiValue->Value.u16 < (INT16)Question-
> >ExtraData.NumData.Minimum) || ((INT16)HiiValue->Value.u16 >
> (INT16)Question->ExtraData.NumData.Maximum)) {
> + HiiValue->Value.u16 = (UINT16)Question-
> >ExtraData.NumData.Minimum;
> + Status = EFI_SUCCESS;
> + }
> +
> + break;
> + case EFI_IFR_NUMERIC_SIZE_4:
> + if (((INT32)HiiValue->Value.u32 < (INT32)Question-
> >ExtraData.NumData.Minimum) || ((INT32)HiiValue->Value.u32 >
> (INT32)Question->ExtraData.NumData.Maximum)) {
> + HiiValue->Value.u32 = (UINT32)Question-
> >ExtraData.NumData.Minimum;
> + Status = EFI_SUCCESS;
> + }
> +
> + break;
> + case EFI_IFR_NUMERIC_SIZE_8:
> + if (((INT64)HiiValue->Value.u64 < (INT64)Question-
> >ExtraData.NumData.Minimum) || ((INT64)HiiValue->Value.u64 >
> (INT64)Question->ExtraData.NumData.Maximum)) {
> + HiiValue->Value.u64 = Question->ExtraData.NumData.Minimum;
> + Status = EFI_SUCCESS;
> + }
> +
> + break;
> + default:
> + break;
> + }
> + } else {
> + if ((HiiValue->Value.u64 < Question->ExtraData.NumData.Minimum) ||
> (HiiValue->Value.u64 > Question->ExtraData.NumData.Maximum)) {
> + HiiValue->Value.u64 = Question->ExtraData.NumData.Minimum;
> + Status = EFI_SUCCESS;
> + }
> + }
> +
> + break;
> +
> + case EFI_IFR_ONE_OF_OP:
> + //
> + // Take first oneof option as oneof's default value
> + //
> + Link = GetFirstNode (&Question->OptionListHead);
> + while (!IsNull (&Question->OptionListHead, Link)) {
> + Option = HII_QUESTION_OPTION_FROM_LINK (Link);
> + Link = GetNextNode (&Question->OptionListHead, Link);
> +
> + if ((Option->SuppressExpression != NULL) &&
> + (EvaluateExpressionList (Option->SuppressExpression, FALSE, NULL,
> NULL) != ExpressFalse))
> + {
> + continue;
> + }
> +
> + CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));
> + Status = EFI_SUCCESS;
> + break;
> + }
> +
> + break;
> +
> + case EFI_IFR_ORDERED_LIST_OP:
> + //
> + // Take option sequence in IFR as ordered list's default value
> + //
> + Index = 0;
> + Link = GetFirstNode (&Question->OptionListHead);
> + while (!IsNull (&Question->OptionListHead, Link)) {
> + Status = EFI_SUCCESS;
> + Option = HII_QUESTION_OPTION_FROM_LINK (Link);
> + Link = GetNextNode (&Question->OptionListHead, Link);
> +
> + if ((Option->SuppressExpression != NULL) &&
> + (EvaluateExpressionList (Option->SuppressExpression, FALSE, NULL,
> NULL) != ExpressFalse))
> + {
> + continue;
> + }
> +
> + SetArrayData (DefaultValue->Buffer, Question->Value.Type, Index,
> Option->Value.Value.u64);
> +
> + Index++;
> + if (Index >= Question->ExtraData.OrderListData.MaxContainers) {
> + break;
> + }
> + }
> +
> + break;
> +
> + default:
> + break;
> + }
> +
> + return Status;
> +}
> diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.c
> b/RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.c
> new file mode 100644
> index 000000000000..168b4459844f
> --- /dev/null
> +++ b/RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.c
> @@ -0,0 +1,810 @@
> +/** @file
> + Implementation of HII utility library.
> +
> + Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> + (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
> + Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include "HiiInternal.h"
> +
> +/**
> + Initialize the internal data structure of a FormSet.
> +
> + @param Handle PackageList Handle
> + @param FormSetGuid On input, GUID or class GUID of a formset. If
> not
> + specified (NULL or zero GUID), take the first
> + FormSet with class GUID
> EFI_HII_PLATFORM_SETUP_FORMSET_GUID
> + found in package list.
> + On output, GUID of the formset found(if not NULL).
> + @param FormSet FormSet data structure.
> +
> + @retval EFI_SUCCESS The function completed successfully.
> + @retval EFI_NOT_FOUND The specified FormSet could not be found.
> +
> +**/
> +EFI_STATUS
> +CreateFormSetFromHiiHandle (
> + IN EFI_HII_HANDLE Handle,
> + IN OUT EFI_GUID *FormSetGuid,
> + OUT HII_FORMSET *FormSet
> + )
> +{
> + EFI_STATUS Status;
> + EFI_HANDLE DriverHandle;
> + EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
> +
> + if ((FormSetGuid == NULL) || (FormSet == NULL)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + //
> + // Locate required Hii Database protocol
> + //
> + Status = gBS->LocateProtocol (
> + &gEfiHiiDatabaseProtocolGuid,
> + NULL,
> + (VOID **)&HiiDatabase
> + );
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet-
> >IfrBinaryLength, &FormSet->IfrBinaryData);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + FormSet->Signature = HII_FORMSET_SIGNATURE;
> + FormSet->HiiHandle = Handle;
> + CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));
> + //
> + // Retrieve ConfigAccess Protocol associated with this HiiPackageList
> + //
> + Status = HiiDatabase->GetPackageListHandle (HiiDatabase, Handle,
> &DriverHandle);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + FormSet->DriverHandle = DriverHandle;
> + Status = gBS->HandleProtocol (
> + DriverHandle,
> + &gEfiHiiConfigAccessProtocolGuid,
> + (VOID **)&FormSet->ConfigAccess
> + );
> + if (EFI_ERROR (Status)) {
> + //
> + // Configuration Driver don't attach ConfigAccess protocol to its HII
> package
> + // list, then there will be no configuration action required
> + //
> + FormSet->ConfigAccess = NULL;
> + }
> +
> + Status = gBS->HandleProtocol (
> + DriverHandle,
> + &gEfiDevicePathProtocolGuid,
> + (VOID **)&FormSet->DevicePath
> + );
> + if (EFI_ERROR (Status)) {
> + //
> + // Configuration Driver don't attach ConfigAccess protocol to its HII
> package
> + // list, then there will be no configuration action required
> + //
> + FormSet->DevicePath = NULL;
> + }
> +
> + //
> + // Parse the IFR binary OpCodes
> + //
> + Status = ParseOpCodes (FormSet);
> +
> + return Status;
> +}
> +
> +/**
> + Initialize a Formset and get current setting for Questions.
> +
> + @param FormSet FormSet data structure.
> +
> +**/
> +VOID
> +InitializeFormSet (
> + IN OUT HII_FORMSET *FormSet
> + )
> +{
> + LIST_ENTRY *Link;
> + HII_FORMSET_STORAGE *Storage;
> + LIST_ENTRY *FormLink;
> + HII_STATEMENT *Question;
> + HII_FORM *Form;
> +
> + if (FormSet == NULL) {
> + return;
> + }
> +
> + //
> + // Load Storage for all questions with storage
> + //
> + Link = GetFirstNode (&FormSet->StorageListHead);
> + while (!IsNull (&FormSet->StorageListHead, Link)) {
> + Storage = HII_STORAGE_FROM_LINK (Link);
> + LoadFormSetStorage (FormSet, Storage);
> + Link = GetNextNode (&FormSet->StorageListHead, Link);
> + }
> +
> + //
> + // Get Current Value for all no storage questions
> + //
> + FormLink = GetFirstNode (&FormSet->FormListHead);
> + while (!IsNull (&FormSet->FormListHead, FormLink)) {
> + Form = HII_FORM_FROM_LINK (FormLink);
> + Link = GetFirstNode (&Form->StatementListHead);
> + while (!IsNull (&Form->StatementListHead, Link)) {
> + Question = HII_STATEMENT_FROM_LINK (Link);
> + if (Question->Storage == NULL) {
> + RetrieveQuestion (FormSet, Form, Question);
> + }
> +
> + Link = GetNextNode (&Form->StatementListHead, Link);
> + }
> +
> + FormLink = GetNextNode (&FormSet->FormListHead, FormLink);
> + }
> +}
> +
> +/**
> + Free resources allocated for a FormSet.
> +
> + @param[in,out] FormSet Pointer of the FormSet
> +
> +**/
> +VOID
> +DestroyFormSet (
> + IN OUT HII_FORMSET *FormSet
> + )
> +{
> + LIST_ENTRY *Link;
> + HII_FORMSET_STORAGE *Storage;
> + HII_FORMSET_DEFAULTSTORE *DefaultStore;
> + HII_FORM *Form;
> +
> + if (FormSet->IfrBinaryData == NULL) {
> + //
> + // Uninitialized FormSet
> + //
> + FreePool (FormSet);
> + return;
> + }
> +
> + //
> + // Free IFR binary buffer
> + //
> + FreePool (FormSet->IfrBinaryData);
> +
> + //
> + // Free FormSet Storage
> + //
> + if (FormSet->StorageListHead.ForwardLink != NULL) {
> + while (!IsListEmpty (&FormSet->StorageListHead)) {
> + Link = GetFirstNode (&FormSet->StorageListHead);
> + Storage = HII_STORAGE_FROM_LINK (Link);
> + RemoveEntryList (&Storage->Link);
> +
> + if (Storage != NULL) {
> + FreePool (Storage);
> + }
> + }
> + }
> +
> + //
> + // Free FormSet Default Store
> + //
> + if (FormSet->DefaultStoreListHead.ForwardLink != NULL) {
> + while (!IsListEmpty (&FormSet->DefaultStoreListHead)) {
> + Link = GetFirstNode (&FormSet->DefaultStoreListHead);
> + DefaultStore = HII_FORMSET_DEFAULTSTORE_FROM_LINK (Link);
> + RemoveEntryList (&DefaultStore->Link);
> +
> + FreePool (DefaultStore);
> + }
> + }
> +
> + //
> + // Free Forms
> + //
> + if (FormSet->FormListHead.ForwardLink != NULL) {
> + while (!IsListEmpty (&FormSet->FormListHead)) {
> + Link = GetFirstNode (&FormSet->FormListHead);
> + Form = HII_FORM_FROM_LINK (Link);
> + RemoveEntryList (&Form->Link);
> +
> + DestroyForm (FormSet, Form);
> + }
> + }
> +
> + FreePool (FormSet);
> +}
> +
> +/**
> + Submit data for a form.
> +
> + @param[in] FormSet FormSet which contains the Form.
> + @param[in] Form Form to submit.
> +
> + @retval EFI_SUCCESS The function completed successfully.
> + @retval Others Other errors occur.
> +
> +**/
> +EFI_STATUS
> +SubmitForm (
> + IN HII_FORMSET *FormSet,
> + IN HII_FORM *Form
> + )
> +{
> + EFI_STATUS Status;
> + EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
> + LIST_ENTRY *Link;
> + EFI_STRING ConfigResp;
> + EFI_STRING Progress;
> + HII_FORMSET_STORAGE *Storage;
> + HII_FORM_CONFIG_REQUEST *ConfigInfo;
> +
> + if ((FormSet == NULL) || (Form == NULL)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + Status = NoSubmitCheck (FormSet, &Form, NULL);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + Link = GetFirstNode (&Form->ConfigRequestHead);
> + while (!IsNull (&Form->ConfigRequestHead, Link)) {
> + ConfigInfo = HII_FORM_CONFIG_REQUEST_FROM_LINK (Link);
> + Link = GetNextNode (&Form->ConfigRequestHead, Link);
> +
> + Storage = ConfigInfo->Storage;
> + if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
> + continue;
> + }
> +
> + //
> + // Skip if there is no RequestElement
> + //
> + if (ConfigInfo->ElementCount == 0) {
> + continue;
> + }
> +
> + Status = StorageToConfigResp (ConfigInfo->Storage, &ConfigResp,
> ConfigInfo->ConfigRequest);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + Status = gBS->LocateProtocol (
> + &gEfiHiiConfigRoutingProtocolGuid,
> + NULL,
> + (VOID **)&HiiConfigRouting
> + );
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + Status = HiiConfigRouting->RouteConfig (
> + HiiConfigRouting,
> + ConfigResp,
> + &Progress
> + );
> +
> + if (EFI_ERROR (Status)) {
> + FreePool (ConfigResp);
> + continue;
> + }
> +
> + FreePool (ConfigResp);
> + }
> +
> + return Status;
> +}
> +
> +/**
> + Save Question Value to the memory, but not to storage.
> +
> + @param[in] FormSet FormSet data structure.
> + @param[in] Form Form data structure.
> + @param[in,out] Question Pointer to the Question.
> + @param[in] QuestionValue New Question Value to be set.
> +
> + @retval EFI_SUCCESS The question value has been set successfully.
> + @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
> +
> +**/
> +EFI_STATUS
> +SetQuestionValue (
> + IN HII_FORMSET *FormSet,
> + IN HII_FORM *Form,
> + IN OUT HII_STATEMENT *Question,
> + IN HII_STATEMENT_VALUE *QuestionValue
> + )
> +{
> + UINT8 *Src;
> + UINTN BufferLen;
> + UINTN StorageWidth;
> + HII_FORMSET_STORAGE *Storage;
> + CHAR16 *ValueStr;
> + BOOLEAN IsBufferStorage;
> + UINT8 *TemBuffer;
> + CHAR16 *TemName;
> + CHAR16 *TemString;
> + UINTN Index;
> + HII_NAME_VALUE_NODE *Node;
> + EFI_STATUS Status;
> +
> + if ((FormSet == NULL) || (Form == NULL) || (Question == NULL) ||
> (QuestionValue == NULL)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + Status = EFI_SUCCESS;
> + Node = NULL;
> +
> + //
> + // If Question value is provided by an Expression, then it is read only
> + //
> + if ((Question->ValueExpression != NULL) || (Question->Value.Type !=
> QuestionValue->Type)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + //
> + // Before set question value, evaluate its write expression.
> + //
> + if ((Question->WriteExpression != NULL) && (Form->FormType ==
> STANDARD_MAP_FORM_TYPE)) {
> + Status = EvaluateHiiExpression (FormSet, Form, Question-
> >WriteExpression);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> + }
> +
> + Storage = Question->Storage;
> + if (Storage != NULL) {
> + StorageWidth = Question->StorageWidth;
> + if (Question->Value.Type == EFI_IFR_TYPE_BUFFER) {
> + Question->Value.BufferLen = QuestionValue->BufferLen;
> + Question->Value.Buffer = AllocateCopyPool (QuestionValue-
> >BufferLen, QuestionValue->Buffer);
> + if (Question->Value.Buffer == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + Question->Value.BufferValueType = QuestionValue->BufferValueType;
> + Src = Question->Value.Buffer;
> + } else if (Question->Value.Type == EFI_IFR_TYPE_STRING) {
> + Question->Value.Value.string = QuestionValue->Value.string;
> + TemString = HiiGetString (FormSet->HiiHandle, QuestionValue-
> >Value.string, NULL);
> + if (TemString == NULL) {
> + return EFI_ABORTED;
> + }
> +
> + Question->Value.BufferLen = Question->StorageWidth;
> + Question->Value.Buffer = AllocateZeroPool (Question->StorageWidth);
> + if (Question->Value.Buffer == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + CopyMem (Question->Value.Buffer, TemString, StrSize (TemString));
> + Src = Question->Value.Buffer;
> + } else {
> + CopyMem (&Question->Value.Value, &QuestionValue->Value, sizeof
> (EFI_IFR_TYPE_VALUE));
> + Src = (UINT8 *)&Question->Value.Value;
> + }
> +
> + if ((Storage->Type == EFI_HII_VARSTORE_BUFFER) || (Storage->Type ==
> EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {
> + IsBufferStorage = TRUE;
> + } else {
> + IsBufferStorage = FALSE;
> + }
> +
> + if (IsBufferStorage) {
> + //
> + // If the Question refer to bit filed, copy the value in related bit filed to
> storage edit buffer.
> + //
> + if (Question->QuestionReferToBitField) {
> + SetBitsQuestionValue (Question, Storage->Buffer + Question-
> >VarStoreInfo.VarOffset, (UINT32)(*Src));
> + } else {
> + CopyMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Src,
> StorageWidth);
> + }
> + } else {
> + if (Question->Value.Type == EFI_IFR_TYPE_STRING) {
> + //
> + // Allocate enough string buffer.
> + //
> + ValueStr = NULL;
> + BufferLen = ((StrLen ((CHAR16 *)Src) * 4) + 1) * sizeof (CHAR16);
> + ValueStr = AllocatePool (BufferLen);
> + if (ValueStr == NULL) {
> + if (Question->Value.Buffer != NULL) {
> + FreePool (Question->Value.Buffer);
> + }
> +
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + //
> + // Convert Unicode String to Config String, e.g. "ABCD" =>
> "0041004200430044"
> + //
> + TemName = (CHAR16 *)Src;
> + TemString = ValueStr;
> + for ( ; *TemName != L'\0'; TemName++) {
> + UnicodeValueToStringS (
> + TemString,
> + BufferLen - ((UINTN)TemString - (UINTN)ValueStr),
> + PREFIX_ZERO | RADIX_HEX,
> + *TemName,
> + 4
> + );
> + TemString += StrnLenS (TemString, (BufferLen - ((UINTN)TemString -
> (UINTN)ValueStr)) / sizeof (CHAR16));
> + }
> + } else {
> + BufferLen = StorageWidth * 2 + 1;
> + ValueStr = AllocateZeroPool (BufferLen * sizeof (CHAR16));
> + if (ValueStr == NULL) {
> + if (Question->Value.Buffer != NULL) {
> + FreePool (Question->Value.Buffer);
> + }
> +
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + //
> + // Convert Buffer to Hex String
> + //
> + TemBuffer = Src + StorageWidth - 1;
> + TemString = ValueStr;
> + for (Index = 0; Index < StorageWidth; Index++, TemBuffer--) {
> + UnicodeValueToStringS (
> + TemString,
> + BufferLen * sizeof (CHAR16) - ((UINTN)TemString - (UINTN)ValueStr),
> + PREFIX_ZERO | RADIX_HEX,
> + *TemBuffer,
> + 2
> + );
> + TemString += StrnLenS (TemString, BufferLen - ((UINTN)TemString -
> (UINTN)ValueStr) / sizeof (CHAR16));
> + }
> + }
> +
> + Status = SetValueByName (Storage, Question->VariableName, ValueStr,
> &Node);
> + FreePool (ValueStr);
> + if (EFI_ERROR (Status)) {
> + if (Question->Value.Buffer != NULL) {
> + FreePool (Question->Value.Buffer);
> + }
> +
> + return Status;
> + }
> + }
> + } else {
> + if (Question->Value.Type == EFI_IFR_TYPE_BUFFER) {
> + Question->Value.BufferLen = QuestionValue->BufferLen;
> + Question->Value.Buffer = AllocateCopyPool (QuestionValue-
> >BufferLen, QuestionValue->Buffer);
> + if (Question->Value.Buffer == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + Question->Value.BufferValueType = QuestionValue->BufferValueType;
> + } else if (Question->Value.Type == EFI_IFR_TYPE_STRING) {
> + Question->Value.Value.string = QuestionValue->Value.string;
> + TemString = HiiGetString (FormSet->HiiHandle, QuestionValue-
> >Value.string, NULL);
> + if (TemString == NULL) {
> + return EFI_ABORTED;
> + }
> +
> + Question->Value.BufferLen = (UINT16)StrSize (TemString);
> + Question->Value.Buffer = AllocateZeroPool (QuestionValue-
> >BufferLen);
> + if (Question->Value.Buffer == NULL) {
> + FreePool (TemString);
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + CopyMem (Question->Value.Buffer, TemString, StrSize (TemString));
> + FreePool (TemString);
> + } else {
> + CopyMem (&Question->Value.Value, &QuestionValue->Value, sizeof
> (EFI_IFR_TYPE_VALUE));
> + }
> + }
> +
> + return Status;
> +}
> +
> +/**
> + Get Question's current Value from storage.
> +
> + @param[in] FormSet FormSet data structure.
> + @param[in] Form Form data structure.
> + @param[in,out] Question Question to be initialized.
> +
> + @return the current Question Value in storage if success.
> + @return NULL if Question is not found or any error occurs.
> +
> +**/
> +HII_STATEMENT_VALUE *
> +RetrieveQuestion (
> + IN HII_FORMSET *FormSet,
> + IN HII_FORM *Form,
> + IN OUT HII_STATEMENT *Question
> + )
> +{
> + EFI_STATUS Status;
> + EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
> + EFI_BROWSER_ACTION_REQUEST ActionRequest;
> + HII_FORMSET_STORAGE *Storage;
> + HII_STATEMENT_VALUE *QuestionValue;
> + EFI_IFR_TYPE_VALUE *TypeValue;
> + EFI_TIME EfiTime;
> + BOOLEAN Enabled;
> + BOOLEAN Pending;
> + UINT8 *Dst;
> + UINTN StorageWidth;
> + CHAR16 *ConfigRequest;
> + CHAR16 *Progress;
> + CHAR16 *Result;
> + CHAR16 *ValueStr;
> + UINTN Length;
> + BOOLEAN IsBufferStorage;
> + CHAR16 *NewHiiString;
> +
> + if ((FormSet == NULL) || (Form == NULL) || (Question == NULL)) {
> + return NULL;
> + }
> +
> + Status = EFI_SUCCESS;
> + ValueStr = NULL;
> + Result = NULL;
> +
> + QuestionValue = AllocateZeroPool (sizeof (HII_STATEMENT_VALUE));
> + if (QuestionValue == NULL) {
> + return NULL;
> + }
> +
> + QuestionValue->Type = Question->Value.Type;
> + QuestionValue->BufferLen = Question->Value.BufferLen;
> + if (QuestionValue->BufferLen != 0) {
> + QuestionValue->Buffer = AllocateZeroPool (QuestionValue->BufferLen);
> + if (QuestionValue->Buffer == NULL) {
> + FreePool (QuestionValue);
> + return NULL;
> + }
> + }
> +
> + //
> + // Question value is provided by RTC
> + //
> + Storage = Question->Storage;
> + StorageWidth = Question->StorageWidth;
> +
> + if (Storage == NULL) {
> + //
> + // It's a Question without storage, or RTC date/time
> + //
> + if ((Question->Operand == EFI_IFR_DATE_OP) || (Question->Operand ==
> EFI_IFR_TIME_OP)) {
> + //
> + // Date and time define the same Flags bit
> + //
> + switch (Question->ExtraData.Flags & EFI_QF_DATE_STORAGE) {
> + case QF_DATE_STORAGE_TIME:
> +
> + Status = gRT->GetTime (&EfiTime, NULL);
> + break;
> +
> + case QF_DATE_STORAGE_WAKEUP:
> +
> + Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);
> + break;
> +
> + case QF_DATE_STORAGE_NORMAL:
> + default:
> +
> + goto ON_ERROR;
> + }
> +
> + if (EFI_ERROR (Status)) {
> + if (Question->Operand == EFI_IFR_DATE_OP) {
> + QuestionValue->Value.date.Year = 0xff;
> + QuestionValue->Value.date.Month = 0xff;
> + QuestionValue->Value.date.Day = 0xff;
> + } else {
> + QuestionValue->Value.time.Hour = 0xff;
> + QuestionValue->Value.time.Minute = 0xff;
> + QuestionValue->Value.time.Second = 0xff;
> + }
> +
> + return QuestionValue;
> + }
> +
> + if (Question->Operand == EFI_IFR_DATE_OP) {
> + QuestionValue->Value.date.Year = EfiTime.Year;
> + QuestionValue->Value.date.Month = EfiTime.Month;
> + QuestionValue->Value.date.Day = EfiTime.Day;
> + } else {
> + QuestionValue->Value.time.Hour = EfiTime.Hour;
> + QuestionValue->Value.time.Minute = EfiTime.Minute;
> + QuestionValue->Value.time.Second = EfiTime.Second;
> + }
> + } else {
> + if (((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) !=
> EFI_IFR_FLAG_CALLBACK) ||
> + (FormSet->ConfigAccess == NULL))
> + {
> + goto ON_ERROR;
> + }
> +
> + if (QuestionValue->Type == EFI_IFR_TYPE_BUFFER) {
> + //
> + // For OrderedList, passing in the value buffer to Callback()
> + //
> + TypeValue = (EFI_IFR_TYPE_VALUE *)QuestionValue->Buffer;
> + } else {
> + TypeValue = &QuestionValue->Value;
> + }
> +
> + ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
> + Status = FormSet->ConfigAccess->Callback (
> + FormSet->ConfigAccess,
> + EFI_BROWSER_ACTION_RETRIEVE,
> + Question->QuestionId,
> + QuestionValue->Type,
> + TypeValue,
> + &ActionRequest
> + );
> +
> + if (!EFI_ERROR (Status) && (QuestionValue->Type ==
> EFI_IFR_TYPE_STRING)) {
> + if (TypeValue->string == 0) {
> + goto ON_ERROR;
> + }
> +
> + NewHiiString = GetTokenString (TypeValue->string, FormSet-
> >HiiHandle);
> + if (NewHiiString == NULL) {
> + goto ON_ERROR;
> + }
> +
> + QuestionValue->Buffer = AllocatePool (StrSize (NewHiiString));
> + if (QuestionValue->Buffer == NULL) {
> + FreePool (NewHiiString);
> + goto ON_ERROR;
> + }
> +
> + CopyMem (QuestionValue->Buffer, NewHiiString, StrSize
> (NewHiiString));
> + QuestionValue->BufferLen = (UINT16)StrSize (NewHiiString);
> +
> + FreePool (NewHiiString);
> + }
> + }
> +
> + return QuestionValue;
> + }
> +
> + //
> + // Question value is provided by EFI variable
> + //
> + if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
> + if ((QuestionValue->Type != EFI_IFR_TYPE_BUFFER) && (QuestionValue-
> >Type != EFI_IFR_TYPE_STRING)) {
> + Dst = QuestionValue->Buffer;
> + StorageWidth = QuestionValue->BufferLen;
> + } else {
> + Dst = (UINT8 *)&QuestionValue->Value;
> + StorageWidth = sizeof (EFI_IFR_TYPE_VALUE);
> + }
> +
> + Status = gRT->GetVariable (
> + Question->VariableName,
> + &Storage->Guid,
> + NULL,
> + &StorageWidth,
> + Dst
> + );
> +
> + return QuestionValue;
> + }
> +
> + Status = gBS->LocateProtocol (
> + &gEfiHiiConfigRoutingProtocolGuid,
> + NULL,
> + (VOID **)&HiiConfigRouting
> + );
> + if (EFI_ERROR (Status)) {
> + goto ON_ERROR;
> + }
> +
> + if (QuestionValue->BufferLen != 0) {
> + Dst = QuestionValue->Buffer;
> + } else {
> + Dst = (UINT8 *)&QuestionValue->Value;
> + }
> +
> + if ((Storage->Type == EFI_HII_VARSTORE_BUFFER) || (Storage->Type ==
> EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {
> + IsBufferStorage = TRUE;
> + } else {
> + IsBufferStorage = FALSE;
> + }
> +
> + Storage = GetFstStgFromVarId (FormSet, Question->VarStoreId);
> + if (Storage == NULL) {
> + goto ON_ERROR;
> + }
> +
> + //
> + // <ConfigRequest> ::= <ConfigHdr> + <BlockName> || <ConfigHdr> + "&"
> + <VariableName>
> + //
> + if (IsBufferStorage) {
> + Length = StrLen (Storage->ConfigHdr);
> + Length += StrLen (Question->BlockName);
> + } else {
> + Length = StrLen (Storage->ConfigHdr);
> + Length += StrLen (Question->VariableName) + 1;
> + }
> +
> + ConfigRequest = AllocatePool ((Length + 1) * sizeof (CHAR16));
> + if (ConfigRequest == NULL) {
> + goto ON_ERROR;
> + }
> +
> + StrCpyS (ConfigRequest, Length + 1, Storage->ConfigHdr);
> + if (IsBufferStorage) {
> + StrCatS (ConfigRequest, Length + 1, Question->BlockName);
> + } else {
> + StrCatS (ConfigRequest, Length + 1, L"&");
> + StrCatS (ConfigRequest, Length + 1, Question->VariableName);
> + }
> +
> + //
> + // Request current settings from Configuration Driver
> + //
> + Status = HiiConfigRouting->ExtractConfig (
> + HiiConfigRouting,
> + ConfigRequest,
> + &Progress,
> + &Result
> + );
> + FreePool (ConfigRequest);
> + if (EFI_ERROR (Status)) {
> + goto ON_ERROR;
> + }
> +
> + if (IsBufferStorage) {
> + ValueStr = StrStr (Result, L"&VALUE");
> + if (ValueStr == NULL) {
> + FreePool (Result);
> + goto ON_ERROR;
> + }
> +
> + ValueStr = ValueStr + 6;
> + } else {
> + ValueStr = Result + Length;
> + }
> +
> + if (*ValueStr != '=') {
> + FreePool (Result);
> + goto ON_ERROR;
> + }
> +
> + ValueStr++;
> + Status = BufferToQuestionValue (Question, ValueStr, QuestionValue);
> + if (EFI_ERROR (Status)) {
> + FreePool (Result);
> + goto ON_ERROR;
> + }
> +
> + if (Result != NULL) {
> + FreePool (Result);
> + }
> +
> + return QuestionValue;
> +
> +ON_ERROR:
> +
> + if (QuestionValue->Buffer != NULL) {
> + FreePool (QuestionValue->Buffer);
> + }
> +
> + FreePool (QuestionValue);
> +
> + return NULL;
> +}
> --
> 2.17.1
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2023-04-19 9:49 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-04-19 9:09 [PATCH v3 2/5] RedfishPkg: introduce HII utility helper library Nickle Wang
2023-04-19 9:48 ` Chang, Abner
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox