From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mx0b-002e3701.pphosted.com (mx0b-002e3701.pphosted.com [148.163.143.35]) by mx.groups.io with SMTP id smtpd.web09.16459.1658668788516649674 for ; Sun, 24 Jul 2022 06:19:49 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@hpe.com header.s=pps0720 header.b=hKjRLZjE; spf=permerror, err=parse error for token &{10 18 %{ir}.%{v}.%{d}.spf.has.pphosted.com}: invalid domain name (domain: hpe.com, ip: 148.163.143.35, mailfrom: prvs=02048cc234=nickle.wang@hpe.com) Received: from pps.filterd (m0150245.ppops.net [127.0.0.1]) by mx0b-002e3701.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 26O5NLLQ004918; Sun, 24 Jul 2022 13:19:45 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=hpe.com; h=from : to : cc : subject : date : message-id : mime-version : content-transfer-encoding; s=pps0720; bh=gmW7oknH9nACc4yew7iTIs4eCISEPXnd6tzuKrtJo+E=; b=hKjRLZjELTolp49BggoFORSgZtH+miZ7wdQRHMtdZPJozSnuUWLS556GhsfkwbkD4hzl Zz7IS3R2eEC6Q/4UVAMGdQ+SuMMN/2SdHpDILHP8+VDFUkS5ARYxMlh7TfgQejlkTgey 2TPsbuxcAP2TmfvoN5vXVBDUHxvPXfrqawjJtge/G3q7k0+AobaPVhC7BlUZserPn1+T Z83MJpEKY8hZUF9fb3d753sHoB4MNDRuU5ZTJViNzA+q1GyNXzNHyixTCPXS5vMRRfXC VJAvP/Mq8I2w90cgtb6GRdy9ega227sqGpHeQha+yvIa8+Ggn+dNDyYzDUMyTDm99zze 4A== Received: from p1lg14880.it.hpe.com (p1lg14880.it.hpe.com [16.230.97.201]) by mx0b-002e3701.pphosted.com (PPS) with ESMTPS id 3hgyvj1us3-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Sun, 24 Jul 2022 13:19:44 +0000 Received: from p1lg14885.dc01.its.hpecorp.net (unknown [10.119.18.236]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by p1lg14880.it.hpe.com (Postfix) with ESMTPS id F09298001AA; Sun, 24 Jul 2022 13:19:43 +0000 (UTC) Received: from WAFM3XJD5N.asiapacific.hpqcorp.net (unknown [16.231.227.36]) by p1lg14885.dc01.its.hpecorp.net (Postfix) with ESMTP id EDB7780A4C1; Sun, 24 Jul 2022 13:19:41 +0000 (UTC) From: "Nickle Wang" To: devel@edk2.groups.io Cc: Abner Chang , Yang Atom , Nick Ramirez Subject: [edk2-staging][PATCH v2 1/1] edk2/RedfishPkg: Update Redfish Platform Config Protocol Date: Sun, 24 Jul 2022 21:19:40 +0800 Message-Id: <20220724131940.714-1-nickle.wang@hpe.com> X-Mailer: git-send-email 2.32.0.windows.2 MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: o2LizXI3ItlW1xR9PD0qv0K-z0X9IEx9 X-Proofpoint-GUID: o2LizXI3ItlW1xR9PD0qv0K-z0X9IEx9 X-HPE-SCL: -1 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.883,Hydra:6.0.517,FMLib:17.11.122.1 definitions=2022-07-23_02,2022-07-21_02,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 adultscore=0 bulkscore=0 clxscore=1015 priorityscore=1501 lowpriorityscore=0 mlxlogscore=999 impostorscore=0 phishscore=0 mlxscore=0 suspectscore=0 malwarescore=0 spamscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2206140000 definitions=main-2207240060 Content-Transfer-Encoding: 8bit Update EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL and add array type of value support to EDKII_REDFISH_VALUE in order to support ordered list op-code in HII. Modify corresponding function to support new type of data structure. Signed-off-by: Nickle Wang Cc: Abner Chang Cc: Yang Atom Cc: Nick Ramirez --- .../Protocol/EdkIIRedfishPlatformConfig.h | 301 +- .../RedfishPlatformConfigDxe.c | 3087 ++++++++++------- .../RedfishPlatformConfigDxe.h | 128 +- .../RedfishPlatformConfigDxe.inf | 104 +- .../RedfishPlatformConfigImpl.c | 2528 +++++++------- .../RedfishPlatformConfigImpl.h | 571 +-- 6 files changed, 3638 insertions(+), 3081 deletions(-) diff --git a/RedfishPkg/Include/Protocol/EdkIIRedfishPlatformConfig.h b/RedfishPkg/Include/Protocol/EdkIIRedfishPlatformConfig.h index 895b010227..bbbab90b03 100644 --- a/RedfishPkg/Include/Protocol/EdkIIRedfishPlatformConfig.h +++ b/RedfishPkg/Include/Protocol/EdkIIRedfishPlatformConfig.h @@ -1,147 +1,154 @@ -/** @file - This file defines the EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL interface. - - (C) Copyright 2021 Hewlett Packard Enterprise Development LP
- - SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#ifndef EDKII_REDFISH_PLATFORM_CONFIG_H_ -#define EDKII_REDFISH_PLATFORM_CONFIG_H_ - -typedef struct _EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL; - -/** - Definition of EDKII_REDFISH_TYPE_VALUE - **/ -typedef union { - INT64 Integer; - BOOLEAN Boolean; - CHAR8 *Buffer; -} EDKII_REDFISH_TYPE_VALUE; - -/** - Definition of EDKII_REDFISH_VALUE_TYPES - **/ -typedef enum { - REDFISH_VALUE_TYPE_UNKNOWN = 0, - REDFISH_VALUE_TYPE_INTEGER, - REDFISH_VALUE_TYPE_BOOLEAN, - REDFISH_VALUE_TYPE_STRING, - REDFISH_VALUE_TYPE_MAX -} EDKII_REDFISH_VALUE_TYPES; - -/** - Definition of EDKII_REDFISH_VALUE - **/ -typedef struct { - EDKII_REDFISH_VALUE_TYPES Type; - EDKII_REDFISH_TYPE_VALUE Value; -} EDKII_REDFISH_VALUE; - -/** - Get Redfish value with the given Schema and Configure Language. - - @param[in] This Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance. - @param[in] Schema The Redfish schema to query. - @param[in] Version The Redfish version to query. - @param[in] ConfigureLang The target value which match this configure Language. - @param[out] Value The returned value. - - @retval EFI_SUCCESS Value is returned successfully. - @retval Others Some error happened. - -**/ -typedef -EFI_STATUS -(EFIAPI *EDKII_REDFISH_PLATFORM_CONFIG_GET_VALUE) ( - IN EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL *This, - IN CHAR8 *Schema, - IN CHAR8 *Version, - IN EFI_STRING ConfigureLang, - OUT EDKII_REDFISH_VALUE *Value - ); - -/** - Set Redfish value with the given Schema and Configure Language. - - @param[in] This Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance. - @param[in] Schema The Redfish schema to query. - @param[in] Version The Redfish version to query. - @param[in] ConfigureLang The target value which match this configure Language. - @param[in] Value The value to set. - - @retval EFI_SUCCESS Value is returned successfully. - @retval Others Some error happened. - -**/ -typedef -EFI_STATUS -(EFIAPI *EDKII_REDFISH_PLATFORM_CONFIG_SET_VALUE) ( - IN EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL *This, - IN CHAR8 *Schema, - IN CHAR8 *Version, - IN EFI_STRING ConfigureLang, - IN EDKII_REDFISH_VALUE Value - ); - -/** - Get the list of Configure Language from platform configuration by the given Schema and Pattern. - - @param[in] This Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance. - @param[in] Schema The Redfish schema to query. - @param[in] Version The Redfish version to query. - @param[in] Pattern The target Configure Language pattern. - @param[out] ConfigureLangList The list of Configure Language. - @param[out] Count The number of Configure Language in ConfigureLangList. - - @retval EFI_SUCCESS ConfigureLangList is returned successfully. - @retval Others Some error happened. - -**/ -typedef -EFI_STATUS -(EFIAPI *EDKII_REDFISH_PLATFORM_CONFIG_GET_CONFIG_LANG) ( - IN EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL *This, - IN CHAR8 *Schema, - IN CHAR8 *Version, - IN EFI_STRING Pattern, - OUT EFI_STRING **ConfigureLangList, - OUT UINTN *Count - ); - - -/** - Get the list of supported Redfish schema from platform configuration on the give HII handle. - - @param[in] This Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance. - @param[in] HiiHandle The target handle to search. If handle is NULL, - this function returns all schema from HII database. - @param[out] SupportedSchema The supported schema list which is separated by ';'. - For example: "x-uefi-redfish-Memory.v1_7_1;x-uefi-redfish-Boot.v1_0_1" - The SupportedSchema is allocated by the callee. It's caller's - responsibility to free this buffer using FreePool(). - - @retval EFI_SUCCESS Schema is returned successfully. - @retval Others Some error happened. - -**/ -typedef -EFI_STATUS -(EFIAPI *EDKII_REDFISH_PLATFORM_CONFIG_GET_SUPPORTED_SCHEMA) ( - IN EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL *This, - IN EFI_HII_HANDLE HiiHandle, OPTIONAL - OUT CHAR8 **SupportedSchema - ); - -struct _EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL { - EDKII_REDFISH_PLATFORM_CONFIG_GET_VALUE GetValue; - EDKII_REDFISH_PLATFORM_CONFIG_SET_VALUE SetValue; - EDKII_REDFISH_PLATFORM_CONFIG_GET_CONFIG_LANG GetConfigureLang; - EDKII_REDFISH_PLATFORM_CONFIG_GET_SUPPORTED_SCHEMA GetSupportedSchema; -}; - -extern EFI_GUID gEdkIIRedfishPlatformConfigProtocolGuid; - -#endif +/** @file + This file defines the EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL interface. + + (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef EDKII_REDFISH_PLATFORM_CONFIG_H_ +#define EDKII_REDFISH_PLATFORM_CONFIG_H_ + +typedef struct _EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL; + +/** + Definition of EDKII_REDFISH_TYPE_VALUE + **/ +typedef union { + INT64 Integer; + BOOLEAN Boolean; + CHAR8 *Buffer; + CHAR8 **StringArray; + INT64 *IntegerArray; + BOOLEAN *BooleanArray; +} EDKII_REDFISH_TYPE_VALUE; + +/** + Definition of EDKII_REDFISH_VALUE_TYPES + **/ +typedef enum { + REDFISH_VALUE_TYPE_UNKNOWN = 0, + REDFISH_VALUE_TYPE_INTEGER, + REDFISH_VALUE_TYPE_BOOLEAN, + REDFISH_VALUE_TYPE_STRING, + REDFISH_VALUE_TYPE_STRING_ARRAY, + REDFISH_VALUE_TYPE_INTEGER_ARRAY, + REDFISH_VALUE_TYPE_BOOLEAN_ARRAY, + REDFISH_VALUE_TYPE_MAX +} EDKII_REDFISH_VALUE_TYPES; + +/** + Definition of EDKII_REDFISH_VALUE + **/ +typedef struct { + EDKII_REDFISH_VALUE_TYPES Type; + EDKII_REDFISH_TYPE_VALUE Value; + UINTN ArrayCount; +} EDKII_REDFISH_VALUE; + +/** + Get Redfish value with the given Schema and Configure Language. + + @param[in] This Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance. + @param[in] Schema The Redfish schema to query. + @param[in] Version The Redfish version to query. + @param[in] ConfigureLang The target value which match this configure Language. + @param[out] Value The returned value. + + @retval EFI_SUCCESS Value is returned successfully. + @retval Others Some error happened. + +**/ +typedef +EFI_STATUS +(EFIAPI *EDKII_REDFISH_PLATFORM_CONFIG_GET_VALUE) ( + IN EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL *This, + IN CHAR8 *Schema, + IN CHAR8 *Version, + IN EFI_STRING ConfigureLang, + OUT EDKII_REDFISH_VALUE *Value + ); + +/** + Set Redfish value with the given Schema and Configure Language. + + @param[in] This Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance. + @param[in] Schema The Redfish schema to query. + @param[in] Version The Redfish version to query. + @param[in] ConfigureLang The target value which match this configure Language. + @param[in] Value The value to set. + + @retval EFI_SUCCESS Value is returned successfully. + @retval Others Some error happened. + +**/ +typedef +EFI_STATUS +(EFIAPI *EDKII_REDFISH_PLATFORM_CONFIG_SET_VALUE) ( + IN EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL *This, + IN CHAR8 *Schema, + IN CHAR8 *Version, + IN EFI_STRING ConfigureLang, + IN EDKII_REDFISH_VALUE Value + ); + +/** + Get the list of Configure Language from platform configuration by the given Schema and RegexPattern. + + @param[in] This Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance. + @param[in] Schema The Redfish schema to query. + @param[in] Version The Redfish version to query. + @param[in] RegexPattern The target Configure Language pattern. This is used for regular expression matching. + @param[out] ConfigureLangList The list of Configure Language. + @param[out] Count The number of Configure Language in ConfigureLangList. + + @retval EFI_SUCCESS ConfigureLangList is returned successfully. + @retval Others Some error happened. + +**/ +typedef +EFI_STATUS +(EFIAPI *EDKII_REDFISH_PLATFORM_CONFIG_GET_CONFIG_LANG) ( + IN EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL *This, + IN CHAR8 *Schema, + IN CHAR8 *Version, + IN EFI_STRING RegexPattern, + OUT EFI_STRING **ConfigureLangList, + OUT UINTN *Count + ); + + +/** + Get the list of supported Redfish schema from platform configuration on the give HII handle. + + @param[in] This Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance. + @param[in] HiiHandle The target handle to search. If handle is NULL, + this function returns all schema from HII database. + @param[out] SupportedSchema The supported schema list which is separated by ';'. + For example: "x-uefi-redfish-Memory.v1_7_1;x-uefi-redfish-Boot.v1_0_1" + The SupportedSchema is allocated by the callee. It's caller's + responsibility to free this buffer using FreePool(). + + @retval EFI_SUCCESS Schema is returned successfully. + @retval Others Some error happened. + +**/ +typedef +EFI_STATUS +(EFIAPI *EDKII_REDFISH_PLATFORM_CONFIG_GET_SUPPORTED_SCHEMA) ( + IN EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL *This, + IN EFI_HII_HANDLE HiiHandle, OPTIONAL + OUT CHAR8 **SupportedSchema + ); + +struct _EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL { + EDKII_REDFISH_PLATFORM_CONFIG_GET_VALUE GetValue; + EDKII_REDFISH_PLATFORM_CONFIG_SET_VALUE SetValue; + EDKII_REDFISH_PLATFORM_CONFIG_GET_CONFIG_LANG GetConfigureLang; + EDKII_REDFISH_PLATFORM_CONFIG_GET_SUPPORTED_SCHEMA GetSupportedSchema; +}; + +extern EFI_GUID gEdkIIRedfishPlatformConfigProtocolGuid; + +#endif diff --git a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.c b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.c index 67818cccd2..971035f27d 100644 --- a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.c +++ b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.c @@ -1,1304 +1,1783 @@ -/** @file - - The implementation of EDKII Redfidh Platform Config Protocol. - - (C) Copyright 2021 Hewlett Packard Enterprise Development LP
- - SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#include "RedfishPlatformConfigDxe.h" -#include "RedfishPlatformConfigImpl.h" - -REDFISH_PLATFORM_CONFIG_PRIVATE *mRedfishPlatformConfigPrivate = NULL; - -/** - Compare two value in HII statement format. - - @param[in] Value1 Firt value to compare. - @param[in] Value2 Second value to be compared. - - @retval UINTN 0 is retuned when two values are equal. - 1 is returned when first value is greater than second value. - -1 is returned when second value is greater than first value. - -**/ -UINTN -CompareHiiStatementValue ( - IN HII_STATEMENT_VALUE *Value1, - IN HII_STATEMENT_VALUE *Value2 - ) -{ - INTN Result; - UINT64 Data1; - UINT64 Data2; - - if (Value1 == NULL || Value2 == NULL) { - return 0xFF; - } - - switch (Value1->Type) { - case EFI_IFR_TYPE_NUM_SIZE_8: - Data1 = Value1->Value.u8; - break; - case EFI_IFR_TYPE_NUM_SIZE_16: - Data1 = Value1->Value.u16; - break; - case EFI_IFR_TYPE_NUM_SIZE_32: - Data1 = Value1->Value.u32; - break; - case EFI_IFR_TYPE_NUM_SIZE_64: - Data1 = Value1->Value.u64; - break; - case EFI_IFR_TYPE_BOOLEAN: - Data1 = (Value1->Value.b ? 1 : 0); - break; - default: - return 0xFF; - } - - switch (Value2->Type) { - case EFI_IFR_TYPE_NUM_SIZE_8: - Data2 = Value2->Value.u8; - break; - case EFI_IFR_TYPE_NUM_SIZE_16: - Data2 = Value2->Value.u16; - break; - case EFI_IFR_TYPE_NUM_SIZE_32: - Data2 = Value2->Value.u32; - break; - case EFI_IFR_TYPE_NUM_SIZE_64: - Data2 = Value2->Value.u64; - break; - case EFI_IFR_TYPE_BOOLEAN: - Data2 = (Value2->Value.b ? 1 : 0); - break; - default: - return 0xFF; - } - - Result = (Data1 == Data2 ? 0 : (Data1 > Data2 ? 1 : -1)); - - return Result; -} - -/** - Convert HII value to the string in HII one-of opcode. - - @param[in] Statement Statement private instance - - @retval EFI_STRING_ID The string ID in HII database. - 0 is returned when something goes wrong. - -**/ -EFI_STRING_ID -HiiValueToOneOfOptionStringId ( - IN REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *Statement - ) -{ - LIST_ENTRY *Link; - HII_QUESTION_OPTION *Option; - - if (Statement->HiiStatement->Operand != EFI_IFR_ONE_OF_OP) { - return 0; - } - - if (IsListEmpty (&Statement->HiiStatement->OptionListHead)) { - return 0; - } - - Link = GetFirstNode (&Statement->HiiStatement->OptionListHead); - while (!IsNull (&Statement->HiiStatement->OptionListHead, Link)) { - Option = HII_QUESTION_OPTION_FROM_LINK (Link); - - if (CompareHiiStatementValue (&Statement->HiiStatement->Value, &Option->Value) == 0) { - return Option->Text; - } - - Link = GetNextNode (&Statement->HiiStatement->OptionListHead, Link); - } - - return 0; -} - -/** - Convert HII string to the value in HII one-of opcode. - - @param[in] Statement Statement private instance - @param[in] Schema Schema string - @param[in] HiiString Input string - @param[out] Value Value returned - - @retval EFI_SUCCESS HII value is returned successfully. - @retval Others Errors occur - -**/ -EFI_STATUS -HiiStringToOneOfOptionValue ( - IN REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *Statement, - IN CHAR8 *Schema, - IN EFI_STRING HiiString, - OUT HII_STATEMENT_VALUE *Value - ) -{ - LIST_ENTRY *Link; - HII_QUESTION_OPTION *Option; - EFI_STRING TmpString; - BOOLEAN Found; - - if (Statement == NULL || IS_EMPTY_STRING (HiiString) || Value == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (Statement->HiiStatement->Operand != EFI_IFR_ONE_OF_OP) { - return EFI_UNSUPPORTED; - } - - if (IsListEmpty (&Statement->HiiStatement->OptionListHead)) { - return EFI_NOT_FOUND; - } - - Found = FALSE; - Link = GetFirstNode (&Statement->HiiStatement->OptionListHead); - while (!IsNull (&Statement->HiiStatement->OptionListHead, Link)) { - Option = HII_QUESTION_OPTION_FROM_LINK (Link); - - TmpString = HiiGetRedfishString (Statement->ParentForm->ParentFormset->HiiHandle, Schema, Option->Text); - if (TmpString != NULL) { - if (StrCmp (TmpString, HiiString) == 0) { - CopyMem (Value, &Option->Value, sizeof (HII_STATEMENT_VALUE)); - Found = TRUE; - } - FreePool (TmpString); - } - - if (Found) { - return EFI_SUCCESS; - } - - Link = GetNextNode (&Statement->HiiStatement->OptionListHead, Link); - } - - return EFI_NOT_FOUND; -} - -/** - Convert HII value to numeric value in Redfish format. - - @param[in] Value Value to be converted. - @param[out] RedfishValue Value in Redfish format. - - @retval EFI_SUCCESS Redfish value is returned successfully. - @retval Others Errors occur - -**/ -EFI_STATUS -HiiValueToRedfishNumeric ( - IN HII_STATEMENT_VALUE *Value, - OUT EDKII_REDFISH_VALUE *RedfishValue - ) -{ - if (Value == NULL || RedfishValue == NULL) { - return EFI_INVALID_PARAMETER; - } - - switch (Value->Type) { - case EFI_IFR_TYPE_NUM_SIZE_8: - RedfishValue->Type = REDFISH_VALUE_TYPE_INTEGER; - RedfishValue->Value.Integer = (INT64)Value->Value.u8; - break; - case EFI_IFR_TYPE_NUM_SIZE_16: - RedfishValue->Type = REDFISH_VALUE_TYPE_INTEGER; - RedfishValue->Value.Integer = (INT64)Value->Value.u16; - break; - case EFI_IFR_TYPE_NUM_SIZE_32: - RedfishValue->Type = REDFISH_VALUE_TYPE_INTEGER; - RedfishValue->Value.Integer = (INT64)Value->Value.u32; - break; - case EFI_IFR_TYPE_NUM_SIZE_64: - RedfishValue->Type = REDFISH_VALUE_TYPE_INTEGER; - RedfishValue->Value.Integer = (INT64)Value->Value.u64; - break; - case EFI_IFR_TYPE_BOOLEAN: - RedfishValue->Type = REDFISH_VALUE_TYPE_BOOLEAN; - RedfishValue->Value.Boolean = Value->Value.b; - break; - default: - RedfishValue->Type = REDFISH_VALUE_TYPE_UNKNOWN; - break; - } - - return EFI_SUCCESS; -} - -/** - Convert numeric value in Redfish format to HII value. - - @param[in] RedfishValue Value in Redfish format to be converted. - @param[out] Value HII value returned. - - @retval EFI_SUCCESS HII value is returned successfully. - @retval Others Errors occur - -**/ -EFI_STATUS -RedfishNumericToHiiValue ( - IN EDKII_REDFISH_VALUE *RedfishValue, - OUT HII_STATEMENT_VALUE *Value - ) -{ - if (Value == NULL || RedfishValue == NULL) { - return EFI_INVALID_PARAMETER; - } - - switch (RedfishValue->Type) { - case REDFISH_VALUE_TYPE_INTEGER: - Value->Type = EFI_IFR_TYPE_NUM_SIZE_64; - Value->Value.u64 = (UINT64)RedfishValue->Value.Integer; - break; - case REDFISH_VALUE_TYPE_BOOLEAN: - Value->Type = EFI_IFR_TYPE_BOOLEAN; - Value->Value.b = RedfishValue->Value.Boolean; - break; - default: - Value->Type = EFI_IFR_TYPE_UNDEFINED; - break; - } - - return EFI_SUCCESS; -} - -/** - Return the full Redfish schema string from the given Schema and Version. - - Returned schema string is: Schema + '.' + Version - - @param[in] Schema Schema string - @param[in] Version Schema version string - - @retval CHAR8 * Schema string. NULL when errors occur. - -**/ -CHAR8 * -GetFullSchemaString ( - IN CHAR8 *Schema, - IN CHAR8 *Version - ) -{ - UINTN Size; - CHAR8 *FullName; - - if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version)) { - return NULL; - } - - Size = AsciiStrSize(CONFIGURE_LANGUAGE_PREFIX) + AsciiStrSize (Schema) + AsciiStrSize (Version); - - FullName = AllocatePool (Size); - if (FullName == NULL) { - DEBUG ((DEBUG_ERROR, "%a, out-of-resource\n", __FUNCTION__)); - return NULL; - } - - AsciiSPrint (FullName, Size, "%a%a.%a", CONFIGURE_LANGUAGE_PREFIX, Schema, Version); - - return FullName; -} - -/** - Common implementation to get statement private instance. - - @param[in] RedfishPlatformConfigPrivate Private instance. - @param[in] Schema Redfish schema string. - @param[in] ConfigureLang Configure language that refers to this statement. - @param[out] Statement Statement instance - - @retval EFI_SUCCESS HII value is returned successfully. - @retval Others Errors occur - -**/ -EFI_STATUS -RedfishPlatformConfigGetStatementCommon ( - IN REDFISH_PLATFORM_CONFIG_PRIVATE *RedfishPlatformConfigPrivate, - IN CHAR8 *Schema, - IN EFI_STRING ConfigureLang, - OUT REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE **Statement - ) -{ - EFI_STATUS Status; - REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *TargetStatement; - - if (RedfishPlatformConfigPrivate == NULL || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (ConfigureLang) || Statement == NULL) { - return EFI_INVALID_PARAMETER; - } - - *Statement = NULL; - - Status = ProcessPendingList (&RedfishPlatformConfigPrivate->FormsetList, &RedfishPlatformConfigPrivate->PendingList); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a, ProcessPendingList failure: %r\n", __FUNCTION__, Status)); - return Status; - } - - TargetStatement = GetStatementPrivateByConfigureLang (&RedfishPlatformConfigPrivate->FormsetList, Schema, ConfigureLang); - if (TargetStatement == NULL) { - DEBUG ((DEBUG_ERROR, "%a, No match HII statement is found by the given %s in schema %a\n", __FUNCTION__, ConfigureLang, Schema)); - return EFI_NOT_FOUND; - } - - // - // Find current HII question value. - // - Status = GetQuestionValue ( - TargetStatement->ParentForm->ParentFormset->HiiFormSet, - TargetStatement->ParentForm->HiiForm, - TargetStatement->HiiStatement, - GetSetValueWithHiiDriver - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a, failed to get question current value: %r\n", __FUNCTION__, Status)); - return Status; - } - - - if (TargetStatement->HiiStatement->Value.Type == EFI_IFR_TYPE_UNDEFINED) { - return EFI_DEVICE_ERROR; - } - - // - // Return Value. - // - *Statement = TargetStatement; - - return EFI_SUCCESS; -} - -/** - Get Redfish value with the given Schema and Configure Language. - - @param[in] This Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance. - @param[in] Schema The Redfish schema to query. - @param[in] Version The Redfish version to query. - @param[in] ConfigureLang The target value which match this configure Language. - @param[out] Value The returned value. - - @retval EFI_SUCCESS Value is returned successfully. - @retval Others Some error happened. - -**/ -EFI_STATUS -EFIAPI -RedfishPlatformConfigProtocolGetValue ( - IN EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL *This, - IN CHAR8 *Schema, - IN CHAR8 *Version, - IN EFI_STRING ConfigureLang, - OUT EDKII_REDFISH_VALUE *Value - ) -{ - EFI_STATUS Status; - REDFISH_PLATFORM_CONFIG_PRIVATE *RedfishPlatformConfigPrivate; - REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *TargetStatement; - EFI_STRING_ID StringId; - CHAR8 *FullSchema; - EFI_STRING HiiString; - UINTN Size; - - if (This == NULL || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || IS_EMPTY_STRING (ConfigureLang) || Value == NULL) { - return EFI_INVALID_PARAMETER; - } - - RedfishPlatformConfigPrivate = REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS (This); - Value->Type = REDFISH_VALUE_TYPE_UNKNOWN; - FullSchema = NULL; - HiiString = NULL; - - FullSchema = GetFullSchemaString (Schema, Version); - if (FullSchema == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - Status = RedfishPlatformConfigGetStatementCommon (RedfishPlatformConfigPrivate, FullSchema, ConfigureLang, &TargetStatement); - if (EFI_ERROR (Status)) { - goto RELEASE_RESOURCE; - } - - switch (TargetStatement->HiiStatement->Operand) { - case EFI_IFR_ONE_OF_OP: - StringId = HiiValueToOneOfOptionStringId (TargetStatement); - if (StringId == 0) { - ASSERT (FALSE); - Status = EFI_DEVICE_ERROR; - goto RELEASE_RESOURCE; - } - - HiiString = HiiGetRedfishString (TargetStatement->ParentForm->ParentFormset->HiiHandle, FullSchema, StringId); - if (HiiString == NULL) { - DEBUG ((DEBUG_ERROR, "%a, Can not find string ID: 0x%x with %a\n", __FUNCTION__, StringId, FullSchema)); - Status = EFI_NOT_FOUND; - goto RELEASE_RESOURCE; - } - - Size = StrLen (HiiString) + 1; - Value->Value.Buffer = AllocatePool (Size); - if (Value->Value.Buffer == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto RELEASE_RESOURCE; - } - - UnicodeStrToAsciiStrS (HiiString, Value->Value.Buffer, Size); - Value->Type = REDFISH_VALUE_TYPE_STRING; - - break; - case EFI_IFR_STRING_OP: - if (TargetStatement->HiiStatement->Value.Type != EFI_IFR_TYPE_STRING) { - ASSERT (FALSE); - Status = EFI_DEVICE_ERROR; - goto RELEASE_RESOURCE; - } - - Value->Type = REDFISH_VALUE_TYPE_STRING; - Value->Value.Buffer = AllocateCopyPool (StrSize ((CHAR16 *)TargetStatement->HiiStatement->Value.Buffer), TargetStatement->HiiStatement->Value.Buffer); - if (Value->Value.Buffer == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto RELEASE_RESOURCE; - } - break; - case EFI_IFR_CHECKBOX_OP: - case EFI_IFR_NUMERIC_OP: - Status = HiiValueToRedfishNumeric (&TargetStatement->HiiStatement->Value, Value); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a, failed to convert HII value to Redfish value: %r\n", __FUNCTION__, Status)); - goto RELEASE_RESOURCE; - } - break; - default: - DEBUG ((DEBUG_ERROR, "%a, catch unsupported type: 0x%x! Please contact with author if we need to support this type.\n", __FUNCTION__, TargetStatement->HiiStatement->Operand)); - ASSERT (FALSE); - Status = EFI_UNSUPPORTED; - goto RELEASE_RESOURCE; - } - -RELEASE_RESOURCE: - - if (FullSchema != NULL) { - FreePool (FullSchema); - } - - if (HiiString != NULL) { - FreePool (HiiString); - } - - return Status; -} - -/** - Function to save question value into HII database. - - @param[in] HiiFormset HII form-set instance - @param[in] HiiForm HII form instance - @param[in] HiiStatement HII statement that keeps new value. - @param[in] Value New value to applyu. - - @retval EFI_SUCCESS HII value is returned successfully. - @retval Others Errors occur - -**/ -EFI_STATUS -RedfishPlatformConfigSaveQuestionValue ( - IN HII_FORMSET *HiiFormset, - IN HII_FORM *HiiForm, - IN HII_STATEMENT *HiiStatement, - IN HII_STATEMENT_VALUE *Value - ) -{ - EFI_STATUS Status; - - if (HiiFormset == NULL || HiiForm == NULL || HiiStatement == NULL || Value == NULL) { - return EFI_INVALID_PARAMETER; - } - - Status = SetQuestionValue ( - HiiFormset, - HiiForm, - HiiStatement, - Value - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a, failed to set question value: %r\n", __FUNCTION__, Status)); - return Status; - } - - Status = SubmitForm (HiiFormset, HiiForm); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a, failed to submit form: %r\n", __FUNCTION__, Status)); - return Status; - } - - return EFI_SUCCESS; -} - -/** - Common implementation to set statement private instance. - - @param[in] RedfishPlatformConfigPrivate Private instance. - @param[in] Schema Redfish schema string. - @param[in] ConfigureLang Configure language that refers to this statement. - @param[in] Statement Statement instance - - @retval EFI_SUCCESS HII value is returned successfully. - @retval Others Errors occur - -**/ -EFI_STATUS -RedfishPlatformConfigSetStatementCommon ( - IN REDFISH_PLATFORM_CONFIG_PRIVATE *RedfishPlatformConfigPrivate, - IN CHAR8 *Schema, - IN EFI_STRING ConfigureLang, - IN HII_STATEMENT_VALUE *StatementValue - ) -{ - EFI_STATUS Status; - REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *TargetStatement; - EFI_STRING TempBuffer; - - if (RedfishPlatformConfigPrivate == NULL || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (ConfigureLang) || StatementValue == NULL) { - return EFI_INVALID_PARAMETER; - } - - TempBuffer = NULL; - - Status = ProcessPendingList (&RedfishPlatformConfigPrivate->FormsetList, &RedfishPlatformConfigPrivate->PendingList); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a, ProcessPendingList failure: %r\n", __FUNCTION__, Status)); - return Status; - } - - TargetStatement = GetStatementPrivateByConfigureLang (&RedfishPlatformConfigPrivate->FormsetList, Schema, ConfigureLang); - if (TargetStatement == NULL) { - DEBUG ((DEBUG_ERROR, "%a, No match HII statement is found by the given %s in schema %a\n", __FUNCTION__, ConfigureLang, Schema)); - return EFI_NOT_FOUND; - } - - if (StatementValue->Type != TargetStatement->HiiStatement->Value.Type) { - // - // We treat one-of type as string in Redfish. But one-of statement is not - // in string format from HII point of view. Do a patch here. - // - if (TargetStatement->HiiStatement->Operand == EFI_IFR_ONE_OF_OP && StatementValue->Type == EFI_IFR_TYPE_STRING) { - TempBuffer = AllocatePool (StatementValue->BufferLen * sizeof (CHAR16)); - if (TempBuffer == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - AsciiStrToUnicodeStrS (StatementValue->Buffer, TempBuffer, StatementValue->BufferLen); - FreePool (StatementValue->Buffer); - StatementValue->Buffer = NULL; - StatementValue->BufferLen = 0; - - Status = HiiStringToOneOfOptionValue (TargetStatement, Schema, TempBuffer, StatementValue); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a, failed to find option value by the given %s\n", __FUNCTION__, TempBuffer)); - FreePool (TempBuffer); - return EFI_NOT_FOUND; - } - - FreePool (TempBuffer); - } else if (TargetStatement->HiiStatement->Operand == EFI_IFR_NUMERIC_OP && StatementValue->Type == EFI_IFR_TYPE_NUM_SIZE_64) { - // - // Redfish only has numeric value type and it does not care about the value size. - // Do a patch here so we have proper value size applied. - // - StatementValue->Type = TargetStatement->HiiStatement->Value.Type; - } else { - DEBUG ((DEBUG_ERROR, "%a, catch value type mismatch! input type: 0x%x but target value type: 0x%x\n", __FUNCTION__, StatementValue->Type, TargetStatement->HiiStatement->Value.Type)); - ASSERT (FALSE); - } - } - - Status = RedfishPlatformConfigSaveQuestionValue ( - TargetStatement->ParentForm->ParentFormset->HiiFormSet, - TargetStatement->ParentForm->HiiForm, - TargetStatement->HiiStatement, - StatementValue - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a, failed to save question value: %r\n", __FUNCTION__, Status)); - return Status; - } - - return EFI_SUCCESS; -} - -/** - Set Redfish value with the given Schema and Configure Language. - - @param[in] This Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance. - @param[in] Schema The Redfish schema to query. - @param[in] Version The Redfish version to query. - @param[in] ConfigureLang The target value which match this configure Language. - @param[in] Value The value to set. - - @retval EFI_SUCCESS Value is returned successfully. - @retval Others Some error happened. - -**/ -EFI_STATUS -EFIAPI -RedfishPlatformConfigProtocolSetValue ( - IN EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL *This, - IN CHAR8 *Schema, - IN CHAR8 *Version, - IN EFI_STRING ConfigureLang, - IN EDKII_REDFISH_VALUE Value - ) -{ - EFI_STATUS Status; - REDFISH_PLATFORM_CONFIG_PRIVATE *RedfishPlatformConfigPrivate; - CHAR8 *FullSchema; - HII_STATEMENT_VALUE NewValue; - - if (This == NULL || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || IS_EMPTY_STRING (ConfigureLang)) { - return EFI_INVALID_PARAMETER; - } - - if (Value.Type == REDFISH_VALUE_TYPE_UNKNOWN || Value.Type >= REDFISH_VALUE_TYPE_MAX) { - return EFI_INVALID_PARAMETER; - } - - RedfishPlatformConfigPrivate = REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS (This); - FullSchema = NULL; - - FullSchema = GetFullSchemaString (Schema, Version); - if (FullSchema == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - ZeroMem (&NewValue, sizeof (HII_STATEMENT_VALUE)); - - switch (Value.Type) { - case REDFISH_VALUE_TYPE_INTEGER: - case REDFISH_VALUE_TYPE_BOOLEAN: - Status = RedfishNumericToHiiValue (&Value, &NewValue); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a, failed to convert Redfish value to Hii value: %r\n", __FUNCTION__, Status)); - goto RELEASE_RESOURCE; - } - break; - case REDFISH_VALUE_TYPE_STRING: - NewValue.Type = EFI_IFR_TYPE_STRING; - NewValue.BufferLen = (UINT16)AsciiStrSize (Value.Value.Buffer); - NewValue.Buffer = AllocateCopyPool (NewValue.BufferLen, Value.Value.Buffer); - if (NewValue.Buffer == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto RELEASE_RESOURCE; - } - break; - default: - ASSERT (FALSE); - break; - } - - Status = RedfishPlatformConfigSetStatementCommon (RedfishPlatformConfigPrivate, FullSchema, ConfigureLang, &NewValue); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a, failed to set value to statement: %r\n", __FUNCTION__, Status)); - } - -RELEASE_RESOURCE: - - if (FullSchema != NULL) { - FreePool (FullSchema); - } - - return Status; -} - -/** - Get the list of Configure Language from platform configuration by the given Schema and Pattern. - - @param[in] This Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance. - @param[in] Schema The Redfish schema to query. - @param[in] Version The Redfish version to query. - @param[in] Pattern The target Configure Language pattern. - @param[out] ConfigureLangList The list of Configure Language. - @param[out] Count The number of Configure Language in ConfigureLangList. - - @retval EFI_SUCCESS ConfigureLangList is returned successfully. - @retval Others Some error happened. - -**/ -EFI_STATUS -EFIAPI -RedfishPlatformConfigProtocolGetConfigureLang ( - IN EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL *This, - IN CHAR8 *Schema, - IN CHAR8 *Version, - IN EFI_STRING Pattern, - OUT EFI_STRING **ConfigureLangList, - OUT UINTN *Count - ) -{ - REDFISH_PLATFORM_CONFIG_PRIVATE *RedfishPlatformConfigPrivate; - EFI_STATUS Status; - REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST StatementList; - REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF *StatementRef; - LIST_ENTRY *NextLink; - EFI_STRING TmpString; - EFI_STRING *TmpConfigureLangList; - UINTN Index; - CHAR8 *FullSchema; - - if (This == NULL || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || Count == NULL || ConfigureLangList == NULL || IS_EMPTY_STRING (Pattern)) { - return EFI_INVALID_PARAMETER; - } - - *Count = 0; - *ConfigureLangList = NULL; - FullSchema = NULL; - RedfishPlatformConfigPrivate = REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS (This); - - Status = ProcessPendingList (&RedfishPlatformConfigPrivate->FormsetList, &RedfishPlatformConfigPrivate->PendingList); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a, ProcessPendingList failure: %r\n", __FUNCTION__, Status)); - return Status; - } - - FullSchema = GetFullSchemaString (Schema, Version); - if (FullSchema == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - Status = GetStatementPrivateByConfigureLangRegex ( - RedfishPlatformConfigPrivate->RegularExpressionProtocol, - &RedfishPlatformConfigPrivate->FormsetList, - FullSchema, - Pattern, - &StatementList - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a, GetStatementPrivateByConfigureLangRegex failure: %r\n", __FUNCTION__, Status)); - goto RELEASE_RESOURCE; - } - - if (!IsListEmpty (&StatementList.StatementList)) { - - TmpConfigureLangList = AllocateZeroPool (sizeof (CHAR16 *) * StatementList.Count); - if (TmpConfigureLangList == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto RELEASE_RESOURCE; - } - - Index = 0; - NextLink = GetFirstNode (&StatementList.StatementList); - while (!IsNull (&StatementList.StatementList, NextLink)) { - StatementRef = REDFISH_PLATFORM_CONFIG_STATEMENT_REF_FROM_LINK (NextLink); - NextLink = GetNextNode (&StatementList.StatementList, NextLink); - - ASSERT (StatementRef->Statement->Description != 0); - if (StatementRef->Statement->Description != 0) { - TmpString = HiiGetRedfishString (StatementRef->Statement->ParentForm->ParentFormset->HiiHandle, FullSchema, StatementRef->Statement->Description); - ASSERT (TmpString != NULL); - if (TmpString != NULL) { - TmpConfigureLangList[Index] = AllocateCopyPool (StrSize (TmpString), TmpString); - ASSERT (TmpConfigureLangList[Index] != NULL); - FreePool (TmpString); - ++Index; - } - } - } - } - - *Count = StatementList.Count; - *ConfigureLangList = TmpConfigureLangList; - -RELEASE_RESOURCE: - - if (FullSchema != NULL) { - FreePool (FullSchema); - } - - ReleaseStatementList (&StatementList); - - return Status; -} - - -/** - Get the list of supported Redfish schema from paltform configuration on give HII handle. - - @param[in] This Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance. - @param[in] HiiHandle The target handle to search. If handle is NULL, - this function return all schema from HII database. - @param[out] SupportedSchema The supported schema list which is separated by ';'. - The SupportedSchema is allocated by the callee. It's caller's - responsibility to free this buffer using FreePool(). - - @retval EFI_SUCCESS Schema is returned successfully. - @retval Others Some error happened. - -**/ -EFI_STATUS -EFIAPI -RedfishPlatformConfigProtocolGetSupportedSchema ( - IN EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL *This, - IN EFI_HII_HANDLE HiiHandle, OPTIONAL - OUT CHAR8 **SupportedSchema - ) -{ - REDFISH_PLATFORM_CONFIG_PRIVATE *RedfishPlatformConfigPrivate; - EFI_STATUS Status; - LIST_ENTRY *HiiFormsetLink; - LIST_ENTRY *HiiFormsetNextLink; - REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *HiiFormsetPrivate; - UINTN Index; - UINTN StringSize; - CHAR8 *StringBuffer; - UINTN StringIndex; - - if (This == NULL || SupportedSchema == NULL) { - return EFI_INVALID_PARAMETER; - } - - *SupportedSchema = NULL; - - RedfishPlatformConfigPrivate = REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS (This); - - Status = ProcessPendingList (&RedfishPlatformConfigPrivate->FormsetList, &RedfishPlatformConfigPrivate->PendingList); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a, ProcessPendingList failure: %r\n", __FUNCTION__, Status)); - return Status; - } - - if (IsListEmpty (&RedfishPlatformConfigPrivate->FormsetList)) { - return EFI_NOT_FOUND; - } - - // - // Calculate for string buffer size. - // - StringSize = 0; - HiiFormsetLink = GetFirstNode (&RedfishPlatformConfigPrivate->FormsetList); - while (!IsNull (&RedfishPlatformConfigPrivate->FormsetList, HiiFormsetLink)) { - HiiFormsetNextLink = GetNextNode (&RedfishPlatformConfigPrivate->FormsetList, HiiFormsetLink); - HiiFormsetPrivate = REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink); - - if (HiiHandle != NULL && HiiHandle != HiiFormsetPrivate->HiiHandle) { - HiiFormsetLink = HiiFormsetNextLink; - continue; - } - - if (HiiFormsetPrivate->SupportedSchema.Count > 0) { - for (Index = 0; Index < HiiFormsetPrivate->SupportedSchema.Count; Index++) { - StringSize += AsciiStrSize (HiiFormsetPrivate->SupportedSchema.SchemaList[Index]); - } - } - - HiiFormsetLink = HiiFormsetNextLink; - } - - if (StringSize == 0) { - return EFI_NOT_FOUND; - } - - StringBuffer = AllocatePool (StringSize); - if (StringBuffer == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - StringIndex = 0; - HiiFormsetLink = GetFirstNode (&RedfishPlatformConfigPrivate->FormsetList); - while (!IsNull (&RedfishPlatformConfigPrivate->FormsetList, HiiFormsetLink)) { - HiiFormsetNextLink = GetNextNode (&RedfishPlatformConfigPrivate->FormsetList, HiiFormsetLink); - HiiFormsetPrivate = REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink); - - if (HiiHandle != NULL && HiiHandle != HiiFormsetPrivate->HiiHandle) { - HiiFormsetLink = HiiFormsetNextLink; - continue; - } - - if (HiiFormsetPrivate->SupportedSchema.Count > 0) { - for (Index = 0; Index < HiiFormsetPrivate->SupportedSchema.Count; Index++) { - AsciiStrCpyS (&StringBuffer[StringIndex], (StringSize - StringIndex), HiiFormsetPrivate->SupportedSchema.SchemaList[Index]); - StringIndex += AsciiStrLen (HiiFormsetPrivate->SupportedSchema.SchemaList[Index]); - StringBuffer[StringIndex] = ';'; - ++StringIndex; - } - } - - HiiFormsetLink = HiiFormsetNextLink; - } - - StringBuffer[--StringIndex] = '\0'; - - *SupportedSchema = StringBuffer; - - return EFI_SUCCESS; -} - -/** - Functions which are registered to receive notification of - database events have this prototype. The actual event is encoded - in NotifyType. The following table describes how PackageType, - PackageGuid, Handle, and Package are used for each of the - notification types. - - @param[in] PackageType Package type of the notification. - @param[in] PackageGuid If PackageType is - EFI_HII_PACKAGE_TYPE_GUID, then this is - the pointer to the GUID from the Guid - field of EFI_HII_PACKAGE_GUID_HEADER. - Otherwise, it must be NULL. - @param[in] Package Points to the package referred to by the - notification Handle The handle of the package - list which contains the specified package. - @param[in] Handle The HII handle. - @param[in] NotifyType The type of change concerning the - database. See - EFI_HII_DATABASE_NOTIFY_TYPE. - -**/ -EFI_STATUS -EFIAPI -RedfishPlatformConfigFormUpdateNotify ( - IN UINT8 PackageType, - IN CONST EFI_GUID *PackageGuid, - IN CONST EFI_HII_PACKAGE_HEADER *Package, - IN EFI_HII_HANDLE Handle, - IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType - ) -{ - EFI_STATUS Status; - - if (NotifyType == EFI_HII_DATABASE_NOTIFY_NEW_PACK || NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) { - // - // HII formset on this handle is updated by driver during run-time. The formset needs to be reloaded. - // - Status = NotifyFormsetUpdate (Handle, &mRedfishPlatformConfigPrivate->PendingList); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a, failed to notify updated formset of HII handle: 0x%x\n", __FUNCTION__, Handle)); - return Status; - } - } else if (NotifyType == EFI_HII_DATABASE_NOTIFY_REMOVE_PACK) { - // - // HII resource is removed. The formset is no longer exist. - // - Status = NotifyFormsetDeleted (Handle, &mRedfishPlatformConfigPrivate->PendingList); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a, failed to notify deleted formset of HII handle: 0x%x\n", __FUNCTION__, Handle)); - return Status; - } - } - - return EFI_SUCCESS; -} - -/** - This is a EFI_HII_STRING_PROTOCOL notification event handler. - - Install HII package notification. - - @param[in] Event Event whose notification function is being invoked. - @param[in] Context Pointer to the notification function's context. - -**/ -VOID -EFIAPI -HiiStringProtocolInstalled ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - EFI_STATUS Status; - - // - // Locate HII database protocol. - // - Status = gBS->LocateProtocol ( - &gEfiHiiStringProtocolGuid, - NULL, - (VOID **)&mRedfishPlatformConfigPrivate->HiiString - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a, locate EFI_HII_STRING_PROTOCOL failure: %r\n", __FUNCTION__, Status)); - return; - } - - gBS->CloseEvent (Event); - mRedfishPlatformConfigPrivate->HiiStringNotify.ProtocolEvent = NULL; -} - -/** - This is a EFI_HII_DATABASE_PROTOCOL notification event handler. - - Install HII package notification. - - @param[in] Event Event whose notification function is being invoked. - @param[in] Context Pointer to the notification function's context. - -**/ -VOID -EFIAPI -HiiDatabaseProtocolInstalled ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - EFI_STATUS Status; - - // - // Locate HII database protocol. - // - Status = gBS->LocateProtocol ( - &gEfiHiiDatabaseProtocolGuid, - NULL, - (VOID **)&mRedfishPlatformConfigPrivate->HiiDatabase - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a, locate EFI_HII_DATABASE_PROTOCOL failure: %r\n", __FUNCTION__, Status)); - return; - } - - // - // Register package notification when new form package is installed. - // - Status = mRedfishPlatformConfigPrivate->HiiDatabase->RegisterPackageNotify ( - mRedfishPlatformConfigPrivate->HiiDatabase, - EFI_HII_PACKAGE_FORMS, - NULL, - RedfishPlatformConfigFormUpdateNotify, - EFI_HII_DATABASE_NOTIFY_NEW_PACK, - &mRedfishPlatformConfigPrivate->NotifyHandle - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a, RegisterPackageNotify for EFI_HII_DATABASE_NOTIFY_NEW_PACK failure: %r\n", __FUNCTION__, Status)); - } - - // - // Register package notification when new form package is updated. - // - Status = mRedfishPlatformConfigPrivate->HiiDatabase->RegisterPackageNotify ( - mRedfishPlatformConfigPrivate->HiiDatabase, - EFI_HII_PACKAGE_FORMS, - NULL, - RedfishPlatformConfigFormUpdateNotify, - EFI_HII_DATABASE_NOTIFY_ADD_PACK, - &mRedfishPlatformConfigPrivate->NotifyHandle - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a, RegisterPackageNotify for EFI_HII_DATABASE_NOTIFY_NEW_PACK failure: %r\n", __FUNCTION__, Status)); - } - -#if REDFISH_PLATFORM_CONFIG_DELETE_EXPIRED_FORMSET - // - // Register package notification when new form package is removed. - // - Status = mRedfishPlatformConfigPrivate->HiiDatabase->RegisterPackageNotify ( - mRedfishPlatformConfigPrivate->HiiDatabase, - EFI_HII_PACKAGE_FORMS, - NULL, - RedfishPlatformConfigFormUpdateNotify, - EFI_HII_DATABASE_NOTIFY_REMOVE_PACK, - &mRedfishPlatformConfigPrivate->NotifyHandle - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a, RegisterPackageNotify for EFI_HII_DATABASE_NOTIFY_NEW_PACK failure: %r\n", __FUNCTION__, Status)); - } -#endif - - gBS->CloseEvent (Event); - mRedfishPlatformConfigPrivate->HiiDbNotify.ProtocolEvent = NULL; - -} - -/** - This is a EFI_REGULAR_EXPRESSION_PROTOCOL notification event handler. - - @param[in] Event Event whose notification function is being invoked. - @param[in] Context Pointer to the notification function's context. - -**/ -VOID -EFIAPI -RegexProtocolInstalled ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - EFI_STATUS Status; - - // - // Locate regular expression protocol. - // - Status = gBS->LocateProtocol ( - &gEfiRegularExpressionProtocolGuid, - NULL, - (VOID **)&mRedfishPlatformConfigPrivate->RegularExpressionProtocol - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a, locate EFI_REGULAR_EXPRESSION_PROTOCOL failure: %r\n", __FUNCTION__, Status)); - return; - } - - gBS->CloseEvent (Event); - mRedfishPlatformConfigPrivate->RegexNotify.ProtocolEvent = NULL; - -} - -/** - Unloads an image. - - @param ImageHandle Handle that identifies the image to be unloaded. - - @retval EFI_SUCCESS The image has been unloaded. - @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle. - -**/ -EFI_STATUS -EFIAPI -RedfishPlatformConfigDxeUnload ( - IN EFI_HANDLE ImageHandle - ) -{ - EFI_STATUS Status; - - if (mRedfishPlatformConfigPrivate != NULL) { - Status = gBS->UninstallProtocolInterface ( - mRedfishPlatformConfigPrivate->ImageHandle, - &gEdkIIRedfishPlatformConfigProtocolGuid, - (VOID*)&mRedfishPlatformConfigPrivate->Protocol - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a, can not uninstall gEdkIIRedfishPlatformConfigProtocolGuid: %r\n", __FUNCTION__, Status)); - ASSERT (FALSE); - } - - // - // Close events - // - if (mRedfishPlatformConfigPrivate->HiiDbNotify.ProtocolEvent != NULL) { - gBS->CloseEvent (mRedfishPlatformConfigPrivate->HiiDbNotify.ProtocolEvent); - } - if (mRedfishPlatformConfigPrivate->HiiStringNotify.ProtocolEvent != NULL) { - gBS->CloseEvent (mRedfishPlatformConfigPrivate->HiiStringNotify.ProtocolEvent); - } - if (mRedfishPlatformConfigPrivate->RegexNotify.ProtocolEvent != NULL) { - gBS->CloseEvent (mRedfishPlatformConfigPrivate->RegexNotify.ProtocolEvent); - } - - // - // Unregister package notification. - // - if (mRedfishPlatformConfigPrivate->NotifyHandle != NULL) { - mRedfishPlatformConfigPrivate->HiiDatabase->UnregisterPackageNotify ( - mRedfishPlatformConfigPrivate->HiiDatabase, - mRedfishPlatformConfigPrivate->NotifyHandle - ); - } - - ReleaseFormsetList (&mRedfishPlatformConfigPrivate->FormsetList); - FreePool (mRedfishPlatformConfigPrivate); - mRedfishPlatformConfigPrivate = NULL; - } - - return EFI_SUCCESS; -} - - -/** - This is the declaration of an EFI image entry point. This entry point is - the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including - both device drivers and bus drivers. - - @param ImageHandle The firmware allocated handle for the UEFI image. - @param SystemTable A pointer to the EFI System Table. - - @retval EFI_SUCCESS The operation completed successfully. - @retval Others An unexpected error occurred. -**/ -EFI_STATUS -EFIAPI -RedfishPlatformConfigDxeEntryPoint ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - mRedfishPlatformConfigPrivate = (REDFISH_PLATFORM_CONFIG_PRIVATE *)AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_PRIVATE)); - if (mRedfishPlatformConfigPrivate == NULL) { - DEBUG ((DEBUG_ERROR, "%a, can not allocate pool for REDFISH_PLATFORM_CONFIG_PRIVATE\n", __FUNCTION__)); - ASSERT (FALSE); - return EFI_OUT_OF_RESOURCES; - } - - // - // Protocol initialization - // - mRedfishPlatformConfigPrivate->ImageHandle = ImageHandle; - mRedfishPlatformConfigPrivate->Protocol.GetValue = RedfishPlatformConfigProtocolGetValue; - mRedfishPlatformConfigPrivate->Protocol.SetValue = RedfishPlatformConfigProtocolSetValue; - mRedfishPlatformConfigPrivate->Protocol.GetConfigureLang = RedfishPlatformConfigProtocolGetConfigureLang; - mRedfishPlatformConfigPrivate->Protocol.GetSupportedSchema = RedfishPlatformConfigProtocolGetSupportedSchema; - - InitializeListHead (&mRedfishPlatformConfigPrivate->FormsetList); - InitializeListHead (&mRedfishPlatformConfigPrivate->PendingList); - - Status = gBS->InstallProtocolInterface ( - &ImageHandle, - &gEdkIIRedfishPlatformConfigProtocolGuid, - EFI_NATIVE_INTERFACE, - (VOID*)&mRedfishPlatformConfigPrivate->Protocol - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a, can not install gEdkIIRedfishPlatformConfigProtocolGuid: %r\n", __FUNCTION__, Status)); - ASSERT (FALSE); - } - - // - // Install protocol notification if HII database protocol is installed. - // - mRedfishPlatformConfigPrivate->HiiDbNotify.ProtocolEvent = EfiCreateProtocolNotifyEvent ( - &gEfiHiiDatabaseProtocolGuid, - TPL_CALLBACK, - HiiDatabaseProtocolInstalled, - NULL, - &mRedfishPlatformConfigPrivate->HiiDbNotify.Registration - ); - if (mRedfishPlatformConfigPrivate->HiiDbNotify.ProtocolEvent == NULL) { - DEBUG ((DEBUG_ERROR, "%a, failed to create protocol notification for gEfiHiiDatabaseProtocolGuid\n", __FUNCTION__)); - ASSERT (FALSE); - } - - // - // Install protocol notification if HII string protocol is installed. - // - mRedfishPlatformConfigPrivate->HiiStringNotify.ProtocolEvent = EfiCreateProtocolNotifyEvent ( - &gEfiHiiStringProtocolGuid, - TPL_CALLBACK, - HiiStringProtocolInstalled, - NULL, - &mRedfishPlatformConfigPrivate->HiiStringNotify.Registration - ); - if (mRedfishPlatformConfigPrivate->HiiStringNotify.ProtocolEvent == NULL) { - DEBUG ((DEBUG_ERROR, "%a, failed to create protocol notification for gEfiHiiStringProtocolGuid\n", __FUNCTION__)); - ASSERT (FALSE); - } - - // - // Install protocol notification if regular expression protocol is installed. - // - mRedfishPlatformConfigPrivate->RegexNotify.ProtocolEvent = EfiCreateProtocolNotifyEvent ( - &gEfiRegularExpressionProtocolGuid, - TPL_CALLBACK, - RegexProtocolInstalled, - NULL, - &mRedfishPlatformConfigPrivate->RegexNotify.Registration - ); - if (mRedfishPlatformConfigPrivate->RegexNotify.ProtocolEvent == NULL) { - DEBUG ((DEBUG_ERROR, "%a, failed to create protocol notification for gEfiRegularExpressionProtocolGuid\n", __FUNCTION__)); - ASSERT (FALSE); - } - - return EFI_SUCCESS; -} +/** @file + + The implementation of EDKII Redfidh Platform Config Protocol. + + (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "RedfishPlatformConfigDxe.h" +#include "RedfishPlatformConfigImpl.h" + +REDFISH_PLATFORM_CONFIG_PRIVATE *mRedfishPlatformConfigPrivate = NULL; + + +/** + Zero extend integer/boolean to UINT64 for comparing. + + @param Value HII Value to be converted. + +**/ +UINT64 +ExtendHiiValueToU64 ( + IN HII_STATEMENT_VALUE *Value + ) +{ + UINT64 Temp; + + Temp = 0; + switch (Value->Type) { + case EFI_IFR_TYPE_NUM_SIZE_8: + Temp = Value->Value.u8; + break; + + case EFI_IFR_TYPE_NUM_SIZE_16: + Temp = Value->Value.u16; + break; + + case EFI_IFR_TYPE_NUM_SIZE_32: + Temp = Value->Value.u32; + break; + + case EFI_IFR_TYPE_BOOLEAN: + Temp = Value->Value.b; + break; + + case EFI_IFR_TYPE_TIME: + case EFI_IFR_TYPE_DATE: + default: + break; + } + + return Temp; +} + +/** + Set value of a data element in an Array by its Index in ordered list buffer. + + @param Array The data array. + @param Type Type of the data in this array. + @param Index Zero based index for data in this array. + @param Value The value to be set. + +**/ +VOID +OrderedListSetArrayData ( + IN VOID *Array, + IN UINT8 Type, + IN UINTN Index, + IN UINT64 Value + ) +{ + + ASSERT (Array != NULL); + + switch (Type) { + case EFI_IFR_TYPE_NUM_SIZE_8: + *(((UINT8 *) Array) + Index) = (UINT8) Value; + break; + + case EFI_IFR_TYPE_NUM_SIZE_16: + *(((UINT16 *) Array) + Index) = (UINT16) Value; + break; + + case EFI_IFR_TYPE_NUM_SIZE_32: + *(((UINT32 *) Array) + Index) = (UINT32) Value; + break; + + case EFI_IFR_TYPE_NUM_SIZE_64: + *(((UINT64 *) Array) + Index) = (UINT64) Value; + break; + + default: + break; + } +} + +/** + Return data element in an Array by its Index in ordered list array buffer. + + @param Array The data array. + @param Type Type of the data in this array. + @param Index Zero based index for data in this array. + + @retval Value The data to be returned + +**/ +UINT64 +OrderedListGetArrayData ( + IN VOID *Array, + IN UINT8 Type, + IN UINTN Index + ) +{ + UINT64 Data; + + ASSERT (Array != NULL); + + Data = 0; + switch (Type) { + case EFI_IFR_TYPE_NUM_SIZE_8: + Data = (UINT64) *(((UINT8 *) Array) + Index); + break; + + case EFI_IFR_TYPE_NUM_SIZE_16: + Data = (UINT64) *(((UINT16 *) Array) + Index); + break; + + case EFI_IFR_TYPE_NUM_SIZE_32: + Data = (UINT64) *(((UINT32 *) Array) + Index); + break; + + case EFI_IFR_TYPE_NUM_SIZE_64: + Data = (UINT64) *(((UINT64 *) Array) + Index); + break; + + default: + break; + } + + return Data; +} + +/** + Find string ID of option if its value equals to given value. + + @param[in] HiiStatement Statement to search. + @param[in] Value Target value. + + @retval EFI_SUCCESS HII value is returned successfully. + @retval Others Errors occur + +**/ +EFI_STRING_ID +OrderedListOptionValueToStringId ( + IN HII_STATEMENT *HiiStatement, + IN UINT64 Value + ) +{ + LIST_ENTRY *Link; + HII_QUESTION_OPTION *Option; + BOOLEAN Found; + UINT64 CurrentValue; + + if (HiiStatement == NULL) { + return 0; + } + + if (HiiStatement->Operand != EFI_IFR_ORDERED_LIST_OP) { + return 0; + } + + if (IsListEmpty (&HiiStatement->OptionListHead)) { + return 0; + } + + Found = FALSE; + Link = GetFirstNode (&HiiStatement->OptionListHead); + while (!IsNull (&HiiStatement->OptionListHead, Link)) { + Option = HII_QUESTION_OPTION_FROM_LINK (Link); + + CurrentValue = ExtendHiiValueToU64 (&Option->Value); + if (Value == CurrentValue) { + return Option->Text; + } + + Link = GetNextNode (&HiiStatement->OptionListHead, Link); + } + + return 0; +} + +/** + Compare two value in HII statement format. + + @param[in] Value1 Firt value to compare. + @param[in] Value2 Second value to be compared. + + @retval INTN 0 is retuned when two values are equal. + 1 is returned when first value is greater than second value. + -1 is returned when second value is greater than first value. + +**/ +INTN +CompareHiiStatementValue ( + IN HII_STATEMENT_VALUE *Value1, + IN HII_STATEMENT_VALUE *Value2 + ) +{ + INTN Result; + UINT64 Data1; + UINT64 Data2; + + if (Value1 == NULL || Value2 == NULL) { + return -1; + } + + switch (Value1->Type) { + case EFI_IFR_TYPE_NUM_SIZE_8: + Data1 = Value1->Value.u8; + break; + case EFI_IFR_TYPE_NUM_SIZE_16: + Data1 = Value1->Value.u16; + break; + case EFI_IFR_TYPE_NUM_SIZE_32: + Data1 = Value1->Value.u32; + break; + case EFI_IFR_TYPE_NUM_SIZE_64: + Data1 = Value1->Value.u64; + break; + case EFI_IFR_TYPE_BOOLEAN: + Data1 = (Value1->Value.b ? 1 : 0); + break; + default: + return -1; + } + + switch (Value2->Type) { + case EFI_IFR_TYPE_NUM_SIZE_8: + Data2 = Value2->Value.u8; + break; + case EFI_IFR_TYPE_NUM_SIZE_16: + Data2 = Value2->Value.u16; + break; + case EFI_IFR_TYPE_NUM_SIZE_32: + Data2 = Value2->Value.u32; + break; + case EFI_IFR_TYPE_NUM_SIZE_64: + Data2 = Value2->Value.u64; + break; + case EFI_IFR_TYPE_BOOLEAN: + Data2 = (Value2->Value.b ? 1 : 0); + break; + default: + return -1; + } + + Result = (Data1 == Data2 ? 0 : (Data1 > Data2 ? 1 : -1)); + + return Result; +} + +/** + Convert HII value to the string in HII one-of opcode. + + @param[in] Statement Statement private instance + + @retval EFI_STRING_ID The string ID in HII database. + 0 is returned when something goes wrong. + +**/ +EFI_STRING_ID +HiiValueToOneOfOptionStringId ( + IN REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *Statement + ) +{ + LIST_ENTRY *Link; + HII_QUESTION_OPTION *Option; + + if (Statement->HiiStatement->Operand != EFI_IFR_ONE_OF_OP) { + return 0; + } + + if (IsListEmpty (&Statement->HiiStatement->OptionListHead)) { + return 0; + } + + Link = GetFirstNode (&Statement->HiiStatement->OptionListHead); + while (!IsNull (&Statement->HiiStatement->OptionListHead, Link)) { + Option = HII_QUESTION_OPTION_FROM_LINK (Link); + + if (CompareHiiStatementValue (&Statement->HiiStatement->Value, &Option->Value) == 0) { + return Option->Text; + } + + Link = GetNextNode (&Statement->HiiStatement->OptionListHead, Link); + } + + return 0; +} + +/** + Convert HII string to the value in HII one-of opcode. + + @param[in] Statement Statement private instance + @param[in] Schema Schema string + @param[in] HiiString Input string + @param[out] Value Value returned + + @retval EFI_SUCCESS HII value is returned successfully. + @retval Others Errors occur + +**/ +EFI_STATUS +HiiStringToOneOfOptionValue ( + IN REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *Statement, + IN CHAR8 *Schema, + IN EFI_STRING HiiString, + OUT HII_STATEMENT_VALUE *Value + ) +{ + LIST_ENTRY *Link; + HII_QUESTION_OPTION *Option; + EFI_STRING TmpString; + BOOLEAN Found; + + if (Statement == NULL || IS_EMPTY_STRING (HiiString) || Value == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Statement->HiiStatement->Operand != EFI_IFR_ONE_OF_OP) { + return EFI_UNSUPPORTED; + } + + if (IsListEmpty (&Statement->HiiStatement->OptionListHead)) { + return EFI_NOT_FOUND; + } + + Found = FALSE; + Link = GetFirstNode (&Statement->HiiStatement->OptionListHead); + while (!IsNull (&Statement->HiiStatement->OptionListHead, Link)) { + Option = HII_QUESTION_OPTION_FROM_LINK (Link); + + TmpString = HiiGetRedfishString (Statement->ParentForm->ParentFormset->HiiHandle, Schema, Option->Text); + if (TmpString != NULL) { + if (StrCmp (TmpString, HiiString) == 0) { + CopyMem (Value, &Option->Value, sizeof (HII_STATEMENT_VALUE)); + Found = TRUE; + } + FreePool (TmpString); + } + + if (Found) { + return EFI_SUCCESS; + } + + Link = GetNextNode (&Statement->HiiStatement->OptionListHead, Link); + } + + return EFI_NOT_FOUND; +} + +/** + Convert HII value to numeric value in Redfish format. + + @param[in] Value Value to be converted. + @param[out] RedfishValue Value in Redfish format. + + @retval EFI_SUCCESS Redfish value is returned successfully. + @retval Others Errors occur + +**/ +EFI_STATUS +HiiValueToRedfishNumeric ( + IN HII_STATEMENT_VALUE *Value, + OUT EDKII_REDFISH_VALUE *RedfishValue + ) +{ + if (Value == NULL || RedfishValue == NULL) { + return EFI_INVALID_PARAMETER; + } + + switch (Value->Type) { + case EFI_IFR_TYPE_NUM_SIZE_8: + RedfishValue->Type = REDFISH_VALUE_TYPE_INTEGER; + RedfishValue->Value.Integer = (INT64)Value->Value.u8; + break; + case EFI_IFR_TYPE_NUM_SIZE_16: + RedfishValue->Type = REDFISH_VALUE_TYPE_INTEGER; + RedfishValue->Value.Integer = (INT64)Value->Value.u16; + break; + case EFI_IFR_TYPE_NUM_SIZE_32: + RedfishValue->Type = REDFISH_VALUE_TYPE_INTEGER; + RedfishValue->Value.Integer = (INT64)Value->Value.u32; + break; + case EFI_IFR_TYPE_NUM_SIZE_64: + RedfishValue->Type = REDFISH_VALUE_TYPE_INTEGER; + RedfishValue->Value.Integer = (INT64)Value->Value.u64; + break; + case EFI_IFR_TYPE_BOOLEAN: + RedfishValue->Type = REDFISH_VALUE_TYPE_BOOLEAN; + RedfishValue->Value.Boolean = Value->Value.b; + break; + default: + RedfishValue->Type = REDFISH_VALUE_TYPE_UNKNOWN; + break; + } + + return EFI_SUCCESS; +} + +/** + Convert numeric value in Redfish format to HII value. + + @param[in] RedfishValue Value in Redfish format to be converted. + @param[out] Value HII value returned. + + @retval EFI_SUCCESS HII value is returned successfully. + @retval Others Errors occur + +**/ +EFI_STATUS +RedfishNumericToHiiValue ( + IN EDKII_REDFISH_VALUE *RedfishValue, + OUT HII_STATEMENT_VALUE *Value + ) +{ + if (Value == NULL || RedfishValue == NULL) { + return EFI_INVALID_PARAMETER; + } + + switch (RedfishValue->Type) { + case REDFISH_VALUE_TYPE_INTEGER: + Value->Type = EFI_IFR_TYPE_NUM_SIZE_64; + Value->Value.u64 = (UINT64)RedfishValue->Value.Integer; + break; + case REDFISH_VALUE_TYPE_BOOLEAN: + Value->Type = EFI_IFR_TYPE_BOOLEAN; + Value->Value.b = RedfishValue->Value.Boolean; + break; + default: + Value->Type = EFI_IFR_TYPE_UNDEFINED; + break; + } + + return EFI_SUCCESS; +} + +/** + Dump the value in ordered list buffer. + + @param[in] OrderedListStatement Ordered list statement. + +**/ +VOID +DumpOrderedListValue ( + IN HII_STATEMENT *OrderedListStatement + ) +{ + UINT8 *Value8; + UINT16 *Value16; + UINT32 *Value32; + UINT64 *Value64; + UINTN Count; + UINTN Index; + + if (OrderedListStatement == NULL || OrderedListStatement->Operand != EFI_IFR_ORDERED_LIST_OP) { + return; + } + + DEBUG ((DEBUG_ERROR, "Value.Type= 0x%x\n", OrderedListStatement->Value.Type)); + DEBUG ((DEBUG_ERROR, "Value.BufferValueType= 0x%x\n", OrderedListStatement->Value.BufferValueType)); + DEBUG ((DEBUG_ERROR, "Value.BufferLen= 0x%x\n", OrderedListStatement->Value.BufferLen)); + DEBUG ((DEBUG_ERROR, "Value.Buffer= 0x%x\n", OrderedListStatement->Value.Buffer)); + DEBUG ((DEBUG_ERROR, "Value.MaxContainers= 0x%x\n", OrderedListStatement->ExtraData.OrderListData.MaxContainers)); + DEBUG ((DEBUG_ERROR, "StorageWidth= 0x%x\n", OrderedListStatement->StorageWidth)); + + if (OrderedListStatement->Value.Buffer == NULL) { + return; + } + + Value8 = NULL; + Value16 = NULL; + Value32 = NULL; + Value64 = NULL; + Count = 0; + + switch (OrderedListStatement->Value.BufferValueType) { + case EFI_IFR_TYPE_NUM_SIZE_8: + Value8 = (UINT8 *)OrderedListStatement->Value.Buffer; + Count = OrderedListStatement->StorageWidth / sizeof (UINT8); + for (Index = 0; Index < Count; Index++) { + DEBUG ((DEBUG_ERROR, "%d ", Value8[Index])); + } + break; + case EFI_IFR_TYPE_NUM_SIZE_16: + Value16 = (UINT16 *)OrderedListStatement->Value.Buffer; + Count = OrderedListStatement->StorageWidth / sizeof (UINT16); + for (Index = 0; Index < Count; Index++) { + DEBUG ((DEBUG_ERROR, "%d ", Value16[Index])); + } + break; + case EFI_IFR_TYPE_NUM_SIZE_32: + Value32 = (UINT32 *)OrderedListStatement->Value.Buffer; + Count = OrderedListStatement->StorageWidth / sizeof (UINT32); + for (Index = 0; Index < Count; Index++) { + DEBUG ((DEBUG_ERROR, "%d ", Value32[Index])); + } + break; + case EFI_IFR_TYPE_NUM_SIZE_64: + Value64 = (UINT64 *)OrderedListStatement->Value.Buffer; + Count = OrderedListStatement->StorageWidth / sizeof (UINT64); + for (Index = 0; Index < Count; Index++) { + DEBUG ((DEBUG_ERROR, "%d ", Value64[Index])); + } + break; + default: + Value8 = (UINT8 *)OrderedListStatement->Value.Buffer; + Count = OrderedListStatement->StorageWidth / sizeof (UINT8); + for (Index = 0; Index < Count; Index++) { + DEBUG ((DEBUG_ERROR, "%d ", Value8[Index])); + } + break; + } + + DEBUG ((DEBUG_ERROR, "\n")); +} + +/** + Convert HII value to the string in HII ordered list opcode. It's caller's + responsibility to free returned buffer using FreePool(). + + @param[in] Statement Statement private instance + @param[out] ReturnSize The size of returned array + + @retval EFI_STRING_ID The string ID array for options in ordered list. + +**/ +EFI_STRING_ID * +HiiValueToOrderedListOptionStringId ( + IN REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *Statement, + OUT UINTN *ReturnSize + ) +{ + LIST_ENTRY *Link; + HII_QUESTION_OPTION *Option; + UINTN OptionCount; + EFI_STRING_ID *ReturnedArray; + UINTN Index; + UINT64 Value; + + if (Statement == NULL || ReturnSize == NULL) { + return NULL; + } + + *ReturnSize = 0; + + if (Statement->HiiStatement->Operand != EFI_IFR_ORDERED_LIST_OP) { + return NULL; + } + + if (IsListEmpty (&Statement->HiiStatement->OptionListHead)) { + return NULL; + } + + DEBUG_CODE ( + DumpOrderedListValue (Statement->HiiStatement); + ); + + OptionCount = 0; + Link = GetFirstNode (&Statement->HiiStatement->OptionListHead); + while (!IsNull (&Statement->HiiStatement->OptionListHead, Link)) { + Option = HII_QUESTION_OPTION_FROM_LINK (Link); + + ++OptionCount; + + Link = GetNextNode (&Statement->HiiStatement->OptionListHead, Link); + } + + *ReturnSize = OptionCount; + ReturnedArray = AllocatePool (sizeof (EFI_STRING_ID) * OptionCount); + if (ReturnedArray == NULL) { + DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__)); + *ReturnSize = 0; + return NULL; + } + + for (Index = 0; Index < OptionCount; Index++) { + Value = OrderedListGetArrayData (Statement->HiiStatement->Value.Buffer, Statement->HiiStatement->Value.BufferValueType, Index); + ReturnedArray[Index] = OrderedListOptionValueToStringId (Statement->HiiStatement, Value); + } + + return ReturnedArray; +} + +/** + Convert HII string to the value in HII ordered list opcode. + + @param[in] Statement Statement private instance + @param[in] Schema Schema string + @param[in] HiiString Input string + @param[out] Value Value returned + + @retval EFI_SUCCESS HII value is returned successfully. + @retval Others Errors occur + +**/ +EFI_STATUS +HiiStringToOrderedListOptionValue ( + IN REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *Statement, + IN CHAR8 *Schema, + IN EFI_STRING HiiString, + OUT UINT64 *Value + ) +{ + LIST_ENTRY *Link; + HII_QUESTION_OPTION *Option; + EFI_STRING TmpString; + BOOLEAN Found; + + if (Statement == NULL || IS_EMPTY_STRING (HiiString) || Value == NULL) { + return EFI_INVALID_PARAMETER; + } + + *Value = 0; + + if (Statement->HiiStatement->Operand != EFI_IFR_ORDERED_LIST_OP) { + return EFI_UNSUPPORTED; + } + + if (IsListEmpty (&Statement->HiiStatement->OptionListHead)) { + return EFI_NOT_FOUND; + } + + Found = FALSE; + Link = GetFirstNode (&Statement->HiiStatement->OptionListHead); + while (!IsNull (&Statement->HiiStatement->OptionListHead, Link)) { + Option = HII_QUESTION_OPTION_FROM_LINK (Link); + + TmpString = HiiGetRedfishString (Statement->ParentForm->ParentFormset->HiiHandle, Schema, Option->Text); + if (TmpString != NULL) { + if (StrCmp (TmpString, HiiString) == 0) { + *Value = ExtendHiiValueToU64 (&Option->Value); + Found = TRUE; + } + FreePool (TmpString); + } + + if (Found) { + return EFI_SUCCESS; + } + + Link = GetNextNode (&Statement->HiiStatement->OptionListHead, Link); + } + + return EFI_NOT_FOUND; +} + +/** + Convert input ascii string to unicode string. It's caller's + responsibility to free returned buffer using FreePool(). + + @param[in] AsciiString Ascii string to be converted. + + @retval CHAR16 * Unicode string on return. + +**/ +EFI_STRING +StrToUnicodeStr ( + IN CHAR8 *AsciiString + ) +{ + UINTN StringLen; + EFI_STRING Buffer; + EFI_STATUS Status; + + if (AsciiString == NULL || AsciiString[0] == '\0') { + return NULL; + } + + StringLen = AsciiStrLen (AsciiString) + 1; + Buffer = AllocatePool (StringLen * sizeof (CHAR16)); + if (Buffer == NULL) { + return NULL; + } + + Status = AsciiStrToUnicodeStrS (AsciiString, Buffer, StringLen); + if (EFI_ERROR (Status)) { + FreePool (Buffer); + return NULL; + } + + return Buffer; +} + +/** + Return the full Redfish schema string from the given Schema and Version. + + Returned schema string is: Schema + '.' + Version + + @param[in] Schema Schema string + @param[in] Version Schema version string + + @retval CHAR8 * Schema string. NULL when errors occur. + +**/ +CHAR8 * +GetFullSchemaString ( + IN CHAR8 *Schema, + IN CHAR8 *Version + ) +{ + UINTN Size; + CHAR8 *FullName; + + if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version)) { + return NULL; + } + + Size = AsciiStrSize(CONFIGURE_LANGUAGE_PREFIX) + AsciiStrSize (Schema) + AsciiStrSize (Version); + + FullName = AllocatePool (Size); + if (FullName == NULL) { + DEBUG ((DEBUG_ERROR, "%a, out-of-resource\n", __FUNCTION__)); + return NULL; + } + + AsciiSPrint (FullName, Size, "%a%a.%a", CONFIGURE_LANGUAGE_PREFIX, Schema, Version); + + return FullName; +} + +/** + Common implementation to get statement private instance. + + @param[in] RedfishPlatformConfigPrivate Private instance. + @param[in] Schema Redfish schema string. + @param[in] ConfigureLang Configure language that refers to this statement. + @param[out] Statement Statement instance + + @retval EFI_SUCCESS HII value is returned successfully. + @retval Others Errors occur + +**/ +EFI_STATUS +RedfishPlatformConfigGetStatementCommon ( + IN REDFISH_PLATFORM_CONFIG_PRIVATE *RedfishPlatformConfigPrivate, + IN CHAR8 *Schema, + IN EFI_STRING ConfigureLang, + OUT REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE **Statement + ) +{ + EFI_STATUS Status; + REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *TargetStatement; + + if (RedfishPlatformConfigPrivate == NULL || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (ConfigureLang) || Statement == NULL) { + return EFI_INVALID_PARAMETER; + } + + *Statement = NULL; + + Status = ProcessPendingList (&RedfishPlatformConfigPrivate->FormsetList, &RedfishPlatformConfigPrivate->PendingList); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, ProcessPendingList failure: %r\n", __FUNCTION__, Status)); + return Status; + } + + TargetStatement = GetStatementPrivateByConfigureLang (&RedfishPlatformConfigPrivate->FormsetList, Schema, ConfigureLang); + if (TargetStatement == NULL) { + DEBUG ((DEBUG_ERROR, "%a, No match HII statement is found by the given %s in schema %a\n", __FUNCTION__, ConfigureLang, Schema)); + return EFI_NOT_FOUND; + } + + // + // Find current HII question value. + // + Status = GetQuestionValue ( + TargetStatement->ParentForm->ParentFormset->HiiFormSet, + TargetStatement->ParentForm->HiiForm, + TargetStatement->HiiStatement, + GetSetValueWithHiiDriver + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, failed to get question current value: %r\n", __FUNCTION__, Status)); + return Status; + } + + + if (TargetStatement->HiiStatement->Value.Type == EFI_IFR_TYPE_UNDEFINED) { + return EFI_DEVICE_ERROR; + } + + // + // Return Value. + // + *Statement = TargetStatement; + + return EFI_SUCCESS; +} + +/** + Get Redfish value with the given Schema and Configure Language. + + @param[in] This Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance. + @param[in] Schema The Redfish schema to query. + @param[in] Version The Redfish version to query. + @param[in] ConfigureLang The target value which match this configure Language. + @param[out] Value The returned value. + + @retval EFI_SUCCESS Value is returned successfully. + @retval Others Some error happened. + +**/ +EFI_STATUS +EFIAPI +RedfishPlatformConfigProtocolGetValue ( + IN EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL *This, + IN CHAR8 *Schema, + IN CHAR8 *Version, + IN EFI_STRING ConfigureLang, + OUT EDKII_REDFISH_VALUE *Value + ) +{ + EFI_STATUS Status; + REDFISH_PLATFORM_CONFIG_PRIVATE *RedfishPlatformConfigPrivate; + REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *TargetStatement; + EFI_STRING_ID StringId; + EFI_STRING_ID *StringIdArray; + CHAR8 *FullSchema; + EFI_STRING HiiString; + UINTN Count; + UINTN Index; + + if (This == NULL || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || IS_EMPTY_STRING (ConfigureLang) || Value == NULL) { + return EFI_INVALID_PARAMETER; + } + + RedfishPlatformConfigPrivate = REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS (This); + Value->Type = REDFISH_VALUE_TYPE_UNKNOWN; + Value->ArrayCount = 0; + Count = 0; + FullSchema = NULL; + HiiString = NULL; + StringIdArray = NULL; + + FullSchema = GetFullSchemaString (Schema, Version); + if (FullSchema == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = RedfishPlatformConfigGetStatementCommon (RedfishPlatformConfigPrivate, FullSchema, ConfigureLang, &TargetStatement); + if (EFI_ERROR (Status)) { + goto RELEASE_RESOURCE; + } + + switch (TargetStatement->HiiStatement->Operand) { + case EFI_IFR_ONE_OF_OP: + StringId = HiiValueToOneOfOptionStringId (TargetStatement); + if (StringId == 0) { + ASSERT (FALSE); + Status = EFI_DEVICE_ERROR; + goto RELEASE_RESOURCE; + } + + Value->Value.Buffer = HiiGetRedfishAsciiString (TargetStatement->ParentForm->ParentFormset->HiiHandle, FullSchema, StringId); + if (Value->Value.Buffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto RELEASE_RESOURCE; + } + + Value->Type = REDFISH_VALUE_TYPE_STRING; + break; + case EFI_IFR_STRING_OP: + if (TargetStatement->HiiStatement->Value.Type != EFI_IFR_TYPE_STRING) { + ASSERT (FALSE); + Status = EFI_DEVICE_ERROR; + goto RELEASE_RESOURCE; + } + + Value->Type = REDFISH_VALUE_TYPE_STRING; + Value->Value.Buffer = AllocatePool (StrLen ((CHAR16 *)TargetStatement->HiiStatement->Value.Buffer) + 1); + UnicodeStrToAsciiStrS ((CHAR16 *)TargetStatement->HiiStatement->Value.Buffer, Value->Value.Buffer, StrLen ((CHAR16 *)TargetStatement->HiiStatement->Value.Buffer) + 1); + break; + case EFI_IFR_CHECKBOX_OP: + case EFI_IFR_NUMERIC_OP: + Status = HiiValueToRedfishNumeric (&TargetStatement->HiiStatement->Value, Value); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, failed to convert HII value to Redfish value: %r\n", __FUNCTION__, Status)); + goto RELEASE_RESOURCE; + } + break; + case EFI_IFR_ACTION_OP: + if (TargetStatement->HiiStatement->Value.Type != EFI_IFR_TYPE_ACTION) { + ASSERT (FALSE); + Status = EFI_DEVICE_ERROR; + goto RELEASE_RESOURCE; + } + + // + // Action has no value. Just return unknown type. + // + Value->Type = REDFISH_VALUE_TYPE_UNKNOWN; + break; + case EFI_IFR_ORDERED_LIST_OP: + StringIdArray = HiiValueToOrderedListOptionStringId (TargetStatement, &Count); + if (StringIdArray == NULL) { + ASSERT (FALSE); + Status = EFI_DEVICE_ERROR; + goto RELEASE_RESOURCE; + } + + Value->Value.StringArray = AllocatePool (sizeof (CHAR8 *) * Count); + if (Value->Value.StringArray == NULL) { + ASSERT (FALSE); + Status = EFI_OUT_OF_RESOURCES; + goto RELEASE_RESOURCE; + } + + for (Index = 0; Index < Count; Index++) { + ASSERT (StringIdArray[Index] != 0); + Value->Value.StringArray[Index] = HiiGetRedfishAsciiString (TargetStatement->ParentForm->ParentFormset->HiiHandle, FullSchema, StringIdArray[Index]); + } + + Value->ArrayCount = Count; + Value->Type = REDFISH_VALUE_TYPE_STRING_ARRAY; + break; + default: + DEBUG ((DEBUG_ERROR, "%a, catch unsupported type: 0x%x! Please contact with author if we need to support this type.\n", __FUNCTION__, TargetStatement->HiiStatement->Operand)); + ASSERT (FALSE); + Status = EFI_UNSUPPORTED; + goto RELEASE_RESOURCE; + } + +RELEASE_RESOURCE: + + if (FullSchema != NULL) { + FreePool (FullSchema); + } + + if (HiiString != NULL) { + FreePool (HiiString); + } + + if (StringIdArray != NULL) { + FreePool (StringIdArray); + } + + return Status; +} + +/** + Function to save question value into HII database. + + @param[in] HiiFormset HII form-set instance + @param[in] HiiForm HII form instance + @param[in] HiiStatement HII statement that keeps new value. + @param[in] Value New value to applyu. + + @retval EFI_SUCCESS HII value is returned successfully. + @retval Others Errors occur + +**/ +EFI_STATUS +RedfishPlatformConfigSaveQuestionValue ( + IN HII_FORMSET *HiiFormset, + IN HII_FORM *HiiForm, + IN HII_STATEMENT *HiiStatement, + IN HII_STATEMENT_VALUE *Value + ) +{ + EFI_STATUS Status; + + if (HiiFormset == NULL || HiiForm == NULL || HiiStatement == NULL || Value == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = SetQuestionValue ( + HiiFormset, + HiiForm, + HiiStatement, + Value + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, failed to set question value: %r\n", __FUNCTION__, Status)); + return Status; + } + + Status = SubmitForm (HiiFormset, HiiForm); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, failed to submit form: %r\n", __FUNCTION__, Status)); + return Status; + } + + return EFI_SUCCESS; +} + +/** + Common implementation to set statement private instance. + + @param[in] RedfishPlatformConfigPrivate Private instance. + @param[in] Schema Redfish schema string. + @param[in] ConfigureLang Configure language that refers to this statement. + @param[in] Statement Statement instance + + @retval EFI_SUCCESS HII value is returned successfully. + @retval Others Errors occur + +**/ +EFI_STATUS +RedfishPlatformConfigSetStatementCommon ( + IN REDFISH_PLATFORM_CONFIG_PRIVATE *RedfishPlatformConfigPrivate, + IN CHAR8 *Schema, + IN EFI_STRING ConfigureLang, + IN HII_STATEMENT_VALUE *StatementValue + ) +{ + EFI_STATUS Status; + REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *TargetStatement; + EFI_STRING TempBuffer; + UINT8 *StringArray; + UINTN Index; + UINT64 Value; + CHAR8 **CharArray; + + if (RedfishPlatformConfigPrivate == NULL || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (ConfigureLang) || StatementValue == NULL) { + return EFI_INVALID_PARAMETER; + } + + TempBuffer = NULL; + StringArray = NULL; + + Status = ProcessPendingList (&RedfishPlatformConfigPrivate->FormsetList, &RedfishPlatformConfigPrivate->PendingList); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, ProcessPendingList failure: %r\n", __FUNCTION__, Status)); + return Status; + } + + TargetStatement = GetStatementPrivateByConfigureLang (&RedfishPlatformConfigPrivate->FormsetList, Schema, ConfigureLang); + if (TargetStatement == NULL) { + DEBUG ((DEBUG_ERROR, "%a, No match HII statement is found by the given %s in schema %a\n", __FUNCTION__, ConfigureLang, Schema)); + return EFI_NOT_FOUND; + } + + if (StatementValue->Type != TargetStatement->HiiStatement->Value.Type) { + // + // We treat one-of type as string in Redfish. But one-of statement is not + // in string format from HII point of view. Do a patch here. + // + if (TargetStatement->HiiStatement->Operand == EFI_IFR_ONE_OF_OP && StatementValue->Type == EFI_IFR_TYPE_STRING) { + + TempBuffer = StrToUnicodeStr ((CHAR8 *)StatementValue->Buffer); + if (TempBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + FreePool (StatementValue->Buffer); + StatementValue->Buffer = NULL; + StatementValue->BufferLen = 0; + + Status = HiiStringToOneOfOptionValue (TargetStatement, Schema, TempBuffer, StatementValue); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, failed to find option value by the given %s\n", __FUNCTION__, TempBuffer)); + FreePool (TempBuffer); + return EFI_NOT_FOUND; + } + + FreePool (TempBuffer); + } else if (TargetStatement->HiiStatement->Operand == EFI_IFR_ORDERED_LIST_OP && StatementValue->Type == EFI_IFR_TYPE_STRING) { + // + // We treat ordered list type as string in Redfish. But ordered list statement is not + // in string format from HII point of view. Do a patch here. + // + StringArray = AllocateZeroPool (TargetStatement->HiiStatement->StorageWidth); + if (StringArray == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Arrage new option order from input string array + // + CharArray = (CHAR8 **)StatementValue->Buffer; + for (Index = 0; Index < StatementValue->BufferLen; Index++) { + TempBuffer = StrToUnicodeStr (CharArray[Index]); + if (TempBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = HiiStringToOrderedListOptionValue (TargetStatement, Schema, TempBuffer, &Value); + if (EFI_ERROR (Status)) { + ASSERT (FALSE); + continue; + } + FreePool (TempBuffer); + OrderedListSetArrayData (StringArray, TargetStatement->HiiStatement->Value.BufferValueType, Index, Value); + } + + StatementValue->Type = EFI_IFR_TYPE_BUFFER; + StatementValue->Buffer = StringArray; + StatementValue->BufferLen = TargetStatement->HiiStatement->StorageWidth; + StatementValue->BufferValueType = TargetStatement->HiiStatement->Value.BufferValueType; + } else if (TargetStatement->HiiStatement->Operand == EFI_IFR_NUMERIC_OP && StatementValue->Type == EFI_IFR_TYPE_NUM_SIZE_64) { + // + // Redfish only has numeric value type and it does not care about the value size. + // Do a patch here so we have proper value size applied. + // + StatementValue->Type = TargetStatement->HiiStatement->Value.Type; + } else { + DEBUG ((DEBUG_ERROR, "%a, catch value type mismatch! input type: 0x%x but target value type: 0x%x\n", __FUNCTION__, StatementValue->Type, TargetStatement->HiiStatement->Value.Type)); + ASSERT (FALSE); + } + } + + Status = RedfishPlatformConfigSaveQuestionValue ( + TargetStatement->ParentForm->ParentFormset->HiiFormSet, + TargetStatement->ParentForm->HiiForm, + TargetStatement->HiiStatement, + StatementValue + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, failed to save question value: %r\n", __FUNCTION__, Status)); + return Status; + } + + return EFI_SUCCESS; +} + +/** + Set Redfish value with the given Schema and Configure Language. + + @param[in] This Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance. + @param[in] Schema The Redfish schema to query. + @param[in] Version The Redfish version to query. + @param[in] ConfigureLang The target value which match this configure Language. + @param[in] Value The value to set. + + @retval EFI_SUCCESS Value is returned successfully. + @retval Others Some error happened. + +**/ +EFI_STATUS +EFIAPI +RedfishPlatformConfigProtocolSetValue ( + IN EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL *This, + IN CHAR8 *Schema, + IN CHAR8 *Version, + IN EFI_STRING ConfigureLang, + IN EDKII_REDFISH_VALUE Value + ) +{ + EFI_STATUS Status; + REDFISH_PLATFORM_CONFIG_PRIVATE *RedfishPlatformConfigPrivate; + CHAR8 *FullSchema; + HII_STATEMENT_VALUE NewValue; + + if (This == NULL || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || IS_EMPTY_STRING (ConfigureLang)) { + return EFI_INVALID_PARAMETER; + } + + if (Value.Type == REDFISH_VALUE_TYPE_UNKNOWN || Value.Type >= REDFISH_VALUE_TYPE_MAX) { + return EFI_INVALID_PARAMETER; + } + + RedfishPlatformConfigPrivate = REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS (This); + FullSchema = NULL; + + FullSchema = GetFullSchemaString (Schema, Version); + if (FullSchema == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + ZeroMem (&NewValue, sizeof (HII_STATEMENT_VALUE)); + + switch (Value.Type) { + case REDFISH_VALUE_TYPE_INTEGER: + case REDFISH_VALUE_TYPE_BOOLEAN: + Status = RedfishNumericToHiiValue (&Value, &NewValue); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, failed to convert Redfish value to Hii value: %r\n", __FUNCTION__, Status)); + goto RELEASE_RESOURCE; + } + break; + case REDFISH_VALUE_TYPE_STRING: + NewValue.Type = EFI_IFR_TYPE_STRING; + NewValue.BufferLen = (UINT16)AsciiStrSize (Value.Value.Buffer); + NewValue.Buffer = AllocateCopyPool (NewValue.BufferLen, Value.Value.Buffer); + if (NewValue.Buffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto RELEASE_RESOURCE; + } + break; + case REDFISH_VALUE_TYPE_STRING_ARRAY: + NewValue.Type = EFI_IFR_TYPE_STRING; + NewValue.BufferLen = (UINT16)Value.ArrayCount; + NewValue.Buffer = (UINT8 *)Value.Value.StringArray; + break; + default: + ASSERT (FALSE); + break; + } + + Status = RedfishPlatformConfigSetStatementCommon (RedfishPlatformConfigPrivate, FullSchema, ConfigureLang, &NewValue); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, failed to set value to statement: %r\n", __FUNCTION__, Status)); + } + +RELEASE_RESOURCE: + + if (FullSchema != NULL) { + FreePool (FullSchema); + } + + return Status; +} + +/** + Get the list of Configure Language from platform configuration by the given Schema and RegexPattern. + + @param[in] This Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance. + @param[in] Schema The Redfish schema to query. + @param[in] Version The Redfish version to query. + @param[in] RegexPattern The target Configure Language pattern. This is used for regular expression matching. + @param[out] ConfigureLangList The list of Configure Language. + @param[out] Count The number of Configure Language in ConfigureLangList. + + @retval EFI_SUCCESS ConfigureLangList is returned successfully. + @retval Others Some error happened. + +**/ +EFI_STATUS +EFIAPI +RedfishPlatformConfigProtocolGetConfigureLang ( + IN EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL *This, + IN CHAR8 *Schema, + IN CHAR8 *Version, + IN EFI_STRING RegexPattern, + OUT EFI_STRING **ConfigureLangList, + OUT UINTN *Count + ) +{ + REDFISH_PLATFORM_CONFIG_PRIVATE *RedfishPlatformConfigPrivate; + EFI_STATUS Status; + REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST StatementList; + REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF *StatementRef; + LIST_ENTRY *NextLink; + EFI_STRING TmpString; + EFI_STRING *TmpConfigureLangList; + UINTN Index; + CHAR8 *FullSchema; + + if (This == NULL || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || Count == NULL || ConfigureLangList == NULL || IS_EMPTY_STRING (RegexPattern)) { + return EFI_INVALID_PARAMETER; + } + + *Count = 0; + *ConfigureLangList = NULL; + FullSchema = NULL; + RedfishPlatformConfigPrivate = REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS (This); + + Status = ProcessPendingList (&RedfishPlatformConfigPrivate->FormsetList, &RedfishPlatformConfigPrivate->PendingList); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, ProcessPendingList failure: %r\n", __FUNCTION__, Status)); + return Status; + } + + FullSchema = GetFullSchemaString (Schema, Version); + if (FullSchema == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = GetStatementPrivateByConfigureLangRegex ( + RedfishPlatformConfigPrivate->RegularExpressionProtocol, + &RedfishPlatformConfigPrivate->FormsetList, + FullSchema, + RegexPattern, + &StatementList + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, GetStatementPrivateByConfigureLangRegex failure: %r\n", __FUNCTION__, Status)); + goto RELEASE_RESOURCE; + } + + if (!IsListEmpty (&StatementList.StatementList)) { + + TmpConfigureLangList = AllocateZeroPool (sizeof (CHAR16 *) * StatementList.Count); + if (TmpConfigureLangList == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto RELEASE_RESOURCE; + } + + Index = 0; + NextLink = GetFirstNode (&StatementList.StatementList); + while (!IsNull (&StatementList.StatementList, NextLink)) { + StatementRef = REDFISH_PLATFORM_CONFIG_STATEMENT_REF_FROM_LINK (NextLink); + NextLink = GetNextNode (&StatementList.StatementList, NextLink); + + ASSERT (StatementRef->Statement->Description != 0); + if (StatementRef->Statement->Description != 0) { + TmpString = HiiGetRedfishString (StatementRef->Statement->ParentForm->ParentFormset->HiiHandle, FullSchema, StatementRef->Statement->Description); + ASSERT (TmpString != NULL); + if (TmpString != NULL) { + TmpConfigureLangList[Index] = AllocateCopyPool (StrSize (TmpString), TmpString); + ASSERT (TmpConfigureLangList[Index] != NULL); + FreePool (TmpString); + ++Index; + } + } + } + } + + *Count = StatementList.Count; + *ConfigureLangList = TmpConfigureLangList; + +RELEASE_RESOURCE: + + if (FullSchema != NULL) { + FreePool (FullSchema); + } + + ReleaseStatementList (&StatementList); + + return Status; +} + +/** + Get the list of supported Redfish schema from paltform configuration on give HII handle. + + @param[in] This Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance. + @param[in] HiiHandle The target handle to search. If handle is NULL, + this function return all schema from HII database. + @param[out] SupportedSchema The supported schema list which is separated by ';'. + The SupportedSchema is allocated by the callee. It's caller's + responsibility to free this buffer using FreePool(). + + @retval EFI_SUCCESS Schema is returned successfully. + @retval Others Some error happened. + +**/ +EFI_STATUS +EFIAPI +RedfishPlatformConfigProtocolGetSupportedSchema ( + IN EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL *This, + IN EFI_HII_HANDLE HiiHandle, OPTIONAL + OUT CHAR8 **SupportedSchema + ) +{ + REDFISH_PLATFORM_CONFIG_PRIVATE *RedfishPlatformConfigPrivate; + EFI_STATUS Status; + LIST_ENTRY *HiiFormsetLink; + LIST_ENTRY *HiiFormsetNextLink; + REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *HiiFormsetPrivate; + UINTN Index; + UINTN StringSize; + CHAR8 *StringBuffer; + UINTN StringIndex; + + if (This == NULL || SupportedSchema == NULL) { + return EFI_INVALID_PARAMETER; + } + + *SupportedSchema = NULL; + + RedfishPlatformConfigPrivate = REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS (This); + + Status = ProcessPendingList (&RedfishPlatformConfigPrivate->FormsetList, &RedfishPlatformConfigPrivate->PendingList); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, ProcessPendingList failure: %r\n", __FUNCTION__, Status)); + return Status; + } + + if (IsListEmpty (&RedfishPlatformConfigPrivate->FormsetList)) { + return EFI_NOT_FOUND; + } + + // + // Calculate for string buffer size. + // + StringSize = 0; + HiiFormsetLink = GetFirstNode (&RedfishPlatformConfigPrivate->FormsetList); + while (!IsNull (&RedfishPlatformConfigPrivate->FormsetList, HiiFormsetLink)) { + HiiFormsetNextLink = GetNextNode (&RedfishPlatformConfigPrivate->FormsetList, HiiFormsetLink); + HiiFormsetPrivate = REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink); + + if (HiiHandle != NULL && HiiHandle != HiiFormsetPrivate->HiiHandle) { + HiiFormsetLink = HiiFormsetNextLink; + continue; + } + + if (HiiFormsetPrivate->SupportedSchema.Count > 0) { + for (Index = 0; Index < HiiFormsetPrivate->SupportedSchema.Count; Index++) { + StringSize += AsciiStrSize (HiiFormsetPrivate->SupportedSchema.SchemaList[Index]); + } + } + + HiiFormsetLink = HiiFormsetNextLink; + } + + if (StringSize == 0) { + return EFI_NOT_FOUND; + } + + StringBuffer = AllocatePool (StringSize); + if (StringBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + StringIndex = 0; + HiiFormsetLink = GetFirstNode (&RedfishPlatformConfigPrivate->FormsetList); + while (!IsNull (&RedfishPlatformConfigPrivate->FormsetList, HiiFormsetLink)) { + HiiFormsetNextLink = GetNextNode (&RedfishPlatformConfigPrivate->FormsetList, HiiFormsetLink); + HiiFormsetPrivate = REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink); + + if (HiiHandle != NULL && HiiHandle != HiiFormsetPrivate->HiiHandle) { + HiiFormsetLink = HiiFormsetNextLink; + continue; + } + + if (HiiFormsetPrivate->SupportedSchema.Count > 0) { + for (Index = 0; Index < HiiFormsetPrivate->SupportedSchema.Count; Index++) { + AsciiStrCpyS (&StringBuffer[StringIndex], (StringSize - StringIndex), HiiFormsetPrivate->SupportedSchema.SchemaList[Index]); + StringIndex += AsciiStrLen (HiiFormsetPrivate->SupportedSchema.SchemaList[Index]); + StringBuffer[StringIndex] = ';'; + ++StringIndex; + } + } + + HiiFormsetLink = HiiFormsetNextLink; + } + + StringBuffer[--StringIndex] = '\0'; + + *SupportedSchema = StringBuffer; + + return EFI_SUCCESS; +} + +/** + Functions which are registered to receive notification of + database events have this prototype. The actual event is encoded + in NotifyType. The following table describes how PackageType, + PackageGuid, Handle, and Package are used for each of the + notification types. + + @param[in] PackageType Package type of the notification. + @param[in] PackageGuid If PackageType is + EFI_HII_PACKAGE_TYPE_GUID, then this is + the pointer to the GUID from the Guid + field of EFI_HII_PACKAGE_GUID_HEADER. + Otherwise, it must be NULL. + @param[in] Package Points to the package referred to by the + notification Handle The handle of the package + list which contains the specified package. + @param[in] Handle The HII handle. + @param[in] NotifyType The type of change concerning the + database. See + EFI_HII_DATABASE_NOTIFY_TYPE. + +**/ +EFI_STATUS +EFIAPI +RedfishPlatformConfigFormUpdateNotify ( + IN UINT8 PackageType, + IN CONST EFI_GUID *PackageGuid, + IN CONST EFI_HII_PACKAGE_HEADER *Package, + IN EFI_HII_HANDLE Handle, + IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType + ) +{ + EFI_STATUS Status; + + if (NotifyType == EFI_HII_DATABASE_NOTIFY_NEW_PACK || NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) { + // + // HII formset on this handle is updated by driver during run-time. The formset needs to be reloaded. + // + Status = NotifyFormsetUpdate (Handle, &mRedfishPlatformConfigPrivate->PendingList); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, failed to notify updated formset of HII handle: 0x%x\n", __FUNCTION__, Handle)); + return Status; + } + } else if (NotifyType == EFI_HII_DATABASE_NOTIFY_REMOVE_PACK) { + // + // HII resource is removed. The formset is no longer exist. + // + Status = NotifyFormsetDeleted (Handle, &mRedfishPlatformConfigPrivate->PendingList); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, failed to notify deleted formset of HII handle: 0x%x\n", __FUNCTION__, Handle)); + return Status; + } + } + + return EFI_SUCCESS; +} + +/** + This is a EFI_HII_STRING_PROTOCOL notification event handler. + + Install HII package notification. + + @param[in] Event Event whose notification function is being invoked. + @param[in] Context Pointer to the notification function's context. + +**/ +VOID +EFIAPI +HiiStringProtocolInstalled ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + + // + // Locate HII database protocol. + // + Status = gBS->LocateProtocol ( + &gEfiHiiStringProtocolGuid, + NULL, + (VOID **)&mRedfishPlatformConfigPrivate->HiiString + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, locate EFI_HII_STRING_PROTOCOL failure: %r\n", __FUNCTION__, Status)); + return; + } + + gBS->CloseEvent (Event); + mRedfishPlatformConfigPrivate->HiiStringNotify.ProtocolEvent = NULL; +} + +/** + This is a EFI_HII_DATABASE_PROTOCOL notification event handler. + + Install HII package notification. + + @param[in] Event Event whose notification function is being invoked. + @param[in] Context Pointer to the notification function's context. + +**/ +VOID +EFIAPI +HiiDatabaseProtocolInstalled ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + + // + // Locate HII database protocol. + // + Status = gBS->LocateProtocol ( + &gEfiHiiDatabaseProtocolGuid, + NULL, + (VOID **)&mRedfishPlatformConfigPrivate->HiiDatabase + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, locate EFI_HII_DATABASE_PROTOCOL failure: %r\n", __FUNCTION__, Status)); + return; + } + + // + // Register package notification when new form package is installed. + // + Status = mRedfishPlatformConfigPrivate->HiiDatabase->RegisterPackageNotify ( + mRedfishPlatformConfigPrivate->HiiDatabase, + EFI_HII_PACKAGE_FORMS, + NULL, + RedfishPlatformConfigFormUpdateNotify, + EFI_HII_DATABASE_NOTIFY_NEW_PACK, + &mRedfishPlatformConfigPrivate->NotifyHandle + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, RegisterPackageNotify for EFI_HII_DATABASE_NOTIFY_NEW_PACK failure: %r\n", __FUNCTION__, Status)); + } + + // + // Register package notification when new form package is updated. + // + Status = mRedfishPlatformConfigPrivate->HiiDatabase->RegisterPackageNotify ( + mRedfishPlatformConfigPrivate->HiiDatabase, + EFI_HII_PACKAGE_FORMS, + NULL, + RedfishPlatformConfigFormUpdateNotify, + EFI_HII_DATABASE_NOTIFY_ADD_PACK, + &mRedfishPlatformConfigPrivate->NotifyHandle + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, RegisterPackageNotify for EFI_HII_DATABASE_NOTIFY_NEW_PACK failure: %r\n", __FUNCTION__, Status)); + } + + gBS->CloseEvent (Event); + mRedfishPlatformConfigPrivate->HiiDbNotify.ProtocolEvent = NULL; + +} + +/** + This is a EFI_REGULAR_EXPRESSION_PROTOCOL notification event handler. + + @param[in] Event Event whose notification function is being invoked. + @param[in] Context Pointer to the notification function's context. + +**/ +VOID +EFIAPI +RegexProtocolInstalled ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + + // + // Locate regular expression protocol. + // + Status = gBS->LocateProtocol ( + &gEfiRegularExpressionProtocolGuid, + NULL, + (VOID **)&mRedfishPlatformConfigPrivate->RegularExpressionProtocol + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, locate EFI_REGULAR_EXPRESSION_PROTOCOL failure: %r\n", __FUNCTION__, Status)); + return; + } + + gBS->CloseEvent (Event); + mRedfishPlatformConfigPrivate->RegexNotify.ProtocolEvent = NULL; + +} + +/** + Unloads an image. + + @param ImageHandle Handle that identifies the image to be unloaded. + + @retval EFI_SUCCESS The image has been unloaded. + @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle. + +**/ +EFI_STATUS +EFIAPI +RedfishPlatformConfigDxeUnload ( + IN EFI_HANDLE ImageHandle + ) +{ + EFI_STATUS Status; + + if (mRedfishPlatformConfigPrivate != NULL) { + Status = gBS->UninstallProtocolInterface ( + mRedfishPlatformConfigPrivate->ImageHandle, + &gEdkIIRedfishPlatformConfigProtocolGuid, + (VOID*)&mRedfishPlatformConfigPrivate->Protocol + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, can not uninstall gEdkIIRedfishPlatformConfigProtocolGuid: %r\n", __FUNCTION__, Status)); + ASSERT (FALSE); + } + + // + // Close events + // + if (mRedfishPlatformConfigPrivate->HiiDbNotify.ProtocolEvent != NULL) { + gBS->CloseEvent (mRedfishPlatformConfigPrivate->HiiDbNotify.ProtocolEvent); + } + if (mRedfishPlatformConfigPrivate->HiiStringNotify.ProtocolEvent != NULL) { + gBS->CloseEvent (mRedfishPlatformConfigPrivate->HiiStringNotify.ProtocolEvent); + } + if (mRedfishPlatformConfigPrivate->RegexNotify.ProtocolEvent != NULL) { + gBS->CloseEvent (mRedfishPlatformConfigPrivate->RegexNotify.ProtocolEvent); + } + + // + // Unregister package notification. + // + if (mRedfishPlatformConfigPrivate->NotifyHandle != NULL) { + mRedfishPlatformConfigPrivate->HiiDatabase->UnregisterPackageNotify ( + mRedfishPlatformConfigPrivate->HiiDatabase, + mRedfishPlatformConfigPrivate->NotifyHandle + ); + } + + ReleaseFormsetList (&mRedfishPlatformConfigPrivate->FormsetList); + FreePool (mRedfishPlatformConfigPrivate); + mRedfishPlatformConfigPrivate = NULL; + } + + return EFI_SUCCESS; +} + +/** + This is the declaration of an EFI image entry point. This entry point is + the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including + both device drivers and bus drivers. + + @param ImageHandle The firmware allocated handle for the UEFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The operation completed successfully. + @retval Others An unexpected error occurred. +**/ +EFI_STATUS +EFIAPI +RedfishPlatformConfigDxeEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + mRedfishPlatformConfigPrivate = (REDFISH_PLATFORM_CONFIG_PRIVATE *)AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_PRIVATE)); + if (mRedfishPlatformConfigPrivate == NULL) { + DEBUG ((DEBUG_ERROR, "%a, can not allocate pool for REDFISH_PLATFORM_CONFIG_PRIVATE\n", __FUNCTION__)); + ASSERT (FALSE); + return EFI_OUT_OF_RESOURCES; + } + + // + // Protocol initialization + // + mRedfishPlatformConfigPrivate->ImageHandle = ImageHandle; + mRedfishPlatformConfigPrivate->Protocol.GetValue = RedfishPlatformConfigProtocolGetValue; + mRedfishPlatformConfigPrivate->Protocol.SetValue = RedfishPlatformConfigProtocolSetValue; + mRedfishPlatformConfigPrivate->Protocol.GetConfigureLang = RedfishPlatformConfigProtocolGetConfigureLang; + mRedfishPlatformConfigPrivate->Protocol.GetSupportedSchema = RedfishPlatformConfigProtocolGetSupportedSchema; + + InitializeListHead (&mRedfishPlatformConfigPrivate->FormsetList); + InitializeListHead (&mRedfishPlatformConfigPrivate->PendingList); + + Status = gBS->InstallProtocolInterface ( + &ImageHandle, + &gEdkIIRedfishPlatformConfigProtocolGuid, + EFI_NATIVE_INTERFACE, + (VOID*)&mRedfishPlatformConfigPrivate->Protocol + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, can not install gEdkIIRedfishPlatformConfigProtocolGuid: %r\n", __FUNCTION__, Status)); + ASSERT (FALSE); + } + + // + // Install protocol notification if HII database protocol is installed. + // + mRedfishPlatformConfigPrivate->HiiDbNotify.ProtocolEvent = EfiCreateProtocolNotifyEvent ( + &gEfiHiiDatabaseProtocolGuid, + TPL_CALLBACK, + HiiDatabaseProtocolInstalled, + NULL, + &mRedfishPlatformConfigPrivate->HiiDbNotify.Registration + ); + if (mRedfishPlatformConfigPrivate->HiiDbNotify.ProtocolEvent == NULL) { + DEBUG ((DEBUG_ERROR, "%a, failed to create protocol notification for gEfiHiiDatabaseProtocolGuid\n", __FUNCTION__)); + ASSERT (FALSE); + } + + // + // Install protocol notification if HII string protocol is installed. + // + mRedfishPlatformConfigPrivate->HiiStringNotify.ProtocolEvent = EfiCreateProtocolNotifyEvent ( + &gEfiHiiStringProtocolGuid, + TPL_CALLBACK, + HiiStringProtocolInstalled, + NULL, + &mRedfishPlatformConfigPrivate->HiiStringNotify.Registration + ); + if (mRedfishPlatformConfigPrivate->HiiStringNotify.ProtocolEvent == NULL) { + DEBUG ((DEBUG_ERROR, "%a, failed to create protocol notification for gEfiHiiStringProtocolGuid\n", __FUNCTION__)); + ASSERT (FALSE); + } + + // + // Install protocol notification if regular expression protocol is installed. + // + mRedfishPlatformConfigPrivate->RegexNotify.ProtocolEvent = EfiCreateProtocolNotifyEvent ( + &gEfiRegularExpressionProtocolGuid, + TPL_CALLBACK, + RegexProtocolInstalled, + NULL, + &mRedfishPlatformConfigPrivate->RegexNotify.Registration + ); + if (mRedfishPlatformConfigPrivate->RegexNotify.ProtocolEvent == NULL) { + DEBUG ((DEBUG_ERROR, "%a, failed to create protocol notification for gEfiRegularExpressionProtocolGuid\n", __FUNCTION__)); + ASSERT (FALSE); + } + + return EFI_SUCCESS; +} diff --git a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.h b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.h index 99a613d229..d3f7af55ad 100644 --- a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.h +++ b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.h @@ -1,64 +1,64 @@ -/** @file - This file defines the EDKII Redfish Platform Config Protocol interface. - - (C) Copyright 2021 Hewlett Packard Enterprise Development LP
- - SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#ifndef EDKII_REDFISH_PLATFORM_CONFIG_DXE_H_ -#define EDKII_REDFISH_PLATFORM_CONFIG_DXE_H_ - -#include - -// -// Libraries -// -#include -#include -#include -#include -#include -#include -#include -#include - -// -// Produced Protocols -// -#include -#include -#include -#include - -// -// Definition of EDKII_REDFISH_PLATFORM_CONFIG_NOTIFY. -// -typedef struct { - EFI_EVENT ProtocolEvent; // Protocol notification event. - VOID *Registration; // Protocol notification registration. -} REDFISH_PLATFORM_CONFIG_NOTIFY; - -// -// Definition of REDFISH_PLATFORM_CONFIG_PRIVATE. -// -typedef struct { - EFI_HANDLE ImageHandle; // Driver image handle. - EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL Protocol; - REDFISH_PLATFORM_CONFIG_NOTIFY HiiDbNotify; - EFI_HII_DATABASE_PROTOCOL *HiiDatabase; // The HII database protocol. - REDFISH_PLATFORM_CONFIG_NOTIFY HiiStringNotify; - EFI_HII_STRING_PROTOCOL *HiiString; // HII String Protocol. - REDFISH_PLATFORM_CONFIG_NOTIFY RegexNotify; - EFI_REGULAR_EXPRESSION_PROTOCOL *RegularExpressionProtocol; // Regular Expression Protocol. - EFI_HANDLE NotifyHandle; // The notify handle. - LIST_ENTRY FormsetList; // The list to keep cached HII formset. - LIST_ENTRY PendingList; // The list to keep updated HII handle. -} REDFISH_PLATFORM_CONFIG_PRIVATE; - -#define REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS(a) BASE_CR (a, REDFISH_PLATFORM_CONFIG_PRIVATE, Protocol) -#define REGULAR_EXPRESSION_INCLUDE_ALL L".*" -#define CONFIGURE_LANGUAGE_PREFIX "x-uefi-redfish-" - -#endif +/** @file + This file defines the EDKII Redfish Platform Config Protocol interface. + + (C) Copyright 2021 Hewlett Packard Enterprise Development LP
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef EDKII_REDFISH_PLATFORM_CONFIG_DXE_H_ +#define EDKII_REDFISH_PLATFORM_CONFIG_DXE_H_ + +#include + +// +// Libraries +// +#include +#include +#include +#include +#include +#include +#include +#include + +// +// Produced Protocols +// +#include +#include +#include +#include + +// +// Definition of EDKII_REDFISH_PLATFORM_CONFIG_NOTIFY. +// +typedef struct { + EFI_EVENT ProtocolEvent; // Protocol notification event. + VOID *Registration; // Protocol notification registration. +} REDFISH_PLATFORM_CONFIG_NOTIFY; + +// +// Definition of REDFISH_PLATFORM_CONFIG_PRIVATE. +// +typedef struct { + EFI_HANDLE ImageHandle; // Driver image handle. + EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL Protocol; + REDFISH_PLATFORM_CONFIG_NOTIFY HiiDbNotify; + EFI_HII_DATABASE_PROTOCOL *HiiDatabase; // The HII database protocol. + REDFISH_PLATFORM_CONFIG_NOTIFY HiiStringNotify; + EFI_HII_STRING_PROTOCOL *HiiString; // HII String Protocol. + REDFISH_PLATFORM_CONFIG_NOTIFY RegexNotify; + EFI_REGULAR_EXPRESSION_PROTOCOL *RegularExpressionProtocol; // Regular Expression Protocol. + EFI_HANDLE NotifyHandle; // The notify handle. + LIST_ENTRY FormsetList; // The list to keep cached HII formset. + LIST_ENTRY PendingList; // The list to keep updated HII handle. +} REDFISH_PLATFORM_CONFIG_PRIVATE; + +#define REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS(a) BASE_CR (a, REDFISH_PLATFORM_CONFIG_PRIVATE, Protocol) +#define REGULAR_EXPRESSION_INCLUDE_ALL L".*" +#define CONFIGURE_LANGUAGE_PREFIX "x-uefi-redfish-" + +#endif diff --git a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.inf b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.inf index 16739bef7a..81b22e03c3 100644 --- a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.inf +++ b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.inf @@ -1,53 +1,53 @@ -## @file -# Implementation of EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL interfaces. -# -# (C) Copyright 2021 Hewlett Packard Enterprise Development LP
-# SPDX-License-Identifier: BSD-2-Clause-Patent -# -## - -[Defines] - INF_VERSION = 0x00010005 - BASE_NAME = RedfishPlatformConfigDxe - FILE_GUID = BEAEFFE1-0633-41B5-913C-9389339C2927 - MODULE_TYPE = DXE_DRIVER - VERSION_STRING = 1.0 - ENTRY_POINT = RedfishPlatformConfigDxeEntryPoint - UNLOAD_IMAGE = RedfishPlatformConfigDxeUnload - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - RedfishPkg/RedfishPkg.dec - -[Sources] - RedfishPlatformConfigDxe.h - RedfishPlatformConfigDxe.c - RedfishPlatformConfigImpl.h - RedfishPlatformConfigImpl.c - -[LibraryClasses] - BaseLib - BaseMemoryLib - DebugLib - DevicePathLib - HiiLib - HiiUtilityLib - MemoryAllocationLib - PrintLib - UefiLib - UefiBootServicesTableLib - UefiRuntimeServicesTableLib - UefiDriverEntryPoint - -[Protocols] - gEdkIIRedfishPlatformConfigProtocolGuid ## PRODUCED - gEfiHiiDatabaseProtocolGuid ## CONSUMED - gEfiHiiStringProtocolGuid ## CONSUMED - gEfiRegularExpressionProtocolGuid ## CONSUMED - -[Guids] - gEfiRegexSyntaxTypePerlGuid ## CONSUMED - -[Depex] +## @file +# Implementation of EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL interfaces. +# +# (C) Copyright 2021 Hewlett Packard Enterprise Development LP
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = RedfishPlatformConfigDxe + FILE_GUID = BEAEFFE1-0633-41B5-913C-9389339C2927 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = RedfishPlatformConfigDxeEntryPoint + UNLOAD_IMAGE = RedfishPlatformConfigDxeUnload + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + RedfishPkg/RedfishPkg.dec + +[Sources] + RedfishPlatformConfigDxe.h + RedfishPlatformConfigDxe.c + RedfishPlatformConfigImpl.h + RedfishPlatformConfigImpl.c + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + DevicePathLib + HiiLib + HiiUtilityLib + MemoryAllocationLib + PrintLib + UefiLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + UefiDriverEntryPoint + +[Protocols] + gEdkIIRedfishPlatformConfigProtocolGuid ## PRODUCED + gEfiHiiDatabaseProtocolGuid ## CONSUMED + gEfiHiiStringProtocolGuid ## CONSUMED + gEfiRegularExpressionProtocolGuid ## CONSUMED + +[Guids] + gEfiRegexSyntaxTypePerlGuid ## CONSUMED + +[Depex] TRUE \ No newline at end of file diff --git a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.c b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.c index d9eab6c883..917f946656 100644 --- a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.c +++ b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.c @@ -1,1240 +1,1288 @@ -/** @file - - The implementation of EDKII Redfidh Platform Config Protocol. - - (C) Copyright 2021 Hewlett Packard Enterprise Development LP
- - SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ -#include "RedfishPlatformConfigDxe.h" -#include "RedfishPlatformConfigImpl.h" - -extern REDFISH_PLATFORM_CONFIG_PRIVATE *mRedfishPlatformConfigPrivate; - -/** - Debug dump HII string - - @param[in] HiiHandle HII handle instance - @param[in] StringId HII string to dump - - @retval EFI_SUCCESS Dump HII string successfully - @retval Others Errors occur - -**/ -EFI_STATUS -DumpHiiString ( - IN EFI_HII_HANDLE HiiHandle, - IN EFI_STRING_ID StringId - ) -{ - EFI_STRING String; - - if (HiiHandle == NULL || StringId == 0) { - DEBUG ((DEBUG_INFO, "???")); - return EFI_INVALID_PARAMETER; - } - - String = HiiGetString (HiiHandle, StringId, NULL); - if (String == NULL) { - return EFI_NOT_FOUND; - } - - DEBUG ((DEBUG_INFO, "%s", String)); - FreePool (String); - - return EFI_SUCCESS; -} - -/** - Debug dump HII form-set data - - @param[in] FormsetPrivate HII form-set private instance. - - @retval EFI_SUCCESS Dump form-set successfully - @retval Others Errors occur - -**/ -EFI_STATUS -DumpFormset ( - IN REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *FormsetPrivate - ) -{ - LIST_ENTRY *HiiFormLink; - LIST_ENTRY *HiiNextFormLink; - REDFISH_PLATFORM_CONFIG_FORM_PRIVATE *HiiFormPrivate; - LIST_ENTRY *HiiStatementLink; - LIST_ENTRY *HiiNextStatementLink; - REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *HiiStatementPrivate; - UINTN Index; - - if (FormsetPrivate == NULL) { - return EFI_INVALID_PARAMETER; - } - - Index = 0; - HiiFormLink = GetFirstNode (&FormsetPrivate->HiiFormList); - while (!IsNull (&FormsetPrivate->HiiFormList, HiiFormLink)) { - HiiFormPrivate = REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK (HiiFormLink); - HiiNextFormLink = GetNextNode (&FormsetPrivate->HiiFormList, HiiFormLink); - - DEBUG ((DEBUG_INFO, " [%d] form: %d title: ", ++Index, HiiFormPrivate->Id)); - DumpHiiString (FormsetPrivate->HiiHandle, HiiFormPrivate->Title); - DEBUG ((DEBUG_INFO, "\n")); - - HiiStatementLink = GetFirstNode (&HiiFormPrivate->StatementList); - while (!IsNull (&HiiFormPrivate->StatementList, HiiStatementLink)) { - HiiStatementPrivate = REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK (HiiStatementLink); - HiiNextStatementLink = GetNextNode (&HiiFormPrivate->StatementList, HiiStatementLink); - - DEBUG ((DEBUG_INFO, " QID: 0x%x Prompt: ", HiiStatementPrivate->QuestionId)); - DumpHiiString (FormsetPrivate->HiiHandle, HiiStatementPrivate->Description); - DEBUG ((DEBUG_INFO, "\n")); - - HiiStatementLink = HiiNextStatementLink; - } - - HiiFormLink = HiiNextFormLink; - } - - return EFI_SUCCESS; -} - -/** - Debug dump HII form-set list - - @param[in] FormsetList Form-set list instance - - @retval EFI_SUCCESS Dump list successfully - @retval Others Errors occur - -**/ -EFI_STATUS -DumpFormsetList ( - IN LIST_ENTRY *FormsetList - ) -{ - LIST_ENTRY *HiiFormsetLink; - LIST_ENTRY *HiiFormsetNextLink; - REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *HiiFormsetPrivate; - UINTN Index; - - if (FormsetList == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (IsListEmpty (FormsetList)) { - DEBUG ((DEBUG_INFO, "%a, Empty formset list\n", __FUNCTION__)); - return EFI_SUCCESS; - } - - Index = 0; - HiiFormsetLink = GetFirstNode (FormsetList); - while (!IsNull (FormsetList, HiiFormsetLink)) { - HiiFormsetNextLink = GetNextNode (FormsetList, HiiFormsetLink); - HiiFormsetPrivate = REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink); - - DEBUG ((DEBUG_INFO, "[%d] HII Handle: 0x%x formset: %g at %s\n", ++Index, HiiFormsetPrivate->HiiHandle, &HiiFormsetPrivate->Guid, HiiFormsetPrivate->DevicePathStr)); - DumpFormset (HiiFormsetPrivate); - - HiiFormsetLink = HiiFormsetNextLink; - } - - return EFI_SUCCESS; -} - -/** - Retrieves a string from a string package in a English language. The - returned string is allocated using AllocatePool(). The caller is responsible - for freeing the allocated buffer using FreePool(). - - If HiiHandle is NULL, then ASSERT(). - If StringId is 0, then ASSET. - - @param[in] HiiStringProtocol EFI_HII_STRING_PROTOCOL instance. - @param[in] HiiHandle A handle that was previously registered in the HII Database. - @param[in] StringId The identifier of the string to retrieved from the string - package associated with HiiHandle. - - @retval NULL The string specified by StringId is not present in the string package. - @retval Other The string was returned. - -**/ -EFI_STRING -HiiGetRedfishString ( - IN EFI_HII_HANDLE HiiHandle, - IN CHAR8 *Language, - IN EFI_STRING_ID StringId - ) -{ - EFI_STATUS Status; - UINTN StringSize; - CHAR16 TempString; - EFI_STRING String; - - if (mRedfishPlatformConfigPrivate->HiiString == NULL || HiiHandle == NULL || StringId == 0 || IS_EMPTY_STRING (Language)) { - ASSERT (FALSE); - return NULL; - } - - // - // Retrieve the size of the string in the string package for the BestLanguage - // - StringSize = 0; - Status = mRedfishPlatformConfigPrivate->HiiString->GetString ( - mRedfishPlatformConfigPrivate->HiiString, - Language, - HiiHandle, - StringId, - &TempString, - &StringSize, - NULL - ); - // - // If GetString() returns EFI_SUCCESS for a zero size, - // then there are no supported languages registered for HiiHandle. If GetString() - // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present - // in the HII Database - // - if (Status != EFI_BUFFER_TOO_SMALL) { - return NULL; - } - - // - // Allocate a buffer for the return string - // - String = AllocateZeroPool (StringSize); - if (String == NULL) { - return NULL; - } - - // - // Retrieve the string from the string package - // - Status = mRedfishPlatformConfigPrivate->HiiString->GetString ( - mRedfishPlatformConfigPrivate->HiiString, - Language, - HiiHandle, - StringId, - String, - &StringSize, - NULL - ); - if (EFI_ERROR (Status)) { - // - // Free the buffer and return NULL if the supported languages can not be retrieved. - // - FreePool (String); - String = NULL; - } - - // - // Return the Null-terminated Unicode string - // - return String; -} - -/** - Get string from HII database in English language. - - @param[in] HiiHandle A handle that was previously registered in the HII Database. - @param[in] StringId The identifier of the string to retrieved from the string - package associated with HiiHandle. - - @retval NULL The string specified by StringId is not present in the string package. - @retval Other The string was returned. - -**/ -EFI_STRING -HiiGetEnglishString ( - IN EFI_HII_HANDLE HiiHandle, - IN EFI_STRING_ID StringId - ) -{ - return HiiGetRedfishString (HiiHandle, ENGLISH_LANGUAGE_CODE, StringId); -} - -/** - Check and see if this is supported schema or not. - - @param[in] SupportedSchema The list of supported schema. - @param[in] Schema Schema string to be checked. - - @retval BOOLEAN TRUE if this is supported schema. FALSE otherwise. - -**/ -BOOLEAN -CheckSupportedSchema ( - IN REDFISH_PLATFORM_CONFIG_SCHEMA *SupportedSchema, - IN CHAR8 *Schema - ) -{ - UINTN Index; - - if (SupportedSchema == NULL || IS_EMPTY_STRING (Schema)) { - return FALSE; - } - - if (SupportedSchema->Count == 0) { - return FALSE; - } - - for (Index = 0; Index < SupportedSchema->Count; Index++) { - if (AsciiStrCmp (SupportedSchema->SchemaList[Index], Schema) == 0) { - return TRUE; - } - } - - return FALSE; -} - -/** - Get the list of supported schema from the given HII handle. - - @param[in] HiiHandle HII handle instance. - @param[out] SupportedSchema Supported schema on this HII handle. - - @retval EFI_SUCCESS Schema list is returned. - @retval EFI_INVALID_PARAMETER HiiHandle is NULL or SupportedSchema is NULL. - @retval EFI_NOT_FOUND No supported schema found. - @retval EFI_OUT_OF_RESOURCES System is out of memory. - -**/ -EFI_STATUS -GetSupportedSchema ( - IN EFI_HII_HANDLE HiiHandle, - OUT REDFISH_PLATFORM_CONFIG_SCHEMA *SupportedSchema - ) -{ - CHAR8 *SupportedLanguages; - UINTN Index; - UINTN LangIndex; - UINTN Count; - UINTN StrSize; - UINTN ListIndex; - - if (HiiHandle == NULL || SupportedSchema == NULL) { - return EFI_INVALID_PARAMETER; - } - - SupportedSchema->Count = 0; - - SupportedLanguages = HiiGetSupportedLanguages (HiiHandle); - if (SupportedLanguages == NULL) { - return EFI_NOT_FOUND; - } - - Index = 0; - LangIndex = 0; - Count = 0; - while (TRUE) { - if (SupportedLanguages[Index] == ';' || SupportedLanguages[Index] == '\0') { - if (AsciiStrnCmp (&SupportedLanguages[LangIndex], X_UEFI_SCHEMA_PREFIX, AsciiStrLen (X_UEFI_SCHEMA_PREFIX)) == 0) { - ++Count; - } - LangIndex = Index + 1; - } - - if (SupportedLanguages[Index] == '\0') { - break; - } - - ++Index; - } - - if (Count == 0) { - return EFI_NOT_FOUND; - } - - SupportedSchema->Count = Count; - SupportedSchema->SchemaList = AllocatePool (sizeof (CHAR8 *) * Count); - if (SupportedSchema->SchemaList == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - Index = 0; - LangIndex = 0; - ListIndex = 0; - while (TRUE) { - - if (SupportedLanguages[Index] == ';' || SupportedLanguages[Index] == '\0') { - if (AsciiStrnCmp (&SupportedLanguages[LangIndex], X_UEFI_SCHEMA_PREFIX, AsciiStrLen (X_UEFI_SCHEMA_PREFIX)) == 0) { - StrSize = Index - LangIndex; - SupportedSchema->SchemaList[ListIndex] = AllocateCopyPool ((StrSize + 1), &SupportedLanguages[LangIndex]); - SupportedSchema->SchemaList[ListIndex][StrSize] = '\0'; - ++ListIndex; - } - - LangIndex = Index + 1; - } - - if (SupportedLanguages[Index] == '\0') { - break; - } - - ++Index; - } - - return EFI_SUCCESS; -} - -/** - Search and find statement private instance by given regular expression patthern - which describes the Configure Language. - - @param[in] RegularExpressionProtocol Regular express protocol. - @param[in] FormsetList Form-set list to search. - @param[in] Schema Schema to be matched. - @param[in] Pattern Regular expression pattern. - @param[out] StatementList Statement list that match above pattern. - - @retval EFI_SUCCESS Statement list is returned. - @retval EFI_INVALID_PARAMETER Input parameter is NULL. - @retval EFI_NOT_READY Regular express protocol is NULL. - @retval EFI_NOT_FOUND No statement is found. - @retval EFI_OUT_OF_RESOURCES System is out of memory. - -**/ -EFI_STATUS -GetStatementPrivateByConfigureLangRegex ( - IN EFI_REGULAR_EXPRESSION_PROTOCOL *RegularExpressionProtocol, - IN LIST_ENTRY *FormsetList, - IN CHAR8 *Schema, - IN EFI_STRING Pattern, - OUT REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST *StatementList - ) -{ - LIST_ENTRY *HiiFormsetLink; - LIST_ENTRY *HiiFormsetNextLink; - REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *HiiFormsetPrivate; - LIST_ENTRY *HiiFormLink; - LIST_ENTRY *HiiNextFormLink; - REDFISH_PLATFORM_CONFIG_FORM_PRIVATE *HiiFormPrivate; - LIST_ENTRY *HiiStatementLink; - LIST_ENTRY *HiiNextStatementLink; - REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *HiiStatementPrivate; - EFI_STRING TmpString; - UINTN CaptureCount; - BOOLEAN IsMatch; - EFI_STATUS Status; - REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF *StatementRef; - - if (FormsetList == NULL || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Pattern) || StatementList == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (RegularExpressionProtocol == NULL) { - return EFI_NOT_READY; - } - - StatementList->Count = 0; - InitializeListHead (&StatementList->StatementList); - - if (IsListEmpty (FormsetList)) { - return EFI_NOT_FOUND; - } - - HiiFormsetLink = GetFirstNode (FormsetList); - while (!IsNull (FormsetList, HiiFormsetLink)) { - HiiFormsetNextLink = GetNextNode (FormsetList, HiiFormsetLink); - HiiFormsetPrivate = REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink); - - // - // Performance check. - // If there is no desired Redfish schema found, skip this formset. - // - if (!CheckSupportedSchema (&HiiFormsetPrivate->SupportedSchema, Schema)) { - HiiFormsetLink = HiiFormsetNextLink; - continue; - } - - HiiFormLink = GetFirstNode (&HiiFormsetPrivate->HiiFormList); - while (!IsNull (&HiiFormsetPrivate->HiiFormList, HiiFormLink)) { - HiiNextFormLink = GetNextNode (&HiiFormsetPrivate->HiiFormList, HiiFormLink); - HiiFormPrivate = REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK (HiiFormLink); - - HiiStatementLink =GetFirstNode (&HiiFormPrivate->StatementList); - while (!IsNull (&HiiFormPrivate->StatementList, HiiStatementLink)) { - HiiNextStatementLink = GetNextNode (&HiiFormPrivate->StatementList, HiiStatementLink); - HiiStatementPrivate = REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK (HiiStatementLink); - - if (HiiStatementPrivate->Description != 0) { - TmpString = HiiGetRedfishString (HiiFormsetPrivate->HiiHandle, Schema, HiiStatementPrivate->Description); - if (TmpString != NULL) { - Status = RegularExpressionProtocol->MatchString ( - RegularExpressionProtocol, - TmpString, - Pattern, - &gEfiRegexSyntaxTypePerlGuid, - &IsMatch, - NULL, - &CaptureCount - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a, MatchString \"%s\" failed: %r\n", __FUNCTION__, Pattern, Status)); - ASSERT (FALSE); - return Status; - } - - // - // Found - // - if (IsMatch) { - StatementRef = AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF)); - if (StatementRef == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - StatementRef->Statement = HiiStatementPrivate; - InsertTailList (&StatementList->StatementList, &StatementRef->Link); - ++StatementList->Count; - } - - FreePool (TmpString); - } - } - - HiiStatementLink = HiiNextStatementLink; - } - - HiiFormLink = HiiNextFormLink; - } - - HiiFormsetLink = HiiFormsetNextLink; - } - - return EFI_SUCCESS; -} - -/** - Get statement private instance by the given configure language. - - @param[in] FormsetList Form-set list to search. - @param[in] Schema Schema to be matched. - @param[in] ConfigureLang Configure language. - - @retval REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE * Pointer to statement private instance. - -**/ -REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE * -GetStatementPrivateByConfigureLang ( - IN LIST_ENTRY *FormsetList, - IN CHAR8 *Schema, - IN EFI_STRING ConfigureLang - ) -{ - LIST_ENTRY *HiiFormsetLink; - LIST_ENTRY *HiiFormsetNextLink; - REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *HiiFormsetPrivate; - LIST_ENTRY *HiiFormLink; - LIST_ENTRY *HiiNextFormLink; - REDFISH_PLATFORM_CONFIG_FORM_PRIVATE *HiiFormPrivate; - LIST_ENTRY *HiiStatementLink; - LIST_ENTRY *HiiNextStatementLink; - REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *HiiStatementPrivate; - EFI_STRING TmpString; - - if (FormsetList == NULL || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (ConfigureLang)) { - return NULL; - } - - if (IsListEmpty (FormsetList)) { - return NULL; - } - - HiiFormsetLink = GetFirstNode (FormsetList); - while (!IsNull (FormsetList, HiiFormsetLink)) { - HiiFormsetNextLink = GetNextNode (FormsetList, HiiFormsetLink); - HiiFormsetPrivate = REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink); - - // - // Performance check. - // If there is no desired Redfish schema found, skip this formset. - // - if (!CheckSupportedSchema (&HiiFormsetPrivate->SupportedSchema, Schema)) { - HiiFormsetLink = HiiFormsetNextLink; - continue; - } - - HiiFormLink = GetFirstNode (&HiiFormsetPrivate->HiiFormList); - while (!IsNull (&HiiFormsetPrivate->HiiFormList, HiiFormLink)) { - HiiNextFormLink = GetNextNode (&HiiFormsetPrivate->HiiFormList, HiiFormLink); - HiiFormPrivate = REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK (HiiFormLink); - - HiiStatementLink =GetFirstNode (&HiiFormPrivate->StatementList); - while (!IsNull (&HiiFormPrivate->StatementList, HiiStatementLink)) { - HiiNextStatementLink = GetNextNode (&HiiFormPrivate->StatementList, HiiStatementLink); - HiiStatementPrivate = REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK (HiiStatementLink); - - DEBUG_CODE ( - STATIC UINTN Index = 0; - DEBUG ((DEBUG_INFO, "%a, [%d] search %s in QID: 0x%x form: 0x%x formset: %g\n", __FUNCTION__, ++Index, ConfigureLang, HiiStatementPrivate->QuestionId, HiiFormPrivate->Id, &HiiFormsetPrivate->Guid)); - ); - - if (HiiStatementPrivate->Description != 0) { - TmpString = HiiGetRedfishString (HiiFormsetPrivate->HiiHandle, Schema, HiiStatementPrivate->Description); - if (TmpString != NULL) { - if (StrCmp (TmpString, ConfigureLang) == 0) { - FreePool (TmpString); - return HiiStatementPrivate; - } - - FreePool (TmpString); - } - } - - HiiStatementLink = HiiNextStatementLink; - } - - HiiFormLink = HiiNextFormLink; - } - - HiiFormsetLink = HiiFormsetNextLink; - } - - return NULL; -} - -/** - Get form-set private instance by the given HII handle. - - @param[in] HiiHandle HII handle instance. - @param[in] FormsetList Form-set list to search. - - @retval REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE * Pointer to form-set private instance. - -**/ -REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE * -GetFormsetPrivateByHiiHandle ( - IN EFI_HII_HANDLE HiiHandle, - IN LIST_ENTRY *FormsetList - ) -{ - LIST_ENTRY *HiiFormsetLink; - LIST_ENTRY *HiiFormsetNextLink; - REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *HiiFormsetPrivate; - - if (HiiHandle == NULL || FormsetList == NULL) { - return NULL; - } - - if (IsListEmpty (FormsetList)) { - return NULL; - } - - HiiFormsetLink = GetFirstNode (FormsetList); - while (!IsNull (FormsetList, HiiFormsetLink)) { - HiiFormsetNextLink = GetNextNode (FormsetList, HiiFormsetLink); - HiiFormsetPrivate = REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink); - - if (HiiFormsetPrivate->HiiHandle == HiiHandle) { - return HiiFormsetPrivate; - } - - HiiFormsetLink = HiiFormsetNextLink; - } - - return NULL; -} - -/** - Release formset and all the forms and statements that belong to this formset. - - @param[in] FormsetPrivate Pointer to HP_HII_FORM_SET_PRIVATE - - @retval EFI_STATUS - -**/ -EFI_STATUS -ReleaseFormset ( - IN REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *FormsetPrivate - ) -{ - LIST_ENTRY *HiiFormLink; - LIST_ENTRY *HiiNextFormLink; - REDFISH_PLATFORM_CONFIG_FORM_PRIVATE *HiiFormPrivate; - LIST_ENTRY *HiiStatementLink; - LIST_ENTRY *HiiNextStatementLink; - REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *HiiStatementPrivate; - UINTN Index; - - if (FormsetPrivate == NULL) { - return EFI_INVALID_PARAMETER; - } - - HiiFormLink = GetFirstNode (&FormsetPrivate->HiiFormList); - while (!IsNull (&FormsetPrivate->HiiFormList, HiiFormLink)) { - HiiFormPrivate = REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK (HiiFormLink); - HiiNextFormLink = GetNextNode (&FormsetPrivate->HiiFormList, HiiFormLink); - - HiiStatementLink = GetFirstNode (&HiiFormPrivate->StatementList); - while (!IsNull (&HiiFormPrivate->StatementList, HiiStatementLink)) { - HiiStatementPrivate = REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK (HiiStatementLink); - HiiNextStatementLink = GetNextNode (&HiiFormPrivate->StatementList, HiiStatementLink); - - // - // HiiStatementPrivate->HiiStatement will be released in DestroyFormSet(). - // - - if (HiiStatementPrivate->DesStringCache != NULL) { - FreePool (HiiStatementPrivate->DesStringCache); - HiiStatementPrivate->DesStringCache = NULL; - } - - RemoveEntryList (&HiiStatementPrivate->Link); - FreePool (HiiStatementPrivate); - HiiStatementLink = HiiNextStatementLink; - } - - // - // HiiStatementPrivate->HiiForm will be released in DestroyFormSet(). - // - - RemoveEntryList (&HiiFormPrivate->Link); - FreePool (HiiFormPrivate); - HiiFormLink = HiiNextFormLink; - } - - if (FormsetPrivate->HiiFormSet != NULL) { - DestroyFormSet (FormsetPrivate->HiiFormSet); - FormsetPrivate->HiiFormSet = NULL; - } - - FreePool (FormsetPrivate->DevicePathStr); - - // - // Release schema list - // - if (FormsetPrivate->SupportedSchema.SchemaList != NULL) { - for (Index = 0; Index < FormsetPrivate->SupportedSchema.Count; Index++) { - FreePool (FormsetPrivate->SupportedSchema.SchemaList[Index]); - } - - FreePool (FormsetPrivate->SupportedSchema.SchemaList); - FormsetPrivate->SupportedSchema.SchemaList = NULL; - FormsetPrivate->SupportedSchema.Count = 0; - } - - return EFI_SUCCESS; -} - -/** - Create new form-set instance. - - @retval REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE * Pointer to newly created form-set private instance. - -**/ -REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE * -NewFormsetPrivate ( - VOID - ) -{ - REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *NewFormsetPrivate; - - NewFormsetPrivate = AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE)); - if (NewFormsetPrivate == NULL) { - return NULL; - } - - // - // Initial newly created formset private data. - // - InitializeListHead (&NewFormsetPrivate->HiiFormList); - - return NewFormsetPrivate; -} - -/** - Load the HII formset from the given HII handle. - - @param[in] HiiHandle Target HII handle to load. - @param[out] FormsetPrivate The formset private data. - - @retval EFI_STATUS - -**/ -EFI_STATUS -LoadFormset ( - IN EFI_HII_HANDLE HiiHandle, - OUT REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *FormsetPrivate - ) -{ - EFI_STATUS Status; - HII_FORMSET *HiiFormSet; - HII_FORM *HiiForm; - LIST_ENTRY *HiiFormLink; - REDFISH_PLATFORM_CONFIG_FORM_PRIVATE *HiiFormPrivate; - HII_STATEMENT *HiiStatement; - LIST_ENTRY *HiiStatementLink; - REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *HiiStatementPrivate; - EFI_GUID ZeroGuid; - - if (HiiHandle == NULL || FormsetPrivate == NULL) { - return EFI_INVALID_PARAMETER; - } - - - HiiFormSet = AllocateZeroPool (sizeof (HII_FORMSET)); - if (HiiFormSet == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - // - // Find HII formset by the given HII handle. - // - ZeroMem (&ZeroGuid, sizeof (ZeroGuid)); - Status = CreateFormSetFromHiiHandle (HiiHandle, &ZeroGuid, HiiFormSet); - if (EFI_ERROR (Status) || IsListEmpty (&HiiFormSet->FormListHead)) { - Status = EFI_NOT_FOUND; - goto ErrorExit; - } - - // - // Initialize formset - // - InitializeFormSet (HiiFormSet); - - // - // Initialize formset private data. - // - FormsetPrivate->HiiFormSet = HiiFormSet; - FormsetPrivate->HiiHandle = HiiHandle; - CopyGuid (&FormsetPrivate->Guid, &HiiFormSet->Guid); - FormsetPrivate->DevicePathStr = ConvertDevicePathToText (HiiFormSet->DevicePath, FALSE, FALSE); - Status = GetSupportedSchema (FormsetPrivate->HiiHandle, &FormsetPrivate->SupportedSchema); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_WARN, "%a, No schema from HII handle: 0x%x found: %r\n", __FUNCTION__, FormsetPrivate->HiiHandle, Status)); - } - - HiiFormLink = GetFirstNode (&HiiFormSet->FormListHead); - while (!IsNull (&HiiFormSet->FormListHead, HiiFormLink)) { - HiiForm = HII_FORM_FROM_LINK (HiiFormLink); - - HiiFormPrivate = AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_FORM_PRIVATE)); - if (HiiFormPrivate == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ErrorExit; - } - - // - // Initialize form private data. - // - HiiFormPrivate->HiiForm = HiiForm; - HiiFormPrivate->Id = HiiForm->FormId; - HiiFormPrivate->Title = HiiForm->FormTitle; - HiiFormPrivate->ParentFormset = FormsetPrivate; - InitializeListHead (&HiiFormPrivate->StatementList); - - HiiStatementLink = GetFirstNode (&HiiForm->StatementListHead); - while (!IsNull (&HiiForm->StatementListHead, HiiStatementLink)) { - HiiStatement = HII_STATEMENT_FROM_LINK (HiiStatementLink); - - HiiStatementPrivate = AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE)); - if (HiiStatementPrivate == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ErrorExit; - } - // - // Initialize statement private data. - // - HiiStatementPrivate->HiiStatement = HiiStatement; - HiiStatementPrivate->QuestionId = HiiStatement->QuestionId; - HiiStatementPrivate->Description = HiiStatement->Prompt; - HiiStatementPrivate->ParentForm = HiiFormPrivate; - - // - // Attach to statement list. - // - InsertTailList (&HiiFormPrivate->StatementList, &HiiStatementPrivate->Link); - HiiStatementLink = GetNextNode (&HiiForm->StatementListHead, HiiStatementLink); - } - // - // Attach to form list. - // - InsertTailList (&FormsetPrivate->HiiFormList, &HiiFormPrivate->Link); - HiiFormLink = GetNextNode (&HiiFormSet->FormListHead, HiiFormLink); - } - - return EFI_SUCCESS; - -ErrorExit: - - // - // Release HiiFormSet if HiiFormSet is not linked to FormsetPrivate yet. - // - if (HiiFormSet != NULL && FormsetPrivate->HiiFormSet != HiiFormSet) { - DestroyFormSet (HiiFormSet); - } - - // - // Release resource when error happens. - // - ReleaseFormset (FormsetPrivate); - - return Status; -} - -/** - Release formset list and all the forms that belong to this formset. - - @param[in] FormsetList Pointer to formst list that needs to be - released. - - @retval EFI_STATUS - -**/ -EFI_STATUS -LoadFormsetList ( - IN EFI_HII_HANDLE *HiiHandle, - OUT LIST_ENTRY *FormsetList - ) -{ - EFI_STATUS Status; - REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *FormsetPrivate; - - if (HiiHandle == NULL || FormsetList == NULL) { - return EFI_INVALID_PARAMETER; - } - - FormsetPrivate = GetFormsetPrivateByHiiHandle (HiiHandle, FormsetList); - if (FormsetPrivate != NULL) { - return EFI_ALREADY_STARTED; - } - - FormsetPrivate = NewFormsetPrivate (); - if (FormsetPrivate == NULL) { - DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__)); - return EFI_OUT_OF_RESOURCES; - } - - // - // Load formset on the given HII handle. - // - Status = LoadFormset (HiiHandle, FormsetPrivate); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a, failed to load formset: %r\n", __FUNCTION__, Status)); - FreePool (FormsetPrivate); - return Status; - } - - // - // Attach to cache list. - // - InsertTailList (FormsetList, &FormsetPrivate->Link); - - DEBUG_CODE ( - DumpFormsetList (FormsetList); - ); - - return EFI_SUCCESS; -} - -/** - Release formset list and all the forms that belong to this formset. - - @param[in] FormsetList Pointer to formst list that needs to be - released. - - @retval EFI_STATUS - -**/ -EFI_STATUS -ReleaseFormsetList ( - IN LIST_ENTRY *FormsetList - ) -{ - LIST_ENTRY *HiiFormsetLink; - LIST_ENTRY *HiiFormsetNextLink; - REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *HiiFormsetPrivate; - - if (FormsetList == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (IsListEmpty (FormsetList)) { - return EFI_SUCCESS; - } - - HiiFormsetLink = GetFirstNode (FormsetList); - while (!IsNull (FormsetList, HiiFormsetLink)) { - HiiFormsetNextLink = GetNextNode (FormsetList, HiiFormsetLink); - HiiFormsetPrivate = REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink); - - // - // Detach from list. - // - RemoveEntryList (&HiiFormsetPrivate->Link); - ReleaseFormset (HiiFormsetPrivate); - FreePool (HiiFormsetPrivate); - HiiFormsetLink = HiiFormsetNextLink; - } - - return EFI_SUCCESS; -} - -/** - Get all pending list. - - @param[in] HiiHandle HII handle instance. - @param[in] PendingList Pending list to keep pending data. - - @retval REDFISH_PLATFORM_CONFIG_PENDING_LIST * Pointer to pending list data. - -**/ -REDFISH_PLATFORM_CONFIG_PENDING_LIST * -GetPendingList ( - IN EFI_HII_HANDLE *HiiHandle, - IN LIST_ENTRY *PendingList - ) -{ - LIST_ENTRY *PendingListLink; - REDFISH_PLATFORM_CONFIG_PENDING_LIST *Target; - - if (HiiHandle == NULL || PendingList == NULL) { - return NULL; - } - - if (IsListEmpty (PendingList)) { - return NULL; - } - - PendingListLink = GetFirstNode (PendingList); - while (!IsNull (PendingList, PendingListLink)) { - Target = REDFISH_PLATFORM_CONFIG_PENDING_LIST_FROM_LINK (PendingListLink); - - if (Target->HiiHandle == HiiHandle) { - return Target; - } - - PendingListLink = GetNextNode (PendingList, PendingListLink); - } - - return NULL; -} - -/** - When HII database is updated. Keep updated HII handle into pending list so - we can process them later. - - @param[in] HiiHandle HII handle instance. - @param[in] PendingList Pending list to keep HII handle which is recently updated. - - @retval EFI_SUCCESS HII handle is saved in pending list. - @retval EFI_INVALID_PARAMETER HiiHnalde is NULL or PendingList is NULL. - @retval EFI_OUT_OF_RESOURCES System is out of memory. - -**/ -EFI_STATUS -NotifyFormsetUpdate ( - IN EFI_HII_HANDLE *HiiHandle, - IN LIST_ENTRY *PendingList - ) -{ - REDFISH_PLATFORM_CONFIG_PENDING_LIST *TargetPendingList; - - if (HiiHandle == NULL || PendingList == NULL) { - return EFI_INVALID_PARAMETER; - } - - // - // Check and see if this HII handle is processed already. - // - TargetPendingList = GetPendingList (HiiHandle, PendingList); - if (TargetPendingList != NULL) { - TargetPendingList->IsDeleted = FALSE; - DEBUG_CODE ( - DEBUG ((DEBUG_INFO, "%a, HII handle: 0x%x is updated\n", __FUNCTION__, HiiHandle)); - ); - return EFI_SUCCESS; - } - - TargetPendingList= AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_PENDING_LIST)); - if (TargetPendingList == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - TargetPendingList->HiiHandle = HiiHandle; - TargetPendingList->IsDeleted = FALSE; - - InsertTailList (PendingList, &TargetPendingList->Link); - - DEBUG_CODE ( - DEBUG ((DEBUG_INFO, "%a, HII handle: 0x%x is created\n", __FUNCTION__, HiiHandle)); - ); - - return EFI_SUCCESS; -} - -/** - When HII database is updated and form-set is deleted. Keep deleted HII handle into pending list so - we can process them later. - - @param[in] HiiHandle HII handle instance. - @param[in] PendingList Pending list to keep HII handle which is recently updated. - - @retval EFI_SUCCESS HII handle is saved in pending list. - @retval EFI_INVALID_PARAMETER HiiHnalde is NULL or PendingList is NULL. - @retval EFI_OUT_OF_RESOURCES System is out of memory. - -**/ -EFI_STATUS -NotifyFormsetDeleted ( - IN EFI_HII_HANDLE *HiiHandle, - IN LIST_ENTRY *PendingList - ) -{ - REDFISH_PLATFORM_CONFIG_PENDING_LIST *TargetPendingList; - - if (HiiHandle == NULL || PendingList == NULL) { - return EFI_INVALID_PARAMETER; - } - - // - // Check and see if this HII handle is processed already. - // - TargetPendingList = GetPendingList (HiiHandle, PendingList); - if (TargetPendingList != NULL) { - TargetPendingList->IsDeleted = TRUE; - DEBUG_CODE ( - DEBUG ((DEBUG_INFO, "%a, HII handle: 0x%x is updated and deleted\n", __FUNCTION__, HiiHandle)); - ); - return EFI_SUCCESS; - } - - TargetPendingList= AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_PENDING_LIST)); - if (TargetPendingList == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - TargetPendingList->HiiHandle = HiiHandle; - TargetPendingList->IsDeleted = TRUE; - - InsertTailList (PendingList, &TargetPendingList->Link); - - DEBUG_CODE ( - DEBUG ((DEBUG_INFO, "%a, HII handle: 0x%x is deleted\n", __FUNCTION__, HiiHandle)); - ); - - return EFI_SUCCESS; -} - -/** - There are HII database update and we need to process them accordingly so that we - won't use stale data. This function will parse updated HII handle again in order - to get updated data-set. - - @param[in] FormsetList List to keep HII form-set. - @param[in] PendingList List to keep HII handle that is updated. - - @retval EFI_SUCCESS HII handle is saved in pending list. - @retval EFI_INVALID_PARAMETER FormsetList is NULL or PendingList is NULL. - -**/ -EFI_STATUS -ProcessPendingList ( - IN LIST_ENTRY *FormsetList, - IN LIST_ENTRY *PendingList - ) -{ - LIST_ENTRY *PendingListLink; - LIST_ENTRY *PendingListNextLink; - REDFISH_PLATFORM_CONFIG_PENDING_LIST *Target; - REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *FormsetPrivate; - EFI_STATUS Status; - - - if (FormsetList == NULL || PendingList == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (IsListEmpty (PendingList)) { - return EFI_SUCCESS; - } - - PendingListLink = GetFirstNode (PendingList); - while (!IsNull (PendingList, PendingListLink)) { - PendingListNextLink = GetNextNode (PendingList, PendingListLink); - Target = REDFISH_PLATFORM_CONFIG_PENDING_LIST_FROM_LINK (PendingListLink); - - if (Target->IsDeleted) { - // - // The HII resource on this HII handle is removed. Release the formset. - // - FormsetPrivate = GetFormsetPrivateByHiiHandle (Target->HiiHandle, FormsetList); - if (FormsetPrivate != NULL) { - DEBUG ((DEBUG_INFO, "%a, formset: %g is removed because driver release HII resource it already\n", __FUNCTION__, FormsetPrivate->Guid)); - RemoveEntryList (&FormsetPrivate->Link); - ReleaseFormset (FormsetPrivate); - FreePool (FormsetPrivate); - } else { - DEBUG ((DEBUG_WARN, "%a, formset on HII handle 0x%x was removed already\n", __FUNCTION__, Target->HiiHandle)); - } - } else { - // - // The HII resource on this HII handle is updated/removed. - // - FormsetPrivate = GetFormsetPrivateByHiiHandle (Target->HiiHandle, FormsetList); - if (FormsetPrivate != NULL) { - // - // HII formset already exist, release it and query again. - // - DEBUG ((DEBUG_INFO, "%a, formset: %g is updated. Release current formset\n", __FUNCTION__, &FormsetPrivate->Guid)); - RemoveEntryList (&FormsetPrivate->Link); - ReleaseFormset (FormsetPrivate); - FreePool (FormsetPrivate); - } - - Status = LoadFormsetList (Target->HiiHandle, FormsetList); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a, load formset from HII handle: 0x%x failed: %r\n", __FUNCTION__, Target->HiiHandle, Status)); - } - } - - // - // Detach it from list first. - // - RemoveEntryList (&Target->Link); - FreePool (Target); - - PendingListLink = PendingListNextLink; - } - - return EFI_SUCCESS; -} - -/** - Release all resource in statement list. - - @param[in] StatementList Statement list to be released. - - @retval EFI_SUCCESS All resource are released. - @retval EFI_INVALID_PARAMETER StatementList is NULL. - -**/ -EFI_STATUS -ReleaseStatementList ( - IN REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST *StatementList - ) -{ - REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF *StatementRef; - LIST_ENTRY *NextLink; - - if (StatementList == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (IsListEmpty (&StatementList->StatementList)) { - return EFI_SUCCESS; - } - - NextLink = GetFirstNode (&StatementList->StatementList); - while (!IsNull (&StatementList->StatementList, NextLink)) { - StatementRef = REDFISH_PLATFORM_CONFIG_STATEMENT_REF_FROM_LINK (NextLink); - NextLink = GetNextNode (&StatementList->StatementList, NextLink); - - RemoveEntryList (&StatementRef->Link); - FreePool (StatementRef); - } - - return EFI_SUCCESS; -} +/** @file + + The implementation of EDKII Redfidh Platform Config Protocol. + + (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include "RedfishPlatformConfigDxe.h" +#include "RedfishPlatformConfigImpl.h" + +extern REDFISH_PLATFORM_CONFIG_PRIVATE *mRedfishPlatformConfigPrivate; + +/** + Debug dump HII string + + @param[in] HiiHandle HII handle instance + @param[in] StringId HII string to dump + + @retval EFI_SUCCESS Dump HII string successfully + @retval Others Errors occur + +**/ +EFI_STATUS +DumpHiiString ( + IN EFI_HII_HANDLE HiiHandle, + IN EFI_STRING_ID StringId + ) +{ + EFI_STRING String; + + if (HiiHandle == NULL || StringId == 0) { + DEBUG ((DEBUG_INFO, "???")); + return EFI_INVALID_PARAMETER; + } + + String = HiiGetString (HiiHandle, StringId, NULL); + if (String == NULL) { + return EFI_NOT_FOUND; + } + + DEBUG ((DEBUG_INFO, "%s", String)); + FreePool (String); + + return EFI_SUCCESS; +} + +/** + Debug dump HII form-set data + + @param[in] FormsetPrivate HII form-set private instance. + + @retval EFI_SUCCESS Dump form-set successfully + @retval Others Errors occur + +**/ +EFI_STATUS +DumpFormset ( + IN REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *FormsetPrivate + ) +{ + LIST_ENTRY *HiiFormLink; + LIST_ENTRY *HiiNextFormLink; + REDFISH_PLATFORM_CONFIG_FORM_PRIVATE *HiiFormPrivate; + LIST_ENTRY *HiiStatementLink; + LIST_ENTRY *HiiNextStatementLink; + REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *HiiStatementPrivate; + UINTN Index; + + if (FormsetPrivate == NULL) { + return EFI_INVALID_PARAMETER; + } + + Index = 0; + HiiFormLink = GetFirstNode (&FormsetPrivate->HiiFormList); + while (!IsNull (&FormsetPrivate->HiiFormList, HiiFormLink)) { + HiiFormPrivate = REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK (HiiFormLink); + HiiNextFormLink = GetNextNode (&FormsetPrivate->HiiFormList, HiiFormLink); + + DEBUG ((DEBUG_INFO, " [%d] form: %d title: ", ++Index, HiiFormPrivate->Id)); + DumpHiiString (FormsetPrivate->HiiHandle, HiiFormPrivate->Title); + DEBUG ((DEBUG_INFO, "\n")); + + HiiStatementLink = GetFirstNode (&HiiFormPrivate->StatementList); + while (!IsNull (&HiiFormPrivate->StatementList, HiiStatementLink)) { + HiiStatementPrivate = REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK (HiiStatementLink); + HiiNextStatementLink = GetNextNode (&HiiFormPrivate->StatementList, HiiStatementLink); + + DEBUG ((DEBUG_INFO, " QID: 0x%x Prompt: ", HiiStatementPrivate->QuestionId)); + DumpHiiString (FormsetPrivate->HiiHandle, HiiStatementPrivate->Description); + DEBUG ((DEBUG_INFO, "\n")); + + HiiStatementLink = HiiNextStatementLink; + } + + HiiFormLink = HiiNextFormLink; + } + + return EFI_SUCCESS; +} + +/** + Debug dump HII form-set list + + @param[in] FormsetList Form-set list instance + + @retval EFI_SUCCESS Dump list successfully + @retval Others Errors occur + +**/ +EFI_STATUS +DumpFormsetList ( + IN LIST_ENTRY *FormsetList + ) +{ + LIST_ENTRY *HiiFormsetLink; + LIST_ENTRY *HiiFormsetNextLink; + REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *HiiFormsetPrivate; + UINTN Index; + + if (FormsetList == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (IsListEmpty (FormsetList)) { + DEBUG ((DEBUG_INFO, "%a, Empty formset list\n", __FUNCTION__)); + return EFI_SUCCESS; + } + + Index = 0; + HiiFormsetLink = GetFirstNode (FormsetList); + while (!IsNull (FormsetList, HiiFormsetLink)) { + HiiFormsetNextLink = GetNextNode (FormsetList, HiiFormsetLink); + HiiFormsetPrivate = REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink); + + DEBUG ((DEBUG_INFO, "[%d] HII Handle: 0x%x formset: %g at %s\n", ++Index, HiiFormsetPrivate->HiiHandle, &HiiFormsetPrivate->Guid, HiiFormsetPrivate->DevicePathStr)); + DumpFormset (HiiFormsetPrivate); + + HiiFormsetLink = HiiFormsetNextLink; + } + + return EFI_SUCCESS; +} + +/** + Retrieves a string from a string package in a English language. The + returned string is allocated using AllocatePool(). The caller is responsible + for freeing the allocated buffer using FreePool(). + + If HiiHandle is NULL, then ASSERT(). + If StringId is 0, then ASSET. + + @param[in] HiiStringProtocol EFI_HII_STRING_PROTOCOL instance. + @param[in] HiiHandle A handle that was previously registered in the HII Database. + @param[in] StringId The identifier of the string to retrieved from the string + package associated with HiiHandle. + + @retval NULL The string specified by StringId is not present in the string package. + @retval Other The string was returned. + +**/ +EFI_STRING +HiiGetRedfishString ( + IN EFI_HII_HANDLE HiiHandle, + IN CHAR8 *Language, + IN EFI_STRING_ID StringId + ) +{ + EFI_STATUS Status; + UINTN StringSize; + CHAR16 TempString; + EFI_STRING String; + + if (mRedfishPlatformConfigPrivate->HiiString == NULL || HiiHandle == NULL || StringId == 0 || IS_EMPTY_STRING (Language)) { + ASSERT (FALSE); + return NULL; + } + + // + // Retrieve the size of the string in the string package for the BestLanguage + // + StringSize = 0; + Status = mRedfishPlatformConfigPrivate->HiiString->GetString ( + mRedfishPlatformConfigPrivate->HiiString, + Language, + HiiHandle, + StringId, + &TempString, + &StringSize, + NULL + ); + // + // If GetString() returns EFI_SUCCESS for a zero size, + // then there are no supported languages registered for HiiHandle. If GetString() + // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present + // in the HII Database + // + if (Status != EFI_BUFFER_TOO_SMALL) { + return NULL; + } + + // + // Allocate a buffer for the return string + // + String = AllocateZeroPool (StringSize); + if (String == NULL) { + return NULL; + } + + // + // Retrieve the string from the string package + // + Status = mRedfishPlatformConfigPrivate->HiiString->GetString ( + mRedfishPlatformConfigPrivate->HiiString, + Language, + HiiHandle, + StringId, + String, + &StringSize, + NULL + ); + if (EFI_ERROR (Status)) { + // + // Free the buffer and return NULL if the supported languages can not be retrieved. + // + FreePool (String); + String = NULL; + } + + // + // Return the Null-terminated Unicode string + // + return String; +} + +/** + Retrieves a string from a string package in a English language. The + returned string is allocated using AllocatePool(). The caller is responsible + for freeing the allocated buffer using FreePool(). + + If HiiHandle is NULL, then ASSERT(). + If StringId is 0, then ASSET. + + @param[in] HiiStringProtocol EFI_HII_STRING_PROTOCOL instance. + @param[in] HiiHandle A handle that was previously registered in the HII Database. + @param[in] StringId The identifier of the string to retrieved from the string + package associated with HiiHandle. + + @retval NULL The string specified by StringId is not present in the string package. + @retval Other The string was returned. + +**/ +CHAR8 * +HiiGetRedfishAsciiString ( + IN EFI_HII_HANDLE HiiHandle, + IN CHAR8 *Language, + IN EFI_STRING_ID StringId + ) +{ + EFI_STRING HiiString; + UINTN StringSize; + CHAR8 *AsciiString; + + HiiString = HiiGetRedfishString (HiiHandle, Language, StringId); + if (HiiString == NULL) { + DEBUG ((DEBUG_ERROR, "%a, Can not find string ID: 0x%x with %a\n", __FUNCTION__, StringId, Language)); + return NULL; + } + + StringSize = (StrLen (HiiString) + 1) * sizeof (CHAR8); + AsciiString = AllocatePool (StringSize); + if (AsciiString == NULL) { + return NULL; + } + + UnicodeStrToAsciiStrS (HiiString, AsciiString, StringSize); + + FreePool (HiiString); + return AsciiString; +} + +/** + Get string from HII database in English language. + + @param[in] HiiHandle A handle that was previously registered in the HII Database. + @param[in] StringId The identifier of the string to retrieved from the string + package associated with HiiHandle. + + @retval NULL The string specified by StringId is not present in the string package. + @retval Other The string was returned. + +**/ +EFI_STRING +HiiGetEnglishString ( + IN EFI_HII_HANDLE HiiHandle, + IN EFI_STRING_ID StringId + ) +{ + return HiiGetRedfishString (HiiHandle, ENGLISH_LANGUAGE_CODE, StringId); +} + +/** + Check and see if this is supported schema or not. + + @param[in] SupportedSchema The list of supported schema. + @param[in] Schema Schema string to be checked. + + @retval BOOLEAN TRUE if this is supported schema. FALSE otherwise. + +**/ +BOOLEAN +CheckSupportedSchema ( + IN REDFISH_PLATFORM_CONFIG_SCHEMA *SupportedSchema, + IN CHAR8 *Schema + ) +{ + UINTN Index; + + if (SupportedSchema == NULL || IS_EMPTY_STRING (Schema)) { + return FALSE; + } + + if (SupportedSchema->Count == 0) { + return FALSE; + } + + for (Index = 0; Index < SupportedSchema->Count; Index++) { + if (AsciiStrCmp (SupportedSchema->SchemaList[Index], Schema) == 0) { + return TRUE; + } + } + + return FALSE; +} + +/** + Get the list of supported schema from the given HII handle. + + @param[in] HiiHandle HII handle instance. + @param[out] SupportedSchema Supported schema on this HII handle. + + @retval EFI_SUCCESS Schema list is returned. + @retval EFI_INVALID_PARAMETER HiiHandle is NULL or SupportedSchema is NULL. + @retval EFI_NOT_FOUND No supported schema found. + @retval EFI_OUT_OF_RESOURCES System is out of memory. + +**/ +EFI_STATUS +GetSupportedSchema ( + IN EFI_HII_HANDLE HiiHandle, + OUT REDFISH_PLATFORM_CONFIG_SCHEMA *SupportedSchema + ) +{ + CHAR8 *SupportedLanguages; + UINTN Index; + UINTN LangIndex; + UINTN Count; + UINTN StrSize; + UINTN ListIndex; + + if (HiiHandle == NULL || SupportedSchema == NULL) { + return EFI_INVALID_PARAMETER; + } + + SupportedSchema->Count = 0; + + SupportedLanguages = HiiGetSupportedLanguages (HiiHandle); + if (SupportedLanguages == NULL) { + return EFI_NOT_FOUND; + } + + Index = 0; + LangIndex = 0; + Count = 0; + while (TRUE) { + if (SupportedLanguages[Index] == ';' || SupportedLanguages[Index] == '\0') { + if (AsciiStrnCmp (&SupportedLanguages[LangIndex], X_UEFI_SCHEMA_PREFIX, AsciiStrLen (X_UEFI_SCHEMA_PREFIX)) == 0) { + ++Count; + } + LangIndex = Index + 1; + } + + if (SupportedLanguages[Index] == '\0') { + break; + } + + ++Index; + } + + if (Count == 0) { + return EFI_NOT_FOUND; + } + + SupportedSchema->Count = Count; + SupportedSchema->SchemaList = AllocatePool (sizeof (CHAR8 *) * Count); + if (SupportedSchema->SchemaList == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Index = 0; + LangIndex = 0; + ListIndex = 0; + while (TRUE) { + + if (SupportedLanguages[Index] == ';' || SupportedLanguages[Index] == '\0') { + if (AsciiStrnCmp (&SupportedLanguages[LangIndex], X_UEFI_SCHEMA_PREFIX, AsciiStrLen (X_UEFI_SCHEMA_PREFIX)) == 0) { + StrSize = Index - LangIndex; + SupportedSchema->SchemaList[ListIndex] = AllocateCopyPool ((StrSize + 1), &SupportedLanguages[LangIndex]); + SupportedSchema->SchemaList[ListIndex][StrSize] = '\0'; + ++ListIndex; + } + + LangIndex = Index + 1; + } + + if (SupportedLanguages[Index] == '\0') { + break; + } + + ++Index; + } + + return EFI_SUCCESS; +} + +/** + Search and find statement private instance by given regular expression patthern + which describes the Configure Language. + + @param[in] RegularExpressionProtocol Regular express protocol. + @param[in] FormsetList Form-set list to search. + @param[in] Schema Schema to be matched. + @param[in] Pattern Regular expression pattern. + @param[out] StatementList Statement list that match above pattern. + + @retval EFI_SUCCESS Statement list is returned. + @retval EFI_INVALID_PARAMETER Input parameter is NULL. + @retval EFI_NOT_READY Regular express protocol is NULL. + @retval EFI_NOT_FOUND No statement is found. + @retval EFI_OUT_OF_RESOURCES System is out of memory. + +**/ +EFI_STATUS +GetStatementPrivateByConfigureLangRegex ( + IN EFI_REGULAR_EXPRESSION_PROTOCOL *RegularExpressionProtocol, + IN LIST_ENTRY *FormsetList, + IN CHAR8 *Schema, + IN EFI_STRING Pattern, + OUT REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST *StatementList + ) +{ + LIST_ENTRY *HiiFormsetLink; + LIST_ENTRY *HiiFormsetNextLink; + REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *HiiFormsetPrivate; + LIST_ENTRY *HiiFormLink; + LIST_ENTRY *HiiNextFormLink; + REDFISH_PLATFORM_CONFIG_FORM_PRIVATE *HiiFormPrivate; + LIST_ENTRY *HiiStatementLink; + LIST_ENTRY *HiiNextStatementLink; + REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *HiiStatementPrivate; + EFI_STRING TmpString; + UINTN CaptureCount; + BOOLEAN IsMatch; + EFI_STATUS Status; + REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF *StatementRef; + + if (FormsetList == NULL || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Pattern) || StatementList == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (RegularExpressionProtocol == NULL) { + return EFI_NOT_READY; + } + + StatementList->Count = 0; + InitializeListHead (&StatementList->StatementList); + + if (IsListEmpty (FormsetList)) { + return EFI_NOT_FOUND; + } + + HiiFormsetLink = GetFirstNode (FormsetList); + while (!IsNull (FormsetList, HiiFormsetLink)) { + HiiFormsetNextLink = GetNextNode (FormsetList, HiiFormsetLink); + HiiFormsetPrivate = REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink); + + // + // Performance check. + // If there is no desired Redfish schema found, skip this formset. + // + if (!CheckSupportedSchema (&HiiFormsetPrivate->SupportedSchema, Schema)) { + HiiFormsetLink = HiiFormsetNextLink; + continue; + } + + HiiFormLink = GetFirstNode (&HiiFormsetPrivate->HiiFormList); + while (!IsNull (&HiiFormsetPrivate->HiiFormList, HiiFormLink)) { + HiiNextFormLink = GetNextNode (&HiiFormsetPrivate->HiiFormList, HiiFormLink); + HiiFormPrivate = REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK (HiiFormLink); + + HiiStatementLink =GetFirstNode (&HiiFormPrivate->StatementList); + while (!IsNull (&HiiFormPrivate->StatementList, HiiStatementLink)) { + HiiNextStatementLink = GetNextNode (&HiiFormPrivate->StatementList, HiiStatementLink); + HiiStatementPrivate = REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK (HiiStatementLink); + + if (HiiStatementPrivate->Description != 0) { + TmpString = HiiGetRedfishString (HiiFormsetPrivate->HiiHandle, Schema, HiiStatementPrivate->Description); + if (TmpString != NULL) { + Status = RegularExpressionProtocol->MatchString ( + RegularExpressionProtocol, + TmpString, + Pattern, + &gEfiRegexSyntaxTypePerlGuid, + &IsMatch, + NULL, + &CaptureCount + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, MatchString \"%s\" failed: %r\n", __FUNCTION__, Pattern, Status)); + ASSERT (FALSE); + return Status; + } + + // + // Found + // + if (IsMatch) { + StatementRef = AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF)); + if (StatementRef == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + StatementRef->Statement = HiiStatementPrivate; + InsertTailList (&StatementList->StatementList, &StatementRef->Link); + ++StatementList->Count; + } + + FreePool (TmpString); + } + } + + HiiStatementLink = HiiNextStatementLink; + } + + HiiFormLink = HiiNextFormLink; + } + + HiiFormsetLink = HiiFormsetNextLink; + } + + return EFI_SUCCESS; +} + +/** + Get statement private instance by the given configure language. + + @param[in] FormsetList Form-set list to search. + @param[in] Schema Schema to be matched. + @param[in] ConfigureLang Configure language. + + @retval REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE * Pointer to statement private instance. + +**/ +REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE * +GetStatementPrivateByConfigureLang ( + IN LIST_ENTRY *FormsetList, + IN CHAR8 *Schema, + IN EFI_STRING ConfigureLang + ) +{ + LIST_ENTRY *HiiFormsetLink; + LIST_ENTRY *HiiFormsetNextLink; + REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *HiiFormsetPrivate; + LIST_ENTRY *HiiFormLink; + LIST_ENTRY *HiiNextFormLink; + REDFISH_PLATFORM_CONFIG_FORM_PRIVATE *HiiFormPrivate; + LIST_ENTRY *HiiStatementLink; + LIST_ENTRY *HiiNextStatementLink; + REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *HiiStatementPrivate; + EFI_STRING TmpString; + + if (FormsetList == NULL || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (ConfigureLang)) { + return NULL; + } + + if (IsListEmpty (FormsetList)) { + return NULL; + } + + HiiFormsetLink = GetFirstNode (FormsetList); + while (!IsNull (FormsetList, HiiFormsetLink)) { + HiiFormsetNextLink = GetNextNode (FormsetList, HiiFormsetLink); + HiiFormsetPrivate = REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink); + + // + // Performance check. + // If there is no desired Redfish schema found, skip this formset. + // + if (!CheckSupportedSchema (&HiiFormsetPrivate->SupportedSchema, Schema)) { + HiiFormsetLink = HiiFormsetNextLink; + continue; + } + + HiiFormLink = GetFirstNode (&HiiFormsetPrivate->HiiFormList); + while (!IsNull (&HiiFormsetPrivate->HiiFormList, HiiFormLink)) { + HiiNextFormLink = GetNextNode (&HiiFormsetPrivate->HiiFormList, HiiFormLink); + HiiFormPrivate = REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK (HiiFormLink); + + HiiStatementLink =GetFirstNode (&HiiFormPrivate->StatementList); + while (!IsNull (&HiiFormPrivate->StatementList, HiiStatementLink)) { + HiiNextStatementLink = GetNextNode (&HiiFormPrivate->StatementList, HiiStatementLink); + HiiStatementPrivate = REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK (HiiStatementLink); + + DEBUG_CODE ( + STATIC UINTN Index = 0; + DEBUG ((DEBUG_INFO, "%a, [%d] search %s in QID: 0x%x form: 0x%x formset: %g\n", __FUNCTION__, ++Index, ConfigureLang, HiiStatementPrivate->QuestionId, HiiFormPrivate->Id, &HiiFormsetPrivate->Guid)); + ); + + if (HiiStatementPrivate->Description != 0) { + TmpString = HiiGetRedfishString (HiiFormsetPrivate->HiiHandle, Schema, HiiStatementPrivate->Description); + if (TmpString != NULL) { + if (StrCmp (TmpString, ConfigureLang) == 0) { + FreePool (TmpString); + return HiiStatementPrivate; + } + + FreePool (TmpString); + } + } + + HiiStatementLink = HiiNextStatementLink; + } + + HiiFormLink = HiiNextFormLink; + } + + HiiFormsetLink = HiiFormsetNextLink; + } + + return NULL; +} + +/** + Get form-set private instance by the given HII handle. + + @param[in] HiiHandle HII handle instance. + @param[in] FormsetList Form-set list to search. + + @retval REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE * Pointer to form-set private instance. + +**/ +REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE * +GetFormsetPrivateByHiiHandle ( + IN EFI_HII_HANDLE HiiHandle, + IN LIST_ENTRY *FormsetList + ) +{ + LIST_ENTRY *HiiFormsetLink; + LIST_ENTRY *HiiFormsetNextLink; + REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *HiiFormsetPrivate; + + if (HiiHandle == NULL || FormsetList == NULL) { + return NULL; + } + + if (IsListEmpty (FormsetList)) { + return NULL; + } + + HiiFormsetLink = GetFirstNode (FormsetList); + while (!IsNull (FormsetList, HiiFormsetLink)) { + HiiFormsetNextLink = GetNextNode (FormsetList, HiiFormsetLink); + HiiFormsetPrivate = REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink); + + if (HiiFormsetPrivate->HiiHandle == HiiHandle) { + return HiiFormsetPrivate; + } + + HiiFormsetLink = HiiFormsetNextLink; + } + + return NULL; +} + +/** + Release formset and all the forms and statements that belong to this formset. + + @param[in] FormsetPrivate Pointer to HP_HII_FORM_SET_PRIVATE + + @retval EFI_STATUS + +**/ +EFI_STATUS +ReleaseFormset ( + IN REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *FormsetPrivate + ) +{ + LIST_ENTRY *HiiFormLink; + LIST_ENTRY *HiiNextFormLink; + REDFISH_PLATFORM_CONFIG_FORM_PRIVATE *HiiFormPrivate; + LIST_ENTRY *HiiStatementLink; + LIST_ENTRY *HiiNextStatementLink; + REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *HiiStatementPrivate; + UINTN Index; + + if (FormsetPrivate == NULL) { + return EFI_INVALID_PARAMETER; + } + + HiiFormLink = GetFirstNode (&FormsetPrivate->HiiFormList); + while (!IsNull (&FormsetPrivate->HiiFormList, HiiFormLink)) { + HiiFormPrivate = REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK (HiiFormLink); + HiiNextFormLink = GetNextNode (&FormsetPrivate->HiiFormList, HiiFormLink); + + HiiStatementLink = GetFirstNode (&HiiFormPrivate->StatementList); + while (!IsNull (&HiiFormPrivate->StatementList, HiiStatementLink)) { + HiiStatementPrivate = REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK (HiiStatementLink); + HiiNextStatementLink = GetNextNode (&HiiFormPrivate->StatementList, HiiStatementLink); + + // + // HiiStatementPrivate->HiiStatement will be released in DestroyFormSet(). + // + + if (HiiStatementPrivate->DesStringCache != NULL) { + FreePool (HiiStatementPrivate->DesStringCache); + HiiStatementPrivate->DesStringCache = NULL; + } + + RemoveEntryList (&HiiStatementPrivate->Link); + FreePool (HiiStatementPrivate); + HiiStatementLink = HiiNextStatementLink; + } + + // + // HiiStatementPrivate->HiiForm will be released in DestroyFormSet(). + // + + RemoveEntryList (&HiiFormPrivate->Link); + FreePool (HiiFormPrivate); + HiiFormLink = HiiNextFormLink; + } + + if (FormsetPrivate->HiiFormSet != NULL) { + DestroyFormSet (FormsetPrivate->HiiFormSet); + FormsetPrivate->HiiFormSet = NULL; + } + + if (FormsetPrivate->DevicePathStr != NULL) { + FreePool(FormsetPrivate->DevicePathStr); + } + + // + // Release schema list + // + if (FormsetPrivate->SupportedSchema.SchemaList != NULL) { + for (Index = 0; Index < FormsetPrivate->SupportedSchema.Count; Index++) { + FreePool (FormsetPrivate->SupportedSchema.SchemaList[Index]); + } + + FreePool (FormsetPrivate->SupportedSchema.SchemaList); + FormsetPrivate->SupportedSchema.SchemaList = NULL; + FormsetPrivate->SupportedSchema.Count = 0; + } + + return EFI_SUCCESS; +} + +/** + Create new form-set instance. + + @retval REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE * Pointer to newly created form-set private instance. + +**/ +REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE * +NewFormsetPrivate ( + VOID + ) +{ + REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *NewFormsetPrivate; + + NewFormsetPrivate = AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE)); + if (NewFormsetPrivate == NULL) { + return NULL; + } + + // + // Initial newly created formset private data. + // + InitializeListHead (&NewFormsetPrivate->HiiFormList); + + return NewFormsetPrivate; +} + +/** + Load the HII formset from the given HII handle. + + @param[in] HiiHandle Target HII handle to load. + @param[out] FormsetPrivate The formset private data. + + @retval EFI_STATUS + +**/ +EFI_STATUS +LoadFormset ( + IN EFI_HII_HANDLE HiiHandle, + OUT REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *FormsetPrivate + ) +{ + EFI_STATUS Status; + HII_FORMSET *HiiFormSet; + HII_FORM *HiiForm; + LIST_ENTRY *HiiFormLink; + REDFISH_PLATFORM_CONFIG_FORM_PRIVATE *HiiFormPrivate; + HII_STATEMENT *HiiStatement; + LIST_ENTRY *HiiStatementLink; + REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *HiiStatementPrivate; + EFI_GUID ZeroGuid; + + if (HiiHandle == NULL || FormsetPrivate == NULL) { + return EFI_INVALID_PARAMETER; + } + + + HiiFormSet = AllocateZeroPool (sizeof (HII_FORMSET)); + if (HiiFormSet == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Find HII formset by the given HII handle. + // + ZeroMem (&ZeroGuid, sizeof (ZeroGuid)); + Status = CreateFormSetFromHiiHandle (HiiHandle, &ZeroGuid, HiiFormSet); + if (EFI_ERROR (Status) || IsListEmpty (&HiiFormSet->FormListHead)) { + Status = EFI_NOT_FOUND; + goto ErrorExit; + } + + // + // Initialize formset + // + InitializeFormSet (HiiFormSet); + + // + // Initialize formset private data. + // + FormsetPrivate->HiiFormSet = HiiFormSet; + FormsetPrivate->HiiHandle = HiiHandle; + CopyGuid (&FormsetPrivate->Guid, &HiiFormSet->Guid); + FormsetPrivate->DevicePathStr = ConvertDevicePathToText (HiiFormSet->DevicePath, FALSE, FALSE); + Status = GetSupportedSchema (FormsetPrivate->HiiHandle, &FormsetPrivate->SupportedSchema); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "%a, No schema from HII handle: 0x%x found: %r\n", __FUNCTION__, FormsetPrivate->HiiHandle, Status)); + } + + HiiFormLink = GetFirstNode (&HiiFormSet->FormListHead); + while (!IsNull (&HiiFormSet->FormListHead, HiiFormLink)) { + HiiForm = HII_FORM_FROM_LINK (HiiFormLink); + + HiiFormPrivate = AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_FORM_PRIVATE)); + if (HiiFormPrivate == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + + // + // Initialize form private data. + // + HiiFormPrivate->HiiForm = HiiForm; + HiiFormPrivate->Id = HiiForm->FormId; + HiiFormPrivate->Title = HiiForm->FormTitle; + HiiFormPrivate->ParentFormset = FormsetPrivate; + InitializeListHead (&HiiFormPrivate->StatementList); + + HiiStatementLink = GetFirstNode (&HiiForm->StatementListHead); + while (!IsNull (&HiiForm->StatementListHead, HiiStatementLink)) { + HiiStatement = HII_STATEMENT_FROM_LINK (HiiStatementLink); + + HiiStatementPrivate = AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE)); + if (HiiStatementPrivate == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + // + // Initialize statement private data. + // + HiiStatementPrivate->HiiStatement = HiiStatement; + HiiStatementPrivate->QuestionId = HiiStatement->QuestionId; + HiiStatementPrivate->Description = HiiStatement->Prompt; + HiiStatementPrivate->ParentForm = HiiFormPrivate; + + // + // Attach to statement list. + // + InsertTailList (&HiiFormPrivate->StatementList, &HiiStatementPrivate->Link); + HiiStatementLink = GetNextNode (&HiiForm->StatementListHead, HiiStatementLink); + } + // + // Attach to form list. + // + InsertTailList (&FormsetPrivate->HiiFormList, &HiiFormPrivate->Link); + HiiFormLink = GetNextNode (&HiiFormSet->FormListHead, HiiFormLink); + } + + return EFI_SUCCESS; + +ErrorExit: + + // + // Release HiiFormSet if HiiFormSet is not linked to FormsetPrivate yet. + // + if (HiiFormSet != NULL && FormsetPrivate->HiiFormSet != HiiFormSet) { + DestroyFormSet (HiiFormSet); + } + + // + // Release resource when error happens. + // + ReleaseFormset (FormsetPrivate); + + return Status; +} + +/** + Release formset list and all the forms that belong to this formset. + + @param[in] FormsetList Pointer to formst list that needs to be + released. + + @retval EFI_STATUS + +**/ +EFI_STATUS +LoadFormsetList ( + IN EFI_HII_HANDLE *HiiHandle, + OUT LIST_ENTRY *FormsetList + ) +{ + EFI_STATUS Status; + REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *FormsetPrivate; + + if (HiiHandle == NULL || FormsetList == NULL) { + return EFI_INVALID_PARAMETER; + } + + FormsetPrivate = GetFormsetPrivateByHiiHandle (HiiHandle, FormsetList); + if (FormsetPrivate != NULL) { + return EFI_ALREADY_STARTED; + } + + FormsetPrivate = NewFormsetPrivate (); + if (FormsetPrivate == NULL) { + DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__)); + return EFI_OUT_OF_RESOURCES; + } + + // + // Load formset on the given HII handle. + // + Status = LoadFormset (HiiHandle, FormsetPrivate); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, failed to load formset: %r\n", __FUNCTION__, Status)); + FreePool (FormsetPrivate); + return Status; + } + + // + // Attach to cache list. + // + InsertTailList (FormsetList, &FormsetPrivate->Link); + + DEBUG_CODE ( + DumpFormsetList (FormsetList); + ); + + return EFI_SUCCESS; +} + +/** + Release formset list and all the forms that belong to this formset. + + @param[in] FormsetList Pointer to formst list that needs to be + released. + + @retval EFI_STATUS + +**/ +EFI_STATUS +ReleaseFormsetList ( + IN LIST_ENTRY *FormsetList + ) +{ + LIST_ENTRY *HiiFormsetLink; + LIST_ENTRY *HiiFormsetNextLink; + REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *HiiFormsetPrivate; + + if (FormsetList == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (IsListEmpty (FormsetList)) { + return EFI_SUCCESS; + } + + HiiFormsetLink = GetFirstNode (FormsetList); + while (!IsNull (FormsetList, HiiFormsetLink)) { + HiiFormsetNextLink = GetNextNode (FormsetList, HiiFormsetLink); + HiiFormsetPrivate = REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink); + + // + // Detach from list. + // + RemoveEntryList (&HiiFormsetPrivate->Link); + ReleaseFormset (HiiFormsetPrivate); + FreePool (HiiFormsetPrivate); + HiiFormsetLink = HiiFormsetNextLink; + } + + return EFI_SUCCESS; +} + +/** + Get all pending list. + + @param[in] HiiHandle HII handle instance. + @param[in] PendingList Pending list to keep pending data. + + @retval REDFISH_PLATFORM_CONFIG_PENDING_LIST * Pointer to pending list data. + +**/ +REDFISH_PLATFORM_CONFIG_PENDING_LIST * +GetPendingList ( + IN EFI_HII_HANDLE *HiiHandle, + IN LIST_ENTRY *PendingList + ) +{ + LIST_ENTRY *PendingListLink; + REDFISH_PLATFORM_CONFIG_PENDING_LIST *Target; + + if (HiiHandle == NULL || PendingList == NULL) { + return NULL; + } + + if (IsListEmpty (PendingList)) { + return NULL; + } + + PendingListLink = GetFirstNode (PendingList); + while (!IsNull (PendingList, PendingListLink)) { + Target = REDFISH_PLATFORM_CONFIG_PENDING_LIST_FROM_LINK (PendingListLink); + + if (Target->HiiHandle == HiiHandle) { + return Target; + } + + PendingListLink = GetNextNode (PendingList, PendingListLink); + } + + return NULL; +} + +/** + When HII database is updated. Keep updated HII handle into pending list so + we can process them later. + + @param[in] HiiHandle HII handle instance. + @param[in] PendingList Pending list to keep HII handle which is recently updated. + + @retval EFI_SUCCESS HII handle is saved in pending list. + @retval EFI_INVALID_PARAMETER HiiHnalde is NULL or PendingList is NULL. + @retval EFI_OUT_OF_RESOURCES System is out of memory. + +**/ +EFI_STATUS +NotifyFormsetUpdate ( + IN EFI_HII_HANDLE *HiiHandle, + IN LIST_ENTRY *PendingList + ) +{ + REDFISH_PLATFORM_CONFIG_PENDING_LIST *TargetPendingList; + + if (HiiHandle == NULL || PendingList == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check and see if this HII handle is processed already. + // + TargetPendingList = GetPendingList (HiiHandle, PendingList); + if (TargetPendingList != NULL) { + TargetPendingList->IsDeleted = FALSE; + DEBUG_CODE ( + DEBUG ((DEBUG_INFO, "%a, HII handle: 0x%x is updated\n", __FUNCTION__, HiiHandle)); + ); + return EFI_SUCCESS; + } + + TargetPendingList= AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_PENDING_LIST)); + if (TargetPendingList == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + TargetPendingList->HiiHandle = HiiHandle; + TargetPendingList->IsDeleted = FALSE; + + InsertTailList (PendingList, &TargetPendingList->Link); + + DEBUG_CODE ( + DEBUG ((DEBUG_INFO, "%a, HII handle: 0x%x is created\n", __FUNCTION__, HiiHandle)); + ); + + return EFI_SUCCESS; +} + +/** + When HII database is updated and form-set is deleted. Keep deleted HII handle into pending list so + we can process them later. + + @param[in] HiiHandle HII handle instance. + @param[in] PendingList Pending list to keep HII handle which is recently updated. + + @retval EFI_SUCCESS HII handle is saved in pending list. + @retval EFI_INVALID_PARAMETER HiiHnalde is NULL or PendingList is NULL. + @retval EFI_OUT_OF_RESOURCES System is out of memory. + +**/ +EFI_STATUS +NotifyFormsetDeleted ( + IN EFI_HII_HANDLE *HiiHandle, + IN LIST_ENTRY *PendingList + ) +{ + REDFISH_PLATFORM_CONFIG_PENDING_LIST *TargetPendingList; + + if (HiiHandle == NULL || PendingList == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check and see if this HII handle is processed already. + // + TargetPendingList = GetPendingList (HiiHandle, PendingList); + if (TargetPendingList != NULL) { + TargetPendingList->IsDeleted = TRUE; + DEBUG_CODE ( + DEBUG ((DEBUG_INFO, "%a, HII handle: 0x%x is updated and deleted\n", __FUNCTION__, HiiHandle)); + ); + return EFI_SUCCESS; + } + + TargetPendingList= AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_PENDING_LIST)); + if (TargetPendingList == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + TargetPendingList->HiiHandle = HiiHandle; + TargetPendingList->IsDeleted = TRUE; + + InsertTailList (PendingList, &TargetPendingList->Link); + + DEBUG_CODE ( + DEBUG ((DEBUG_INFO, "%a, HII handle: 0x%x is deleted\n", __FUNCTION__, HiiHandle)); + ); + + return EFI_SUCCESS; +} + +/** + There are HII database update and we need to process them accordingly so that we + won't use stale data. This function will parse updated HII handle again in order + to get updated data-set. + + @param[in] FormsetList List to keep HII form-set. + @param[in] PendingList List to keep HII handle that is updated. + + @retval EFI_SUCCESS HII handle is saved in pending list. + @retval EFI_INVALID_PARAMETER FormsetList is NULL or PendingList is NULL. + +**/ +EFI_STATUS +ProcessPendingList ( + IN LIST_ENTRY *FormsetList, + IN LIST_ENTRY *PendingList + ) +{ + LIST_ENTRY *PendingListLink; + LIST_ENTRY *PendingListNextLink; + REDFISH_PLATFORM_CONFIG_PENDING_LIST *Target; + REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *FormsetPrivate; + EFI_STATUS Status; + + + if (FormsetList == NULL || PendingList == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (IsListEmpty (PendingList)) { + return EFI_SUCCESS; + } + + PendingListLink = GetFirstNode (PendingList); + while (!IsNull (PendingList, PendingListLink)) { + PendingListNextLink = GetNextNode (PendingList, PendingListLink); + Target = REDFISH_PLATFORM_CONFIG_PENDING_LIST_FROM_LINK (PendingListLink); + + if (Target->IsDeleted) { + // + // The HII resource on this HII handle is removed. Release the formset. + // + FormsetPrivate = GetFormsetPrivateByHiiHandle (Target->HiiHandle, FormsetList); + if (FormsetPrivate != NULL) { + DEBUG ((DEBUG_INFO, "%a, formset: %g is removed because driver release HII resource it already\n", __FUNCTION__, FormsetPrivate->Guid)); + RemoveEntryList (&FormsetPrivate->Link); + ReleaseFormset (FormsetPrivate); + FreePool (FormsetPrivate); + } else { + DEBUG ((DEBUG_WARN, "%a, formset on HII handle 0x%x was removed already\n", __FUNCTION__, Target->HiiHandle)); + } + } else { + // + // The HII resource on this HII handle is updated/removed. + // + FormsetPrivate = GetFormsetPrivateByHiiHandle (Target->HiiHandle, FormsetList); + if (FormsetPrivate != NULL) { + // + // HII formset already exist, release it and query again. + // + DEBUG ((DEBUG_INFO, "%a, formset: %g is updated. Release current formset\n", __FUNCTION__, &FormsetPrivate->Guid)); + RemoveEntryList (&FormsetPrivate->Link); + ReleaseFormset (FormsetPrivate); + FreePool (FormsetPrivate); + } + + Status = LoadFormsetList (Target->HiiHandle, FormsetList); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, load formset from HII handle: 0x%x failed: %r\n", __FUNCTION__, Target->HiiHandle, Status)); + } + } + + // + // Detach it from list first. + // + RemoveEntryList (&Target->Link); + FreePool (Target); + + PendingListLink = PendingListNextLink; + } + + return EFI_SUCCESS; +} + +/** + Release all resource in statement list. + + @param[in] StatementList Statement list to be released. + + @retval EFI_SUCCESS All resource are released. + @retval EFI_INVALID_PARAMETER StatementList is NULL. + +**/ +EFI_STATUS +ReleaseStatementList ( + IN REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST *StatementList + ) +{ + REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF *StatementRef; + LIST_ENTRY *NextLink; + + if (StatementList == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (IsListEmpty (&StatementList->StatementList)) { + return EFI_SUCCESS; + } + + NextLink = GetFirstNode (&StatementList->StatementList); + while (!IsNull (&StatementList->StatementList, NextLink)) { + StatementRef = REDFISH_PLATFORM_CONFIG_STATEMENT_REF_FROM_LINK (NextLink); + NextLink = GetNextNode (&StatementList->StatementList, NextLink); + + RemoveEntryList (&StatementRef->Link); + FreePool (StatementRef); + } + + return EFI_SUCCESS; +} diff --git a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.h b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.h index e0ba0fb2d3..be2f63df8d 100644 --- a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.h +++ b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.h @@ -1,274 +1,297 @@ -/** @file - This file defines the EDKII Redfish Platform Config Protocol interface. - - (C) Copyright 2021 Hewlett Packard Enterprise Development LP
- - SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#ifndef EDKII_REDFISH_PLATFORM_CONFIG_IMPL_H_ -#define EDKII_REDFISH_PLATFORM_CONFIG_IMPL_H_ - -#include - -// -// Libraries -// -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define REDFISH_PLATFORM_CONFIG_DELETE_EXPIRED_FORMSET 0x00 -#define IS_EMPTY_STRING(a) (a == NULL || a[0] == L'\0') -#define ENGLISH_LANGUAGE_CODE "en-US" -#define X_UEFI_SCHEMA_PREFIX "x-uefi-redfish-" - -// -// Definition of REDFISH_PLATFORM_CONFIG_PRIVATE. -// -typedef struct { - LIST_ENTRY Link; - EFI_HII_HANDLE HiiHandle; - BOOLEAN IsDeleted; -} REDFISH_PLATFORM_CONFIG_PENDING_LIST; - -#define REDFISH_PLATFORM_CONFIG_PENDING_LIST_FROM_LINK(a) BASE_CR (a, REDFISH_PLATFORM_CONFIG_PENDING_LIST, Link) - -typedef struct { - UINTN Count; // Number of schema in list - CHAR8 **SchemaList; // Schema list -} REDFISH_PLATFORM_CONFIG_SCHEMA; - -// -// Definition of REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE -// -typedef struct { - LIST_ENTRY Link; - HII_FORMSET *HiiFormSet; // Pointer to HII formset data. - EFI_GUID Guid; // Formset GUID. - EFI_HII_HANDLE HiiHandle; // Hii Handle of this formset. - LIST_ENTRY HiiFormList; // Form list that keep form data under this formset. - CHAR16 *DevicePathStr; // Device path of this formset. - REDFISH_PLATFORM_CONFIG_SCHEMA SupportedSchema; // Schema that is supported in this formset. -} REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE; - -#define REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK(a) BASE_CR (a, REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE, Link) - -// -// Definition of REDFISH_PLATFORM_CONFIG_FORM_PRIVATE -// -typedef struct { - LIST_ENTRY Link; - UINT16 Id; // Form ID. - EFI_STRING_ID Title; // String token of form title. - REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *ParentFormset; - HII_FORM *HiiForm; // Pointer to HII form data. - LIST_ENTRY StatementList; // Statement list that keep statement under this form. -} REDFISH_PLATFORM_CONFIG_FORM_PRIVATE; - -#define REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK(a) BASE_CR (a, REDFISH_PLATFORM_CONFIG_FORM_PRIVATE, Link) - -// -// Definition of REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE -// -typedef struct { - LIST_ENTRY Link; - REDFISH_PLATFORM_CONFIG_FORM_PRIVATE *ParentForm; - HII_STATEMENT *HiiStatement; // Pointer to HII statement data. - EFI_QUESTION_ID QuestionId; // Question ID of this statement. - EFI_STRING_ID Description; // String token of this question. - EFI_STRING DesStringCache; // The string cache for search function. -} REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE; - -#define REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK(a) BASE_CR (a, REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE, Link) - -// -// Definition of REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF -// -typedef struct { - LIST_ENTRY Link; - REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *Statement; -} REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF; - -#define REDFISH_PLATFORM_CONFIG_STATEMENT_REF_FROM_LINK(a) BASE_CR (a, REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF, Link) - -// -// Definition of REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST -// -typedef struct { - LIST_ENTRY StatementList; // List of REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF - UINTN Count; -} REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST; - -/** - Release formset list and all the forms that belong to this formset. - - @param[in] FormsetList Pointer to formst list that needs to be - released. - - @retval EFI_STATUS - -**/ -EFI_STATUS -ReleaseFormsetList ( - IN LIST_ENTRY *FormsetList - ); - -/** - Release formset list and all the forms that belong to this formset. - - @param[in] FormsetList Pointer to formst list that needs to be - released. - - @retval EFI_STATUS - -**/ -EFI_STATUS -LoadFormsetList ( - IN EFI_HII_HANDLE *HiiHandle, - OUT LIST_ENTRY *FormsetList - ); - -/** - When HII database is updated. Keep updated HII handle into pending list so - we can process them later. - - @param[in] HiiHandle HII handle instance. - @param[in] PendingList Pending list to keep HII handle which is recently updated. - - @retval EFI_SUCCESS HII handle is saved in pending list. - @retval EFI_INVALID_PARAMETER HiiHnalde is NULL or PendingList is NULL. - @retval EFI_OUT_OF_RESOURCES System is out of memory. - -**/ -EFI_STATUS -NotifyFormsetUpdate ( - IN EFI_HII_HANDLE *HiiHandle, - IN LIST_ENTRY *PendingList - ); - -/** - When HII database is updated and form-set is deleted. Keep deleted HII handle into pending list so - we can process them later. - - @param[in] HiiHandle HII handle instance. - @param[in] PendingList Pending list to keep HII handle which is recently updated. - - @retval EFI_SUCCESS HII handle is saved in pending list. - @retval EFI_INVALID_PARAMETER HiiHnalde is NULL or PendingList is NULL. - @retval EFI_OUT_OF_RESOURCES System is out of memory. - -**/ -EFI_STATUS -NotifyFormsetDeleted ( - IN EFI_HII_HANDLE *HiiHandle, - IN LIST_ENTRY *PendingList - ); - -/** - Get statement private instance by the given configure language. - - @param[in] FormsetList Form-set list to search. - @param[in] Schema Schema to be matched. - @param[in] ConfigureLang Configure language. - - @retval REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE * Pointer to statement private instance. - -**/ -REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE * -GetStatementPrivateByConfigureLang ( - IN LIST_ENTRY *FormsetList, - IN CHAR8 *Schema, - IN EFI_STRING ConfigureLang - ); - -/** - Search and find statement private instance by given regular expression patthern - which describes the Configure Language. - - @param[in] RegularExpressionProtocol Regular express protocol. - @param[in] FormsetList Form-set list to search. - @param[in] Schema Schema to be matched. - @param[in] Pattern Regular expression pattern. - @param[out] StatementList Statement list that match above pattern. - - @retval EFI_SUCCESS Statement list is returned. - @retval EFI_INVALID_PARAMETER Input parameter is NULL. - @retval EFI_NOT_READY Regular express protocol is NULL. - @retval EFI_NOT_FOUND No statement is found. - @retval EFI_OUT_OF_RESOURCES System is out of memory. - -**/ -EFI_STATUS -GetStatementPrivateByConfigureLangRegex ( - IN EFI_REGULAR_EXPRESSION_PROTOCOL *RegularExpressionProtocol, - IN LIST_ENTRY *FormsetList, - IN CHAR8 *Schema, - IN EFI_STRING Pattern, - OUT REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST *StatementList - ); - -/** - There are HII database update and we need to process them accordingly so that we - won't use stale data. This function will parse updated HII handle again in order - to get updated data-set. - - @param[in] FormsetList List to keep HII form-set. - @param[in] PendingList List to keep HII handle that is updated. - - @retval EFI_SUCCESS HII handle is saved in pending list. - @retval EFI_INVALID_PARAMETER FormsetList is NULL or PendingList is NULL. - -**/ -EFI_STATUS -ProcessPendingList ( - IN LIST_ENTRY *FormsetList, - IN LIST_ENTRY *PendingList - ); - -/** - Retrieves a string from a string package in a English language. The - returned string is allocated using AllocatePool(). The caller is responsible - for freeing the allocated buffer using FreePool(). - - If HiiHandle is NULL, then ASSERT(). - If StringId is 0, then ASSET. - - @param[in] HiiStringProtocol EFI_HII_STRING_PROTOCOL instance. - @param[in] HiiHandle A handle that was previously registered in the HII Database. - @param[in] StringId The identifier of the string to retrieved from the string - package associated with HiiHandle. - - @retval NULL The string specified by StringId is not present in the string package. - @retval Other The string was returned. - -**/ -EFI_STRING -HiiGetRedfishString ( - IN EFI_HII_HANDLE HiiHandle, - IN CHAR8 *Language, - IN EFI_STRING_ID StringId - ); - -/** - Release all resource in statement list. - - @param[in] StatementList Statement list to be released. - - @retval EFI_SUCCESS All resource are released. - @retval EFI_INVALID_PARAMETER StatementList is NULL. - -**/ -EFI_STATUS -ReleaseStatementList ( - IN REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST *StatementList - ); - -#endif +/** @file + This file defines the EDKII Redfish Platform Config Protocol interface. + + (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef EDKII_REDFISH_PLATFORM_CONFIG_IMPL_H_ +#define EDKII_REDFISH_PLATFORM_CONFIG_IMPL_H_ + +#include + +// +// Libraries +// +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IS_EMPTY_STRING(a) (a == NULL || a[0] == L'\0') +#define ENGLISH_LANGUAGE_CODE "en-US" +#define X_UEFI_SCHEMA_PREFIX "x-uefi-redfish-" + +// +// Definition of REDFISH_PLATFORM_CONFIG_PRIVATE. +// +typedef struct { + LIST_ENTRY Link; + EFI_HII_HANDLE HiiHandle; + BOOLEAN IsDeleted; +} REDFISH_PLATFORM_CONFIG_PENDING_LIST; + +#define REDFISH_PLATFORM_CONFIG_PENDING_LIST_FROM_LINK(a) BASE_CR (a, REDFISH_PLATFORM_CONFIG_PENDING_LIST, Link) + +typedef struct { + UINTN Count; // Number of schema in list + CHAR8 **SchemaList; // Schema list +} REDFISH_PLATFORM_CONFIG_SCHEMA; + +// +// Definition of REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE +// +typedef struct { + LIST_ENTRY Link; + HII_FORMSET *HiiFormSet; // Pointer to HII formset data. + EFI_GUID Guid; // Formset GUID. + EFI_HII_HANDLE HiiHandle; // Hii Handle of this formset. + LIST_ENTRY HiiFormList; // Form list that keep form data under this formset. + CHAR16 *DevicePathStr; // Device path of this formset. + REDFISH_PLATFORM_CONFIG_SCHEMA SupportedSchema; // Schema that is supported in this formset. +} REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE; + +#define REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK(a) BASE_CR (a, REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE, Link) + +// +// Definition of REDFISH_PLATFORM_CONFIG_FORM_PRIVATE +// +typedef struct { + LIST_ENTRY Link; + UINT16 Id; // Form ID. + EFI_STRING_ID Title; // String token of form title. + REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *ParentFormset; + HII_FORM *HiiForm; // Pointer to HII form data. + LIST_ENTRY StatementList; // Statement list that keep statement under this form. +} REDFISH_PLATFORM_CONFIG_FORM_PRIVATE; + +#define REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK(a) BASE_CR (a, REDFISH_PLATFORM_CONFIG_FORM_PRIVATE, Link) + +// +// Definition of REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE +// +typedef struct { + LIST_ENTRY Link; + REDFISH_PLATFORM_CONFIG_FORM_PRIVATE *ParentForm; + HII_STATEMENT *HiiStatement; // Pointer to HII statement data. + EFI_QUESTION_ID QuestionId; // Question ID of this statement. + EFI_STRING_ID Description; // String token of this question. + EFI_STRING DesStringCache; // The string cache for search function. +} REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE; + +#define REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK(a) BASE_CR (a, REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE, Link) + +// +// Definition of REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF +// +typedef struct { + LIST_ENTRY Link; + REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *Statement; +} REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF; + +#define REDFISH_PLATFORM_CONFIG_STATEMENT_REF_FROM_LINK(a) BASE_CR (a, REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF, Link) + +// +// Definition of REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST +// +typedef struct { + LIST_ENTRY StatementList; // List of REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF + UINTN Count; +} REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST; + +/** + Release formset list and all the forms that belong to this formset. + + @param[in] FormsetList Pointer to formst list that needs to be + released. + + @retval EFI_STATUS + +**/ +EFI_STATUS +ReleaseFormsetList ( + IN LIST_ENTRY *FormsetList + ); + +/** + Release formset list and all the forms that belong to this formset. + + @param[in] FormsetList Pointer to formst list that needs to be + released. + + @retval EFI_STATUS + +**/ +EFI_STATUS +LoadFormsetList ( + IN EFI_HII_HANDLE *HiiHandle, + OUT LIST_ENTRY *FormsetList + ); + +/** + When HII database is updated. Keep updated HII handle into pending list so + we can process them later. + + @param[in] HiiHandle HII handle instance. + @param[in] PendingList Pending list to keep HII handle which is recently updated. + + @retval EFI_SUCCESS HII handle is saved in pending list. + @retval EFI_INVALID_PARAMETER HiiHnalde is NULL or PendingList is NULL. + @retval EFI_OUT_OF_RESOURCES System is out of memory. + +**/ +EFI_STATUS +NotifyFormsetUpdate ( + IN EFI_HII_HANDLE *HiiHandle, + IN LIST_ENTRY *PendingList + ); + +/** + When HII database is updated and form-set is deleted. Keep deleted HII handle into pending list so + we can process them later. + + @param[in] HiiHandle HII handle instance. + @param[in] PendingList Pending list to keep HII handle which is recently updated. + + @retval EFI_SUCCESS HII handle is saved in pending list. + @retval EFI_INVALID_PARAMETER HiiHnalde is NULL or PendingList is NULL. + @retval EFI_OUT_OF_RESOURCES System is out of memory. + +**/ +EFI_STATUS +NotifyFormsetDeleted ( + IN EFI_HII_HANDLE *HiiHandle, + IN LIST_ENTRY *PendingList + ); + +/** + Get statement private instance by the given configure language. + + @param[in] FormsetList Form-set list to search. + @param[in] Schema Schema to be matched. + @param[in] ConfigureLang Configure language. + + @retval REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE * Pointer to statement private instance. + +**/ +REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE * +GetStatementPrivateByConfigureLang ( + IN LIST_ENTRY *FormsetList, + IN CHAR8 *Schema, + IN EFI_STRING ConfigureLang + ); + +/** + Search and find statement private instance by given regular expression patthern + which describes the Configure Language. + + @param[in] RegularExpressionProtocol Regular express protocol. + @param[in] FormsetList Form-set list to search. + @param[in] Schema Schema to be matched. + @param[in] Pattern Regular expression pattern. + @param[out] StatementList Statement list that match above pattern. + + @retval EFI_SUCCESS Statement list is returned. + @retval EFI_INVALID_PARAMETER Input parameter is NULL. + @retval EFI_NOT_READY Regular express protocol is NULL. + @retval EFI_NOT_FOUND No statement is found. + @retval EFI_OUT_OF_RESOURCES System is out of memory. + +**/ +EFI_STATUS +GetStatementPrivateByConfigureLangRegex ( + IN EFI_REGULAR_EXPRESSION_PROTOCOL *RegularExpressionProtocol, + IN LIST_ENTRY *FormsetList, + IN CHAR8 *Schema, + IN EFI_STRING Pattern, + OUT REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST *StatementList + ); + +/** + There are HII database update and we need to process them accordingly so that we + won't use stale data. This function will parse updated HII handle again in order + to get updated data-set. + + @param[in] FormsetList List to keep HII form-set. + @param[in] PendingList List to keep HII handle that is updated. + + @retval EFI_SUCCESS HII handle is saved in pending list. + @retval EFI_INVALID_PARAMETER FormsetList is NULL or PendingList is NULL. + +**/ +EFI_STATUS +ProcessPendingList ( + IN LIST_ENTRY *FormsetList, + IN LIST_ENTRY *PendingList + ); + +/** + Retrieves a string from a string package in a English language. The + returned string is allocated using AllocatePool(). The caller is responsible + for freeing the allocated buffer using FreePool(). + + If HiiHandle is NULL, then ASSERT(). + If StringId is 0, then ASSET. + + @param[in] HiiStringProtocol EFI_HII_STRING_PROTOCOL instance. + @param[in] HiiHandle A handle that was previously registered in the HII Database. + @param[in] StringId The identifier of the string to retrieved from the string + package associated with HiiHandle. + + @retval NULL The string specified by StringId is not present in the string package. + @retval Other The string was returned. + +**/ +EFI_STRING +HiiGetRedfishString ( + IN EFI_HII_HANDLE HiiHandle, + IN CHAR8 *Language, + IN EFI_STRING_ID StringId + ); + +/** + Retrieves a string from a string package in a English language. The + returned string is allocated using AllocatePool(). The caller is responsible + for freeing the allocated buffer using FreePool(). + + If HiiHandle is NULL, then ASSERT(). + If StringId is 0, then ASSET. + + @param[in] HiiStringProtocol EFI_HII_STRING_PROTOCOL instance. + @param[in] HiiHandle A handle that was previously registered in the HII Database. + @param[in] StringId The identifier of the string to retrieved from the string + package associated with HiiHandle. + + @retval NULL The string specified by StringId is not present in the string package. + @retval Other The string was returned. + +**/ +CHAR8 * +HiiGetRedfishAsciiString ( + IN EFI_HII_HANDLE HiiHandle, + IN CHAR8 *Language, + IN EFI_STRING_ID StringId + ); + +/** + Release all resource in statement list. + + @param[in] StatementList Statement list to be released. + + @retval EFI_SUCCESS All resource are released. + @retval EFI_INVALID_PARAMETER StatementList is NULL. + +**/ +EFI_STATUS +ReleaseStatementList ( + IN REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST *StatementList + ); + +#endif -- 2.32.0.windows.2