From 02990e2558ffe4ed7e78103dfa2df88badc66316 Mon Sep 17 00:00:00 2001 From: Nickle Wang Date: Mon, 10 Apr 2023 21:12:03 +0800 Subject: RedfishPkg: introduce HII utility helper library HiiUtilityLib is a helper library that provides the functions to manipulate HII options. Signed-off-by: Nickle Wang Cc: Abner Chang Cc: Igor Kulchytskyy Cc: Nick Ramirez Reviewed-by: Abner Chang Reviewed-by: Igor Kulchytskyy --- RedfishPkg/Include/Library/HiiUtilityLib.h | 1204 ++++ RedfishPkg/Library/HiiUtilityLib/HiiExpression.c | 1439 +++++ RedfishPkg/Library/HiiUtilityLib/HiiExpression.h | 191 + RedfishPkg/Library/HiiUtilityLib/HiiIfrParse.c | 2715 +++++++++ RedfishPkg/Library/HiiUtilityLib/HiiInternal.h | 376 ++ .../Library/HiiUtilityLib/HiiUtilityInternal.c | 5770 ++++++++++++++++++++ RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.c | 810 +++ RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.inf | 62 + RedfishPkg/RedfishPkg.dec | 4 + 9 files changed, 12571 insertions(+) create mode 100644 RedfishPkg/Include/Library/HiiUtilityLib.h create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiExpression.c create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiExpression.h create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiIfrParse.c create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiInternal.h create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiUtilityInternal.c create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.c create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.inf diff --git a/RedfishPkg/Include/Library/HiiUtilityLib.h b/RedfishPkg/Include/Library/HiiUtilityLib.h new file mode 100644 index 0000000000..0999ef77fe --- /dev/null +++ b/RedfishPkg/Include/Library/HiiUtilityLib.h @@ -0,0 +1,1204 @@ +/** @file + Definitions of RedfishPlatformConfigLib. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP
+ 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 +#include + +// +// 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; ///< + CHAR16 *ConfigRequest; ///< = + + UINTN ElementCount; ///< Number of in the + 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.c b/RedfishPkg/Library/HiiUtilityLib/HiiExpression.c new file mode 100644 index 0000000000..c36c241642 --- /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.
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP
+ 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/HiiExpression.h b/RedfishPkg/Library/HiiUtilityLib/HiiExpression.h new file mode 100644 index 0000000000..dda96ada60 --- /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.
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP
+ 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 + +/** + 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/HiiIfrParse.c b/RedfishPkg/Library/HiiUtilityLib/HiiIfrParse.c new file mode 100644 index 0000000000..a51d7b9c6d --- /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.
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP
+ 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. ::= '&' | '&'