--- /dev/null
+/** @file\r
+ Definitions of RedfishPlatformConfigLib.\r
+\r
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>\r
+ Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.\r
+\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#ifndef HII_UTILITY_LIB_\r
+#define HII_UTILITY_LIB_\r
+\r
+#include <Protocol/DisplayProtocol.h>\r
+#include <Protocol/HiiConfigAccess.h>\r
+\r
+//\r
+// IFR relative definition\r
+//\r
+#define EFI_HII_EXPRESSION_INCONSISTENT_IF 0\r
+#define EFI_HII_EXPRESSION_NO_SUBMIT_IF 1\r
+#define EFI_HII_EXPRESSION_GRAY_OUT_IF 2\r
+#define EFI_HII_EXPRESSION_SUPPRESS_IF 3\r
+#define EFI_HII_EXPRESSION_DISABLE_IF 4\r
+#define EFI_HII_EXPRESSION_VALUE 5\r
+#define EFI_HII_EXPRESSION_RULE 6\r
+#define EFI_HII_EXPRESSION_READ 7\r
+#define EFI_HII_EXPRESSION_WRITE 8\r
+#define EFI_HII_EXPRESSION_WARNING_IF 9\r
+\r
+#define EFI_HII_VARSTORE_BUFFER 0\r
+#define EFI_HII_VARSTORE_NAME_VALUE 1\r
+#define EFI_HII_VARSTORE_EFI_VARIABLE 2 // EFI Varstore type follow UEFI spec before 2.3.1.\r
+#define EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER 3 // EFI varstore type follow UEFI spec 2.3.1 and later.\r
+\r
+///\r
+/// HII_NAME_VALUE_NODE for name/value storage\r
+///\r
+typedef struct {\r
+ UINTN Signature;\r
+ LIST_ENTRY Link;\r
+ CHAR16 *Name;\r
+ CHAR16 *Value;\r
+} HII_NAME_VALUE_NODE;\r
+\r
+#define HII_NAME_VALUE_NODE_SIGNATURE SIGNATURE_32 ('N', 'V', 'S', 'T')\r
+#define HII_NAME_VALUE_NODE_FROM_LINK(a) CR (a, HII_NAME_VALUE_NODE, Link, HII_NAME_VALUE_NODE_SIGNATURE)\r
+\r
+///\r
+/// Storage info\r
+///\r
+typedef union {\r
+ EFI_STRING_ID VarName;\r
+ UINT16 VarOffset;\r
+} HII_VAR_STORE_INFO;\r
+\r
+///\r
+/// FormSet storage\r
+///\r
+typedef struct {\r
+ UINTN Signature;\r
+ LIST_ENTRY Link;\r
+\r
+ UINT8 Type; ///< Storage type\r
+ EFI_HII_HANDLE HiiHandle; ///< HiiHandle for this varstore.\r
+\r
+ ///\r
+ /// For all type of storages.\r
+ ///\r
+ UINT16 VarStoreId; ///< VarStore ID.\r
+ EFI_GUID Guid; ///< VarStore Guid.\r
+\r
+ ///\r
+ /// For EFI_IFR_VARSTORE, EFI_IFR_VARSTORE_EFI\r
+ ///\r
+ CHAR16 *Name; ///< VarStore name\r
+ UINT16 Size; ///< VarStore size.\r
+ UINT8 *Buffer; ///< Buffer storage.\r
+ UINT8 *EditBuffer; ///< Edit copy for Buffer Storage\r
+\r
+ ///\r
+ /// For EFI_IFR_VARSTORE_EFI: EFI Variable.\r
+ ///\r
+ UINT32 Attributes;\r
+\r
+ ///\r
+ /// For EFI_IFR_VARSTORE_NAME_VALUE.\r
+ ///\r
+ LIST_ENTRY NameValueList; ///< List of NAME_VALUE_NODE\r
+\r
+ CHAR16 *ConfigHdr; ///< <ConfigHdr>\r
+ CHAR16 *ConfigRequest; ///< <ConfigRequest> = <ConfigHdr> + <RequestElement>\r
+ UINTN ElementCount; ///< Number of <RequestElement> in the <ConfigRequest>\r
+ UINTN SpareStrLen; ///< Spare length of ConfigRequest string buffer\r
+} HII_FORMSET_STORAGE;\r
+\r
+#define HII_STORAGE_SIGNATURE SIGNATURE_32 ('B', 'S', 'T', 'G')\r
+#define HII_STORAGE_FROM_LINK(a) CR (a, HII_FORMSET_STORAGE, Link, HII_STORAGE_SIGNATURE)\r
+\r
+///\r
+/// Definition of EXPRESS_RESULT\r
+///\r
+typedef enum {\r
+ ExpressFalse = 0,\r
+ ExpressGrayOut,\r
+ ExpressSuppress,\r
+ ExpressDisable\r
+} EXPRESS_RESULT;\r
+\r
+///\r
+/// Definition of EXPRESS_LEVEL\r
+///\r
+typedef enum {\r
+ ExpressNone = 0,\r
+ ExpressForm,\r
+ ExpressStatement,\r
+ ExpressOption\r
+} EXPRESS_LEVEL;\r
+\r
+///\r
+/// Definition of HII_EXPRESSION_OPCODE_EXTRA\r
+///\r
+typedef union {\r
+ EFI_HII_VALUE Value; ///< EFI_IFR_UINT64, EFI_IFR_UINT32, EFI_IFR_UINT16, EFI_IFR_UINT8, EFI_IFR_STRING_REF1\r
+ UINT8 Format; ///< For EFI_IFR_TO_STRING, EFI_IFR_FIND\r
+ UINT8 Flags; ///< For EFI_IFR_SPAN\r
+ UINT8 RuleId; ///< For EFI_IFR_RULE_REF\r
+ EFI_GUID Guid; ///< For EFI_IFR_SECURITY, EFI_IFR_MATCH2\r
+\r
+ struct {\r
+ EFI_QUESTION_ID QuestionId;\r
+ EFI_HII_VALUE Value;\r
+ } EqIdValData;\r
+\r
+ struct {\r
+ EFI_QUESTION_ID QuestionId1;\r
+ EFI_QUESTION_ID QuestionId2;\r
+ } EqIdIdData;\r
+\r
+ struct {\r
+ EFI_QUESTION_ID QuestionId; ///< For EFI_IFR_EQ_ID_VAL_LIST\r
+ UINT16 ListLength;\r
+ UINT16 *ValueList;\r
+ } EqIdListData;\r
+\r
+ struct {\r
+ EFI_QUESTION_ID QuestionId;\r
+ } QuestionRef1Data;\r
+\r
+ struct {\r
+ EFI_STRING_ID DevicePath; ///< For EFI_IFR_QUESTION_REF3_3\r
+ EFI_GUID Guid;\r
+ } QuestionRef3Data;\r
+\r
+ struct {\r
+ HII_FORMSET_STORAGE *VarStorage;\r
+ HII_VAR_STORE_INFO VarStoreInfo;\r
+ UINT8 ValueType;\r
+ UINT8 ValueWidth;\r
+ CHAR16 *ValueName;\r
+ } GetSetData;\r
+} HII_EXPRESSION_OPCODE_EXTRA;\r
+\r
+typedef union _HII_DEPENDENCY_EXPRESSION HII_DEPENDENCY_EXPRESSION;\r
+\r
+///\r
+/// Definition of HII_EXPRESSION_CONSTANT\r
+///\r
+/// Operand:\r
+///\r
+/// EFI_IFR_TRUE\r
+/// EFI_IFR_FALSE\r
+/// EFI_IFR_ONE\r
+/// EFI_IFR_ONES\r
+/// EFI_IFR_ZERO\r
+/// EFI_IFR_UNDEFINED\r
+/// EFI_IFR_VERSION\r
+/// EFI_IFR_UINT8\r
+/// EFI_IFR_UINT16\r
+/// EFI_IFR_UINT32\r
+/// EFI_IFR_UINT64\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ EFI_HII_VALUE Value;\r
+} HII_EXPRESSION_CONSTANT;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_DUP\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+} HII_DEPENDENCY_DUP;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_EQ_ID_VAL\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ EFI_QUESTION_ID QuestionId;\r
+ EFI_HII_VALUE Value;\r
+} HII_DEPENDENCY_EQ_ID_VAL;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_EQ_ID_VAL\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ EFI_QUESTION_ID QuestionId1;\r
+ EFI_QUESTION_ID QuestionId2;\r
+} HII_DEPENDENCY_EQ_ID_ID;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_EQ_ID_VAL_LIST\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ EFI_QUESTION_ID QuestionId;\r
+ UINT16 ListLength;\r
+ UINT16 *ValueList;\r
+} HII_DEPENDENCY_EQ_ID_VAL_LIST;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_QUESTION_REF1\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ EFI_QUESTION_ID QuestionId;\r
+} HII_DEPENDENCY_QUESTION_REF1;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_RULE_REF\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ UINT8 RuleId;\r
+} HII_DEPENDENCY_RULE_REF;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_STRING_REF1\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ EFI_HII_VALUE Value;\r
+} HII_DEPENDENCY_STRING_REF1;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_THIS\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ EFI_QUESTION_ID QuestionId;\r
+} HII_DEPENDENCY_THIS;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_SECURITY\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ EFI_GUID Permissions;\r
+} HII_DEPENDENCY_SECURITY;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_GET\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ HII_FORMSET_STORAGE *VarStorage;\r
+ HII_VAR_STORE_INFO VarStoreInfo;\r
+ UINT8 ValueType;\r
+ UINT8 ValueWidth;\r
+ CHAR16 *ValueName;\r
+} HII_DEPENDENCY_GET;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_LENGTH\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ HII_DEPENDENCY_EXPRESSION *SubExpression;\r
+} HII_DEPENDENCY_LENGTH;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_BITWISE_NOT\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ HII_DEPENDENCY_EXPRESSION *SubExpression;\r
+} HII_DEPENDENCY_BITWISE_NOT;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_STRING_REF2\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ HII_DEPENDENCY_EXPRESSION *SubExpression;\r
+} HII_DEPENDENCY_STRING_REF2;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_QUESTION_REF2\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ HII_DEPENDENCY_EXPRESSION *SubExpression;\r
+} HII_DEPENDENCY_QUESTION_REF2;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_QUESTION_REF3\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ EFI_STRING_ID DevicePath;\r
+ EFI_GUID Guid;\r
+ HII_DEPENDENCY_EXPRESSION *SubExpression;\r
+} HII_DEPENDENCY_QUESTION_REF3;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_TO_BOOLEAN\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ HII_DEPENDENCY_EXPRESSION *SubExpression;\r
+} HII_DEPENDENCY_TO_BOOLEAN;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_TO_STRING\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ UINT8 Format;\r
+ HII_DEPENDENCY_EXPRESSION *SubExpression;\r
+} HII_DEPENDENCY_TO_STRING;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_TO_UINT\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ HII_DEPENDENCY_EXPRESSION *SubExpression;\r
+} HII_DEPENDENCY_TO_UINT;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_TO_UPPER\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ HII_DEPENDENCY_EXPRESSION *SubExpression;\r
+} HII_DEPENDENCY_TO_UPPER;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_TO_LOWER\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ HII_DEPENDENCY_EXPRESSION *SubExpression;\r
+} HII_DEPENDENCY_TO_LOWER;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_SET\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ HII_FORMSET_STORAGE *VarStorage;\r
+ HII_VAR_STORE_INFO VarStoreInfo;\r
+ UINT8 ValueType;\r
+ UINT8 ValueWidth;\r
+ CHAR16 *ValueName;\r
+ HII_DEPENDENCY_EXPRESSION *SubExpression;\r
+} HII_DEPENDENCY_SET;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_NOT\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ HII_DEPENDENCY_EXPRESSION *SubExpression;\r
+} HII_DEPENDENCY_NOT;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_CATENATE\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ HII_DEPENDENCY_EXPRESSION *LeftStringExp;\r
+ HII_DEPENDENCY_EXPRESSION *RightStringExp;\r
+} HII_DEPENDENCY_CATENATE;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_MATCH\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ HII_DEPENDENCY_EXPRESSION *StringExp;\r
+ HII_DEPENDENCY_EXPRESSION *PatternExp;\r
+} HII_DEPENDENCY_MATCH;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_MATCH2\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ EFI_GUID SyntaxType;\r
+ HII_DEPENDENCY_EXPRESSION *StringExp;\r
+ HII_DEPENDENCY_EXPRESSION *PatternExp;\r
+} HII_DEPENDENCY_MATCH2;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_MULT\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ HII_DEPENDENCY_EXPRESSION *RightHandExp;\r
+ HII_DEPENDENCY_EXPRESSION *LeftHandExp;\r
+} HII_DEPENDENCY_MULT;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_DIV\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ HII_DEPENDENCY_EXPRESSION *RightHandExp; ///< right value\r
+ HII_DEPENDENCY_EXPRESSION *LeftHandExp; ///< left value\r
+} HII_DEPENDENCY_DIV;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_MOD\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ HII_DEPENDENCY_EXPRESSION *RightHandExp; ///< right value\r
+ HII_DEPENDENCY_EXPRESSION *LeftHandExp; ///< left value\r
+} HII_DEPENDENCY_MOD;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_ADD\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ HII_DEPENDENCY_EXPRESSION *RightHandExp; ///< right value\r
+ HII_DEPENDENCY_EXPRESSION *LeftHandExp; ///< left value\r
+} HII_DEPENDENCY_ADD;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_SUBTRACT\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ HII_DEPENDENCY_EXPRESSION *RightHandExp; ///< right value\r
+ HII_DEPENDENCY_EXPRESSION *LeftHandExp; ///< left value\r
+} HII_DEPENDENCY_SUBTRACT;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_SHIFT_LEFT\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ HII_DEPENDENCY_EXPRESSION *RightHandExp;\r
+ HII_DEPENDENCY_EXPRESSION *LeftHandExp;\r
+} HII_DEPENDENCY_SHIFT_LEFT;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_SHIFT_RIGHT\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ HII_DEPENDENCY_EXPRESSION *RightHandExp;\r
+ HII_DEPENDENCY_EXPRESSION *LeftHandExp;\r
+} HII_DEPENDENCY_SHIFT_RIGHT;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_GREATER_THAN\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ HII_DEPENDENCY_EXPRESSION *RightHandExp;\r
+ HII_DEPENDENCY_EXPRESSION *LeftHandExp;\r
+} HII_DEPENDENCY_GREATER_THAN;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_GREATER_EQUAL\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ HII_DEPENDENCY_EXPRESSION *RightHandExp;\r
+ HII_DEPENDENCY_EXPRESSION *LeftHandExp;\r
+} HII_DEPENDENCY_GREATER_EQUAL;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_LESS_THAN\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ HII_DEPENDENCY_EXPRESSION *RightHandExp;\r
+ HII_DEPENDENCY_EXPRESSION *LeftHandExp;\r
+} HII_DEPENDENCY_LESS_THAN;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_LESS_EQUAL\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ HII_DEPENDENCY_EXPRESSION *RightHandExp;\r
+ HII_DEPENDENCY_EXPRESSION *LeftHandExp;\r
+} HII_DEPENDENCY_LESS_EQUAL;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_EQUAL\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ HII_DEPENDENCY_EXPRESSION *SubExpression1;\r
+ HII_DEPENDENCY_EXPRESSION *SubExpression2;\r
+} HII_DEPENDENCY_EQUAL;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_NOT_EQUAL\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ HII_DEPENDENCY_EXPRESSION *SubExpression1;\r
+ HII_DEPENDENCY_EXPRESSION *SubExpression2;\r
+} HII_DEPENDENCY_NOT_EQUAL;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_BITWISE_AND\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ HII_DEPENDENCY_EXPRESSION *SubExpression1;\r
+ HII_DEPENDENCY_EXPRESSION *SubExpression2;\r
+} HII_DEPENDENCY_BITWISE_AND;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_BITWISE_OR\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ HII_DEPENDENCY_EXPRESSION *SubExpression1;\r
+ HII_DEPENDENCY_EXPRESSION *SubExpression2;\r
+} HII_DEPENDENCY_BITWISE_OR;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_AND\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ HII_DEPENDENCY_EXPRESSION *SubExpression1;\r
+ HII_DEPENDENCY_EXPRESSION *SubExpression2;\r
+} HII_DEPENDENCY_AND;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_OR\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ HII_DEPENDENCY_EXPRESSION *SubExpression1;\r
+ HII_DEPENDENCY_EXPRESSION *SubExpression2;\r
+} HII_DEPENDENCY_OR;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_CONDITIONAL\r
+///\r
+/// Ternary expression\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ HII_DEPENDENCY_EXPRESSION *CondTrueValExp; ///< right value\r
+ HII_DEPENDENCY_EXPRESSION *CondFalseValExp; ///< middle value\r
+ HII_DEPENDENCY_EXPRESSION *ConditionExp; ///< left value\r
+} HII_DEPENDENCY_CONDITIONAL;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_FIND\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ UINT8 Format;\r
+ HII_DEPENDENCY_EXPRESSION *IndexExp; ///< right value\r
+ HII_DEPENDENCY_EXPRESSION *StringToCompWithExp; ///< middle value\r
+ HII_DEPENDENCY_EXPRESSION *StringToSearchExp; ///< left value\r
+} HII_DEPENDENCY_FIND;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_MID\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ HII_DEPENDENCY_EXPRESSION *LengthExp; ///< right value\r
+ HII_DEPENDENCY_EXPRESSION *IndexExp; ///< middle value\r
+ HII_DEPENDENCY_EXPRESSION *StringOrBufferExp; ///< left value\r
+} HII_DEPENDENCY_MID;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_TOKEN\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ HII_DEPENDENCY_EXPRESSION *IndexExp; ///< right value\r
+ HII_DEPENDENCY_EXPRESSION *DelimiterExp; ///< middle value\r
+ HII_DEPENDENCY_EXPRESSION *StringToSearchExp; ///< left value\r
+} HII_DEPENDENCY_TOKEN;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_SPAN\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ UINT8 Flags;\r
+ HII_DEPENDENCY_EXPRESSION *IndexExp; ///< right value\r
+ HII_DEPENDENCY_EXPRESSION *CharsetExp; ///< middle value\r
+ HII_DEPENDENCY_EXPRESSION *StringToSearchExp; ///< left value\r
+} HII_DEPENDENCY_SPAN;\r
+\r
+///\r
+/// Map expression\r
+///\r
+typedef struct {\r
+ HII_DEPENDENCY_EXPRESSION *MatchExp;\r
+ HII_DEPENDENCY_EXPRESSION *ReturnExp;\r
+} HII_DEPENDENCY_EXPRESSION_PAIR;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_MAP\r
+///\r
+typedef struct {\r
+ UINT8 Operand;\r
+ HII_DEPENDENCY_EXPRESSION *SubExp;\r
+ HII_DEPENDENCY_EXPRESSION_PAIR *ExpPair;\r
+ UINT8 ExpPairNo;\r
+} HII_DEPENDENCY_MAP;\r
+\r
+///\r
+/// Definition of HII_DEPENDENCY_EXPRESSION\r
+///\r
+union _HII_DEPENDENCY_EXPRESSION {\r
+ ///\r
+ /// Constant\r
+ ///\r
+ HII_EXPRESSION_CONSTANT ConstantExp;\r
+ ///\r
+ /// build-in expression\r
+ ///\r
+ HII_DEPENDENCY_DUP DupExp;\r
+ HII_DEPENDENCY_EQ_ID_VAL EqIdValExp;\r
+ HII_DEPENDENCY_EQ_ID_ID EqIdIdExp;\r
+ HII_DEPENDENCY_EQ_ID_VAL_LIST EqIdListExp;\r
+ HII_DEPENDENCY_QUESTION_REF1 QuestionRef1Exp;\r
+ HII_DEPENDENCY_RULE_REF RuleRefExp;\r
+ HII_DEPENDENCY_STRING_REF1 StringRef1Exp;\r
+ HII_DEPENDENCY_THIS ThisExp;\r
+ HII_DEPENDENCY_SECURITY SecurityExp;\r
+ HII_DEPENDENCY_GET GetExp;\r
+\r
+ ///\r
+ /// unary expression\r
+ ///\r
+ HII_DEPENDENCY_LENGTH LengthExp;\r
+ HII_DEPENDENCY_BITWISE_NOT BitWiseNotExp;\r
+ HII_DEPENDENCY_STRING_REF2 StringRef2Exp;\r
+ HII_DEPENDENCY_QUESTION_REF2 QuestionRef2Exp;\r
+ HII_DEPENDENCY_QUESTION_REF3 QuestionRef3Exp;\r
+ HII_DEPENDENCY_TO_BOOLEAN ToBooleanExp;\r
+ HII_DEPENDENCY_TO_STRING ToStringExp;\r
+ HII_DEPENDENCY_TO_UINT ToUintExp;\r
+ HII_DEPENDENCY_TO_UPPER ToUpperExp;\r
+ HII_DEPENDENCY_TO_LOWER ToLowerExp;\r
+ HII_DEPENDENCY_SET SetExp;\r
+ HII_DEPENDENCY_NOT NotExp;\r
+\r
+ ///\r
+ /// Binary expression\r
+ ///\r
+ HII_DEPENDENCY_CATENATE CatenateExp;\r
+ HII_DEPENDENCY_MATCH MatchExp;\r
+ HII_DEPENDENCY_MATCH2 Match2Exp;\r
+ HII_DEPENDENCY_MULT MultExp;\r
+ HII_DEPENDENCY_DIV DivExp;\r
+ HII_DEPENDENCY_MOD ModExp;\r
+ HII_DEPENDENCY_ADD AddExp;\r
+ HII_DEPENDENCY_SUBTRACT SubtractExp;\r
+ HII_DEPENDENCY_SHIFT_LEFT ShiftLeftExp;\r
+ HII_DEPENDENCY_SHIFT_RIGHT ShiftRightExp;\r
+ HII_DEPENDENCY_GREATER_THAN GreaterThanExp;\r
+ HII_DEPENDENCY_GREATER_EQUAL GreaterEqualExp;\r
+ HII_DEPENDENCY_LESS_THAN LessThanExp;\r
+ HII_DEPENDENCY_LESS_EQUAL LessEqualExp;\r
+ HII_DEPENDENCY_EQUAL EqualExp;\r
+ HII_DEPENDENCY_NOT_EQUAL NotEqualExp;\r
+ HII_DEPENDENCY_BITWISE_AND BitwiseAndExp;\r
+ HII_DEPENDENCY_BITWISE_OR BitwiseOrExp;\r
+ HII_DEPENDENCY_AND AndExp;\r
+ HII_DEPENDENCY_OR OrExp;\r
+\r
+ ///\r
+ /// ternary expression\r
+ ///\r
+ HII_DEPENDENCY_CONDITIONAL ConditionalExp;\r
+ HII_DEPENDENCY_FIND FindExp;\r
+ HII_DEPENDENCY_MID MidExp;\r
+ HII_DEPENDENCY_TOKEN TokenExp;\r
+ HII_DEPENDENCY_SPAN SpanExp;\r
+ HII_DEPENDENCY_MAP MapExp;\r
+};\r
+\r
+///\r
+/// Definition of HII_EXPRESSION_OPCODE\r
+///\r
+typedef struct {\r
+ UINTN Signature;\r
+ LIST_ENTRY Link;\r
+ UINT8 Operand;\r
+ HII_EXPRESSION_OPCODE_EXTRA ExtraData;\r
+ LIST_ENTRY MapExpressionList; ///< nested expressions inside of Map opcode.\r
+} HII_EXPRESSION_OPCODE;\r
+\r
+#define HII_EXPRESSION_OPCODE_SIGNATURE SIGNATURE_32 ('E', 'X', 'O', 'P')\r
+#define HII_EXPRESSION_OPCODE_FROM_LINK(a) CR (a, HII_EXPRESSION_OPCODE, Link, HII_EXPRESSION_OPCODE_SIGNATURE)\r
+\r
+///\r
+/// Definition of HII_WARNING_IF_DATA\r
+///\r
+typedef struct {\r
+ EFI_STRING_ID WarningIfError;\r
+ UINT8 TimeOut;\r
+} HII_WARNING_IF_DATA;\r
+\r
+///\r
+/// Definition of HII_EXTRA_DATA\r
+///\r
+typedef union {\r
+ UINT8 RuleId; ///< For EFI_IFR_RULE only\r
+ EFI_STRING_ID Error; ///< For EFI_IFR_NO_SUBMIT_IF, EFI_IFR_INCONSISTENT_IF only\r
+ HII_WARNING_IF_DATA WarningIfData;\r
+} HII_EXTRA_DATA;\r
+\r
+///\r
+/// Definition of HII_EXPRESSION\r
+///\r
+typedef struct {\r
+ UINTN Signature;\r
+ LIST_ENTRY Link;\r
+ UINT8 Type; ///< Type for this expression\r
+ EFI_IFR_OP_HEADER *OpCode; ///< Save the opcode buffer.\r
+ LIST_ENTRY OpCodeListHead; ///< OpCodes consist of this expression (HII_EXPRESSION_OPCODE)\r
+ HII_DEPENDENCY_EXPRESSION *RootDependencyExp; ///< Expression OpCodes tree layout to describe dependency of this expression.\r
+ HII_EXTRA_DATA ExtraData;\r
+ EFI_HII_VALUE Result; ///< Expression evaluation result\r
+} HII_EXPRESSION;\r
+\r
+#define HII_EXPRESSION_SIGNATURE SIGNATURE_32 ('F', 'E', 'X', 'P')\r
+#define HII_EXPRESSION_FROM_LINK(a) CR (a, HII_EXPRESSION, Link, HII_EXPRESSION_SIGNATURE)\r
+\r
+///\r
+/// Definition of HII_EXPRESSION_LIST\r
+///\r
+typedef struct {\r
+ UINTN Signature;\r
+ UINTN Count;\r
+ HII_EXPRESSION *Expression[1]; ///< Array[Count] of expressions\r
+} HII_EXPRESSION_LIST;\r
+\r
+#define HII_EXPRESSION_LIST_SIGNATURE SIGNATURE_32 ('F', 'E', 'X', 'R')\r
+\r
+///\r
+/// Definition of HII_STATEMENT_VALUE\r
+///\r
+typedef struct {\r
+ ///\r
+ /// HII Data Type\r
+ ///\r
+ UINT8 Type;\r
+ EFI_IFR_TYPE_VALUE Value;\r
+ ///\r
+ /// Buffer Data and Length if Type is EFI_IFR_TYPE_BUFFER or EFI_IFR_TYPE_STRING\r
+ ///\r
+ UINT8 *Buffer;\r
+ UINT16 BufferLen;\r
+ UINT8 BufferValueType; ///< Data type for buffer internal data, currently only for orderedlist\r
+} HII_STATEMENT_VALUE;\r
+\r
+///\r
+/// Default value\r
+///\r
+typedef struct {\r
+ UINTN Signature;\r
+ LIST_ENTRY Link;\r
+\r
+ UINT16 DefaultId;\r
+ HII_STATEMENT_VALUE Value; ///< Default value\r
+\r
+ HII_EXPRESSION *ValueExpression; ///< Not-NULL indicates default value is provided by EFI_IFR_VALUE\r
+} HII_QUESTION_DEFAULT;\r
+\r
+#define HII_QUESTION_DEFAULT_SIGNATURE SIGNATURE_32 ('Q', 'D', 'F', 'T')\r
+#define HII_QUESTION_DEFAULT_FROM_LINK(a) CR (a, HII_QUESTION_DEFAULT, Link, HII_QUESTION_DEFAULT_SIGNATURE)\r
+\r
+#define HII_QUESTION_OPTION_SIGNATURE SIGNATURE_32 ('Q', 'O', 'P', 'T')\r
+\r
+///\r
+/// Option value\r
+///\r
+typedef struct {\r
+ UINTN Signature;\r
+ LIST_ENTRY Link;\r
+\r
+ EFI_IFR_ONE_OF_OPTION *OpCode; ///< OneOfOption Data\r
+\r
+ EFI_STRING_ID Text;\r
+ UINT8 Flags;\r
+ HII_STATEMENT_VALUE Value;\r
+ EFI_IMAGE_ID ImageId;\r
+\r
+ HII_EXPRESSION_LIST *SuppressExpression; ///< Non-NULL indicates nested inside of SuppressIf\r
+} HII_QUESTION_OPTION;\r
+\r
+#define HII_QUESTION_OPTION_FROM_LINK(a) CR (a, HII_QUESTION_OPTION, Link, HII_QUESTION_OPTION_SIGNATURE)\r
+\r
+///\r
+/// class of default\r
+///\r
+typedef struct {\r
+ UINTN Signature;\r
+ LIST_ENTRY Link;\r
+\r
+ UINT16 DefaultId;\r
+ EFI_STRING_ID DefaultName;\r
+} HII_FORMSET_DEFAULTSTORE;\r
+\r
+#define HII_FORMSET_DEFAULTSTORE_SIGNATURE SIGNATURE_32 ('F', 'D', 'F', 'S')\r
+#define HII_FORMSET_DEFAULTSTORE_FROM_LINK(a) CR (a, HII_FORMSET_DEFAULTSTORE, Link, HII_FORMSET_DEFAULTSTORE_SIGNATURE)\r
+\r
+///\r
+/// Definition of HII_STATEMENT_EXTRA\r
+///\r
+typedef union {\r
+ UINT8 Flags;\r
+ EFI_STRING_ID TextTwo;\r
+ EFI_DEFAULT_ID DefaultId;\r
+ EFI_STRING_ID QuestionConfig;\r
+ EFI_GUID Guid;\r
+\r
+ struct {\r
+ UINT8 Flags;\r
+ UINT64 Minimum; ///< for EFI_IFR_ONE_OF/EFI_IFR_NUMERIC, it's Min/Max value\r
+ UINT64 Maximum; ///< for EFI_IFR_STRING/EFI_IFR_PASSWORD, it's Min/Max length\r
+ UINT64 Step;\r
+ EFI_GUID Guid;\r
+ } NumData;\r
+\r
+ struct {\r
+ UINT8 Flags;\r
+ UINT8 MaxContainers; ///< for EFI_IFR_ORDERED_LIST\r
+ } OrderListData;\r
+\r
+ struct {\r
+ UINT8 Flags;\r
+ UINT8 MinSize;\r
+ UINT8 MaxSize;\r
+ } StrData;\r
+\r
+ struct {\r
+ UINT16 MinSize;\r
+ UINT16 MaxSize;\r
+ } PwdData;\r
+} HII_STATEMENT_EXTRA;\r
+\r
+///\r
+/// Statement (Question)\r
+///\r
+typedef struct _HII_STATEMENT HII_STATEMENT;\r
+struct _HII_STATEMENT {\r
+ UINTN Signature;\r
+ LIST_ENTRY Link;\r
+\r
+ UINT8 Operand; ///< The operand (first byte) of this Statement or Question\r
+ EFI_IFR_OP_HEADER *OpCode;\r
+\r
+ ///\r
+ /// Statement Header\r
+ ///\r
+ EFI_STRING_ID Prompt;\r
+ EFI_STRING_ID Help;\r
+\r
+ ///\r
+ /// Question Header\r
+ ///\r
+ EFI_QUESTION_ID QuestionId; ///< Question id, the value of zero is reserved\r
+ EFI_VARSTORE_ID VarStoreId; ///< VarStore id, a value of zero indicates no variable storage\r
+ 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).\r
+ ///< 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.\r
+ UINT8 QuestionFlags; ///< The flag of this Question.(Readonly, reset required, callback attribute....)\r
+\r
+ BOOLEAN QuestionReferToBitField; ///< Whether the question is stored in a bit field.\r
+ UINT16 StorageWidth; ///< The storage width of this Question.\r
+ UINT16 BitStorageWidth; ///< The Storage width of this Question in bit level.\r
+ UINT16 BitVarOffset; ///< The storage offset of this Question in bit level.\r
+ CHAR16 *VariableName; ///< Name/Value or EFI Variable name\r
+ CHAR16 *BlockName; ///< Buffer storage block name: "OFFSET=...WIDTH=..."\r
+\r
+ HII_FORMSET_STORAGE *Storage; ///< Point to the storage that store this question.\r
+ HII_STATEMENT_EXTRA ExtraData;\r
+\r
+ BOOLEAN Locked; ///< Whether this statement is locked.\r
+\r
+ HII_STATEMENT_VALUE Value;\r
+\r
+ ///\r
+ /// Get from IFR parsing\r
+ ///\r
+\r
+ HII_STATEMENT *ParentStatement; ///< Parent Statement of current statement.\r
+ HII_EXPRESSION_LIST *ExpressionList; ///< nesting inside of GrayedOutIf/DisableIf/SuppressIf\r
+ HII_EXPRESSION *ValueExpression; ///< nested EFI_IFR_VALUE, provide Question value and indicate Question is ReadOnly\r
+\r
+ EFI_IMAGE_ID ImageId; ///< nested EFI_IFR_IMAGE\r
+ UINT8 RefreshInterval; ///< nested EFI_IFR_REFRESH, refresh interval(in seconds) for Question value, 0 means no refresh\r
+\r
+ LIST_ENTRY DefaultListHead; ///< nested EFI_IFR_DEFAULT list (HII_QUESTION_DEFAULT), provide default values\r
+ LIST_ENTRY OptionListHead; ///< nested EFI_IFR_ONE_OF_OPTION list (HII_QUESTION_OPTION)\r
+ LIST_ENTRY InconsistentListHead; ///< nested inconsistent expression list (HII_EXPRESSION)\r
+ LIST_ENTRY NoSubmitListHead; ///< nested nosubmit expression list (HII_EXPRESSION)\r
+ LIST_ENTRY WarningListHead; ///< nested warning expression list (HII_EXPRESSION)\r
+\r
+ HII_EXPRESSION *ReadExpression; ///< nested EFI_IFR_READ, provide this question value by read expression.\r
+ HII_EXPRESSION *WriteExpression; ///< nested EFI_IFR_WRITE, evaluate write expression after this question value is set.\r
+};\r
+\r
+#define HII_STATEMENT_SIGNATURE SIGNATURE_32 ('H', 'S', 'T', 'A')\r
+#define HII_STATEMENT_FROM_LINK(a) CR (a, HII_STATEMENT, Link, HII_STATEMENT_SIGNATURE)\r
+\r
+///\r
+/// Form\r
+///\r
+#define STANDARD_MAP_FORM_TYPE 0x01\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+ LIST_ENTRY Link;\r
+\r
+ UINT16 FormId; ///< FormId of normal form or formmap form.\r
+ EFI_STRING_ID FormTitle; ///< FormTile of normal form, or FormMapMethod title of formmap form.\r
+ UINT16 FormType; ///< Specific form type for the different form.\r
+\r
+ EFI_IMAGE_ID ImageId; ///< The image id.\r
+\r
+ BOOLEAN ModalForm; ///< Whether this is a modal form.\r
+ BOOLEAN Locked; ///< Whether this form is locked.\r
+ EFI_GUID RefreshGuid; ///< Form refresh event guid.\r
+\r
+ LIST_ENTRY StatementListHead; ///< List of Statements and Questions (HII_STATEMENT)\r
+ LIST_ENTRY ConfigRequestHead; ///< List of configrequest for all storage.\r
+ LIST_ENTRY RuleListHead; ///< nested EFI_IFR_RULE list, pre-defined expressions attached to the form.\r
+ HII_EXPRESSION_LIST *SuppressExpression; ///< nesting inside of SuppressIf\r
+} HII_FORM;\r
+\r
+#define HII_FORM_SIGNATURE SIGNATURE_32 ('F', 'F', 'R', 'M')\r
+#define HII_FORM_FROM_LINK(a) CR (a, HII_FORM, Link, HII_FORM_SIGNATURE)\r
+\r
+///\r
+/// FormSet\r
+///\r
+typedef struct {\r
+ UINTN Signature;\r
+ LIST_ENTRY Link;\r
+\r
+ EFI_HII_HANDLE HiiHandle; ///< Unique id for formset, HII Handle of this FormSet package.\r
+ EFI_HANDLE DriverHandle; ///< EFI_HANDLE which was registered with the package list in NewPackageList().\r
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess; ///< ConfigAccess Protocol associated with this HiiPackageList\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+\r
+ UINTN IfrBinaryLength; ///< Ifr binary data length of this formset.\r
+ UINT8 *IfrBinaryData; ///< Point to the Ifr binary data.\r
+\r
+ EFI_GUID Guid; ///< Formset Guid.\r
+ EFI_STRING_ID FormSetTitle; ///< String Id of Formset title.\r
+ EFI_STRING_ID Help; ///< String Id of Formset title.\r
+\r
+ UINT8 NumberOfClassGuid; ///< Class Guid name\r
+ EFI_GUID ClassGuid[3]; ///< Up to three ClassGuid\r
+\r
+ EFI_IMAGE_ID ImageId; ///< The image id.\r
+\r
+ LIST_ENTRY StatementListOSF; ///< Statement list out side of the form.\r
+ LIST_ENTRY StorageListHead; ///< Storage list (HII_FORMSET_STORAGE)\r
+ LIST_ENTRY DefaultStoreListHead; ///< DefaultStore list (HII_FORMSET_DEFAULTSTORE)\r
+ LIST_ENTRY FormListHead; ///< Form list (HII_FORM_BROWSER_FORM)\r
+} HII_FORMSET;\r
+\r
+#define HII_FORMSET_SIGNATURE SIGNATURE_32 ('H', 'I', 'F', 'S')\r
+#define HII_FORMSET_FROM_LINK(a) CR (a, HII_FORMSET, Link, HII_FORMSET_SIGNATURE)\r
+\r
+///\r
+/// Get/set question value from/to.\r
+///\r
+typedef enum {\r
+ GetSetValueWithBuffer = 0, ///< Get/Set question value from/to buffer in the storage.\r
+ GetSetValueWithHiiDriver, ///< Get/Set question value from/to hii driver.\r
+ GetSetValueWithBoth, ///< Compare the editbuffer with buffer for this question, not use the question value.\r
+ GetSetValueWithMax ///< Invalid value.\r
+} GET_SET_QUESTION_VALUE_WITH;\r
+\r
+/**\r
+ Initialize the internal data structure of a FormSet.\r
+\r
+ @param[in] Handle PackageList Handle\r
+ @param[in,out] FormSetGuid On input, GUID or class GUID of a formset. If not\r
+ specified (NULL or zero GUID), take the first\r
+ FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
+ found in package list.\r
+ On output, GUID of the formset found(if not NULL).\r
+ @param[out] FormSet FormSet data structure.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+ @retval EFI_NOT_FOUND The specified FormSet could not be found.\r
+\r
+**/\r
+EFI_STATUS\r
+CreateFormSetFromHiiHandle (\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN OUT EFI_GUID *FormSetGuid,\r
+ OUT HII_FORMSET *FormSet\r
+ );\r
+\r
+/**\r
+ Initialize a Formset and get current setting for Questions.\r
+\r
+ @param[in,out] FormSet FormSet data structure.\r
+\r
+**/\r
+VOID\r
+InitializeFormSet (\r
+ IN OUT HII_FORMSET *FormSet\r
+ );\r
+\r
+/**\r
+ Free resources allocated for a FormSet.\r
+\r
+ @param[in,out] FormSet Pointer of the FormSet\r
+\r
+**/\r
+VOID\r
+DestroyFormSet (\r
+ IN OUT HII_FORMSET *FormSet\r
+ );\r
+\r
+/**\r
+ Save Question Value to the memory, but not to storage.\r
+\r
+ @param[in] FormSet FormSet data structure.\r
+ @param[in] Form Form data structure.\r
+ @param[in,out] Question Pointer to the Question.\r
+ @param[in] QuestionValue New Question Value to be set.\r
+\r
+ @retval EFI_SUCCESS The question value has been set successfully.\r
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+SetQuestionValue (\r
+ IN HII_FORMSET *FormSet,\r
+ IN HII_FORM *Form,\r
+ IN OUT HII_STATEMENT *Question,\r
+ IN HII_STATEMENT_VALUE *QuestionValue\r
+ );\r
+\r
+/**\r
+ Get Question's current Value from storage.\r
+\r
+ @param[in] FormSet FormSet data structure.\r
+ @param[in] Form Form data structure.\r
+ @param[in,out] Question Question to be initialized.\r
+\r
+ @return the current Question Value in storage if success.\r
+ @return NULL if Question is not found or any error occurs.\r
+\r
+**/\r
+HII_STATEMENT_VALUE *\r
+RetrieveQuestion (\r
+ IN HII_FORMSET *FormSet,\r
+ IN HII_FORM *Form,\r
+ IN OUT HII_STATEMENT *Question\r
+ );\r
+\r
+/**\r
+ Get Question's current Value.\r
+\r
+ @param[in] FormSet FormSet data structure.\r
+ @param[in] Form Form data structure.\r
+ @param[out] Question Question to be initialized.\r
+ @param[in] GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+ @retval EFI_INVALID_PARAMETER Formset, Form or Question is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+GetQuestionValue (\r
+ IN HII_FORMSET *FormSet,\r
+ IN HII_FORM *Form,\r
+ IN OUT HII_STATEMENT *Question,\r
+ IN GET_SET_QUESTION_VALUE_WITH GetValueFrom\r
+ );\r
+\r
+/**\r
+ Submit data for a form.\r
+\r
+ @param[in] FormSet FormSet which contains the Form.\r
+ @param[in] Form Form to submit.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+ @retval Others Other errors occur.\r
+\r
+**/\r
+EFI_STATUS\r
+SubmitForm (\r
+ IN HII_FORMSET *FormSet,\r
+ IN HII_FORM *Form\r
+ );\r
+\r
+/**\r
+ Evaluate the result of a HII expression.\r
+\r
+ If Expression is NULL, then ASSERT.\r
+\r
+ @param[in] FormSet FormSet associated with this expression.\r
+ @param[in] Form Form associated with this expression.\r
+ @param[in,out] Expression Expression to be evaluated.\r
+\r
+ @retval EFI_SUCCESS The expression evaluated successfully\r
+ @retval EFI_NOT_FOUND The Question which referenced by a QuestionId\r
+ could not be found.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
+ stack.\r
+ @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
+ @retval EFI_INVALID_PARAMETER Syntax error with the Expression\r
+\r
+**/\r
+EFI_STATUS\r
+EvaluateHiiExpression (\r
+ IN HII_FORMSET *FormSet,\r
+ IN HII_FORM *Form,\r
+ IN OUT HII_EXPRESSION *Expression\r
+ );\r
+\r
+/**\r
+ Retrieve dependencies within an expression. These dependencies can express how\r
+ this expression will be evaluated.\r
+\r
+ @param[in] Expression Expression to retrieve dependencies.\r
+\r
+ @retval EFI_SUCCESS The dependencies were successfully retrieved.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory.\r
+\r
+**/\r
+EFI_STATUS\r
+GetHiiExpressionDependency (\r
+ IN HII_EXPRESSION *Expression\r
+ );\r
+\r
+/**\r
+ Get default value of question.\r
+\r
+ @param[in] FormSet The form set.\r
+ @param[in] Form The form.\r
+ @param[in] Question The question.\r
+ @param[in] DefaultId The Class of the default.\r
+ @param[out] DefaultValue The default value of given question.\r
+\r
+ @retval EFI_SUCCESS Question is reset to default value.\r
+\r
+**/\r
+EFI_STATUS\r
+GetQuestionDefault (\r
+ IN HII_FORMSET *FormSet,\r
+ IN HII_FORM *Form,\r
+ IN HII_STATEMENT *Question,\r
+ IN UINT16 DefaultId,\r
+ OUT HII_STATEMENT_VALUE *DefaultValue\r
+ );\r
+\r
+/**\r
+ Return the result of the expression list. Check the expression list and\r
+ return the highest priority express result.\r
+ Priority: DisableIf > SuppressIf > GrayOutIf > FALSE\r
+\r
+ @param[in] ExpList The input expression list.\r
+ @param[in] Evaluate Whether need to evaluate the expression first.\r
+ @param[in] FormSet FormSet associated with this expression.\r
+ @param[in] Form Form associated with this expression.\r
+\r
+ @retval EXPRESS_RESULT Return the higher priority express result.\r
+ DisableIf > SuppressIf > GrayOutIf > FALSE\r
+\r
+**/\r
+EXPRESS_RESULT\r
+EvaluateExpressionList (\r
+ IN HII_EXPRESSION_LIST *ExpList,\r
+ IN BOOLEAN Evaluate,\r
+ IN HII_FORMSET *FormSet OPTIONAL,\r
+ IN HII_FORM *Form OPTIONAL\r
+ );\r
+\r
+#endif // HII_UTILITY_LIB_\r
--- /dev/null
+/** @file\r
+ The implementation of HII expression.\r
+\r
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>\r
+ Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.\r
+\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+#include "HiiInternal.h"\r
+\r
+//\r
+// Global stack used to evaluate boolean expressions\r
+//\r
+EFI_HII_VALUE *mOpCodeScopeStack = NULL;\r
+EFI_HII_VALUE *mOpCodeScopeStackEnd = NULL;\r
+EFI_HII_VALUE *mOpCodeScopeStackPointer = NULL;\r
+\r
+//\r
+// Stack used for Suppressif/grayoutif/disableif expression list.\r
+//\r
+HII_EXPRESSION **mFormExpressionStack = NULL;\r
+HII_EXPRESSION **mFormExpressionEnd = NULL;\r
+HII_EXPRESSION **mFormExpressionPointer = NULL;\r
+\r
+HII_EXPRESSION **mStatementExpressionStack = NULL;\r
+HII_EXPRESSION **mStatementExpressionEnd = NULL;\r
+HII_EXPRESSION **mStatementExpressionPointer = NULL;\r
+\r
+HII_EXPRESSION **mOptionExpressionStack = NULL;\r
+HII_EXPRESSION **mOptionExpressionEnd = NULL;\r
+HII_EXPRESSION **mOptionExpressionPointer = NULL;\r
+\r
+//\r
+// Stack used for the sub expresion in map expression.\r
+//\r
+EFI_HII_VALUE *mCurrentExpressionStack = NULL;\r
+EFI_HII_VALUE *mCurrentExpressionEnd = NULL;\r
+EFI_HII_VALUE *mCurrentExpressionPointer = NULL;\r
+\r
+//\r
+// Stack used for the map expression list.\r
+//\r
+EFI_HII_VALUE *mMapExpressionListStack = NULL;\r
+EFI_HII_VALUE *mMapExpressionListEnd = NULL;\r
+EFI_HII_VALUE *mMapExpressionListPointer = NULL;\r
+\r
+//\r
+// Stack used for dependency expression.\r
+//\r
+HII_DEPENDENCY_EXPRESSION **mExpressionDependencyStack = NULL;\r
+HII_DEPENDENCY_EXPRESSION **mExpressionDependencyEnd = NULL;\r
+HII_DEPENDENCY_EXPRESSION **mExpressionDependencyPointer = NULL;\r
+\r
+/**\r
+ Grow size of the stack.\r
+\r
+ This is an internal function.\r
+\r
+ @param Stack On input: old stack; On output: new stack\r
+ @param StackPtr On input: old stack pointer; On output: new stack\r
+ pointer\r
+ @param StackEnd On input: old stack end; On output: new stack end\r
+\r
+ @retval EFI_SUCCESS Grow stack success.\r
+ @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.\r
+\r
+**/\r
+EFI_STATUS\r
+GrowStack (\r
+ IN OUT EFI_HII_VALUE **Stack,\r
+ IN OUT EFI_HII_VALUE **StackPtr,\r
+ IN OUT EFI_HII_VALUE **StackEnd\r
+ )\r
+{\r
+ UINTN Size;\r
+ EFI_HII_VALUE *NewStack;\r
+\r
+ Size = EXPRESSION_STACK_SIZE_INCREMENT;\r
+ if (*StackPtr != NULL) {\r
+ Size = Size + (*StackEnd - *Stack);\r
+ }\r
+\r
+ NewStack = AllocatePool (Size * sizeof (EFI_HII_VALUE));\r
+ if (NewStack == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ if (*StackPtr != NULL) {\r
+ //\r
+ // Copy from Old Stack to the New Stack\r
+ //\r
+ CopyMem (\r
+ NewStack,\r
+ *Stack,\r
+ (*StackEnd - *Stack) * sizeof (EFI_HII_VALUE)\r
+ );\r
+\r
+ //\r
+ // Free The Old Stack\r
+ //\r
+ FreePool (*Stack);\r
+ }\r
+\r
+ //\r
+ // Make the Stack pointer point to the old data in the new stack\r
+ //\r
+ *StackPtr = NewStack + (*StackPtr - *Stack);\r
+ *Stack = NewStack;\r
+ *StackEnd = NewStack + Size;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Push an element onto the Boolean Stack.\r
+\r
+ @param Stack On input: old stack; On output: new stack\r
+ @param StackPtr On input: old stack pointer; On output: new stack\r
+ pointer\r
+ @param StackEnd On input: old stack end; On output: new stack end\r
+ @param Data Data to push.\r
+\r
+ @retval EFI_SUCCESS Push stack success.\r
+\r
+**/\r
+EFI_STATUS\r
+PushStack (\r
+ IN OUT EFI_HII_VALUE **Stack,\r
+ IN OUT EFI_HII_VALUE **StackPtr,\r
+ IN OUT EFI_HII_VALUE **StackEnd,\r
+ IN EFI_HII_VALUE *Data\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Check for a stack overflow condition\r
+ //\r
+ if (*StackPtr >= *StackEnd) {\r
+ //\r
+ // Grow the stack\r
+ //\r
+ Status = GrowStack (Stack, StackPtr, StackEnd);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Push the item onto the stack\r
+ //\r
+ CopyMem (*StackPtr, Data, sizeof (EFI_HII_VALUE));\r
+ if (Data->Type == EFI_IFR_TYPE_BUFFER) {\r
+ (*StackPtr)->Buffer = AllocateCopyPool (Data->BufferLen, Data->Buffer);\r
+ if ((*StackPtr)->Buffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ }\r
+\r
+ *StackPtr = *StackPtr + 1;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Pop an element from the stack.\r
+\r
+ @param Stack On input: old stack\r
+ @param StackPtr On input: old stack pointer; On output: new stack pointer\r
+ @param Data Data to pop.\r
+\r
+ @retval EFI_SUCCESS The value was popped onto the stack.\r
+ @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
+\r
+**/\r
+EFI_STATUS\r
+PopStack (\r
+ IN EFI_HII_VALUE *Stack,\r
+ IN OUT EFI_HII_VALUE **StackPtr,\r
+ OUT EFI_HII_VALUE *Data\r
+ )\r
+{\r
+ //\r
+ // Check for a stack underflow condition\r
+ //\r
+ if (*StackPtr == Stack) {\r
+ return EFI_ACCESS_DENIED;\r
+ }\r
+\r
+ //\r
+ // Pop the item off the stack\r
+ //\r
+ *StackPtr = *StackPtr - 1;\r
+ CopyMem (Data, *StackPtr, sizeof (EFI_HII_VALUE));\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Reset stack pointer to begin of the stack.\r
+\r
+**/\r
+VOID\r
+ResetCurrentExpressionStack (\r
+ VOID\r
+ )\r
+{\r
+ mCurrentExpressionPointer = mCurrentExpressionStack;\r
+ mFormExpressionPointer = mFormExpressionStack;\r
+ mStatementExpressionPointer = mStatementExpressionStack;\r
+ mOptionExpressionPointer = mOptionExpressionStack;\r
+}\r
+\r
+/**\r
+ Push current expression onto the Stack\r
+\r
+ @param Pointer Pointer to current expression.\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushCurrentExpression (\r
+ IN VOID *Pointer\r
+ )\r
+{\r
+ EFI_HII_VALUE Data;\r
+\r
+ Data.Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+ Data.Value.u64 = (UINT64)(UINTN)Pointer;\r
+\r
+ return PushStack (\r
+ &mCurrentExpressionStack,\r
+ &mCurrentExpressionPointer,\r
+ &mCurrentExpressionEnd,\r
+ &Data\r
+ );\r
+}\r
+\r
+/**\r
+ Pop current expression from the Stack\r
+\r
+ @param Pointer Pointer to current expression to be pop.\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopCurrentExpression (\r
+ OUT VOID **Pointer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_VALUE Data;\r
+\r
+ Status = PopStack (\r
+ mCurrentExpressionStack,\r
+ &mCurrentExpressionPointer,\r
+ &Data\r
+ );\r
+\r
+ *Pointer = (VOID *)(UINTN)Data.Value.u64;\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Reset stack pointer to begin of the stack.\r
+\r
+**/\r
+VOID\r
+ResetMapExpressionListStack (\r
+ VOID\r
+ )\r
+{\r
+ mMapExpressionListPointer = mMapExpressionListStack;\r
+}\r
+\r
+/**\r
+ Grow size of the stack.\r
+\r
+ This is an internal function.\r
+\r
+ @param Stack On input: old stack; On output: new stack\r
+ @param StackPtr On input: old stack pointer; On output: new stack\r
+ pointer\r
+ @param StackEnd On input: old stack end; On output: new stack end\r
+ @param MemberSize The stack member size.\r
+\r
+ @retval EFI_SUCCESS Grow stack success.\r
+ @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.\r
+\r
+**/\r
+EFI_STATUS\r
+GrowConditionalStack (\r
+ IN OUT HII_EXPRESSION ***Stack,\r
+ IN OUT HII_EXPRESSION ***StackPtr,\r
+ IN OUT HII_EXPRESSION ***StackEnd,\r
+ IN UINTN MemberSize\r
+ )\r
+{\r
+ UINTN Size;\r
+ HII_EXPRESSION **NewStack;\r
+\r
+ Size = EXPRESSION_STACK_SIZE_INCREMENT;\r
+ if (*StackPtr != NULL) {\r
+ Size = Size + (*StackEnd - *Stack);\r
+ }\r
+\r
+ NewStack = AllocatePool (Size * MemberSize);\r
+ if (NewStack == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ if (*StackPtr != NULL) {\r
+ //\r
+ // Copy from Old Stack to the New Stack\r
+ //\r
+ CopyMem (\r
+ NewStack,\r
+ *Stack,\r
+ (*StackEnd - *Stack) * MemberSize\r
+ );\r
+\r
+ //\r
+ // Free The Old Stack\r
+ //\r
+ FreePool (*Stack);\r
+ }\r
+\r
+ //\r
+ // Make the Stack pointer point to the old data in the new stack\r
+ //\r
+ *StackPtr = NewStack + (*StackPtr - *Stack);\r
+ *Stack = NewStack;\r
+ *StackEnd = NewStack + Size;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Push an element onto the Stack.\r
+\r
+ @param Stack On input: old stack; On output: new stack\r
+ @param StackPtr On input: old stack pointer; On output: new stack\r
+ pointer\r
+ @param StackEnd On input: old stack end; On output: new stack end\r
+ @param Data Data to push.\r
+\r
+ @retval EFI_SUCCESS Push stack success.\r
+\r
+**/\r
+EFI_STATUS\r
+PushConditionalStack (\r
+ IN OUT HII_EXPRESSION ***Stack,\r
+ IN OUT HII_EXPRESSION ***StackPtr,\r
+ IN OUT HII_EXPRESSION ***StackEnd,\r
+ IN HII_EXPRESSION **Data\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Check for a stack overflow condition\r
+ //\r
+ if (*StackPtr >= *StackEnd) {\r
+ //\r
+ // Grow the stack\r
+ //\r
+ Status = GrowConditionalStack (Stack, StackPtr, StackEnd, sizeof (HII_EXPRESSION *));\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Push the item onto the stack\r
+ //\r
+ CopyMem (*StackPtr, Data, sizeof (HII_EXPRESSION *));\r
+ *StackPtr = *StackPtr + 1;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Pop an element from the stack.\r
+\r
+ @param Stack On input: old stack\r
+ @param StackPtr On input: old stack pointer; On output: new stack pointer\r
+ @param Data Data to pop.\r
+\r
+ @retval EFI_SUCCESS The value was popped onto the stack.\r
+ @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
+\r
+**/\r
+EFI_STATUS\r
+PopConditionalStack (\r
+ IN HII_EXPRESSION **Stack,\r
+ IN OUT HII_EXPRESSION ***StackPtr,\r
+ OUT HII_EXPRESSION **Data\r
+ )\r
+{\r
+ //\r
+ // Check for a stack underflow condition\r
+ //\r
+ if (*StackPtr == Stack) {\r
+ return EFI_ACCESS_DENIED;\r
+ }\r
+\r
+ //\r
+ // Pop the item off the stack\r
+ //\r
+ *StackPtr = *StackPtr - 1;\r
+ CopyMem (Data, *StackPtr, sizeof (HII_EXPRESSION *));\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Get the expression list count.\r
+\r
+ @param Level Which type this expression belong to. Form,\r
+ statement or option?\r
+\r
+ @retval >=0 The expression count\r
+ @retval -1 Input parameter error.\r
+\r
+**/\r
+INTN\r
+GetConditionalExpressionCount (\r
+ IN EXPRESS_LEVEL Level\r
+ )\r
+{\r
+ switch (Level) {\r
+ case ExpressForm:\r
+ return mFormExpressionPointer - mFormExpressionStack;\r
+ case ExpressStatement:\r
+ return mStatementExpressionPointer - mStatementExpressionStack;\r
+ case ExpressOption:\r
+ return mOptionExpressionPointer - mOptionExpressionStack;\r
+ default:\r
+ ASSERT (FALSE);\r
+ return -1;\r
+ }\r
+}\r
+\r
+/**\r
+ Get the expression Buffer pointer.\r
+\r
+ @param Level Which type this expression belong to. Form,\r
+ statement or option?\r
+\r
+ @retval The start pointer of the expression buffer or NULL.\r
+\r
+**/\r
+HII_EXPRESSION **\r
+GetConditionalExpressionList (\r
+ IN EXPRESS_LEVEL Level\r
+ )\r
+{\r
+ switch (Level) {\r
+ case ExpressForm:\r
+ return mFormExpressionStack;\r
+ case ExpressStatement:\r
+ return mStatementExpressionStack;\r
+ case ExpressOption:\r
+ return mOptionExpressionStack;\r
+ default:\r
+ ASSERT (FALSE);\r
+ return NULL;\r
+ }\r
+}\r
+\r
+/**\r
+ Push the expression options onto the Stack.\r
+\r
+ @param Pointer Pointer to the current expression.\r
+ @param Level Which type this expression belong to. Form,\r
+ statement or option?\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushConditionalExpression (\r
+ IN HII_EXPRESSION *Pointer,\r
+ IN EXPRESS_LEVEL Level\r
+ )\r
+{\r
+ switch (Level) {\r
+ case ExpressForm:\r
+ return PushConditionalStack (\r
+ &mFormExpressionStack,\r
+ &mFormExpressionPointer,\r
+ &mFormExpressionEnd,\r
+ &Pointer\r
+ );\r
+ case ExpressStatement:\r
+ return PushConditionalStack (\r
+ &mStatementExpressionStack,\r
+ &mStatementExpressionPointer,\r
+ &mStatementExpressionEnd,\r
+ &Pointer\r
+ );\r
+ case ExpressOption:\r
+ return PushConditionalStack (\r
+ &mOptionExpressionStack,\r
+ &mOptionExpressionPointer,\r
+ &mOptionExpressionEnd,\r
+ &Pointer\r
+ );\r
+ default:\r
+ ASSERT (FALSE);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+}\r
+\r
+/**\r
+ Pop the expression options from the Stack\r
+\r
+ @param Level Which type this expression belong to. Form,\r
+ statement or option?\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopConditionalExpression (\r
+ IN EXPRESS_LEVEL Level\r
+ )\r
+{\r
+ HII_EXPRESSION *Pointer;\r
+\r
+ switch (Level) {\r
+ case ExpressForm:\r
+ return PopConditionalStack (\r
+ mFormExpressionStack,\r
+ &mFormExpressionPointer,\r
+ &Pointer\r
+ );\r
+\r
+ case ExpressStatement:\r
+ return PopConditionalStack (\r
+ mStatementExpressionStack,\r
+ &mStatementExpressionPointer,\r
+ &Pointer\r
+ );\r
+\r
+ case ExpressOption:\r
+ return PopConditionalStack (\r
+ mOptionExpressionStack,\r
+ &mOptionExpressionPointer,\r
+ &Pointer\r
+ );\r
+\r
+ default:\r
+ ASSERT (FALSE);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+}\r
+\r
+/**\r
+ Push the list of map expression onto the Stack\r
+\r
+ @param Pointer Pointer to the list of map expression to be pushed.\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushMapExpressionList (\r
+ IN VOID *Pointer\r
+ )\r
+{\r
+ EFI_HII_VALUE Data;\r
+\r
+ Data.Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+ Data.Value.u64 = (UINT64)(UINTN)Pointer;\r
+\r
+ return PushStack (\r
+ &mMapExpressionListStack,\r
+ &mMapExpressionListPointer,\r
+ &mMapExpressionListEnd,\r
+ &Data\r
+ );\r
+}\r
+\r
+/**\r
+ Pop the list of map expression from the Stack\r
+\r
+ @param Pointer Pointer to the list of map expression to be pop.\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopMapExpressionList (\r
+ OUT VOID **Pointer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_VALUE Data;\r
+\r
+ Status = PopStack (\r
+ mMapExpressionListStack,\r
+ &mMapExpressionListPointer,\r
+ &Data\r
+ );\r
+\r
+ *Pointer = (VOID *)(UINTN)Data.Value.u64;\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Reset stack pointer to begin of the stack.\r
+\r
+**/\r
+VOID\r
+ResetScopeStack (\r
+ VOID\r
+ )\r
+{\r
+ mOpCodeScopeStackPointer = mOpCodeScopeStack;\r
+}\r
+\r
+/**\r
+ Push an Operand onto the Stack\r
+\r
+ @param Operand Operand to push.\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
+ stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushScope (\r
+ IN UINT8 Operand\r
+ )\r
+{\r
+ EFI_HII_VALUE Data;\r
+\r
+ Data.Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
+ Data.Value.u8 = Operand;\r
+\r
+ return PushStack (\r
+ &mOpCodeScopeStack,\r
+ &mOpCodeScopeStackPointer,\r
+ &mOpCodeScopeStackEnd,\r
+ &Data\r
+ );\r
+}\r
+\r
+/**\r
+ Pop an Operand from the Stack\r
+\r
+ @param Operand Operand to pop.\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
+ stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopScope (\r
+ OUT UINT8 *Operand\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_VALUE Data;\r
+\r
+ Status = PopStack (\r
+ mOpCodeScopeStack,\r
+ &mOpCodeScopeStackPointer,\r
+ &Data\r
+ );\r
+\r
+ *Operand = Data.Value.u8;\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Grow size of the stack for Expression Dependencies.\r
+\r
+ This is an internal function.\r
+\r
+ @param Stack On input: old stack; On output: new stack\r
+ @param StackPtr On input: old stack pointer; On output: new stack\r
+ pointer\r
+ @param StackEnd On input: old stack end; On output: new stack end\r
+\r
+ @retval EFI_SUCCESS Grow Dependency stack success.\r
+ @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.\r
+\r
+**/\r
+EFI_STATUS\r
+GrowDependencyStack (\r
+ IN OUT HII_DEPENDENCY_EXPRESSION ***Stack,\r
+ IN OUT HII_DEPENDENCY_EXPRESSION ***StackPtr,\r
+ IN OUT HII_DEPENDENCY_EXPRESSION ***StackEnd\r
+ )\r
+{\r
+ UINTN Size;\r
+ HII_DEPENDENCY_EXPRESSION **NewStack;\r
+\r
+ Size = EXPRESSION_STACK_SIZE_INCREMENT;\r
+ if (*StackPtr != NULL) {\r
+ Size = Size + (*StackEnd - *Stack);\r
+ }\r
+\r
+ NewStack = AllocatePool (Size * sizeof (HII_DEPENDENCY_EXPRESSION *));\r
+ if (NewStack == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ if (*StackPtr != NULL) {\r
+ //\r
+ // Copy from Old Stack to the New Stack\r
+ //\r
+ CopyMem (\r
+ NewStack,\r
+ *Stack,\r
+ (*StackEnd - *Stack) * sizeof (HII_DEPENDENCY_EXPRESSION *)\r
+ );\r
+\r
+ //\r
+ // Free The Old Stack\r
+ //\r
+ FreePool (*Stack);\r
+ }\r
+\r
+ //\r
+ // Make the Stack pointer point to the old data in the new stack\r
+ //\r
+ *StackPtr = NewStack + (*StackPtr - *Stack);\r
+ *Stack = NewStack;\r
+ *StackEnd = NewStack + Size;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Push an element onto the Stack for Expression Dependencies.\r
+\r
+ @param Stack On input: old stack; On output: new stack\r
+ @param StackPtr On input: old stack pointer; On output: new stack\r
+ pointer\r
+ @param StackEnd On input: old stack end; On output: new stack end\r
+ @param Data Data to push.\r
+\r
+ @retval EFI_SUCCESS Push stack success.\r
+\r
+**/\r
+EFI_STATUS\r
+PushDependencyStack (\r
+ IN OUT HII_DEPENDENCY_EXPRESSION ***Stack,\r
+ IN OUT HII_DEPENDENCY_EXPRESSION ***StackPtr,\r
+ IN OUT HII_DEPENDENCY_EXPRESSION ***StackEnd,\r
+ IN HII_DEPENDENCY_EXPRESSION **Data\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Check for a stack overflow condition\r
+ //\r
+ if (*StackPtr >= *StackEnd) {\r
+ //\r
+ // Grow the stack\r
+ //\r
+ Status = GrowDependencyStack (Stack, StackPtr, StackEnd);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Push the item onto the stack\r
+ //\r
+ CopyMem (*StackPtr, Data, sizeof (HII_DEPENDENCY_EXPRESSION *));\r
+ *StackPtr = *StackPtr + 1;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Pop the Expression Dependency options from the Stack\r
+\r
+ @param Stack On input: old stack; On output: new stack\r
+ @param StackPtr On input: old stack pointer; On output: new stack\r
+ pointer\r
+ @param Data Data to push.\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopDependencyStack (\r
+ IN HII_DEPENDENCY_EXPRESSION **Stack,\r
+ IN OUT HII_DEPENDENCY_EXPRESSION ***StackPtr,\r
+ OUT HII_DEPENDENCY_EXPRESSION **Data\r
+ )\r
+{\r
+ //\r
+ // Check for a stack underflow condition\r
+ //\r
+ if (*StackPtr == Stack) {\r
+ return EFI_ACCESS_DENIED;\r
+ }\r
+\r
+ //\r
+ // Pop the item off the stack\r
+ //\r
+ *StackPtr = *StackPtr - 1;\r
+ CopyMem (Data, *StackPtr, sizeof (HII_DEPENDENCY_EXPRESSION *));\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Push the list of Expression Dependencies onto the Stack\r
+\r
+ @param Pointer Pointer to the list of map expression to be pushed.\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushDependencyExpDes (\r
+ IN HII_DEPENDENCY_EXPRESSION **Pointer\r
+ )\r
+{\r
+ return PushDependencyStack (\r
+ &mExpressionDependencyStack,\r
+ &mExpressionDependencyPointer,\r
+ &mExpressionDependencyEnd,\r
+ Pointer\r
+ );\r
+}\r
+\r
+/**\r
+ Pop the list of Expression Dependencies from the Stack\r
+\r
+ @param Pointer Pointer to the list of map expression to be pop.\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopDependencyExpDes (\r
+ OUT HII_DEPENDENCY_EXPRESSION **Pointer\r
+ )\r
+{\r
+ return PopDependencyStack (\r
+ mExpressionDependencyStack,\r
+ &mExpressionDependencyPointer,\r
+ Pointer\r
+ );\r
+}\r
+\r
+/**\r
+ Retrieve dependencies within an expression. These dependencies can express how\r
+ this expression will be evaluated.\r
+\r
+ @param[in,out] Expression Expression to retrieve dependencies.\r
+\r
+ @retval EFI_SUCCESS The dependencies were successfully retrieved.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory.\r
+\r
+**/\r
+EFI_STATUS\r
+GetHiiExpressionDependency (\r
+ IN OUT HII_EXPRESSION *Expression\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ HII_EXPRESSION_OPCODE *ExpressionOpCode;\r
+ HII_DEPENDENCY_EXPRESSION *DepExpressionOpCode;\r
+ LIST_ENTRY *SubExpressionLink;\r
+ HII_EXPRESSION *SubExpression;\r
+ UINT8 MapPairCount;\r
+\r
+ Link = GetFirstNode (&Expression->OpCodeListHead);\r
+ while (!IsNull (&Expression->OpCodeListHead, Link)) {\r
+ ExpressionOpCode = HII_EXPRESSION_OPCODE_FROM_LINK (Link);\r
+ Link = GetNextNode (&Expression->OpCodeListHead, Link);\r
+ Status = EFI_SUCCESS;\r
+\r
+ DepExpressionOpCode = (HII_DEPENDENCY_EXPRESSION *)AllocateZeroPool (sizeof (HII_DEPENDENCY_EXPRESSION));\r
+ if (DepExpressionOpCode == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ switch (ExpressionOpCode->Operand) {\r
+ //\r
+ // Constant\r
+ //\r
+ case EFI_IFR_FALSE_OP:\r
+ case EFI_IFR_ONE_OP:\r
+ case EFI_IFR_ONES_OP:\r
+ case EFI_IFR_TRUE_OP:\r
+ case EFI_IFR_UINT8_OP:\r
+ case EFI_IFR_UINT16_OP:\r
+ case EFI_IFR_UINT32_OP:\r
+ case EFI_IFR_UINT64_OP:\r
+ case EFI_IFR_UNDEFINED_OP:\r
+ case EFI_IFR_VERSION_OP:\r
+ case EFI_IFR_ZERO_OP:\r
+ DepExpressionOpCode->ConstantExp.Operand = ExpressionOpCode->Operand;\r
+ CopyMem (&DepExpressionOpCode->ConstantExp.Value, &ExpressionOpCode->ExtraData.Value, sizeof (EFI_HII_VALUE));\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ //\r
+ // Built-in functions\r
+ //\r
+ case EFI_IFR_DUP_OP:\r
+ DepExpressionOpCode->DupExp.Operand = ExpressionOpCode->Operand;\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_EQ_ID_VAL_OP:\r
+ DepExpressionOpCode->EqIdValExp.Operand = ExpressionOpCode->Operand;\r
+ CopyMem (&DepExpressionOpCode->EqIdValExp.QuestionId, &ExpressionOpCode->ExtraData.EqIdValData.QuestionId, sizeof (EFI_QUESTION_ID));\r
+ CopyMem (&DepExpressionOpCode->EqIdValExp.Value, &ExpressionOpCode->ExtraData.EqIdValData.Value, sizeof (EFI_HII_VALUE));\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_EQ_ID_ID_OP:\r
+ DepExpressionOpCode->EqIdIdExp.Operand = ExpressionOpCode->Operand;\r
+ CopyMem (&DepExpressionOpCode->EqIdIdExp.QuestionId1, &ExpressionOpCode->ExtraData.EqIdIdData.QuestionId1, sizeof (EFI_QUESTION_ID));\r
+ CopyMem (&DepExpressionOpCode->EqIdIdExp.QuestionId2, &ExpressionOpCode->ExtraData.EqIdIdData.QuestionId2, sizeof (EFI_QUESTION_ID));\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_EQ_ID_VAL_LIST_OP:\r
+ DepExpressionOpCode->EqIdListExp.Operand = ExpressionOpCode->Operand;\r
+ DepExpressionOpCode->EqIdListExp.ListLength = ExpressionOpCode->ExtraData.EqIdListData.ListLength;\r
+ CopyMem (&DepExpressionOpCode->EqIdListExp.QuestionId, &ExpressionOpCode->ExtraData.EqIdListData.QuestionId, sizeof (EFI_QUESTION_ID));\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ DepExpressionOpCode->EqIdListExp.ValueList = AllocateCopyPool (\r
+ DepExpressionOpCode->EqIdListExp.ListLength * sizeof (UINT16),\r
+ ExpressionOpCode->ExtraData.EqIdListData.ValueList\r
+ );\r
+ if (DepExpressionOpCode->EqIdListExp.ValueList == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_GET_OP:\r
+ DepExpressionOpCode->GetExp.Operand = ExpressionOpCode->Operand;\r
+ DepExpressionOpCode->GetExp.VarStorage = ExpressionOpCode->ExtraData.GetSetData.VarStorage;\r
+ CopyMem (&DepExpressionOpCode->GetExp.VarStoreInfo.VarName, &ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo.VarName, sizeof (EFI_STRING_ID));\r
+ CopyMem (&DepExpressionOpCode->GetExp.VarStoreInfo.VarOffset, &ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset, sizeof (UINT16));\r
+ DepExpressionOpCode->GetExp.VarStoreInfo = ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo;\r
+ if (ExpressionOpCode->ExtraData.GetSetData.ValueName != NULL) {\r
+ DepExpressionOpCode->GetExp.ValueName = (CHAR16 *)AllocateCopyPool (sizeof (ExpressionOpCode->ExtraData.GetSetData.ValueName), ExpressionOpCode->ExtraData.GetSetData.ValueName);\r
+ if (DepExpressionOpCode->GetExp.ValueName == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ }\r
+\r
+ DepExpressionOpCode->GetExp.ValueType = ExpressionOpCode->ExtraData.GetSetData.ValueType;\r
+ DepExpressionOpCode->GetExp.ValueWidth = ExpressionOpCode->ExtraData.GetSetData.ValueWidth;\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_QUESTION_REF1_OP:\r
+ DepExpressionOpCode->QuestionRef1Exp.Operand = ExpressionOpCode->Operand;\r
+ CopyMem (&DepExpressionOpCode->QuestionRef1Exp.QuestionId, &ExpressionOpCode->ExtraData.QuestionRef1Data.QuestionId, sizeof (EFI_QUESTION_ID));\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_RULE_REF_OP:\r
+ DepExpressionOpCode->RuleRefExp.Operand = ExpressionOpCode->Operand;\r
+ DepExpressionOpCode->RuleRefExp.RuleId = ExpressionOpCode->ExtraData.RuleId;\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_STRING_REF1_OP:\r
+ DepExpressionOpCode->StringRef1Exp.Operand = ExpressionOpCode->Operand;\r
+ CopyMem (&DepExpressionOpCode->StringRef1Exp.Value.Value.string, &ExpressionOpCode->ExtraData.Value.Value.string, sizeof (EFI_STRING_ID));\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_THIS_OP:\r
+ DepExpressionOpCode->ThisExp.Operand = ExpressionOpCode->Operand;\r
+ CopyMem (&DepExpressionOpCode->ThisExp.QuestionId, &ExpressionOpCode->ExtraData.QuestionRef1Data.QuestionId, sizeof (EFI_QUESTION_ID));\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_SECURITY_OP:\r
+ DepExpressionOpCode->SecurityExp.Operand = ExpressionOpCode->Operand;\r
+ CopyMem (&DepExpressionOpCode->SecurityExp.Permissions, &ExpressionOpCode->ExtraData.Guid, sizeof (EFI_GUID));\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ //\r
+ // unary-op\r
+ //\r
+ case EFI_IFR_LENGTH_OP:\r
+ DepExpressionOpCode->LengthExp.Operand = ExpressionOpCode->Operand;\r
+ PopDependencyExpDes (&DepExpressionOpCode->LengthExp.SubExpression);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_NOT_OP:\r
+ DepExpressionOpCode->NotExp.Operand = ExpressionOpCode->Operand;\r
+ PopDependencyExpDes (&DepExpressionOpCode->NotExp.SubExpression);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_BITWISE_NOT_OP:\r
+ DepExpressionOpCode->BitWiseNotExp.Operand = ExpressionOpCode->Operand;\r
+ PopDependencyExpDes (&DepExpressionOpCode->BitWiseNotExp.SubExpression);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_QUESTION_REF2_OP:\r
+ DepExpressionOpCode->QuestionRef2Exp.Operand = ExpressionOpCode->Operand;\r
+ PopDependencyExpDes (&DepExpressionOpCode->QuestionRef2Exp.SubExpression);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_QUESTION_REF3_OP:\r
+ DepExpressionOpCode->QuestionRef3Exp.Operand = ExpressionOpCode->Operand;\r
+ CopyMem (&DepExpressionOpCode->QuestionRef3Exp.DevicePath, &ExpressionOpCode->ExtraData.QuestionRef3Data.DevicePath, sizeof (EFI_DEVICE_PATH));\r
+ CopyMem (&DepExpressionOpCode->QuestionRef3Exp.Guid, &ExpressionOpCode->ExtraData.QuestionRef3Data.Guid, sizeof (EFI_GUID));\r
+ PopDependencyExpDes (&DepExpressionOpCode->QuestionRef3Exp.SubExpression);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_SET_OP:\r
+ DepExpressionOpCode->SetExp.Operand = ExpressionOpCode->Operand;\r
+ DepExpressionOpCode->SetExp.VarStorage = ExpressionOpCode->ExtraData.GetSetData.VarStorage;\r
+ CopyMem (&DepExpressionOpCode->SetExp.VarStoreInfo.VarName, &ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo.VarName, sizeof (EFI_STRING_ID));\r
+ CopyMem (&DepExpressionOpCode->SetExp.VarStoreInfo.VarOffset, &ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset, sizeof (UINT16));\r
+ DepExpressionOpCode->SetExp.VarStoreInfo = ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo;\r
+ if (ExpressionOpCode->ExtraData.GetSetData.ValueName != NULL) {\r
+ DepExpressionOpCode->SetExp.ValueName = (CHAR16 *)AllocateCopyPool (sizeof (ExpressionOpCode->ExtraData.GetSetData.ValueName), ExpressionOpCode->ExtraData.GetSetData.ValueName);\r
+ if (DepExpressionOpCode->SetExp.ValueName == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ }\r
+\r
+ DepExpressionOpCode->SetExp.ValueType = ExpressionOpCode->ExtraData.GetSetData.ValueType;\r
+ DepExpressionOpCode->SetExp.ValueWidth = ExpressionOpCode->ExtraData.GetSetData.ValueWidth;\r
+ PopDependencyExpDes (&DepExpressionOpCode->SetExp.SubExpression);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_STRING_REF2_OP:\r
+ DepExpressionOpCode->StringRef2Exp.Operand = ExpressionOpCode->Operand;\r
+ PopDependencyExpDes (&DepExpressionOpCode->StringRef2Exp.SubExpression);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_TO_BOOLEAN_OP:\r
+ DepExpressionOpCode->ToBooleanExp.Operand = ExpressionOpCode->Operand;\r
+ PopDependencyExpDes (&DepExpressionOpCode->ToBooleanExp.SubExpression);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_TO_STRING_OP:\r
+ DepExpressionOpCode->ToStringExp.Operand = ExpressionOpCode->Operand;\r
+ DepExpressionOpCode->ToStringExp.Format = ExpressionOpCode->ExtraData.Format;\r
+ PopDependencyExpDes (&DepExpressionOpCode->ToStringExp.SubExpression);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_TO_UINT_OP:\r
+ DepExpressionOpCode->ToUintExp.Operand = ExpressionOpCode->Operand;\r
+ PopDependencyExpDes (&DepExpressionOpCode->ToUintExp.SubExpression);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_TO_LOWER_OP:\r
+ DepExpressionOpCode->ToLowerExp.Operand = ExpressionOpCode->Operand;\r
+ PopDependencyExpDes (&DepExpressionOpCode->ToLowerExp.SubExpression);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_TO_UPPER_OP:\r
+ DepExpressionOpCode->ToUpperExp.Operand = ExpressionOpCode->Operand;\r
+ PopDependencyExpDes (&DepExpressionOpCode->ToUpperExp.SubExpression);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ //\r
+ // binary-op\r
+ //\r
+ case EFI_IFR_ADD_OP:\r
+ DepExpressionOpCode->AddExp.Operand = ExpressionOpCode->Operand;\r
+ PopDependencyExpDes (&DepExpressionOpCode->AddExp.LeftHandExp);\r
+ PopDependencyExpDes (&DepExpressionOpCode->AddExp.RightHandExp);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_AND_OP:\r
+ DepExpressionOpCode->AndExp.Operand = ExpressionOpCode->Operand;\r
+ PopDependencyExpDes (&DepExpressionOpCode->AndExp.SubExpression1);\r
+ PopDependencyExpDes (&DepExpressionOpCode->AndExp.SubExpression2);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_BITWISE_AND_OP:\r
+ DepExpressionOpCode->BitwiseAndExp.Operand = ExpressionOpCode->Operand;\r
+ PopDependencyExpDes (&DepExpressionOpCode->BitwiseAndExp.SubExpression1);\r
+ PopDependencyExpDes (&DepExpressionOpCode->BitwiseAndExp.SubExpression2);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_BITWISE_OR_OP:\r
+ DepExpressionOpCode->BitwiseOrExp.Operand = ExpressionOpCode->Operand;\r
+ PopDependencyExpDes (&DepExpressionOpCode->BitwiseOrExp.SubExpression1);\r
+ PopDependencyExpDes (&DepExpressionOpCode->BitwiseOrExp.SubExpression2);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_CATENATE_OP:\r
+ DepExpressionOpCode->CatenateExp.Operand = ExpressionOpCode->Operand;\r
+ PopDependencyExpDes (&DepExpressionOpCode->CatenateExp.LeftStringExp);\r
+ PopDependencyExpDes (&DepExpressionOpCode->CatenateExp.RightStringExp);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_DIVIDE_OP:\r
+ DepExpressionOpCode->DivExp.Operand = ExpressionOpCode->Operand;\r
+ PopDependencyExpDes (&DepExpressionOpCode->DivExp.LeftHandExp);\r
+ PopDependencyExpDes (&DepExpressionOpCode->DivExp.RightHandExp);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_EQUAL_OP:\r
+ DepExpressionOpCode->EqualExp.Operand = ExpressionOpCode->Operand;\r
+ PopDependencyExpDes (&DepExpressionOpCode->EqualExp.SubExpression1);\r
+ PopDependencyExpDes (&DepExpressionOpCode->EqualExp.SubExpression2);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_GREATER_EQUAL_OP:\r
+ DepExpressionOpCode->GreaterEqualExp.Operand = ExpressionOpCode->Operand;\r
+ PopDependencyExpDes (&DepExpressionOpCode->GreaterEqualExp.LeftHandExp);\r
+ PopDependencyExpDes (&DepExpressionOpCode->GreaterEqualExp.RightHandExp);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_GREATER_THAN_OP:\r
+ DepExpressionOpCode->GreaterThanExp.Operand = ExpressionOpCode->Operand;\r
+ PopDependencyExpDes (&DepExpressionOpCode->GreaterThanExp.LeftHandExp);\r
+ PopDependencyExpDes (&DepExpressionOpCode->GreaterThanExp.RightHandExp);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_LESS_EQUAL_OP:\r
+ DepExpressionOpCode->LessEqualExp.Operand = ExpressionOpCode->Operand;\r
+ PopDependencyExpDes (&DepExpressionOpCode->LessEqualExp.LeftHandExp);\r
+ PopDependencyExpDes (&DepExpressionOpCode->LessEqualExp.RightHandExp);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_LESS_THAN_OP:\r
+ DepExpressionOpCode->LessThanExp.Operand = ExpressionOpCode->Operand;\r
+ PopDependencyExpDes (&DepExpressionOpCode->LessThanExp.LeftHandExp);\r
+ PopDependencyExpDes (&DepExpressionOpCode->LessThanExp.RightHandExp);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_MATCH_OP:\r
+ DepExpressionOpCode->MatchExp.Operand = ExpressionOpCode->Operand;\r
+ PopDependencyExpDes (&DepExpressionOpCode->MatchExp.PatternExp);\r
+ PopDependencyExpDes (&DepExpressionOpCode->MatchExp.StringExp);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_MATCH2_OP:\r
+ DepExpressionOpCode->Match2Exp.Operand = ExpressionOpCode->Operand;\r
+ CopyMem (&DepExpressionOpCode->Match2Exp.SyntaxType, &ExpressionOpCode->ExtraData.Guid, sizeof (EFI_GUID));\r
+ PopDependencyExpDes (&DepExpressionOpCode->Match2Exp.PatternExp);\r
+ PopDependencyExpDes (&DepExpressionOpCode->Match2Exp.StringExp);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_MODULO_OP:\r
+ DepExpressionOpCode->ModExp.Operand = ExpressionOpCode->Operand;\r
+ PopDependencyExpDes (&DepExpressionOpCode->ModExp.LeftHandExp);\r
+ PopDependencyExpDes (&DepExpressionOpCode->ModExp.RightHandExp);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_MULTIPLY_OP:\r
+ DepExpressionOpCode->MultExp.Operand = ExpressionOpCode->Operand;\r
+ PopDependencyExpDes (&DepExpressionOpCode->MultExp.LeftHandExp);\r
+ PopDependencyExpDes (&DepExpressionOpCode->MultExp.RightHandExp);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_NOT_EQUAL_OP:\r
+ DepExpressionOpCode->NotEqualExp.Operand = ExpressionOpCode->Operand;\r
+ PopDependencyExpDes (&DepExpressionOpCode->NotEqualExp.SubExpression1);\r
+ PopDependencyExpDes (&DepExpressionOpCode->NotEqualExp.SubExpression2);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_OR_OP:\r
+ DepExpressionOpCode->OrExp.Operand = ExpressionOpCode->Operand;\r
+ PopDependencyExpDes (&DepExpressionOpCode->OrExp.SubExpression1);\r
+ PopDependencyExpDes (&DepExpressionOpCode->OrExp.SubExpression2);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_SHIFT_LEFT_OP:\r
+ DepExpressionOpCode->ShiftLeftExp.Operand = ExpressionOpCode->Operand;\r
+ PopDependencyExpDes (&DepExpressionOpCode->ShiftLeftExp.LeftHandExp);\r
+ PopDependencyExpDes (&DepExpressionOpCode->ShiftLeftExp.RightHandExp);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_SHIFT_RIGHT_OP:\r
+ DepExpressionOpCode->ShiftRightExp.Operand = ExpressionOpCode->Operand;\r
+ PopDependencyExpDes (&DepExpressionOpCode->ShiftRightExp.LeftHandExp);\r
+ PopDependencyExpDes (&DepExpressionOpCode->ShiftRightExp.RightHandExp);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_SUBTRACT_OP:\r
+ DepExpressionOpCode->SubtractExp.Operand = ExpressionOpCode->Operand;\r
+ PopDependencyExpDes (&DepExpressionOpCode->SubtractExp.LeftHandExp);\r
+ PopDependencyExpDes (&DepExpressionOpCode->SubtractExp.RightHandExp);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ //\r
+ // ternary-op\r
+ //\r
+ case EFI_IFR_CONDITIONAL_OP:\r
+ DepExpressionOpCode->ConditionalExp.Operand = ExpressionOpCode->Operand;\r
+ PopDependencyExpDes (&DepExpressionOpCode->ConditionalExp.CondTrueValExp);\r
+ PopDependencyExpDes (&DepExpressionOpCode->ConditionalExp.CondFalseValExp);\r
+ PopDependencyExpDes (&DepExpressionOpCode->ConditionalExp.ConditionExp);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_FIND_OP:\r
+ DepExpressionOpCode->FindExp.Operand = ExpressionOpCode->Operand;\r
+ PopDependencyExpDes (&DepExpressionOpCode->FindExp.StringToSearchExp);\r
+ PopDependencyExpDes (&DepExpressionOpCode->FindExp.StringToCompWithExp);\r
+ PopDependencyExpDes (&DepExpressionOpCode->FindExp.IndexExp);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_MID_OP:\r
+ DepExpressionOpCode->MidExp.Operand = ExpressionOpCode->Operand;\r
+ PopDependencyExpDes (&DepExpressionOpCode->MidExp.StringOrBufferExp);\r
+ PopDependencyExpDes (&DepExpressionOpCode->MidExp.IndexExp);\r
+ PopDependencyExpDes (&DepExpressionOpCode->MidExp.LengthExp);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_TOKEN_OP:\r
+ DepExpressionOpCode->TokenExp.Operand = ExpressionOpCode->Operand;\r
+ PopDependencyExpDes (&DepExpressionOpCode->TokenExp.StringToSearchExp);\r
+ PopDependencyExpDes (&DepExpressionOpCode->TokenExp.DelimiterExp);\r
+ PopDependencyExpDes (&DepExpressionOpCode->TokenExp.IndexExp);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ case EFI_IFR_SPAN_OP:\r
+ DepExpressionOpCode->SpanExp.Operand = ExpressionOpCode->Operand;\r
+ PopDependencyExpDes (&DepExpressionOpCode->SpanExp.StringToSearchExp);\r
+ PopDependencyExpDes (&DepExpressionOpCode->SpanExp.CharsetExp);\r
+ PopDependencyExpDes (&DepExpressionOpCode->SpanExp.IndexExp);\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ //\r
+ // Map\r
+ //\r
+ case EFI_IFR_MAP_OP:\r
+ //\r
+ // Go through map expression list.\r
+ //\r
+ DepExpressionOpCode->MapExp.Operand = ExpressionOpCode->Operand;\r
+ MapPairCount = 0;\r
+ SubExpressionLink = GetFirstNode (&ExpressionOpCode->MapExpressionList);\r
+ while (!IsNull (&ExpressionOpCode->MapExpressionList, SubExpressionLink)) {\r
+ MapPairCount++;\r
+ SubExpressionLink = GetNextNode (&ExpressionOpCode->MapExpressionList, SubExpressionLink);\r
+ if (IsNull (&ExpressionOpCode->MapExpressionList, SubExpressionLink)) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Goto the first expression on next pair.\r
+ //\r
+ SubExpressionLink = GetNextNode (&ExpressionOpCode->MapExpressionList, SubExpressionLink);\r
+ }\r
+\r
+ DepExpressionOpCode->MapExp.ExpPair = (HII_DEPENDENCY_EXPRESSION_PAIR *)AllocateZeroPool (\r
+ MapPairCount * sizeof (HII_DEPENDENCY_EXPRESSION_PAIR)\r
+ );\r
+ if (DepExpressionOpCode->MapExp.ExpPair == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+\r
+ DepExpressionOpCode->MapExp.ExpPairNo = MapPairCount;\r
+ MapPairCount = 0;\r
+ PopDependencyExpDes (&DepExpressionOpCode->MapExp.SubExp);\r
+\r
+ //\r
+ // Go through map expression list.\r
+ //\r
+ SubExpressionLink = GetFirstNode (&ExpressionOpCode->MapExpressionList);\r
+ while (!IsNull (&ExpressionOpCode->MapExpressionList, SubExpressionLink)) {\r
+ SubExpression = HII_EXPRESSION_FROM_LINK (SubExpressionLink);\r
+ //\r
+ // Get the first expression description in this pair.\r
+ //\r
+ GetHiiExpressionDependency (SubExpression);\r
+ DepExpressionOpCode->MapExp.ExpPair[MapPairCount].MatchExp = SubExpression->RootDependencyExp;\r
+\r
+ //\r
+ // Get the second expression description in this pair.\r
+ //\r
+ SubExpressionLink = GetNextNode (&ExpressionOpCode->MapExpressionList, SubExpressionLink);\r
+ SubExpression = HII_EXPRESSION_FROM_LINK (SubExpressionLink);\r
+ GetHiiExpressionDependency (SubExpression);\r
+ DepExpressionOpCode->MapExp.ExpPair[MapPairCount].ReturnExp = SubExpression->RootDependencyExp;\r
+ //\r
+ // Goto the first expression on next pair.\r
+ //\r
+ SubExpressionLink = GetNextNode (&ExpressionOpCode->MapExpressionList, SubExpressionLink);\r
+ MapPairCount++;\r
+ }\r
+\r
+ PushDependencyExpDes (&DepExpressionOpCode);\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+\r
+ PopDependencyExpDes (&Expression->RootDependencyExp);\r
+\r
+Done:\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Return the result of the expression list. Check the expression list and\r
+ return the highest priority express result.\r
+ Priority: DisableIf > SuppressIf > GrayOutIf > FALSE\r
+\r
+ @param[in] ExpList The input expression list.\r
+ @param[in] Evaluate Whether need to evaluate the expression first.\r
+ @param[in] FormSet FormSet associated with this expression.\r
+ @param[in] Form Form associated with this expression.\r
+\r
+ @retval EXPRESS_RESULT Return the higher priority express result.\r
+ DisableIf > SuppressIf > GrayOutIf > FALSE\r
+\r
+**/\r
+EXPRESS_RESULT\r
+EvaluateExpressionList (\r
+ IN HII_EXPRESSION_LIST *ExpList,\r
+ IN BOOLEAN Evaluate,\r
+ IN HII_FORMSET *FormSet OPTIONAL,\r
+ IN HII_FORM *Form OPTIONAL\r
+ )\r
+{\r
+ UINTN Index;\r
+ EXPRESS_RESULT ReturnVal;\r
+ EXPRESS_RESULT CompareOne;\r
+ EFI_STATUS Status;\r
+\r
+ if (ExpList == NULL) {\r
+ return ExpressFalse;\r
+ }\r
+\r
+ ASSERT (ExpList->Signature == HII_EXPRESSION_LIST_SIGNATURE);\r
+ Index = 0;\r
+\r
+ //\r
+ // Check whether need to evaluate the expression first.\r
+ //\r
+ if (Evaluate) {\r
+ while (ExpList->Count > Index) {\r
+ Status = EvaluateHiiExpression (FormSet, Form, ExpList->Expression[Index++]);\r
+ if (EFI_ERROR (Status)) {\r
+ return ExpressFalse;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Run the list of expressions.\r
+ //\r
+ ReturnVal = ExpressFalse;\r
+ for (Index = 0; Index < ExpList->Count; Index++) {\r
+ if (IsHiiValueTrue (&ExpList->Expression[Index]->Result)) {\r
+ switch (ExpList->Expression[Index]->Type) {\r
+ case EFI_HII_EXPRESSION_SUPPRESS_IF:\r
+ CompareOne = ExpressSuppress;\r
+ break;\r
+\r
+ case EFI_HII_EXPRESSION_GRAY_OUT_IF:\r
+ CompareOne = ExpressGrayOut;\r
+ break;\r
+\r
+ case EFI_HII_EXPRESSION_DISABLE_IF:\r
+ CompareOne = ExpressDisable;\r
+ break;\r
+\r
+ default:\r
+ return ExpressFalse;\r
+ }\r
+\r
+ ReturnVal = ReturnVal < CompareOne ? CompareOne : ReturnVal;\r
+ }\r
+ }\r
+\r
+ return ReturnVal;\r
+}\r
--- /dev/null
+/** @file\r
+ Definitions of Hii Expression.\r
+\r
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>\r
+ Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.\r
+\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#ifndef HII_EXPRESSION_H_\r
+#define HII_EXPRESSION_H_\r
+\r
+#include <Library/HiiUtilityLib.h>\r
+\r
+/**\r
+ Get the expression list count.\r
+\r
+ @param[in] Level Which type this expression belong to. Form,\r
+ statement or option?\r
+\r
+ @retval >=0 The expression count\r
+ @retval -1 Input parameter error.\r
+\r
+**/\r
+INTN\r
+GetConditionalExpressionCount (\r
+ IN EXPRESS_LEVEL Level\r
+ );\r
+\r
+/**\r
+ Get the expression Buffer pointer.\r
+\r
+ @param[in] Level Which type this expression belong to. Form,\r
+ statement or option?\r
+\r
+ @retval The start pointer of the expression buffer or NULL.\r
+\r
+**/\r
+HII_EXPRESSION **\r
+GetConditionalExpressionList (\r
+ IN EXPRESS_LEVEL Level\r
+ );\r
+\r
+/**\r
+ Push the expression options onto the Stack.\r
+\r
+ @param[in] Pointer Pointer to the current expression.\r
+ @param[in] Level Which type this expression belong to. Form,\r
+ statement or option?\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushConditionalExpression (\r
+ IN HII_EXPRESSION *Pointer,\r
+ IN EXPRESS_LEVEL Level\r
+ );\r
+\r
+/**\r
+ Pop the expression options from the Stack\r
+\r
+ @param[in] Level Which type this expression belong to. Form,\r
+ statement or option?\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopConditionalExpression (\r
+ IN EXPRESS_LEVEL Level\r
+ );\r
+\r
+/**\r
+ Reset stack pointer to begin of the stack.\r
+\r
+**/\r
+VOID\r
+ResetCurrentExpressionStack (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Push current expression onto the Stack\r
+\r
+ @param[in] Pointer Pointer to current expression.\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushCurrentExpression (\r
+ IN VOID *Pointer\r
+ );\r
+\r
+/**\r
+ Pop current expression from the Stack\r
+\r
+ @param[in] Pointer Pointer to current expression to be pop.\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopCurrentExpression (\r
+ OUT VOID **Pointer\r
+ );\r
+\r
+/**\r
+ Reset stack pointer to begin of the stack.\r
+\r
+**/\r
+VOID\r
+ResetMapExpressionListStack (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Push the list of map expression onto the Stack\r
+\r
+ @param[in] Pointer Pointer to the list of map expression to be pushed.\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushMapExpressionList (\r
+ IN VOID *Pointer\r
+ );\r
+\r
+/**\r
+ Pop the list of map expression from the Stack\r
+\r
+ @param[in] Pointer Pointer to the list of map expression to be pop.\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopMapExpressionList (\r
+ OUT VOID **Pointer\r
+ );\r
+\r
+/**\r
+ Reset stack pointer to begin of the stack.\r
+\r
+**/\r
+VOID\r
+ResetScopeStack (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Push an Operand onto the Stack\r
+\r
+ @param[in] Operand Operand to push.\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
+ stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushScope (\r
+ IN UINT8 Operand\r
+ );\r
+\r
+/**\r
+ Pop an Operand from the Stack\r
+\r
+ @param[out] Operand Operand to pop.\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
+ stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopScope (\r
+ OUT UINT8 *Operand\r
+ );\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ The implementation of HII IFR parser.\r
+\r
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>\r
+ Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.\r
+\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include "HiiInternal.h"\r
+\r
+/**\r
+ Initialize Statement header members.\r
+\r
+ @param[in] OpCodeData Pointer of the raw OpCode data.\r
+ @param[in,out] FormSet Pointer of the current FormSet.\r
+ @param[in,out] Form Pointer of the current Form.\r
+\r
+ @return The Statement.\r
+\r
+**/\r
+HII_STATEMENT *\r
+CreateStatement (\r
+ IN UINT8 *OpCodeData,\r
+ IN OUT HII_FORMSET *FormSet,\r
+ IN OUT HII_FORM *Form\r
+ )\r
+{\r
+ HII_STATEMENT *Statement;\r
+ EFI_IFR_STATEMENT_HEADER *StatementHdr;\r
+ INTN ConditionalExprCount;\r
+\r
+ if (Form == NULL) {\r
+ //\r
+ // Only guid op may out side the form level.\r
+ //\r
+ if (((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode != EFI_IFR_GUID_OP) {\r
+ return NULL;\r
+ }\r
+ }\r
+\r
+ Statement = (HII_STATEMENT *)AllocateZeroPool (sizeof (HII_STATEMENT));\r
+ if (Statement == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ InitializeListHead (&Statement->DefaultListHead);\r
+ InitializeListHead (&Statement->OptionListHead);\r
+ InitializeListHead (&Statement->InconsistentListHead);\r
+ InitializeListHead (&Statement->NoSubmitListHead);\r
+ InitializeListHead (&Statement->WarningListHead);\r
+\r
+ Statement->Signature = HII_STATEMENT_SIGNATURE;\r
+ Statement->Operand = ((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode;\r
+ Statement->OpCode = (EFI_IFR_OP_HEADER *)OpCodeData;\r
+ Statement->QuestionReferToBitField = FALSE;\r
+\r
+ StatementHdr = (EFI_IFR_STATEMENT_HEADER *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER));\r
+ CopyMem (&Statement->Prompt, &StatementHdr->Prompt, sizeof (EFI_STRING_ID));\r
+ CopyMem (&Statement->Help, &StatementHdr->Help, sizeof (EFI_STRING_ID));\r
+\r
+ ConditionalExprCount = GetConditionalExpressionCount (ExpressStatement);\r
+ if (ConditionalExprCount > 0) {\r
+ //\r
+ // Form is inside of suppressif\r
+ //\r
+ Statement->ExpressionList = (HII_EXPRESSION_LIST *)AllocatePool (\r
+ (UINTN)(sizeof (HII_EXPRESSION_LIST) + ((ConditionalExprCount - 1) * sizeof (HII_EXPRESSION *)))\r
+ );\r
+ if (Statement->ExpressionList == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ Statement->ExpressionList->Count = (UINTN)ConditionalExprCount;\r
+ Statement->ExpressionList->Signature = HII_EXPRESSION_LIST_SIGNATURE;\r
+ CopyMem (\r
+ Statement->ExpressionList->Expression,\r
+ GetConditionalExpressionList (ExpressStatement),\r
+ (UINTN)(sizeof (HII_EXPRESSION *) * ConditionalExprCount)\r
+ );\r
+ }\r
+\r
+ //\r
+ // Insert this Statement into current Form\r
+ //\r
+ if (Form == NULL) {\r
+ InsertTailList (&FormSet->StatementListOSF, &Statement->Link);\r
+ } else {\r
+ InsertTailList (&Form->StatementListHead, &Statement->Link);\r
+ }\r
+\r
+ return Statement;\r
+}\r
+\r
+/**\r
+ Initialize Question's members.\r
+\r
+ @param[in] OpCodeData Pointer of the raw OpCode data.\r
+ @param[in,out] FormSet Pointer of the current FormSet.\r
+ @param[in,out] Form Pointer of the current Form.\r
+\r
+ @return The Question.\r
+\r
+**/\r
+HII_STATEMENT *\r
+CreateQuestion (\r
+ IN UINT8 *OpCodeData,\r
+ IN OUT HII_FORMSET *FormSet,\r
+ IN OUT HII_FORM *Form\r
+ )\r
+{\r
+ HII_STATEMENT *Statement;\r
+ EFI_IFR_QUESTION_HEADER *QuestionHdr;\r
+ LIST_ENTRY *Link;\r
+ HII_FORMSET_STORAGE *Storage;\r
+ HII_NAME_VALUE_NODE *NameValueNode;\r
+ BOOLEAN Find;\r
+\r
+ Statement = CreateStatement (OpCodeData, FormSet, Form);\r
+ if (Statement == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ QuestionHdr = (EFI_IFR_QUESTION_HEADER *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER));\r
+ CopyMem (&Statement->QuestionId, &QuestionHdr->QuestionId, sizeof (EFI_QUESTION_ID));\r
+ CopyMem (&Statement->VarStoreId, &QuestionHdr->VarStoreId, sizeof (EFI_VARSTORE_ID));\r
+ CopyMem (&Statement->VarStoreInfo.VarOffset, &QuestionHdr->VarStoreInfo.VarOffset, sizeof (UINT16));\r
+\r
+ Statement->QuestionFlags = QuestionHdr->Flags;\r
+\r
+ if (Statement->VarStoreId == 0) {\r
+ //\r
+ // VarStoreId of zero indicates no variable storage\r
+ //\r
+ return Statement;\r
+ }\r
+\r
+ //\r
+ // Find Storage for this Question\r
+ //\r
+ Link = GetFirstNode (&FormSet->StorageListHead);\r
+ while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+ Storage = HII_STORAGE_FROM_LINK (Link);\r
+\r
+ if (Statement->VarStoreId == Storage->VarStoreId) {\r
+ Statement->Storage = Storage;\r
+ break;\r
+ }\r
+\r
+ Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+ }\r
+\r
+ if (Statement->Storage == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Initialize varname for Name/Value or EFI Variable\r
+ //\r
+ if ((Statement->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) ||\r
+ (Statement->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE))\r
+ {\r
+ Statement->VariableName = GetTokenString (Statement->VarStoreInfo.VarName, FormSet->HiiHandle);\r
+ if (Statement->VariableName == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ if (Statement->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+ //\r
+ // Check whether old string node already exist.\r
+ //\r
+ Find = FALSE;\r
+ if (!IsListEmpty (&Statement->Storage->NameValueList)) {\r
+ Link = GetFirstNode (&Statement->Storage->NameValueList);\r
+ while (!IsNull (&Statement->Storage->NameValueList, Link)) {\r
+ NameValueNode = HII_NAME_VALUE_NODE_FROM_LINK (Link);\r
+\r
+ if (StrCmp (Statement->VariableName, NameValueNode->Name) == 0) {\r
+ Find = TRUE;\r
+ break;\r
+ }\r
+\r
+ Link = GetNextNode (&Statement->Storage->NameValueList, Link);\r
+ }\r
+ }\r
+\r
+ if (!Find) {\r
+ //\r
+ // Insert to Name/Value varstore list\r
+ //\r
+ NameValueNode = AllocateZeroPool (sizeof (HII_NAME_VALUE_NODE));\r
+ if (NameValueNode == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ NameValueNode->Signature = HII_NAME_VALUE_NODE_SIGNATURE;\r
+ NameValueNode->Name = AllocateCopyPool (StrSize (Statement->VariableName), Statement->VariableName);\r
+ if (NameValueNode->Name == NULL) {\r
+ FreePool (NameValueNode);\r
+ return NULL;\r
+ }\r
+\r
+ NameValueNode->Value = AllocateZeroPool (0x10);\r
+ if (NameValueNode->Value == NULL) {\r
+ FreePool (NameValueNode->Name);\r
+ FreePool (NameValueNode);\r
+ return NULL;\r
+ }\r
+\r
+ InsertTailList (&Statement->Storage->NameValueList, &NameValueNode->Link);\r
+ }\r
+ }\r
+ }\r
+\r
+ return Statement;\r
+}\r
+\r
+/**\r
+ Allocate a HII_EXPRESSION node.\r
+\r
+ @param[in,out] Form The Form associated with this Expression\r
+ @param[in] OpCode The binary opcode data.\r
+\r
+ @return Pointer to a HII_EXPRESSION data structure.\r
+\r
+**/\r
+HII_EXPRESSION *\r
+CreateExpression (\r
+ IN OUT HII_FORM *Form,\r
+ IN UINT8 *OpCode\r
+ )\r
+{\r
+ HII_EXPRESSION *Expression;\r
+\r
+ Expression = AllocateZeroPool (sizeof (HII_EXPRESSION));\r
+ if (Expression == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ Expression->Signature = HII_EXPRESSION_SIGNATURE;\r
+ InitializeListHead (&Expression->OpCodeListHead);\r
+ Expression->OpCode = (EFI_IFR_OP_HEADER *)OpCode;\r
+\r
+ return Expression;\r
+}\r
+\r
+/**\r
+ Create ConfigHdr string for a storage.\r
+\r
+ @param[in] FormSet Pointer of the current FormSet\r
+ @param[in,out] Storage Pointer of the storage\r
+\r
+ @retval EFI_SUCCESS Initialize ConfigHdr success\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeConfigHdr (\r
+ IN HII_FORMSET *FormSet,\r
+ IN OUT HII_FORMSET_STORAGE *Storage\r
+ )\r
+{\r
+ CHAR16 *Name;\r
+\r
+ if ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ||\r
+ (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER))\r
+ {\r
+ Name = Storage->Name;\r
+ } else {\r
+ Name = NULL;\r
+ }\r
+\r
+ Storage->ConfigHdr = HiiConstructConfigHdr (\r
+ &Storage->Guid,\r
+ Name,\r
+ FormSet->DriverHandle\r
+ );\r
+\r
+ if (Storage->ConfigHdr == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Convert Ascii string to Unicode.\r
+\r
+ This is an internal function.\r
+\r
+ @param[in] AsciiString The Ascii string to be converted.\r
+ @param[out] UnicodeString The Unicode string retrieved.\r
+\r
+**/\r
+VOID\r
+AsciiToUnicode (\r
+ IN CHAR8 *AsciiString,\r
+ OUT CHAR16 *UnicodeString\r
+ )\r
+{\r
+ UINT8 Index;\r
+\r
+ Index = 0;\r
+ while (AsciiString[Index] != 0) {\r
+ UnicodeString[Index] = (CHAR16)AsciiString[Index];\r
+ Index++;\r
+ }\r
+\r
+ UnicodeString[Index] = L'\0';\r
+}\r
+\r
+/**\r
+ Allocate a HII_FORMSET_STORAGE data structure and insert to FormSet Storage List.\r
+\r
+ @param[in] FormSet Pointer of the current FormSet\r
+ @param[in] StorageType Storage type.\r
+ @param[in] OpCodeData Binary data for this opcode.\r
+\r
+ @return Pointer to a HII_FORMSET_STORAGE data structure.\r
+\r
+**/\r
+HII_FORMSET_STORAGE *\r
+CreateStorage (\r
+ IN HII_FORMSET *FormSet,\r
+ IN UINT8 StorageType,\r
+ IN UINT8 *OpCodeData\r
+ )\r
+{\r
+ HII_FORMSET_STORAGE *Storage;\r
+ CHAR8 *AsciiStorageName;\r
+\r
+ AsciiStorageName = NULL;\r
+\r
+ Storage = AllocateZeroPool (sizeof (HII_FORMSET_STORAGE));\r
+ if (Storage == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ Storage->Signature = HII_STORAGE_SIGNATURE;\r
+ Storage->Type = StorageType;\r
+\r
+ switch (StorageType) {\r
+ case EFI_HII_VARSTORE_BUFFER:\r
+\r
+ CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE *)OpCodeData)->Guid, sizeof (EFI_GUID));\r
+ CopyMem (&Storage->Size, &((EFI_IFR_VARSTORE *)OpCodeData)->Size, sizeof (UINT16));\r
+\r
+ Storage->Buffer = AllocateZeroPool (Storage->Size);\r
+ if (Storage->Buffer == NULL) {\r
+ FreePool (Storage);\r
+ return NULL;\r
+ }\r
+\r
+ AsciiStorageName = (CHAR8 *)((EFI_IFR_VARSTORE *)OpCodeData)->Name;\r
+ Storage->Name = AllocatePool (sizeof (CHAR16) * (AsciiStrLen (AsciiStorageName) + 1));\r
+ if (Storage->Name == NULL) {\r
+ FreePool (Storage);\r
+ return NULL;\r
+ }\r
+\r
+ AsciiToUnicode (AsciiStorageName, Storage->Name);\r
+\r
+ break;\r
+\r
+ case EFI_HII_VARSTORE_EFI_VARIABLE:\r
+ case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
+ CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_EFI *)OpCodeData)->Guid, sizeof (EFI_GUID));\r
+ CopyMem (&Storage->Attributes, &((EFI_IFR_VARSTORE_EFI *)OpCodeData)->Attributes, sizeof (UINT32));\r
+ CopyMem (&Storage->Size, &((EFI_IFR_VARSTORE_EFI *)OpCodeData)->Size, sizeof (UINT16));\r
+\r
+ if (StorageType == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
+ Storage->Buffer = AllocateZeroPool (Storage->Size);\r
+ if (Storage->Buffer == NULL) {\r
+ FreePool (Storage);\r
+ return NULL;\r
+ }\r
+ }\r
+\r
+ AsciiStorageName = (CHAR8 *)((EFI_IFR_VARSTORE_EFI *)OpCodeData)->Name;\r
+ Storage->Name = AllocatePool (sizeof (CHAR16) * (AsciiStrLen (AsciiStorageName) + 1));\r
+ if (Storage->Name == NULL) {\r
+ FreePool (Storage);\r
+ return NULL;\r
+ }\r
+\r
+ AsciiToUnicode (AsciiStorageName, Storage->Name);\r
+\r
+ break;\r
+\r
+ case EFI_HII_VARSTORE_NAME_VALUE:\r
+ CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_NAME_VALUE *)OpCodeData)->Guid, sizeof (EFI_GUID));\r
+ InitializeListHead (&Storage->NameValueList);\r
+\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ InitializeConfigHdr (FormSet, Storage);\r
+ InsertTailList (&FormSet->StorageListHead, &Storage->Link);\r
+\r
+ return Storage;\r
+}\r
+\r
+/**\r
+ Get formset storage based on the input varstoreid info.\r
+\r
+ @param[in] FormSet Pointer of the current FormSet.\r
+ @param[in] VarStoreId Varstore ID info.\r
+\r
+ @return Pointer to a HII_FORMSET_STORAGE data structure.\r
+\r
+**/\r
+HII_FORMSET_STORAGE *\r
+GetFstStgFromVarId (\r
+ IN HII_FORMSET *FormSet,\r
+ IN EFI_VARSTORE_ID VarStoreId\r
+ )\r
+{\r
+ HII_FORMSET_STORAGE *Storage;\r
+ LIST_ENTRY *Link;\r
+ BOOLEAN Found;\r
+\r
+ Found = FALSE;\r
+ Storage = NULL;\r
+ //\r
+ // Find Formset Storage for this Question\r
+ //\r
+ Link = GetFirstNode (&FormSet->StorageListHead);\r
+ while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+ Storage = HII_STORAGE_FROM_LINK (Link);\r
+\r
+ if (Storage->VarStoreId == VarStoreId) {\r
+ Found = TRUE;\r
+ break;\r
+ }\r
+\r
+ Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+ }\r
+\r
+ return Found ? Storage : NULL;\r
+}\r
+\r
+/**\r
+ Initialize Request Element of a Question. <RequestElement> ::= '&'<BlockName> | '&'<Label>\r
+\r
+ @param[in,out] FormSet Pointer of the current FormSet.\r
+ @param[in,out] Question The Question to be initialized.\r
+ @param[in,out] Form Pointer of the current form.\r
+\r
+ @retval EFI_SUCCESS Function success.\r
+ @retval EFI_INVALID_PARAMETER No storage associated with the Question.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeRequestElement (\r
+ IN OUT HII_FORMSET *FormSet,\r
+ IN OUT HII_STATEMENT *Question,\r
+ IN OUT HII_FORM *Form\r
+ )\r
+{\r
+ HII_FORMSET_STORAGE *Storage;\r
+ HII_FORM_CONFIG_REQUEST *ConfigInfo;\r
+ UINTN StrLen;\r
+ UINTN StringSize;\r
+ CHAR16 *NewStr;\r
+ CHAR16 RequestElement[30];\r
+ LIST_ENTRY *Link;\r
+ BOOLEAN Find;\r
+ UINTN MaxLen;\r
+\r
+ Storage = Question->Storage;\r
+ if (Storage == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+ //\r
+ // <ConfigRequest> is unnecessary for EFI variable storage,\r
+ // GetVariable()/SetVariable() will be used to retrieve/save values\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Prepare <RequestElement>\r
+ //\r
+ if ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ||\r
+ (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER))\r
+ {\r
+ StrLen = UnicodeSPrint (\r
+ RequestElement,\r
+ 30 * sizeof (CHAR16),\r
+ L"&OFFSET=%04x&WIDTH=%04x",\r
+ Question->VarStoreInfo.VarOffset,\r
+ Question->StorageWidth\r
+ );\r
+ HiiStringToLowercase (RequestElement);\r
+ Question->BlockName = AllocateCopyPool ((StrLen + 1) * sizeof (CHAR16), RequestElement);\r
+ if (Question->BlockName == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ } else {\r
+ StrLen = UnicodeSPrint (RequestElement, 30 * sizeof (CHAR16), L"&%s", Question->VariableName);\r
+ }\r
+\r
+ if ((Question->Operand == EFI_IFR_PASSWORD_OP) &&\r
+ ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK))\r
+ {\r
+ //\r
+ // Password with CALLBACK flag is stored in encoded format,\r
+ // so don't need to append it to <ConfigRequest>\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ StringSize = (Storage->ConfigRequest != NULL) ? StrSize (Storage->ConfigRequest) : sizeof (CHAR16);\r
+ MaxLen = StringSize / sizeof (CHAR16) + Storage->SpareStrLen;\r
+\r
+ //\r
+ // Append <RequestElement> to <ConfigRequest>\r
+ //\r
+ if (StrLen > Storage->SpareStrLen) {\r
+ //\r
+ // Old String buffer is not sufficient for RequestElement, allocate a new one\r
+ //\r
+ MaxLen = StringSize / sizeof (CHAR16) + CONFIG_REQUEST_STRING_INCREMENTAL;\r
+ NewStr = AllocatePool (MaxLen * sizeof (CHAR16));\r
+ if (NewStr == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ if (Storage->ConfigRequest != NULL) {\r
+ CopyMem (NewStr, Storage->ConfigRequest, StringSize);\r
+ FreePool (Storage->ConfigRequest);\r
+ } else {\r
+ NewStr[0] = L'\0';\r
+ }\r
+\r
+ Storage->ConfigRequest = NewStr;\r
+ Storage->SpareStrLen = CONFIG_REQUEST_STRING_INCREMENTAL;\r
+ }\r
+\r
+ StrCatS (Storage->ConfigRequest, MaxLen, RequestElement);\r
+ Storage->ElementCount++;\r
+ Storage->SpareStrLen -= StrLen;\r
+\r
+ //\r
+ // Update the Config Request info saved in the form.\r
+ //\r
+ ConfigInfo = NULL;\r
+ Find = FALSE;\r
+ Link = GetFirstNode (&Form->ConfigRequestHead);\r
+ while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
+ ConfigInfo = HII_FORM_CONFIG_REQUEST_FROM_LINK (Link);\r
+ if ((ConfigInfo != NULL) && (ConfigInfo->Storage == Storage)) {\r
+ Find = TRUE;\r
+ break;\r
+ }\r
+\r
+ Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
+ }\r
+\r
+ if (!Find) {\r
+ ConfigInfo = AllocateZeroPool (sizeof (HII_FORM_CONFIG_REQUEST));\r
+ if (ConfigInfo == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ ConfigInfo->Signature = HII_FORM_CONFIG_REQUEST_SIGNATURE;\r
+ ConfigInfo->ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigHdr), Storage->ConfigHdr);\r
+ if (ConfigInfo->ConfigRequest == NULL) {\r
+ FreePool (ConfigInfo);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ ConfigInfo->SpareStrLen = 0;\r
+ ConfigInfo->Storage = Storage;\r
+ InsertTailList (&Form->ConfigRequestHead, &ConfigInfo->Link);\r
+ }\r
+\r
+ StringSize = (ConfigInfo->ConfigRequest != NULL) ? StrSize (ConfigInfo->ConfigRequest) : sizeof (CHAR16);\r
+ MaxLen = StringSize / sizeof (CHAR16) + ConfigInfo->SpareStrLen;\r
+\r
+ //\r
+ // Append <RequestElement> to <ConfigRequest>\r
+ //\r
+ if (StrLen > ConfigInfo->SpareStrLen) {\r
+ //\r
+ // Old String buffer is not sufficient for RequestElement, allocate a new one\r
+ //\r
+ MaxLen = StringSize / sizeof (CHAR16) + CONFIG_REQUEST_STRING_INCREMENTAL;\r
+ NewStr = AllocatePool (MaxLen * sizeof (CHAR16));\r
+ if (NewStr == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ if (ConfigInfo->ConfigRequest != NULL) {\r
+ CopyMem (NewStr, ConfigInfo->ConfigRequest, StringSize);\r
+ FreePool (ConfigInfo->ConfigRequest);\r
+ } else {\r
+ NewStr[0] = L'\0';\r
+ }\r
+\r
+ ConfigInfo->ConfigRequest = NewStr;\r
+ ConfigInfo->SpareStrLen = CONFIG_REQUEST_STRING_INCREMENTAL;\r
+ }\r
+\r
+ StrCatS (ConfigInfo->ConfigRequest, MaxLen, RequestElement);\r
+ ConfigInfo->ElementCount++;\r
+ ConfigInfo->SpareStrLen -= StrLen;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Free resources of a Expression.\r
+\r
+ @param[in] FormSet Pointer of the Expression\r
+\r
+**/\r
+VOID\r
+DestroyExpression (\r
+ IN HII_EXPRESSION *Expression\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ HII_EXPRESSION_OPCODE *OpCode;\r
+ LIST_ENTRY *SubExpressionLink;\r
+ HII_EXPRESSION *SubExpression;\r
+\r
+ while (!IsListEmpty (&Expression->OpCodeListHead)) {\r
+ Link = GetFirstNode (&Expression->OpCodeListHead);\r
+ OpCode = HII_EXPRESSION_OPCODE_FROM_LINK (Link);\r
+\r
+ RemoveEntryList (&OpCode->Link);\r
+ if ((OpCode->Operand == EFI_IFR_EQ_ID_VAL_LIST_OP) && (OpCode->ExtraData.EqIdListData.ValueList != NULL)) {\r
+ FreePool (OpCode->ExtraData.EqIdListData.ValueList);\r
+ }\r
+\r
+ if (((OpCode->Operand == EFI_IFR_GET_OP) || (OpCode->Operand == EFI_IFR_SET_OP)) &&\r
+ (OpCode->ExtraData.GetSetData.ValueName != NULL))\r
+ {\r
+ FreePool (OpCode->ExtraData.GetSetData.ValueName);\r
+ }\r
+\r
+ if (OpCode->MapExpressionList.ForwardLink != NULL) {\r
+ while (!IsListEmpty (&OpCode->MapExpressionList)) {\r
+ SubExpressionLink = GetFirstNode (&OpCode->MapExpressionList);\r
+ SubExpression = HII_EXPRESSION_FROM_LINK (SubExpressionLink);\r
+ RemoveEntryList (&SubExpression->Link);\r
+ DestroyExpression (SubExpression);\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Free this Expression\r
+ //\r
+ FreePool (Expression);\r
+}\r
+\r
+/**\r
+ Delete a string from HII Package List.\r
+\r
+ @param[in] StringId Id of the string in HII database.\r
+ @param[in] HiiHandle The HII package list handle.\r
+\r
+ @retval EFI_SUCCESS The string was deleted successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+DeleteString (\r
+ IN EFI_STRING_ID StringId,\r
+ IN EFI_HII_HANDLE HiiHandle\r
+ )\r
+{\r
+ CHAR16 NullChar;\r
+\r
+ NullChar = CHAR_NULL;\r
+ HiiSetString (HiiHandle, StringId, &NullChar, NULL);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Free resources of a Statement.\r
+\r
+ @param[in] FormSet Pointer of the FormSet\r
+ @param[in,out] Statement Pointer of the Statement\r
+\r
+**/\r
+VOID\r
+DestroyStatement (\r
+ IN HII_FORMSET *FormSet,\r
+ IN OUT HII_STATEMENT *Statement\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ HII_QUESTION_DEFAULT *Default;\r
+ HII_QUESTION_OPTION *Option;\r
+ HII_EXPRESSION *Expression;\r
+\r
+ //\r
+ // Free Default value List\r
+ //\r
+ while (!IsListEmpty (&Statement->DefaultListHead)) {\r
+ Link = GetFirstNode (&Statement->DefaultListHead);\r
+ Default = HII_QUESTION_DEFAULT_FROM_LINK (Link);\r
+ RemoveEntryList (&Default->Link);\r
+\r
+ if (Default->Value.Buffer != NULL) {\r
+ FreePool (Default->Value.Buffer);\r
+ }\r
+\r
+ FreePool (Default);\r
+ }\r
+\r
+ //\r
+ // Free Options List\r
+ //\r
+ while (!IsListEmpty (&Statement->OptionListHead)) {\r
+ Link = GetFirstNode (&Statement->OptionListHead);\r
+ Option = HII_QUESTION_OPTION_FROM_LINK (Link);\r
+\r
+ if (Option->SuppressExpression != NULL) {\r
+ FreePool (Option->SuppressExpression);\r
+ }\r
+\r
+ RemoveEntryList (&Option->Link);\r
+\r
+ FreePool (Option);\r
+ }\r
+\r
+ //\r
+ // Free Inconsistent List\r
+ //\r
+ while (!IsListEmpty (&Statement->InconsistentListHead)) {\r
+ Link = GetFirstNode (&Statement->InconsistentListHead);\r
+ Expression = HII_EXPRESSION_FROM_LINK (Link);\r
+ RemoveEntryList (&Expression->Link);\r
+\r
+ DestroyExpression (Expression);\r
+ }\r
+\r
+ //\r
+ // Free NoSubmit List\r
+ //\r
+ while (!IsListEmpty (&Statement->NoSubmitListHead)) {\r
+ Link = GetFirstNode (&Statement->NoSubmitListHead);\r
+ Expression = HII_EXPRESSION_FROM_LINK (Link);\r
+ RemoveEntryList (&Expression->Link);\r
+\r
+ DestroyExpression (Expression);\r
+ }\r
+\r
+ //\r
+ // Free WarningIf List\r
+ //\r
+ while (!IsListEmpty (&Statement->WarningListHead)) {\r
+ Link = GetFirstNode (&Statement->WarningListHead);\r
+ Expression = HII_EXPRESSION_FROM_LINK (Link);\r
+ RemoveEntryList (&Expression->Link);\r
+\r
+ DestroyExpression (Expression);\r
+ }\r
+\r
+ if (Statement->ExpressionList != NULL) {\r
+ FreePool (Statement->ExpressionList);\r
+ }\r
+\r
+ if (Statement->VariableName != NULL) {\r
+ FreePool (Statement->VariableName);\r
+ }\r
+\r
+ if (Statement->BlockName != NULL) {\r
+ FreePool (Statement->BlockName);\r
+ }\r
+\r
+ if (Statement->Value.Buffer != NULL) {\r
+ FreePool (Statement->Value.Buffer);\r
+ }\r
+\r
+ if ((Statement->Operand == EFI_IFR_STRING_OP) || (Statement->Operand == EFI_IFR_PASSWORD_OP)) {\r
+ DeleteString (Statement->Value.Value.string, FormSet->HiiHandle);\r
+ }\r
+}\r
+\r
+/**\r
+ Free resources of a Form.\r
+\r
+ @param[in] FormSet Pointer of the FormSet\r
+ @param[in,out] Form Pointer of the Form.\r
+\r
+**/\r
+VOID\r
+DestroyForm (\r
+ IN HII_FORMSET *FormSet,\r
+ IN OUT HII_FORM *Form\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ HII_EXPRESSION *Expression;\r
+ HII_STATEMENT *Statement;\r
+ HII_FORM_CONFIG_REQUEST *ConfigInfo;\r
+\r
+ //\r
+ // Free Rule Expressions\r
+ //\r
+ while (!IsListEmpty (&Form->RuleListHead)) {\r
+ Link = GetFirstNode (&Form->RuleListHead);\r
+ Expression = HII_EXPRESSION_FROM_LINK (Link);\r
+ RemoveEntryList (&Expression->Link);\r
+ DestroyExpression (Expression);\r
+ }\r
+\r
+ //\r
+ // Free Statements/Questions\r
+ //\r
+ while (!IsListEmpty (&Form->StatementListHead)) {\r
+ Link = GetFirstNode (&Form->StatementListHead);\r
+ Statement = HII_STATEMENT_FROM_LINK (Link);\r
+ RemoveEntryList (&Statement->Link);\r
+ DestroyStatement (FormSet, Statement);\r
+ }\r
+\r
+ //\r
+ // Free ConfigRequest string.\r
+ //\r
+ while (!IsListEmpty (&Form->ConfigRequestHead)) {\r
+ Link = GetFirstNode (&Form->ConfigRequestHead);\r
+ ConfigInfo = HII_FORM_CONFIG_REQUEST_FROM_LINK (Link);\r
+\r
+ RemoveEntryList (&ConfigInfo->Link);\r
+\r
+ FreePool (ConfigInfo->ConfigRequest);\r
+ FreePool (ConfigInfo);\r
+ }\r
+\r
+ if (Form->SuppressExpression != NULL) {\r
+ FreePool (Form->SuppressExpression);\r
+ }\r
+\r
+ //\r
+ // Free this Form\r
+ //\r
+ FreePool (Form);\r
+}\r
+\r
+/**\r
+ Tell whether this Operand is an Expression OpCode or not\r
+\r
+ @param[in] Operand Operand of an IFR OpCode.\r
+\r
+ @retval TRUE This is an Expression OpCode.\r
+ @retval FALSE Not an Expression OpCode.\r
+\r
+**/\r
+BOOLEAN\r
+IsExpressionOpCode (\r
+ IN UINT8 Operand\r
+ )\r
+{\r
+ if (((Operand >= EFI_IFR_EQ_ID_VAL_OP) && (Operand <= EFI_IFR_NOT_OP)) ||\r
+ ((Operand >= EFI_IFR_MATCH_OP) && (Operand <= EFI_IFR_SET_OP)) ||\r
+ ((Operand >= EFI_IFR_EQUAL_OP) && (Operand <= EFI_IFR_SPAN_OP)) ||\r
+ (Operand == EFI_IFR_CATENATE_OP) ||\r
+ (Operand == EFI_IFR_TO_LOWER_OP) ||\r
+ (Operand == EFI_IFR_TO_UPPER_OP) ||\r
+ (Operand == EFI_IFR_MAP_OP) ||\r
+ (Operand == EFI_IFR_VERSION_OP) ||\r
+ (Operand == EFI_IFR_SECURITY_OP) ||\r
+ (Operand == EFI_IFR_MATCH2_OP))\r
+ {\r
+ return TRUE;\r
+ } else {\r
+ return FALSE;\r
+ }\r
+}\r
+\r
+/**\r
+ Tell whether this Operand is an Statement OpCode.\r
+\r
+ @param[in] Operand Operand of an IFR OpCode.\r
+\r
+ @retval TRUE This is an Statement OpCode.\r
+ @retval FALSE Not an Statement OpCode.\r
+\r
+**/\r
+BOOLEAN\r
+IsStatementOpCode (\r
+ IN UINT8 Operand\r
+ )\r
+{\r
+ if ((Operand == EFI_IFR_SUBTITLE_OP) ||\r
+ (Operand == EFI_IFR_TEXT_OP) ||\r
+ (Operand == EFI_IFR_RESET_BUTTON_OP) ||\r
+ (Operand == EFI_IFR_REF_OP) ||\r
+ (Operand == EFI_IFR_ACTION_OP) ||\r
+ (Operand == EFI_IFR_NUMERIC_OP) ||\r
+ (Operand == EFI_IFR_ORDERED_LIST_OP) ||\r
+ (Operand == EFI_IFR_CHECKBOX_OP) ||\r
+ (Operand == EFI_IFR_STRING_OP) ||\r
+ (Operand == EFI_IFR_PASSWORD_OP) ||\r
+ (Operand == EFI_IFR_DATE_OP) ||\r
+ (Operand == EFI_IFR_TIME_OP) ||\r
+ (Operand == EFI_IFR_GUID_OP) ||\r
+ (Operand == EFI_IFR_ONE_OF_OP))\r
+ {\r
+ return TRUE;\r
+ } else {\r
+ return FALSE;\r
+ }\r
+}\r
+\r
+/**\r
+ Tell whether this Operand is an known OpCode.\r
+\r
+ @param[in] Operand Operand of an IFR OpCode.\r
+\r
+ @retval TRUE This is an Statement OpCode.\r
+ @retval FALSE Not an Statement OpCode.\r
+\r
+**/\r
+BOOLEAN\r
+IsUnKnownOpCode (\r
+ IN UINT8 Operand\r
+ )\r
+{\r
+ return Operand > EFI_IFR_MATCH2_OP ? TRUE : FALSE;\r
+}\r
+\r
+/**\r
+ Calculate number of Statements(Questions) and Expression OpCodes.\r
+\r
+ @param[in] FormSet The FormSet to be counted.\r
+ @param[in,out] NumberOfStatement Number of Statements(Questions)\r
+ @param[in,out] NumberOfExpression Number of Expression OpCodes\r
+\r
+**/\r
+VOID\r
+CountOpCodes (\r
+ IN HII_FORMSET *FormSet,\r
+ IN OUT UINT16 *NumberOfStatement,\r
+ IN OUT UINT16 *NumberOfExpression\r
+ )\r
+{\r
+ UINT16 StatementCount;\r
+ UINT16 ExpressionCount;\r
+ UINT8 *OpCodeData;\r
+ UINTN Offset;\r
+ UINTN OpCodeLen;\r
+\r
+ Offset = 0;\r
+ StatementCount = 0;\r
+ ExpressionCount = 0;\r
+\r
+ while (Offset < FormSet->IfrBinaryLength) {\r
+ OpCodeData = FormSet->IfrBinaryData + Offset;\r
+ OpCodeLen = ((EFI_IFR_OP_HEADER *)OpCodeData)->Length;\r
+ Offset += OpCodeLen;\r
+\r
+ if (IsExpressionOpCode (((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode)) {\r
+ ExpressionCount++;\r
+ } else {\r
+ StatementCount++;\r
+ }\r
+ }\r
+\r
+ *NumberOfStatement = StatementCount;\r
+ *NumberOfExpression = ExpressionCount;\r
+}\r
+\r
+/**\r
+ Parse opcodes in the formset IFR binary.\r
+\r
+ @param[in] FormSet Pointer of the FormSet data structure.\r
+\r
+ @retval EFI_SUCCESS Opcode parse success.\r
+ @retval Other Opcode parse fail.\r
+\r
+**/\r
+EFI_STATUS\r
+ParseOpCodes (\r
+ IN HII_FORMSET *FormSet\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ HII_FORM *CurrentForm;\r
+ HII_STATEMENT *CurrentStatement;\r
+ HII_STATEMENT *ParentStatement;\r
+ HII_EXPRESSION_OPCODE *ExpressionOpCode;\r
+ HII_EXPRESSION *CurrentExpression;\r
+ UINT8 Operand;\r
+ UINT8 Scope;\r
+ UINTN OpCodeOffset;\r
+ UINTN OpCodeLength;\r
+ UINT8 *OpCodeData;\r
+ UINT8 ScopeOpCode;\r
+ HII_FORMSET_DEFAULTSTORE *DefaultStore;\r
+ HII_QUESTION_DEFAULT *CurrentDefault;\r
+ HII_QUESTION_OPTION *CurrentOption;\r
+ UINT8 Width;\r
+ UINT16 NumberOfStatement;\r
+ UINT16 NumberOfExpression;\r
+ EFI_IMAGE_ID *ImageId;\r
+ BOOLEAN SuppressForQuestion;\r
+ BOOLEAN SuppressForOption;\r
+ UINT16 DepthOfDisable;\r
+ BOOLEAN OpCodeDisabled;\r
+ BOOLEAN SingleOpCodeExpression;\r
+ BOOLEAN InScopeDefault;\r
+ EFI_HII_VALUE *ExpressionValue;\r
+ HII_STATEMENT_VALUE *StatementValue;\r
+ EFI_IFR_FORM_MAP_METHOD *MapMethod;\r
+ UINT8 MapScopeDepth;\r
+ LIST_ENTRY *Link;\r
+ HII_FORMSET_STORAGE *Storage;\r
+ LIST_ENTRY *MapExpressionList;\r
+ EFI_VARSTORE_ID TempVarstoreId;\r
+ BOOLEAN InScopeDisable;\r
+ INTN ConditionalExprCount;\r
+ BOOLEAN InUnknownScope;\r
+ UINT8 UnknownDepth;\r
+ HII_FORMSET_DEFAULTSTORE *PreDefaultStore;\r
+ LIST_ENTRY *DefaultLink;\r
+ BOOLEAN HaveInserted;\r
+ UINT16 TotalBits;\r
+ BOOLEAN QuestionReferBitField;\r
+\r
+ SuppressForQuestion = FALSE;\r
+ SuppressForOption = FALSE;\r
+ InScopeDisable = FALSE;\r
+ DepthOfDisable = 0;\r
+ OpCodeDisabled = FALSE;\r
+ SingleOpCodeExpression = FALSE;\r
+ InScopeDefault = FALSE;\r
+ CurrentExpression = NULL;\r
+ CurrentDefault = NULL;\r
+ CurrentOption = NULL;\r
+ ImageId = NULL;\r
+ MapMethod = NULL;\r
+ MapScopeDepth = 0;\r
+ Link = NULL;\r
+ MapExpressionList = NULL;\r
+ TempVarstoreId = 0;\r
+ ConditionalExprCount = 0;\r
+ InUnknownScope = FALSE;\r
+ UnknownDepth = 0;\r
+ QuestionReferBitField = FALSE;\r
+\r
+ //\r
+ // Get the number of Statements and Expressions\r
+ //\r
+ CountOpCodes (FormSet, &NumberOfStatement, &NumberOfExpression);\r
+\r
+ InitializeListHead (&FormSet->StatementListOSF);\r
+ InitializeListHead (&FormSet->StorageListHead);\r
+ InitializeListHead (&FormSet->DefaultStoreListHead);\r
+ InitializeListHead (&FormSet->FormListHead);\r
+ ResetCurrentExpressionStack ();\r
+ ResetMapExpressionListStack ();\r
+\r
+ CurrentForm = NULL;\r
+ CurrentStatement = NULL;\r
+ ParentStatement = NULL;\r
+\r
+ ResetScopeStack ();\r
+\r
+ OpCodeOffset = 0;\r
+ while (OpCodeOffset < FormSet->IfrBinaryLength) {\r
+ OpCodeData = FormSet->IfrBinaryData + OpCodeOffset;\r
+\r
+ OpCodeLength = ((EFI_IFR_OP_HEADER *)OpCodeData)->Length;\r
+ OpCodeOffset += OpCodeLength;\r
+ Operand = ((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode;\r
+ Scope = ((EFI_IFR_OP_HEADER *)OpCodeData)->Scope;\r
+ if (InUnknownScope) {\r
+ if (Operand == EFI_IFR_END_OP) {\r
+ UnknownDepth--;\r
+\r
+ if (UnknownDepth == 0) {\r
+ InUnknownScope = FALSE;\r
+ }\r
+ } else {\r
+ if (Scope != 0) {\r
+ UnknownDepth++;\r
+ }\r
+ }\r
+\r
+ continue;\r
+ }\r
+\r
+ if (IsUnKnownOpCode (Operand)) {\r
+ if (Scope != 0) {\r
+ InUnknownScope = TRUE;\r
+ UnknownDepth++;\r
+ }\r
+\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // If scope bit set, push onto scope stack\r
+ //\r
+ if (Scope != 0) {\r
+ PushScope (Operand);\r
+ }\r
+\r
+ if (OpCodeDisabled) {\r
+ //\r
+ // DisableIf Expression is evaluated to be TRUE, try to find its end.\r
+ // Here only cares the EFI_IFR_DISABLE_IF and EFI_IFR_END\r
+ //\r
+ if (Operand == EFI_IFR_DISABLE_IF_OP) {\r
+ DepthOfDisable++;\r
+ } else if (Operand == EFI_IFR_END_OP) {\r
+ Status = PopScope (&ScopeOpCode);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (ScopeOpCode == EFI_IFR_DISABLE_IF_OP) {\r
+ if (DepthOfDisable == 0) {\r
+ InScopeDisable = FALSE;\r
+ OpCodeDisabled = FALSE;\r
+ } else {\r
+ DepthOfDisable--;\r
+ }\r
+ }\r
+ }\r
+\r
+ continue;\r
+ }\r
+\r
+ if (IsExpressionOpCode (Operand)) {\r
+ ExpressionOpCode = (HII_EXPRESSION_OPCODE *)AllocateZeroPool (sizeof (HII_EXPRESSION_OPCODE));\r
+ if (ExpressionOpCode == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ ExpressionOpCode->Signature = HII_EXPRESSION_OPCODE_SIGNATURE;\r
+ ExpressionOpCode->Operand = Operand;\r
+\r
+ switch (Operand) {\r
+ case EFI_IFR_EQ_ID_VAL_OP:\r
+\r
+ CopyMem (&ExpressionOpCode->ExtraData.EqIdValData.QuestionId, &((EFI_IFR_EQ_ID_VAL *)OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));\r
+\r
+ ExpressionValue = &ExpressionOpCode->ExtraData.EqIdValData.Value;\r
+ ExpressionValue->Type = EFI_IFR_TYPE_NUM_SIZE_16;\r
+ CopyMem (&ExpressionValue->Value.u16, &((EFI_IFR_EQ_ID_VAL *)OpCodeData)->Value, sizeof (UINT16));\r
+ break;\r
+\r
+ case EFI_IFR_EQ_ID_ID_OP:\r
+ CopyMem (&ExpressionOpCode->ExtraData.EqIdIdData.QuestionId1, &((EFI_IFR_EQ_ID_ID *)OpCodeData)->QuestionId1, sizeof (EFI_QUESTION_ID));\r
+ CopyMem (&ExpressionOpCode->ExtraData.EqIdIdData.QuestionId2, &((EFI_IFR_EQ_ID_ID *)OpCodeData)->QuestionId2, sizeof (EFI_QUESTION_ID));\r
+ break;\r
+\r
+ case EFI_IFR_EQ_ID_VAL_LIST_OP:\r
+\r
+ CopyMem (&ExpressionOpCode->ExtraData.EqIdListData.QuestionId, &((EFI_IFR_EQ_ID_VAL_LIST *)OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));\r
+ CopyMem (&ExpressionOpCode->ExtraData.EqIdListData.ListLength, &((EFI_IFR_EQ_ID_VAL_LIST *)OpCodeData)->ListLength, sizeof (UINT16));\r
+ ExpressionOpCode->ExtraData.EqIdListData.ValueList = AllocateCopyPool (\r
+ ExpressionOpCode->ExtraData.EqIdListData.ListLength * sizeof (UINT16),\r
+ &((EFI_IFR_EQ_ID_VAL_LIST *)OpCodeData)->ValueList\r
+ );\r
+ if (ExpressionOpCode->ExtraData.EqIdListData.ValueList == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_TO_STRING_OP:\r
+ case EFI_IFR_FIND_OP:\r
+\r
+ ExpressionOpCode->ExtraData.Format = ((EFI_IFR_TO_STRING *)OpCodeData)->Format;\r
+ break;\r
+\r
+ case EFI_IFR_STRING_REF1_OP:\r
+\r
+ ExpressionValue = &ExpressionOpCode->ExtraData.Value;\r
+ ExpressionValue->Type = EFI_IFR_TYPE_STRING;\r
+ CopyMem (&ExpressionValue->Value.string, &((EFI_IFR_STRING_REF1 *)OpCodeData)->StringId, sizeof (EFI_STRING_ID));\r
+ break;\r
+\r
+ case EFI_IFR_RULE_REF_OP:\r
+\r
+ ExpressionOpCode->ExtraData.RuleId = ((EFI_IFR_RULE_REF *)OpCodeData)->RuleId;\r
+ break;\r
+\r
+ case EFI_IFR_SPAN_OP:\r
+\r
+ ExpressionOpCode->ExtraData.Flags = ((EFI_IFR_SPAN *)OpCodeData)->Flags;\r
+ break;\r
+\r
+ case EFI_IFR_THIS_OP:\r
+\r
+ if (ParentStatement != NULL) {\r
+ ExpressionOpCode->ExtraData.QuestionRef1Data.QuestionId = ParentStatement->QuestionId;\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_SECURITY_OP:\r
+\r
+ CopyMem (&ExpressionOpCode->ExtraData.Guid, &((EFI_IFR_SECURITY *)OpCodeData)->Permissions, sizeof (EFI_GUID));\r
+ break;\r
+\r
+ case EFI_IFR_MATCH2_OP:\r
+\r
+ CopyMem (&ExpressionOpCode->ExtraData.Guid, &((EFI_IFR_MATCH2 *)OpCodeData)->SyntaxType, sizeof (EFI_GUID));\r
+ break;\r
+\r
+ case EFI_IFR_GET_OP:\r
+ case EFI_IFR_SET_OP:\r
+\r
+ CopyMem (&TempVarstoreId, &((EFI_IFR_GET *)OpCodeData)->VarStoreId, sizeof (TempVarstoreId));\r
+ if (TempVarstoreId != 0) {\r
+ if (FormSet->StorageListHead.ForwardLink != NULL) {\r
+ Link = GetFirstNode (&FormSet->StorageListHead);\r
+ while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+ Storage = HII_STORAGE_FROM_LINK (Link);\r
+ if (Storage->VarStoreId == ((EFI_IFR_GET *)OpCodeData)->VarStoreId) {\r
+ ExpressionOpCode->ExtraData.GetSetData.VarStorage = Storage;\r
+ break;\r
+ }\r
+\r
+ Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+ }\r
+ }\r
+\r
+ if (ExpressionOpCode->ExtraData.GetSetData.VarStorage == NULL) {\r
+ //\r
+ // VarStorage is not found.\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+\r
+ ExpressionOpCode->ExtraData.GetSetData.ValueType = ((EFI_IFR_GET *)OpCodeData)->VarStoreType;\r
+ switch (ExpressionOpCode->ExtraData.GetSetData.ValueType) {\r
+ case EFI_IFR_TYPE_BOOLEAN:\r
+ case EFI_IFR_TYPE_NUM_SIZE_8:\r
+ ExpressionOpCode->ExtraData.GetSetData.ValueWidth = 1;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_16:\r
+ case EFI_IFR_TYPE_STRING:\r
+ ExpressionOpCode->ExtraData.GetSetData.ValueWidth = 2;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_32:\r
+ ExpressionOpCode->ExtraData.GetSetData.ValueWidth = 4;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_64:\r
+ ExpressionOpCode->ExtraData.GetSetData.ValueWidth = 8;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_DATE:\r
+ ExpressionOpCode->ExtraData.GetSetData.ValueWidth = (UINT8)sizeof (EFI_IFR_DATE);\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_TIME:\r
+ ExpressionOpCode->ExtraData.GetSetData.ValueWidth = (UINT8)sizeof (EFI_IFR_TIME);\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_REF:\r
+ ExpressionOpCode->ExtraData.GetSetData.ValueWidth = (UINT8)sizeof (EFI_IFR_REF);\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_OTHER:\r
+ case EFI_IFR_TYPE_UNDEFINED:\r
+ case EFI_IFR_TYPE_ACTION:\r
+ case EFI_IFR_TYPE_BUFFER:\r
+ default:\r
+ //\r
+ // Invalid value type for Get/Set opcode.\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ CopyMem (\r
+ &ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo.VarName,\r
+ &((EFI_IFR_GET *)OpCodeData)->VarStoreInfo.VarName,\r
+ sizeof (EFI_STRING_ID)\r
+ );\r
+ CopyMem (\r
+ &ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset,\r
+ &((EFI_IFR_GET *)OpCodeData)->VarStoreInfo.VarOffset,\r
+ sizeof (UINT16)\r
+ );\r
+ if ((ExpressionOpCode->ExtraData.GetSetData.VarStorage != NULL) &&\r
+ ((ExpressionOpCode->ExtraData.GetSetData.VarStorage->Type == EFI_HII_VARSTORE_NAME_VALUE) ||\r
+ (ExpressionOpCode->ExtraData.GetSetData.VarStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)))\r
+ {\r
+ ExpressionOpCode->ExtraData.GetSetData.ValueName = GetTokenString (ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo.VarName, FormSet->HiiHandle);\r
+ if (ExpressionOpCode->ExtraData.GetSetData.ValueName == NULL) {\r
+ //\r
+ // String ID is invalid.\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_QUESTION_REF1_OP:\r
+\r
+ CopyMem (&ExpressionOpCode->ExtraData.QuestionRef1Data.QuestionId, &((EFI_IFR_EQ_ID_VAL_LIST *)OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));\r
+ break;\r
+\r
+ case EFI_IFR_QUESTION_REF3_OP:\r
+\r
+ if (OpCodeLength >= sizeof (EFI_IFR_QUESTION_REF3_2)) {\r
+ CopyMem (&ExpressionOpCode->ExtraData.QuestionRef3Data.DevicePath, &((EFI_IFR_QUESTION_REF3_2 *)OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));\r
+\r
+ if (OpCodeLength >= sizeof (EFI_IFR_QUESTION_REF3_3)) {\r
+ CopyMem (&ExpressionOpCode->ExtraData.QuestionRef3Data.Guid, &((EFI_IFR_QUESTION_REF3_3 *)OpCodeData)->Guid, sizeof (EFI_GUID));\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+ //\r
+ // constant\r
+ //\r
+ case EFI_IFR_TRUE_OP:\r
+\r
+ ExpressionValue = &ExpressionOpCode->ExtraData.Value;\r
+ ExpressionValue->Type = EFI_IFR_TYPE_BOOLEAN;\r
+ ExpressionValue->Value.b = TRUE;\r
+ break;\r
+\r
+ case EFI_IFR_FALSE_OP:\r
+\r
+ ExpressionValue = &ExpressionOpCode->ExtraData.Value;\r
+ ExpressionValue->Type = EFI_IFR_TYPE_BOOLEAN;\r
+ ExpressionValue->Value.b = FALSE;\r
+ break;\r
+\r
+ case EFI_IFR_ONE_OP:\r
+\r
+ ExpressionValue = &ExpressionOpCode->ExtraData.Value;\r
+ ExpressionValue->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
+ ExpressionValue->Value.u8 = 1;\r
+ break;\r
+\r
+ case EFI_IFR_ZERO_OP:\r
+\r
+ ExpressionValue = &ExpressionOpCode->ExtraData.Value;\r
+ ExpressionValue->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
+ ExpressionValue->Value.u8 = 0;\r
+ break;\r
+\r
+ case EFI_IFR_ONES_OP:\r
+\r
+ ExpressionValue = &ExpressionOpCode->ExtraData.Value;\r
+ ExpressionValue->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+ ExpressionValue->Value.u64 = 0xffffffffffffffffULL;\r
+ break;\r
+\r
+ case EFI_IFR_UINT8_OP:\r
+\r
+ ExpressionValue = &ExpressionOpCode->ExtraData.Value;\r
+ ExpressionValue->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
+ ExpressionValue->Value.u8 = ((EFI_IFR_UINT8 *)OpCodeData)->Value;\r
+ break;\r
+\r
+ case EFI_IFR_UINT16_OP:\r
+\r
+ ExpressionValue = &ExpressionOpCode->ExtraData.Value;\r
+ ExpressionValue->Type = EFI_IFR_TYPE_NUM_SIZE_16;\r
+ CopyMem (&ExpressionValue->Value.u16, &((EFI_IFR_UINT16 *)OpCodeData)->Value, sizeof (UINT16));\r
+ break;\r
+\r
+ case EFI_IFR_UINT32_OP:\r
+\r
+ ExpressionValue = &ExpressionOpCode->ExtraData.Value;\r
+ ExpressionValue->Type = EFI_IFR_TYPE_NUM_SIZE_32;\r
+ CopyMem (&ExpressionValue->Value.u32, &((EFI_IFR_UINT32 *)OpCodeData)->Value, sizeof (UINT32));\r
+ break;\r
+\r
+ case EFI_IFR_UINT64_OP:\r
+\r
+ ExpressionValue = &ExpressionOpCode->ExtraData.Value;\r
+ ExpressionValue->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+ CopyMem (&ExpressionValue->Value.u64, &((EFI_IFR_UINT64 *)OpCodeData)->Value, sizeof (UINT64));\r
+ break;\r
+\r
+ case EFI_IFR_UNDEFINED_OP:\r
+ ExpressionValue = &ExpressionOpCode->ExtraData.Value;\r
+ ExpressionValue->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ break;\r
+\r
+ case EFI_IFR_VERSION_OP:\r
+ ExpressionValue = &ExpressionOpCode->ExtraData.Value;\r
+ ExpressionValue->Type = EFI_IFR_TYPE_NUM_SIZE_16;\r
+ ExpressionValue->Value.u16 = EFI_IFR_SPECIFICATION_VERSION;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Create sub expression nested in MAP opcode\r
+ //\r
+ if ((CurrentExpression == NULL) && (MapScopeDepth > 0)) {\r
+ CurrentExpression = CreateExpression (CurrentForm, OpCodeData);\r
+ if (CurrentExpression == NULL) {\r
+ continue;\r
+ }\r
+\r
+ InsertTailList (MapExpressionList, &CurrentExpression->Link);\r
+ if (Scope == 0) {\r
+ SingleOpCodeExpression = TRUE;\r
+ }\r
+ }\r
+\r
+ InsertTailList (&CurrentExpression->OpCodeListHead, &ExpressionOpCode->Link);\r
+ if (Operand == EFI_IFR_MAP_OP) {\r
+ //\r
+ // Store current Map Expression List.\r
+ //\r
+ if (MapExpressionList != NULL) {\r
+ PushMapExpressionList (MapExpressionList);\r
+ }\r
+\r
+ //\r
+ // Initialize new Map Expression List.\r
+ //\r
+ MapExpressionList = &ExpressionOpCode->MapExpressionList;\r
+ InitializeListHead (MapExpressionList);\r
+ //\r
+ // Store current expression.\r
+ //\r
+ PushCurrentExpression (CurrentExpression);\r
+ CurrentExpression = NULL;\r
+ MapScopeDepth++;\r
+ } else if (SingleOpCodeExpression) {\r
+ //\r
+ // There are two cases to indicate the end of an Expression:\r
+ // for single OpCode expression: one Expression OpCode\r
+ // for expression consists of more than one OpCode: EFI_IFR_END\r
+ //\r
+ SingleOpCodeExpression = FALSE;\r
+\r
+ if (InScopeDisable && (CurrentForm == NULL)) {\r
+ //\r
+ // This is DisableIf expression for Form, it should be a constant expression\r
+ //\r
+ Status = EvaluateHiiExpression (FormSet, CurrentForm, CurrentExpression);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ OpCodeDisabled = IsHiiValueTrue (&CurrentExpression->Result);\r
+ }\r
+\r
+ CurrentExpression = NULL;\r
+ }\r
+\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Parse the Opcode\r
+ //\r
+ switch (Operand) {\r
+ case EFI_IFR_FORM_SET_OP:\r
+ //\r
+ // Check the formset GUID\r
+ //\r
+\r
+ if (CompareMem (&FormSet->Guid, &((EFI_IFR_FORM_SET *)OpCodeData)->Guid, sizeof (EFI_GUID)) != 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ CopyMem (&FormSet->FormSetTitle, &((EFI_IFR_FORM_SET *)OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID));\r
+ CopyMem (&FormSet->Help, &((EFI_IFR_FORM_SET *)OpCodeData)->Help, sizeof (EFI_STRING_ID));\r
+\r
+ if (OpCodeLength > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) {\r
+ //\r
+ // The formset OpCode contains ClassGuid\r
+ //\r
+ FormSet->NumberOfClassGuid = (UINT8)(((EFI_IFR_FORM_SET *)OpCodeData)->Flags & 0x3);\r
+ CopyMem (FormSet->ClassGuid, OpCodeData + sizeof (EFI_IFR_FORM_SET), FormSet->NumberOfClassGuid * sizeof (EFI_GUID));\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_FORM_OP:\r
+\r
+ //\r
+ // Create a new Form for this FormSet\r
+ //\r
+ CurrentForm = AllocateZeroPool (sizeof (HII_FORM));\r
+ if (CurrentForm == NULL) {\r
+ break;\r
+ }\r
+\r
+ CurrentForm->Signature = HII_FORM_SIGNATURE;\r
+ InitializeListHead (&CurrentForm->StatementListHead);\r
+ InitializeListHead (&CurrentForm->ConfigRequestHead);\r
+ InitializeListHead (&CurrentForm->RuleListHead);\r
+\r
+ CurrentForm->FormType = STANDARD_MAP_FORM_TYPE;\r
+ CopyMem (&CurrentForm->FormId, &((EFI_IFR_FORM *)OpCodeData)->FormId, sizeof (UINT16));\r
+ CopyMem (&CurrentForm->FormTitle, &((EFI_IFR_FORM *)OpCodeData)->FormTitle, sizeof (EFI_STRING_ID));\r
+\r
+ ConditionalExprCount = GetConditionalExpressionCount (ExpressForm);\r
+ if ( ConditionalExprCount > 0) {\r
+ //\r
+ // Form is inside of suppressif\r
+ //\r
+ CurrentForm->SuppressExpression = (HII_EXPRESSION_LIST *)AllocatePool (\r
+ (UINTN)(sizeof (HII_EXPRESSION_LIST) + ((ConditionalExprCount -1) * sizeof (HII_EXPRESSION *)))\r
+ );\r
+ if (CurrentForm->SuppressExpression == NULL) {\r
+ break;\r
+ }\r
+\r
+ CurrentForm->SuppressExpression->Count = (UINTN)ConditionalExprCount;\r
+ CurrentForm->SuppressExpression->Signature = HII_EXPRESSION_LIST_SIGNATURE;\r
+ CopyMem (CurrentForm->SuppressExpression->Expression, GetConditionalExpressionList (ExpressForm), (UINTN)(sizeof (HII_EXPRESSION *) * ConditionalExprCount));\r
+ }\r
+\r
+ if (Scope != 0) {\r
+ //\r
+ // Enter scope of a Form, suppressif will be used for Question or Option\r
+ //\r
+ SuppressForQuestion = TRUE;\r
+ }\r
+\r
+ //\r
+ // Insert into Form list of this FormSet\r
+ //\r
+ InsertTailList (&FormSet->FormListHead, &CurrentForm->Link);\r
+ break;\r
+\r
+ case EFI_IFR_FORM_MAP_OP:\r
+\r
+ //\r
+ // Create a new Form for this FormSet\r
+ //\r
+ CurrentForm = AllocateZeroPool (sizeof (HII_FORM));\r
+ if (CurrentForm == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ CurrentForm->Signature = HII_FORM_SIGNATURE;\r
+ InitializeListHead (&CurrentForm->StatementListHead);\r
+ InitializeListHead (&CurrentForm->ConfigRequestHead);\r
+ InitializeListHead (&CurrentForm->RuleListHead);\r
+\r
+ CopyMem (&CurrentForm->FormId, &((EFI_IFR_FORM *)OpCodeData)->FormId, sizeof (UINT16));\r
+\r
+ MapMethod = (EFI_IFR_FORM_MAP_METHOD *)(OpCodeData + sizeof (EFI_IFR_FORM_MAP));\r
+ //\r
+ // FormMap Form must contain at least one Map Method.\r
+ //\r
+ if (((EFI_IFR_OP_HEADER *)OpCodeData)->Length < ((UINTN)(UINT8 *)(MapMethod + 1) - (UINTN)OpCodeData)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Try to find the standard form map method.\r
+ //\r
+ while (((UINTN)(UINT8 *)MapMethod - (UINTN)OpCodeData) < ((EFI_IFR_OP_HEADER *)OpCodeData)->Length) {\r
+ if (CompareGuid ((EFI_GUID *)(VOID *)&MapMethod->MethodIdentifier, &gEfiHiiStandardFormGuid)) {\r
+ CopyMem (&CurrentForm->FormTitle, &MapMethod->MethodTitle, sizeof (EFI_STRING_ID));\r
+ CurrentForm->FormType = STANDARD_MAP_FORM_TYPE;\r
+ break;\r
+ }\r
+\r
+ MapMethod++;\r
+ }\r
+\r
+ //\r
+ // If the standard form map method is not found, the first map method title will be used.\r
+ //\r
+ if (CurrentForm->FormTitle == 0) {\r
+ MapMethod = (EFI_IFR_FORM_MAP_METHOD *)(OpCodeData + sizeof (EFI_IFR_FORM_MAP));\r
+ CopyMem (&CurrentForm->FormTitle, &MapMethod->MethodTitle, sizeof (EFI_STRING_ID));\r
+ }\r
+\r
+ ConditionalExprCount = GetConditionalExpressionCount (ExpressForm);\r
+ if ( ConditionalExprCount > 0) {\r
+ //\r
+ // Form is inside of suppressif\r
+ //\r
+ CurrentForm->SuppressExpression = (HII_EXPRESSION_LIST *)AllocateZeroPool (\r
+ (UINTN)(sizeof (HII_EXPRESSION_LIST) + ((ConditionalExprCount -1) * sizeof (HII_EXPRESSION *)))\r
+ );\r
+ if (CurrentForm->SuppressExpression == NULL) {\r
+ FreePool (CurrentForm);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ CurrentForm->SuppressExpression->Count = (UINTN)ConditionalExprCount;\r
+ CurrentForm->SuppressExpression->Signature = HII_EXPRESSION_LIST_SIGNATURE;\r
+ CopyMem (CurrentForm->SuppressExpression->Expression, GetConditionalExpressionList (ExpressForm), (UINTN)(sizeof (HII_EXPRESSION *) * ConditionalExprCount));\r
+ }\r
+\r
+ if (Scope != 0) {\r
+ //\r
+ // Enter scope of a Form, suppressif will be used for Question or Option\r
+ //\r
+ SuppressForQuestion = TRUE;\r
+ }\r
+\r
+ //\r
+ // Insert into Form list of this FormSet\r
+ //\r
+ InsertTailList (&FormSet->FormListHead, &CurrentForm->Link);\r
+ break;\r
+\r
+ //\r
+ // Storage\r
+ //\r
+ case EFI_IFR_VARSTORE_OP:\r
+\r
+ //\r
+ // Create a buffer Storage for this FormSet\r
+ //\r
+ Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_BUFFER, OpCodeData);\r
+ CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE *)OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));\r
+ break;\r
+\r
+ case EFI_IFR_VARSTORE_NAME_VALUE_OP:\r
+\r
+ //\r
+ // Create a name/value Storage for this FormSet\r
+ //\r
+ Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_NAME_VALUE, OpCodeData);\r
+ CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_NAME_VALUE *)OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));\r
+ break;\r
+\r
+ case EFI_IFR_VARSTORE_EFI_OP:\r
+\r
+ //\r
+ // Create a EFI variable Storage for this FormSet\r
+ //\r
+ if (OpCodeLength < sizeof (EFI_IFR_VARSTORE_EFI)) {\r
+ //\r
+ // Create efi varstore with format follow UEFI spec before 2.3.1.\r
+ //\r
+ Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_EFI_VARIABLE, OpCodeData);\r
+ } else {\r
+ //\r
+ // Create efi varstore with format follow UEFI spec 2.3.1 and later.\r
+ //\r
+ Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER, OpCodeData);\r
+ }\r
+\r
+ CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_EFI *)OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));\r
+ break;\r
+\r
+ //\r
+ // DefaultStore\r
+ //\r
+ case EFI_IFR_DEFAULTSTORE_OP:\r
+\r
+ HaveInserted = FALSE;\r
+ DefaultStore = AllocateZeroPool (sizeof (HII_FORMSET_DEFAULTSTORE));\r
+ if (DefaultStore == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ DefaultStore->Signature = HII_FORMSET_DEFAULTSTORE_SIGNATURE;\r
+\r
+ CopyMem (&DefaultStore->DefaultId, &((EFI_IFR_DEFAULTSTORE *)OpCodeData)->DefaultId, sizeof (UINT16));\r
+ CopyMem (&DefaultStore->DefaultName, &((EFI_IFR_DEFAULTSTORE *)OpCodeData)->DefaultName, sizeof (EFI_STRING_ID));\r
+ //\r
+ // Insert it to the DefaultStore list of this Formset with ascending order.\r
+ //\r
+ if (!IsListEmpty (&FormSet->DefaultStoreListHead)) {\r
+ DefaultLink = GetFirstNode (&FormSet->DefaultStoreListHead);\r
+ while (!IsNull (&FormSet->DefaultStoreListHead, DefaultLink)) {\r
+ PreDefaultStore = HII_FORMSET_DEFAULTSTORE_FROM_LINK (DefaultLink);\r
+ DefaultLink = GetNextNode (&FormSet->DefaultStoreListHead, DefaultLink);\r
+ if (DefaultStore->DefaultId < PreDefaultStore->DefaultId) {\r
+ InsertTailList (&PreDefaultStore->Link, &DefaultStore->Link);\r
+ HaveInserted = TRUE;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (!HaveInserted) {\r
+ InsertTailList (&FormSet->DefaultStoreListHead, &DefaultStore->Link);\r
+ }\r
+\r
+ break;\r
+\r
+ //\r
+ // Statements\r
+ //\r
+ case EFI_IFR_SUBTITLE_OP:\r
+\r
+ CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);\r
+ break;\r
+\r
+ case EFI_IFR_TEXT_OP:\r
+\r
+ CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);\r
+ CopyMem (&CurrentStatement->ExtraData.TextTwo, &((EFI_IFR_TEXT *)OpCodeData)->TextTwo, sizeof (EFI_STRING_ID));\r
+ break;\r
+\r
+ case EFI_IFR_RESET_BUTTON_OP:\r
+\r
+ CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);\r
+ CopyMem (&CurrentStatement->ExtraData.DefaultId, &((EFI_IFR_RESET_BUTTON *)OpCodeData)->DefaultId, sizeof (EFI_DEFAULT_ID));\r
+ break;\r
+\r
+ //\r
+ // Questions\r
+ //\r
+ case EFI_IFR_ACTION_OP:\r
+\r
+ CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
+ CurrentStatement->Value.Type = EFI_IFR_TYPE_ACTION;\r
+\r
+ if (OpCodeLength == sizeof (EFI_IFR_ACTION_1)) {\r
+ //\r
+ // No QuestionConfig present, so no configuration string will be processed\r
+ //\r
+ CurrentStatement->ExtraData.QuestionConfig = 0;\r
+ } else {\r
+ CopyMem (&CurrentStatement->ExtraData.QuestionConfig, &((EFI_IFR_ACTION *)OpCodeData)->QuestionConfig, sizeof (EFI_STRING_ID));\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_REF_OP:\r
+\r
+ CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
+ StatementValue = &CurrentStatement->Value;\r
+ StatementValue->Type = EFI_IFR_TYPE_REF;\r
+ if (OpCodeLength >= sizeof (EFI_IFR_REF)) {\r
+ CopyMem (&StatementValue->Value.ref.FormId, &((EFI_IFR_REF *)OpCodeData)->FormId, sizeof (EFI_FORM_ID));\r
+\r
+ if (OpCodeLength >= sizeof (EFI_IFR_REF2)) {\r
+ CopyMem (&StatementValue->Value.ref.QuestionId, &((EFI_IFR_REF2 *)OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));\r
+\r
+ if (OpCodeLength >= sizeof (EFI_IFR_REF3)) {\r
+ CopyMem (&StatementValue->Value.ref.FormSetGuid, &((EFI_IFR_REF3 *)OpCodeData)->FormSetId, sizeof (EFI_GUID));\r
+\r
+ if (OpCodeLength >= sizeof (EFI_IFR_REF4)) {\r
+ CopyMem (&StatementValue->Value.ref.DevicePath, &((EFI_IFR_REF4 *)OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ CurrentStatement->StorageWidth = (UINT16)sizeof (EFI_HII_REF);\r
+ InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);\r
+ break;\r
+\r
+ case EFI_IFR_ONE_OF_OP:\r
+ case EFI_IFR_NUMERIC_OP:\r
+\r
+ CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
+ CurrentStatement->ExtraData.NumData.Flags = ((EFI_IFR_ONE_OF *)OpCodeData)->Flags;\r
+ StatementValue = &CurrentStatement->Value;\r
+\r
+ if (QuestionReferBitField) {\r
+ //\r
+ // Get the bit var store info (bit/byte offset, bit/byte offset)\r
+ //\r
+ CurrentStatement->QuestionReferToBitField = TRUE;\r
+ CurrentStatement->BitStorageWidth = CurrentStatement->ExtraData.NumData.Flags & EDKII_IFR_NUMERIC_SIZE_BIT;\r
+ CurrentStatement->BitVarOffset = CurrentStatement->VarStoreInfo.VarOffset;\r
+ CurrentStatement->VarStoreInfo.VarOffset = CurrentStatement->BitVarOffset / 8;\r
+ TotalBits = CurrentStatement->BitVarOffset % 8 + CurrentStatement->BitStorageWidth;\r
+ CurrentStatement->StorageWidth = (TotalBits % 8 == 0 ? TotalBits / 8 : TotalBits / 8 + 1);\r
+\r
+ //\r
+ // Get the Minimum/Maximum/Step value(Note: bit field type has been stored as UINT32 type)\r
+ //\r
+ CurrentStatement->ExtraData.NumData.Minimum = ((EFI_IFR_NUMERIC *)OpCodeData)->data.u32.MinValue;\r
+ CurrentStatement->ExtraData.NumData.Maximum = ((EFI_IFR_NUMERIC *)OpCodeData)->data.u32.MaxValue;\r
+ CurrentStatement->ExtraData.NumData.Step = ((EFI_IFR_NUMERIC *)OpCodeData)->data.u32.Step;\r
+\r
+ //\r
+ // Update the Flag and type of Minimum/Maximum/Step according to the actual width of bit field,\r
+ // in order to make Browser handle these question with bit varstore correctly.\r
+ //\r
+ ((EFI_IFR_NUMERIC *)OpCodeData)->Flags &= EDKII_IFR_DISPLAY_BIT;\r
+ ((EFI_IFR_NUMERIC *)OpCodeData)->Flags >>= 2;\r
+ switch (CurrentStatement->StorageWidth) {\r
+ case 1:\r
+ ((EFI_IFR_NUMERIC *)OpCodeData)->Flags |= EFI_IFR_TYPE_NUM_SIZE_8;\r
+ ((EFI_IFR_NUMERIC *)OpCodeData)->data.u8.MinValue = (UINT8)CurrentStatement->ExtraData.NumData.Minimum;\r
+ ((EFI_IFR_NUMERIC *)OpCodeData)->data.u8.MaxValue = (UINT8)CurrentStatement->ExtraData.NumData.Maximum;\r
+ ((EFI_IFR_NUMERIC *)OpCodeData)->data.u8.Step = (UINT8)CurrentStatement->ExtraData.NumData.Step;\r
+ StatementValue->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
+ break;\r
+ case 2:\r
+ ((EFI_IFR_NUMERIC *)OpCodeData)->Flags |= EFI_IFR_TYPE_NUM_SIZE_16;\r
+ ((EFI_IFR_NUMERIC *)OpCodeData)->data.u16.MinValue = (UINT16)CurrentStatement->ExtraData.NumData.Minimum;\r
+ ((EFI_IFR_NUMERIC *)OpCodeData)->data.u16.MaxValue = (UINT16)CurrentStatement->ExtraData.NumData.Maximum;\r
+ ((EFI_IFR_NUMERIC *)OpCodeData)->data.u16.Step = (UINT16)CurrentStatement->ExtraData.NumData.Step;\r
+ StatementValue->Type = EFI_IFR_TYPE_NUM_SIZE_16;\r
+ break;\r
+ case 3:\r
+ case 4:\r
+ ((EFI_IFR_NUMERIC *)OpCodeData)->Flags |= EFI_IFR_TYPE_NUM_SIZE_32;\r
+ ((EFI_IFR_NUMERIC *)OpCodeData)->data.u32.MinValue = (UINT32)CurrentStatement->ExtraData.NumData.Minimum;\r
+ ((EFI_IFR_NUMERIC *)OpCodeData)->data.u32.MaxValue = (UINT32)CurrentStatement->ExtraData.NumData.Maximum;\r
+ ((EFI_IFR_NUMERIC *)OpCodeData)->data.u32.Step = (UINT32)CurrentStatement->ExtraData.NumData.Step;\r
+ StatementValue->Type = EFI_IFR_TYPE_NUM_SIZE_32;\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ } else {\r
+ switch (CurrentStatement->ExtraData.NumData.Flags & EFI_IFR_NUMERIC_SIZE) {\r
+ case EFI_IFR_NUMERIC_SIZE_1:\r
+ CurrentStatement->ExtraData.NumData.Minimum = ((EFI_IFR_NUMERIC *)OpCodeData)->data.u8.MinValue;\r
+ CurrentStatement->ExtraData.NumData.Maximum = ((EFI_IFR_NUMERIC *)OpCodeData)->data.u8.MaxValue;\r
+ CurrentStatement->ExtraData.NumData.Step = ((EFI_IFR_NUMERIC *)OpCodeData)->data.u8.Step;\r
+ CurrentStatement->StorageWidth = (UINT16)sizeof (UINT8);\r
+ StatementValue->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
+\r
+ break;\r
+\r
+ case EFI_IFR_NUMERIC_SIZE_2:\r
+ CopyMem (&CurrentStatement->ExtraData.NumData.Minimum, &((EFI_IFR_NUMERIC *)OpCodeData)->data.u16.MinValue, sizeof (UINT16));\r
+ CopyMem (&CurrentStatement->ExtraData.NumData.Maximum, &((EFI_IFR_NUMERIC *)OpCodeData)->data.u16.MaxValue, sizeof (UINT16));\r
+ CopyMem (&CurrentStatement->ExtraData.NumData.Step, &((EFI_IFR_NUMERIC *)OpCodeData)->data.u16.Step, sizeof (UINT16));\r
+ CurrentStatement->StorageWidth = (UINT16)sizeof (UINT16);\r
+ StatementValue->Type = EFI_IFR_TYPE_NUM_SIZE_16;\r
+\r
+ break;\r
+\r
+ case EFI_IFR_NUMERIC_SIZE_4:\r
+ CopyMem (&CurrentStatement->ExtraData.NumData.Minimum, &((EFI_IFR_NUMERIC *)OpCodeData)->data.u32.MinValue, sizeof (UINT32));\r
+ CopyMem (&CurrentStatement->ExtraData.NumData.Maximum, &((EFI_IFR_NUMERIC *)OpCodeData)->data.u32.MaxValue, sizeof (UINT32));\r
+ CopyMem (&CurrentStatement->ExtraData.NumData.Step, &((EFI_IFR_NUMERIC *)OpCodeData)->data.u32.Step, sizeof (UINT32));\r
+ CurrentStatement->StorageWidth = (UINT16)sizeof (UINT32);\r
+ StatementValue->Type = EFI_IFR_TYPE_NUM_SIZE_32;\r
+\r
+ break;\r
+\r
+ case EFI_IFR_NUMERIC_SIZE_8:\r
+ CopyMem (&CurrentStatement->ExtraData.NumData.Minimum, &((EFI_IFR_NUMERIC *)OpCodeData)->data.u64.MinValue, sizeof (UINT64));\r
+ CopyMem (&CurrentStatement->ExtraData.NumData.Maximum, &((EFI_IFR_NUMERIC *)OpCodeData)->data.u64.MaxValue, sizeof (UINT64));\r
+ CopyMem (&CurrentStatement->ExtraData.NumData.Step, &((EFI_IFR_NUMERIC *)OpCodeData)->data.u64.Step, sizeof (UINT64));\r
+ CurrentStatement->StorageWidth = (UINT16)sizeof (UINT64);\r
+ StatementValue->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+\r
+ break;\r
+\r
+ default:\r
+\r
+ break;\r
+ }\r
+ }\r
+\r
+ InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);\r
+\r
+ if ((Operand == EFI_IFR_ONE_OF_OP) && (Scope != 0)) {\r
+ SuppressForOption = TRUE;\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_ORDERED_LIST_OP:\r
+\r
+ CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
+ CurrentStatement->ExtraData.OrderListData.Flags = ((EFI_IFR_ORDERED_LIST *)OpCodeData)->Flags;\r
+ CurrentStatement->ExtraData.OrderListData.MaxContainers = ((EFI_IFR_ORDERED_LIST *)OpCodeData)->MaxContainers;\r
+ CurrentStatement->Value.Type = EFI_IFR_TYPE_BUFFER;\r
+ CurrentStatement->Value.Buffer = NULL;\r
+\r
+ if (Scope != 0) {\r
+ SuppressForOption = TRUE;\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_CHECKBOX_OP:\r
+\r
+ CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
+ CurrentStatement->ExtraData.Flags = ((EFI_IFR_CHECKBOX *)OpCodeData)->Flags;\r
+ CurrentStatement->StorageWidth = (UINT16)sizeof (BOOLEAN);\r
+ CurrentStatement->Value.Type = EFI_IFR_TYPE_BOOLEAN;\r
+\r
+ if (QuestionReferBitField) {\r
+ //\r
+ // Get the bit var store info (bit/byte offset, bit/byte offset)\r
+ //\r
+ CurrentStatement->QuestionReferToBitField = TRUE;\r
+ CurrentStatement->BitStorageWidth = 1;\r
+ CurrentStatement->BitVarOffset = CurrentStatement->VarStoreInfo.VarOffset;\r
+ CurrentStatement->VarStoreInfo.VarOffset = CurrentStatement->BitVarOffset / 8;\r
+ TotalBits = CurrentStatement->BitVarOffset % 8 + CurrentStatement->BitStorageWidth;\r
+ CurrentStatement->StorageWidth = (TotalBits % 8 == 0 ? TotalBits / 8 : TotalBits / 8 + 1);\r
+ }\r
+\r
+ InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);\r
+\r
+ break;\r
+\r
+ case EFI_IFR_STRING_OP:\r
+\r
+ CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
+\r
+ //\r
+ // MinSize is the minimum number of characters that can be accepted for this opcode,\r
+ // MaxSize is the maximum number of characters that can be accepted for this opcode.\r
+ // The characters are stored as Unicode, so the storage width should multiply 2.\r
+ //\r
+ CurrentStatement->ExtraData.StrData.MinSize = ((EFI_IFR_STRING *)OpCodeData)->MinSize;\r
+ CurrentStatement->ExtraData.StrData.MaxSize = ((EFI_IFR_STRING *)OpCodeData)->MaxSize;\r
+ CurrentStatement->ExtraData.StrData.Flags = ((EFI_IFR_STRING *)OpCodeData)->Flags;\r
+ CurrentStatement->StorageWidth = (UINT16)((UINTN)CurrentStatement->ExtraData.StrData.MaxSize * sizeof (CHAR16));\r
+\r
+ CurrentStatement->Value.Type = EFI_IFR_TYPE_STRING;\r
+ CurrentStatement->Value.Buffer = AllocateZeroPool (CurrentStatement->StorageWidth + sizeof (CHAR16));\r
+ if (CurrentStatement->Value.Buffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ CurrentStatement->Value.Value.string = NewHiiString ((CHAR16 *)CurrentStatement->Value.Buffer, FormSet->HiiHandle);\r
+\r
+ InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);\r
+ break;\r
+\r
+ case EFI_IFR_PASSWORD_OP:\r
+\r
+ CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
+\r
+ //\r
+ // MinSize is the minimum number of characters that can be accepted for this opcode,\r
+ // MaxSize is the maximum number of characters that can be accepted for this opcode.\r
+ // The characters are stored as Unicode, so the storage width should multiply 2.\r
+ //\r
+ CopyMem (&CurrentStatement->ExtraData.PwdData.MinSize, &((EFI_IFR_PASSWORD *)OpCodeData)->MinSize, sizeof (UINT16));\r
+ CopyMem (&CurrentStatement->ExtraData.PwdData.MaxSize, &((EFI_IFR_PASSWORD *)OpCodeData)->MaxSize, sizeof (UINT16));\r
+ CurrentStatement->StorageWidth = (UINT16)((UINTN)CurrentStatement->ExtraData.PwdData.MaxSize * sizeof (CHAR16));\r
+\r
+ CurrentStatement->Value.Type = EFI_IFR_TYPE_STRING;\r
+ CurrentStatement->Value.Buffer = AllocateZeroPool ((CurrentStatement->StorageWidth + sizeof (CHAR16)));\r
+ if (CurrentStatement->Value.Buffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ CurrentStatement->Value.Value.string = NewHiiString ((CHAR16 *)CurrentStatement->Value.Buffer, FormSet->HiiHandle);\r
+\r
+ InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);\r
+ break;\r
+\r
+ case EFI_IFR_DATE_OP:\r
+\r
+ CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
+ CurrentStatement->ExtraData.Flags = ((EFI_IFR_DATE *)OpCodeData)->Flags;\r
+ CurrentStatement->Value.Type = EFI_IFR_TYPE_DATE;\r
+\r
+ if ((CurrentStatement->ExtraData.Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_NORMAL) {\r
+ CurrentStatement->StorageWidth = (UINT16)sizeof (EFI_HII_DATE);\r
+\r
+ InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);\r
+ } else {\r
+ //\r
+ // Don't assign storage for RTC type of date/time\r
+ //\r
+ CurrentStatement->Storage = NULL;\r
+ CurrentStatement->StorageWidth = 0;\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_TIME_OP:\r
+\r
+ CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);\r
+ CurrentStatement->ExtraData.Flags = ((EFI_IFR_TIME *)OpCodeData)->Flags;\r
+ CurrentStatement->Value.Type = EFI_IFR_TYPE_TIME;\r
+\r
+ if ((CurrentStatement->ExtraData.Flags & QF_TIME_STORAGE) == QF_TIME_STORAGE_NORMAL) {\r
+ CurrentStatement->StorageWidth = (UINT16)sizeof (EFI_HII_TIME);\r
+\r
+ InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);\r
+ } else {\r
+ //\r
+ // Don't assign storage for RTC type of date/time\r
+ //\r
+ CurrentStatement->Storage = NULL;\r
+ CurrentStatement->StorageWidth = 0;\r
+ }\r
+\r
+ break;\r
+\r
+ //\r
+ // Default\r
+ //\r
+ case EFI_IFR_DEFAULT_OP:\r
+\r
+ //\r
+ // EFI_IFR_DEFAULT appear in scope of a Question,\r
+ // It creates a default value for the current question.\r
+ // A Question may have more than one Default value which have different default types.\r
+ //\r
+ CurrentDefault = AllocateZeroPool (sizeof (HII_QUESTION_DEFAULT));\r
+ if (CurrentDefault == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ CurrentDefault->Signature = HII_QUESTION_DEFAULT_SIGNATURE;\r
+\r
+ CurrentDefault->Value.Type = ((EFI_IFR_DEFAULT *)OpCodeData)->Type;\r
+ CopyMem (&CurrentDefault->DefaultId, &((EFI_IFR_DEFAULT *)OpCodeData)->DefaultId, sizeof (UINT16));\r
+ if (CurrentDefault->Value.Type == EFI_IFR_TYPE_BUFFER) {\r
+ CurrentDefault->Value.BufferLen = (UINT16)(OpCodeLength - OFFSET_OF (EFI_IFR_DEFAULT, Value));\r
+ CurrentDefault->Value.Buffer = AllocateCopyPool (CurrentDefault->Value.BufferLen, &((EFI_IFR_DEFAULT *)OpCodeData)->Value);\r
+ if (CurrentDefault->Value.Buffer == NULL) {\r
+ FreePool (CurrentDefault);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ if (ParentStatement->Operand == EFI_IFR_ORDERED_LIST_OP) {\r
+ ParentStatement->Value.BufferLen = CurrentDefault->Value.BufferLen;\r
+ CopyMem (ParentStatement->Value.Buffer, CurrentDefault->Value.Buffer, ParentStatement->Value.BufferLen);\r
+ }\r
+ } else {\r
+ CopyMem (&CurrentDefault->Value.Value, &((EFI_IFR_DEFAULT *)OpCodeData)->Value, OpCodeLength - OFFSET_OF (EFI_IFR_DEFAULT, Value));\r
+ ExtendValueToU64 (&CurrentDefault->Value);\r
+\r
+ CopyMem (&ParentStatement->Value.Value, &((EFI_IFR_DEFAULT *)OpCodeData)->Value, OpCodeLength - OFFSET_OF (EFI_IFR_DEFAULT, Value));\r
+ ExtendValueToU64 (&ParentStatement->Value);\r
+ }\r
+\r
+ //\r
+ // Insert to Default Value list of current Question\r
+ //\r
+ InsertTailList (&ParentStatement->DefaultListHead, &CurrentDefault->Link);\r
+\r
+ if (Scope != 0) {\r
+ InScopeDefault = TRUE;\r
+ }\r
+\r
+ break;\r
+\r
+ //\r
+ // Option\r
+ //\r
+ case EFI_IFR_ONE_OF_OPTION_OP:\r
+\r
+ if (ParentStatement == NULL) {\r
+ break;\r
+ }\r
+\r
+ CurrentDefault = NULL;\r
+ if (((ParentStatement->Operand == EFI_IFR_ORDERED_LIST_OP) || (ParentStatement->Operand == EFI_IFR_ONE_OF_OP)) &&\r
+ ((((EFI_IFR_ONE_OF_OPTION *)OpCodeData)->Flags & (EFI_IFR_OPTION_DEFAULT | EFI_IFR_OPTION_DEFAULT_MFG)) != 0))\r
+ {\r
+ CurrentDefault = AllocateZeroPool (sizeof (HII_QUESTION_DEFAULT));\r
+ if (CurrentDefault == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ CurrentDefault->Signature = HII_QUESTION_DEFAULT_SIGNATURE;\r
+ if ((((EFI_IFR_ONE_OF_OPTION *)OpCodeData)->Flags & EFI_IFR_OPTION_DEFAULT) != 0) {\r
+ CurrentDefault->DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
+ } else {\r
+ CurrentDefault->DefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
+ }\r
+\r
+ if (ParentStatement->Operand == EFI_IFR_ORDERED_LIST_OP) {\r
+ CurrentDefault->Value.Type = EFI_IFR_TYPE_BUFFER;\r
+ CurrentDefault->Value.BufferLen = (UINT16)(OpCodeLength - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));\r
+ CurrentDefault->Value.Buffer = AllocateCopyPool (CurrentDefault->Value.BufferLen, &((EFI_IFR_ONE_OF_OPTION *)OpCodeData)->Value);\r
+ if (CurrentDefault->Value.Buffer == NULL) {\r
+ FreePool (CurrentDefault);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ } else {\r
+ CurrentDefault->Value.Type = ((EFI_IFR_ONE_OF_OPTION *)OpCodeData)->Type;\r
+ CopyMem (&CurrentDefault->Value.Value, &((EFI_IFR_ONE_OF_OPTION *)OpCodeData)->Value, sizeof (EFI_IFR_TYPE_VALUE));\r
+ ExtendValueToU64 (&CurrentDefault->Value);\r
+ }\r
+\r
+ //\r
+ // Insert to Default Value list of current Question\r
+ //\r
+ InsertTailList (&ParentStatement->DefaultListHead, &CurrentDefault->Link);\r
+ }\r
+\r
+ //\r
+ // EFI_IFR_ONE_OF_OPTION appear in scope of a Question.\r
+ // It create a selection for use in current Question.\r
+ //\r
+ CurrentOption = AllocateZeroPool (sizeof (HII_QUESTION_OPTION));\r
+ if (CurrentOption == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ CurrentOption->Signature = HII_QUESTION_OPTION_SIGNATURE;\r
+ CurrentOption->OpCode = (EFI_IFR_ONE_OF_OPTION *)OpCodeData;\r
+ CurrentOption->Flags = ((EFI_IFR_ONE_OF_OPTION *)OpCodeData)->Flags;\r
+ CurrentOption->Value.Type = ((EFI_IFR_ONE_OF_OPTION *)OpCodeData)->Type;\r
+ CopyMem (&CurrentOption->Text, &((EFI_IFR_ONE_OF_OPTION *)OpCodeData)->Option, sizeof (EFI_STRING_ID));\r
+ CopyMem (&CurrentOption->Value.Value, &((EFI_IFR_ONE_OF_OPTION *)OpCodeData)->Value, OpCodeLength - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));\r
+ ExtendValueToU64 (&CurrentOption->Value);\r
+\r
+ ConditionalExprCount = GetConditionalExpressionCount (ExpressOption);\r
+ if ( ConditionalExprCount > 0) {\r
+ //\r
+ // Form is inside of suppressif\r
+ //\r
+ CurrentOption->SuppressExpression = (HII_EXPRESSION_LIST *)AllocatePool (\r
+ (UINTN)(sizeof (HII_EXPRESSION_LIST) + ((ConditionalExprCount -1) * sizeof (HII_EXPRESSION *)))\r
+ );\r
+ if (CurrentOption->SuppressExpression == NULL) {\r
+ FreePool (CurrentOption);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ CurrentOption->SuppressExpression->Count = (UINTN)ConditionalExprCount;\r
+ CurrentOption->SuppressExpression->Signature = HII_EXPRESSION_LIST_SIGNATURE;\r
+ CopyMem (CurrentOption->SuppressExpression->Expression, GetConditionalExpressionList (ExpressOption), (UINTN)(sizeof (HII_EXPRESSION *) * ConditionalExprCount));\r
+ }\r
+\r
+ //\r
+ // Insert to Option list of current Question\r
+ //\r
+ InsertTailList (&ParentStatement->OptionListHead, &CurrentOption->Link);\r
+\r
+ //\r
+ // Now we know the Storage width of nested Ordered List\r
+ //\r
+ if ((ParentStatement->Operand == EFI_IFR_ORDERED_LIST_OP) && (ParentStatement->Value.Buffer == NULL)) {\r
+ Width = 1;\r
+ switch (CurrentOption->Value.Type) {\r
+ case EFI_IFR_TYPE_NUM_SIZE_8:\r
+ Width = 1;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_16:\r
+ Width = 2;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_32:\r
+ Width = 4;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_64:\r
+ Width = 8;\r
+ break;\r
+\r
+ default:\r
+ //\r
+ // Invalid type for Ordered List\r
+ //\r
+ break;\r
+ }\r
+\r
+ ParentStatement->StorageWidth = (UINT16)(ParentStatement->ExtraData.OrderListData.MaxContainers * Width);\r
+ ParentStatement->Value.Buffer = AllocateZeroPool (ParentStatement->StorageWidth);\r
+ if (ParentStatement->Value.Buffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ ParentStatement->Value.BufferLen = 0;\r
+ ParentStatement->Value.BufferValueType = CurrentOption->Value.Type;\r
+ InitializeRequestElement (FormSet, ParentStatement, CurrentForm);\r
+ }\r
+\r
+ break;\r
+\r
+ //\r
+ // Conditional\r
+ //\r
+ case EFI_IFR_NO_SUBMIT_IF_OP:\r
+ case EFI_IFR_INCONSISTENT_IF_OP:\r
+\r
+ //\r
+ // Create an Expression node\r
+ //\r
+ CurrentExpression = CreateExpression (CurrentForm, OpCodeData);\r
+ CopyMem (&CurrentExpression->ExtraData.Error, &((EFI_IFR_INCONSISTENT_IF *)OpCodeData)->Error, sizeof (EFI_STRING_ID));\r
+\r
+ if (Operand == EFI_IFR_NO_SUBMIT_IF_OP) {\r
+ CurrentExpression->Type = EFI_HII_EXPRESSION_NO_SUBMIT_IF;\r
+ InsertTailList (&ParentStatement->NoSubmitListHead, &CurrentExpression->Link);\r
+ } else {\r
+ CurrentExpression->Type = EFI_HII_EXPRESSION_INCONSISTENT_IF;\r
+ InsertTailList (&ParentStatement->InconsistentListHead, &CurrentExpression->Link);\r
+ }\r
+\r
+ //\r
+ // Take a look at next OpCode to see whether current expression consists\r
+ // of single OpCode\r
+ //\r
+ if (((EFI_IFR_OP_HEADER *)(OpCodeData + OpCodeLength))->Scope == 0) {\r
+ SingleOpCodeExpression = TRUE;\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_WARNING_IF_OP:\r
+\r
+ //\r
+ // Create an Expression node\r
+ //\r
+ CurrentExpression = CreateExpression (CurrentForm, OpCodeData);\r
+ CopyMem (&CurrentExpression->ExtraData.WarningIfData.WarningIfError, &((EFI_IFR_WARNING_IF *)OpCodeData)->Warning, sizeof (EFI_STRING_ID));\r
+ CurrentExpression->ExtraData.WarningIfData.TimeOut = ((EFI_IFR_WARNING_IF *)OpCodeData)->TimeOut;\r
+ CurrentExpression->Type = EFI_HII_EXPRESSION_WARNING_IF;\r
+ InsertTailList (&ParentStatement->WarningListHead, &CurrentExpression->Link);\r
+\r
+ //\r
+ // Take a look at next OpCode to see whether current expression consists\r
+ // of single OpCode\r
+ //\r
+ if (((EFI_IFR_OP_HEADER *)(OpCodeData + OpCodeLength))->Scope == 0) {\r
+ SingleOpCodeExpression = TRUE;\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_SUPPRESS_IF_OP:\r
+\r
+ //\r
+ // Question and Option will appear in scope of this OpCode\r
+ //\r
+ CurrentExpression = CreateExpression (CurrentForm, OpCodeData);\r
+ CurrentExpression->Type = EFI_HII_EXPRESSION_SUPPRESS_IF;\r
+\r
+ if (SuppressForOption) {\r
+ PushConditionalExpression (CurrentExpression, ExpressOption);\r
+ } else if (SuppressForQuestion) {\r
+ PushConditionalExpression (CurrentExpression, ExpressStatement);\r
+ } else {\r
+ PushConditionalExpression (CurrentExpression, ExpressForm);\r
+ }\r
+\r
+ //\r
+ // Take a look at next OpCode to see whether current expression consists\r
+ // of single OpCode\r
+ //\r
+ if (((EFI_IFR_OP_HEADER *)(OpCodeData + OpCodeLength))->Scope == 0) {\r
+ SingleOpCodeExpression = TRUE;\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_GRAY_OUT_IF_OP:\r
+\r
+ //\r
+ // Questions will appear in scope of this OpCode\r
+ //\r
+ CurrentExpression = CreateExpression (CurrentForm, OpCodeData);\r
+ CurrentExpression->Type = EFI_HII_EXPRESSION_GRAY_OUT_IF;\r
+ PushConditionalExpression (CurrentExpression, ExpressStatement);\r
+\r
+ //\r
+ // Take a look at next OpCode to see whether current expression consists\r
+ // of single OpCode\r
+ //\r
+ if (((EFI_IFR_OP_HEADER *)(OpCodeData + OpCodeLength))->Scope == 0) {\r
+ SingleOpCodeExpression = TRUE;\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_DISABLE_IF_OP:\r
+\r
+ //\r
+ // The DisableIf expression should only rely on constant, so it could be\r
+ // evaluated at initialization and it will not be queued\r
+ //\r
+ CurrentExpression = AllocateZeroPool (sizeof (HII_EXPRESSION));\r
+ if (CurrentExpression == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ CurrentExpression->Signature = HII_EXPRESSION_SIGNATURE;\r
+ CurrentExpression->Type = EFI_HII_EXPRESSION_DISABLE_IF;\r
+ InitializeListHead (&CurrentExpression->OpCodeListHead);\r
+\r
+ if (CurrentForm != NULL) {\r
+ //\r
+ // This is DisableIf for Question, enqueue it to Form expression list\r
+ //\r
+ PushConditionalExpression (CurrentExpression, ExpressStatement);\r
+ }\r
+\r
+ OpCodeDisabled = FALSE;\r
+ InScopeDisable = TRUE;\r
+ //\r
+ // Take a look at next OpCode to see whether current expression consists\r
+ // of single OpCode\r
+ //\r
+ if (((EFI_IFR_OP_HEADER *)(OpCodeData + OpCodeLength))->Scope == 0) {\r
+ SingleOpCodeExpression = TRUE;\r
+ }\r
+\r
+ break;\r
+\r
+ //\r
+ // Expression\r
+ //\r
+ case EFI_IFR_VALUE_OP:\r
+\r
+ CurrentExpression = CreateExpression (CurrentForm, OpCodeData);\r
+ CurrentExpression->Type = EFI_HII_EXPRESSION_VALUE;\r
+\r
+ if (InScopeDefault) {\r
+ //\r
+ // Used for default (EFI_IFR_DEFAULT)\r
+ //\r
+ CurrentDefault->ValueExpression = CurrentExpression;\r
+ } else {\r
+ //\r
+ // If used for a question, then the question will be read-only\r
+ //\r
+ // Make sure CurrentStatement is not NULL.\r
+ // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR\r
+ // file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler.\r
+ //\r
+ if (ParentStatement == NULL) {\r
+ break;\r
+ }\r
+\r
+ ParentStatement->ValueExpression = CurrentExpression;\r
+ }\r
+\r
+ //\r
+ // Take a look at next OpCode to see whether current expression consists\r
+ // of single OpCode\r
+ //\r
+ if (((EFI_IFR_OP_HEADER *)(OpCodeData + OpCodeLength))->Scope == 0) {\r
+ SingleOpCodeExpression = TRUE;\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_RULE_OP:\r
+\r
+ CurrentExpression = CreateExpression (CurrentForm, OpCodeData);\r
+ CurrentExpression->Type = EFI_HII_EXPRESSION_RULE;\r
+\r
+ CurrentExpression->ExtraData.RuleId = ((EFI_IFR_RULE *)OpCodeData)->RuleId;\r
+ InsertTailList (&CurrentForm->RuleListHead, &CurrentExpression->Link);\r
+\r
+ //\r
+ // Take a look at next OpCode to see whether current expression consists\r
+ // of single OpCode\r
+ //\r
+ if (((EFI_IFR_OP_HEADER *)(OpCodeData + OpCodeLength))->Scope == 0) {\r
+ SingleOpCodeExpression = TRUE;\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_READ_OP:\r
+\r
+ CurrentExpression = CreateExpression (CurrentForm, OpCodeData);\r
+ CurrentExpression->Type = EFI_HII_EXPRESSION_READ;\r
+\r
+ //\r
+ // Make sure CurrentStatement is not NULL.\r
+ // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR\r
+ // file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler.\r
+ //\r
+ if (ParentStatement == NULL) {\r
+ break;\r
+ }\r
+\r
+ ParentStatement->ReadExpression = CurrentExpression;\r
+\r
+ //\r
+ // Take a look at next OpCode to see whether current expression consists\r
+ // of single OpCode\r
+ //\r
+ if (((EFI_IFR_OP_HEADER *)(OpCodeData + OpCodeLength))->Scope == 0) {\r
+ SingleOpCodeExpression = TRUE;\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_WRITE_OP:\r
+\r
+ CurrentExpression = CreateExpression (CurrentForm, OpCodeData);\r
+ CurrentExpression->Type = EFI_HII_EXPRESSION_WRITE;\r
+\r
+ //\r
+ // Make sure CurrentStatement is not NULL.\r
+ // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR\r
+ // file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler.\r
+ //\r
+ if (ParentStatement == NULL) {\r
+ break;\r
+ }\r
+\r
+ ParentStatement->WriteExpression = CurrentExpression;\r
+\r
+ //\r
+ // Take a look at next OpCode to see whether current expression consists\r
+ // of single OpCode\r
+ //\r
+ if (((EFI_IFR_OP_HEADER *)(OpCodeData + OpCodeLength))->Scope == 0) {\r
+ SingleOpCodeExpression = TRUE;\r
+ }\r
+\r
+ break;\r
+\r
+ //\r
+ // Image\r
+ //\r
+ case EFI_IFR_IMAGE_OP:\r
+ //\r
+ // Get ScopeOpcode from top of stack\r
+ //\r
+ PopScope (&ScopeOpCode);\r
+ PushScope (ScopeOpCode);\r
+\r
+ switch (ScopeOpCode) {\r
+ case EFI_IFR_FORM_SET_OP:\r
+\r
+ ImageId = &FormSet->ImageId;\r
+ break;\r
+\r
+ case EFI_IFR_FORM_OP:\r
+ case EFI_IFR_FORM_MAP_OP:\r
+\r
+ if (CurrentForm != NULL) {\r
+ ImageId = &CurrentForm->ImageId;\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_ONE_OF_OPTION_OP:\r
+\r
+ if (CurrentOption != NULL) {\r
+ ImageId = &CurrentOption->ImageId;\r
+ }\r
+\r
+ break;\r
+\r
+ default:\r
+\r
+ //\r
+ // Make sure CurrentStatement is not NULL.\r
+ // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR\r
+ // file is wrongly generated by tools such as VFR Compiler.\r
+ //\r
+ if (ParentStatement != NULL) {\r
+ ImageId = &ParentStatement->ImageId;\r
+ }\r
+\r
+ break;\r
+ }\r
+\r
+ CopyMem (ImageId, &((EFI_IFR_IMAGE *)OpCodeData)->Id, sizeof (EFI_IMAGE_ID));\r
+ break;\r
+\r
+ //\r
+ // Refresh\r
+ //\r
+ case EFI_IFR_REFRESH_OP:\r
+\r
+ if (ParentStatement != NULL) {\r
+ ParentStatement->RefreshInterval = ((EFI_IFR_REFRESH *)OpCodeData)->RefreshInterval;\r
+ }\r
+\r
+ break;\r
+\r
+ //\r
+ // Refresh guid.\r
+ //\r
+ case EFI_IFR_REFRESH_ID_OP:\r
+ //\r
+ // Get ScopeOpcode from top of stack\r
+ //\r
+ PopScope (&ScopeOpCode);\r
+ PushScope (ScopeOpCode);\r
+\r
+ switch (ScopeOpCode) {\r
+ case EFI_IFR_FORM_OP:\r
+ case EFI_IFR_FORM_MAP_OP:\r
+\r
+ if (CurrentForm != NULL) {\r
+ CopyMem (&CurrentForm->RefreshGuid, &((EFI_IFR_REFRESH_ID *)OpCodeData)->RefreshEventGroupId, sizeof (EFI_GUID));\r
+ }\r
+\r
+ break;\r
+\r
+ default:\r
+\r
+ if (ParentStatement != NULL) {\r
+ if (ParentStatement->Operand == EFI_IFR_NUMERIC_OP) {\r
+ CopyMem (&ParentStatement->ExtraData.NumData.Guid, &((EFI_IFR_REFRESH_ID *)OpCodeData)->RefreshEventGroupId, sizeof (EFI_GUID));\r
+ }\r
+ }\r
+\r
+ break;\r
+ }\r
+\r
+ break;\r
+\r
+ //\r
+ // Modal tag\r
+ //\r
+ case EFI_IFR_MODAL_TAG_OP:\r
+\r
+ if (CurrentForm != NULL) {\r
+ CurrentForm->ModalForm = TRUE;\r
+ }\r
+\r
+ break;\r
+\r
+ //\r
+ // Lock tag, used by form and statement.\r
+ //\r
+ case EFI_IFR_LOCKED_OP:\r
+ //\r
+ // Get ScopeOpcode from top of stack\r
+ //\r
+ PopScope (&ScopeOpCode);\r
+ PushScope (ScopeOpCode);\r
+\r
+ switch (ScopeOpCode) {\r
+ case EFI_IFR_FORM_OP:\r
+ case EFI_IFR_FORM_MAP_OP:\r
+\r
+ if (CurrentForm != NULL) {\r
+ CurrentForm->Locked = TRUE;\r
+ }\r
+\r
+ break;\r
+\r
+ default:\r
+\r
+ if (ParentStatement != NULL) {\r
+ ParentStatement->Locked = TRUE;\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+ //\r
+ // Vendor specific\r
+ //\r
+ case EFI_IFR_GUID_OP:\r
+ CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);\r
+ if (CompareGuid ((EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)), &gEdkiiIfrBitVarstoreGuid)) {\r
+ Scope = 0;\r
+ QuestionReferBitField = TRUE;\r
+ }\r
+\r
+ break;\r
+\r
+ //\r
+ // Scope End\r
+ //\r
+ case EFI_IFR_END_OP:\r
+ QuestionReferBitField = FALSE;\r
+ Status = PopScope (&ScopeOpCode);\r
+ if (EFI_ERROR (Status)) {\r
+ ResetScopeStack ();\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Parent statement end tag found, update ParentStatement info.\r
+ //\r
+ if (IsStatementOpCode (ScopeOpCode) && (ParentStatement != NULL) && (ParentStatement->Operand == ScopeOpCode)) {\r
+ ParentStatement = ParentStatement->ParentStatement;\r
+ }\r
+\r
+ switch (ScopeOpCode) {\r
+ case EFI_IFR_FORM_SET_OP:\r
+ //\r
+ // End of FormSet, update FormSet IFR binary length\r
+ // to stop parsing substantial OpCodes\r
+ //\r
+ FormSet->IfrBinaryLength = OpCodeOffset;\r
+ break;\r
+\r
+ case EFI_IFR_FORM_OP:\r
+ case EFI_IFR_FORM_MAP_OP:\r
+ //\r
+ // End of Form\r
+ //\r
+ CurrentForm = NULL;\r
+ SuppressForQuestion = FALSE;\r
+ break;\r
+\r
+ case EFI_IFR_ONE_OF_OPTION_OP:\r
+ //\r
+ // End of Option\r
+ //\r
+ CurrentOption = NULL;\r
+ break;\r
+\r
+ case EFI_IFR_NO_SUBMIT_IF_OP:\r
+ case EFI_IFR_INCONSISTENT_IF_OP:\r
+ case EFI_IFR_WARNING_IF_OP:\r
+ //\r
+ // Ignore end of EFI_IFR_NO_SUBMIT_IF and EFI_IFR_INCONSISTENT_IF\r
+ //\r
+ break;\r
+\r
+ case EFI_IFR_SUPPRESS_IF_OP:\r
+ if (SuppressForOption) {\r
+ PopConditionalExpression (ExpressOption);\r
+ } else if (SuppressForQuestion) {\r
+ PopConditionalExpression (ExpressStatement);\r
+ } else {\r
+ PopConditionalExpression (ExpressForm);\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_GRAY_OUT_IF_OP:\r
+ PopConditionalExpression (ExpressStatement);\r
+ break;\r
+\r
+ case EFI_IFR_DISABLE_IF_OP:\r
+ if (CurrentForm != NULL) {\r
+ PopConditionalExpression (ExpressStatement);\r
+ }\r
+\r
+ InScopeDisable = FALSE;\r
+ OpCodeDisabled = FALSE;\r
+ break;\r
+\r
+ case EFI_IFR_ONE_OF_OP:\r
+ case EFI_IFR_ORDERED_LIST_OP:\r
+ SuppressForOption = FALSE;\r
+ break;\r
+\r
+ case EFI_IFR_DEFAULT_OP:\r
+ InScopeDefault = FALSE;\r
+ break;\r
+\r
+ case EFI_IFR_MAP_OP:\r
+\r
+ //\r
+ // Get current Map Expression List.\r
+ //\r
+ Status = PopMapExpressionList ((VOID **)&MapExpressionList);\r
+ if (Status == EFI_ACCESS_DENIED) {\r
+ MapExpressionList = NULL;\r
+ }\r
+\r
+ //\r
+ // Get current expression.\r
+ //\r
+ Status = PopCurrentExpression ((VOID **)&CurrentExpression);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (MapScopeDepth > 0) {\r
+ MapScopeDepth--;\r
+ }\r
+\r
+ break;\r
+\r
+ default:\r
+\r
+ if (IsExpressionOpCode (ScopeOpCode)) {\r
+ if (InScopeDisable && (CurrentForm == NULL)) {\r
+ //\r
+ // This is DisableIf expression for Form, it should be a constant expression\r
+ //\r
+ Status = EvaluateHiiExpression (FormSet, CurrentForm, CurrentExpression);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ OpCodeDisabled = IsHiiValueTrue (&CurrentExpression->Result);\r
+\r
+ //\r
+ // DisableIf Expression is only used once and not queued, free it\r
+ //\r
+ DestroyExpression (CurrentExpression);\r
+ }\r
+\r
+ //\r
+ // End of current Expression\r
+ //\r
+ CurrentExpression = NULL;\r
+ }\r
+\r
+ break;\r
+ }\r
+\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ if (IsStatementOpCode (Operand)) {\r
+ CurrentStatement->ParentStatement = ParentStatement;\r
+ if (Scope != 0) {\r
+ //\r
+ // Scope != 0, other statements or options may nest in this statement.\r
+ // Update the ParentStatement info.\r
+ //\r
+ ParentStatement = CurrentStatement;\r
+ }\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+/** @file\r
+ HII internal header file.\r
+\r
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>\r
+ Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.\r
+\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#ifndef HII_INTERNAL_H_\r
+#define HII_INTERNAL_H_\r
+\r
+#include <Uefi.h>\r
+\r
+#include <Protocol/UnicodeCollation.h>\r
+#include <Protocol/HiiConfigRouting.h>\r
+#include <Protocol/HiiDatabase.h>\r
+#include <Protocol/UserManager.h>\r
+#include <Protocol/DevicePathFromText.h>\r
+#include <Protocol/RegularExpressionProtocol.h>\r
+\r
+#include <Guid/MdeModuleHii.h>\r
+#include <Guid/ZeroGuid.h>\r
+#include <Guid/HiiPlatformSetupFormset.h>\r
+#include <Guid/HiiFormMapMethodGuid.h>\r
+\r
+#include <Library/PrintLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/HiiLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/UefiLib.h>\r
+\r
+#include "HiiExpression.h"\r
+#include <Library/HiiUtilityLib.h>\r
+\r
+#define EXPRESSION_STACK_SIZE_INCREMENT 0x100\r
+#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))\r
+\r
+///\r
+/// Definition of HII_FORM_CONFIG_REQUEST\r
+//\r
+typedef struct {\r
+ UINTN Signature;\r
+ LIST_ENTRY Link;\r
+\r
+ CHAR16 *ConfigRequest; ///< <ConfigRequest> = <ConfigHdr> + <RequestElement>\r
+ CHAR16 *ConfigAltResp; ///< Alt config response string for this ConfigRequest.\r
+ UINTN ElementCount; ///< Number of <RequestElement> in the <ConfigRequest>\r
+ UINTN SpareStrLen;\r
+ CHAR16 *RestoreConfigRequest; ///< When submit form fail, the element need to be restored\r
+ CHAR16 *SyncConfigRequest; ///< When submit form fail, the element need to be synced\r
+\r
+ HII_FORMSET_STORAGE *Storage;\r
+} HII_FORM_CONFIG_REQUEST;\r
+\r
+#define HII_FORM_CONFIG_REQUEST_SIGNATURE SIGNATURE_32 ('F', 'C', 'R', 'S')\r
+#define HII_FORM_CONFIG_REQUEST_FROM_LINK(a) CR (a, HII_FORM_CONFIG_REQUEST, Link, HII_FORM_CONFIG_REQUEST_SIGNATURE)\r
+\r
+///\r
+/// Incremental string length of ConfigRequest\r
+///\r
+#define CONFIG_REQUEST_STRING_INCREMENTAL 1024\r
+\r
+/**\r
+ Allocate new memory and then copy the Unicode string Source to Destination.\r
+\r
+ @param[in,out] Dest Location to copy string\r
+ @param[in] Src String to copy\r
+\r
+**/\r
+VOID\r
+NewStringCopy (\r
+ IN OUT CHAR16 **Dest,\r
+ IN CHAR16 *Src\r
+ );\r
+\r
+/**\r
+ Set Value of given Name in a NameValue Storage.\r
+\r
+ @param[in] Storage The NameValue Storage.\r
+ @param[in] Name The Name.\r
+ @param[in] Value The Value to set.\r
+ @param[out] ReturnNode The node use the input name.\r
+\r
+ @retval EFI_SUCCESS Value found for given Name.\r
+ @retval EFI_NOT_FOUND No such Name found in NameValue storage.\r
+\r
+**/\r
+EFI_STATUS\r
+SetValueByName (\r
+ IN HII_FORMSET_STORAGE *Storage,\r
+ IN CHAR16 *Name,\r
+ IN CHAR16 *Value,\r
+ OUT HII_NAME_VALUE_NODE **ReturnNode\r
+ );\r
+\r
+/**\r
+ Get bit field value from the buffer and then set the value for the question.\r
+ Note: Data type UINT32 can cover all the bit field value.\r
+\r
+ @param[in] Question The question refer to bit field.\r
+ @param[in] Buffer Point to the buffer which the question value get from.\r
+ @param[out] QuestionValue The Question Value retrieved from Bits.\r
+\r
+**/\r
+VOID\r
+GetBitsQuestionValue (\r
+ IN HII_STATEMENT *Question,\r
+ IN UINT8 *Buffer,\r
+ OUT HII_STATEMENT_VALUE *QuestionValue\r
+ );\r
+\r
+/**\r
+ Set bit field value to the buffer.\r
+ Note: Data type UINT32 can cover all the bit field value.\r
+\r
+ @param[in] Question The question refer to bit field.\r
+ @param[in,out] Buffer Point to the buffer which the question value set to.\r
+ @param[in] Value The bit field value need to set.\r
+\r
+**/\r
+VOID\r
+SetBitsQuestionValue (\r
+ IN HII_STATEMENT *Question,\r
+ IN OUT UINT8 *Buffer,\r
+ IN UINT32 Value\r
+ );\r
+\r
+/**\r
+ Convert the buffer value to HiiValue.\r
+\r
+ @param[in] Question The question.\r
+ @param[in] Value Unicode buffer save the question value.\r
+ @param[out] QuestionValue The Question Value retrieved from Buffer.\r
+\r
+ @retval Status whether convert the value success.\r
+\r
+**/\r
+EFI_STATUS\r
+BufferToQuestionValue (\r
+ IN HII_STATEMENT *Question,\r
+ IN CHAR16 *Value,\r
+ OUT HII_STATEMENT_VALUE *QuestionValue\r
+ );\r
+\r
+/**\r
+ Get the string based on the StringId and HII Package List Handle.\r
+\r
+ @param[in] Token The String's ID.\r
+ @param[in] HiiHandle The package list in the HII database to search for\r
+ the specified string.\r
+\r
+ @return The output string.\r
+\r
+**/\r
+CHAR16 *\r
+GetTokenString (\r
+ IN EFI_STRING_ID Token,\r
+ IN EFI_HII_HANDLE HiiHandle\r
+ );\r
+\r
+/**\r
+ Converts the unicode character of the string from uppercase to lowercase.\r
+ This is a internal function.\r
+\r
+ @param[in] ConfigString String to be converted\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+HiiStringToLowercase (\r
+ IN EFI_STRING ConfigString\r
+ );\r
+\r
+/**\r
+ Evaluate if the result is a non-zero value.\r
+\r
+ @param[in] Result The result to be evaluated.\r
+\r
+ @retval TRUE It is a non-zero value.\r
+ @retval FALSE It is a zero value.\r
+\r
+**/\r
+BOOLEAN\r
+IsHiiValueTrue (\r
+ IN EFI_HII_VALUE *Result\r
+ );\r
+\r
+/**\r
+ Set a new string to string package.\r
+\r
+ @param[in] String A pointer to the Null-terminated Unicode string\r
+ to add or update in the String Package associated\r
+ with HiiHandle.\r
+ @param[in] HiiHandle A handle that was previously registered in the\r
+ HII Database.\r
+\r
+ @return the Id for this new string.\r
+\r
+**/\r
+EFI_STRING_ID\r
+NewHiiString (\r
+ IN CHAR16 *String,\r
+ IN EFI_HII_HANDLE HiiHandle\r
+ );\r
+\r
+/**\r
+ Perform nosubmitif check for a Form.\r
+\r
+ @param[in] FormSet FormSet data structure.\r
+ @param[in] Form Form data structure.\r
+ @param[in] Question The Question to be validated.\r
+\r
+ @retval EFI_SUCCESS Form validation pass.\r
+ @retval other Form validation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+ValidateNoSubmit (\r
+ IN HII_FORMSET *FormSet,\r
+ IN HII_FORM *Form,\r
+ IN HII_STATEMENT *Question\r
+ );\r
+\r
+/**\r
+ Perform NoSubmit check for each Form in FormSet.\r
+\r
+ @param[in] FormSet FormSet data structure.\r
+ @param[in,out] CurrentForm Current input form data structure.\r
+ @param[out] Statement The statement for this check.\r
+\r
+ @retval EFI_SUCCESS Form validation pass.\r
+ @retval other Form validation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+NoSubmitCheck (\r
+ IN HII_FORMSET *FormSet,\r
+ IN OUT HII_FORM **CurrentForm,\r
+ OUT HII_STATEMENT **Statement\r
+ );\r
+\r
+/**\r
+ Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.\r
+\r
+ @param[in] Storage The Storage to be converted.\r
+ @param[in] ConfigResp The returned <ConfigResp>.\r
+ @param[in] ConfigRequest The ConfigRequest string.\r
+\r
+ @retval EFI_SUCCESS Convert success.\r
+ @retval EFI_INVALID_PARAMETER Incorrect storage type.\r
+\r
+**/\r
+EFI_STATUS\r
+StorageToConfigResp (\r
+ IN HII_FORMSET_STORAGE *Storage,\r
+ IN CHAR16 **ConfigResp,\r
+ IN CHAR16 *ConfigRequest\r
+ );\r
+\r
+/**\r
+ Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.\r
+\r
+ @param[in] Storage The Storage to receive the settings.\r
+ @param[in] ConfigResp The <ConfigResp> to be converted.\r
+\r
+ @retval EFI_SUCCESS Convert success.\r
+ @retval EFI_INVALID_PARAMETER Incorrect storage type.\r
+\r
+**/\r
+EFI_STATUS\r
+ConfigRespToStorage (\r
+ IN HII_FORMSET_STORAGE *Storage,\r
+ IN CHAR16 *ConfigResp\r
+ );\r
+\r
+/**\r
+ Fetch the Ifr binary data of a FormSet.\r
+\r
+ @param[in] Handle PackageList Handle\r
+ @param[in,out] FormSetGuid On input, GUID or class GUID of a formset. If not\r
+ specified (NULL or zero GUID), take the first\r
+ FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
+ found in package list.\r
+ On output, GUID of the formset found(if not NULL).\r
+ @param[out] BinaryLength The length of the FormSet IFR binary.\r
+ @param[out] BinaryData The buffer designed to receive the FormSet.\r
+\r
+ @retval EFI_SUCCESS Buffer filled with the requested FormSet.\r
+ BufferLength was updated.\r
+ @retval EFI_INVALID_PARAMETER The handle is unknown.\r
+ @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot\r
+ be found with the requested FormId.\r
+\r
+**/\r
+EFI_STATUS\r
+GetIfrBinaryData (\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN OUT EFI_GUID *FormSetGuid,\r
+ OUT UINTN *BinaryLength,\r
+ OUT UINT8 **BinaryData\r
+ );\r
+\r
+/**\r
+ Fill storage with settings requested from Configuration Driver.\r
+\r
+ @param[in] FormSet FormSet data structure.\r
+ @param[in] Storage Buffer Storage.\r
+\r
+**/\r
+VOID\r
+LoadFormSetStorage (\r
+ IN HII_FORMSET *FormSet,\r
+ IN HII_FORMSET_STORAGE *Storage\r
+ );\r
+\r
+/**\r
+ Free resources of a Form.\r
+\r
+ @param[in] FormSet Pointer of the FormSet\r
+ @param[in,out] Form Pointer of the Form.\r
+\r
+**/\r
+VOID\r
+DestroyForm (\r
+ IN HII_FORMSET *FormSet,\r
+ IN OUT HII_FORM *Form\r
+ );\r
+\r
+/**\r
+ Get formset storage based on the input varstoreid info.\r
+\r
+ @param[in] FormSet Pointer of the current FormSet.\r
+ @param[in] VarStoreId Varstore ID info.\r
+\r
+ @return Pointer to a HII_FORMSET_STORAGE data structure.\r
+\r
+**/\r
+HII_FORMSET_STORAGE *\r
+GetFstStgFromVarId (\r
+ IN HII_FORMSET *FormSet,\r
+ IN EFI_VARSTORE_ID VarStoreId\r
+ );\r
+\r
+/**\r
+ Zero extend integer/boolean/date/time to UINT64 for comparing.\r
+\r
+ @param[in] Value HII Value to be converted.\r
+\r
+**/\r
+VOID\r
+ExtendValueToU64 (\r
+ IN HII_STATEMENT_VALUE *Value\r
+ );\r
+\r
+/**\r
+ Parse opcodes in the formset IFR binary.\r
+\r
+ @param[in] FormSet Pointer of the FormSet data structure.\r
+\r
+ @retval EFI_SUCCESS Opcode parse success.\r
+ @retval Other Opcode parse fail.\r
+\r
+**/\r
+EFI_STATUS\r
+ParseOpCodes (\r
+ IN HII_FORMSET *FormSet\r
+ );\r
+\r
+#endif // HII_INTERNAL_H_\r
--- /dev/null
+/** @file\r
+ HII utility internal functions.\r
+\r
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>\r
+ Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.\r
+\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include "HiiInternal.h"\r
+\r
+CHAR16 *mUnknownString = L"!";\r
+CHAR16 *gEmptyString = L"";\r
+\r
+EFI_HII_VALUE *mExpressionEvaluationStack = NULL;\r
+EFI_HII_VALUE *mExpressionEvaluationStackEnd = NULL;\r
+EFI_HII_VALUE *mExpressionEvaluationStackPointer = NULL;\r
+UINTN mExpressionEvaluationStackOffset = 0;\r
+\r
+//\r
+// Unicode collation protocol interface\r
+//\r
+EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollation = NULL;\r
+EFI_USER_MANAGER_PROTOCOL *mUserManager = NULL;\r
+\r
+/**\r
+ Allocate new memory and then copy the Unicode string Source to Destination.\r
+\r
+ @param[in,out] Dest Location to copy string\r
+ @param[in] Src String to copy\r
+\r
+**/\r
+VOID\r
+NewStringCopy (\r
+ IN OUT CHAR16 **Dest,\r
+ IN CHAR16 *Src\r
+ )\r
+{\r
+ if (*Dest != NULL) {\r
+ FreePool (*Dest);\r
+ }\r
+\r
+ *Dest = AllocateCopyPool (StrSize (Src), Src);\r
+}\r
+\r
+/**\r
+ Set Value of given Name in a NameValue Storage.\r
+\r
+ @param[in] Storage The NameValue Storage.\r
+ @param[in] Name The Name.\r
+ @param[in] Value The Value to set.\r
+ @param[out] ReturnNode The node use the input name.\r
+\r
+ @retval EFI_SUCCESS Value found for given Name.\r
+ @retval EFI_NOT_FOUND No such Name found in NameValue storage.\r
+\r
+**/\r
+EFI_STATUS\r
+SetValueByName (\r
+ IN HII_FORMSET_STORAGE *Storage,\r
+ IN CHAR16 *Name,\r
+ IN CHAR16 *Value,\r
+ OUT HII_NAME_VALUE_NODE **ReturnNode\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ HII_NAME_VALUE_NODE *Node;\r
+ CHAR16 *Buffer;\r
+\r
+ Link = GetFirstNode (&Storage->NameValueList);\r
+ while (!IsNull (&Storage->NameValueList, Link)) {\r
+ Node = HII_NAME_VALUE_NODE_FROM_LINK (Link);\r
+\r
+ if (StrCmp (Name, Node->Name) == 0) {\r
+ Buffer = Node->Value;\r
+ if (Buffer != NULL) {\r
+ FreePool (Buffer);\r
+ }\r
+\r
+ Buffer = AllocateCopyPool (StrSize (Value), Value);\r
+ if (Buffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Node->Value = Buffer;\r
+\r
+ if (ReturnNode != NULL) {\r
+ *ReturnNode = Node;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Link = GetNextNode (&Storage->NameValueList, Link);\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+ Get bit field value from the buffer and then set the value for the question.\r
+ Note: Data type UINT32 can cover all the bit field value.\r
+\r
+ @param[in] Question The question refer to bit field.\r
+ @param[in] Buffer Point to the buffer which the question value get from.\r
+ @param[out] QuestionValue The Question Value retrieved from Bits.\r
+\r
+**/\r
+VOID\r
+GetBitsQuestionValue (\r
+ IN HII_STATEMENT *Question,\r
+ IN UINT8 *Buffer,\r
+ OUT HII_STATEMENT_VALUE *QuestionValue\r
+ )\r
+{\r
+ UINTN StartBit;\r
+ UINTN EndBit;\r
+ UINT32 RetVal;\r
+ UINT32 BufferValue;\r
+\r
+ StartBit = Question->BitVarOffset % 8;\r
+ EndBit = StartBit + Question->BitStorageWidth - 1;\r
+\r
+ CopyMem ((UINT8 *)&BufferValue, Buffer, Question->StorageWidth);\r
+\r
+ RetVal = BitFieldRead32 (BufferValue, StartBit, EndBit);\r
+\r
+ //\r
+ // Set question value.\r
+ // Note: Since Question with BufferValue (orderedlist, password, string)are not supported to refer bit field.\r
+ // Only oneof/checkbox/oneof can support bit field.So we can copy the value to the HiiValue of Question directly.\r
+ //\r
+ CopyMem ((UINT8 *)&QuestionValue->Value, (UINT8 *)&RetVal, Question->StorageWidth);\r
+}\r
+\r
+/**\r
+ Set bit field value to the buffer.\r
+ Note: Data type UINT32 can cover all the bit field value.\r
+\r
+ @param[in] Question The question refer to bit field.\r
+ @param[in,out] Buffer Point to the buffer which the question value set to.\r
+ @param[in] Value The bit field value need to set.\r
+\r
+**/\r
+VOID\r
+SetBitsQuestionValue (\r
+ IN HII_STATEMENT *Question,\r
+ IN OUT UINT8 *Buffer,\r
+ IN UINT32 Value\r
+ )\r
+{\r
+ UINT32 Operand;\r
+ UINTN StartBit;\r
+ UINTN EndBit;\r
+ UINT32 RetVal;\r
+\r
+ StartBit = Question->BitVarOffset % 8;\r
+ EndBit = StartBit + Question->BitStorageWidth - 1;\r
+\r
+ CopyMem ((UINT8 *)&Operand, Buffer, Question->StorageWidth);\r
+ RetVal = BitFieldWrite32 (Operand, StartBit, EndBit, Value);\r
+ CopyMem (Buffer, (UINT8 *)&RetVal, Question->StorageWidth);\r
+}\r
+\r
+/**\r
+ Convert the buffer value to HiiValue.\r
+\r
+ @param[in] Question The question.\r
+ @param[in] Value Unicode buffer save the question value.\r
+ @param[out] QuestionValue The Question Value retrieved from Buffer.\r
+\r
+ @retval Status whether convert the value success.\r
+\r
+**/\r
+EFI_STATUS\r
+BufferToQuestionValue (\r
+ IN HII_STATEMENT *Question,\r
+ IN CHAR16 *Value,\r
+ OUT HII_STATEMENT_VALUE *QuestionValue\r
+ )\r
+{\r
+ CHAR16 *StringPtr;\r
+ BOOLEAN IsBufferStorage;\r
+ CHAR16 *DstBuf;\r
+ CHAR16 TempChar;\r
+ UINTN LengthStr;\r
+ UINT8 *Dst;\r
+ CHAR16 TemStr[5];\r
+ UINTN Index;\r
+ UINT8 DigitUint8;\r
+ BOOLEAN IsString;\r
+ UINTN Length;\r
+ EFI_STATUS Status;\r
+ UINT8 *Buffer;\r
+\r
+ Buffer = NULL;\r
+\r
+ IsString = (BOOLEAN)((QuestionValue->Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);\r
+ if ((Question->Storage->Type == EFI_HII_VARSTORE_BUFFER) ||\r
+ (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER))\r
+ {\r
+ IsBufferStorage = TRUE;\r
+ } else {\r
+ IsBufferStorage = FALSE;\r
+ }\r
+\r
+ //\r
+ // Question Value is provided by Buffer Storage or NameValue Storage\r
+ //\r
+ if ((QuestionValue->Type == EFI_IFR_TYPE_STRING) || (QuestionValue->Type == EFI_IFR_TYPE_BUFFER)) {\r
+ //\r
+ // This Question is password or orderedlist\r
+ //\r
+ if (QuestionValue->Buffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Dst = QuestionValue->Buffer;\r
+ } else {\r
+ //\r
+ // Other type of Questions\r
+ //\r
+ if (Question->QuestionReferToBitField) {\r
+ Buffer = (UINT8 *)AllocateZeroPool (Question->StorageWidth);\r
+ if (Buffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Dst = Buffer;\r
+ } else {\r
+ Dst = (UINT8 *)&QuestionValue->Value;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Temp cut at the end of this section, end with '\0' or '&'.\r
+ //\r
+ StringPtr = Value;\r
+ while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
+ StringPtr++;\r
+ }\r
+\r
+ TempChar = *StringPtr;\r
+ *StringPtr = L'\0';\r
+\r
+ LengthStr = StrLen (Value);\r
+\r
+ //\r
+ // Value points to a Unicode hexadecimal string, we need to convert the string to the value with CHAR16/UINT8...type.\r
+ // When generating the Value string, we follow this rule: 1 byte -> 2 Unicode characters (for string: 2 byte(CHAR16) ->4 Unicode characters).\r
+ // So the maximum value string length of a question is : Question->StorageWidth * 2.\r
+ // If the value string length > Question->StorageWidth * 2, only set the string length as Question->StorageWidth * 2, then convert.\r
+ //\r
+ if (LengthStr > (UINTN)Question->StorageWidth * 2) {\r
+ Length = (UINTN)Question->StorageWidth * 2;\r
+ } else {\r
+ Length = LengthStr;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ if (!IsBufferStorage && IsString) {\r
+ //\r
+ // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
+ // Add string tail char L'\0' into Length\r
+ //\r
+ DstBuf = (CHAR16 *)Dst;\r
+ ZeroMem (TemStr, sizeof (TemStr));\r
+ for (Index = 0; Index < Length; Index += 4) {\r
+ StrnCpyS (TemStr, sizeof (TemStr) / sizeof (CHAR16), Value + Index, 4);\r
+ DstBuf[Index/4] = (CHAR16)StrHexToUint64 (TemStr);\r
+ }\r
+\r
+ //\r
+ // Add tailing L'\0' character\r
+ //\r
+ DstBuf[Index/4] = L'\0';\r
+ } else {\r
+ ZeroMem (TemStr, sizeof (TemStr));\r
+ for (Index = 0; Index < Length; Index++) {\r
+ TemStr[0] = Value[LengthStr - Index - 1];\r
+ DigitUint8 = (UINT8)StrHexToUint64 (TemStr);\r
+ if ((Index & 1) == 0) {\r
+ Dst[Index/2] = DigitUint8;\r
+ } else {\r
+ Dst[Index/2] = (UINT8)((DigitUint8 << 4) + Dst[Index/2]);\r
+ }\r
+ }\r
+ }\r
+\r
+ *StringPtr = TempChar;\r
+\r
+ if ((Buffer != NULL) && Question->QuestionReferToBitField) {\r
+ GetBitsQuestionValue (Question, Buffer, QuestionValue);\r
+ FreePool (Buffer);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Get the string based on the StringId and HII Package List Handle.\r
+\r
+ @param[in] Token The String's ID.\r
+ @param[in] HiiHandle The package list in the HII database to search for\r
+ the specified string.\r
+\r
+ @return The output string.\r
+\r
+**/\r
+CHAR16 *\r
+GetTokenString (\r
+ IN EFI_STRING_ID Token,\r
+ IN EFI_HII_HANDLE HiiHandle\r
+ )\r
+{\r
+ EFI_STRING String;\r
+\r
+ if (HiiHandle == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ String = HiiGetString (HiiHandle, Token, NULL);\r
+ if (String == NULL) {\r
+ String = AllocateCopyPool (StrSize (mUnknownString), mUnknownString);\r
+ if (String == NULL) {\r
+ return NULL;\r
+ }\r
+ }\r
+\r
+ return (CHAR16 *)String;\r
+}\r
+\r
+/**\r
+ Converts the unicode character of the string from uppercase to lowercase.\r
+ This is a internal function.\r
+\r
+ @param[in] ConfigString String to be converted\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+HiiStringToLowercase (\r
+ IN EFI_STRING ConfigString\r
+ )\r
+{\r
+ EFI_STRING String;\r
+ BOOLEAN Lower;\r
+\r
+ //\r
+ // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
+ //\r
+ for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {\r
+ if (*String == L'=') {\r
+ Lower = TRUE;\r
+ } else if (*String == L'&') {\r
+ Lower = FALSE;\r
+ } else if (Lower && (*String >= L'A') && (*String <= L'F')) {\r
+ *String = (CHAR16)(*String - L'A' + L'a');\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Evaluate if the result is a non-zero value.\r
+\r
+ @param[in] Result The result to be evaluated.\r
+\r
+ @retval TRUE It is a non-zero value.\r
+ @retval FALSE It is a zero value.\r
+\r
+**/\r
+BOOLEAN\r
+IsHiiValueTrue (\r
+ IN EFI_HII_VALUE *Result\r
+ )\r
+{\r
+ switch (Result->Type) {\r
+ case EFI_IFR_TYPE_BOOLEAN:\r
+ return Result->Value.b;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_8:\r
+ return (BOOLEAN)(Result->Value.u8 != 0);\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_16:\r
+ return (BOOLEAN)(Result->Value.u16 != 0);\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_32:\r
+ return (BOOLEAN)(Result->Value.u32 != 0);\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_64:\r
+ return (BOOLEAN)(Result->Value.u64 != 0);\r
+\r
+ default:\r
+ return FALSE;\r
+ }\r
+}\r
+\r
+/**\r
+ Set a new string to string package.\r
+\r
+ @param[in] String A pointer to the Null-terminated Unicode string\r
+ to add or update in the String Package associated\r
+ with HiiHandle.\r
+ @param[in] HiiHandle A handle that was previously registered in the\r
+ HII Database.\r
+\r
+ @return the Id for this new string.\r
+\r
+**/\r
+EFI_STRING_ID\r
+NewHiiString (\r
+ IN CHAR16 *String,\r
+ IN EFI_HII_HANDLE HiiHandle\r
+ )\r
+{\r
+ EFI_STRING_ID StringId;\r
+\r
+ StringId = HiiSetString (HiiHandle, 0, String, NULL);\r
+ return StringId;\r
+}\r
+\r
+/**\r
+ Perform nosubmitif check for a Form.\r
+\r
+ @param[in] FormSet FormSet data structure.\r
+ @param[in] Form Form data structure.\r
+ @param[in] Question The Question to be validated.\r
+\r
+ @retval EFI_SUCCESS Form validation pass.\r
+ @retval other Form validation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+ValidateNoSubmit (\r
+ IN HII_FORMSET *FormSet,\r
+ IN HII_FORM *Form,\r
+ IN HII_STATEMENT *Question\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ LIST_ENTRY *ListHead;\r
+ HII_EXPRESSION *Expression;\r
+\r
+ ListHead = &Question->NoSubmitListHead;\r
+ Link = GetFirstNode (ListHead);\r
+ while (!IsNull (ListHead, Link)) {\r
+ Expression = HII_EXPRESSION_FROM_LINK (Link);\r
+\r
+ //\r
+ // Evaluate the expression\r
+ //\r
+ Status = EvaluateHiiExpression (FormSet, Form, Expression);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (IsHiiValueTrue (&Expression->Result)) {\r
+ return EFI_NOT_READY;\r
+ }\r
+\r
+ Link = GetNextNode (ListHead, Link);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Perform NoSubmit check for each Form in FormSet.\r
+\r
+ @param[in] FormSet FormSet data structure.\r
+ @param[in,out] CurrentForm Current input form data structure.\r
+ @param[out] Statement The statement for this check.\r
+\r
+ @retval EFI_SUCCESS Form validation pass.\r
+ @retval other Form validation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+NoSubmitCheck (\r
+ IN HII_FORMSET *FormSet,\r
+ IN OUT HII_FORM **CurrentForm,\r
+ OUT HII_STATEMENT **Statement\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ HII_STATEMENT *Question;\r
+ HII_FORM *Form;\r
+ LIST_ENTRY *LinkForm;\r
+\r
+ LinkForm = GetFirstNode (&FormSet->FormListHead);\r
+ while (!IsNull (&FormSet->FormListHead, LinkForm)) {\r
+ Form = HII_FORM_FROM_LINK (LinkForm);\r
+ LinkForm = GetNextNode (&FormSet->FormListHead, LinkForm);\r
+\r
+ if ((*CurrentForm != NULL) && (*CurrentForm != Form)) {\r
+ continue;\r
+ }\r
+\r
+ Link = GetFirstNode (&Form->StatementListHead);\r
+ while (!IsNull (&Form->StatementListHead, Link)) {\r
+ Question = HII_STATEMENT_FROM_LINK (Link);\r
+ Status = ValidateNoSubmit (FormSet, Form, Question);\r
+ if (EFI_ERROR (Status)) {\r
+ if (*CurrentForm == NULL) {\r
+ *CurrentForm = Form;\r
+ }\r
+\r
+ if (Statement != NULL) {\r
+ *Statement = Question;\r
+ }\r
+\r
+ return Status;\r
+ }\r
+\r
+ Link = GetNextNode (&Form->StatementListHead, Link);\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Allocate new memory and concatenate Source on the end of Destination.\r
+\r
+ @param Dest String to added to the end of.\r
+ @param Src String to concatenate.\r
+\r
+**/\r
+VOID\r
+NewStringCat (\r
+ IN OUT CHAR16 **Dest,\r
+ IN CHAR16 *Src\r
+ )\r
+{\r
+ CHAR16 *NewHiiString;\r
+ UINTN MaxLen;\r
+\r
+ if (*Dest == NULL) {\r
+ NewStringCopy (Dest, Src);\r
+ return;\r
+ }\r
+\r
+ MaxLen = (StrSize (*Dest) + StrSize (Src) - 2) / sizeof (CHAR16);\r
+ NewHiiString = AllocatePool (MaxLen * sizeof (CHAR16));\r
+ if (NewHiiString == NULL) {\r
+ return;\r
+ }\r
+\r
+ StrCpyS (NewHiiString, MaxLen, *Dest);\r
+ StrCatS (NewHiiString, MaxLen, Src);\r
+\r
+ FreePool (*Dest);\r
+ *Dest = NewHiiString;\r
+}\r
+\r
+/**\r
+ Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.\r
+\r
+ @param[in] Storage The Storage to be converted.\r
+ @param[in] ConfigResp The returned <ConfigResp>.\r
+ @param[in] ConfigRequest The ConfigRequest string.\r
+\r
+ @retval EFI_SUCCESS Convert success.\r
+ @retval EFI_INVALID_PARAMETER Incorrect storage type.\r
+\r
+**/\r
+EFI_STATUS\r
+StorageToConfigResp (\r
+ IN HII_FORMSET_STORAGE *Storage,\r
+ IN CHAR16 **ConfigResp,\r
+ IN CHAR16 *ConfigRequest\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_STRING Progress;\r
+ LIST_ENTRY *Link;\r
+ HII_NAME_VALUE_NODE *Node;\r
+ UINT8 *SourceBuf;\r
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;\r
+ EFI_STRING TempConfigRequest;\r
+ UINTN RequestStrSize;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ if (Storage->ConfigHdr == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (ConfigRequest != NULL) {\r
+ TempConfigRequest = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);\r
+ if (TempConfigRequest == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ } else {\r
+ RequestStrSize = (StrLen (Storage->ConfigHdr) + StrLen (Storage->ConfigRequest) + 1) * sizeof (CHAR16);\r
+ TempConfigRequest = AllocatePool (RequestStrSize);\r
+ if (TempConfigRequest == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ UnicodeSPrint (\r
+ TempConfigRequest,\r
+ RequestStrSize,\r
+ L"%s%s",\r
+ Storage->ConfigHdr,\r
+ Storage->ConfigRequest\r
+ );\r
+ }\r
+\r
+ switch (Storage->Type) {\r
+ case EFI_HII_VARSTORE_BUFFER:\r
+ case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
+\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiHiiConfigRoutingProtocolGuid,\r
+ NULL,\r
+ (VOID **)&HiiConfigRouting\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ SourceBuf = Storage->Buffer;\r
+ Status = HiiConfigRouting->BlockToConfig (\r
+ HiiConfigRouting,\r
+ TempConfigRequest,\r
+ SourceBuf,\r
+ Storage->Size,\r
+ ConfigResp,\r
+ &Progress\r
+ );\r
+ break;\r
+\r
+ case EFI_HII_VARSTORE_NAME_VALUE:\r
+\r
+ *ConfigResp = NULL;\r
+ NewStringCat (ConfigResp, Storage->ConfigHdr);\r
+\r
+ Link = GetFirstNode (&Storage->NameValueList);\r
+ while (!IsNull (&Storage->NameValueList, Link)) {\r
+ Node = HII_NAME_VALUE_NODE_FROM_LINK (Link);\r
+\r
+ if (StrStr (TempConfigRequest, Node->Name) != NULL) {\r
+ NewStringCat (ConfigResp, L"&");\r
+ NewStringCat (ConfigResp, Node->Name);\r
+ NewStringCat (ConfigResp, L"=");\r
+ NewStringCat (ConfigResp, Node->Value);\r
+ }\r
+\r
+ Link = GetNextNode (&Storage->NameValueList, Link);\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_HII_VARSTORE_EFI_VARIABLE:\r
+ default:\r
+ Status = EFI_INVALID_PARAMETER;\r
+ break;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.\r
+\r
+ @param[in] Storage The Storage to receive the settings.\r
+ @param[in] ConfigResp The <ConfigResp> to be converted.\r
+\r
+ @retval EFI_SUCCESS Convert success.\r
+ @retval EFI_INVALID_PARAMETER Incorrect storage type.\r
+\r
+**/\r
+EFI_STATUS\r
+ConfigRespToStorage (\r
+ IN HII_FORMSET_STORAGE *Storage,\r
+ IN CHAR16 *ConfigResp\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_STRING Progress;\r
+ UINTN BufferSize;\r
+ CHAR16 *StrPtr;\r
+ CHAR16 *Name;\r
+ CHAR16 *Value;\r
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ switch (Storage->Type) {\r
+ case EFI_HII_VARSTORE_BUFFER:\r
+ case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
+\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiHiiConfigRoutingProtocolGuid,\r
+ NULL,\r
+ (VOID **)&HiiConfigRouting\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ BufferSize = Storage->Size;\r
+ Status = HiiConfigRouting->ConfigToBlock (\r
+ HiiConfigRouting,\r
+ ConfigResp,\r
+ Storage->Buffer,\r
+ &BufferSize,\r
+ &Progress\r
+ );\r
+ break;\r
+\r
+ case EFI_HII_VARSTORE_NAME_VALUE:\r
+ StrPtr = StrStr (ConfigResp, L"PATH");\r
+ if (StrPtr == NULL) {\r
+ break;\r
+ }\r
+\r
+ StrPtr = StrStr (ConfigResp, L"&");\r
+ while (StrPtr != NULL) {\r
+ //\r
+ // Skip '&'\r
+ //\r
+ StrPtr = StrPtr + 1;\r
+ Name = StrPtr;\r
+ StrPtr = StrStr (StrPtr, L"=");\r
+ if (StrPtr == NULL) {\r
+ break;\r
+ }\r
+\r
+ *StrPtr = 0;\r
+\r
+ //\r
+ // Skip '='\r
+ //\r
+ StrPtr = StrPtr + 1;\r
+ Value = StrPtr;\r
+ StrPtr = StrStr (StrPtr, L"&");\r
+ if (StrPtr != NULL) {\r
+ *StrPtr = 0;\r
+ }\r
+\r
+ SetValueByName (Storage, Name, Value, NULL);\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_HII_VARSTORE_EFI_VARIABLE:\r
+ default:\r
+ Status = EFI_INVALID_PARAMETER;\r
+ break;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Fetch the Ifr binary data of a FormSet.\r
+\r
+ @param[in] Handle PackageList Handle\r
+ @param[in,out] FormSetGuid On input, GUID or class GUID of a formset. If not\r
+ specified (NULL or zero GUID), take the first\r
+ FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
+ found in package list.\r
+ On output, GUID of the formset found(if not NULL).\r
+ @param[out] BinaryLength The length of the FormSet IFR binary.\r
+ @param[out] BinaryData The buffer designed to receive the FormSet.\r
+\r
+ @retval EFI_SUCCESS Buffer filled with the requested FormSet.\r
+ BufferLength was updated.\r
+ @retval EFI_INVALID_PARAMETER The handle is unknown.\r
+ @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot\r
+ be found with the requested FormId.\r
+\r
+**/\r
+EFI_STATUS\r
+GetIfrBinaryData (\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN OUT EFI_GUID *FormSetGuid,\r
+ OUT UINTN *BinaryLength,\r
+ OUT UINT8 **BinaryData\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
+ UINTN BufferSize;\r
+ UINT8 *Package;\r
+ UINT8 *OpCodeData;\r
+ UINT32 Offset;\r
+ UINT32 Offset2;\r
+ UINT32 PackageListLength;\r
+ EFI_HII_PACKAGE_HEADER PackageHeader;\r
+ UINT8 Index;\r
+ UINT8 NumberOfClassGuid;\r
+ BOOLEAN ClassGuidMatch;\r
+ EFI_GUID *ClassGuid;\r
+ EFI_GUID *ComparingGuid;\r
+ EFI_HII_DATABASE_PROTOCOL *HiiDatabase;\r
+\r
+ OpCodeData = NULL;\r
+ Package = NULL;\r
+ ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
+\r
+ //\r
+ // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list\r
+ //\r
+ if (FormSetGuid == NULL) {\r
+ ComparingGuid = &gZeroGuid;\r
+ } else {\r
+ ComparingGuid = FormSetGuid;\r
+ }\r
+\r
+ //\r
+ // Get HII PackageList\r
+ //\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiHiiDatabaseProtocolGuid,\r
+ NULL,\r
+ (VOID **)&HiiDatabase\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ *BinaryData = NULL;\r
+ return Status;\r
+ }\r
+\r
+ BufferSize = 0;\r
+ HiiPackageList = NULL;\r
+ Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList);\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ HiiPackageList = AllocatePool (BufferSize);\r
+ if (HiiPackageList == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList);\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ if (HiiPackageList != NULL) {\r
+ FreePool (HiiPackageList);\r
+ }\r
+\r
+ *BinaryData = NULL;\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Get Form package from this HII package List\r
+ //\r
+ Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+ Offset2 = 0;\r
+ CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
+\r
+ ClassGuidMatch = FALSE;\r
+ while (Offset < PackageListLength) {\r
+ Package = ((UINT8 *)HiiPackageList) + Offset;\r
+ CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
+\r
+ if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
+ //\r
+ // Search FormSet in this Form Package\r
+ //\r
+\r
+ Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
+ while (Offset2 < PackageHeader.Length) {\r
+ OpCodeData = Package + Offset2;\r
+\r
+ if (((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
+ //\r
+ // Try to compare against formset GUID\r
+ //\r
+\r
+ if (IsZeroGuid (FormSetGuid) ||\r
+ CompareGuid (ComparingGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER))))\r
+ {\r
+ break;\r
+ }\r
+\r
+ if (((EFI_IFR_OP_HEADER *)OpCodeData)->Length > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) {\r
+ //\r
+ // Try to compare against formset class GUID\r
+ //\r
+ NumberOfClassGuid = (UINT8)(((EFI_IFR_FORM_SET *)OpCodeData)->Flags & 0x3);\r
+ ClassGuid = (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_FORM_SET));\r
+ for (Index = 0; Index < NumberOfClassGuid; Index++) {\r
+ if (CompareGuid (ComparingGuid, ClassGuid + Index)) {\r
+ ClassGuidMatch = TRUE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (ClassGuidMatch) {\r
+ break;\r
+ }\r
+ } else if (ComparingGuid == &gEfiHiiPlatformSetupFormsetGuid) {\r
+ ClassGuidMatch = TRUE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ Offset2 += ((EFI_IFR_OP_HEADER *)OpCodeData)->Length;\r
+ }\r
+\r
+ if (Offset2 < PackageHeader.Length) {\r
+ //\r
+ // Target formset found\r
+ //\r
+ break;\r
+ }\r
+ }\r
+\r
+ Offset += PackageHeader.Length;\r
+ }\r
+\r
+ if (Offset >= PackageListLength) {\r
+ //\r
+ // Form package not found in this Package List\r
+ //\r
+ FreePool (HiiPackageList);\r
+ *BinaryData = NULL;\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ if (FormSetGuid != NULL) {\r
+ //\r
+ // Return the FormSet GUID\r
+ //\r
+ CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *)OpCodeData)->Guid, sizeof (EFI_GUID));\r
+ }\r
+\r
+ //\r
+ // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes\r
+ // in this FormSet; So, here just simply copy the data from start of a FormSet to the end\r
+ // of the Form Package.\r
+ //\r
+\r
+ *BinaryLength = PackageHeader.Length - Offset2;\r
+ *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);\r
+ FreePool (HiiPackageList);\r
+ if (*BinaryData == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Check if the requested element is in storage.\r
+\r
+ @param Storage The storage contains elements.\r
+ @param RequestElement The element to be searched.\r
+\r
+**/\r
+BOOLEAN\r
+ElementValidation (\r
+ IN HII_FORMSET_STORAGE *Storage,\r
+ IN CHAR16 *RequestElement\r
+ )\r
+{\r
+ return StrStr (Storage->ConfigRequest, RequestElement) != NULL ? TRUE : FALSE;\r
+}\r
+\r
+/**\r
+ Append the Request element to the Config Request.\r
+\r
+ @param ConfigRequest Current ConfigRequest info.\r
+ @param SpareStrLen Current remain free buffer for config request.\r
+ @param RequestElement New Request element.\r
+\r
+**/\r
+VOID\r
+AppendConfigRequest (\r
+ IN OUT CHAR16 **ConfigRequest,\r
+ IN OUT UINTN *SpareStrLen,\r
+ IN CHAR16 *RequestElement\r
+ )\r
+{\r
+ CHAR16 *NewStr;\r
+ UINTN StringSize;\r
+ UINTN StrLength;\r
+ UINTN MaxLen;\r
+\r
+ StrLength = StrLen (RequestElement);\r
+ StringSize = (*ConfigRequest != NULL) ? StrSize (*ConfigRequest) : sizeof (CHAR16);\r
+ MaxLen = StringSize / sizeof (CHAR16) + *SpareStrLen;\r
+\r
+ //\r
+ // Append <RequestElement> to <ConfigRequest>\r
+ //\r
+ if (StrLength > *SpareStrLen) {\r
+ //\r
+ // Old String buffer is not sufficient for RequestElement, allocate a new one\r
+ //\r
+ MaxLen = StringSize / sizeof (CHAR16) + CONFIG_REQUEST_STRING_INCREMENTAL;\r
+ NewStr = AllocatePool (MaxLen * sizeof (CHAR16));\r
+ if (NewStr == NULL) {\r
+ return;\r
+ }\r
+\r
+ if (*ConfigRequest != NULL) {\r
+ CopyMem (NewStr, *ConfigRequest, StringSize);\r
+ FreePool (*ConfigRequest);\r
+ } else {\r
+ NewStr[0] = L'\0';\r
+ }\r
+\r
+ *ConfigRequest = NewStr;\r
+ *SpareStrLen = CONFIG_REQUEST_STRING_INCREMENTAL;\r
+ }\r
+\r
+ StrCatS (*ConfigRequest, MaxLen, RequestElement);\r
+ *SpareStrLen -= StrLength;\r
+}\r
+\r
+/**\r
+ Adjust the config request info, remove the request elements which already in AllConfigRequest string.\r
+\r
+ @param Storage Form set Storage.\r
+ @param Request The input request string.\r
+ @param RespString Whether the input is ConfigRequest or ConfigResp format.\r
+\r
+ @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig\r
+ @retval FALSE All elements covered by current used elements.\r
+\r
+**/\r
+BOOLEAN\r
+ConfigRequestAdjust (\r
+ IN HII_FORMSET_STORAGE *Storage,\r
+ IN CHAR16 *Request,\r
+ IN BOOLEAN RespString\r
+ )\r
+{\r
+ CHAR16 *RequestElement;\r
+ CHAR16 *NextRequestElement;\r
+ CHAR16 *NextElementBackup;\r
+ CHAR16 *SearchKey;\r
+ CHAR16 *ValueKey;\r
+ BOOLEAN RetVal;\r
+ CHAR16 *ConfigRequest;\r
+\r
+ RetVal = FALSE;\r
+ NextElementBackup = NULL;\r
+ ValueKey = NULL;\r
+\r
+ if (Request != NULL) {\r
+ ConfigRequest = Request;\r
+ } else {\r
+ ConfigRequest = Storage->ConfigRequest;\r
+ }\r
+\r
+ if (Storage->ConfigRequest == NULL) {\r
+ Storage->ConfigRequest = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);\r
+ if (Storage->ConfigRequest == NULL) {\r
+ return FALSE;\r
+ }\r
+\r
+ return TRUE;\r
+ }\r
+\r
+ if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+ //\r
+ // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage\r
+ //\r
+ SearchKey = L"&";\r
+ } else {\r
+ //\r
+ // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage\r
+ //\r
+ SearchKey = L"&OFFSET";\r
+ ValueKey = L"&VALUE";\r
+ }\r
+\r
+ //\r
+ // Find SearchKey storage\r
+ //\r
+ if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+ RequestElement = StrStr (ConfigRequest, L"PATH");\r
+ if (RequestElement == NULL) {\r
+ return FALSE;\r
+ }\r
+\r
+ RequestElement = StrStr (RequestElement, SearchKey);\r
+ } else {\r
+ RequestElement = StrStr (ConfigRequest, SearchKey);\r
+ }\r
+\r
+ while (RequestElement != NULL) {\r
+ //\r
+ // +1 to avoid find header itself.\r
+ //\r
+ NextRequestElement = StrStr (RequestElement + 1, SearchKey);\r
+\r
+ //\r
+ // The last Request element in configRequest string.\r
+ //\r
+ if (NextRequestElement != NULL) {\r
+ if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
+ NextElementBackup = NextRequestElement;\r
+ NextRequestElement = StrStr (RequestElement, ValueKey);\r
+ if (NextRequestElement == NULL) {\r
+ return FALSE;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Replace "&" with '\0'.\r
+ //\r
+ *NextRequestElement = L'\0';\r
+ } else {\r
+ if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
+ NextElementBackup = NextRequestElement;\r
+ NextRequestElement = StrStr (RequestElement, ValueKey);\r
+ if (NextRequestElement == NULL) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Replace "&" with '\0'.\r
+ //\r
+ *NextRequestElement = L'\0';\r
+ }\r
+ }\r
+\r
+ if (!ElementValidation (Storage, RequestElement)) {\r
+ //\r
+ // Add this element to the Storage->BrowserStorage->AllRequestElement.\r
+ //\r
+ AppendConfigRequest (&Storage->ConfigRequest, &Storage->SpareStrLen, RequestElement);\r
+ RetVal = TRUE;\r
+ }\r
+\r
+ if (NextRequestElement != NULL) {\r
+ //\r
+ // Restore '&' with '\0' for later used.\r
+ //\r
+ *NextRequestElement = L'&';\r
+ }\r
+\r
+ if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
+ RequestElement = NextElementBackup;\r
+ } else {\r
+ RequestElement = NextRequestElement;\r
+ }\r
+ }\r
+\r
+ return RetVal;\r
+}\r
+\r
+/**\r
+ Fill storage with settings requested from Configuration Driver.\r
+\r
+ @param[in] FormSet FormSet data structure.\r
+ @param[in] Storage Buffer Storage.\r
+\r
+**/\r
+VOID\r
+LoadFormSetStorage (\r
+ IN HII_FORMSET *FormSet,\r
+ IN HII_FORMSET_STORAGE *Storage\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_STRING Progress;\r
+ EFI_STRING Result;\r
+ CHAR16 *StrPtr;\r
+ EFI_STRING ConfigRequest;\r
+ UINTN RequestStrSize;\r
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;\r
+\r
+ ConfigRequest = NULL;\r
+\r
+ switch (Storage->Type) {\r
+ case EFI_HII_VARSTORE_EFI_VARIABLE:\r
+ return;\r
+\r
+ case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
+ #if 0 // bug fix for efivarstore\r
+ if (Storage->ConfigRequest != NULL) {\r
+ ConfigRequestAdjust (Storage, Storage->ConfigRequest, FALSE);\r
+ return;\r
+ }\r
+\r
+ #endif\r
+ break;\r
+\r
+ case EFI_HII_VARSTORE_BUFFER:\r
+ case EFI_HII_VARSTORE_NAME_VALUE:\r
+ //\r
+ // Skip if there is no RequestElement.\r
+ //\r
+ if (Storage->ElementCount == 0) {\r
+ return;\r
+ }\r
+\r
+ break;\r
+\r
+ default:\r
+ return;\r
+ }\r
+\r
+ if (Storage->Type != EFI_HII_VARSTORE_NAME_VALUE) {\r
+ //\r
+ // Create the config request string to get all fields for this storage.\r
+ // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
+ // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator\r
+ //\r
+ RequestStrSize = StrSize (Storage->ConfigHdr) + 20 * sizeof (CHAR16);\r
+ ConfigRequest = AllocatePool (RequestStrSize);\r
+ if (ConfigRequest == NULL) {\r
+ return;\r
+ }\r
+\r
+ UnicodeSPrint (\r
+ ConfigRequest,\r
+ RequestStrSize,\r
+ L"%s&OFFSET=0&WIDTH=%04x",\r
+ Storage->ConfigHdr,\r
+ Storage->Size\r
+ );\r
+ } else {\r
+ RequestStrSize = (StrLen (Storage->ConfigHdr) + StrLen (Storage->ConfigRequest) + 1) * sizeof (CHAR16);\r
+ ConfigRequest = AllocatePool (RequestStrSize);\r
+ if (ConfigRequest == NULL) {\r
+ return;\r
+ }\r
+\r
+ UnicodeSPrint (\r
+ ConfigRequest,\r
+ RequestStrSize,\r
+ L"%s%s",\r
+ Storage->ConfigHdr,\r
+ Storage->ConfigRequest\r
+ );\r
+ }\r
+\r
+ //\r
+ // Request current settings from Configuration Driver\r
+ //\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiHiiConfigRoutingProtocolGuid,\r
+ NULL,\r
+ (VOID **)&HiiConfigRouting\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return;\r
+ }\r
+\r
+ Status = HiiConfigRouting->ExtractConfig (\r
+ HiiConfigRouting,\r
+ ConfigRequest,\r
+ &Progress,\r
+ &Result\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Convert Result from <ConfigAltResp> to <ConfigResp>\r
+ //\r
+ StrPtr = StrStr (Result, L"&GUID=");\r
+ if (StrPtr != NULL) {\r
+ *StrPtr = L'\0';\r
+ }\r
+\r
+ Status = ConfigRespToStorage (Storage, Result);\r
+ FreePool (Result);\r
+ }\r
+\r
+ Storage->ConfigRequest = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);\r
+ if (Storage->ConfigRequest == NULL) {\r
+ if (ConfigRequest != NULL) {\r
+ FreePool (ConfigRequest);\r
+ }\r
+\r
+ return;\r
+ }\r
+\r
+ if (Storage->Type != EFI_HII_VARSTORE_NAME_VALUE) {\r
+ if (ConfigRequest != NULL) {\r
+ FreePool (ConfigRequest);\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Zero extend integer/boolean/date/time to UINT64 for comparing.\r
+\r
+ @param[in] Value HII Value to be converted.\r
+\r
+**/\r
+VOID\r
+ExtendValueToU64 (\r
+ IN HII_STATEMENT_VALUE *Value\r
+ )\r
+{\r
+ UINT64 Temp;\r
+\r
+ Temp = 0;\r
+ switch (Value->Type) {\r
+ case EFI_IFR_TYPE_NUM_SIZE_8:\r
+ Temp = Value->Value.u8;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_16:\r
+ Temp = Value->Value.u16;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_32:\r
+ Temp = Value->Value.u32;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_BOOLEAN:\r
+ Temp = Value->Value.b;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_TIME:\r
+ Temp = Value->Value.u32 & 0xffffff;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_DATE:\r
+ Temp = Value->Value.u32;\r
+ break;\r
+\r
+ default:\r
+ return;\r
+ }\r
+\r
+ Value->Value.u64 = Temp;\r
+}\r
+\r
+/**\r
+ Pop an element from the stack.\r
+\r
+ @param Stack On input: old stack\r
+ @param StackPtr On input: old stack pointer; On output: new stack pointer\r
+ @param Data Data to pop.\r
+\r
+ @retval EFI_SUCCESS The value was popped onto the stack.\r
+ @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
+\r
+**/\r
+EFI_STATUS\r
+PopStack (\r
+ IN EFI_HII_VALUE *Stack,\r
+ IN OUT EFI_HII_VALUE **StackPtr,\r
+ OUT EFI_HII_VALUE *Data\r
+ );\r
+\r
+/**\r
+ Push an element onto the Boolean Stack.\r
+\r
+ @param Stack On input: old stack; On output: new stack\r
+ @param StackPtr On input: old stack pointer; On output: new stack\r
+ pointer\r
+ @param StackEnd On input: old stack end; On output: new stack end\r
+ @param Data Data to push.\r
+\r
+ @retval EFI_SUCCESS Push stack success.\r
+\r
+**/\r
+EFI_STATUS\r
+PushStack (\r
+ IN OUT EFI_HII_VALUE **Stack,\r
+ IN OUT EFI_HII_VALUE **StackPtr,\r
+ IN OUT EFI_HII_VALUE **StackEnd,\r
+ IN EFI_HII_VALUE *Data\r
+ );\r
+\r
+/**\r
+ Initialize the internal data structure of a FormSet.\r
+\r
+ @param[in] Handle PackageList Handle\r
+ @param[in,out] FormSetGuid On input, GUID or class GUID of a formset. If not\r
+ specified (NULL or zero GUID), take the first\r
+ FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
+ found in package list.\r
+ On output, GUID of the formset found(if not NULL).\r
+ @param[out] FormSet FormSet data structure.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+ @retval EFI_NOT_FOUND The specified FormSet could not be found.\r
+\r
+**/\r
+EFI_STATUS\r
+CreateFormSetFromHiiHandle (\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN OUT EFI_GUID *FormSetGuid,\r
+ OUT HII_FORMSET *FormSet\r
+ );\r
+\r
+/**\r
+ Initialize a Formset and get current setting for Questions.\r
+\r
+ @param[in,out] FormSet FormSet data structure.\r
+\r
+**/\r
+VOID\r
+InitializeFormSet (\r
+ IN OUT HII_FORMSET *FormSet\r
+ );\r
+\r
+/**\r
+ Get Value for given Name from a NameValue Storage.\r
+\r
+ @param[in] Storage The NameValue Storage.\r
+ @param[in] Name The Name.\r
+ @param[in,out] Value The returned Value.\r
+\r
+ @retval EFI_SUCCESS Value found for given Name.\r
+ @retval EFI_NOT_FOUND No such Name found in NameValue storage.\r
+ @retval EFI_INVALID_PARAMETER Storage or Value is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+GetValueByName (\r
+ IN HII_FORMSET_STORAGE *Storage,\r
+ IN CHAR16 *Name,\r
+ IN OUT CHAR16 **Value\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ HII_NAME_VALUE_NODE *Node;\r
+\r
+ if ((Storage == NULL) || (Value == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ *Value = NULL;\r
+\r
+ Link = GetFirstNode (&Storage->NameValueList);\r
+ while (!IsNull (&Storage->NameValueList, Link)) {\r
+ Node = HII_NAME_VALUE_NODE_FROM_LINK (Link);\r
+\r
+ if (StrCmp (Name, Node->Name) == 0) {\r
+ NewStringCopy (Value, Node->Value);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Link = GetNextNode (&Storage->NameValueList, Link);\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+ Get Question's current Value.\r
+\r
+ @param[in] FormSet FormSet data structure.\r
+ @param[in] Form Form data structure.\r
+ @param[in,out] Question Question to be initialized.\r
+ @param[in] GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+ @retval EFI_INVALID_PARAMETER Formset, Form or Question is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+GetQuestionValue (\r
+ IN HII_FORMSET *FormSet,\r
+ IN HII_FORM *Form,\r
+ IN OUT HII_STATEMENT *Question,\r
+ IN GET_SET_QUESTION_VALUE_WITH GetValueFrom\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ BOOLEAN Enabled;\r
+ BOOLEAN Pending;\r
+ UINT8 *Dst;\r
+ UINTN StorageWidth;\r
+ EFI_TIME EfiTime;\r
+ HII_FORMSET_STORAGE *Storage;\r
+ HII_FORMSET_STORAGE *FormsetStorage;\r
+ EFI_IFR_TYPE_VALUE *QuestionValue;\r
+ CHAR16 *ConfigRequest;\r
+ CHAR16 *Progress;\r
+ CHAR16 *Result;\r
+ CHAR16 *Value;\r
+ UINTN Length;\r
+ BOOLEAN IsBufferStorage;\r
+ UINTN MaxLen;\r
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;\r
+\r
+ if ((FormSet == NULL) || (Form == NULL) || (Question == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ Value = NULL;\r
+ Result = NULL;\r
+\r
+ if (GetValueFrom >= GetSetValueWithMax) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Question value is provided by an Expression, evaluate it\r
+ //\r
+ if (Question->ValueExpression != NULL) {\r
+ Status = EvaluateHiiExpression (FormSet, Form, Question->ValueExpression);\r
+ if (!EFI_ERROR (Status)) {\r
+ if (Question->ValueExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {\r
+ ASSERT (Question->Value.Type == EFI_IFR_TYPE_BUFFER && Question->Value.Buffer != NULL);\r
+ if (Question->StorageWidth > Question->ValueExpression->Result.BufferLen) {\r
+ CopyMem (Question->Value.Buffer, Question->ValueExpression->Result.Buffer, Question->ValueExpression->Result.BufferLen);\r
+ Question->Value.BufferLen = Question->ValueExpression->Result.BufferLen;\r
+ } else {\r
+ CopyMem (Question->Value.Buffer, Question->ValueExpression->Result.Buffer, Question->StorageWidth);\r
+ Question->Value.BufferLen = Question->StorageWidth;\r
+ }\r
+\r
+ FreePool (Question->ValueExpression->Result.Buffer);\r
+ }\r
+\r
+ Question->Value.Type = Question->ValueExpression->Result.Type;\r
+ CopyMem (&Question->Value.Value, &Question->ValueExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE));\r
+ }\r
+\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Get question value by read expression.\r
+ //\r
+ if ((Question->ReadExpression != NULL) && (Form->FormType == STANDARD_MAP_FORM_TYPE)) {\r
+ Status = EvaluateHiiExpression (FormSet, Form, Question->ReadExpression);\r
+ if (!EFI_ERROR (Status) &&\r
+ ((Question->ReadExpression->Result.Type < EFI_IFR_TYPE_OTHER) || (Question->ReadExpression->Result.Type == EFI_IFR_TYPE_BUFFER)))\r
+ {\r
+ //\r
+ // Only update question value to the valid result.\r
+ //\r
+ if (Question->ReadExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {\r
+ ASSERT (Question->Value.Type == EFI_IFR_TYPE_BUFFER && Question->Value.Buffer != NULL);\r
+ if (Question->StorageWidth > Question->ReadExpression->Result.BufferLen) {\r
+ CopyMem (Question->Value.Buffer, Question->ReadExpression->Result.Buffer, Question->ReadExpression->Result.BufferLen);\r
+ Question->Value.BufferLen = Question->ReadExpression->Result.BufferLen;\r
+ } else {\r
+ CopyMem (Question->Value.Buffer, Question->ReadExpression->Result.Buffer, Question->StorageWidth);\r
+ Question->Value.BufferLen = Question->StorageWidth;\r
+ }\r
+\r
+ FreePool (Question->ReadExpression->Result.Buffer);\r
+ }\r
+\r
+ Question->Value.Type = Question->ReadExpression->Result.Type;\r
+ CopyMem (&Question->Value.Value, &Question->ReadExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE));\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Question value is provided by RTC\r
+ //\r
+ Storage = Question->Storage;\r
+ QuestionValue = &Question->Value.Value;\r
+ if (Storage == NULL) {\r
+ //\r
+ // It's a Question without storage, or RTC date/time\r
+ //\r
+ if ((Question->Operand == EFI_IFR_DATE_OP) || (Question->Operand == EFI_IFR_TIME_OP)) {\r
+ //\r
+ // Date and time define the same Flags bit\r
+ //\r
+ switch (Question->ExtraData.Flags & EFI_QF_DATE_STORAGE) {\r
+ case QF_DATE_STORAGE_TIME:\r
+ Status = gRT->GetTime (&EfiTime, NULL);\r
+ break;\r
+\r
+ case QF_DATE_STORAGE_WAKEUP:\r
+ Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
+ break;\r
+\r
+ case QF_DATE_STORAGE_NORMAL:\r
+ default:\r
+ //\r
+ // For date/time without storage\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ if (Question->Operand == EFI_IFR_DATE_OP) {\r
+ QuestionValue->date.Year = 0xff;\r
+ QuestionValue->date.Month = 0xff;\r
+ QuestionValue->date.Day = 0xff;\r
+ } else {\r
+ QuestionValue->time.Hour = 0xff;\r
+ QuestionValue->time.Minute = 0xff;\r
+ QuestionValue->time.Second = 0xff;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (Question->Operand == EFI_IFR_DATE_OP) {\r
+ QuestionValue->date.Year = EfiTime.Year;\r
+ QuestionValue->date.Month = EfiTime.Month;\r
+ QuestionValue->date.Day = EfiTime.Day;\r
+ } else {\r
+ QuestionValue->time.Hour = EfiTime.Hour;\r
+ QuestionValue->time.Minute = EfiTime.Minute;\r
+ QuestionValue->time.Second = EfiTime.Second;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Question value is provided by EFI variable\r
+ //\r
+ StorageWidth = Question->StorageWidth;\r
+ if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+ if (Question->Value.Buffer != NULL) {\r
+ Dst = Question->Value.Buffer;\r
+ } else {\r
+ Dst = (UINT8 *)QuestionValue;\r
+ }\r
+\r
+ Status = gRT->GetVariable (\r
+ Question->VariableName,\r
+ &Storage->Guid,\r
+ NULL,\r
+ &StorageWidth,\r
+ Dst\r
+ );\r
+ //\r
+ // Always return success, even this EFI variable doesn't exist\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Question Value is provided by Buffer Storage or NameValue Storage\r
+ //\r
+ if (Question->Value.Buffer != NULL) {\r
+ //\r
+ // This Question is password or orderedlist\r
+ //\r
+ Dst = Question->Value.Buffer;\r
+ } else {\r
+ //\r
+ // Other type of Questions\r
+ //\r
+ Dst = (UINT8 *)&Question->Value.Value;\r
+ }\r
+\r
+ if ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ||\r
+ (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER))\r
+ {\r
+ IsBufferStorage = TRUE;\r
+ } else {\r
+ IsBufferStorage = FALSE;\r
+ }\r
+\r
+ if (GetValueFrom == GetSetValueWithBuffer ) {\r
+ if (IsBufferStorage) {\r
+ //\r
+ // Copy from storage Edit buffer\r
+ // If the Question refer to bit filed, get the value in the related bit filed.\r
+ //\r
+ if (Question->QuestionReferToBitField) {\r
+ GetBitsQuestionValue (Question, Storage->Buffer + Question->VarStoreInfo.VarOffset, &Question->Value);\r
+ } else {\r
+ CopyMem (Dst, Storage->Buffer + Question->VarStoreInfo.VarOffset, StorageWidth);\r
+ }\r
+ } else {\r
+ Value = NULL;\r
+ Status = GetValueByName (Storage, Question->VariableName, &Value);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ ASSERT (Value != NULL);\r
+ Status = BufferToQuestionValue (Question, Value, &Question->Value);\r
+ FreePool (Value);\r
+ }\r
+ } else {\r
+ FormsetStorage = GetFstStgFromVarId (FormSet, Question->VarStoreId);\r
+ ASSERT (FormsetStorage != NULL);\r
+ //\r
+ // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||\r
+ // <ConfigHdr> + "&" + <VariableName>\r
+ //\r
+ if (IsBufferStorage) {\r
+ Length = StrLen (FormsetStorage->ConfigHdr);\r
+ Length += StrLen (Question->BlockName);\r
+ } else {\r
+ Length = StrLen (FormsetStorage->ConfigHdr);\r
+ Length += StrLen (Question->VariableName) + 1;\r
+ }\r
+\r
+ // Allocate buffer include '\0'\r
+ MaxLen = Length + 1;\r
+ ConfigRequest = AllocatePool (MaxLen * sizeof (CHAR16));\r
+ ASSERT (ConfigRequest != NULL);\r
+\r
+ StrCpyS (ConfigRequest, MaxLen, FormsetStorage->ConfigHdr);\r
+ if (IsBufferStorage) {\r
+ StrCatS (ConfigRequest, MaxLen, Question->BlockName);\r
+ } else {\r
+ StrCatS (ConfigRequest, MaxLen, L"&");\r
+ StrCatS (ConfigRequest, MaxLen, Question->VariableName);\r
+ }\r
+\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiHiiConfigRoutingProtocolGuid,\r
+ NULL,\r
+ (VOID **)&HiiConfigRouting\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Request current settings from Configuration Driver\r
+ //\r
+ Status = HiiConfigRouting->ExtractConfig (\r
+ HiiConfigRouting,\r
+ ConfigRequest,\r
+ &Progress,\r
+ &Result\r
+ );\r
+ FreePool (ConfigRequest);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Skip <ConfigRequest>\r
+ //\r
+ if (IsBufferStorage) {\r
+ Value = StrStr (Result, L"&VALUE");\r
+ if (Value == NULL) {\r
+ FreePool (Result);\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Skip "&VALUE"\r
+ //\r
+ Value = Value + 6;\r
+ } else {\r
+ Value = Result + Length;\r
+ }\r
+\r
+ if (*Value != '=') {\r
+ FreePool (Result);\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Skip '=', point to value\r
+ //\r
+ Value = Value + 1;\r
+\r
+ Status = BufferToQuestionValue (Question, Value, &Question->Value);\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (Result);\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Synchronize Buffer\r
+ //\r
+ if (IsBufferStorage) {\r
+ CopyMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth);\r
+ } else {\r
+ SetValueByName (Storage, Question->VariableName, Value, NULL);\r
+ }\r
+\r
+ if (Result != NULL) {\r
+ FreePool (Result);\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Convert the input Unicode character to upper.\r
+\r
+ @param[in] String Th Unicode character to be converted.\r
+\r
+**/\r
+VOID\r
+IfrStrToUpper (\r
+ IN CHAR16 *String\r
+ )\r
+{\r
+ if (String == NULL) {\r
+ return;\r
+ }\r
+\r
+ while (*String != 0) {\r
+ if ((*String >= 'a') && (*String <= 'z')) {\r
+ *String = (UINT16)((*String) & ((UINT16) ~0x20));\r
+ }\r
+\r
+ String++;\r
+ }\r
+}\r
+\r
+/**\r
+ Check whether this value type can be transfer to EFI_IFR_TYPE_BUFFER type.\r
+\r
+ EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to\r
+ EFI_IFR_TYPE_BUFFER when do the value compare.\r
+\r
+ @param[in] Value Expression value to compare on.\r
+\r
+ @retval TRUE This value type can be transferred to EFI_IFR_TYPE_BUFFER type.\r
+ @retval FALSE This value type can't be transferred to EFI_IFR_TYPE_BUFFER type.\r
+\r
+**/\r
+BOOLEAN\r
+IsTypeInBuffer (\r
+ IN EFI_HII_VALUE *Value\r
+ )\r
+{\r
+ if (Value == NULL) {\r
+ return FALSE;\r
+ }\r
+\r
+ switch (Value->Type) {\r
+ case EFI_IFR_TYPE_BUFFER:\r
+ case EFI_IFR_TYPE_DATE:\r
+ case EFI_IFR_TYPE_TIME:\r
+ case EFI_IFR_TYPE_REF:\r
+ return TRUE;\r
+\r
+ default:\r
+ return FALSE;\r
+ }\r
+}\r
+\r
+/**\r
+ Check whether this value type can be transfer to EFI_IFR_TYPE_UINT64\r
+\r
+ @param[in] Value Expression value to compare on.\r
+\r
+ @retval TRUE This value type can be transferred to EFI_IFR_TYPE_BUFFER type.\r
+ @retval FALSE This value type can't be transferred to EFI_IFR_TYPE_BUFFER type.\r
+\r
+**/\r
+BOOLEAN\r
+IsTypeInUINT64 (\r
+ IN EFI_HII_VALUE *Value\r
+ )\r
+{\r
+ if (Value == NULL) {\r
+ return FALSE;\r
+ }\r
+\r
+ switch (Value->Type) {\r
+ case EFI_IFR_TYPE_NUM_SIZE_8:\r
+ case EFI_IFR_TYPE_NUM_SIZE_16:\r
+ case EFI_IFR_TYPE_NUM_SIZE_32:\r
+ case EFI_IFR_TYPE_NUM_SIZE_64:\r
+ case EFI_IFR_TYPE_BOOLEAN:\r
+ return TRUE;\r
+\r
+ default:\r
+ return FALSE;\r
+ }\r
+}\r
+\r
+/**\r
+ Return the buffer pointer for this value.\r
+\r
+ EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to\r
+ EFI_IFR_TYPE_BUFFER when do the value compare.\r
+\r
+ @param[in] Value Expression value to compare on.\r
+\r
+ @retval Buf Return the buffer pointer.\r
+\r
+**/\r
+UINT8 *\r
+GetBufferForValue (\r
+ IN EFI_HII_VALUE *Value\r
+ )\r
+{\r
+ if (Value == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ switch (Value->Type) {\r
+ case EFI_IFR_TYPE_BUFFER:\r
+ return Value->Buffer;\r
+\r
+ case EFI_IFR_TYPE_DATE:\r
+ return (UINT8 *)(&Value->Value.date);\r
+\r
+ case EFI_IFR_TYPE_TIME:\r
+ return (UINT8 *)(&Value->Value.time);\r
+\r
+ case EFI_IFR_TYPE_REF:\r
+ return (UINT8 *)(&Value->Value.ref);\r
+\r
+ default:\r
+ return NULL;\r
+ }\r
+}\r
+\r
+/**\r
+ Return the buffer length for this value.\r
+\r
+ EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to\r
+ EFI_IFR_TYPE_BUFFER when do the value compare.\r
+\r
+ @param[in] Value Expression value to compare on.\r
+\r
+ @retval BufLen Return the buffer length.\r
+\r
+**/\r
+UINT16\r
+GetLengthForValue (\r
+ IN EFI_HII_VALUE *Value\r
+ )\r
+{\r
+ if (Value == NULL) {\r
+ return 0;\r
+ }\r
+\r
+ switch (Value->Type) {\r
+ case EFI_IFR_TYPE_BUFFER:\r
+ return Value->BufferLen;\r
+\r
+ case EFI_IFR_TYPE_DATE:\r
+ return (UINT16)sizeof (EFI_HII_DATE);\r
+\r
+ case EFI_IFR_TYPE_TIME:\r
+ return (UINT16)sizeof (EFI_HII_TIME);\r
+\r
+ case EFI_IFR_TYPE_REF:\r
+ return (UINT16)sizeof (EFI_HII_REF);\r
+\r
+ default:\r
+ return 0;\r
+ }\r
+}\r
+\r
+/**\r
+ Get UINT64 type value.\r
+\r
+ @param[in] Value Input Hii value.\r
+\r
+ @retval UINT64 Return the UINT64 type value.\r
+\r
+**/\r
+UINT64\r
+HiiValueToUINT64 (\r
+ IN EFI_HII_VALUE *Value\r
+ )\r
+{\r
+ UINT64 RetVal;\r
+\r
+ if (Value == NULL) {\r
+ return 0;\r
+ }\r
+\r
+ RetVal = 0;\r
+\r
+ switch (Value->Type) {\r
+ case EFI_IFR_TYPE_NUM_SIZE_8:\r
+ RetVal = Value->Value.u8;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_16:\r
+ RetVal = Value->Value.u16;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_32:\r
+ RetVal = Value->Value.u32;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_BOOLEAN:\r
+ RetVal = Value->Value.b;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_DATE:\r
+ RetVal = *(UINT64 *)&Value->Value.date;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_TIME:\r
+ RetVal = (*(UINT64 *)&Value->Value.time) & 0xffffff;\r
+ break;\r
+\r
+ default:\r
+ RetVal = Value->Value.u64;\r
+ break;\r
+ }\r
+\r
+ return RetVal;\r
+}\r
+\r
+/**\r
+ Compare two Hii value.\r
+\r
+ @param[in] Value1 Expression value to compare on left-hand.\r
+ @param[in] Value2 Expression value to compare on right-hand.\r
+ @param[out] Result Return value after compare.\r
+ retval 0 Two operators equal.\r
+ return Positive value if Value1 is greater than Value2.\r
+ retval Negative value if Value1 is less than Value2.\r
+ @param[in] HiiHandle Only required for string compare.\r
+\r
+ @retval other Could not perform compare on two values.\r
+ @retval EFI_SUCCESS Compare the value success.\r
+ @retval EFI_INVALID_PARAMETER Value1, Value2 or Result is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+CompareHiiValue (\r
+ IN EFI_HII_VALUE *Value1,\r
+ IN EFI_HII_VALUE *Value2,\r
+ OUT INTN *Result,\r
+ IN EFI_HII_HANDLE HiiHandle OPTIONAL\r
+ )\r
+{\r
+ INT64 Temp64;\r
+ CHAR16 *Str1;\r
+ CHAR16 *Str2;\r
+ UINTN Len;\r
+ UINT8 *Buf1;\r
+ UINT16 Buf1Len;\r
+ UINT8 *Buf2;\r
+ UINT16 Buf2Len;\r
+\r
+ if ((Value1 == NULL) || (Value2 == NULL) || (Result == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((Value1->Type == EFI_IFR_TYPE_STRING) && (Value2->Type == EFI_IFR_TYPE_STRING)) {\r
+ if ((Value1->Value.string == 0) || (Value2->Value.string == 0)) {\r
+ //\r
+ // StringId 0 is reserved\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Value1->Value.string == Value2->Value.string) {\r
+ *Result = 0;\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Str1 = GetTokenString (Value1->Value.string, HiiHandle);\r
+ if (Str1 == NULL) {\r
+ //\r
+ // String not found\r
+ //\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Str2 = GetTokenString (Value2->Value.string, HiiHandle);\r
+ if (Str2 == NULL) {\r
+ FreePool (Str1);\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ *Result = StrCmp (Str1, Str2);\r
+\r
+ FreePool (Str1);\r
+ FreePool (Str2);\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Take types(date, time, ref, buffer) as buffer\r
+ //\r
+ if (IsTypeInBuffer (Value1) && IsTypeInBuffer (Value2)) {\r
+ Buf1 = GetBufferForValue (Value1);\r
+ Buf1Len = GetLengthForValue (Value1);\r
+ Buf2 = GetBufferForValue (Value2);\r
+ Buf2Len = GetLengthForValue (Value2);\r
+\r
+ Len = Buf1Len > Buf2Len ? Buf2Len : Buf1Len;\r
+ *Result = CompareMem (Buf1, Buf2, Len);\r
+ if ((*Result == 0) && (Buf1Len != Buf2Len)) {\r
+ //\r
+ // In this case, means base on small number buffer, the data is same\r
+ // So which value has more data, which value is bigger.\r
+ //\r
+ *Result = Buf1Len > Buf2Len ? 1 : -1;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Take types(integer, boolean) as integer\r
+ //\r
+ if (IsTypeInUINT64 (Value1) && IsTypeInUINT64 (Value2)) {\r
+ Temp64 = HiiValueToUINT64 (Value1) - HiiValueToUINT64 (Value2);\r
+ if (Temp64 > 0) {\r
+ *Result = 1;\r
+ } else if (Temp64 < 0) {\r
+ *Result = -1;\r
+ } else {\r
+ *Result = 0;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+ Check if current user has the privilege specified by the permissions GUID.\r
+\r
+ @param[in] Guid A GUID specifying setup access permissions.\r
+\r
+ @retval TRUE Current user has the privilege.\r
+ @retval FALSE Current user does not have the privilege.\r
+**/\r
+BOOLEAN\r
+CheckUserPrivilege (\r
+ IN EFI_GUID *Guid\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_USER_PROFILE_HANDLE UserProfileHandle;\r
+ EFI_USER_INFO_HANDLE UserInfoHandle;\r
+ EFI_USER_INFO *UserInfo;\r
+ EFI_GUID *UserPermissionsGuid;\r
+ UINTN UserInfoSize;\r
+ UINTN AccessControlDataSize;\r
+ EFI_USER_INFO_ACCESS_CONTROL *AccessControl;\r
+ UINTN RemainSize;\r
+\r
+ if (mUserManager == NULL) {\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiUserManagerProtocolGuid,\r
+ NULL,\r
+ (VOID **)&mUserManager\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ///\r
+ /// If the system does not support user management, then it is assumed that\r
+ /// all users have admin privilege and evaluation of each EFI_IFR_SECURITY\r
+ /// op-code is always TRUE.\r
+ ///\r
+ return TRUE;\r
+ }\r
+ }\r
+\r
+ Status = mUserManager->Current (mUserManager, &UserProfileHandle);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ ///\r
+ /// Enumerate all user information of the current user profile\r
+ /// to look for any EFI_USER_INFO_ACCESS_SETUP record.\r
+ ///\r
+\r
+ for (UserInfoHandle = NULL; ;) {\r
+ Status = mUserManager->GetNextInfo (mUserManager, UserProfileHandle, &UserInfoHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+\r
+ UserInfoSize = 0;\r
+ Status = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, NULL, &UserInfoSize);\r
+ if (Status != EFI_BUFFER_TOO_SMALL) {\r
+ continue;\r
+ }\r
+\r
+ UserInfo = (EFI_USER_INFO *)AllocatePool (UserInfoSize);\r
+ if (UserInfo == NULL) {\r
+ break;\r
+ }\r
+\r
+ Status = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, UserInfo, &UserInfoSize);\r
+ if (EFI_ERROR (Status) ||\r
+ (UserInfo->InfoType != EFI_USER_INFO_ACCESS_POLICY_RECORD) ||\r
+ (UserInfo->InfoSize <= sizeof (EFI_USER_INFO)))\r
+ {\r
+ FreePool (UserInfo);\r
+ continue;\r
+ }\r
+\r
+ RemainSize = UserInfo->InfoSize - sizeof (EFI_USER_INFO);\r
+ AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)(UserInfo + 1);\r
+ while (RemainSize >= sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {\r
+ if ((RemainSize < AccessControl->Size) || (AccessControl->Size < sizeof (EFI_USER_INFO_ACCESS_CONTROL))) {\r
+ break;\r
+ }\r
+\r
+ if (AccessControl->Type == EFI_USER_INFO_ACCESS_SETUP) {\r
+ ///\r
+ /// Check if current user has the privilege specified by the permissions GUID.\r
+ ///\r
+\r
+ UserPermissionsGuid = (EFI_GUID *)(AccessControl + 1);\r
+ AccessControlDataSize = AccessControl->Size - sizeof (EFI_USER_INFO_ACCESS_CONTROL);\r
+ while (AccessControlDataSize >= sizeof (EFI_GUID)) {\r
+ if (CompareGuid (Guid, UserPermissionsGuid)) {\r
+ FreePool (UserInfo);\r
+ return TRUE;\r
+ }\r
+\r
+ UserPermissionsGuid++;\r
+ AccessControlDataSize -= sizeof (EFI_GUID);\r
+ }\r
+ }\r
+\r
+ RemainSize -= AccessControl->Size;\r
+ AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)((UINT8 *)AccessControl + AccessControl->Size);\r
+ }\r
+\r
+ FreePool (UserInfo);\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ Search a Question in Form scope using its QuestionId.\r
+\r
+ @param[in] Form The form which contains this Question.\r
+ @param[in] QuestionId Id of this Question.\r
+\r
+ @retval Pointer The Question.\r
+ @retval NULL Specified Question not found in the form.\r
+\r
+**/\r
+HII_STATEMENT *\r
+QuestionIdInForm (\r
+ IN HII_FORM *Form,\r
+ IN UINT16 QuestionId\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ HII_STATEMENT *Question;\r
+\r
+ if ((QuestionId == 0) || (Form == NULL)) {\r
+ //\r
+ // The value of zero is reserved\r
+ //\r
+ return NULL;\r
+ }\r
+\r
+ Link = GetFirstNode (&Form->StatementListHead);\r
+ while (!IsNull (&Form->StatementListHead, Link)) {\r
+ Question = HII_STATEMENT_FROM_LINK (Link);\r
+\r
+ if (Question->QuestionId == QuestionId) {\r
+ return Question;\r
+ }\r
+\r
+ Link = GetNextNode (&Form->StatementListHead, Link);\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+/**\r
+ Search a Question in Formset scope using its QuestionId.\r
+\r
+ @param[in] FormSet The formset which contains this form.\r
+ @param[in] Form The form which contains this Question.\r
+ @param[in] QuestionId Id of this Question.\r
+\r
+ @retval Pointer The Question.\r
+ @retval NULL Specified Question not found in the form.\r
+\r
+**/\r
+HII_STATEMENT *\r
+QuestionIdInFormset (\r
+ IN HII_FORMSET *FormSet,\r
+ IN HII_FORM *Form,\r
+ IN UINT16 QuestionId\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ HII_STATEMENT *Question;\r
+\r
+ if ((FormSet == NULL) || (Form == NULL)) {\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Search in the form scope first\r
+ //\r
+ Question = QuestionIdInForm (Form, QuestionId);\r
+ if (Question != NULL) {\r
+ return Question;\r
+ }\r
+\r
+ //\r
+ // Search in the formset scope\r
+ //\r
+ Link = GetFirstNode (&FormSet->FormListHead);\r
+ while (!IsNull (&FormSet->FormListHead, Link)) {\r
+ Form = HII_FORM_FROM_LINK (Link);\r
+\r
+ Question = QuestionIdInForm (Form, QuestionId);\r
+ if (Question != NULL) {\r
+ //\r
+ // EFI variable storage may be updated by Callback() asynchronous,\r
+ // to keep synchronous, always reload the Question Value.\r
+ //\r
+ if (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+ GetQuestionValue (FormSet, Form, Question, GetSetValueWithHiiDriver);\r
+ }\r
+\r
+ return Question;\r
+ }\r
+\r
+ Link = GetNextNode (&FormSet->FormListHead, Link);\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+/**\r
+ Push an Expression value onto the Stack\r
+\r
+ @param[in] Value Expression value to push.\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
+ stack.\r
+ @retval EFI_INVALID_PARAMETER Value is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+PushExpression (\r
+ IN EFI_HII_VALUE *Value\r
+ )\r
+{\r
+ if (Value == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ return PushStack (\r
+ &mExpressionEvaluationStack,\r
+ &mExpressionEvaluationStackPointer,\r
+ &mExpressionEvaluationStackEnd,\r
+ Value\r
+ );\r
+}\r
+\r
+/**\r
+ Pop an Expression value from the stack.\r
+\r
+ @param[out] Value Expression value to pop.\r
+\r
+ @retval EFI_SUCCESS The value was popped onto the stack.\r
+ @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
+ @retval EFI_INVALID_PARAMETER Value is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+PopExpression (\r
+ OUT EFI_HII_VALUE *Value\r
+ )\r
+{\r
+ if (Value == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ return PopStack (\r
+ mExpressionEvaluationStack + mExpressionEvaluationStackOffset,\r
+ &mExpressionEvaluationStackPointer,\r
+ Value\r
+ );\r
+}\r
+\r
+/**\r
+ Get current stack offset from stack start.\r
+\r
+ @return Stack offset to stack start.\r
+**/\r
+UINTN\r
+SaveExpressionEvaluationStackOffset (\r
+ VOID\r
+ )\r
+{\r
+ UINTN TempStackOffset;\r
+\r
+ TempStackOffset = mExpressionEvaluationStackOffset;\r
+ mExpressionEvaluationStackOffset = mExpressionEvaluationStackPointer - mExpressionEvaluationStack;\r
+ return TempStackOffset;\r
+}\r
+\r
+/**\r
+ Restore stack offset based on input stack offset\r
+\r
+ @param[in] StackOffset Offset to stack start.\r
+\r
+**/\r
+VOID\r
+RestoreExpressionEvaluationStackOffset (\r
+ UINTN StackOffset\r
+ )\r
+{\r
+ mExpressionEvaluationStackOffset = StackOffset;\r
+}\r
+\r
+/**\r
+ Evaluate opcode EFI_IFR_TO_STRING.\r
+\r
+ @param[in] FormSet Formset which contains this opcode.\r
+ @param[in] Format String format in EFI_IFR_TO_STRING.\r
+ @param[out] Result Evaluation result for this opcode.\r
+\r
+ @retval EFI_SUCCESS Opcode evaluation success.\r
+ @retval Other Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrToString (\r
+ IN HII_FORMSET *FormSet,\r
+ IN UINT8 Format,\r
+ OUT EFI_HII_VALUE *Result\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_VALUE Value;\r
+ CHAR16 *String;\r
+ CHAR16 *PrintFormat;\r
+ CHAR16 Buffer[MAXIMUM_VALUE_CHARACTERS];\r
+ UINT8 *SrcBuf;\r
+ UINTN BufferSize;\r
+\r
+ if ((FormSet == NULL) || (Result == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = PopExpression (&Value);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ switch (Value.Type) {\r
+ case EFI_IFR_TYPE_NUM_SIZE_8:\r
+ case EFI_IFR_TYPE_NUM_SIZE_16:\r
+ case EFI_IFR_TYPE_NUM_SIZE_32:\r
+ case EFI_IFR_TYPE_NUM_SIZE_64:\r
+ BufferSize = MAXIMUM_VALUE_CHARACTERS * sizeof (CHAR16);\r
+ switch (Format) {\r
+ case EFI_IFR_STRING_UNSIGNED_DEC:\r
+ case EFI_IFR_STRING_SIGNED_DEC:\r
+ PrintFormat = L"%ld";\r
+ break;\r
+\r
+ case EFI_IFR_STRING_LOWERCASE_HEX:\r
+ PrintFormat = L"%lx";\r
+ break;\r
+\r
+ case EFI_IFR_STRING_UPPERCASE_HEX:\r
+ PrintFormat = L"%lX";\r
+ break;\r
+\r
+ default:\r
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ UnicodeSPrint (Buffer, BufferSize, PrintFormat, Value.Value.u64);\r
+ String = Buffer;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_STRING:\r
+ CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));\r
+ return EFI_SUCCESS;\r
+\r
+ case EFI_IFR_TYPE_BOOLEAN:\r
+ String = (Value.Value.b) ? L"True" : L"False";\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_BUFFER:\r
+ case EFI_IFR_TYPE_DATE:\r
+ case EFI_IFR_TYPE_TIME:\r
+ case EFI_IFR_TYPE_REF:\r
+ //\r
+ // + 3 is base on the unicode format, the length may be odd number,\r
+ // so need 1 byte to align, also need 2 bytes for L'\0'.\r
+ //\r
+ if (Value.Type == EFI_IFR_TYPE_BUFFER) {\r
+ SrcBuf = Value.Buffer;\r
+ } else {\r
+ SrcBuf = GetBufferForValue (&Value);\r
+ }\r
+\r
+ if (Format == EFI_IFR_STRING_ASCII) {\r
+ PrintFormat = L"%a";\r
+ } else {\r
+ // Format == EFI_IFR_STRING_UNICODE\r
+ PrintFormat = L"%s";\r
+ }\r
+\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), PrintFormat, SrcBuf);\r
+ String = Buffer;\r
+ if (Value.Type == EFI_IFR_TYPE_BUFFER) {\r
+ FreePool (Value.Buffer);\r
+ }\r
+\r
+ break;\r
+\r
+ default:\r
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Result->Type = EFI_IFR_TYPE_STRING;\r
+ Result->Value.string = NewHiiString (String, FormSet->HiiHandle);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Evaluate opcode EFI_IFR_TO_UINT.\r
+\r
+ @param[in] FormSet Formset which contains this opcode.\r
+ @param[out] Result Evaluation result for this opcode.\r
+\r
+ @retval EFI_SUCCESS Opcode evaluation success.\r
+ @retval Other Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrToUint (\r
+ IN HII_FORMSET *FormSet,\r
+ OUT EFI_HII_VALUE *Result\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_VALUE Value;\r
+ CHAR16 *String;\r
+ CHAR16 *StringPtr;\r
+\r
+ if ((FormSet == NULL) || (Result == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = PopExpression (&Value);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if ((Value.Type >= EFI_IFR_TYPE_OTHER) && !IsTypeInBuffer (&Value)) {\r
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ if (Value.Type == EFI_IFR_TYPE_STRING) {\r
+ String = GetTokenString (Value.Value.string, FormSet->HiiHandle);\r
+ if (String == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ IfrStrToUpper (String);\r
+ StringPtr = StrStr (String, L"0X");\r
+ if (StringPtr != NULL) {\r
+ //\r
+ // Hex string\r
+ //\r
+ Result->Value.u64 = StrHexToUint64 (String);\r
+ } else {\r
+ //\r
+ // decimal string\r
+ //\r
+ Result->Value.u64 = StrDecimalToUint64 (String);\r
+ }\r
+\r
+ FreePool (String);\r
+ } else if (IsTypeInBuffer (&Value)) {\r
+ if (GetLengthForValue (&Value) > 8) {\r
+ if (Value.Type == EFI_IFR_TYPE_BUFFER) {\r
+ FreePool (Value.Buffer);\r
+ }\r
+\r
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Result->Value.u64 = *(UINT64 *)GetBufferForValue (&Value);\r
+ if (Value.Type == EFI_IFR_TYPE_BUFFER) {\r
+ FreePool (Value.Buffer);\r
+ }\r
+ } else {\r
+ CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));\r
+ }\r
+\r
+ Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Evaluate opcode EFI_IFR_CATENATE.\r
+\r
+ @param[in] FormSet Formset which contains this opcode.\r
+ @param[out] Result Evaluation result for this opcode.\r
+\r
+ @retval EFI_SUCCESS Opcode evaluation success.\r
+ @retval Other Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrCatenate (\r
+ IN HII_FORMSET *FormSet,\r
+ OUT EFI_HII_VALUE *Result\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_VALUE Value[2];\r
+ CHAR16 *String[2];\r
+ UINTN Index;\r
+ CHAR16 *StringPtr;\r
+ UINTN Size;\r
+ UINT16 Length0;\r
+ UINT16 Length1;\r
+ UINT8 *TmpBuf;\r
+ UINTN MaxLen;\r
+\r
+ if ((FormSet == NULL) || (Result == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // String[0] - The second string\r
+ // String[1] - The first string\r
+ //\r
+ String[0] = NULL;\r
+ String[1] = NULL;\r
+ StringPtr = NULL;\r
+ Status = EFI_SUCCESS;\r
+ ZeroMem (Value, sizeof (Value));\r
+\r
+ Status = PopExpression (&Value[0]);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ Status = PopExpression (&Value[1]);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ for (Index = 0; Index < 2; Index++) {\r
+ if ((Value[Index].Type != EFI_IFR_TYPE_STRING) && !IsTypeInBuffer (&Value[Index])) {\r
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ Status = EFI_SUCCESS;\r
+ goto Done;\r
+ }\r
+\r
+ if (Value[Index].Type == EFI_IFR_TYPE_STRING) {\r
+ String[Index] = GetTokenString (Value[Index].Value.string, FormSet->HiiHandle);\r
+ if (String[Index] == NULL) {\r
+ Status = EFI_NOT_FOUND;\r
+ goto Done;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (Value[0].Type == EFI_IFR_TYPE_STRING) {\r
+ Size = StrSize (String[0]);\r
+ MaxLen = (StrSize (String[1]) + Size) / sizeof (CHAR16);\r
+ StringPtr = AllocatePool (MaxLen * sizeof (CHAR16));\r
+ ASSERT (StringPtr != NULL);\r
+ StrCpyS (StringPtr, MaxLen, String[1]);\r
+ StrCatS (StringPtr, MaxLen, String[0]);\r
+\r
+ Result->Type = EFI_IFR_TYPE_STRING;\r
+ Result->Value.string = NewHiiString (StringPtr, FormSet->HiiHandle);\r
+ } else {\r
+ Result->Type = EFI_IFR_TYPE_BUFFER;\r
+ Length0 = GetLengthForValue (&Value[0]);\r
+ Length1 = GetLengthForValue (&Value[1]);\r
+ Result->BufferLen = (UINT16)(Length0 + Length1);\r
+\r
+ Result->Buffer = AllocatePool (Result->BufferLen);\r
+ ASSERT (Result->Buffer != NULL);\r
+\r
+ TmpBuf = GetBufferForValue (&Value[0]);\r
+ ASSERT (TmpBuf != NULL);\r
+ CopyMem (Result->Buffer, TmpBuf, Length0);\r
+ TmpBuf = GetBufferForValue (&Value[1]);\r
+ ASSERT (TmpBuf != NULL);\r
+ CopyMem (&Result->Buffer[Length0], TmpBuf, Length1);\r
+ }\r
+\r
+Done:\r
+ if (Value[0].Buffer != NULL) {\r
+ FreePool (Value[0].Buffer);\r
+ }\r
+\r
+ if (Value[1].Buffer != NULL) {\r
+ FreePool (Value[1].Buffer);\r
+ }\r
+\r
+ if (String[0] != NULL) {\r
+ FreePool (String[0]);\r
+ }\r
+\r
+ if (String[1] != NULL) {\r
+ FreePool (String[1]);\r
+ }\r
+\r
+ if (StringPtr != NULL) {\r
+ FreePool (StringPtr);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Evaluate opcode EFI_IFR_MATCH.\r
+\r
+ @param[in] FormSet Formset which contains this opcode.\r
+ @param[out] Result Evaluation result for this opcode.\r
+\r
+ @retval EFI_SUCCESS Opcode evaluation success.\r
+ @retval Other Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrMatch (\r
+ IN HII_FORMSET *FormSet,\r
+ OUT EFI_HII_VALUE *Result\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_VALUE Value[2];\r
+ CHAR16 *String[2];\r
+ UINTN Index;\r
+\r
+ if ((FormSet == NULL) || (Result == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // String[0] - The string to search\r
+ // String[1] - pattern\r
+ //\r
+ String[0] = NULL;\r
+ String[1] = NULL;\r
+ Status = EFI_SUCCESS;\r
+ ZeroMem (Value, sizeof (Value));\r
+\r
+ Status = PopExpression (&Value[0]);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ Status = PopExpression (&Value[1]);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ for (Index = 0; Index < 2; Index++) {\r
+ if (Value[Index].Type != EFI_IFR_TYPE_STRING) {\r
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ Status = EFI_SUCCESS;\r
+ goto Done;\r
+ }\r
+\r
+ String[Index] = GetTokenString (Value[Index].Value.string, FormSet->HiiHandle);\r
+ if (String[Index] == NULL) {\r
+ Status = EFI_NOT_FOUND;\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ Result->Type = EFI_IFR_TYPE_BOOLEAN;\r
+ Result->Value.b = mUnicodeCollation->MetaiMatch (mUnicodeCollation, String[0], String[1]);\r
+\r
+Done:\r
+ if (String[0] != NULL) {\r
+ FreePool (String[0]);\r
+ }\r
+\r
+ if (String[1] != NULL) {\r
+ FreePool (String[1]);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Evaluate opcode EFI_IFR_MATCH2.\r
+\r
+ @param[in] FormSet Formset which contains this opcode.\r
+ @param[in] SyntaxType Syntax type for match2.\r
+ @param[out] Result Evaluation result for this opcode.\r
+\r
+ @retval EFI_SUCCESS Opcode evaluation success.\r
+ @retval Other Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrMatch2 (\r
+ IN HII_FORMSET *FormSet,\r
+ IN EFI_GUID *SyntaxType,\r
+ OUT EFI_HII_VALUE *Result\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_VALUE Value[2];\r
+ CHAR16 *String[2];\r
+ UINTN Index;\r
+ UINTN GuidIndex;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN BufferSize;\r
+ EFI_REGULAR_EXPRESSION_PROTOCOL *RegularExpressionProtocol;\r
+ UINTN RegExSyntaxTypeListSize;\r
+ EFI_REGEX_SYNTAX_TYPE *RegExSyntaxTypeList;\r
+ UINTN CapturesCount;\r
+\r
+ if ((FormSet == NULL) || (SyntaxType == NULL) || (Result == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // String[0] - The string to search\r
+ // String[1] - pattern\r
+ //\r
+ String[0] = NULL;\r
+ String[1] = NULL;\r
+ HandleBuffer = NULL;\r
+ RegExSyntaxTypeList = NULL;\r
+ Status = EFI_SUCCESS;\r
+ ZeroMem (Value, sizeof (Value));\r
+\r
+ Status = PopExpression (&Value[0]);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ Status = PopExpression (&Value[1]);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ for (Index = 0; Index < 2; Index++) {\r
+ if (Value[Index].Type != EFI_IFR_TYPE_STRING) {\r
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ Status = EFI_SUCCESS;\r
+ goto Done;\r
+ }\r
+\r
+ String[Index] = GetTokenString (Value[Index].Value.string, FormSet->HiiHandle);\r
+ if (String[Index] == NULL) {\r
+ Status = EFI_NOT_FOUND;\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ BufferSize = 0;\r
+ HandleBuffer = NULL;\r
+ Status = gBS->LocateHandle (\r
+ ByProtocol,\r
+ &gEfiRegularExpressionProtocolGuid,\r
+ NULL,\r
+ &BufferSize,\r
+ HandleBuffer\r
+ );\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ HandleBuffer = AllocatePool (BufferSize);\r
+ if (HandleBuffer == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+\r
+ Status = gBS->LocateHandle (\r
+ ByProtocol,\r
+ &gEfiRegularExpressionProtocolGuid,\r
+ NULL,\r
+ &BufferSize,\r
+ HandleBuffer\r
+ );\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ Status = EFI_SUCCESS;\r
+ goto Done;\r
+ }\r
+\r
+ ASSERT (HandleBuffer != NULL);\r
+ for ( Index = 0; Index < BufferSize / sizeof (EFI_HANDLE); Index++) {\r
+ Status = gBS->HandleProtocol (\r
+ HandleBuffer[Index],\r
+ &gEfiRegularExpressionProtocolGuid,\r
+ (VOID **)&RegularExpressionProtocol\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ RegExSyntaxTypeListSize = 0;\r
+ RegExSyntaxTypeList = NULL;\r
+\r
+ Status = RegularExpressionProtocol->GetInfo (\r
+ RegularExpressionProtocol,\r
+ &RegExSyntaxTypeListSize,\r
+ RegExSyntaxTypeList\r
+ );\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ RegExSyntaxTypeList = AllocatePool (RegExSyntaxTypeListSize);\r
+ if (RegExSyntaxTypeList == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+\r
+ Status = RegularExpressionProtocol->GetInfo (\r
+ RegularExpressionProtocol,\r
+ &RegExSyntaxTypeListSize,\r
+ RegExSyntaxTypeList\r
+ );\r
+ } else if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ for (GuidIndex = 0; GuidIndex < RegExSyntaxTypeListSize / sizeof (EFI_GUID); GuidIndex++) {\r
+ if (CompareGuid (&RegExSyntaxTypeList[GuidIndex], SyntaxType)) {\r
+ //\r
+ // Find the match type, return the value.\r
+ //\r
+ Result->Type = EFI_IFR_TYPE_BOOLEAN;\r
+ Status = RegularExpressionProtocol->MatchString (\r
+ RegularExpressionProtocol,\r
+ String[0],\r
+ String[1],\r
+ SyntaxType,\r
+ &Result->Value.b,\r
+ NULL,\r
+ &CapturesCount\r
+ );\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ if (RegExSyntaxTypeList != NULL) {\r
+ FreePool (RegExSyntaxTypeList);\r
+ }\r
+ }\r
+\r
+ //\r
+ // Type specified by SyntaxType is not supported\r
+ // in any of the EFI_REGULAR_EXPRESSION_PROTOCOL instances.\r
+ //\r
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ Status = EFI_SUCCESS;\r
+\r
+Done:\r
+ if (String[0] != NULL) {\r
+ FreePool (String[0]);\r
+ }\r
+\r
+ if (String[1] != NULL) {\r
+ FreePool (String[1]);\r
+ }\r
+\r
+ if (RegExSyntaxTypeList != NULL) {\r
+ FreePool (RegExSyntaxTypeList);\r
+ }\r
+\r
+ if (HandleBuffer != NULL) {\r
+ FreePool (HandleBuffer);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Evaluate opcode EFI_IFR_FIND.\r
+\r
+ @param[in] FormSet Formset which contains this opcode.\r
+ @param[in] Format Case sensitive or insensitive.\r
+ @param[out] Result Evaluation result for this opcode.\r
+\r
+ @retval EFI_SUCCESS Opcode evaluation success.\r
+ @retval Other Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrFind (\r
+ IN HII_FORMSET *FormSet,\r
+ IN UINT8 Format,\r
+ OUT EFI_HII_VALUE *Result\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_VALUE Value[3];\r
+ CHAR16 *String[2];\r
+ UINTN Base;\r
+ CHAR16 *StringPtr;\r
+ UINTN Index;\r
+\r
+ if ((FormSet == NULL) || (Result == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ ZeroMem (Value, sizeof (Value));\r
+\r
+ if (Format > EFI_IFR_FF_CASE_INSENSITIVE) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = PopExpression (&Value[0]);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = PopExpression (&Value[1]);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = PopExpression (&Value[2]);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Base = (UINTN)Value[0].Value.u64;\r
+\r
+ //\r
+ // String[0] - sub-string\r
+ // String[1] - The string to search\r
+ //\r
+ String[0] = NULL;\r
+ String[1] = NULL;\r
+ for (Index = 0; Index < 2; Index++) {\r
+ if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {\r
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ Status = EFI_SUCCESS;\r
+ goto Done;\r
+ }\r
+\r
+ String[Index] = GetTokenString (Value[Index + 1].Value.string, FormSet->HiiHandle);\r
+ if (String[Index] == NULL) {\r
+ Status = EFI_NOT_FOUND;\r
+ goto Done;\r
+ }\r
+\r
+ if (Format == EFI_IFR_FF_CASE_INSENSITIVE) {\r
+ //\r
+ // Case insensitive, convert both string to upper case\r
+ //\r
+ IfrStrToUpper (String[Index]);\r
+ }\r
+ }\r
+\r
+ Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+ if (Base >= StrLen (String[1])) {\r
+ Result->Value.u64 = 0xFFFFFFFFFFFFFFFFULL;\r
+ } else {\r
+ StringPtr = StrStr (String[1] + Base, String[0]);\r
+ Result->Value.u64 = (StringPtr == NULL) ? 0xFFFFFFFFFFFFFFFFULL : (StringPtr - String[1]);\r
+ }\r
+\r
+Done:\r
+ if (String[0] != NULL) {\r
+ FreePool (String[0]);\r
+ }\r
+\r
+ if (String[1] != NULL) {\r
+ FreePool (String[1]);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Evaluate opcode EFI_IFR_MID.\r
+\r
+ @param[in] FormSet Formset which contains this opcode.\r
+ @param[out] Result Evaluation result for this opcode.\r
+\r
+ @retval EFI_SUCCESS Opcode evaluation success.\r
+ @retval Other Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrMid (\r
+ IN HII_FORMSET *FormSet,\r
+ OUT EFI_HII_VALUE *Result\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_VALUE Value[3];\r
+ CHAR16 *String;\r
+ UINTN Base;\r
+ UINTN Length;\r
+ CHAR16 *SubString;\r
+ UINT16 BufferLen;\r
+ UINT8 *Buffer;\r
+\r
+ if ((FormSet == NULL) || (Result == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ ZeroMem (Value, sizeof (Value));\r
+\r
+ Status = PopExpression (&Value[0]);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = PopExpression (&Value[1]);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = PopExpression (&Value[2]);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Length = (UINTN)Value[0].Value.u64;\r
+\r
+ if (Value[1].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Base = (UINTN)Value[1].Value.u64;\r
+\r
+ if ((Value[2].Type != EFI_IFR_TYPE_STRING) && !IsTypeInBuffer (&Value[2])) {\r
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (Value[2].Type == EFI_IFR_TYPE_STRING) {\r
+ String = GetTokenString (Value[2].Value.string, FormSet->HiiHandle);\r
+ if (String == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ if ((Length == 0) || (Base >= StrLen (String))) {\r
+ SubString = gEmptyString;\r
+ } else {\r
+ SubString = String + Base;\r
+ if ((Base + Length) < StrLen (String)) {\r
+ SubString[Length] = L'\0';\r
+ }\r
+ }\r
+\r
+ Result->Type = EFI_IFR_TYPE_STRING;\r
+ Result->Value.string = NewHiiString (SubString, FormSet->HiiHandle);\r
+\r
+ FreePool (String);\r
+ } else {\r
+ BufferLen = GetLengthForValue (&Value[2]);\r
+ Buffer = GetBufferForValue (&Value[2]);\r
+\r
+ Result->Type = EFI_IFR_TYPE_BUFFER;\r
+ if ((Length == 0) || (Base >= BufferLen)) {\r
+ Result->BufferLen = 0;\r
+ Result->Buffer = NULL;\r
+ } else {\r
+ Result->BufferLen = (UINT16)((BufferLen - Base) < Length ? (BufferLen - Base) : Length);\r
+ Result->Buffer = AllocatePool (Result->BufferLen);\r
+ ASSERT (Result->Buffer != NULL);\r
+ CopyMem (Result->Buffer, &Buffer[Base], Result->BufferLen);\r
+ }\r
+\r
+ if (Value[2].Type == EFI_IFR_TYPE_BUFFER) {\r
+ FreePool (Value[2].Buffer);\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Evaluate opcode EFI_IFR_TOKEN.\r
+\r
+ @param[in] FormSet Formset which contains this opcode.\r
+ @param[out] Result Evaluation result for this opcode.\r
+\r
+ @retval EFI_SUCCESS Opcode evaluation success.\r
+ @retval Other Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrToken (\r
+ IN HII_FORMSET *FormSet,\r
+ OUT EFI_HII_VALUE *Result\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_VALUE Value[3];\r
+ CHAR16 *String[2];\r
+ UINTN Count;\r
+ CHAR16 *Delimiter;\r
+ CHAR16 *SubString;\r
+ CHAR16 *StringPtr;\r
+ UINTN Index;\r
+\r
+ if ((FormSet == NULL) || (Result == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ ZeroMem (Value, sizeof (Value));\r
+\r
+ Status = PopExpression (&Value[0]);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = PopExpression (&Value[1]);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = PopExpression (&Value[2]);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Count = (UINTN)Value[0].Value.u64;\r
+\r
+ //\r
+ // String[0] - Delimiter\r
+ // String[1] - The string to search\r
+ //\r
+ String[0] = NULL;\r
+ String[1] = NULL;\r
+ for (Index = 0; Index < 2; Index++) {\r
+ if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {\r
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ Status = EFI_SUCCESS;\r
+ goto Done;\r
+ }\r
+\r
+ String[Index] = GetTokenString (Value[Index + 1].Value.string, FormSet->HiiHandle);\r
+ if (String[Index] == NULL) {\r
+ Status = EFI_NOT_FOUND;\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ Delimiter = String[0];\r
+ SubString = String[1];\r
+ while (Count > 0) {\r
+ SubString = StrStr (SubString, Delimiter);\r
+ if (SubString != NULL) {\r
+ //\r
+ // Skip over the delimiter\r
+ //\r
+ SubString = SubString + StrLen (Delimiter);\r
+ } else {\r
+ break;\r
+ }\r
+\r
+ Count--;\r
+ }\r
+\r
+ if (SubString == NULL) {\r
+ //\r
+ // nth delimited sub-string not found, push an empty string\r
+ //\r
+ SubString = gEmptyString;\r
+ } else {\r
+ //\r
+ // Put a NULL terminator for nth delimited sub-string\r
+ //\r
+ StringPtr = StrStr (SubString, Delimiter);\r
+ if (StringPtr != NULL) {\r
+ *StringPtr = L'\0';\r
+ }\r
+ }\r
+\r
+ Result->Type = EFI_IFR_TYPE_STRING;\r
+ Result->Value.string = NewHiiString (SubString, FormSet->HiiHandle);\r
+\r
+Done:\r
+ if (String[0] != NULL) {\r
+ FreePool (String[0]);\r
+ }\r
+\r
+ if (String[1] != NULL) {\r
+ FreePool (String[1]);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Evaluate opcode EFI_IFR_SPAN.\r
+\r
+ @param[in] FormSet Formset which contains this opcode.\r
+ @param[in] Flags FIRST_MATCHING or FIRST_NON_MATCHING.\r
+ @param[out] Result Evaluation result for this opcode.\r
+\r
+ @retval EFI_SUCCESS Opcode evaluation success.\r
+ @retval Other Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrSpan (\r
+ IN HII_FORMSET *FormSet,\r
+ IN UINT8 Flags,\r
+ OUT EFI_HII_VALUE *Result\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_VALUE Value[3];\r
+ CHAR16 *String[2];\r
+ CHAR16 *Charset;\r
+ UINTN Base;\r
+ UINTN Index;\r
+ CHAR16 *StringPtr;\r
+ BOOLEAN Found;\r
+\r
+ if ((FormSet == NULL) || (Result == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ ZeroMem (Value, sizeof (Value));\r
+\r
+ Status = PopExpression (&Value[0]);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = PopExpression (&Value[1]);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = PopExpression (&Value[2]);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Base = (UINTN)Value[0].Value.u64;\r
+\r
+ //\r
+ // String[0] - Charset\r
+ // String[1] - The string to search\r
+ //\r
+ String[0] = NULL;\r
+ String[1] = NULL;\r
+ for (Index = 0; Index < 2; Index++) {\r
+ if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {\r
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ Status = EFI_SUCCESS;\r
+ goto Done;\r
+ }\r
+\r
+ String[Index] = GetTokenString (Value[Index + 1].Value.string, FormSet->HiiHandle);\r
+ if (String[Index] == NULL) {\r
+ Status = EFI_NOT_FOUND;\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ if (Base >= StrLen (String[1])) {\r
+ Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ Status = EFI_SUCCESS;\r
+ goto Done;\r
+ }\r
+\r
+ Found = FALSE;\r
+ StringPtr = String[1] + Base;\r
+ Charset = String[0];\r
+ while (*StringPtr != 0 && !Found) {\r
+ Index = 0;\r
+ while (Charset[Index] != 0) {\r
+ if ((*StringPtr >= Charset[Index]) && (*StringPtr <= Charset[Index + 1])) {\r
+ if (Flags == EFI_IFR_FLAGS_FIRST_MATCHING) {\r
+ Found = TRUE;\r
+ break;\r
+ }\r
+ } else {\r
+ if (Flags == EFI_IFR_FLAGS_FIRST_NON_MATCHING) {\r
+ Found = TRUE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Skip characters pair representing low-end of a range and high-end of a range\r
+ //\r
+ Index += 2;\r
+ }\r
+\r
+ if (!Found) {\r
+ StringPtr++;\r
+ }\r
+ }\r
+\r
+ Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+ Result->Value.u64 = StringPtr - String[1];\r
+\r
+Done:\r
+ if (String[0] != NULL) {\r
+ FreePool (String[0]);\r
+ }\r
+\r
+ if (String[1] != NULL) {\r
+ FreePool (String[1]);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Get Expression given its RuleId.\r
+\r
+ @param[in] Form The form which contains this Expression.\r
+ @param[in] RuleId Id of this Expression.\r
+\r
+ @retval Pointer The Expression.\r
+ @retval NULL Specified Expression not found in the form.\r
+\r
+**/\r
+HII_EXPRESSION *\r
+RuleIdToExpression (\r
+ IN HII_FORM *Form,\r
+ IN UINT8 RuleId\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ HII_EXPRESSION *Expression;\r
+\r
+ if (Form == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ Link = GetFirstNode (&Form->RuleListHead);\r
+ while (!IsNull (&Form->RuleListHead, Link)) {\r
+ Expression = HII_EXPRESSION_FROM_LINK (Link);\r
+\r
+ if ((Expression->Type == EFI_HII_EXPRESSION_RULE) && (Expression->ExtraData.RuleId == RuleId)) {\r
+ return Expression;\r
+ }\r
+\r
+ Link = GetNextNode (&Form->RuleListHead, Link);\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+/**\r
+ Locate the Unicode Collation Protocol interface for later use.\r
+\r
+ @retval EFI_SUCCESS Protocol interface initialize success.\r
+ @retval Other Protocol interface initialize failed.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeUnicodeCollationProtocol (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ if (mUnicodeCollation != NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // BUGBUG: Proper implementation is to locate all Unicode Collation Protocol\r
+ // instances first and then select one which support English language.\r
+ // Current implementation just pick the first instance.\r
+ //\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiUnicodeCollation2ProtocolGuid,\r
+ NULL,\r
+ (VOID **)&mUnicodeCollation\r
+ );\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Check whether the formset guid is in this Hii package list.\r
+\r
+ @param[in] HiiHandle The HiiHandle for this HII package list.\r
+ @param[in] FormSetGuid The formset guid for the request formset.\r
+\r
+ @retval TRUE Find the formset guid.\r
+ @retval FALSE Not found the formset guid.\r
+\r
+**/\r
+BOOLEAN\r
+IsFormsetGuidInHiiHandle (\r
+ IN EFI_HII_HANDLE HiiHandle,\r
+ IN EFI_GUID *FormSetGuid\r
+ )\r
+{\r
+ EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
+ UINTN BufferSize;\r
+ UINT32 Offset;\r
+ UINT32 Offset2;\r
+ UINT32 PackageListLength;\r
+ EFI_HII_PACKAGE_HEADER *PackageHeader;\r
+ UINT8 *Package;\r
+ UINT8 *OpCodeData;\r
+ EFI_STATUS Status;\r
+ BOOLEAN FindGuid;\r
+ EFI_HII_DATABASE_PROTOCOL *HiiDatabase;\r
+\r
+ if (FormSetGuid == NULL) {\r
+ return FALSE;\r
+ }\r
+\r
+ BufferSize = 0;\r
+ HiiPackageList = NULL;\r
+ FindGuid = FALSE;\r
+\r
+ //\r
+ // Locate required Hii Database protocol\r
+ //\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiHiiDatabaseProtocolGuid,\r
+ NULL,\r
+ (VOID **)&HiiDatabase\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return FALSE;\r
+ }\r
+\r
+ Status = HiiDatabase->ExportPackageLists (HiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ HiiPackageList = AllocatePool (BufferSize);\r
+ if (HiiPackageList == NULL) {\r
+ ASSERT (HiiPackageList != NULL);\r
+ return FALSE;\r
+ }\r
+\r
+ Status = HiiDatabase->ExportPackageLists (HiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
+ } else {\r
+ //\r
+ // Fix coverity: 14253 Explicit null dereferenced.\r
+ // When calling ExportPackageLists with BufferSize = 0, only EFI_BUFFER_TOO_SMALL is expected.\r
+ // Otherwise, return FALSE immediately.\r
+ //\r
+ return FALSE;\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ if (HiiPackageList != NULL) {\r
+ FreePool (HiiPackageList);\r
+ }\r
+\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Get Form package from this HII package List\r
+ //\r
+ Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+ Offset2 = 0;\r
+ PackageListLength = HiiPackageList->PackageLength;\r
+\r
+ while (Offset < PackageListLength) {\r
+ Package = ((UINT8 *)HiiPackageList) + Offset;\r
+ PackageHeader = (EFI_HII_PACKAGE_HEADER *)Package;\r
+ Offset += PackageHeader->Length;\r
+\r
+ if (PackageHeader->Type == EFI_HII_PACKAGE_FORMS) {\r
+ //\r
+ // Search FormSet in this Form Package\r
+ //\r
+ Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
+ while (Offset2 < PackageHeader->Length) {\r
+ OpCodeData = Package + Offset2;\r
+\r
+ if (((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
+ if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
+ FindGuid = TRUE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ Offset2 += ((EFI_IFR_OP_HEADER *)OpCodeData)->Length;\r
+ }\r
+ }\r
+\r
+ if (FindGuid) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ FreePool (HiiPackageList);\r
+\r
+ return FindGuid;\r
+}\r
+\r
+/**\r
+ Find HII Handle in the HII database associated with given Device Path.\r
+\r
+ If DevicePath is NULL, then ASSERT.\r
+\r
+ @param[in] DevicePath Device Path associated with the HII package list\r
+ handle.\r
+ @param[in] FormsetGuid The formset guid for this formset.\r
+\r
+ @retval Handle HII package list Handle associated with the Device\r
+ Path.\r
+ @retval NULL Hii Package list handle is not found.\r
+\r
+**/\r
+EFI_HII_HANDLE\r
+DevicePathToHiiHandle (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ IN EFI_GUID *FormsetGuid\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;\r
+ UINTN Index;\r
+ EFI_HANDLE Handle;\r
+ EFI_HANDLE DriverHandle;\r
+ EFI_HII_HANDLE *HiiHandles;\r
+ EFI_HII_HANDLE HiiHandle;\r
+ EFI_HII_DATABASE_PROTOCOL *HiiDatabase;\r
+\r
+ if ((DevicePath == NULL) || (FormsetGuid == NULL)) {\r
+ return NULL;\r
+ }\r
+\r
+ TmpDevicePath = DevicePath;\r
+ //\r
+ // Locate Device Path Protocol handle buffer\r
+ //\r
+ Status = gBS->LocateDevicePath (\r
+ &gEfiDevicePathProtocolGuid,\r
+ &TmpDevicePath,\r
+ &DriverHandle\r
+ );\r
+ if (EFI_ERROR (Status) || !IsDevicePathEnd (TmpDevicePath)) {\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Locate required Hii Database protocol\r
+ //\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiHiiDatabaseProtocolGuid,\r
+ NULL,\r
+ (VOID **)&HiiDatabase\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Retrieve all HII Handles from HII database\r
+ //\r
+ HiiHandles = HiiGetHiiHandles (NULL);\r
+ if (HiiHandles == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Search Hii Handle by Driver Handle\r
+ //\r
+ HiiHandle = NULL;\r
+ for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
+ Status = HiiDatabase->GetPackageListHandle (\r
+ HiiDatabase,\r
+ HiiHandles[Index],\r
+ &Handle\r
+ );\r
+ if (!EFI_ERROR (Status) && (Handle == DriverHandle)) {\r
+ if (IsFormsetGuidInHiiHandle (HiiHandles[Index], FormsetGuid)) {\r
+ HiiHandle = HiiHandles[Index];\r
+ break;\r
+ }\r
+\r
+ if (HiiHandle != NULL) {\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ FreePool (HiiHandles);\r
+ return HiiHandle;\r
+}\r
+\r
+/**\r
+ Get question value from the predefined formset.\r
+\r
+ @param[in] DevicePath The driver's device path which produce the formset data.\r
+ @param[in] InputHiiHandle The hii handle associate with the formset data.\r
+ @param[in] FormSetGuid The formset guid which include the question.\r
+ @param[in] QuestionId The question id which need to get value from.\r
+ @param[out] Value The return data about question's value.\r
+\r
+ @retval TRUE Get the question value success.\r
+ @retval FALSE Get the question value failed.\r
+**/\r
+BOOLEAN\r
+GetQuestionValueFromForm (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ IN EFI_HII_HANDLE InputHiiHandle,\r
+ IN EFI_GUID *FormSetGuid,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ OUT EFI_HII_VALUE *Value\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_HANDLE HiiHandle;\r
+ HII_STATEMENT *Question;\r
+ HII_FORMSET *FormSet;\r
+ HII_FORM *Form;\r
+ BOOLEAN GetTheVal;\r
+ LIST_ENTRY *Link;\r
+\r
+ //\r
+ // The input parameter DevicePath or InputHiiHandle must have one valid input.\r
+ //\r
+ if ((DevicePath == NULL) && (InputHiiHandle == NULL)) {\r
+ ASSERT (\r
+ (DevicePath != NULL && InputHiiHandle == NULL) ||\r
+ (DevicePath == NULL && InputHiiHandle != NULL)\r
+ );\r
+ return FALSE;\r
+ }\r
+\r
+ if ((FormSetGuid == NULL) || (Value == NULL)) {\r
+ return FALSE;\r
+ }\r
+\r
+ GetTheVal = TRUE;\r
+ HiiHandle = NULL;\r
+ Question = NULL;\r
+ Form = NULL;\r
+\r
+ //\r
+ // Get HiiHandle.\r
+ //\r
+ if (DevicePath != NULL) {\r
+ HiiHandle = DevicePathToHiiHandle (DevicePath, FormSetGuid);\r
+ if (HiiHandle == NULL) {\r
+ return FALSE;\r
+ }\r
+ } else {\r
+ HiiHandle = InputHiiHandle;\r
+ }\r
+\r
+ ASSERT (HiiHandle != NULL);\r
+\r
+ //\r
+ // Get the formset data include this question.\r
+ //\r
+ FormSet = AllocateZeroPool (sizeof (HII_FORMSET));\r
+ ASSERT (FormSet != NULL);\r
+\r
+ Status = CreateFormSetFromHiiHandle (HiiHandle, FormSetGuid, FormSet);\r
+ if (EFI_ERROR (Status)) {\r
+ GetTheVal = FALSE;\r
+ goto Done;\r
+ }\r
+\r
+ InitializeFormSet (FormSet);\r
+\r
+ //\r
+ // Base on the Question Id to get the question info.\r
+ //\r
+ Question = QuestionIdInFormset (FormSet, NULL, QuestionId);\r
+ if (Question == NULL) {\r
+ GetTheVal = FALSE;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Search form in the formset scope\r
+ //\r
+ Link = GetFirstNode (&FormSet->FormListHead);\r
+ while (!IsNull (&FormSet->FormListHead, Link)) {\r
+ Form = HII_FORM_FROM_LINK (Link);\r
+\r
+ Question = QuestionIdInForm (Form, QuestionId);\r
+ if (Question != NULL) {\r
+ break;\r
+ }\r
+\r
+ Link = GetNextNode (&FormSet->FormListHead, Link);\r
+ Form = NULL;\r
+ }\r
+\r
+ ASSERT (Form != NULL);\r
+\r
+ //\r
+ // Get the question value.\r
+ //\r
+ Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);\r
+ if (EFI_ERROR (Status)) {\r
+ GetTheVal = FALSE;\r
+ goto Done;\r
+ }\r
+\r
+ CopyMem (Value, &Question->Value, sizeof (EFI_HII_VALUE));\r
+\r
+Done:\r
+ //\r
+ // Clean the formset structure and restore the global parameter.\r
+ //\r
+ if (FormSet != NULL) {\r
+ DestroyFormSet (FormSet);\r
+ }\r
+\r
+ return GetTheVal;\r
+}\r
+\r
+/**\r
+ Covert HII_STATEMENT_VALUE to EFI_HII_VALUE.\r
+\r
+ The HiiValue->Buffer is allocated from EFI boot services memory. It is the\r
+ responsibility of the caller to free the memory allocated.\r
+\r
+ @param[in] StatementValue Source to be converted.\r
+ @param[out] HiiValue The buffer that is converted from StatementValue\r
+\r
+ @retval EFI_SUCCESS Convert successfully.\r
+ @retval EFI_INVALID_PARAMETER StatementValue is NULL or HiiValue is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+HiiStatementValueToHiiValue (\r
+ IN HII_STATEMENT_VALUE *StatementValue,\r
+ OUT EFI_HII_VALUE *HiiValue\r
+ )\r
+{\r
+ if ((StatementValue == NULL) || (HiiValue == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ ZeroMem (HiiValue, sizeof (EFI_HII_VALUE));\r
+\r
+ HiiValue->Type = StatementValue->Type;\r
+ HiiValue->BufferLen = StatementValue->BufferLen;\r
+ if ((StatementValue->Buffer != NULL) && (StatementValue->BufferLen > 0)) {\r
+ HiiValue->Buffer = AllocateCopyPool (HiiValue->BufferLen, StatementValue->Buffer);\r
+ }\r
+\r
+ CopyMem (&HiiValue->Value, &StatementValue->Value, sizeof (EFI_IFR_TYPE_VALUE));\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Release the buffer in EFI_HII_VALUE if the buffer is not NULL.\r
+\r
+ @param[in] HiiValue The buffer to be released.\r
+\r
+ @retval EFI_SUCCESS release HiiValue successfully.\r
+ @retval EFI_INVALID_PARAMETER HiiValue is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+ReleaseHiiValue (\r
+ IN EFI_HII_VALUE *HiiValue\r
+ )\r
+{\r
+ if (HiiValue == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (HiiValue->Buffer == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ FreePool (HiiValue->Buffer);\r
+ ZeroMem (HiiValue, sizeof (EFI_HII_VALUE));\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Evaluate the result of a HII expression.\r
+\r
+ If Expression is NULL, then ASSERT.\r
+\r
+ @param[in] FormSet FormSet associated with this expression.\r
+ @param[in] Form Form associated with this expression.\r
+ @param[in,out] Expression Expression to be evaluated.\r
+\r
+ @retval EFI_SUCCESS The expression evaluated successfully.\r
+ @retval EFI_NOT_FOUND The Question which referenced by a QuestionId\r
+ could not be found.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
+ stack.\r
+ @retval EFI_ACCESS_DENIED The pop operation underflowed the stack.\r
+ @retval EFI_INVALID_PARAMETER Syntax error with the Expression.\r
+ @retval EFI_INVALID_PARAMETER Formset, Form or Expression is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EvaluateHiiExpression (\r
+ IN HII_FORMSET *FormSet,\r
+ IN HII_FORM *Form,\r
+ IN OUT HII_EXPRESSION *Expression\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ HII_EXPRESSION_OPCODE *OpCode;\r
+ HII_STATEMENT *Question;\r
+ HII_STATEMENT *Question2;\r
+ UINT16 Index;\r
+ EFI_HII_VALUE Data1;\r
+ EFI_HII_VALUE Data2;\r
+ EFI_HII_VALUE Data3;\r
+ HII_EXPRESSION *RuleExpression;\r
+ EFI_HII_VALUE *Value;\r
+ INTN Result;\r
+ CHAR16 *StrPtr;\r
+ CHAR16 *NameValue;\r
+ UINT32 TempValue;\r
+ LIST_ENTRY *SubExpressionLink;\r
+ HII_EXPRESSION *SubExpression;\r
+ UINTN StackOffset;\r
+ UINTN TempLength;\r
+ CHAR16 TempStr[5];\r
+ UINT8 DigitUint8;\r
+ UINT8 *TempBuffer;\r
+ EFI_TIME EfiTime;\r
+ EFI_HII_VALUE QuestionVal;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *PathFromText;\r
+\r
+ if ((FormSet == NULL) || (Form == NULL) || (Expression == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ StrPtr = NULL;\r
+ DevicePath = NULL;\r
+ PathFromText = NULL;\r
+\r
+ //\r
+ // Save current stack offset.\r
+ //\r
+ StackOffset = SaveExpressionEvaluationStackOffset ();\r
+\r
+ ASSERT (Expression != NULL);\r
+ Expression->Result.Type = EFI_IFR_TYPE_OTHER;\r
+\r
+ Link = GetFirstNode (&Expression->OpCodeListHead);\r
+ while (!IsNull (&Expression->OpCodeListHead, Link)) {\r
+ OpCode = HII_EXPRESSION_OPCODE_FROM_LINK (Link);\r
+\r
+ Link = GetNextNode (&Expression->OpCodeListHead, Link);\r
+\r
+ ZeroMem (&Data1, sizeof (EFI_HII_VALUE));\r
+ ZeroMem (&Data2, sizeof (EFI_HII_VALUE));\r
+ ZeroMem (&Data3, sizeof (EFI_HII_VALUE));\r
+\r
+ Value = &Data3;\r
+ Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
+ Status = EFI_SUCCESS;\r
+\r
+ switch (OpCode->Operand) {\r
+ //\r
+ // Built-in functions\r
+ //\r
+ case EFI_IFR_EQ_ID_VAL_OP:\r
+ Question = QuestionIdInFormset (FormSet, Form, OpCode->ExtraData.EqIdValData.QuestionId);\r
+ if (Question == NULL) {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Load value from storage.\r
+ //\r
+ Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);\r
+ if (EFI_ERROR (Status)) {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ break;\r
+ }\r
+\r
+ Status = HiiStatementValueToHiiValue (&Question->Value, &Data1);\r
+ if (EFI_ERROR (Status)) {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ break;\r
+ }\r
+\r
+ Status = CompareHiiValue (&Data1, &OpCode->ExtraData.EqIdValData.Value, &Result, NULL);\r
+ ReleaseHiiValue (&Data1);\r
+ if (Status == EFI_UNSUPPORTED) {\r
+ Status = EFI_SUCCESS;\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ break;\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ Value->Value.b = (BOOLEAN)((Result == 0) ? TRUE : FALSE);\r
+ break;\r
+\r
+ case EFI_IFR_EQ_ID_ID_OP:\r
+ Question = QuestionIdInFormset (FormSet, Form, OpCode->ExtraData.EqIdIdData.QuestionId1);\r
+ if (Question == NULL) {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Load value from storage.\r
+ //\r
+ Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);\r
+ if (EFI_ERROR (Status)) {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ break;\r
+ }\r
+\r
+ Status = HiiStatementValueToHiiValue (&Question->Value, &Data1);\r
+ if (EFI_ERROR (Status)) {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ break;\r
+ }\r
+\r
+ Question2 = QuestionIdInFormset (FormSet, Form, OpCode->ExtraData.EqIdIdData.QuestionId2);\r
+ if (Question2 == NULL) {\r
+ ReleaseHiiValue (&Data1);\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Load value from storage.\r
+ //\r
+ Status = GetQuestionValue (FormSet, Form, Question2, GetSetValueWithBuffer);\r
+ if (EFI_ERROR (Status)) {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ break;\r
+ }\r
+\r
+ Status = HiiStatementValueToHiiValue (&Question2->Value, &Data2);\r
+ if (EFI_ERROR (Status)) {\r
+ ReleaseHiiValue (&Data1);\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ break;\r
+ }\r
+\r
+ Status = CompareHiiValue (&Data1, &Data2, &Result, FormSet->HiiHandle);\r
+ ReleaseHiiValue (&Data1);\r
+ ReleaseHiiValue (&Data2);\r
+ if (Status == EFI_UNSUPPORTED) {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ Status = EFI_SUCCESS;\r
+ break;\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ Value->Value.b = (BOOLEAN)((Result == 0) ? TRUE : FALSE);\r
+ break;\r
+\r
+ case EFI_IFR_EQ_ID_VAL_LIST_OP:\r
+ Question = QuestionIdInFormset (FormSet, Form, OpCode->ExtraData.EqIdListData.QuestionId);\r
+ if (Question == NULL) {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Load value from storage.\r
+ //\r
+ Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);\r
+ if (EFI_ERROR (Status)) {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ break;\r
+ }\r
+\r
+ Value->Value.b = FALSE;\r
+ for (Index = 0; Index < OpCode->ExtraData.EqIdListData.ListLength; Index++) {\r
+ if (Question->Value.Value.u16 == OpCode->ExtraData.EqIdListData.ValueList[Index]) {\r
+ Value->Value.b = TRUE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_DUP_OP:\r
+ Status = PopExpression (Value);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ Status = PushExpression (Value);\r
+ break;\r
+\r
+ case EFI_IFR_QUESTION_REF1_OP:\r
+ case EFI_IFR_THIS_OP:\r
+ Question = QuestionIdInFormset (FormSet, Form, OpCode->ExtraData.QuestionRef1Data.QuestionId);\r
+ if (Question == NULL) {\r
+ Status = EFI_NOT_FOUND;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Load value from storage.\r
+ //\r
+ Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ Value = (EFI_HII_VALUE *)&Question->Value;\r
+ break;\r
+\r
+ case EFI_IFR_SECURITY_OP:\r
+ Value->Value.b = CheckUserPrivilege (&OpCode->ExtraData.Guid);\r
+ break;\r
+\r
+ case EFI_IFR_GET_OP:\r
+ //\r
+ // Get Value from VarStore buffer, EFI VarStore, Name/Value VarStore.\r
+ //\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ Value->Value.u8 = 0;\r
+ if (OpCode->ExtraData.GetSetData.VarStorage != NULL) {\r
+ switch (OpCode->ExtraData.GetSetData.VarStorage->Type) {\r
+ case EFI_HII_VARSTORE_BUFFER:\r
+ case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
+ //\r
+ // Get value from Edit Buffer\r
+ //\r
+ Value->Type = OpCode->ExtraData.GetSetData.ValueType;\r
+ CopyMem (&Value->Value, OpCode->ExtraData.GetSetData.VarStorage->EditBuffer + OpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset, OpCode->ExtraData.GetSetData.ValueWidth);\r
+ break;\r
+ case EFI_HII_VARSTORE_NAME_VALUE:\r
+ if (OpCode->ExtraData.GetSetData.ValueType != EFI_IFR_TYPE_STRING) {\r
+ //\r
+ // Get value from string except for STRING value.\r
+ //\r
+ Status = GetValueByName (OpCode->ExtraData.GetSetData.VarStorage, OpCode->ExtraData.GetSetData.ValueName, &StrPtr);\r
+ if (!EFI_ERROR (Status)) {\r
+ ASSERT (StrPtr != NULL);\r
+ TempLength = StrLen (StrPtr);\r
+ if (OpCode->ExtraData.GetSetData.ValueWidth >= ((TempLength + 1) / 2)) {\r
+ Value->Type = OpCode->ExtraData.GetSetData.ValueType;\r
+ TempBuffer = (UINT8 *)&Value->Value;\r
+ ZeroMem (TempStr, sizeof (TempStr));\r
+ for (Index = 0; Index < TempLength; Index++) {\r
+ TempStr[0] = StrPtr[TempLength - Index - 1];\r
+ DigitUint8 = (UINT8)StrHexToUint64 (TempStr);\r
+ if ((Index & 1) == 0) {\r
+ TempBuffer[Index/2] = DigitUint8;\r
+ } else {\r
+ TempBuffer[Index/2] = (UINT8)((DigitUint8 << 4) + TempBuffer[Index/2]);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ break;\r
+ case EFI_HII_VARSTORE_EFI_VARIABLE:\r
+ //\r
+ // Get value from variable.\r
+ //\r
+ TempLength = OpCode->ExtraData.GetSetData.ValueWidth;\r
+ Value->Type = OpCode->ExtraData.GetSetData.ValueType;\r
+ Status = gRT->GetVariable (\r
+ OpCode->ExtraData.GetSetData.ValueName,\r
+ &OpCode->ExtraData.GetSetData.VarStorage->Guid,\r
+ NULL,\r
+ &TempLength,\r
+ &Value->Value\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ Value->Value.u8 = 0;\r
+ }\r
+\r
+ break;\r
+ default:\r
+ //\r
+ // Not recognize storage.\r
+ //\r
+ Status = EFI_UNSUPPORTED;\r
+ goto Done;\r
+ }\r
+ } else {\r
+ //\r
+ // For Time/Date Data\r
+ //\r
+ if ((OpCode->ExtraData.GetSetData.ValueType != EFI_IFR_TYPE_DATE) && (OpCode->ExtraData.GetSetData.ValueType != EFI_IFR_TYPE_TIME)) {\r
+ //\r
+ // Only support Data/Time data when storage doesn't exist.\r
+ //\r
+ Status = EFI_UNSUPPORTED;\r
+ goto Done;\r
+ }\r
+\r
+ Status = gRT->GetTime (&EfiTime, NULL);\r
+ if (!EFI_ERROR (Status)) {\r
+ if (OpCode->ExtraData.GetSetData.ValueType == EFI_IFR_TYPE_DATE) {\r
+ switch (OpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset) {\r
+ case 0x00:\r
+ Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;\r
+ Value->Value.u16 = EfiTime.Year;\r
+ break;\r
+ case 0x02:\r
+ Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
+ Value->Value.u8 = EfiTime.Month;\r
+ break;\r
+ case 0x03:\r
+ Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
+ Value->Value.u8 = EfiTime.Day;\r
+ break;\r
+ default:\r
+ //\r
+ // Invalid Date field.\r
+ //\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+ } else {\r
+ switch (OpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset) {\r
+ case 0x00:\r
+ Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
+ Value->Value.u8 = EfiTime.Hour;\r
+ break;\r
+ case 0x01:\r
+ Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
+ Value->Value.u8 = EfiTime.Minute;\r
+ break;\r
+ case 0x02:\r
+ Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
+ Value->Value.u8 = EfiTime.Second;\r
+ break;\r
+ default:\r
+ //\r
+ // Invalid Time field.\r
+ //\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_QUESTION_REF3_OP:\r
+ //\r
+ // EFI_IFR_QUESTION_REF3\r
+ // Pop an expression from the expression stack\r
+ //\r
+ Status = PopExpression (Value);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Validate the expression value\r
+ //\r
+ if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ break;\r
+ }\r
+\r
+ if (OpCode->ExtraData.QuestionRef3Data.DevicePath != 0) {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiDevicePathFromTextProtocolGuid,\r
+ NULL,\r
+ (VOID **)&PathFromText\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ StrPtr = GetTokenString (OpCode->ExtraData.QuestionRef3Data.DevicePath, FormSet->HiiHandle);\r
+ if ((StrPtr != NULL) && (PathFromText != NULL)) {\r
+ DevicePath = PathFromText->ConvertTextToDevicePath (StrPtr);\r
+ if ((DevicePath != NULL) && GetQuestionValueFromForm (DevicePath, NULL, &OpCode->ExtraData.Guid, Value->Value.u16, &QuestionVal)) {\r
+ Value = &QuestionVal;\r
+ }\r
+\r
+ if (DevicePath != NULL) {\r
+ FreePool (DevicePath);\r
+ }\r
+ }\r
+\r
+ if (StrPtr != NULL) {\r
+ FreePool (StrPtr);\r
+ }\r
+ } else if (IsZeroGuid (&OpCode->ExtraData.Guid)) {\r
+ if (!GetQuestionValueFromForm (NULL, FormSet->HiiHandle, &OpCode->ExtraData.Guid, Value->Value.u16, &QuestionVal)) {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ break;\r
+ }\r
+\r
+ Value = &QuestionVal;\r
+ } else {\r
+ Question = QuestionIdInFormset (FormSet, Form, Value->Value.u16);\r
+ if (Question == NULL) {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Load value from storage.\r
+ //\r
+ Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);\r
+ if (EFI_ERROR (Status)) {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // push the questions' value on to the expression stack\r
+ //\r
+ Value = (EFI_HII_VALUE *)&Question->Value;\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_RULE_REF_OP:\r
+ //\r
+ // Find expression for this rule\r
+ //\r
+ RuleExpression = RuleIdToExpression (Form, OpCode->ExtraData.RuleId);\r
+ if (RuleExpression == NULL) {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Evaluate this rule expression\r
+ //\r
+ Status = EvaluateHiiExpression (FormSet, Form, RuleExpression);\r
+ if (EFI_ERROR (Status) || (RuleExpression->Result.Type == EFI_IFR_TYPE_UNDEFINED)) {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ break;\r
+ }\r
+\r
+ Value = &RuleExpression->Result;\r
+ break;\r
+\r
+ case EFI_IFR_STRING_REF1_OP:\r
+ Value->Type = EFI_IFR_TYPE_STRING;\r
+ Value->Value.string = OpCode->ExtraData.Value.Value.string;\r
+ break;\r
+\r
+ //\r
+ // Constant\r
+ //\r
+ case EFI_IFR_TRUE_OP:\r
+ case EFI_IFR_FALSE_OP:\r
+ case EFI_IFR_ONE_OP:\r
+ case EFI_IFR_ONES_OP:\r
+ case EFI_IFR_UINT8_OP:\r
+ case EFI_IFR_UINT16_OP:\r
+ case EFI_IFR_UINT32_OP:\r
+ case EFI_IFR_UINT64_OP:\r
+ case EFI_IFR_UNDEFINED_OP:\r
+ case EFI_IFR_VERSION_OP:\r
+ case EFI_IFR_ZERO_OP:\r
+ Value = &OpCode->ExtraData.Value;\r
+ break;\r
+\r
+ //\r
+ // unary-op\r
+ //\r
+ case EFI_IFR_LENGTH_OP:\r
+ Status = PopExpression (Value);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ if ((Value->Type != EFI_IFR_TYPE_STRING) && !IsTypeInBuffer (Value)) {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ break;\r
+ }\r
+\r
+ if (Value->Type == EFI_IFR_TYPE_STRING) {\r
+ StrPtr = GetTokenString (Value->Value.string, FormSet->HiiHandle);\r
+ if (StrPtr == NULL) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+\r
+ Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+ Value->Value.u64 = StrLen (StrPtr);\r
+ FreePool (StrPtr);\r
+ } else {\r
+ Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+ Value->Value.u64 = GetLengthForValue (Value);\r
+ FreePool (Value->Buffer);\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_NOT_OP:\r
+ Status = PopExpression (Value);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ break;\r
+ }\r
+\r
+ Value->Value.b = (BOOLEAN)(!Value->Value.b);\r
+ break;\r
+\r
+ case EFI_IFR_QUESTION_REF2_OP:\r
+ //\r
+ // Pop an expression from the expression stack\r
+ //\r
+ Status = PopExpression (Value);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Validate the expression value\r
+ //\r
+ if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ break;\r
+ }\r
+\r
+ Question = QuestionIdInFormset (FormSet, Form, Value->Value.u16);\r
+ if (Question == NULL) {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Load value from storage.\r
+ //\r
+ Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);\r
+ if (EFI_ERROR (Status)) {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ break;\r
+ }\r
+\r
+ Value = (EFI_HII_VALUE *)&Question->Value;\r
+ break;\r
+\r
+ case EFI_IFR_STRING_REF2_OP:\r
+ //\r
+ // Pop an expression from the expression stack\r
+ //\r
+ Status = PopExpression (Value);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Validate the expression value\r
+ //\r
+ if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ break;\r
+ }\r
+\r
+ Value->Type = EFI_IFR_TYPE_STRING;\r
+ StrPtr = GetTokenString (Value->Value.u16, FormSet->HiiHandle);\r
+ if (StrPtr == NULL) {\r
+ //\r
+ // If String not exit, push an empty string\r
+ //\r
+ Value->Value.string = NewHiiString (gEmptyString, FormSet->HiiHandle);\r
+ } else {\r
+ Index = (UINT16)Value->Value.u64;\r
+ Value->Value.string = Index;\r
+ FreePool (StrPtr);\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_TO_BOOLEAN_OP:\r
+ //\r
+ // Pop an expression from the expression stack\r
+ //\r
+ Status = PopExpression (Value);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Convert an expression to a Boolean\r
+ //\r
+ if (Value->Type <= EFI_IFR_TYPE_DATE) {\r
+ //\r
+ // When converting from an unsigned integer, zero will be converted to\r
+ // FALSE and any other value will be converted to TRUE.\r
+ //\r
+ Value->Value.b = (BOOLEAN)(HiiValueToUINT64 (Value) != 0);\r
+\r
+ Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
+ } else if (Value->Type == EFI_IFR_TYPE_STRING) {\r
+ //\r
+ // When converting from a string, if case-insensitive compare\r
+ // with "true" is True, then push True. If a case-insensitive compare\r
+ // with "false" is True, then push False. Otherwise, push Undefined.\r
+ //\r
+ StrPtr = GetTokenString (Value->Value.string, FormSet->HiiHandle);\r
+ if (StrPtr == NULL) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+\r
+ IfrStrToUpper (StrPtr);\r
+ if (StrCmp (StrPtr, L"TRUE") == 0) {\r
+ Value->Value.b = TRUE;\r
+ Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
+ } else if (StrCmp (StrPtr, L"FALSE") == 0) {\r
+ Value->Value.b = FALSE;\r
+ Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
+ } else {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ }\r
+\r
+ FreePool (StrPtr);\r
+ } else if (Value->Type == EFI_IFR_TYPE_BUFFER) {\r
+ //\r
+ // When converting from a buffer, if the buffer is all zeroes,\r
+ // then push False. Otherwise push True.\r
+ //\r
+ for (Index = 0; Index < Value->BufferLen; Index++) {\r
+ if (Value->Buffer[Index] != 0) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (Index >= Value->BufferLen) {\r
+ Value->Value.b = FALSE;\r
+ } else {\r
+ Value->Value.b = TRUE;\r
+ }\r
+\r
+ Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
+ FreePool (Value->Buffer);\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_TO_STRING_OP:\r
+ Status = IfrToString (FormSet, OpCode->ExtraData.Format, Value);\r
+ break;\r
+\r
+ case EFI_IFR_TO_UINT_OP:\r
+ Status = IfrToUint (FormSet, Value);\r
+ break;\r
+\r
+ case EFI_IFR_TO_LOWER_OP:\r
+ case EFI_IFR_TO_UPPER_OP:\r
+ Status = InitializeUnicodeCollationProtocol ();\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ Status = PopExpression (Value);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ if (Value->Type != EFI_IFR_TYPE_STRING) {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ break;\r
+ }\r
+\r
+ StrPtr = GetTokenString (Value->Value.string, FormSet->HiiHandle);\r
+ if (StrPtr == NULL) {\r
+ Status = EFI_NOT_FOUND;\r
+ goto Done;\r
+ }\r
+\r
+ if (OpCode->Operand == EFI_IFR_TO_LOWER_OP) {\r
+ mUnicodeCollation->StrLwr (mUnicodeCollation, StrPtr);\r
+ } else {\r
+ mUnicodeCollation->StrUpr (mUnicodeCollation, StrPtr);\r
+ }\r
+\r
+ Value->Value.string = NewHiiString (StrPtr, FormSet->HiiHandle);\r
+ FreePool (StrPtr);\r
+ break;\r
+\r
+ case EFI_IFR_BITWISE_NOT_OP:\r
+ //\r
+ // Pop an expression from the expression stack\r
+ //\r
+ Status = PopExpression (Value);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ if (Value->Type > EFI_IFR_TYPE_DATE) {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ break;\r
+ }\r
+\r
+ Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+ Value->Value.u64 = ~HiiValueToUINT64(Value);\r
+ break;\r
+\r
+ case EFI_IFR_SET_OP:\r
+ //\r
+ // Pop an expression from the expression stack\r
+ //\r
+ Status = PopExpression (Value);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ Data1.Type = EFI_IFR_TYPE_BOOLEAN;\r
+ Data1.Value.b = FALSE;\r
+ //\r
+ // Set value to var storage buffer\r
+ //\r
+ if (OpCode->ExtraData.GetSetData.VarStorage != NULL) {\r
+ switch (OpCode->ExtraData.GetSetData.VarStorage->Type) {\r
+ case EFI_HII_VARSTORE_BUFFER:\r
+ case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
+ CopyMem (OpCode->ExtraData.GetSetData.VarStorage->EditBuffer + OpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset, &Value->Value, OpCode->ExtraData.GetSetData.ValueWidth);\r
+ Data1.Value.b = TRUE;\r
+ break;\r
+ case EFI_HII_VARSTORE_NAME_VALUE:\r
+ if (OpCode->ExtraData.GetSetData.ValueType != EFI_IFR_TYPE_STRING) {\r
+ NameValue = AllocatePool ((OpCode->ExtraData.GetSetData.ValueWidth * 2 + 1) * sizeof (CHAR16));\r
+ ASSERT (NameValue != NULL);\r
+ //\r
+ // Convert Buffer to Hex String\r
+ //\r
+ TempBuffer = (UINT8 *)&Value->Value + OpCode->ExtraData.GetSetData.ValueWidth - 1;\r
+ StrPtr = NameValue;\r
+ for (Index = 0; Index < OpCode->ExtraData.GetSetData.ValueWidth; Index++, TempBuffer--) {\r
+ UnicodeValueToStringS (\r
+ StrPtr,\r
+ (OpCode->ExtraData.GetSetData.ValueWidth * 2 + 1) * sizeof (CHAR16) - ((UINTN)StrPtr - (UINTN)NameValue),\r
+ PREFIX_ZERO | RADIX_HEX,\r
+ *TempBuffer,\r
+ 2\r
+ );\r
+ StrPtr += StrnLenS (StrPtr, OpCode->ExtraData.GetSetData.ValueWidth * 2 + 1 - ((UINTN)StrPtr - (UINTN)NameValue) / sizeof (CHAR16));\r
+ }\r
+\r
+ Status = SetValueByName (OpCode->ExtraData.GetSetData.VarStorage, OpCode->ExtraData.GetSetData.ValueName, NameValue, NULL);\r
+ FreePool (NameValue);\r
+ if (!EFI_ERROR (Status)) {\r
+ Data1.Value.b = TRUE;\r
+ }\r
+ }\r
+\r
+ break;\r
+ case EFI_HII_VARSTORE_EFI_VARIABLE:\r
+ Status = gRT->SetVariable (\r
+ OpCode->ExtraData.GetSetData.ValueName,\r
+ &OpCode->ExtraData.GetSetData.VarStorage->Guid,\r
+ OpCode->ExtraData.GetSetData.VarStorage->Attributes,\r
+ OpCode->ExtraData.GetSetData.ValueWidth,\r
+ &Value->Value\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Data1.Value.b = TRUE;\r
+ }\r
+\r
+ break;\r
+ default:\r
+ //\r
+ // Not recognize storage.\r
+ //\r
+ Status = EFI_UNSUPPORTED;\r
+ goto Done;\r
+ }\r
+ } else {\r
+ //\r
+ // For Time/Date Data\r
+ //\r
+ if ((OpCode->ExtraData.GetSetData.ValueType != EFI_IFR_TYPE_DATE) && (OpCode->ExtraData.GetSetData.ValueType != EFI_IFR_TYPE_TIME)) {\r
+ //\r
+ // Only support Data/Time data when storage doesn't exist.\r
+ //\r
+ Status = EFI_UNSUPPORTED;\r
+ goto Done;\r
+ }\r
+\r
+ Status = gRT->GetTime (&EfiTime, NULL);\r
+ if (!EFI_ERROR (Status)) {\r
+ if (OpCode->ExtraData.GetSetData.ValueType == EFI_IFR_TYPE_DATE) {\r
+ switch (OpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset) {\r
+ case 0x00:\r
+ EfiTime.Year = Value->Value.u16;\r
+ break;\r
+ case 0x02:\r
+ EfiTime.Month = Value->Value.u8;\r
+ break;\r
+ case 0x03:\r
+ EfiTime.Day = Value->Value.u8;\r
+ break;\r
+ default:\r
+ //\r
+ // Invalid Date field.\r
+ //\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+ } else {\r
+ switch (OpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset) {\r
+ case 0x00:\r
+ EfiTime.Hour = Value->Value.u8;\r
+ break;\r
+ case 0x01:\r
+ EfiTime.Minute = Value->Value.u8;\r
+ break;\r
+ case 0x02:\r
+ EfiTime.Second = Value->Value.u8;\r
+ break;\r
+ default:\r
+ //\r
+ // Invalid Time field.\r
+ //\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ Status = gRT->SetTime (&EfiTime);\r
+ if (!EFI_ERROR (Status)) {\r
+ Data1.Value.b = TRUE;\r
+ }\r
+ }\r
+ }\r
+\r
+ Value = &Data1;\r
+ break;\r
+\r
+ //\r
+ // binary-op\r
+ //\r
+ case EFI_IFR_ADD_OP:\r
+ case EFI_IFR_SUBTRACT_OP:\r
+ case EFI_IFR_MULTIPLY_OP:\r
+ case EFI_IFR_DIVIDE_OP:\r
+ case EFI_IFR_MODULO_OP:\r
+ case EFI_IFR_BITWISE_AND_OP:\r
+ case EFI_IFR_BITWISE_OR_OP:\r
+ case EFI_IFR_SHIFT_LEFT_OP:\r
+ case EFI_IFR_SHIFT_RIGHT_OP:\r
+ //\r
+ // Pop an expression from the expression stack\r
+ //\r
+ Status = PopExpression (&Data2);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Pop another expression from the expression stack\r
+ //\r
+ Status = PopExpression (&Data1);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ if (Data2.Type > EFI_IFR_TYPE_DATE) {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ break;\r
+ }\r
+\r
+ if (Data1.Type > EFI_IFR_TYPE_DATE) {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ break;\r
+ }\r
+\r
+ Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+\r
+ switch (OpCode->Operand) {\r
+ case EFI_IFR_ADD_OP:\r
+ Value->Value.u64 = HiiValueToUINT64 (&Data1) + HiiValueToUINT64 (&Data2);\r
+ break;\r
+\r
+ case EFI_IFR_SUBTRACT_OP:\r
+ Value->Value.u64 = HiiValueToUINT64 (&Data1) - HiiValueToUINT64 (&Data2);\r
+ break;\r
+\r
+ case EFI_IFR_MULTIPLY_OP:\r
+ Value->Value.u64 = MultU64x32 (HiiValueToUINT64 (&Data1), (UINT32)HiiValueToUINT64 (&Data2));\r
+ break;\r
+\r
+ case EFI_IFR_DIVIDE_OP:\r
+ Value->Value.u64 = DivU64x32 (HiiValueToUINT64 (&Data1), (UINT32)HiiValueToUINT64 (&Data2));\r
+ break;\r
+\r
+ case EFI_IFR_MODULO_OP:\r
+ DivU64x32Remainder (HiiValueToUINT64 (&Data1), (UINT32)HiiValueToUINT64 (&Data2), &TempValue);\r
+ Value->Value.u64 = TempValue;\r
+ break;\r
+\r
+ case EFI_IFR_BITWISE_AND_OP:\r
+ Value->Value.u64 = HiiValueToUINT64 (&Data1) & HiiValueToUINT64 (&Data2);\r
+ break;\r
+\r
+ case EFI_IFR_BITWISE_OR_OP:\r
+ Value->Value.u64 = HiiValueToUINT64 (&Data1) | HiiValueToUINT64 (&Data2);\r
+ break;\r
+\r
+ case EFI_IFR_SHIFT_LEFT_OP:\r
+ Value->Value.u64 = LShiftU64 (HiiValueToUINT64 (&Data1), (UINTN)HiiValueToUINT64 (&Data2));\r
+ break;\r
+\r
+ case EFI_IFR_SHIFT_RIGHT_OP:\r
+ Value->Value.u64 = RShiftU64 (HiiValueToUINT64 (&Data1), (UINTN)HiiValueToUINT64 (&Data2));\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_AND_OP:\r
+ case EFI_IFR_OR_OP:\r
+ //\r
+ // Two Boolean operator\r
+ //\r
+ Status = PopExpression (&Data2);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Pop another expression from the expression stack\r
+ //\r
+ Status = PopExpression (&Data1);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ break;\r
+ }\r
+\r
+ if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ break;\r
+ }\r
+\r
+ if (OpCode->Operand == EFI_IFR_AND_OP) {\r
+ Value->Value.b = (BOOLEAN)(Data1.Value.b && Data2.Value.b);\r
+ } else {\r
+ Value->Value.b = (BOOLEAN)(Data1.Value.b || Data2.Value.b);\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_EQUAL_OP:\r
+ case EFI_IFR_NOT_EQUAL_OP:\r
+ case EFI_IFR_GREATER_EQUAL_OP:\r
+ case EFI_IFR_GREATER_THAN_OP:\r
+ case EFI_IFR_LESS_EQUAL_OP:\r
+ case EFI_IFR_LESS_THAN_OP:\r
+ //\r
+ // Compare two integer, string, boolean or date/time\r
+ //\r
+ Status = PopExpression (&Data2);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Pop another expression from the expression stack\r
+ //\r
+ Status = PopExpression (&Data1);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ if ((Data2.Type > EFI_IFR_TYPE_BOOLEAN) &&\r
+ (Data2.Type != EFI_IFR_TYPE_STRING) &&\r
+ !IsTypeInBuffer (&Data2))\r
+ {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ break;\r
+ }\r
+\r
+ if ((Data1.Type > EFI_IFR_TYPE_BOOLEAN) &&\r
+ (Data1.Type != EFI_IFR_TYPE_STRING) &&\r
+ !IsTypeInBuffer (&Data1))\r
+ {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ break;\r
+ }\r
+\r
+ Status = CompareHiiValue (&Data1, &Data2, &Result, FormSet->HiiHandle);\r
+ if (Data1.Type == EFI_IFR_TYPE_BUFFER) {\r
+ FreePool (Data1.Buffer);\r
+ }\r
+\r
+ if (Data2.Type == EFI_IFR_TYPE_BUFFER) {\r
+ FreePool (Data2.Buffer);\r
+ }\r
+\r
+ if (Status == EFI_UNSUPPORTED) {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ Status = EFI_SUCCESS;\r
+ break;\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ switch (OpCode->Operand) {\r
+ case EFI_IFR_EQUAL_OP:\r
+ Value->Value.b = (BOOLEAN)((Result == 0) ? TRUE : FALSE);\r
+ break;\r
+\r
+ case EFI_IFR_NOT_EQUAL_OP:\r
+ Value->Value.b = (BOOLEAN)((Result != 0) ? TRUE : FALSE);\r
+ break;\r
+\r
+ case EFI_IFR_GREATER_EQUAL_OP:\r
+ Value->Value.b = (BOOLEAN)((Result >= 0) ? TRUE : FALSE);\r
+ break;\r
+\r
+ case EFI_IFR_GREATER_THAN_OP:\r
+ Value->Value.b = (BOOLEAN)((Result > 0) ? TRUE : FALSE);\r
+ break;\r
+\r
+ case EFI_IFR_LESS_EQUAL_OP:\r
+ Value->Value.b = (BOOLEAN)((Result <= 0) ? TRUE : FALSE);\r
+ break;\r
+\r
+ case EFI_IFR_LESS_THAN_OP:\r
+ Value->Value.b = (BOOLEAN)((Result < 0) ? TRUE : FALSE);\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_MATCH_OP:\r
+ Status = InitializeUnicodeCollationProtocol ();\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ Status = IfrMatch (FormSet, Value);\r
+ break;\r
+\r
+ case EFI_IFR_MATCH2_OP:\r
+ Status = IfrMatch2 (FormSet, &OpCode->ExtraData.Guid, Value);\r
+ break;\r
+\r
+ case EFI_IFR_CATENATE_OP:\r
+ Status = IfrCatenate (FormSet, Value);\r
+ break;\r
+\r
+ //\r
+ // ternary-op\r
+ //\r
+ case EFI_IFR_CONDITIONAL_OP:\r
+ //\r
+ // Pop third expression from the expression stack\r
+ //\r
+ Status = PopExpression (&Data3);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Pop second expression from the expression stack\r
+ //\r
+ Status = PopExpression (&Data2);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Pop first expression from the expression stack\r
+ //\r
+ Status = PopExpression (&Data1);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ break;\r
+ }\r
+\r
+ if (Data1.Value.b) {\r
+ Value = &Data3;\r
+ } else {\r
+ Value = &Data2;\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_FIND_OP:\r
+ Status = IfrFind (FormSet, OpCode->ExtraData.Format, Value);\r
+ break;\r
+\r
+ case EFI_IFR_MID_OP:\r
+ Status = IfrMid (FormSet, Value);\r
+ break;\r
+\r
+ case EFI_IFR_TOKEN_OP:\r
+ Status = IfrToken (FormSet, Value);\r
+ break;\r
+\r
+ case EFI_IFR_SPAN_OP:\r
+ Status = IfrSpan (FormSet, OpCode->ExtraData.Flags, Value);\r
+ break;\r
+\r
+ case EFI_IFR_MAP_OP:\r
+ //\r
+ // Pop the check value\r
+ //\r
+ Status = PopExpression (&Data1);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Check MapExpression list is valid.\r
+ //\r
+ if (OpCode->MapExpressionList.ForwardLink == NULL) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Go through map expression list.\r
+ //\r
+ SubExpressionLink = GetFirstNode (&OpCode->MapExpressionList);\r
+ while (!IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
+ SubExpression = HII_EXPRESSION_FROM_LINK (SubExpressionLink);\r
+ //\r
+ // Evaluate the first expression in this pair.\r
+ //\r
+ Status = EvaluateHiiExpression (FormSet, Form, SubExpression);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Compare the expression value with current value\r
+ //\r
+ if ((CompareHiiValue (&Data1, &SubExpression->Result, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {\r
+ //\r
+ // Try get the map value.\r
+ //\r
+ SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
+ if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+\r
+ SubExpression = HII_EXPRESSION_FROM_LINK (SubExpressionLink);\r
+ Status = EvaluateHiiExpression (FormSet, Form, SubExpression);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ Value = &SubExpression->Result;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Skip the second expression on this pair.\r
+ //\r
+ SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
+ if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Goto the first expression on next pair.\r
+ //\r
+ SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
+ }\r
+\r
+ //\r
+ // No map value is found.\r
+ //\r
+ if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
+ Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+ Value->Value.u8 = 0;\r
+ }\r
+\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ if (EFI_ERROR (Status) || (Value->Type == EFI_IFR_TYPE_UNDEFINED)) {\r
+ goto Done;\r
+ }\r
+\r
+ Status = PushExpression (Value);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Pop the final result from expression stack\r
+ //\r
+ Value = &Data1;\r
+ Status = PopExpression (Value);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // After evaluating an expression, there should be only one value left on the expression stack\r
+ //\r
+ if (PopExpression (Value) != EFI_ACCESS_DENIED) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+Done:\r
+ RestoreExpressionEvaluationStackOffset (StackOffset);\r
+ if (!EFI_ERROR (Status)) {\r
+ CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Set value of a data element in an Array by its Index.\r
+\r
+ @param[in] Array The data array.\r
+ @param[in] Type Type of the data in this array.\r
+ @param[in] Index Zero based index for data in this array.\r
+ @param[in] Value The value to be set.\r
+\r
+**/\r
+VOID\r
+SetArrayData (\r
+ IN VOID *Array,\r
+ IN UINT8 Type,\r
+ IN UINTN Index,\r
+ IN UINT64 Value\r
+ )\r
+{\r
+ ASSERT (Array != NULL);\r
+\r
+ switch (Type) {\r
+ case EFI_IFR_TYPE_NUM_SIZE_8:\r
+ *(((UINT8 *)Array) + Index) = (UINT8)Value;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_16:\r
+ *(((UINT16 *)Array) + Index) = (UINT16)Value;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_32:\r
+ *(((UINT32 *)Array) + Index) = (UINT32)Value;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_64:\r
+ *(((UINT64 *)Array) + Index) = (UINT64)Value;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+ Search an Option of a Question by its value.\r
+\r
+ @param[in] Question The Question\r
+ @param[in] OptionValue Value for Option to be searched.\r
+\r
+ @retval Pointer Pointer to the found Option.\r
+ @retval NULL Option not found.\r
+\r
+**/\r
+HII_QUESTION_OPTION *\r
+ValueToOption (\r
+ IN HII_STATEMENT *Question,\r
+ IN HII_STATEMENT_VALUE *OptionValue\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ HII_QUESTION_OPTION *Option;\r
+ EFI_HII_VALUE Data1;\r
+ EFI_HII_VALUE Data2;\r
+ INTN Result;\r
+ EFI_STATUS Status;\r
+\r
+ Result = 0;\r
+ ZeroMem (&Data1, sizeof (EFI_HII_VALUE));\r
+ ZeroMem (&Data2, sizeof (EFI_HII_VALUE));\r
+\r
+ Status = HiiStatementValueToHiiValue (OptionValue, &Data1);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Link = GetFirstNode (&Question->OptionListHead);\r
+ while (!IsNull (&Question->OptionListHead, Link)) {\r
+ Option = HII_QUESTION_OPTION_FROM_LINK (Link);\r
+\r
+ Status = HiiStatementValueToHiiValue (&Option->Value, &Data2);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ if ((CompareHiiValue (&Data1, &Data2, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {\r
+ //\r
+ // Check the suppressif condition, only a valid option can be return.\r
+ //\r
+ if ((Option->SuppressExpression == NULL) ||\r
+ ((EvaluateExpressionList (Option->SuppressExpression, FALSE, NULL, NULL) == ExpressFalse)))\r
+ {\r
+ return Option;\r
+ }\r
+ }\r
+\r
+ Link = GetNextNode (&Question->OptionListHead, Link);\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+/**\r
+ Find the point in the ConfigResp string for this question.\r
+\r
+ @param[in] Question The question.\r
+ @param[in] ConfigResp Get ConfigResp string.\r
+\r
+ @retval point to the offset where is for this question.\r
+\r
+**/\r
+CHAR16 *\r
+GetOffsetFromConfigResp (\r
+ IN HII_STATEMENT *Question,\r
+ IN CHAR16 *ConfigResp\r
+ )\r
+{\r
+ CHAR16 *RequestElement;\r
+ CHAR16 *BlockData;\r
+\r
+ //\r
+ // Type is EFI_HII_VARSTORE_NAME_VALUE.\r
+ //\r
+ if (Question->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+ RequestElement = StrStr (ConfigResp, Question->VariableName);\r
+ if (RequestElement != NULL) {\r
+ //\r
+ // Skip the "VariableName=" field.\r
+ //\r
+ RequestElement += StrLen (Question->VariableName) + 1;\r
+ }\r
+\r
+ return RequestElement;\r
+ }\r
+\r
+ //\r
+ // Type is EFI_HII_VARSTORE_EFI_VARIABLE or EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER\r
+ //\r
+\r
+ //\r
+ // Convert all hex digits in ConfigResp to lower case before searching.\r
+ //\r
+ HiiStringToLowercase (ConfigResp);\r
+\r
+ //\r
+ // 1. Directly use Question->BlockName to find.\r
+ //\r
+ RequestElement = StrStr (ConfigResp, Question->BlockName);\r
+ if (RequestElement != NULL) {\r
+ //\r
+ // Skip the "Question->BlockName&VALUE=" field.\r
+ //\r
+ RequestElement += StrLen (Question->BlockName) + StrLen (L"&VALUE=");\r
+ return RequestElement;\r
+ }\r
+\r
+ //\r
+ // 2. Change all hex digits in Question->BlockName to lower and compare again.\r
+ //\r
+ BlockData = AllocateCopyPool (StrSize (Question->BlockName), Question->BlockName);\r
+ ASSERT (BlockData != NULL);\r
+ HiiStringToLowercase (BlockData);\r
+ RequestElement = StrStr (ConfigResp, BlockData);\r
+ FreePool (BlockData);\r
+\r
+ if (RequestElement != NULL) {\r
+ //\r
+ // Skip the "Question->BlockName&VALUE=" field.\r
+ //\r
+ RequestElement += StrLen (Question->BlockName) + StrLen (L"&VALUE=");\r
+ }\r
+\r
+ return RequestElement;\r
+}\r
+\r
+/**\r
+ Get Question default value from AltCfg string.\r
+\r
+ @param[in] FormSet The form set.\r
+ @param[in] Form The form\r
+ @param[in] Question The question.\r
+ @param[out] DefaultValue Default value.\r
+\r
+ @retval EFI_SUCCESS Question is reset to default value.\r
+\r
+**/\r
+EFI_STATUS\r
+GetDefaultValueFromAltCfg (\r
+ IN HII_FORMSET *FormSet,\r
+ IN HII_FORM *Form,\r
+ IN HII_STATEMENT *Question,\r
+ OUT HII_STATEMENT_VALUE *DefaultValue\r
+ )\r
+{\r
+ HII_FORMSET_STORAGE *Storage;\r
+ CHAR16 *ConfigResp;\r
+ CHAR16 *Value;\r
+ LIST_ENTRY *Link;\r
+ HII_FORM_CONFIG_REQUEST *ConfigInfo;\r
+\r
+ Storage = Question->Storage;\r
+ if ((Storage == NULL) || (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Try to get AltCfg string from form. If not found it, then\r
+ // try to get it from formset.\r
+ //\r
+ ConfigResp = NULL;\r
+ Link = GetFirstNode (&Form->ConfigRequestHead);\r
+ while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
+ ConfigInfo = HII_FORM_CONFIG_REQUEST_FROM_LINK (Link);\r
+ Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
+\r
+ if (Storage == ConfigInfo->Storage) {\r
+ ConfigResp = ConfigInfo->ConfigAltResp;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (ConfigResp == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Value = GetOffsetFromConfigResp (Question, ConfigResp);\r
+ if (Value == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ return BufferToQuestionValue (Question, Value, DefaultValue);\r
+}\r
+\r
+/**\r
+ Get default Id value used for browser.\r
+\r
+ @param[in] DefaultId The default id value used by hii.\r
+\r
+ @retval Browser used default value.\r
+\r
+**/\r
+INTN\r
+GetDefaultIdForCallBack (\r
+ IN UINTN DefaultId\r
+ )\r
+{\r
+ if (DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) {\r
+ return EFI_BROWSER_ACTION_DEFAULT_STANDARD;\r
+ } else if (DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
+ return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING;\r
+ } else if (DefaultId == EFI_HII_DEFAULT_CLASS_SAFE) {\r
+ return EFI_BROWSER_ACTION_DEFAULT_SAFE;\r
+ } else if ((DefaultId >= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN) && (DefaultId < EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN + 0x1000)) {\r
+ return EFI_BROWSER_ACTION_DEFAULT_PLATFORM + DefaultId - EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN;\r
+ } else if ((DefaultId >= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN) && (DefaultId < EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN + 0x1000)) {\r
+ return EFI_BROWSER_ACTION_DEFAULT_HARDWARE + DefaultId - EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN;\r
+ } else if ((DefaultId >= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN) && (DefaultId < EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN + 0x1000)) {\r
+ return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE + DefaultId - EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN;\r
+ } else {\r
+ return -1;\r
+ }\r
+}\r
+\r
+/**\r
+ Get default value of question.\r
+\r
+ @param[in] FormSet The form set.\r
+ @param[in] Form The form.\r
+ @param[in] Question The question.\r
+ @param[in] DefaultId The Class of the default.\r
+ @param[out] DefaultValue The default value of given question.\r
+\r
+ @retval EFI_SUCCESS Question is reset to default value.\r
+\r
+**/\r
+EFI_STATUS\r
+GetQuestionDefault (\r
+ IN HII_FORMSET *FormSet,\r
+ IN HII_FORM *Form,\r
+ IN HII_STATEMENT *Question,\r
+ IN UINT16 DefaultId,\r
+ OUT HII_STATEMENT_VALUE *DefaultValue\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ HII_QUESTION_DEFAULT *Default;\r
+ HII_QUESTION_OPTION *Option;\r
+ HII_STATEMENT_VALUE *HiiValue;\r
+ UINT8 Index;\r
+ EFI_STRING StrValue;\r
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
+ INTN Action;\r
+ EFI_IFR_TYPE_VALUE *TypeValue;\r
+ UINT16 OriginalDefaultId;\r
+ HII_FORMSET_DEFAULTSTORE *DefaultStore;\r
+ LIST_ENTRY *DefaultLink;\r
+\r
+ if ((FormSet == NULL) || (Form == NULL) || (Question == NULL) || (DefaultValue == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = EFI_NOT_FOUND;\r
+ StrValue = NULL;\r
+ OriginalDefaultId = DefaultId;\r
+ DefaultLink = GetFirstNode (&FormSet->DefaultStoreListHead);\r
+\r
+ //\r
+ // Statement don't have storage, skip them\r
+ //\r
+ if (Question->QuestionId == 0) {\r
+ DEBUG ((DEBUG_ERROR, "%a: Question has no storage, skip it\n", __func__));\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // There are Five ways to specify default value for a Question:\r
+ // 1, use call back function (highest priority)\r
+ // 2, use ExtractConfig function\r
+ // 3, use nested EFI_IFR_DEFAULT\r
+ // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)\r
+ // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)\r
+ //\r
+ CopyMem (DefaultValue, &Question->Value, sizeof (HII_STATEMENT_VALUE));\r
+ReGetDefault:\r
+ HiiValue = DefaultValue;\r
+ TypeValue = &HiiValue->Value;\r
+ if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
+ //\r
+ // For orderedlist, need to pass the BufferValue to Callback function.\r
+ //\r
+ DefaultValue->BufferLen = Question->Value.BufferLen;\r
+ DefaultValue->Buffer = AllocateZeroPool (DefaultValue->BufferLen);\r
+ ASSERT (DefaultValue->Buffer != NULL);\r
+ if (DefaultValue->Buffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ TypeValue = (EFI_IFR_TYPE_VALUE *)DefaultValue->Buffer;\r
+ }\r
+\r
+ //\r
+ // Get Question default value from call back function.\r
+ // The string type of question cause HII driver to set string to its default value.\r
+ // So, we don't do this otherwise it will actually set question to default value.\r
+ // We only want to get default value of question.\r
+ //\r
+ if (HiiValue->Type != EFI_IFR_TYPE_STRING) {\r
+ ConfigAccess = FormSet->ConfigAccess;\r
+ Action = GetDefaultIdForCallBack (DefaultId);\r
+ if ((Action > 0) && ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) && (ConfigAccess != NULL)) {\r
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+ Status = ConfigAccess->Callback (\r
+ ConfigAccess,\r
+ Action,\r
+ Question->QuestionId,\r
+ HiiValue->Type,\r
+ TypeValue,\r
+ &ActionRequest\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Get default value from altcfg string.\r
+ //\r
+ if (ConfigAccess != NULL) {\r
+ Status = GetDefaultValueFromAltCfg (FormSet, Form, Question, DefaultValue);\r
+ if (!EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ //\r
+ // EFI_IFR_DEFAULT has highest priority\r
+ //\r
+ if (!IsListEmpty (&Question->DefaultListHead)) {\r
+ Link = GetFirstNode (&Question->DefaultListHead);\r
+ while (!IsNull (&Question->DefaultListHead, Link)) {\r
+ Default = HII_QUESTION_DEFAULT_FROM_LINK (Link);\r
+\r
+ if (Default->DefaultId == DefaultId) {\r
+ if (Default->ValueExpression != NULL) {\r
+ //\r
+ // Default is provided by an Expression, evaluate it\r
+ //\r
+ Status = EvaluateHiiExpression (FormSet, Form, Default->ValueExpression);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (Default->ValueExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {\r
+ ASSERT (HiiValue->Type == EFI_IFR_TYPE_BUFFER && DefaultValue->Buffer != NULL);\r
+ if (DefaultValue->BufferLen > Default->ValueExpression->Result.BufferLen) {\r
+ CopyMem (DefaultValue->Buffer, Default->ValueExpression->Result.Buffer, Default->ValueExpression->Result.BufferLen);\r
+ DefaultValue->BufferLen = Default->ValueExpression->Result.BufferLen;\r
+ } else {\r
+ CopyMem (DefaultValue->Buffer, Default->ValueExpression->Result.Buffer, DefaultValue->BufferLen);\r
+ }\r
+\r
+ FreePool (Default->ValueExpression->Result.Buffer);\r
+ }\r
+\r
+ HiiValue->Type = Default->ValueExpression->Result.Type;\r
+ CopyMem (&HiiValue->Value, &Default->ValueExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE));\r
+ } else {\r
+ //\r
+ // Default value is embedded in EFI_IFR_DEFAULT\r
+ //\r
+ if (Default->Value.Type == EFI_IFR_TYPE_BUFFER) {\r
+ ASSERT (HiiValue->Buffer != NULL);\r
+ CopyMem (HiiValue->Buffer, Default->Value.Buffer, Default->Value.BufferLen);\r
+ } else {\r
+ CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));\r
+ }\r
+ }\r
+\r
+ if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
+ StrValue = HiiGetString (FormSet->HiiHandle, HiiValue->Value.string, NULL);\r
+ if (StrValue == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ if (DefaultValue->BufferLen > StrSize (StrValue)) {\r
+ ZeroMem (DefaultValue->Buffer, DefaultValue->BufferLen);\r
+ CopyMem (DefaultValue->Buffer, StrValue, StrSize (StrValue));\r
+ } else {\r
+ CopyMem (DefaultValue->Buffer, StrValue, DefaultValue->BufferLen);\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Link = GetNextNode (&Question->DefaultListHead, Link);\r
+ }\r
+ }\r
+\r
+ //\r
+ // EFI_ONE_OF_OPTION\r
+ //\r
+ if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {\r
+ if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
+ //\r
+ // OneOfOption could only provide Standard and Manufacturing default\r
+ //\r
+ Link = GetFirstNode (&Question->OptionListHead);\r
+ while (!IsNull (&Question->OptionListHead, Link)) {\r
+ Option = HII_QUESTION_OPTION_FROM_LINK (Link);\r
+ Link = GetNextNode (&Question->OptionListHead, Link);\r
+\r
+ if ((Option->SuppressExpression != NULL) &&\r
+ (EvaluateExpressionList (Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse))\r
+ {\r
+ continue;\r
+ }\r
+\r
+ if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||\r
+ ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))\r
+ )\r
+ {\r
+ CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // EFI_IFR_CHECKBOX - lowest priority\r
+ //\r
+ if (Question->Operand == EFI_IFR_CHECKBOX_OP) {\r
+ if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
+ //\r
+ // Checkbox could only provide Standard and Manufacturing default\r
+ //\r
+ if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Question->ExtraData.Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0)) ||\r
+ ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Question->ExtraData.Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0))\r
+ )\r
+ {\r
+ HiiValue->Value.b = TRUE;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ //\r
+ // For question without default value for current default Id, we try to re-get the default value form other default id in the DefaultStoreList.\r
+ // If get, will exit the function, if not, will choose next default id in the DefaultStoreList.\r
+ // The default id in DefaultStoreList are in ascending order to make sure choose the smallest default id every time.\r
+ //\r
+ while (!IsNull (&FormSet->DefaultStoreListHead, DefaultLink)) {\r
+ DefaultStore = HII_FORMSET_DEFAULTSTORE_FROM_LINK (DefaultLink);\r
+ DefaultLink = GetNextNode (&FormSet->DefaultStoreListHead, DefaultLink);\r
+ DefaultId = DefaultStore->DefaultId;\r
+ if (DefaultId == OriginalDefaultId) {\r
+ continue;\r
+ }\r
+\r
+ goto ReGetDefault;\r
+ }\r
+\r
+ //\r
+ // For Questions without default value for all the default id in the DefaultStoreList.\r
+ //\r
+ Status = EFI_NOT_FOUND;\r
+ switch (Question->Operand) {\r
+ case EFI_IFR_CHECKBOX_OP:\r
+ HiiValue->Value.b = FALSE;\r
+ Status = EFI_SUCCESS;\r
+ break;\r
+\r
+ case EFI_IFR_NUMERIC_OP:\r
+ //\r
+ // Take minimum value as numeric default value\r
+ //\r
+ if ((Question->ExtraData.NumData.Flags & EFI_IFR_DISPLAY) == 0) {\r
+ //\r
+ // In EFI_IFR_DISPLAY_INT_DEC type, should check value with int* type.\r
+ //\r
+ switch (Question->ExtraData.NumData.Flags & EFI_IFR_NUMERIC_SIZE) {\r
+ case EFI_IFR_NUMERIC_SIZE_1:\r
+ if (((INT8)HiiValue->Value.u8 < (INT8)Question->ExtraData.NumData.Minimum) || ((INT8)HiiValue->Value.u8 > (INT8)Question->ExtraData.NumData.Maximum)) {\r
+ HiiValue->Value.u8 = (UINT8)Question->ExtraData.NumData.Minimum;\r
+ Status = EFI_SUCCESS;\r
+ }\r
+\r
+ break;\r
+ case EFI_IFR_NUMERIC_SIZE_2:\r
+ if (((INT16)HiiValue->Value.u16 < (INT16)Question->ExtraData.NumData.Minimum) || ((INT16)HiiValue->Value.u16 > (INT16)Question->ExtraData.NumData.Maximum)) {\r
+ HiiValue->Value.u16 = (UINT16)Question->ExtraData.NumData.Minimum;\r
+ Status = EFI_SUCCESS;\r
+ }\r
+\r
+ break;\r
+ case EFI_IFR_NUMERIC_SIZE_4:\r
+ if (((INT32)HiiValue->Value.u32 < (INT32)Question->ExtraData.NumData.Minimum) || ((INT32)HiiValue->Value.u32 > (INT32)Question->ExtraData.NumData.Maximum)) {\r
+ HiiValue->Value.u32 = (UINT32)Question->ExtraData.NumData.Minimum;\r
+ Status = EFI_SUCCESS;\r
+ }\r
+\r
+ break;\r
+ case EFI_IFR_NUMERIC_SIZE_8:\r
+ if (((INT64)HiiValue->Value.u64 < (INT64)Question->ExtraData.NumData.Minimum) || ((INT64)HiiValue->Value.u64 > (INT64)Question->ExtraData.NumData.Maximum)) {\r
+ HiiValue->Value.u64 = Question->ExtraData.NumData.Minimum;\r
+ Status = EFI_SUCCESS;\r
+ }\r
+\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ } else {\r
+ if ((HiiValue->Value.u64 < Question->ExtraData.NumData.Minimum) || (HiiValue->Value.u64 > Question->ExtraData.NumData.Maximum)) {\r
+ HiiValue->Value.u64 = Question->ExtraData.NumData.Minimum;\r
+ Status = EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_ONE_OF_OP:\r
+ //\r
+ // Take first oneof option as oneof's default value\r
+ //\r
+ Link = GetFirstNode (&Question->OptionListHead);\r
+ while (!IsNull (&Question->OptionListHead, Link)) {\r
+ Option = HII_QUESTION_OPTION_FROM_LINK (Link);\r
+ Link = GetNextNode (&Question->OptionListHead, Link);\r
+\r
+ if ((Option->SuppressExpression != NULL) &&\r
+ (EvaluateExpressionList (Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse))\r
+ {\r
+ continue;\r
+ }\r
+\r
+ CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
+ Status = EFI_SUCCESS;\r
+ break;\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_ORDERED_LIST_OP:\r
+ //\r
+ // Take option sequence in IFR as ordered list's default value\r
+ //\r
+ Index = 0;\r
+ Link = GetFirstNode (&Question->OptionListHead);\r
+ while (!IsNull (&Question->OptionListHead, Link)) {\r
+ Status = EFI_SUCCESS;\r
+ Option = HII_QUESTION_OPTION_FROM_LINK (Link);\r
+ Link = GetNextNode (&Question->OptionListHead, Link);\r
+\r
+ if ((Option->SuppressExpression != NULL) &&\r
+ (EvaluateExpressionList (Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse))\r
+ {\r
+ continue;\r
+ }\r
+\r
+ SetArrayData (DefaultValue->Buffer, Question->Value.Type, Index, Option->Value.Value.u64);\r
+\r
+ Index++;\r
+ if (Index >= Question->ExtraData.OrderListData.MaxContainers) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ return Status;\r
+}\r
--- /dev/null
+/** @file\r
+ Implementation of HII utility library.\r
+\r
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>\r
+ Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.\r
+\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include "HiiInternal.h"\r
+\r
+/**\r
+ Initialize the internal data structure of a FormSet.\r
+\r
+ @param Handle PackageList Handle\r
+ @param FormSetGuid On input, GUID or class GUID of a formset. If not\r
+ specified (NULL or zero GUID), take the first\r
+ FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
+ found in package list.\r
+ On output, GUID of the formset found(if not NULL).\r
+ @param FormSet FormSet data structure.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+ @retval EFI_NOT_FOUND The specified FormSet could not be found.\r
+\r
+**/\r
+EFI_STATUS\r
+CreateFormSetFromHiiHandle (\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN OUT EFI_GUID *FormSetGuid,\r
+ OUT HII_FORMSET *FormSet\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE DriverHandle;\r
+ EFI_HII_DATABASE_PROTOCOL *HiiDatabase;\r
+\r
+ if ((FormSetGuid == NULL) || (FormSet == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Locate required Hii Database protocol\r
+ //\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiHiiDatabaseProtocolGuid,\r
+ NULL,\r
+ (VOID **)&HiiDatabase\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ FormSet->Signature = HII_FORMSET_SIGNATURE;\r
+ FormSet->HiiHandle = Handle;\r
+ CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));\r
+ //\r
+ // Retrieve ConfigAccess Protocol associated with this HiiPackageList\r
+ //\r
+ Status = HiiDatabase->GetPackageListHandle (HiiDatabase, Handle, &DriverHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ FormSet->DriverHandle = DriverHandle;\r
+ Status = gBS->HandleProtocol (\r
+ DriverHandle,\r
+ &gEfiHiiConfigAccessProtocolGuid,\r
+ (VOID **)&FormSet->ConfigAccess\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Configuration Driver don't attach ConfigAccess protocol to its HII package\r
+ // list, then there will be no configuration action required\r
+ //\r
+ FormSet->ConfigAccess = NULL;\r
+ }\r
+\r
+ Status = gBS->HandleProtocol (\r
+ DriverHandle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **)&FormSet->DevicePath\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Configuration Driver don't attach ConfigAccess protocol to its HII package\r
+ // list, then there will be no configuration action required\r
+ //\r
+ FormSet->DevicePath = NULL;\r
+ }\r
+\r
+ //\r
+ // Parse the IFR binary OpCodes\r
+ //\r
+ Status = ParseOpCodes (FormSet);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Initialize a Formset and get current setting for Questions.\r
+\r
+ @param FormSet FormSet data structure.\r
+\r
+**/\r
+VOID\r
+InitializeFormSet (\r
+ IN OUT HII_FORMSET *FormSet\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ HII_FORMSET_STORAGE *Storage;\r
+ LIST_ENTRY *FormLink;\r
+ HII_STATEMENT *Question;\r
+ HII_FORM *Form;\r
+\r
+ if (FormSet == NULL) {\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Load Storage for all questions with storage\r
+ //\r
+ Link = GetFirstNode (&FormSet->StorageListHead);\r
+ while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+ Storage = HII_STORAGE_FROM_LINK (Link);\r
+ LoadFormSetStorage (FormSet, Storage);\r
+ Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+ }\r
+\r
+ //\r
+ // Get Current Value for all no storage questions\r
+ //\r
+ FormLink = GetFirstNode (&FormSet->FormListHead);\r
+ while (!IsNull (&FormSet->FormListHead, FormLink)) {\r
+ Form = HII_FORM_FROM_LINK (FormLink);\r
+ Link = GetFirstNode (&Form->StatementListHead);\r
+ while (!IsNull (&Form->StatementListHead, Link)) {\r
+ Question = HII_STATEMENT_FROM_LINK (Link);\r
+ if (Question->Storage == NULL) {\r
+ RetrieveQuestion (FormSet, Form, Question);\r
+ }\r
+\r
+ Link = GetNextNode (&Form->StatementListHead, Link);\r
+ }\r
+\r
+ FormLink = GetNextNode (&FormSet->FormListHead, FormLink);\r
+ }\r
+}\r
+\r
+/**\r
+ Free resources allocated for a FormSet.\r
+\r
+ @param[in,out] FormSet Pointer of the FormSet\r
+\r
+**/\r
+VOID\r
+DestroyFormSet (\r
+ IN OUT HII_FORMSET *FormSet\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ HII_FORMSET_STORAGE *Storage;\r
+ HII_FORMSET_DEFAULTSTORE *DefaultStore;\r
+ HII_FORM *Form;\r
+\r
+ if (FormSet->IfrBinaryData == NULL) {\r
+ //\r
+ // Uninitialized FormSet\r
+ //\r
+ FreePool (FormSet);\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Free IFR binary buffer\r
+ //\r
+ FreePool (FormSet->IfrBinaryData);\r
+\r
+ //\r
+ // Free FormSet Storage\r
+ //\r
+ if (FormSet->StorageListHead.ForwardLink != NULL) {\r
+ while (!IsListEmpty (&FormSet->StorageListHead)) {\r
+ Link = GetFirstNode (&FormSet->StorageListHead);\r
+ Storage = HII_STORAGE_FROM_LINK (Link);\r
+ RemoveEntryList (&Storage->Link);\r
+\r
+ if (Storage != NULL) {\r
+ FreePool (Storage);\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Free FormSet Default Store\r
+ //\r
+ if (FormSet->DefaultStoreListHead.ForwardLink != NULL) {\r
+ while (!IsListEmpty (&FormSet->DefaultStoreListHead)) {\r
+ Link = GetFirstNode (&FormSet->DefaultStoreListHead);\r
+ DefaultStore = HII_FORMSET_DEFAULTSTORE_FROM_LINK (Link);\r
+ RemoveEntryList (&DefaultStore->Link);\r
+\r
+ FreePool (DefaultStore);\r
+ }\r
+ }\r
+\r
+ //\r
+ // Free Forms\r
+ //\r
+ if (FormSet->FormListHead.ForwardLink != NULL) {\r
+ while (!IsListEmpty (&FormSet->FormListHead)) {\r
+ Link = GetFirstNode (&FormSet->FormListHead);\r
+ Form = HII_FORM_FROM_LINK (Link);\r
+ RemoveEntryList (&Form->Link);\r
+\r
+ DestroyForm (FormSet, Form);\r
+ }\r
+ }\r
+\r
+ FreePool (FormSet);\r
+}\r
+\r
+/**\r
+ Submit data for a form.\r
+\r
+ @param[in] FormSet FormSet which contains the Form.\r
+ @param[in] Form Form to submit.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+ @retval Others Other errors occur.\r
+\r
+**/\r
+EFI_STATUS\r
+SubmitForm (\r
+ IN HII_FORMSET *FormSet,\r
+ IN HII_FORM *Form\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;\r
+ LIST_ENTRY *Link;\r
+ EFI_STRING ConfigResp;\r
+ EFI_STRING Progress;\r
+ HII_FORMSET_STORAGE *Storage;\r
+ HII_FORM_CONFIG_REQUEST *ConfigInfo;\r
+\r
+ if ((FormSet == NULL) || (Form == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = NoSubmitCheck (FormSet, &Form, NULL);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Link = GetFirstNode (&Form->ConfigRequestHead);\r
+ while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
+ ConfigInfo = HII_FORM_CONFIG_REQUEST_FROM_LINK (Link);\r
+ Link = GetNextNode (&Form->ConfigRequestHead, Link);\r
+\r
+ Storage = ConfigInfo->Storage;\r
+ if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Skip if there is no RequestElement\r
+ //\r
+ if (ConfigInfo->ElementCount == 0) {\r
+ continue;\r
+ }\r
+\r
+ Status = StorageToConfigResp (ConfigInfo->Storage, &ConfigResp, ConfigInfo->ConfigRequest);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiHiiConfigRoutingProtocolGuid,\r
+ NULL,\r
+ (VOID **)&HiiConfigRouting\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = HiiConfigRouting->RouteConfig (\r
+ HiiConfigRouting,\r
+ ConfigResp,\r
+ &Progress\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (ConfigResp);\r
+ continue;\r
+ }\r
+\r
+ FreePool (ConfigResp);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Save Question Value to the memory, but not to storage.\r
+\r
+ @param[in] FormSet FormSet data structure.\r
+ @param[in] Form Form data structure.\r
+ @param[in,out] Question Pointer to the Question.\r
+ @param[in] QuestionValue New Question Value to be set.\r
+\r
+ @retval EFI_SUCCESS The question value has been set successfully.\r
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+SetQuestionValue (\r
+ IN HII_FORMSET *FormSet,\r
+ IN HII_FORM *Form,\r
+ IN OUT HII_STATEMENT *Question,\r
+ IN HII_STATEMENT_VALUE *QuestionValue\r
+ )\r
+{\r
+ UINT8 *Src;\r
+ UINTN BufferLen;\r
+ UINTN StorageWidth;\r
+ HII_FORMSET_STORAGE *Storage;\r
+ CHAR16 *ValueStr;\r
+ BOOLEAN IsBufferStorage;\r
+ UINT8 *TemBuffer;\r
+ CHAR16 *TemName;\r
+ CHAR16 *TemString;\r
+ UINTN Index;\r
+ HII_NAME_VALUE_NODE *Node;\r
+ EFI_STATUS Status;\r
+\r
+ if ((FormSet == NULL) || (Form == NULL) || (Question == NULL) || (QuestionValue == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ Node = NULL;\r
+\r
+ //\r
+ // If Question value is provided by an Expression, then it is read only\r
+ //\r
+ if ((Question->ValueExpression != NULL) || (Question->Value.Type != QuestionValue->Type)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Before set question value, evaluate its write expression.\r
+ //\r
+ if ((Question->WriteExpression != NULL) && (Form->FormType == STANDARD_MAP_FORM_TYPE)) {\r
+ Status = EvaluateHiiExpression (FormSet, Form, Question->WriteExpression);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ Storage = Question->Storage;\r
+ if (Storage != NULL) {\r
+ StorageWidth = Question->StorageWidth;\r
+ if (Question->Value.Type == EFI_IFR_TYPE_BUFFER) {\r
+ Question->Value.BufferLen = QuestionValue->BufferLen;\r
+ Question->Value.Buffer = AllocateCopyPool (QuestionValue->BufferLen, QuestionValue->Buffer);\r
+ if (Question->Value.Buffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Question->Value.BufferValueType = QuestionValue->BufferValueType;\r
+ Src = Question->Value.Buffer;\r
+ } else if (Question->Value.Type == EFI_IFR_TYPE_STRING) {\r
+ Question->Value.Value.string = QuestionValue->Value.string;\r
+ TemString = HiiGetString (FormSet->HiiHandle, QuestionValue->Value.string, NULL);\r
+ if (TemString == NULL) {\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ Question->Value.BufferLen = Question->StorageWidth;\r
+ Question->Value.Buffer = AllocateZeroPool (Question->StorageWidth);\r
+ if (Question->Value.Buffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ CopyMem (Question->Value.Buffer, TemString, StrSize (TemString));\r
+ Src = Question->Value.Buffer;\r
+ } else {\r
+ CopyMem (&Question->Value.Value, &QuestionValue->Value, sizeof (EFI_IFR_TYPE_VALUE));\r
+ Src = (UINT8 *)&Question->Value.Value;\r
+ }\r
+\r
+ if ((Storage->Type == EFI_HII_VARSTORE_BUFFER) || (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
+ IsBufferStorage = TRUE;\r
+ } else {\r
+ IsBufferStorage = FALSE;\r
+ }\r
+\r
+ if (IsBufferStorage) {\r
+ //\r
+ // If the Question refer to bit filed, copy the value in related bit filed to storage edit buffer.\r
+ //\r
+ if (Question->QuestionReferToBitField) {\r
+ SetBitsQuestionValue (Question, Storage->Buffer + Question->VarStoreInfo.VarOffset, (UINT32)(*Src));\r
+ } else {\r
+ CopyMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
+ }\r
+ } else {\r
+ if (Question->Value.Type == EFI_IFR_TYPE_STRING) {\r
+ //\r
+ // Allocate enough string buffer.\r
+ //\r
+ ValueStr = NULL;\r
+ BufferLen = ((StrLen ((CHAR16 *)Src) * 4) + 1) * sizeof (CHAR16);\r
+ ValueStr = AllocatePool (BufferLen);\r
+ if (ValueStr == NULL) {\r
+ if (Question->Value.Buffer != NULL) {\r
+ FreePool (Question->Value.Buffer);\r
+ }\r
+\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
+ //\r
+ TemName = (CHAR16 *)Src;\r
+ TemString = ValueStr;\r
+ for ( ; *TemName != L'\0'; TemName++) {\r
+ UnicodeValueToStringS (\r
+ TemString,\r
+ BufferLen - ((UINTN)TemString - (UINTN)ValueStr),\r
+ PREFIX_ZERO | RADIX_HEX,\r
+ *TemName,\r
+ 4\r
+ );\r
+ TemString += StrnLenS (TemString, (BufferLen - ((UINTN)TemString - (UINTN)ValueStr)) / sizeof (CHAR16));\r
+ }\r
+ } else {\r
+ BufferLen = StorageWidth * 2 + 1;\r
+ ValueStr = AllocateZeroPool (BufferLen * sizeof (CHAR16));\r
+ if (ValueStr == NULL) {\r
+ if (Question->Value.Buffer != NULL) {\r
+ FreePool (Question->Value.Buffer);\r
+ }\r
+\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Convert Buffer to Hex String\r
+ //\r
+ TemBuffer = Src + StorageWidth - 1;\r
+ TemString = ValueStr;\r
+ for (Index = 0; Index < StorageWidth; Index++, TemBuffer--) {\r
+ UnicodeValueToStringS (\r
+ TemString,\r
+ BufferLen * sizeof (CHAR16) - ((UINTN)TemString - (UINTN)ValueStr),\r
+ PREFIX_ZERO | RADIX_HEX,\r
+ *TemBuffer,\r
+ 2\r
+ );\r
+ TemString += StrnLenS (TemString, BufferLen - ((UINTN)TemString - (UINTN)ValueStr) / sizeof (CHAR16));\r
+ }\r
+ }\r
+\r
+ Status = SetValueByName (Storage, Question->VariableName, ValueStr, &Node);\r
+ FreePool (ValueStr);\r
+ if (EFI_ERROR (Status)) {\r
+ if (Question->Value.Buffer != NULL) {\r
+ FreePool (Question->Value.Buffer);\r
+ }\r
+\r
+ return Status;\r
+ }\r
+ }\r
+ } else {\r
+ if (Question->Value.Type == EFI_IFR_TYPE_BUFFER) {\r
+ Question->Value.BufferLen = QuestionValue->BufferLen;\r
+ Question->Value.Buffer = AllocateCopyPool (QuestionValue->BufferLen, QuestionValue->Buffer);\r
+ if (Question->Value.Buffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Question->Value.BufferValueType = QuestionValue->BufferValueType;\r
+ } else if (Question->Value.Type == EFI_IFR_TYPE_STRING) {\r
+ Question->Value.Value.string = QuestionValue->Value.string;\r
+ TemString = HiiGetString (FormSet->HiiHandle, QuestionValue->Value.string, NULL);\r
+ if (TemString == NULL) {\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ Question->Value.BufferLen = (UINT16)StrSize (TemString);\r
+ Question->Value.Buffer = AllocateZeroPool (QuestionValue->BufferLen);\r
+ if (Question->Value.Buffer == NULL) {\r
+ FreePool (TemString);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ CopyMem (Question->Value.Buffer, TemString, StrSize (TemString));\r
+ FreePool (TemString);\r
+ } else {\r
+ CopyMem (&Question->Value.Value, &QuestionValue->Value, sizeof (EFI_IFR_TYPE_VALUE));\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Get Question's current Value from storage.\r
+\r
+ @param[in] FormSet FormSet data structure.\r
+ @param[in] Form Form data structure.\r
+ @param[in,out] Question Question to be initialized.\r
+\r
+ @return the current Question Value in storage if success.\r
+ @return NULL if Question is not found or any error occurs.\r
+\r
+**/\r
+HII_STATEMENT_VALUE *\r
+RetrieveQuestion (\r
+ IN HII_FORMSET *FormSet,\r
+ IN HII_FORM *Form,\r
+ IN OUT HII_STATEMENT *Question\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;\r
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
+ HII_FORMSET_STORAGE *Storage;\r
+ HII_STATEMENT_VALUE *QuestionValue;\r
+ EFI_IFR_TYPE_VALUE *TypeValue;\r
+ EFI_TIME EfiTime;\r
+ BOOLEAN Enabled;\r
+ BOOLEAN Pending;\r
+ UINT8 *Dst;\r
+ UINTN StorageWidth;\r
+ CHAR16 *ConfigRequest;\r
+ CHAR16 *Progress;\r
+ CHAR16 *Result;\r
+ CHAR16 *ValueStr;\r
+ UINTN Length;\r
+ BOOLEAN IsBufferStorage;\r
+ CHAR16 *NewHiiString;\r
+\r
+ if ((FormSet == NULL) || (Form == NULL) || (Question == NULL)) {\r
+ return NULL;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ ValueStr = NULL;\r
+ Result = NULL;\r
+\r
+ QuestionValue = AllocateZeroPool (sizeof (HII_STATEMENT_VALUE));\r
+ if (QuestionValue == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ QuestionValue->Type = Question->Value.Type;\r
+ QuestionValue->BufferLen = Question->Value.BufferLen;\r
+ if (QuestionValue->BufferLen != 0) {\r
+ QuestionValue->Buffer = AllocateZeroPool (QuestionValue->BufferLen);\r
+ if (QuestionValue->Buffer == NULL) {\r
+ FreePool (QuestionValue);\r
+ return NULL;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Question value is provided by RTC\r
+ //\r
+ Storage = Question->Storage;\r
+ StorageWidth = Question->StorageWidth;\r
+\r
+ if (Storage == NULL) {\r
+ //\r
+ // It's a Question without storage, or RTC date/time\r
+ //\r
+ if ((Question->Operand == EFI_IFR_DATE_OP) || (Question->Operand == EFI_IFR_TIME_OP)) {\r
+ //\r
+ // Date and time define the same Flags bit\r
+ //\r
+ switch (Question->ExtraData.Flags & EFI_QF_DATE_STORAGE) {\r
+ case QF_DATE_STORAGE_TIME:\r
+\r
+ Status = gRT->GetTime (&EfiTime, NULL);\r
+ break;\r
+\r
+ case QF_DATE_STORAGE_WAKEUP:\r
+\r
+ Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
+ break;\r
+\r
+ case QF_DATE_STORAGE_NORMAL:\r
+ default:\r
+\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ if (Question->Operand == EFI_IFR_DATE_OP) {\r
+ QuestionValue->Value.date.Year = 0xff;\r
+ QuestionValue->Value.date.Month = 0xff;\r
+ QuestionValue->Value.date.Day = 0xff;\r
+ } else {\r
+ QuestionValue->Value.time.Hour = 0xff;\r
+ QuestionValue->Value.time.Minute = 0xff;\r
+ QuestionValue->Value.time.Second = 0xff;\r
+ }\r
+\r
+ return QuestionValue;\r
+ }\r
+\r
+ if (Question->Operand == EFI_IFR_DATE_OP) {\r
+ QuestionValue->Value.date.Year = EfiTime.Year;\r
+ QuestionValue->Value.date.Month = EfiTime.Month;\r
+ QuestionValue->Value.date.Day = EfiTime.Day;\r
+ } else {\r
+ QuestionValue->Value.time.Hour = EfiTime.Hour;\r
+ QuestionValue->Value.time.Minute = EfiTime.Minute;\r
+ QuestionValue->Value.time.Second = EfiTime.Second;\r
+ }\r
+ } else {\r
+ if (((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) ||\r
+ (FormSet->ConfigAccess == NULL))\r
+ {\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ if (QuestionValue->Type == EFI_IFR_TYPE_BUFFER) {\r
+ //\r
+ // For OrderedList, passing in the value buffer to Callback()\r
+ //\r
+ TypeValue = (EFI_IFR_TYPE_VALUE *)QuestionValue->Buffer;\r
+ } else {\r
+ TypeValue = &QuestionValue->Value;\r
+ }\r
+\r
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+ Status = FormSet->ConfigAccess->Callback (\r
+ FormSet->ConfigAccess,\r
+ EFI_BROWSER_ACTION_RETRIEVE,\r
+ Question->QuestionId,\r
+ QuestionValue->Type,\r
+ TypeValue,\r
+ &ActionRequest\r
+ );\r
+\r
+ if (!EFI_ERROR (Status) && (QuestionValue->Type == EFI_IFR_TYPE_STRING)) {\r
+ if (TypeValue->string == 0) {\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ NewHiiString = GetTokenString (TypeValue->string, FormSet->HiiHandle);\r
+ if (NewHiiString == NULL) {\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ QuestionValue->Buffer = AllocatePool (StrSize (NewHiiString));\r
+ if (QuestionValue->Buffer == NULL) {\r
+ FreePool (NewHiiString);\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ CopyMem (QuestionValue->Buffer, NewHiiString, StrSize (NewHiiString));\r
+ QuestionValue->BufferLen = (UINT16)StrSize (NewHiiString);\r
+\r
+ FreePool (NewHiiString);\r
+ }\r
+ }\r
+\r
+ return QuestionValue;\r
+ }\r
+\r
+ //\r
+ // Question value is provided by EFI variable\r
+ //\r
+ if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+ if ((QuestionValue->Type != EFI_IFR_TYPE_BUFFER) && (QuestionValue->Type != EFI_IFR_TYPE_STRING)) {\r
+ Dst = QuestionValue->Buffer;\r
+ StorageWidth = QuestionValue->BufferLen;\r
+ } else {\r
+ Dst = (UINT8 *)&QuestionValue->Value;\r
+ StorageWidth = sizeof (EFI_IFR_TYPE_VALUE);\r
+ }\r
+\r
+ Status = gRT->GetVariable (\r
+ Question->VariableName,\r
+ &Storage->Guid,\r
+ NULL,\r
+ &StorageWidth,\r
+ Dst\r
+ );\r
+\r
+ return QuestionValue;\r
+ }\r
+\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiHiiConfigRoutingProtocolGuid,\r
+ NULL,\r
+ (VOID **)&HiiConfigRouting\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ if (QuestionValue->BufferLen != 0) {\r
+ Dst = QuestionValue->Buffer;\r
+ } else {\r
+ Dst = (UINT8 *)&QuestionValue->Value;\r
+ }\r
+\r
+ if ((Storage->Type == EFI_HII_VARSTORE_BUFFER) || (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
+ IsBufferStorage = TRUE;\r
+ } else {\r
+ IsBufferStorage = FALSE;\r
+ }\r
+\r
+ Storage = GetFstStgFromVarId (FormSet, Question->VarStoreId);\r
+ if (Storage == NULL) {\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ //\r
+ // <ConfigRequest> ::= <ConfigHdr> + <BlockName> || <ConfigHdr> + "&" + <VariableName>\r
+ //\r
+ if (IsBufferStorage) {\r
+ Length = StrLen (Storage->ConfigHdr);\r
+ Length += StrLen (Question->BlockName);\r
+ } else {\r
+ Length = StrLen (Storage->ConfigHdr);\r
+ Length += StrLen (Question->VariableName) + 1;\r
+ }\r
+\r
+ ConfigRequest = AllocatePool ((Length + 1) * sizeof (CHAR16));\r
+ if (ConfigRequest == NULL) {\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ StrCpyS (ConfigRequest, Length + 1, Storage->ConfigHdr);\r
+ if (IsBufferStorage) {\r
+ StrCatS (ConfigRequest, Length + 1, Question->BlockName);\r
+ } else {\r
+ StrCatS (ConfigRequest, Length + 1, L"&");\r
+ StrCatS (ConfigRequest, Length + 1, Question->VariableName);\r
+ }\r
+\r
+ //\r
+ // Request current settings from Configuration Driver\r
+ //\r
+ Status = HiiConfigRouting->ExtractConfig (\r
+ HiiConfigRouting,\r
+ ConfigRequest,\r
+ &Progress,\r
+ &Result\r
+ );\r
+ FreePool (ConfigRequest);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ if (IsBufferStorage) {\r
+ ValueStr = StrStr (Result, L"&VALUE");\r
+ if (ValueStr == NULL) {\r
+ FreePool (Result);\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ ValueStr = ValueStr + 6;\r
+ } else {\r
+ ValueStr = Result + Length;\r
+ }\r
+\r
+ if (*ValueStr != '=') {\r
+ FreePool (Result);\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ ValueStr++;\r
+ Status = BufferToQuestionValue (Question, ValueStr, QuestionValue);\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (Result);\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ if (Result != NULL) {\r
+ FreePool (Result);\r
+ }\r
+\r
+ return QuestionValue;\r
+\r
+ON_ERROR:\r
+\r
+ if (QuestionValue->Buffer != NULL) {\r
+ FreePool (QuestionValue->Buffer);\r
+ }\r
+\r
+ FreePool (QuestionValue);\r
+\r
+ return NULL;\r
+}\r
--- /dev/null
+## @file\r
+# Library to handle HII IFR data.\r
+#\r
+# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+# (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>\r
+# Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.\r
+#\r
+# SPDX-License-Identifier: BSD-2-Clause-Patent\r
+#\r
+##\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = HiiUtilityLib\r
+ FILE_GUID = D00DA028-F19A-47AF-B22A-6EE9E8BD7335\r
+ MODULE_TYPE = UEFI_DRIVER\r
+ VERSION_STRING = 1.0\r
+ LIBRARY_CLASS = HiiUtilityLib|DXE_DRIVER UEFI_DRIVER UEFI_APPLICATION\r
+\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64 EBC\r
+#\r
+\r
+[Sources]\r
+ HiiUtilityLib.c\r
+ HiiExpression.c\r
+ HiiUtilityInternal.c\r
+ HiiIfrParse.c\r
+ HiiInternal.h\r
+ HiiExpression.h\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+ RedfishPkg/RedfishPkg.dec\r
+\r
+[LibraryClasses]\r
+ PrintLib\r
+ DebugLib\r
+ BaseMemoryLib\r
+ UefiRuntimeServicesTableLib\r
+ UefiBootServicesTableLib\r
+ MemoryAllocationLib\r
+ HiiLib\r
+\r
+[Guids]\r
+ gZeroGuid\r
+ gEdkiiIfrBitVarstoreGuid\r
+ gEfiHiiPlatformSetupFormsetGuid\r
+ gEfiHiiStandardFormGuid\r
+\r
+[Protocols]\r
+ gEfiHiiDatabaseProtocolGuid\r
+ gEfiHiiConfigRoutingProtocolGuid\r
+ gEfiHiiConfigAccessProtocolGuid\r
+ gEfiDevicePathFromTextProtocolGuid\r
+ gEfiUnicodeCollation2ProtocolGuid\r
+ gEfiRegularExpressionProtocolGuid\r
+ gEfiUserManagerProtocolGuid\r
+\r
+[Depex]\r
+ TRUE\r
# Library provides Redfish debug functions.\r
RedfishDebugLib|Include/Library/RedfishDebugLib.h\r
\r
+ ## @libraryclass Provides the library functions to parse IFR binary data.\r
+ #\r
+ HiiUtilityLib|Include/Library/HiiUtilityLib.h\r
+\r
[LibraryClasses.Common.Private]\r
## @libraryclass Provides the private C runtime library functions.\r
# CRT library is currently used by edk2 JsonLib (open source\r