From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mx0a-002e3701.pphosted.com (mx0a-002e3701.pphosted.com [148.163.147.86]) by mx.groups.io with SMTP id smtpd.web12.5249.1635383284647589938 for ; Wed, 27 Oct 2021 18:08:12 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@hpe.com header.s=pps0720 header.b=F8sXUnAk; spf=temperror, err=temporary DNS error (domain: hpe.com, ip: 148.163.147.86, mailfrom: prvs=09357d8486=abner.chang@hpe.com) Received: from pps.filterd (m0134420.ppops.net [127.0.0.1]) by mx0b-002e3701.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 19RG8tPN020381; Thu, 28 Oct 2021 01:07:31 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=hpe.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pps0720; bh=wCBa8HdPyhIdQ6388NsUPBtTGj0xXP64emO9LdLvZQY=; b=F8sXUnAklrikTVzqNPao9ix6gtGuHaxakHTjD/20+wyz4YY48u10mjPIhSB8dghig8YT burWv5cMI/XQkSDA91EesZdfgcRLozMkewBeWAiYKHi94+PoQXyM7/6QrKJTJrlNM/gE qJI1wWLzyhqVO/12MUowZAdhIjFre4p0AatB2oUNMH6qn52IyVU8QUsMj3f3LXumCeJQ uASesd9sZckjXMq4OkPzDsjtiWShXDdPZY1HEDaaOZwjyjB643+kqguSOOQBmFyIp3nZ qMelQ5bNwuUdRbmeRCNFh/ow+TVSDrUx9rs3jbmEi0cUyxpuc6GETLjEDmcjugV+RoHx hg== Received: from g2t2354.austin.hpe.com (g2t2354.austin.hpe.com [15.233.44.27]) by mx0b-002e3701.pphosted.com with ESMTP id 3by4ayxrk5-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 28 Oct 2021 01:07:29 +0000 Received: from g2t2360.austin.hpecorp.net (g2t2360.austin.hpecorp.net [16.196.225.135]) by g2t2354.austin.hpe.com (Postfix) with ESMTP id 95850A0; Thu, 28 Oct 2021 01:07:28 +0000 (UTC) Received: from SAC2XFT1JT.asiapacific.hpqcorp.net (unknown [10.43.62.133]) by g2t2360.austin.hpecorp.net (Postfix) with ESMTP id 24FE736; Thu, 28 Oct 2021 01:07:26 +0000 (UTC) From: "Abner Chang" To: devel@edk2.groups.io Cc: nickle.wang@hpe.com, Liming Gao Subject: [PATCH RESEND 2/5] edk2-staging/RedfishPkg: HII utility helper library Date: Thu, 28 Oct 2021 09:07:20 +0800 Message-Id: <20211028010723.37316-3-abner.chang@hpe.com> X-Mailer: git-send-email 2.21.0.windows.1 In-Reply-To: <20211028010723.37316-1-abner.chang@hpe.com> References: <20211028010723.37316-1-abner.chang@hpe.com> MIME-Version: 1.0 X-Proofpoint-GUID: NfR73sbobkMwv1LkVQTJdfUdDgN2F91f X-Proofpoint-ORIG-GUID: NfR73sbobkMwv1LkVQTJdfUdDgN2F91f X-HPE-SCL: -1 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.182.1,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.0.607.475 definitions=2021-10-27_07,2021-10-26_01,2020-04-07_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 clxscore=1015 mlxlogscore=999 priorityscore=1501 phishscore=0 mlxscore=0 spamscore=0 bulkscore=0 lowpriorityscore=0 malwarescore=0 adultscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2110280005 Content-Transfer-Encoding: 8bit HiiUtilityLib is a helper library that provides the functions to manipulate HII options. Signed-off-by: Nickle Wang Cc: Abner Chang Cc: Liming Gao --- RedfishPkg/RedfishPkg.dec | 4 + .../Library/HiiUtilityLib/HiiUtilityLib.inf | 61 + RedfishPkg/Include/Library/HiiUtilityLib.h | 1195 ++++ .../Library/HiiUtilityLib/HiiExpression.h | 190 + .../Library/HiiUtilityLib/HiiInternal.h | 371 ++ .../Library/HiiUtilityLib/HiiExpression.c | 1367 +++++ .../Library/HiiUtilityLib/HiiIfrParse.c | 2671 +++++++++ .../HiiUtilityLib/HiiUtilityInternal.c | 5045 +++++++++++++++++ .../Library/HiiUtilityLib/HiiUtilityLib.c | 855 +++ 9 files changed, 11759 insertions(+) create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.inf create mode 100644 RedfishPkg/Include/Library/HiiUtilityLib.h create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiExpression.h create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiInternal.h create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiExpression.c create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiIfrParse.c create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiUtilityInternal.c create mode 100644 RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.c diff --git a/RedfishPkg/RedfishPkg.dec b/RedfishPkg/RedfishPkg.dec index 4d80515fe07..eac219ccbb9 100644 --- a/RedfishPkg/RedfishPkg.dec +++ b/RedfishPkg/RedfishPkg.dec @@ -55,6 +55,10 @@ # RedfishContentCodingLib|Include/Library/RedfishContentCodingLib.h + ## @libraryclass Provides the library functions to parse IFR binary data. + # + HiiUtilityLib|Include/Library/HiiUtilityLib.h + [LibraryClasses.Common.Private] ## @libraryclass Provides the private C runtime library functions. # CRT library is currently used by edk2 JsonLib (open source diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.inf b/RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.inf new file mode 100644 index 00000000000..36a629a758b --- /dev/null +++ b/RedfishPkg/Library/HiiUtilityLib/HiiUtilityLib.inf @@ -0,0 +1,61 @@ +## @file +# Library to handle HII IFR data. +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# (C) Copyright 2021 Hewlett Packard Enterprise Development LP
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = HiiUtilityLib + FILE_GUID = D00DA028-F19A-47AF-B22A-6EE9E8BD7335 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = HiiUtilityLib|DXE_DRIVER UEFI_DRIVER UEFI_APPLICATION + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + HiiUtilityLib.c + HiiExpression.c + HiiUtilityInternal.c + HiiIfrParse.c + HiiInternal.h + HiiExpression.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + RedfishPkg/RedfishPkg.dec + +[LibraryClasses] + PrintLib + DebugLib + BaseMemoryLib + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + MemoryAllocationLib + HiiLib + +[Guids] + gZeroGuid + gEdkiiIfrBitVarstoreGuid + gEfiHiiPlatformSetupFormsetGuid + gEfiHiiStandardFormGuid + +[Protocols] + gEfiHiiDatabaseProtocolGuid + gEfiHiiConfigRoutingProtocolGuid + gEfiHiiConfigAccessProtocolGuid + gEfiDevicePathFromTextProtocolGuid + gEfiUnicodeCollation2ProtocolGuid + gEfiRegularExpressionProtocolGuid + gEfiUserManagerProtocolGuid + +[Depex] + TRUE diff --git a/RedfishPkg/Include/Library/HiiUtilityLib.h b/RedfishPkg/Include/Library/HiiUtilityLib.h new file mode 100644 index 00000000000..1f164ba49c6 --- /dev/null +++ b/RedfishPkg/Include/Library/HiiUtilityLib.h @@ -0,0 +1,1195 @@ +/** @file + Definitinos of RedfishPlatformConfigLib + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#ifndef HII_UTILITY_LIB_ +#define HII_UTILITY_LIB_ + +#include +#include + +// +// IFR relative definition +// +#define EFI_HII_EXPRESSION_INCONSISTENT_IF 0 +#define EFI_HII_EXPRESSION_NO_SUBMIT_IF 1 +#define EFI_HII_EXPRESSION_GRAY_OUT_IF 2 +#define EFI_HII_EXPRESSION_SUPPRESS_IF 3 +#define EFI_HII_EXPRESSION_DISABLE_IF 4 +#define EFI_HII_EXPRESSION_VALUE 5 +#define EFI_HII_EXPRESSION_RULE 6 +#define EFI_HII_EXPRESSION_READ 7 +#define EFI_HII_EXPRESSION_WRITE 8 +#define EFI_HII_EXPRESSION_WARNING_IF 9 + +#define EFI_HII_VARSTORE_BUFFER 0 +#define EFI_HII_VARSTORE_NAME_VALUE 1 +#define EFI_HII_VARSTORE_EFI_VARIABLE 2 // EFI Varstore type follow UEFI spec before 2.3.1. +#define EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER 3 // EFI varstore type follow UEFI spec 2.3.1 and later. + +// +// HII_NAME_VALUE_NODE for name/value storage +// +typedef struct { + + UINTN Signature; + LIST_ENTRY Link; + CHAR16 *Name; + CHAR16 *Value; + +} HII_NAME_VALUE_NODE; + +#define HII_NAME_VALUE_NODE_SIGNATURE SIGNATURE_32 ('N', 'V', 'S', 'T') +#define HII_NAME_VALUE_NODE_FROM_LINK(a) CR (a, HII_NAME_VALUE_NODE, Link, HII_NAME_VALUE_NODE_SIGNATURE) + +// +// Storage info +// +typedef union { + EFI_STRING_ID VarName; + UINT16 VarOffset; +} HII_VAR_STORE_INFO; + +// +// FormSet storage +// +typedef struct { + UINTN Signature; + LIST_ENTRY Link; + + UINT8 Type; // Storage type + EFI_HII_HANDLE HiiHandle; // HiiHandle for this varstore. + + // + // For all type of storages. + // + UINT16 VarStoreId; // VarStore ID. + EFI_GUID Guid; // VarStore Guid. + + // + // For EFI_IFR_VARSTORE, EFI_IFR_VARSTORE_EFI + // + CHAR16 *Name; // VarStore name + UINT16 Size; // Varatore size. + UINT8 *Buffer; // Buffer storage. + UINT8 *EditBuffer; // Edit copy for Buffer Storage + + // + // For EFI_IFR_VARSTORE_EFI: EFI Variable. + // + UINT32 Attributes; + + // + //For EFI_IFR_VARSTORE_NAME_VALUE. + // + LIST_ENTRY NameValueList; // List of NAME_VALUE_NODE + + CHAR16 *ConfigHdr; // + CHAR16 *ConfigRequest; // = + + UINTN ElementCount; // Number of in the + UINTN SpareStrLen; // Spare length of ConfigRequest string buffer +} HII_FORMSET_STORAGE; + + +#define HII_STORAGE_SIGNATURE SIGNATURE_32 ('B', 'S', 'T', 'G') +#define HII_STORAGE_FROM_LINK(a) CR (a, HII_FORMSET_STORAGE, Link, HII_STORAGE_SIGNATURE) + +// +// Definition of EXPRESS_RESULT +// +typedef enum { + ExpressFalse = 0, + ExpressGrayOut, + ExpressSuppress, + ExpressDisable +} EXPRESS_RESULT; + +// +// Definition of EXPRESS_LEVEL +// +typedef enum { + ExpressNone = 0, + ExpressForm, + ExpressStatement, + ExpressOption +} EXPRESS_LEVEL; + +// +// Definition of HII_EXPRESSION_OPCODE_EXTRA +// +typedef union { + + EFI_HII_VALUE Value; // EFI_IFR_UINT64, EFI_IFR_UINT32, EFI_IFR_UINT16, EFI_IFR_UINT8, EFI_IFR_STRING_REF1 + UINT8 Format; // For EFI_IFR_TO_STRING, EFI_IFR_FIND + UINT8 Flags; // For EFI_IFR_SPAN + UINT8 RuleId; // For EFI_IFR_RULE_REF + EFI_GUID Guid; // For EFI_IFR_SECURITY, EFI_IFR_MATCH2 + + struct { + EFI_QUESTION_ID QuestionId; + EFI_HII_VALUE Value; + } EqIdValData; + + struct { + EFI_QUESTION_ID QuestionId1; + EFI_QUESTION_ID QuestionId2; + } EqIdIdData; + + struct { + EFI_QUESTION_ID QuestionId; // For EFI_IFR_EQ_ID_VAL_LIST + UINT16 ListLength; + UINT16 *ValueList; + } EqIdListData; + + struct { + EFI_QUESTION_ID QuestionId; + } QuestionRef1Data; + + struct { + EFI_STRING_ID DevicePath; // For EFI_IFR_QUESTION_REF3_3 + EFI_GUID Guid; + } QuestionRef3Data; + + struct { + HII_FORMSET_STORAGE *VarStorage; + HII_VAR_STORE_INFO VarStoreInfo; + UINT8 ValueType; + UINT8 ValueWidth; + CHAR16 *ValueName; + } GetSetData; + +} HII_EXPRESSION_OPCODE_EXTRA; + +typedef union _HII_DEPENDENCY_EXPRESSION HII_DEPENDENCY_EXPRESSION; + +// +// Definition of HII_EXPRESSION_CONSTANT +// +// Operand: +// +// EFI_IFR_TRUE +// EFI_IFR_FALSE +// EFI_IFR_ONE +// EFI_IFR_ONES +// EFI_IFR_ZERO +// EFI_IFR_UNDEFINED +// EFI_IFR_VERSION +// EFI_IFR_UINT8 +// EFI_IFR_UINT16 +// EFI_IFR_UINT32 +// EFI_IFR_UINT64 +// +typedef struct { + UINT8 Operand; + EFI_HII_VALUE Value; +} HII_EXPRESSION_CONSTANT; + +// +// Definition of HII_DEPENDENCY_DUP +// +typedef struct { + UINT8 Operand; +} HII_DEPENDENCY_DUP; + +// +// Definition of HII_DEPENDENCY_EQ_ID_VAL +// +typedef struct { + UINT8 Operand; + EFI_QUESTION_ID QuestionId; + EFI_HII_VALUE Value; +} HII_DEPENDENCY_EQ_ID_VAL; + +// +// Definition of HII_DEPENDENCY_EQ_ID_VAL +// +typedef struct { + UINT8 Operand; + EFI_QUESTION_ID QuestionId1; + EFI_QUESTION_ID QuestionId2; +} HII_DEPENDENCY_EQ_ID_ID; + +// +// Definition of HII_DEPENDENCY_EQ_ID_VAL_LIST +// +typedef struct { + UINT8 Operand; + EFI_QUESTION_ID QuestionId; + UINT16 ListLength; + UINT16 *ValueList; +} HII_DEPENDENCY_EQ_ID_VAL_LIST; + +// +// Definition of HII_DEPENDENCY_QUESTION_REF1 +// +typedef struct { + UINT8 Operand; + EFI_QUESTION_ID QuestionId; +} HII_DEPENDENCY_QUESTION_REF1; + +// +// Definition of HII_DEPENDENCY_RULE_REF +// +typedef struct { + UINT8 Operand; + UINT8 RuleId; +} HII_DEPENDENCY_RULE_REF; + +// +// Definition of HII_DEPENDENCY_STRING_REF1 +// +typedef struct { + UINT8 Operand; + EFI_HII_VALUE Value; +} HII_DEPENDENCY_STRING_REF1; + +// +// Definition of HII_DEPENDENCY_THIS +// +typedef struct { + UINT8 Operand; + EFI_QUESTION_ID QuestionId; +} HII_DEPENDENCY_THIS; + +// +// Definition of HII_DEPENDENCY_SECURITY +// +typedef struct { + UINT8 Operand; + EFI_GUID Permissions; +} HII_DEPENDENCY_SECURITY; + +// +// Definition of HII_DEPENDENCY_GET +// +typedef struct { + UINT8 Operand; + HII_FORMSET_STORAGE *VarStorage; + HII_VAR_STORE_INFO VarStoreInfo; + UINT8 ValueType; + UINT8 ValueWidth; + CHAR16 *ValueName; +} HII_DEPENDENCY_GET; + +// +// Definition of HII_DEPENDENCY_LENGTH +// +typedef struct { + UINT8 Operand; + HII_DEPENDENCY_EXPRESSION *SubExpression; +} HII_DEPENDENCY_LENGTH; + +// +// Definition of HII_DEPENDENCY_BITWISE_NOT +// +typedef struct { + UINT8 Operand; + HII_DEPENDENCY_EXPRESSION *SubExpression; +} HII_DEPENDENCY_BITWISE_NOT; + +// +// Definition of HII_DEPENDENCY_STRING_REF2 +// +typedef struct { + UINT8 Operand; + HII_DEPENDENCY_EXPRESSION *SubExpression; +} HII_DEPENDENCY_STRING_REF2; + +// +// Definition of HII_DEPENDENCY_QUESTION_REF2 +// +typedef struct { + UINT8 Operand; + HII_DEPENDENCY_EXPRESSION *SubExpression; +} HII_DEPENDENCY_QUESTION_REF2; + +// +// Definition of HII_DEPENDENCY_QUESTION_REF3 +// +typedef struct { + UINT8 Operand; + EFI_STRING_ID DevicePath; + EFI_GUID Guid; + HII_DEPENDENCY_EXPRESSION *SubExpression; +} HII_DEPENDENCY_QUESTION_REF3; + +// +// Definition of HII_DEPENDENCY_TO_BOOLEAN +// +typedef struct { + UINT8 Operand; + HII_DEPENDENCY_EXPRESSION *SubExpression; +} HII_DEPENDENCY_TO_BOOLEAN; + +// +// Definition of HII_DEPENDENCY_TO_STRING +// +typedef struct { + UINT8 Operand; + UINT8 Format; + HII_DEPENDENCY_EXPRESSION *SubExpression; +} HII_DEPENDENCY_TO_STRING; + +// +// Definition of HII_DEPENDENCY_TO_UINT +// +typedef struct { + UINT8 Operand; + HII_DEPENDENCY_EXPRESSION *SubExpression; +} HII_DEPENDENCY_TO_UINT; + +// +// Definition of HII_DEPENDENCY_TO_UPPER +// +typedef struct { + UINT8 Operand; + HII_DEPENDENCY_EXPRESSION *SubExpression; +} HII_DEPENDENCY_TO_UPPER; + +// +// Definition of HII_DEPENDENCY_TO_LOWER +// +typedef struct { + UINT8 Operand; + HII_DEPENDENCY_EXPRESSION *SubExpression; +} HII_DEPENDENCY_TO_LOWER; + +// +// Definition of HII_DEPENDENCY_SET +// +typedef struct { + UINT8 Operand; + HII_FORMSET_STORAGE *VarStorage; + HII_VAR_STORE_INFO VarStoreInfo; + UINT8 ValueType; + UINT8 ValueWidth; + CHAR16 *ValueName; + HII_DEPENDENCY_EXPRESSION *SubExpression; +} HII_DEPENDENCY_SET; + +// +// Definition of HII_DEPENDENCY_NOT +// +typedef struct { + UINT8 Operand; + HII_DEPENDENCY_EXPRESSION *SubExpression; +} HII_DEPENDENCY_NOT; + +// +// Definition of HII_DEPENDENCY_CATENATE +// +typedef struct { + UINT8 Operand; + HII_DEPENDENCY_EXPRESSION *LeftStringExp; + HII_DEPENDENCY_EXPRESSION *RightStringExp; +} HII_DEPENDENCY_CATENATE; + +// +// Definition of HII_DEPENDENCY_MATCH +// +typedef struct { + UINT8 Operand; + HII_DEPENDENCY_EXPRESSION *StringExp; + HII_DEPENDENCY_EXPRESSION *PatternExp; +} HII_DEPENDENCY_MATCH; + +// +// Definition of HII_DEPENDENCY_MATCH2 +// +typedef struct { + UINT8 Operand; + EFI_GUID SyntaxType; + HII_DEPENDENCY_EXPRESSION *StringExp; + HII_DEPENDENCY_EXPRESSION *PatternExp; +} HII_DEPENDENCY_MATCH2; + +// +// Definition of HII_DEPENDENCY_MULT +// +typedef struct { + UINT8 Operand; + HII_DEPENDENCY_EXPRESSION *RightHandExp; + HII_DEPENDENCY_EXPRESSION *LeftHandExp; +} HII_DEPENDENCY_MULT; + +// +// Definition of HII_DEPENDENCY_DIV +// +typedef struct { + UINT8 Operand; + HII_DEPENDENCY_EXPRESSION *RightHandExp; // right value + HII_DEPENDENCY_EXPRESSION *LeftHandExp; // left value +} HII_DEPENDENCY_DIV; + +// +// Definition of HII_DEPENDENCY_MOD +// +typedef struct { + UINT8 Operand; + HII_DEPENDENCY_EXPRESSION *RightHandExp; // right value + HII_DEPENDENCY_EXPRESSION *LeftHandExp; // left value +} HII_DEPENDENCY_MOD; + +// +// Definition of HII_DEPENDENCY_ADD +// +typedef struct { + UINT8 Operand; + HII_DEPENDENCY_EXPRESSION *RightHandExp; // right value + HII_DEPENDENCY_EXPRESSION *LeftHandExp; // left value +} HII_DEPENDENCY_ADD; + +// +// Definition of HII_DEPENDENCY_SUBTRACT +// +typedef struct { + UINT8 Operand; + HII_DEPENDENCY_EXPRESSION *RightHandExp; // right value + HII_DEPENDENCY_EXPRESSION *LeftHandExp; // left value +} HII_DEPENDENCY_SUBTRACT; + +// +// Definition of HII_DEPENDENCY_SHIFT_LEFT +// +typedef struct { + UINT8 Operand; + HII_DEPENDENCY_EXPRESSION *RightHandExp; + HII_DEPENDENCY_EXPRESSION *LeftHandExp; +} HII_DEPENDENCY_SHIFT_LEFT; + +// +// Definition of HII_DEPENDENCY_SHIFT_RIGHT +// +typedef struct { + UINT8 Operand; + HII_DEPENDENCY_EXPRESSION *RightHandExp; + HII_DEPENDENCY_EXPRESSION *LeftHandExp; +} HII_DEPENDENCY_SHIFT_RIGHT; + +// +// Definition of HII_DEPENDENCY_GREATER_THAN +// +typedef struct { + UINT8 Operand; + HII_DEPENDENCY_EXPRESSION *RightHandExp; + HII_DEPENDENCY_EXPRESSION *LeftHandExp; +} HII_DEPENDENCY_GREATER_THAN; + +// +// Definition of HII_DEPENDENCY_GREATER_EQUAL +// +typedef struct { + UINT8 Operand; + HII_DEPENDENCY_EXPRESSION *RightHandExp; + HII_DEPENDENCY_EXPRESSION *LeftHandExp; +} HII_DEPENDENCY_GREATER_EQUAL; + +// +// Definition of HII_DEPENDENCY_LESS_THAN +// +typedef struct { + UINT8 Operand; + HII_DEPENDENCY_EXPRESSION *RightHandExp; + HII_DEPENDENCY_EXPRESSION *LeftHandExp; +} HII_DEPENDENCY_LESS_THAN; + +// +// Definition of HII_DEPENDENCY_LESS_EQUAL +// +typedef struct { + UINT8 Operand; + HII_DEPENDENCY_EXPRESSION *RightHandExp; + HII_DEPENDENCY_EXPRESSION *LeftHandExp; +} HII_DEPENDENCY_LESS_EQUAL; + +// +// Definition of HII_DEPENDENCY_EQUAL +// +typedef struct { + UINT8 Operand; + HII_DEPENDENCY_EXPRESSION *SubExpression1; + HII_DEPENDENCY_EXPRESSION *SubExpression2; +} HII_DEPENDENCY_EQUAL; + +// +// Definition of HII_DEPENDENCY_NOT_EQUAL +// +typedef struct { + UINT8 Operand; + HII_DEPENDENCY_EXPRESSION *SubExpression1; + HII_DEPENDENCY_EXPRESSION *SubExpression2; +} HII_DEPENDENCY_NOT_EQUAL; + +// +// Definition of HII_DEPENDENCY_BITWISE_AND +// +typedef struct { + UINT8 Operand; + HII_DEPENDENCY_EXPRESSION *SubExpression1; + HII_DEPENDENCY_EXPRESSION *SubExpression2; +} HII_DEPENDENCY_BITWISE_AND; + +// +// Definition of HII_DEPENDENCY_BITWISE_OR +// +typedef struct { + UINT8 Operand; + HII_DEPENDENCY_EXPRESSION *SubExpression1; + HII_DEPENDENCY_EXPRESSION *SubExpression2; +} HII_DEPENDENCY_BITWISE_OR; + +// +// Definition of HII_DEPENDENCY_AND +// +typedef struct { + UINT8 Operand; + HII_DEPENDENCY_EXPRESSION *SubExpression1; + HII_DEPENDENCY_EXPRESSION *SubExpression2; +} HII_DEPENDENCY_AND; + +// +// Definition of HII_DEPENDENCY_OR +// +typedef struct { + UINT8 Operand; + HII_DEPENDENCY_EXPRESSION *SubExpression1; + HII_DEPENDENCY_EXPRESSION *SubExpression2; +} HII_DEPENDENCY_OR; + +// +// Definition of HII_DEPENDENCY_CONDITIONAL +// +// Ternary expression +// +typedef struct { + UINT8 Operand; + HII_DEPENDENCY_EXPRESSION *CondTrueValExp; // right value + HII_DEPENDENCY_EXPRESSION *CondFalseValExp; // middle value + HII_DEPENDENCY_EXPRESSION *ConditionExp; // left value +} HII_DEPENDENCY_CONDITIONAL; + +// +// Definition of HII_DEPENDENCY_FIND +// +typedef struct { + UINT8 Operand; + UINT8 Format; + HII_DEPENDENCY_EXPRESSION *IndexExp; // right value + HII_DEPENDENCY_EXPRESSION *StringToCompWithExp; // middle value + HII_DEPENDENCY_EXPRESSION *StringToSearchExp; // left value +} HII_DEPENDENCY_FIND; + +// +// Definition of HII_DEPENDENCY_MID +// +typedef struct { + UINT8 Operand; + HII_DEPENDENCY_EXPRESSION *LengthExp; // right value + HII_DEPENDENCY_EXPRESSION *IndexExp; // middle value + HII_DEPENDENCY_EXPRESSION *StringOrBufferExp; // left value +} HII_DEPENDENCY_MID; + +// +// Definition of HII_DEPENDENCY_TOKEN +// +typedef struct { + UINT8 Operand; + HII_DEPENDENCY_EXPRESSION *IndexExp; // right value + HII_DEPENDENCY_EXPRESSION *DelimiterExp; // middle value + HII_DEPENDENCY_EXPRESSION *StringToSearchExp; // left value +} HII_DEPENDENCY_TOKEN; + +// +// Definition of HII_DEPENDENCY_SPAN +// +typedef struct { + UINT8 Operand; + UINT8 Flags; + HII_DEPENDENCY_EXPRESSION *IndeExp; // right value + HII_DEPENDENCY_EXPRESSION *CharsetExp; // middle value + HII_DEPENDENCY_EXPRESSION *StringToSearchExp; // left value +} HII_DEPENDENCY_SPAN; + +// +// Map expression +// +typedef struct { + HII_DEPENDENCY_EXPRESSION *MatchExp; + HII_DEPENDENCY_EXPRESSION *ReturnExp; +} HII_DEPENDENCY_EXPRESSION_PAIR; + +// +// Definition of HII_DEPENDENCY_MAP +// +typedef struct { + UINT8 Operand; + HII_DEPENDENCY_EXPRESSION *SubExp; + HII_DEPENDENCY_EXPRESSION_PAIR *ExpPair; + UINT8 ExpPairNo; +} HII_DEPENDENCY_MAP; + +// +// Definition of HII_DEPENDENCY_EXPRESSION +// +union _HII_DEPENDENCY_EXPRESSION { + // + // Constant + // + HII_EXPRESSION_CONSTANT ContantExp; + // + // build-in expression + // + HII_DEPENDENCY_DUP DupExp; + HII_DEPENDENCY_EQ_ID_VAL EqIdValExp; + HII_DEPENDENCY_EQ_ID_ID EqIdIdExp; + HII_DEPENDENCY_EQ_ID_VAL_LIST EqIdListExp; + HII_DEPENDENCY_QUESTION_REF1 QuestionRef1Exp; + HII_DEPENDENCY_RULE_REF RuleRefExp; + HII_DEPENDENCY_STRING_REF1 StringRef1Exp; + HII_DEPENDENCY_THIS ThisExp; + HII_DEPENDENCY_SECURITY SecurityExp; + HII_DEPENDENCY_GET GetExp; + + // + //unary expression + // + HII_DEPENDENCY_LENGTH LengthExp; + HII_DEPENDENCY_BITWISE_NOT BitWiseNotExp; + HII_DEPENDENCY_STRING_REF2 StringRef2Exp; + HII_DEPENDENCY_QUESTION_REF2 QuestionRef2Exp; + HII_DEPENDENCY_QUESTION_REF3 QuestionRef3Exp; + HII_DEPENDENCY_TO_BOOLEAN ToBooleanExp; + HII_DEPENDENCY_TO_STRING ToStringExp; + HII_DEPENDENCY_TO_UINT ToUintExp; + HII_DEPENDENCY_TO_UPPER ToUpperExp; + HII_DEPENDENCY_TO_LOWER ToLowerExp; + HII_DEPENDENCY_SET SetExp; + HII_DEPENDENCY_NOT NotExp; + + // + // Binary expression + // + HII_DEPENDENCY_CATENATE CatenateExp; + HII_DEPENDENCY_MATCH MatchExp; + HII_DEPENDENCY_MATCH2 Match2Exp; + HII_DEPENDENCY_MULT MultExp; + HII_DEPENDENCY_DIV DivExp; + HII_DEPENDENCY_MOD ModExp; + HII_DEPENDENCY_ADD AddExp; + HII_DEPENDENCY_SUBTRACT SubtractExp; + HII_DEPENDENCY_SHIFT_LEFT ShiftLeftExp; + HII_DEPENDENCY_SHIFT_RIGHT ShiftRightExp; + HII_DEPENDENCY_GREATER_THAN GreaterThanExp; + HII_DEPENDENCY_GREATER_EQUAL GreaterEqualExp; + HII_DEPENDENCY_LESS_THAN LessThanExp; + HII_DEPENDENCY_LESS_EQUAL LessEqualExp; + HII_DEPENDENCY_EQUAL EqualExp; + HII_DEPENDENCY_NOT_EQUAL NotEqualExp; + HII_DEPENDENCY_BITWISE_AND BitwiseAndExp; + HII_DEPENDENCY_BITWISE_OR BitwiseOrExp; + HII_DEPENDENCY_AND AndExp; + HII_DEPENDENCY_OR OrExp; + + // + // ternary expression + // + HII_DEPENDENCY_CONDITIONAL ConditionalExp; + HII_DEPENDENCY_FIND FindExp; + HII_DEPENDENCY_MID MidExp; + HII_DEPENDENCY_TOKEN TokenExp; + HII_DEPENDENCY_SPAN SpanExp; + HII_DEPENDENCY_MAP MapExp; +}; + +// +// Definition of HII_EXPRESSION_OPCODE +// +typedef struct { + + UINTN Signature; + LIST_ENTRY Link; + UINT8 Operand; + HII_EXPRESSION_OPCODE_EXTRA ExtraData; + LIST_ENTRY MapExpressionList; // nested expressions inside of Map opcode. +} HII_EXPRESSION_OPCODE; + +#define HII_EXPRESSION_OPCODE_SIGNATURE SIGNATURE_32 ('E', 'X', 'O', 'P') +#define HII_EXPRESSION_OPCODE_FROM_LINK(a) CR (a, HII_EXPRESSION_OPCODE, Link, HII_EXPRESSION_OPCODE_SIGNATURE) + +// +// Definition of HII_EXPRESSION +// +typedef struct { + + UINTN Signature; + LIST_ENTRY Link; + UINT8 Type; // Type for this expression + EFI_IFR_OP_HEADER *OpCode; // Save the opcode buffer. + LIST_ENTRY OpCodeListHead; // OpCodes consist of this expression (HII_EXPRESSION_OPCODE) + HII_DEPENDENCY_EXPRESSION *RootDepdencyExp; // Expression OpCodes tree layout to describe dependency of this expression. + + union { + UINT8 RuleId; // For EFI_IFR_RULE only + EFI_STRING_ID Error; // For EFI_IFR_NO_SUBMIT_IF, EFI_IFR_INCONSISTENT_IF only + + struct { + EFI_STRING_ID WarningIfError; + UINT8 TimeOut; + } WarningIfData; + + } ExtraData; + + EFI_HII_VALUE Result; // Expression evaluation result + +} HII_EXPRESSION; + +#define HII_EXPRESSION_SIGNATURE SIGNATURE_32 ('F', 'E', 'X', 'P') +#define HII_EXPRESSION_FROM_LINK(a) CR (a, HII_EXPRESSION, Link, HII_EXPRESSION_SIGNATURE) + +// +// Definition of HII_EXPRESSION_LIST +// +typedef struct { + UINTN Signature; + UINTN Count; + HII_EXPRESSION *Expression[1]; // Array[Count] of expressions +} HII_EXPRESSION_LIST; + +#define HII_EXPRESSION_LIST_SIGNATURE SIGNATURE_32 ('F', 'E', 'X', 'R') + +// +// Definition of HII_STATEMENT_VALUE +// +typedef struct { + + // + // HII Data Type + // + UINT8 Type; + EFI_IFR_TYPE_VALUE Value; + // + // Buffer Data and Length if Type is EFI_IFR_TYPE_BUFFER or EFI_IFR_TYPE_STRING + // + UINT8 *Buffer; + UINT16 BufferLen; + UINT8 BufferValueType; // Data type for buffer internal data, currently only for orderedlist + +} HII_STATEMENT_VALUE; + +// +// Default value +// +typedef struct { + UINTN Signature; + LIST_ENTRY Link; + + UINT16 DefaultId; + HII_STATEMENT_VALUE Value; // Default value + + HII_EXPRESSION *ValueExpression; // Not-NULL indicates default value is provided by EFI_IFR_VALUE +} HII_QUESTION_DEFAULT; + +#define HII_QUESTION_DEFAULT_SIGNATURE SIGNATURE_32 ('Q', 'D', 'F', 'T') +#define HII_QUESTION_DEFAULT_FROM_LINK(a) CR (a, HII_QUESTION_DEFAULT, Link, HII_QUESTION_DEFAULT_SIGNATURE) + +#define HII_QUESTION_OPTION_SIGNATURE SIGNATURE_32 ('Q', 'O', 'P', 'T') + +// +// Option value +// +typedef struct { + UINTN Signature; + LIST_ENTRY Link; + + EFI_IFR_ONE_OF_OPTION *OpCode; // OneOfOption Data + + EFI_STRING_ID Text; + UINT8 Flags; + HII_STATEMENT_VALUE Value; + EFI_IMAGE_ID ImageId; + + HII_EXPRESSION_LIST *SuppressExpression; // Non-NULL indicates nested inside of SuppressIf +} HII_QUESTION_OPTION; + +#define HII_QUESTION_OPTION_FROM_LINK(a) CR (a, HII_QUESTION_OPTION, Link, HII_QUESTION_OPTION_SIGNATURE) + +// +//class of default +// +typedef struct { + UINTN Signature; + LIST_ENTRY Link; + + UINT16 DefaultId; + EFI_STRING_ID DefaultName; +} HII_FORMSET_DEFAULTSTORE; + +#define HII_FORMSET_DEFAULTSTORE_SIGNATURE SIGNATURE_32 ('F', 'D', 'F', 'S') +#define HII_FORMSET_DEFAULTSTORE_FROM_LINK(a) CR (a, HII_FORMSET_DEFAULTSTORE, Link, HII_FORMSET_DEFAULTSTORE_SIGNATURE) + +// +// Definition of HII_STATEMENT_EXTRA +// +typedef union { + + UINT8 Flags; + EFI_STRING_ID TextTwo; + EFI_DEFAULT_ID DefaultId; + EFI_STRING_ID QuestionConfig; + EFI_GUID Guid; + + struct { + UINT8 Flags; + UINT64 Minimum; // for EFI_IFR_ONE_OF/EFI_IFR_NUMERIC, it's Min/Max value + UINT64 Maximum; // for EFI_IFR_STRING/EFI_IFR_PASSWORD, it's Min/Max length + UINT64 Step; + EFI_GUID Guid; + } NumData; + + struct { + UINT8 Flags; + UINT8 MaxContainers; // for EFI_IFR_ORDERED_LIST + } OrderListData; + + struct { + UINT8 Flags; + UINT8 MinSize; + UINT8 MaxSize; + } StrData; + + struct { + UINT16 MinSize; + UINT16 MaxSize; + } PwdData; + +} HII_STATEMENT_EXTRA; + +// +// Statement (Question) +// +typedef struct _HII_STATEMENT HII_STATEMENT; +struct _HII_STATEMENT{ + UINTN Signature; + LIST_ENTRY Link; + + UINT8 Operand; // The operand (first byte) of this Statement or Question + EFI_IFR_OP_HEADER *OpCode; + + // + // Statement Header + // + EFI_STRING_ID Prompt; + EFI_STRING_ID Help; + + // + // Question Header + // + EFI_QUESTION_ID QuestionId; // Question id, the value of zero is reserved + EFI_VARSTORE_ID VarStoreId; // VarStore id, a value of zero indicates no variable storage + HII_VAR_STORE_INFO VarStoreInfo; // VarStoreInfoIf VarStoreId refers to Buffer Storage (EFI_IFR_VARSTORE or EFI_IFR_VARSTORE_EFI), then VarStoreInfo contains a 16-bit Buffer Storage offset (VarOffset). + // If VarStoreId refers to Name/Value Storage (EFI_IFR_VARSTORE_NAME_VALUE), then VarStoreInfo contains the String ID of the name (VarName) for this name/value pair. + UINT8 QuestionFlags; // The flag of this Question.(Readonly, reset required, calback attribute....) + + BOOLEAN QuestionReferToBitField; // Whether the question is stored in a bit field. + UINT16 StorageWidth; // The storage width of this Question. + UINT16 BitStorageWidth; // The Storage width of this Question in bit level. + UINT16 BitVarOffset; // The storahe offset of this Question in bit level. + CHAR16 *VariableName; // Name/Value or EFI Variable name + CHAR16 *BlockName; // Buffer storage block name: "OFFSET=...WIDTH=..." + + HII_FORMSET_STORAGE *Storage; // Point to the storage that store this question. + HII_STATEMENT_EXTRA ExtraData; + + BOOLEAN Locked; // Whether this statement is locked. + + HII_STATEMENT_VALUE Value; + + // + // Get from IFR parsing + // + + HII_STATEMENT *ParentStatement; // Parent Statement of current statement. + HII_EXPRESSION_LIST *ExpressionList; // nesting inside of GrayOutIf/DisableIf/SuppressIf + HII_EXPRESSION *ValueExpression; // nested EFI_IFR_VALUE, provide Question value and indicate Question is ReadOnly + + EFI_IMAGE_ID ImageId; // nested EFI_IFR_IMAGE + UINT8 RefreshInterval; // nested EFI_IFR_REFRESH, refresh interval(in seconds) for Question value, 0 means no refresh + + LIST_ENTRY DefaultListHead; // nested EFI_IFR_DEFAULT list (HII_QUESTION_DEFAULT), provide default values + LIST_ENTRY OptionListHead; // nested EFI_IFR_ONE_OF_OPTION list (HII_QUESTION_OPTION) + LIST_ENTRY InconsistentListHead; // nested inconsistent expression list (HII_EXPRESSION) + LIST_ENTRY NoSubmitListHead; // nested nosubmit expression list (HII_EXPRESSION) + LIST_ENTRY WarningListHead; // nested warning expression list (HII_EXPRESSION) + + HII_EXPRESSION *ReadExpression; // nested EFI_IFR_READ, provide this question value by read expression. + HII_EXPRESSION *WriteExpression; // nested EFI_IFR_WRITE, evaluate write expression after this question value is set. +}; + +#define HII_STATEMENT_SIGNATURE SIGNATURE_32 ('H', 'S', 'T', 'A') +#define HII_STATEMENT_FROM_LINK(a) CR (a, HII_STATEMENT, Link, HII_STATEMENT_SIGNATURE) + +// +// Form +// +#define STANDARD_MAP_FORM_TYPE 0x01 + +typedef struct { + + UINTN Signature; + LIST_ENTRY Link; + + UINT16 FormId; // FormId of normal form or formmap form. + EFI_STRING_ID FormTitle; // FormTile of normal form, or FormMapMethod title of formmap form. + UINT16 FormType; // Specific form type for the different form. + + EFI_IMAGE_ID ImageId; // The image id. + + BOOLEAN ModalForm; // Whether this is a modal form. + BOOLEAN Locked; // Whether this form is locked. + EFI_GUID RefreshGuid; // Form refresh event guid. + + LIST_ENTRY StatementListHead; // List of Statements and Questions (HII_STATEMENT) + LIST_ENTRY ConfigRequestHead; // List of configreques for all storage. + LIST_ENTRY RuleListHead; // nesed EFI_IFR_RULE list, pre-defined expressions attached to the form. + HII_EXPRESSION_LIST *SuppressExpression; // nesting inside of SuppressIf + +} HII_FORM; + + +#define HII_FORM_SIGNATURE SIGNATURE_32 ('F', 'F', 'R', 'M') +#define HII_FORM_FROM_LINK(a) CR (a, HII_FORM, Link, HII_FORM_SIGNATURE) + +// +// FormSet +// +typedef struct { + UINTN Signature; + LIST_ENTRY Link; + + EFI_HII_HANDLE HiiHandle; // Unique id for formset, HII Hanlde of this FormSet package. + EFI_HANDLE DriverHandle; // EFI_HANDLE which was registered with the package list in NewPackageList(). + EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess; // ConfigAccess Protocol associated with this HiiPackageList + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + UINTN IfrBinaryLength; // Ifr binary data length of this formset. + UINT8 *IfrBinaryData; // Point to the Ifr binary data. + + EFI_GUID Guid; // Formset Guid. + EFI_STRING_ID FormSetTitle; // String Id of Formset title. + EFI_STRING_ID Help; // String Id of Formset title. + + UINT8 NumberOfClassGuid; // Class Guid name + EFI_GUID ClassGuid[3]; // Up to three ClassGuid + + EFI_IMAGE_ID ImageId; // The image id. + + LIST_ENTRY StatementListOSF; // Statement list out side of the form. + LIST_ENTRY StorageListHead; // Storage list (HII_FORMSET_STORAGE) + LIST_ENTRY DefaultStoreListHead; // DefaultStore list (HII_FORMSET_DEFAULTSTORE) + LIST_ENTRY FormListHead; // Form list (HII_FORM_BROWSER_FORM) + +} HII_FORMSET; + + +#define HII_FORMSET_SIGNATURE SIGNATURE_32 ('H', 'I', 'F', 'S') +#define HII_FORMSET_FROM_LINK(a) CR (a, HII_FORMSET, Link, HII_FORMSET_SIGNATURE) + +// +// Get/set question value from/to. +// +typedef enum { + GetSetValueWithBuffer = 0, // Get/Set question value from/to buffer in the storage. + GetSetValueWithHiiDriver, // Get/Set question value from/to hii driver. + GetSetValueWithBoth, // Compare the editbuffer with buffer for this question, not use the question value. + GetSetValueWithMax // Invalid value. +} GET_SET_QUESTION_VALUE_WITH; + +/** + Initialize the internal data structure of a FormSet. + + @param Handle PackageList Handle + @param FormSetGuid On input, GUID or class GUID of a formset. If not + specified (NULL or zero GUID), take the first + FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID + found in package list. + On output, GUID of the formset found(if not NULL). + @param FormSet FormSet data structure. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_FOUND The specified FormSet could not be found. + +**/ +EFI_STATUS +CreateFormSetFromHiiHandle ( + IN EFI_HII_HANDLE Handle, + IN OUT EFI_GUID *FormSetGuid, + OUT HII_FORMSET *FormSet + ); + +/** + Initialize a Formset and get current setting for Questions. + + @param FormSet FormSet data structure. + +**/ +VOID +InitializeFormSet ( + IN OUT HII_FORMSET *FormSet + ); + +/** + Free resources allocated for a FormSet. + + @param FormSet Pointer of the FormSet + +**/ +VOID +DestroyFormSet ( + IN OUT HII_FORMSET *FormSet + ); + +/** + Save Question Value to the memory, but not to storage. + + @param FormSet FormSet data structure. + @param Form Form data structure. + @param Question Pointer to the Question. + @param QuestionValue New Question Value to be set. + + @retval EFI_SUCCESS The question value has been set successfully. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + +**/ +EFI_STATUS +SetQuestionValue ( + IN HII_FORMSET *FormSet, + IN HII_FORM *Form, + IN OUT HII_STATEMENT *Question, + IN HII_STATEMENT_VALUE *QuestionValue + ); + +/** + Get Question's current Value from storage. + + @param FormSet FormSet data structure. + @param Form Form data structure. + @param Question Question to be initialized. + + @return the current Question Value in storage if success. + @return NULL if Question is not found or any error occurs. + +**/ +HII_STATEMENT_VALUE * +RetrieveQuestion ( + IN HII_FORMSET *FormSet, + IN HII_FORM *Form, + IN OUT HII_STATEMENT *Question + ); + +/** + Get Question's current Value. + + @param[in] FormSet FormSet data structure. + @param[in] Form Form data structure. + @param[out] Question Question to be initialized. + @param[in] GetValueFrom Where to get value, may from editbuffer, buffer or hii driver. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Formset, Form or Question is NULL. + +**/ +EFI_STATUS +GetQuestionValue ( + IN HII_FORMSET *FormSet, + IN HII_FORM *Form, + IN OUT HII_STATEMENT *Question, + IN GET_SET_QUESTION_VALUE_WITH GetValueFrom + ); + +/** + Submit data for a form. + + @param FormSet FormSet which contains the Form. + @param Form Form to submit. + + @retval EFI_SUCCESS The function completed successfully. + @retval Others Other errors occur. + +**/ +EFI_STATUS +SubmitForm ( + IN HII_FORMSET *FormSet, + IN HII_FORM *Form + ); + +/** + Evaluate the result of a HII expression. + + If Expression is NULL, then ASSERT. + + @param FormSet FormSet associated with this expression. + @param Form Form associated with this expression. + @param Expression Expression to be evaluated. + + @retval EFI_SUCCESS The expression evaluated successfuly + @retval EFI_NOT_FOUND The Question which referenced by a QuestionId + could not be found. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the + stack. + @retval EFI_ACCESS_DENIED The pop operation underflowed the stack + @retval EFI_INVALID_PARAMETER Syntax error with the Expression + +**/ +EFI_STATUS +EvaluateHiiExpression ( + IN HII_FORMSET *FormSet, + IN HII_FORM *Form, + IN OUT HII_EXPRESSION *Expression + ); + +/** + Retrieve dependencies within an expression. These dependencies can express how + this expression will be evaluated. + + @param Expression Expression to retrieve dependencies. + + @retval EFI_SUCCESS The dependencies were successfully retrieved. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory. + +**/ +EFI_STATUS +GetHiiExpressionDependency ( + IN HII_EXPRESSION *Expression + ); + +/** + Evaluate the result of a HII expression. + + If Expression is NULL, then ASSERT. + + @param FormSet FormSet associated with this expression. + @param Form Form associated with this expression. + @param Expression Expression to be evaluated. + + @retval EFI_SUCCESS The expression evaluated successfuly + @retval EFI_NOT_FOUND The Question which referenced by a QuestionId + could not be found. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the + stack. + @retval EFI_ACCESS_DENIED The pop operation underflowed the stack + @retval EFI_INVALID_PARAMETER Syntax error with the Expression + +**/ +EFI_STATUS +HpEvaluateHiiExpression ( + IN HII_FORMSET *FormSet, + IN HII_FORM *Form, + IN OUT HII_EXPRESSION *Expression + ); + +#endif // _HII_UTILITY_LIB_ diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiExpression.h b/RedfishPkg/Library/HiiUtilityLib/HiiExpression.h new file mode 100644 index 00000000000..e96c07b4de2 --- /dev/null +++ b/RedfishPkg/Library/HiiUtilityLib/HiiExpression.h @@ -0,0 +1,190 @@ +/** @file + Definitinos of RedfishPlatformConfigLib + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef HII_EXPRESSION_H_ +#define HII_EXPRESSION_H_ + +#include + +/** + Get the expression list count. + + @param[in] Level Which type this expression belong to. Form, + statement or option? + + @retval >=0 The expression count + @retval -1 Input parameter error. + +**/ +INTN +GetConditionalExpressionCount ( + IN EXPRESS_LEVEL Level + ); + +/** + Get the expression Buffer pointer. + + @param[in] Level Which type this expression belong to. Form, + statement or option? + + @retval The start pointer of the expression buffer or NULL. + +**/ +HII_EXPRESSION ** +GetConditionalExpressionList ( + IN EXPRESS_LEVEL Level + ); + +/** + Push the expression options onto the Stack. + + @param[in] Pointer Pointer to the current expression. + @param[in] Level Which type this expression belong to. Form, + statement or option? + + @retval EFI_SUCCESS The value was pushed onto the stack. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. + +**/ +EFI_STATUS +PushConditionalExpression ( + IN HII_EXPRESSION *Pointer, + IN EXPRESS_LEVEL Level + ); + +/** + Pop the expression options from the Stack + + @param[in] Level Which type this expression belong to. Form, + statement or option? + + @retval EFI_SUCCESS The value was pushed onto the stack. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. + +**/ +EFI_STATUS +PopConditionalExpression ( + IN EXPRESS_LEVEL Level + ); + +/** + Reset stack pointer to begin of the stack. + +**/ +VOID +ResetCurrentExpressionStack ( + VOID + ); + +/** + Push current expression onto the Stack + + @param[in] Pointer Pointer to current expression. + + @retval EFI_SUCCESS The value was pushed onto the stack. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. + +**/ +EFI_STATUS +PushCurrentExpression ( + IN VOID *Pointer + ); + +/** + Pop current expression from the Stack + + @param[in] Pointer Pointer to current expression to be pop. + + @retval EFI_SUCCESS The value was pushed onto the stack. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. + +**/ +EFI_STATUS +PopCurrentExpression ( + OUT VOID **Pointer + ); + +/** + Reset stack pointer to begin of the stack. + +**/ +VOID +ResetMapExpressionListStack ( + VOID + ); + +/** + Push the list of map expression onto the Stack + + @param[in] Pointer Pointer to the list of map expression to be pushed. + + @retval EFI_SUCCESS The value was pushed onto the stack. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. + +**/ +EFI_STATUS +PushMapExpressionList ( + IN VOID *Pointer + ); + +/** + Pop the list of map expression from the Stack + + @param[in] Pointer Pointer to the list of map expression to be pop. + + @retval EFI_SUCCESS The value was pushed onto the stack. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. + +**/ +EFI_STATUS +PopMapExpressionList ( + OUT VOID **Pointer + ); + +/** + Reset stack pointer to begin of the stack. + +**/ +VOID +ResetScopeStack ( + VOID + ); + +/** + Push an Operand onto the Stack + + @param[in] Operand Operand to push. + + @retval EFI_SUCCESS The value was pushed onto the stack. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the + stack. + +**/ +EFI_STATUS +PushScope ( + IN UINT8 Operand + ); + +/** + Pop an Operand from the Stack + + @param[out] Operand Operand to pop. + + @retval EFI_SUCCESS The value was pushed onto the stack. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the + stack. + +**/ +EFI_STATUS +PopScope ( + OUT UINT8 *Operand + ); + +#endif diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiInternal.h b/RedfishPkg/Library/HiiUtilityLib/HiiInternal.h new file mode 100644 index 00000000000..1106896dc46 --- /dev/null +++ b/RedfishPkg/Library/HiiUtilityLib/HiiInternal.h @@ -0,0 +1,371 @@ +/** @file + Definitinos of RedfishPlatformConfigLib + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef HII_INTERNAL_H_ +#define HII_INTERNAL_H_ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "HiiExpression.h" +#include + +typedef struct { + + UINTN Signature; + LIST_ENTRY Link; + + CHAR16 *ConfigRequest; // = + + CHAR16 *ConfigAltResp; // Alt config response string for this ConfigRequest. + UINTN ElementCount; // Number of in the + UINTN SpareStrLen; + CHAR16 *RestoreConfigRequest; // When submit form fail, the element need to be restored + CHAR16 *SyncConfigRequest; // When submit form fail, the element need to be synced + + HII_FORMSET_STORAGE *Storage; +} HII_FORM_CONFIG_REQUEST; + +#define HII_FORM_CONFIG_REQUEST_SIGNATURE SIGNATURE_32 ('F', 'C', 'R', 'S') +#define HII_FORM_CONFIG_REQUEST_FROM_LINK(a) CR (a, HII_FORM_CONFIG_REQUEST, Link, HII_FORM_CONFIG_REQUEST_SIGNATURE) + +// Incremental string lenght of ConfigRequest +// +#define CONFIG_REQUEST_STRING_INCREMENTAL 1024 + +/** + Allocate new memory and then copy the Unicode string Source to Destination. + + @param Dest Location to copy string + @param Src String to copy + +**/ +VOID +NewStringCpy ( + IN OUT CHAR16 **Dest, + IN CHAR16 *Src + ); + +/** + Set Value of given Name in a NameValue Storage. + + @param Storage The NameValue Storage. + @param Name The Name. + @param Value The Value to set. + @param ReturnNode The node use the input name. + + @retval EFI_SUCCESS Value found for given Name. + @retval EFI_NOT_FOUND No such Name found in NameValue storage. + +**/ +EFI_STATUS +SetValueByName ( + IN HII_FORMSET_STORAGE *Storage, + IN CHAR16 *Name, + IN CHAR16 *Value, + OUT HII_NAME_VALUE_NODE **ReturnNode + ); + +/** + Get bit field value from the buffer and then set the value for the question. + Note: Data type UINT32 can cover all the bit field value. + + @param Question The question refer to bit field. + @param Buffer Point to the buffer which the question value get from. + @param QuestionValue The Question Value retrieved from Bits. + +**/ +VOID +GetBitsQuestionValue ( + IN HII_STATEMENT *Question, + IN UINT8 *Buffer, + OUT HII_STATEMENT_VALUE *QuestionValue + ); + +/** + Set bit field value to the buffer. + Note: Data type UINT32 can cover all the bit field value. + + @param Question The question refer to bit field. + @param Buffer Point to the buffer which the question value set to. + @param Value The bit field value need to set. + +**/ +VOID +SetBitsQuestionValue ( + IN HII_STATEMENT *Question, + IN OUT UINT8 *Buffer, + IN UINT32 Value + ); + +/** + Convert the buffer value to HiiValue. + + @param Question The question. + @param Value Unicode buffer save the question value. + @param QuestionValue The Question Value retrieved from Buffer. + + @retval Status whether convert the value success. + +**/ +EFI_STATUS +BufferToValue ( + IN HII_STATEMENT *Question, + IN CHAR16 *Value, + OUT HII_STATEMENT_VALUE *QuestionValue + ); + +/** + Get the string based on the StringId and HII Package List Handle. + + @param Token The String's ID. + @param HiiHandle The package list in the HII database to search for + the specified string. + + @return The output string. + +**/ +CHAR16* +GetToken ( + IN EFI_STRING_ID Token, + IN EFI_HII_HANDLE HiiHandle + ); + +/** + Converts the unicode character of the string from uppercase to lowercase. + This is a internal function. + + @param ConfigString String to be converted + +**/ +VOID +EFIAPI +HiiToLower ( + IN EFI_STRING ConfigString + ); + +/** + Evaluate if the result is a non-zero value. + + @param Result The result to be evaluated. + + @retval TRUE It is a non-zero value. + @retval FALSE It is a zero value. + +**/ +BOOLEAN +IsTrue ( + IN EFI_HII_VALUE *Result + ); + +/** + Set a new string to string package. + + @param[in] String A pointer to the Null-terminated Unicode string + to add or update in the String Package associated + with HiiHandle. + @param[in] HiiHandle A handle that was previously registered in the + HII Database. + + @return the Id for this new string. + +**/ +EFI_STRING_ID +NewString ( + IN CHAR16 *String, + IN EFI_HII_HANDLE HiiHandle + ); + +/** + Perform nosubmitif check for a Form. + + @param FormSet FormSet data structure. + @param Form Form data structure. + @param Question The Question to be validated. + + @retval EFI_SUCCESS Form validation pass. + @retval other Form validation failed. + +**/ +EFI_STATUS +ValidateNoSubmit ( + IN HII_FORMSET *FormSet, + IN HII_FORM *Form, + IN HII_STATEMENT *Question + ); + +/** + Perform NoSubmit check for each Form in FormSet. + + @param FormSet FormSet data structure. + @param CurrentForm Current input form data structure. + @param Statement The statement for this check. + + @retval EFI_SUCCESS Form validation pass. + @retval other Form validation failed. + +**/ +EFI_STATUS +NoSubmitCheck ( + IN HII_FORMSET *FormSet, + IN OUT HII_FORM **CurrentForm, + OUT HII_STATEMENT **Statement + ); + + +/** + Convert setting of Buffer Storage or NameValue Storage to . + + @param Storage The Storage to be conveted. + @param ConfigResp The returned . + @param ConfigRequest The ConfigRequest string. + + @retval EFI_SUCCESS Convert success. + @retval EFI_INVALID_PARAMETER Incorrect storage type. + +**/ +EFI_STATUS +StorageToConfigResp ( + IN HII_FORMSET_STORAGE *Storage, + IN CHAR16 **ConfigResp, + IN CHAR16 *ConfigRequest + ); + + +/** + Convert to settings in Buffer Storage or NameValue Storage. + + @param Storage The Storage to receive the settings. + @param ConfigResp The to be converted. + + @retval EFI_SUCCESS Convert success. + @retval EFI_INVALID_PARAMETER Incorrect storage type. + +**/ +EFI_STATUS +ConfigRespToStorage ( + IN HII_FORMSET_STORAGE *Storage, + IN CHAR16 *ConfigResp + ); + +/** + Fetch the Ifr binary data of a FormSet. + + @param Handle PackageList Handle + @param FormSetGuid On input, GUID or class GUID of a formset. If not + specified (NULL or zero GUID), take the first + FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID + found in package list. + On output, GUID of the formset found(if not NULL). + @param BinaryLength The length of the FormSet IFR binary. + @param BinaryData The buffer designed to receive the FormSet. + + @retval EFI_SUCCESS Buffer filled with the requested FormSet. + BufferLength was updated. + @retval EFI_INVALID_PARAMETER The handle is unknown. + @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot + be found with the requested FormId. + +**/ +EFI_STATUS +GetIfrBinaryData ( + IN EFI_HII_HANDLE Handle, + IN OUT EFI_GUID *FormSetGuid, + OUT UINTN *BinaryLength, + OUT UINT8 **BinaryData + ); + +/** + Fill storage with settings requested from Configuration Driver. + + @param FormSet FormSet data structure. + @param Storage Buffer Storage. + +**/ +VOID +LoadStorage ( + IN HII_FORMSET *FormSet, + IN HII_FORMSET_STORAGE *Storage + ); + +/** + Free resources of a Form. + + @param FormSet Pointer of the FormSet + @param Form Pointer of the Form. + +**/ +VOID +DestroyForm ( + IN HII_FORMSET *FormSet, + IN OUT HII_FORM *Form + ); + +/** + Get formset storage based on the input varstoreid info. + + @param FormSet Pointer of the current FormSet. + @param VarStoreId Varstore ID info. + + @return Pointer to a HII_FORMSET_STORAGE data structure. + +**/ +HII_FORMSET_STORAGE * +GetFstStgFromVarId ( + IN HII_FORMSET *FormSet, + IN EFI_VARSTORE_ID VarStoreId + ); + +/** + Zero extend integer/boolean/date/time to UINT64 for comparing. + + @param Value HII Value to be converted. + +**/ +VOID +ExtendValueToU64 ( + IN HII_STATEMENT_VALUE *Value + ); + +/** + Parse opcodes in the formset IFR binary. + + @param FormSet Pointer of the FormSet data structure. + + @retval EFI_SUCCESS Opcode parse success. + @retval Other Opcode parse fail. + +**/ +EFI_STATUS +ParseOpCodes ( + IN HII_FORMSET *FormSet + ); + +#endif // _HII_INTERNAL_H_ diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiExpression.c b/RedfishPkg/Library/HiiUtilityLib/HiiExpression.c new file mode 100644 index 00000000000..7111b40acf0 --- /dev/null +++ b/RedfishPkg/Library/HiiUtilityLib/HiiExpression.c @@ -0,0 +1,1367 @@ +/** @file + Definitinos of RedfishPlatformConfigLib + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include "HiiInternal.h" + +// +// Global stack used to evaluate boolean expresions +// +EFI_HII_VALUE *mOpCodeScopeStack = NULL; +EFI_HII_VALUE *mOpCodeScopeStackEnd = NULL; +EFI_HII_VALUE *mOpCodeScopeStackPointer = NULL; + +// +// Stack used for Suppressif/grayoutif/dusableif expression list. +// +HII_EXPRESSION **mFormExpressionStack = NULL; +HII_EXPRESSION **mFormExpressionEnd = NULL; +HII_EXPRESSION **mFormExpressionPointer = NULL; + +HII_EXPRESSION **mStatementExpressionStack = NULL; +HII_EXPRESSION **mStatementExpressionEnd = NULL; +HII_EXPRESSION **mStatementExpressionPointer = NULL; + +HII_EXPRESSION **mOptionExpressionStack = NULL; +HII_EXPRESSION **mOptionExpressionEnd = NULL; +HII_EXPRESSION **mOptionExpressionPointer = NULL; + +// +// Stack used for the sub expresion in map expression. +// +EFI_HII_VALUE *mCurrentExpressionStack = NULL; +EFI_HII_VALUE *mCurrentExpressionEnd = NULL; +EFI_HII_VALUE *mCurrentExpressionPointer = NULL; + +// +// Stack used for the map expression list. +// +EFI_HII_VALUE *mMapExpressionListStack = NULL; +EFI_HII_VALUE *mMapExpressionListEnd = NULL; +EFI_HII_VALUE *mMapExpressionListPointer = NULL; + +// +// Stack used for dependency expression. +// +HII_DEPENDENCY_EXPRESSION **mExpressionDependencyStack = NULL; +HII_DEPENDENCY_EXPRESSION **mExpressionDependencyEnd = NULL; +HII_DEPENDENCY_EXPRESSION **mExpressionDependencyPointer = NULL; + +#define EXPRESSION_STACK_SIZE_INCREMENT 0x100 + +/** + Grow size of the stack. + + This is an internal function. + + @param Stack On input: old stack; On output: new stack + @param StackPtr On input: old stack pointer; On output: new stack + pointer + @param StackEnd On input: old stack end; On output: new stack end + + @retval EFI_SUCCESS Grow stack success. + @retval EFI_OUT_OF_RESOURCES No enough memory for stack space. + +**/ +EFI_STATUS +GrowStack ( + IN OUT EFI_HII_VALUE **Stack, + IN OUT EFI_HII_VALUE **StackPtr, + IN OUT EFI_HII_VALUE **StackEnd + ) +{ + UINTN Size; + EFI_HII_VALUE *NewStack; + + Size = EXPRESSION_STACK_SIZE_INCREMENT; + if (*StackPtr != NULL) { + Size = Size + (*StackEnd - *Stack); + } + + NewStack = AllocatePool (Size * sizeof (EFI_HII_VALUE)); + if (NewStack == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + if (*StackPtr != NULL) { + // + // Copy from Old Stack to the New Stack + // + CopyMem ( + NewStack, + *Stack, + (*StackEnd - *Stack) * sizeof (EFI_HII_VALUE) + ); + + // + // Free The Old Stack + // + FreePool (*Stack); + } + + // + // Make the Stack pointer point to the old data in the new stack + // + *StackPtr = NewStack + (*StackPtr - *Stack); + *Stack = NewStack; + *StackEnd = NewStack + Size; + + return EFI_SUCCESS; +} + + +/** + Push an element onto the Boolean Stack. + + @param Stack On input: old stack; On output: new stack + @param StackPtr On input: old stack pointer; On output: new stack + pointer + @param StackEnd On input: old stack end; On output: new stack end + @param Data Data to push. + + @retval EFI_SUCCESS Push stack success. + +**/ +EFI_STATUS +PushStack ( + IN OUT EFI_HII_VALUE **Stack, + IN OUT EFI_HII_VALUE **StackPtr, + IN OUT EFI_HII_VALUE **StackEnd, + IN EFI_HII_VALUE *Data + ) +{ + EFI_STATUS Status; + + // + // Check for a stack overflow condition + // + if (*StackPtr >= *StackEnd) { + // + // Grow the stack + // + Status = GrowStack (Stack, StackPtr, StackEnd); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // + // Push the item onto the stack + // + CopyMem (*StackPtr, Data, sizeof (EFI_HII_VALUE)); + if (Data->Type == EFI_IFR_TYPE_BUFFER) { + (*StackPtr)->Buffer = AllocateCopyPool(Data->BufferLen, Data->Buffer); + if ((*StackPtr)->Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + } + *StackPtr = *StackPtr + 1; + + return EFI_SUCCESS; +} + + +/** + Pop an element from the stack. + + @param Stack On input: old stack + @param StackPtr On input: old stack pointer; On output: new stack pointer + @param Data Data to pop. + + @retval EFI_SUCCESS The value was popped onto the stack. + @retval EFI_ACCESS_DENIED The pop operation underflowed the stack + +**/ +EFI_STATUS +PopStack ( + IN EFI_HII_VALUE *Stack, + IN OUT EFI_HII_VALUE **StackPtr, + OUT EFI_HII_VALUE *Data + ) +{ + // + // Check for a stack underflow condition + // + if (*StackPtr == Stack) { + return EFI_ACCESS_DENIED; + } + + // + // Pop the item off the stack + // + *StackPtr = *StackPtr - 1; + CopyMem (Data, *StackPtr, sizeof (EFI_HII_VALUE)); + return EFI_SUCCESS; +} + + +/** + Reset stack pointer to begin of the stack. + +**/ +VOID +ResetCurrentExpressionStack ( + VOID + ) +{ + mCurrentExpressionPointer = mCurrentExpressionStack; + mFormExpressionPointer = mFormExpressionStack; + mStatementExpressionPointer = mStatementExpressionStack; + mOptionExpressionPointer = mOptionExpressionStack; +} + +/** + Push current expression onto the Stack + + @param Pointer Pointer to current expression. + + @retval EFI_SUCCESS The value was pushed onto the stack. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. + +**/ +EFI_STATUS +PushCurrentExpression ( + IN VOID *Pointer + ) +{ + EFI_HII_VALUE Data; + + Data.Type = EFI_IFR_TYPE_NUM_SIZE_64; + Data.Value.u64 = (UINT64) (UINTN) Pointer; + + return PushStack ( + &mCurrentExpressionStack, + &mCurrentExpressionPointer, + &mCurrentExpressionEnd, + &Data + ); +} + +/** + Pop current expression from the Stack + + @param Pointer Pointer to current expression to be pop. + + @retval EFI_SUCCESS The value was pushed onto the stack. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. + +**/ +EFI_STATUS +PopCurrentExpression ( + OUT VOID **Pointer + ) +{ + EFI_STATUS Status; + EFI_HII_VALUE Data; + + Status = PopStack ( + mCurrentExpressionStack, + &mCurrentExpressionPointer, + &Data + ); + + *Pointer = (VOID *) (UINTN) Data.Value.u64; + + return Status; +} + +/** + Reset stack pointer to begin of the stack. + +**/ +VOID +ResetMapExpressionListStack ( + VOID + ) +{ + mMapExpressionListPointer = mMapExpressionListStack; +} + +/** + Grow size of the stack. + + This is an internal function. + + @param Stack On input: old stack; On output: new stack + @param StackPtr On input: old stack pointer; On output: new stack + pointer + @param StackEnd On input: old stack end; On output: new stack end + @param MemberSize The stack member size. + + @retval EFI_SUCCESS Grow stack success. + @retval EFI_OUT_OF_RESOURCES No enough memory for stack space. + +**/ +EFI_STATUS +GrowConditionalStack ( + IN OUT HII_EXPRESSION ***Stack, + IN OUT HII_EXPRESSION ***StackPtr, + IN OUT HII_EXPRESSION ***StackEnd, + IN UINTN MemberSize + ) +{ + UINTN Size; + HII_EXPRESSION **NewStack; + + Size = EXPRESSION_STACK_SIZE_INCREMENT; + if (*StackPtr != NULL) { + Size = Size + (*StackEnd - *Stack); + } + + NewStack = AllocatePool (Size * MemberSize); + if (NewStack == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + if (*StackPtr != NULL) { + // + // Copy from Old Stack to the New Stack + // + CopyMem ( + NewStack, + *Stack, + (*StackEnd - *Stack) * MemberSize + ); + + // + // Free The Old Stack + // + FreePool (*Stack); + } + + // + // Make the Stack pointer point to the old data in the new stack + // + *StackPtr = NewStack + (*StackPtr - *Stack); + *Stack = NewStack; + *StackEnd = NewStack + Size; + + return EFI_SUCCESS; +} + +/** + Push an element onto the Stack. + + @param Stack On input: old stack; On output: new stack + @param StackPtr On input: old stack pointer; On output: new stack + pointer + @param StackEnd On input: old stack end; On output: new stack end + @param Data Data to push. + + @retval EFI_SUCCESS Push stack success. + +**/ +EFI_STATUS +PushConditionalStack ( + IN OUT HII_EXPRESSION ***Stack, + IN OUT HII_EXPRESSION ***StackPtr, + IN OUT HII_EXPRESSION ***StackEnd, + IN HII_EXPRESSION **Data + ) +{ + EFI_STATUS Status; + + // + // Check for a stack overflow condition + // + if (*StackPtr >= *StackEnd) { + // + // Grow the stack + // + Status = GrowConditionalStack (Stack, StackPtr, StackEnd, sizeof (HII_EXPRESSION *)); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // + // Push the item onto the stack + // + CopyMem (*StackPtr, Data, sizeof (HII_EXPRESSION *)); + *StackPtr = *StackPtr + 1; + + return EFI_SUCCESS; + +} + +/** + Pop an element from the stack. + + @param Stack On input: old stack + @param StackPtr On input: old stack pointer; On output: new stack pointer + @param Data Data to pop. + + @retval EFI_SUCCESS The value was popped onto the stack. + @retval EFI_ACCESS_DENIED The pop operation underflowed the stack + +**/ +EFI_STATUS +PopConditionalStack ( + IN HII_EXPRESSION **Stack, + IN OUT HII_EXPRESSION ***StackPtr, + OUT HII_EXPRESSION **Data + ) +{ + // + // Check for a stack underflow condition + // + if (*StackPtr == Stack) { + return EFI_ACCESS_DENIED; + } + + // + // Pop the item off the stack + // + *StackPtr = *StackPtr - 1; + CopyMem (Data, *StackPtr, sizeof (HII_EXPRESSION *)); + return EFI_SUCCESS; + +} + +/** + Get the expression list count. + + @param Level Which type this expression belong to. Form, + statement or option? + + @retval >=0 The expression count + @retval -1 Input parameter error. + +**/ +INTN +GetConditionalExpressionCount ( + IN EXPRESS_LEVEL Level + ) +{ + switch (Level) { + case ExpressForm: + return mFormExpressionPointer - mFormExpressionStack; + case ExpressStatement: + return mStatementExpressionPointer - mStatementExpressionStack; + case ExpressOption: + return mOptionExpressionPointer - mOptionExpressionStack; + default: + ASSERT (FALSE); + return -1; + } +} + +/** + Get the expression Buffer pointer. + + @param Level Which type this expression belong to. Form, + statement or option? + + @retval The start pointer of the expression buffer or NULL. + +**/ +HII_EXPRESSION ** +GetConditionalExpressionList ( + IN EXPRESS_LEVEL Level + ) +{ + switch (Level) { + case ExpressForm: + return mFormExpressionStack; + case ExpressStatement: + return mStatementExpressionStack; + case ExpressOption: + return mOptionExpressionStack; + default: + ASSERT (FALSE); + return NULL; + } +} + + +/** + Push the expression options onto the Stack. + + @param Pointer Pointer to the current expression. + @param Level Which type this expression belong to. Form, + statement or option? + + @retval EFI_SUCCESS The value was pushed onto the stack. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. + +**/ +EFI_STATUS +PushConditionalExpression ( + IN HII_EXPRESSION *Pointer, + IN EXPRESS_LEVEL Level + ) +{ + switch (Level) { + case ExpressForm: + return PushConditionalStack ( + &mFormExpressionStack, + &mFormExpressionPointer, + &mFormExpressionEnd, + &Pointer + ); + case ExpressStatement: + return PushConditionalStack ( + &mStatementExpressionStack, + &mStatementExpressionPointer, + &mStatementExpressionEnd, + &Pointer + ); + case ExpressOption: + return PushConditionalStack ( + &mOptionExpressionStack, + &mOptionExpressionPointer, + &mOptionExpressionEnd, + &Pointer + ); + default: + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } +} + +/** + Pop the expression options from the Stack + + @param Level Which type this expression belong to. Form, + statement or option? + + @retval EFI_SUCCESS The value was pushed onto the stack. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. + +**/ +EFI_STATUS +PopConditionalExpression ( + IN EXPRESS_LEVEL Level + ) +{ + HII_EXPRESSION *Pointer; + + switch (Level) { + case ExpressForm: + return PopConditionalStack ( + mFormExpressionStack, + &mFormExpressionPointer, + &Pointer + ); + + case ExpressStatement: + return PopConditionalStack ( + mStatementExpressionStack, + &mStatementExpressionPointer, + &Pointer + ); + + case ExpressOption: + return PopConditionalStack ( + mOptionExpressionStack, + &mOptionExpressionPointer, + &Pointer + ); + + default: + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } +} + + +/** + Push the list of map expression onto the Stack + + @param Pointer Pointer to the list of map expression to be pushed. + + @retval EFI_SUCCESS The value was pushed onto the stack. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. + +**/ +EFI_STATUS +PushMapExpressionList ( + IN VOID *Pointer + ) +{ + EFI_HII_VALUE Data; + + Data.Type = EFI_IFR_TYPE_NUM_SIZE_64; + Data.Value.u64 = (UINT64) (UINTN) Pointer; + + return PushStack ( + &mMapExpressionListStack, + &mMapExpressionListPointer, + &mMapExpressionListEnd, + &Data + ); +} + + +/** + Pop the list of map expression from the Stack + + @param Pointer Pointer to the list of map expression to be pop. + + @retval EFI_SUCCESS The value was pushed onto the stack. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. + +**/ +EFI_STATUS +PopMapExpressionList ( + OUT VOID **Pointer + ) +{ + EFI_STATUS Status; + EFI_HII_VALUE Data; + + Status = PopStack ( + mMapExpressionListStack, + &mMapExpressionListPointer, + &Data + ); + + *Pointer = (VOID *) (UINTN) Data.Value.u64; + + return Status; +} + +/** + Reset stack pointer to begin of the stack. + +**/ +VOID +ResetScopeStack ( + VOID + ) +{ + mOpCodeScopeStackPointer = mOpCodeScopeStack; +} + + +/** + Push an Operand onto the Stack + + @param Operand Operand to push. + + @retval EFI_SUCCESS The value was pushed onto the stack. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the + stack. + +**/ +EFI_STATUS +PushScope ( + IN UINT8 Operand + ) +{ + EFI_HII_VALUE Data; + + Data.Type = EFI_IFR_TYPE_NUM_SIZE_8; + Data.Value.u8 = Operand; + + return PushStack ( + &mOpCodeScopeStack, + &mOpCodeScopeStackPointer, + &mOpCodeScopeStackEnd, + &Data + ); +} + + +/** + Pop an Operand from the Stack + + @param Operand Operand to pop. + + @retval EFI_SUCCESS The value was pushed onto the stack. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the + stack. + +**/ +EFI_STATUS +PopScope ( + OUT UINT8 *Operand + ) +{ + EFI_STATUS Status; + EFI_HII_VALUE Data; + + Status = PopStack ( + mOpCodeScopeStack, + &mOpCodeScopeStackPointer, + &Data + ); + + *Operand = Data.Value.u8; + + return Status; +} + +/** + Grow size of the stack for Expression Dependencies. + + This is an internal function. + + @param Stack On input: old stack; On output: new stack + @param StackPtr On input: old stack pointer; On output: new stack + pointer + @param StackEnd On input: old stack end; On output: new stack end + + @retval EFI_SUCCESS Grow Dependency stack success. + @retval EFI_OUT_OF_RESOURCES No enough memory for stack space. + +**/ +EFI_STATUS +GrowDependencyStack ( + IN OUT HII_DEPENDENCY_EXPRESSION ***Stack, + IN OUT HII_DEPENDENCY_EXPRESSION ***StackPtr, + IN OUT HII_DEPENDENCY_EXPRESSION ***StackEnd + ) +{ + UINTN Size; + HII_DEPENDENCY_EXPRESSION **NewStack; + + Size = EXPRESSION_STACK_SIZE_INCREMENT; + if (*StackPtr != NULL) { + Size = Size + (*StackEnd - *Stack); + } + + NewStack = AllocatePool (Size * sizeof (HII_DEPENDENCY_EXPRESSION *)); + if (NewStack == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + if (*StackPtr != NULL) { + // + // Copy from Old Stack to the New Stack + // + CopyMem ( + NewStack, + *Stack, + (*StackEnd - *Stack) * sizeof (HII_DEPENDENCY_EXPRESSION *) + ); + + // + // Free The Old Stack + // + FreePool (*Stack); + } + + // + // Make the Stack pointer point to the old data in the new stack + // + *StackPtr = NewStack + (*StackPtr - *Stack); + *Stack = NewStack; + *StackEnd = NewStack + Size; + + return EFI_SUCCESS; +} + +/** + Push an element onto the Stack for Expression Dependencies. + + @param Stack On input: old stack; On output: new stack + @param StackPtr On input: old stack pointer; On output: new stack + pointer + @param StackEnd On input: old stack end; On output: new stack end + @param Data Data to push. + + @retval EFI_SUCCESS Push stack success. + +**/ +EFI_STATUS +PushDependencyStack ( + IN OUT HII_DEPENDENCY_EXPRESSION ***Stack, + IN OUT HII_DEPENDENCY_EXPRESSION ***StackPtr, + IN OUT HII_DEPENDENCY_EXPRESSION ***StackEnd, + IN HII_DEPENDENCY_EXPRESSION **Data + ) +{ + EFI_STATUS Status; + + // + // Check for a stack overflow condition + // + if (*StackPtr >= *StackEnd) { + // + // Grow the stack + // + Status = GrowDependencyStack (Stack, StackPtr, StackEnd); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // + // Push the item onto the stack + // + CopyMem (*StackPtr, Data, sizeof (HII_DEPENDENCY_EXPRESSION *)); + *StackPtr = *StackPtr + 1; + + return EFI_SUCCESS; + +} + +/** + Pop the Expression Dependency options from the Stack + + @param Stack On input: old stack; On output: new stack + @param StackPtr On input: old stack pointer; On output: new stack + pointer + @param Data Data to push. + + @retval EFI_SUCCESS The value was pushed onto the stack. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. + +**/ +EFI_STATUS +PopDependencyStack ( + IN HII_DEPENDENCY_EXPRESSION **Stack, + IN OUT HII_DEPENDENCY_EXPRESSION ***StackPtr, + OUT HII_DEPENDENCY_EXPRESSION **Data + ) +{ + // + // Check for a stack underflow condition + // + if (*StackPtr == Stack) { + return EFI_ACCESS_DENIED; + } + + // + // Pop the item off the stack + // + *StackPtr = *StackPtr - 1; + CopyMem (Data, *StackPtr, sizeof (HII_DEPENDENCY_EXPRESSION *)); + return EFI_SUCCESS; + +} + +/** + Push the list of Expression Dependencies onto the Stack + + @param Pointer Pointer to the list of map expression to be pushed. + + @retval EFI_SUCCESS The value was pushed onto the stack. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. + +**/ +EFI_STATUS +PushDependencyExpDes ( + IN HII_DEPENDENCY_EXPRESSION **Pointer + ) +{ + return PushDependencyStack ( + &mExpressionDependencyStack, + &mExpressionDependencyPointer, + &mExpressionDependencyEnd, + Pointer + ); +} + +/** + Pop the list of Expression Dependencies from the Stack + + @param Pointer Pointer to the list of map expression to be pop. + + @retval EFI_SUCCESS The value was pushed onto the stack. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. + +**/ +EFI_STATUS +PopDependencyExpDes ( + OUT HII_DEPENDENCY_EXPRESSION **Pointer + ) +{ + return PopDependencyStack ( + mExpressionDependencyStack, + &mExpressionDependencyPointer, + Pointer + ); +} + +/** + Retrieve dependencies within an expression. These dependencies can express how + this expression will be evaluated. + + @param Expression Expression to retrieve dependencies. + + @retval EFI_SUCCESS The dependencies were successfully retrieved. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory. + +**/ +EFI_STATUS +GetHiiExpressionDependency ( + IN OUT HII_EXPRESSION *Expression + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Link; + HII_EXPRESSION_OPCODE *ExpressionOpCode; + HII_DEPENDENCY_EXPRESSION *DepExpressionOpCode; + LIST_ENTRY *SubExpressionLink; + HII_EXPRESSION *SubExpression; + UINT8 MapPairpCount; + + Link = GetFirstNode (&Expression->OpCodeListHead); + while (!IsNull (&Expression->OpCodeListHead, Link)) { + + ExpressionOpCode = HII_EXPRESSION_OPCODE_FROM_LINK (Link); + Link = GetNextNode (&Expression->OpCodeListHead, Link); + Status = EFI_SUCCESS; + + DepExpressionOpCode = (HII_DEPENDENCY_EXPRESSION *) AllocateZeroPool (sizeof (HII_DEPENDENCY_EXPRESSION)); + if (DepExpressionOpCode == NULL) { + return EFI_OUT_OF_RESOURCES; + } + switch (ExpressionOpCode->Operand) { + // + // Constant + // + case EFI_IFR_FALSE_OP: + case EFI_IFR_ONE_OP: + case EFI_IFR_ONES_OP: + case EFI_IFR_TRUE_OP: + case EFI_IFR_UINT8_OP: + case EFI_IFR_UINT16_OP: + case EFI_IFR_UINT32_OP: + case EFI_IFR_UINT64_OP: + case EFI_IFR_UNDEFINED_OP: + case EFI_IFR_VERSION_OP: + case EFI_IFR_ZERO_OP: + DepExpressionOpCode->ContantExp.Operand = ExpressionOpCode->Operand; + CopyMem (&DepExpressionOpCode->ContantExp.Value, &ExpressionOpCode->ExtraData.Value, sizeof (EFI_HII_VALUE)); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + // + // Built-in functions + // + case EFI_IFR_DUP_OP: + DepExpressionOpCode->DupExp.Operand = ExpressionOpCode->Operand; + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_EQ_ID_VAL_OP: + DepExpressionOpCode->EqIdValExp.Operand = ExpressionOpCode->Operand; + CopyMem (&DepExpressionOpCode->EqIdValExp.QuestionId, &ExpressionOpCode->ExtraData.EqIdValData.QuestionId, sizeof (EFI_QUESTION_ID)); + CopyMem (&DepExpressionOpCode->EqIdValExp.Value, &ExpressionOpCode->ExtraData.EqIdValData.Value, sizeof (EFI_HII_VALUE)); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_EQ_ID_ID_OP: + DepExpressionOpCode->EqIdIdExp.Operand = ExpressionOpCode->Operand; + CopyMem (&DepExpressionOpCode->EqIdIdExp.QuestionId1, &ExpressionOpCode->ExtraData.EqIdIdData.QuestionId1, sizeof (EFI_QUESTION_ID)); + CopyMem (&DepExpressionOpCode->EqIdIdExp.QuestionId2, &ExpressionOpCode->ExtraData.EqIdIdData.QuestionId2, sizeof (EFI_QUESTION_ID)); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_EQ_ID_VAL_LIST_OP: + DepExpressionOpCode->EqIdListExp.Operand = ExpressionOpCode->Operand; + DepExpressionOpCode->EqIdListExp.ListLength = ExpressionOpCode->ExtraData.EqIdListData.ListLength; + CopyMem (&DepExpressionOpCode->EqIdListExp.QuestionId, &ExpressionOpCode->ExtraData.EqIdListData.QuestionId, sizeof (EFI_QUESTION_ID)); + PushDependencyExpDes (&DepExpressionOpCode); + DepExpressionOpCode->EqIdListExp.ValueList = AllocateCopyPool ( + DepExpressionOpCode->EqIdListExp.ListLength * sizeof (UINT16), ExpressionOpCode->ExtraData.EqIdListData.ValueList); + if (DepExpressionOpCode->EqIdListExp.ValueList == NULL) { + return EFI_OUT_OF_RESOURCES; + } + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_GET_OP: + DepExpressionOpCode->GetExp.Operand = ExpressionOpCode->Operand; + DepExpressionOpCode->GetExp.VarStorage = ExpressionOpCode->ExtraData.GetSetData.VarStorage; + CopyMem (&DepExpressionOpCode->GetExp.VarStoreInfo.VarName, &ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo.VarName, sizeof (EFI_STRING_ID)); + CopyMem (&DepExpressionOpCode->GetExp.VarStoreInfo.VarOffset, &ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset, sizeof (UINT16)); + DepExpressionOpCode->GetExp.VarStoreInfo = ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo; + if (ExpressionOpCode->ExtraData.GetSetData.ValueName != NULL) { + DepExpressionOpCode->GetExp.ValueName = (CHAR16*)AllocateCopyPool (sizeof (ExpressionOpCode->ExtraData.GetSetData.ValueName), ExpressionOpCode->ExtraData.GetSetData.ValueName); + if (DepExpressionOpCode->GetExp.ValueName == NULL) { + return EFI_OUT_OF_RESOURCES; + } + } + DepExpressionOpCode->GetExp.ValueType = ExpressionOpCode->ExtraData.GetSetData.ValueType; + DepExpressionOpCode->GetExp.ValueWidth = ExpressionOpCode->ExtraData.GetSetData.ValueWidth; + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_QUESTION_REF1_OP: + DepExpressionOpCode->QuestionRef1Exp.Operand = ExpressionOpCode->Operand; + CopyMem (&DepExpressionOpCode->QuestionRef1Exp.QuestionId, &ExpressionOpCode->ExtraData.QuestionRef1Data.QuestionId, sizeof (EFI_QUESTION_ID)); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_RULE_REF_OP: + DepExpressionOpCode->RuleRefExp.Operand = ExpressionOpCode->Operand; + DepExpressionOpCode->RuleRefExp.RuleId = ExpressionOpCode->ExtraData.RuleId; + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_STRING_REF1_OP: + DepExpressionOpCode->StringRef1Exp.Operand = ExpressionOpCode->Operand; + CopyMem (&DepExpressionOpCode->StringRef1Exp.Value.Value.string, &ExpressionOpCode->ExtraData.Value.Value.string, sizeof (EFI_STRING_ID)); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_THIS_OP: + DepExpressionOpCode->ThisExp.Operand = ExpressionOpCode->Operand; + CopyMem (&DepExpressionOpCode->ThisExp.QuestionId, &ExpressionOpCode->ExtraData.QuestionRef1Data.QuestionId, sizeof (EFI_QUESTION_ID)); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_SECURITY_OP: + DepExpressionOpCode->SecurityExp.Operand = ExpressionOpCode->Operand; + CopyMem (&DepExpressionOpCode->SecurityExp.Permissions, &ExpressionOpCode->ExtraData.Guid, sizeof (EFI_GUID)); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + // + // unary-op + // + case EFI_IFR_LENGTH_OP: + DepExpressionOpCode->LengthExp.Operand = ExpressionOpCode->Operand; + PopDependencyExpDes (&DepExpressionOpCode->LengthExp.SubExpression); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_NOT_OP: + DepExpressionOpCode->NotExp.Operand = ExpressionOpCode->Operand; + PopDependencyExpDes (&DepExpressionOpCode->NotExp.SubExpression); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_BITWISE_NOT_OP: + DepExpressionOpCode->BitWiseNotExp.Operand = ExpressionOpCode->Operand; + PopDependencyExpDes (&DepExpressionOpCode->BitWiseNotExp.SubExpression); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_QUESTION_REF2_OP: + DepExpressionOpCode->QuestionRef2Exp.Operand = ExpressionOpCode->Operand; + PopDependencyExpDes (&DepExpressionOpCode->QuestionRef2Exp.SubExpression); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_QUESTION_REF3_OP: + DepExpressionOpCode->QuestionRef3Exp.Operand = ExpressionOpCode->Operand; + CopyMem (&DepExpressionOpCode->QuestionRef3Exp.DevicePath, &ExpressionOpCode->ExtraData.QuestionRef3Data.DevicePath, sizeof (EFI_DEVICE_PATH)); + CopyMem (&DepExpressionOpCode->QuestionRef3Exp.Guid, &ExpressionOpCode->ExtraData.QuestionRef3Data.Guid, sizeof (EFI_GUID)); + PopDependencyExpDes (&DepExpressionOpCode->QuestionRef3Exp.SubExpression); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_SET_OP: + DepExpressionOpCode->SetExp.Operand = ExpressionOpCode->Operand; + DepExpressionOpCode->SetExp.VarStorage = ExpressionOpCode->ExtraData.GetSetData.VarStorage; + CopyMem (&DepExpressionOpCode->SetExp.VarStoreInfo.VarName, &ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo.VarName, sizeof (EFI_STRING_ID)); + CopyMem (&DepExpressionOpCode->SetExp.VarStoreInfo.VarOffset, &ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset, sizeof (UINT16)); + DepExpressionOpCode->SetExp.VarStoreInfo = ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo; + if (ExpressionOpCode->ExtraData.GetSetData.ValueName != NULL) { + DepExpressionOpCode->SetExp.ValueName = (CHAR16*)AllocateCopyPool (sizeof (ExpressionOpCode->ExtraData.GetSetData.ValueName), ExpressionOpCode->ExtraData.GetSetData.ValueName); + if (DepExpressionOpCode->SetExp.ValueName == NULL) { + return EFI_OUT_OF_RESOURCES; + } + } + DepExpressionOpCode->SetExp.ValueType = ExpressionOpCode->ExtraData.GetSetData.ValueType; + DepExpressionOpCode->SetExp.ValueWidth = ExpressionOpCode->ExtraData.GetSetData.ValueWidth; + PopDependencyExpDes (&DepExpressionOpCode->SetExp.SubExpression); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_STRING_REF2_OP: + DepExpressionOpCode->StringRef2Exp.Operand = ExpressionOpCode->Operand; + PopDependencyExpDes (&DepExpressionOpCode->StringRef2Exp.SubExpression); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_TO_BOOLEAN_OP: + DepExpressionOpCode->ToBooleanExp.Operand = ExpressionOpCode->Operand; + PopDependencyExpDes (&DepExpressionOpCode->ToBooleanExp.SubExpression); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_TO_STRING_OP: + DepExpressionOpCode->ToStringExp.Operand = ExpressionOpCode->Operand; + DepExpressionOpCode->ToStringExp.Format = ExpressionOpCode->ExtraData.Format; + PopDependencyExpDes (&DepExpressionOpCode->ToStringExp.SubExpression); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_TO_UINT_OP: + DepExpressionOpCode->ToUintExp.Operand = ExpressionOpCode->Operand; + PopDependencyExpDes (&DepExpressionOpCode->ToUintExp.SubExpression); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_TO_LOWER_OP: + DepExpressionOpCode->ToLowerExp.Operand = ExpressionOpCode->Operand; + PopDependencyExpDes (&DepExpressionOpCode->ToLowerExp.SubExpression); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_TO_UPPER_OP: + DepExpressionOpCode->ToUpperExp.Operand = ExpressionOpCode->Operand; + PopDependencyExpDes (&DepExpressionOpCode->ToUpperExp.SubExpression); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + // + // binary-op + // + case EFI_IFR_ADD_OP: + DepExpressionOpCode->AddExp.Operand = ExpressionOpCode->Operand; + PopDependencyExpDes (&DepExpressionOpCode->AddExp.LeftHandExp); + PopDependencyExpDes (&DepExpressionOpCode->AddExp.RightHandExp); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_AND_OP: + DepExpressionOpCode->AndExp.Operand = ExpressionOpCode->Operand; + PopDependencyExpDes (&DepExpressionOpCode->AndExp.SubExpression1); + PopDependencyExpDes (&DepExpressionOpCode->AndExp.SubExpression2); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_BITWISE_AND_OP: + DepExpressionOpCode->BitwiseAndExp.Operand = ExpressionOpCode->Operand; + PopDependencyExpDes (&DepExpressionOpCode->BitwiseAndExp.SubExpression1); + PopDependencyExpDes (&DepExpressionOpCode->BitwiseAndExp.SubExpression2); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_BITWISE_OR_OP: + DepExpressionOpCode->BitwiseOrExp.Operand = ExpressionOpCode->Operand; + PopDependencyExpDes (&DepExpressionOpCode->BitwiseOrExp.SubExpression1); + PopDependencyExpDes (&DepExpressionOpCode->BitwiseOrExp.SubExpression2); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_CATENATE_OP: + DepExpressionOpCode->CatenateExp.Operand = ExpressionOpCode->Operand; + PopDependencyExpDes (&DepExpressionOpCode->CatenateExp.LeftStringExp); + PopDependencyExpDes (&DepExpressionOpCode->CatenateExp.RightStringExp); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_DIVIDE_OP: + DepExpressionOpCode->DivExp.Operand = ExpressionOpCode->Operand; + PopDependencyExpDes (&DepExpressionOpCode->DivExp.LeftHandExp); + PopDependencyExpDes (&DepExpressionOpCode->DivExp.RightHandExp); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_EQUAL_OP: + DepExpressionOpCode->EqualExp.Operand = ExpressionOpCode->Operand; + PopDependencyExpDes (&DepExpressionOpCode->EqualExp.SubExpression1); + PopDependencyExpDes (&DepExpressionOpCode->EqualExp.SubExpression2); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_GREATER_EQUAL_OP: + DepExpressionOpCode->GreaterEqualExp.Operand = ExpressionOpCode->Operand; + PopDependencyExpDes (&DepExpressionOpCode->GreaterEqualExp.LeftHandExp); + PopDependencyExpDes (&DepExpressionOpCode->GreaterEqualExp.RightHandExp); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_GREATER_THAN_OP: + DepExpressionOpCode->GreaterThanExp.Operand = ExpressionOpCode->Operand; + PopDependencyExpDes (&DepExpressionOpCode->GreaterThanExp.LeftHandExp); + PopDependencyExpDes (&DepExpressionOpCode->GreaterThanExp.RightHandExp); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_LESS_EQUAL_OP: + DepExpressionOpCode->LessEqualExp.Operand = ExpressionOpCode->Operand; + PopDependencyExpDes (&DepExpressionOpCode->LessEqualExp.LeftHandExp); + PopDependencyExpDes (&DepExpressionOpCode->LessEqualExp.RightHandExp); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_LESS_THAN_OP: + DepExpressionOpCode->LessThanExp.Operand = ExpressionOpCode->Operand; + PopDependencyExpDes (&DepExpressionOpCode->LessThanExp.LeftHandExp); + PopDependencyExpDes (&DepExpressionOpCode->LessThanExp.RightHandExp); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_MATCH_OP: + DepExpressionOpCode->MatchExp.Operand = ExpressionOpCode->Operand; + PopDependencyExpDes (&DepExpressionOpCode->MatchExp.PatternExp); + PopDependencyExpDes (&DepExpressionOpCode->MatchExp.StringExp); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_MATCH2_OP: + DepExpressionOpCode->Match2Exp.Operand = ExpressionOpCode->Operand; + CopyMem (&DepExpressionOpCode->Match2Exp.SyntaxType, &ExpressionOpCode->ExtraData.Guid, sizeof (EFI_GUID)); + PopDependencyExpDes (&DepExpressionOpCode->Match2Exp.PatternExp); + PopDependencyExpDes (&DepExpressionOpCode->Match2Exp.StringExp); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_MODULO_OP: + DepExpressionOpCode->ModExp.Operand = ExpressionOpCode->Operand; + PopDependencyExpDes (&DepExpressionOpCode->ModExp.LeftHandExp); + PopDependencyExpDes (&DepExpressionOpCode->ModExp.RightHandExp); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_MULTIPLY_OP: + DepExpressionOpCode->MultExp.Operand = ExpressionOpCode->Operand; + PopDependencyExpDes (&DepExpressionOpCode->MultExp.LeftHandExp); + PopDependencyExpDes (&DepExpressionOpCode->MultExp.RightHandExp); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_NOT_EQUAL_OP: + DepExpressionOpCode->NotEqualExp.Operand = ExpressionOpCode->Operand; + PopDependencyExpDes (&DepExpressionOpCode->NotEqualExp.SubExpression1); + PopDependencyExpDes (&DepExpressionOpCode->NotEqualExp.SubExpression2); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_OR_OP: + DepExpressionOpCode->OrExp.Operand = ExpressionOpCode->Operand; + PopDependencyExpDes (&DepExpressionOpCode->OrExp.SubExpression1); + PopDependencyExpDes (&DepExpressionOpCode->OrExp.SubExpression2); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_SHIFT_LEFT_OP: + DepExpressionOpCode->ShiftLeftExp.Operand = ExpressionOpCode->Operand; + PopDependencyExpDes (&DepExpressionOpCode->ShiftLeftExp.LeftHandExp); + PopDependencyExpDes (&DepExpressionOpCode->ShiftLeftExp.RightHandExp); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_SHIFT_RIGHT_OP: + DepExpressionOpCode->ShiftRightExp.Operand = ExpressionOpCode->Operand; + PopDependencyExpDes (&DepExpressionOpCode->ShiftRightExp.LeftHandExp); + PopDependencyExpDes (&DepExpressionOpCode->ShiftRightExp.RightHandExp); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_SUBTRACT_OP: + DepExpressionOpCode->SubtractExp.Operand = ExpressionOpCode->Operand; + PopDependencyExpDes (&DepExpressionOpCode->SubtractExp.LeftHandExp); + PopDependencyExpDes (&DepExpressionOpCode->SubtractExp.RightHandExp); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + // + // ternary-op + // + case EFI_IFR_CONDITIONAL_OP: + DepExpressionOpCode->ConditionalExp.Operand = ExpressionOpCode->Operand; + PopDependencyExpDes (&DepExpressionOpCode->ConditionalExp.CondTrueValExp); + PopDependencyExpDes (&DepExpressionOpCode->ConditionalExp.CondFalseValExp); + PopDependencyExpDes (&DepExpressionOpCode->ConditionalExp.ConditionExp); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_FIND_OP: + DepExpressionOpCode->FindExp.Operand = ExpressionOpCode->Operand; + PopDependencyExpDes (&DepExpressionOpCode->FindExp.StringToSearchExp); + PopDependencyExpDes (&DepExpressionOpCode->FindExp.StringToCompWithExp); + PopDependencyExpDes (&DepExpressionOpCode->FindExp.IndexExp); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_MID_OP: + DepExpressionOpCode->MidExp.Operand = ExpressionOpCode->Operand; + PopDependencyExpDes (&DepExpressionOpCode->MidExp.StringOrBufferExp); + PopDependencyExpDes (&DepExpressionOpCode->MidExp.IndexExp); + PopDependencyExpDes (&DepExpressionOpCode->MidExp.LengthExp); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_TOKEN_OP: + DepExpressionOpCode->TokenExp.Operand = ExpressionOpCode->Operand; + PopDependencyExpDes (&DepExpressionOpCode->TokenExp.StringToSearchExp); + PopDependencyExpDes (&DepExpressionOpCode->TokenExp.DelimiterExp); + PopDependencyExpDes (&DepExpressionOpCode->TokenExp.IndexExp); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + case EFI_IFR_SPAN_OP: + DepExpressionOpCode->SpanExp.Operand = ExpressionOpCode->Operand; + PopDependencyExpDes (&DepExpressionOpCode->SpanExp.StringToSearchExp); + PopDependencyExpDes (&DepExpressionOpCode->SpanExp.CharsetExp); + PopDependencyExpDes (&DepExpressionOpCode->SpanExp.IndeExp); + PushDependencyExpDes (&DepExpressionOpCode); + break; + + // + // Map + // + case EFI_IFR_MAP_OP: + // + // Go through map expression list. + // + DepExpressionOpCode->MapExp.Operand = ExpressionOpCode->Operand; + MapPairpCount = 0; + SubExpressionLink = GetFirstNode(&ExpressionOpCode->MapExpressionList); + while (!IsNull (&ExpressionOpCode->MapExpressionList, SubExpressionLink)) { + MapPairpCount ++; + SubExpressionLink = GetNextNode (&ExpressionOpCode->MapExpressionList, SubExpressionLink); + if (IsNull (&ExpressionOpCode->MapExpressionList, SubExpressionLink)) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + // + // Goto the first expression on next pair. + // + SubExpressionLink = GetNextNode (&ExpressionOpCode->MapExpressionList, SubExpressionLink); + } + DepExpressionOpCode->MapExp.ExpPair = (HII_DEPENDENCY_EXPRESSION_PAIR*) AllocateZeroPool ( + MapPairpCount * sizeof (HII_DEPENDENCY_EXPRESSION_PAIR)); + if (DepExpressionOpCode->MapExp.ExpPair == NULL) { + + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + DepExpressionOpCode->MapExp.ExpPairNo = MapPairpCount; + MapPairpCount = 0; + PopDependencyExpDes (&DepExpressionOpCode->MapExp.SubExp); + + // + // Go through map expression list. + // + SubExpressionLink = GetFirstNode(&ExpressionOpCode->MapExpressionList); + while (!IsNull (&ExpressionOpCode->MapExpressionList, SubExpressionLink)) { + SubExpression = HII_EXPRESSION_FROM_LINK (SubExpressionLink); + // + // Get the first expression description in this pair. + // + GetHiiExpressionDependency (SubExpression); + DepExpressionOpCode->MapExp.ExpPair[MapPairpCount].MatchExp= SubExpression->RootDepdencyExp; + + // + // Get the second expression description in this pair. + // + SubExpressionLink = GetNextNode (&ExpressionOpCode->MapExpressionList, SubExpressionLink); + SubExpression = HII_EXPRESSION_FROM_LINK (SubExpressionLink); + GetHiiExpressionDependency (SubExpression); + DepExpressionOpCode->MapExp.ExpPair[MapPairpCount].ReturnExp= SubExpression->RootDepdencyExp; + // + // Goto the first expression on next pair. + // + SubExpressionLink = GetNextNode (&ExpressionOpCode->MapExpressionList, SubExpressionLink); + MapPairpCount++; + } + PushDependencyExpDes (&DepExpressionOpCode); + break; + + default: + break; + } + } + + PopDependencyExpDes (&Expression->RootDepdencyExp); + +Done: + return Status; +} diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiIfrParse.c b/RedfishPkg/Library/HiiUtilityLib/HiiIfrParse.c new file mode 100644 index 00000000000..3546f92c1e7 --- /dev/null +++ b/RedfishPkg/Library/HiiUtilityLib/HiiIfrParse.c @@ -0,0 +1,2671 @@ +/** @file + Definitinos of RedfishPlatformConfigLib + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "HiiInternal.h" + +#define EFI_IFR_SPECIFICATION_VERSION (UINT16) (((EFI_SYSTEM_TABLE_REVISION >> 16) << 8) | (((EFI_SYSTEM_TABLE_REVISION & 0xFFFF) / 10) << 4) | ((EFI_SYSTEM_TABLE_REVISION & 0xFFFF) % 10)) + +/** + Initialize Statement header members. + + @param[in] OpCodeData Pointer of the raw OpCode data. + @param[in,out] FormSet Pointer of the current FormSet. + @param[in,out] Form Pointer of the current Form. + + @return The Statement. + +**/ +HII_STATEMENT * +CreateStatement ( + IN UINT8 *OpCodeData, + IN OUT HII_FORMSET *FormSet, + IN OUT HII_FORM *Form + ) +{ + HII_STATEMENT *Statement; + EFI_IFR_STATEMENT_HEADER *StatementHdr; + INTN ConditionalExprCount; + + if (Form == NULL) { + // + // Only guid op may out side the form level. + // + if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode != EFI_IFR_GUID_OP) { + return NULL; + } + } + + Statement = (HII_STATEMENT *) AllocateZeroPool (sizeof (HII_STATEMENT)); + if (Statement == NULL) { + return NULL; + } + + InitializeListHead (&Statement->DefaultListHead); + InitializeListHead (&Statement->OptionListHead); + InitializeListHead (&Statement->InconsistentListHead); + InitializeListHead (&Statement->NoSubmitListHead); + InitializeListHead (&Statement->WarningListHead); + + Statement->Signature = HII_STATEMENT_SIGNATURE; + Statement->Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode; + Statement->OpCode = (EFI_IFR_OP_HEADER *) OpCodeData; + Statement->QuestionReferToBitField = FALSE; + + StatementHdr = (EFI_IFR_STATEMENT_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER)); + CopyMem (&Statement->Prompt, &StatementHdr->Prompt, sizeof (EFI_STRING_ID)); + CopyMem (&Statement->Help, &StatementHdr->Help, sizeof (EFI_STRING_ID)); + + ConditionalExprCount = GetConditionalExpressionCount(ExpressStatement); + if (ConditionalExprCount > 0) { + + // + // Form is inside of suppressif + // + Statement->ExpressionList = (HII_EXPRESSION_LIST *) AllocatePool( + (UINTN) (sizeof(HII_EXPRESSION_LIST) + ((ConditionalExprCount - 1) * sizeof (HII_EXPRESSION *)))); + if (Statement->ExpressionList == NULL) { + return NULL; + } + + Statement->ExpressionList->Count = (UINTN) ConditionalExprCount; + Statement->ExpressionList->Signature = HII_EXPRESSION_LIST_SIGNATURE; + CopyMem (Statement->ExpressionList->Expression, + GetConditionalExpressionList(ExpressStatement), (UINTN) (sizeof (HII_EXPRESSION *) * ConditionalExprCount)); + } + + // + // Insert this Statement into current Form + // + if (Form == NULL) { + InsertTailList (&FormSet->StatementListOSF, &Statement->Link); + } else { + InsertTailList (&Form->StatementListHead, &Statement->Link); + } + return Statement; +} + +/** + Initialize Question's members. + + @param[in] OpCodeData Pointer of the raw OpCode data. + @param[in,out] FormSet Pointer of the current FormSet. + @param[in,out] Form Pointer of the current Form. + + @return The Question. + +**/ +HII_STATEMENT * +CreateQuestion ( + IN UINT8 *OpCodeData, + IN OUT HII_FORMSET *FormSet, + IN OUT HII_FORM *Form + ) +{ + HII_STATEMENT *Statement; + EFI_IFR_QUESTION_HEADER *QuestionHdr; + LIST_ENTRY *Link; + HII_FORMSET_STORAGE *Storage; + HII_NAME_VALUE_NODE *NameValueNode; + BOOLEAN Find; + + Statement = CreateStatement (OpCodeData, FormSet, Form); + if (Statement == NULL) { + return NULL; + } + + QuestionHdr = (EFI_IFR_QUESTION_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER)); + CopyMem (&Statement->QuestionId, &QuestionHdr->QuestionId, sizeof (EFI_QUESTION_ID)); + CopyMem (&Statement->VarStoreId, &QuestionHdr->VarStoreId, sizeof (EFI_VARSTORE_ID)); + CopyMem (&Statement->VarStoreInfo.VarOffset, &QuestionHdr->VarStoreInfo.VarOffset, sizeof (UINT16)); + + Statement->QuestionFlags = QuestionHdr->Flags; + + if (Statement->VarStoreId == 0) { + // + // VarStoreId of zero indicates no variable storage + // + return Statement; + } + + // + // Find Storage for this Question + // + Link = GetFirstNode (&FormSet->StorageListHead); + while (!IsNull (&FormSet->StorageListHead, Link)) { + Storage = HII_STORAGE_FROM_LINK (Link); + + if (Statement->VarStoreId == Storage->VarStoreId) { + + Statement->Storage = Storage; + break; + } + + Link = GetNextNode (&FormSet->StorageListHead, Link); + } + if (Statement->Storage == NULL) { + return NULL; + } + + // + // Initialilze varname for Name/Value or EFI Variable + // + if ((Statement->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) || + (Statement->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) { + + Statement->VariableName = GetToken (Statement->VarStoreInfo.VarName, FormSet->HiiHandle); + if (Statement->VariableName == NULL) { + return NULL; + } + + if (Statement->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) { + + // + // Check whether old string node already exist. + // + Find = FALSE; + if (!IsListEmpty(&Statement->Storage->NameValueList)) { + Link = GetFirstNode (&Statement->Storage->NameValueList); + while (!IsNull (&Statement->Storage->NameValueList, Link)) { + NameValueNode = HII_NAME_VALUE_NODE_FROM_LINK (Link); + + if (StrCmp (Statement->VariableName, NameValueNode->Name) == 0) { + Find = TRUE; + break; + } + + Link = GetNextNode (&Statement->Storage->NameValueList, Link); + } + } + + + if (!Find) { + // + // Insert to Name/Value varstore list + // + NameValueNode = AllocateZeroPool (sizeof (HII_NAME_VALUE_NODE)); + if (NameValueNode == NULL) { + return NULL; + } + + NameValueNode->Signature = HII_NAME_VALUE_NODE_SIGNATURE; + NameValueNode->Name = AllocateCopyPool (StrSize (Statement->VariableName), Statement->VariableName); + if (NameValueNode->Name == NULL) { + + FreePool (NameValueNode); + return NULL; + } + + NameValueNode->Value = AllocateZeroPool (0x10); + if (NameValueNode->Value == NULL) { + + FreePool (NameValueNode->Name); + FreePool (NameValueNode); + return NULL; + } + + + InsertTailList (&Statement->Storage->NameValueList, &NameValueNode->Link); + } + } + } + + return Statement; +} + + +/** + Allocate a HII_EXPRESSION node. + + @param[in,out] Form The Form associated with this Expression + @param[in] OpCode The binary opcode data. + + @return Pointer to a HII_EXPRESSION data structure. + +**/ +HII_EXPRESSION * +CreateExpression ( + IN OUT HII_FORM *Form, + IN UINT8 *OpCode + ) +{ + HII_EXPRESSION *Expression; + + Expression = AllocateZeroPool (sizeof (HII_EXPRESSION)); + if (Expression == NULL) { + return NULL; + } + + Expression->Signature = HII_EXPRESSION_SIGNATURE; + InitializeListHead (&Expression->OpCodeListHead); + Expression->OpCode = (EFI_IFR_OP_HEADER *) OpCode; + + return Expression; +} + +/** + Create ConfigHdr string for a storage. + + @param[in] FormSet Pointer of the current FormSet + @param[in,out] Storage Pointer of the storage + + @retval EFI_SUCCESS Initialize ConfigHdr success + +**/ +EFI_STATUS +InitializeConfigHdr ( + IN HII_FORMSET *FormSet, + IN OUT HII_FORMSET_STORAGE *Storage + ) +{ + CHAR16 *Name; + + if (Storage->Type == EFI_HII_VARSTORE_BUFFER || + Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) { + + Name = Storage->Name; + } else { + Name = NULL; + } + + Storage->ConfigHdr = HiiConstructConfigHdr ( + &FormSet->Guid, + Name, + FormSet->DriverHandle + ); + + if (Storage->ConfigHdr == NULL) { + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + +/** + Convert Ascii string to Unicode. + + This is an internal function. + + @param[in] AsciiString The Ascii string to be converted. + @param[out] UnicodeString The Unicode string retrieved. + +**/ +VOID +AsciiToUnicode ( + IN CHAR8 *AsciiString, + OUT CHAR16 *UnicodeString + ) +{ + UINT8 Index; + + Index = 0; + while (AsciiString[Index] != 0) { + UnicodeString[Index] = (CHAR16)AsciiString[Index]; + Index++; + } + + UnicodeString[Index] = L'\0'; +} + +/** + Allocate a HII_FORMSET_STORAGE data structure and insert to FormSet Storage List. + + @param[in] FormSet Pointer of the current FormSet + @param[in] StorageType Storage type. + @param[in] OpCodeData Binary data for this opcode. + + @return Pointer to a HII_FORMSET_STORAGE data structure. + +**/ +HII_FORMSET_STORAGE * +CreateStorage ( + IN HII_FORMSET *FormSet, + IN UINT8 StorageType, + IN UINT8 *OpCodeData + ) +{ + HII_FORMSET_STORAGE *Storage; + CHAR8 *AsciiStorageName; + + AsciiStorageName = NULL; + + Storage = AllocateZeroPool (sizeof (HII_FORMSET_STORAGE)); + if (Storage == NULL) { + return NULL; + } + + Storage->Signature = HII_STORAGE_SIGNATURE; + Storage->Type = StorageType; + + switch (StorageType) { + case EFI_HII_VARSTORE_BUFFER: + + CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE *) OpCodeData)->Guid, sizeof (EFI_GUID)); + CopyMem (&Storage->Size, &((EFI_IFR_VARSTORE *) OpCodeData)->Size, sizeof (UINT16)); + + Storage->Buffer = AllocateZeroPool (Storage->Size); + if (Storage->Buffer == NULL) { + + FreePool (Storage); + return NULL; + } + + AsciiStorageName = (CHAR8 *) ((EFI_IFR_VARSTORE *) OpCodeData)->Name; + Storage->Name = AllocatePool (sizeof (CHAR16) * (AsciiStrLen (AsciiStorageName) + 1)); + if (Storage->Name == NULL) { + + FreePool (Storage); + return NULL; + } + + AsciiToUnicode (AsciiStorageName, Storage->Name); + + break; + + case EFI_HII_VARSTORE_EFI_VARIABLE: + case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER: + CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Guid, sizeof (EFI_GUID)); + CopyMem (&Storage->Attributes, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Attributes, sizeof (UINT32)); + CopyMem (&Storage->Size, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Size, sizeof (UINT16)); + + if (StorageType == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) { + Storage->Buffer = AllocateZeroPool (Storage->Size); + if (Storage->Buffer == NULL) { + + FreePool (Storage); + return NULL; + } + } + + AsciiStorageName = (CHAR8 *) ((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Name; + Storage->Name = AllocatePool (sizeof (CHAR16) * (AsciiStrLen (AsciiStorageName) + 1)); + if (Storage->Name == NULL) { + + FreePool (Storage); + return NULL; + } + AsciiToUnicode (AsciiStorageName, Storage->Name); + + break; + + case EFI_HII_VARSTORE_NAME_VALUE: + CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->Guid, sizeof (EFI_GUID)); + InitializeListHead (&Storage->NameValueList); + + break; + + default: + break; + } + + InitializeConfigHdr (FormSet, Storage); + InsertTailList (&FormSet->StorageListHead, &Storage->Link); + + return Storage; +} + +/** + Get formset storage based on the input varstoreid info. + + @param[in] FormSet Pointer of the current FormSet. + @param[in] VarStoreId Varstore ID info. + + @return Pointer to a HII_FORMSET_STORAGE data structure. + +**/ +HII_FORMSET_STORAGE * +GetFstStgFromVarId ( + IN HII_FORMSET *FormSet, + IN EFI_VARSTORE_ID VarStoreId + ) +{ + HII_FORMSET_STORAGE *Storage; + LIST_ENTRY *Link; + BOOLEAN Found; + + Found = FALSE; + Storage = NULL; + // + // Find Formset Storage for this Question + // + Link = GetFirstNode (&FormSet->StorageListHead); + while (!IsNull (&FormSet->StorageListHead, Link)) { + Storage = HII_STORAGE_FROM_LINK (Link); + + if (Storage->VarStoreId == VarStoreId) { + Found = TRUE; + break; + } + + Link = GetNextNode (&FormSet->StorageListHead, Link); + } + + return Found ? Storage : NULL; +} + +/** + Initialize Request Element of a Question. ::= '&' | '&'