From nobody Sun Apr 28 17:11:20 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+82767+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+82767+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=hpe.com ARC-Seal: i=1; a=rsa-sha256; t=1635382870; cv=none; d=zohomail.com; s=zohoarc; b=U8DFcM9Hv7G7PZovoC21nR/AQDTzQjcPUYV06C0sUFU1DKZaSTGz7HvOQBy52CoGtofIkyssm77hYrUitZxiyBFikfoTNh0Y7kDZQfgoMjllJwmCPmXlRqJONlWHDUhYua43I7OC0rdJhD74h46T83fr2DIUtTneFocKv3etWlY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1635382870; h=Content-Transfer-Encoding:Cc:Date:From:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Sender:Subject:To; bh=BWJITztQLBhICLbrpwxESHPfQVq3LmEW5Y9Wzm8Z41Y=; b=K0ekrzMg2HJ6jtk7kuYSnllA7306NdC/L/mg8GwVLR09/N8ZEFZA7WRsSVBP5Ok9SZNjjdj+BGcMHOkBLE5okONTrITGydJ81F0YeyKJB96Ielh1n6bGBc1yx/d3Lpn5ebj1K0QBj5P3dFcGVx3Hc1TY9SbzJHIiS0dF4wi5fKY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+82767+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 163538287010622.758133403200077; Wed, 27 Oct 2021 18:01:10 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id Er0AYY1788612xDDB3XbEsbs; Wed, 27 Oct 2021 18:01:09 -0700 X-Received: from mx0a-002e3701.pphosted.com (mx0a-002e3701.pphosted.com [148.163.147.86]) by mx.groups.io with SMTP id smtpd.web09.5435.1635382861151665497 for ; Wed, 27 Oct 2021 18:01:09 -0700 X-Received: from pps.filterd (m0150241.ppops.net [127.0.0.1]) by mx0a-002e3701.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 19RNEFQ5019322; Thu, 28 Oct 2021 01:00:18 GMT X-Received: from g9t5008.houston.hpe.com (g9t5008.houston.hpe.com [15.241.48.72]) by mx0a-002e3701.pphosted.com with ESMTP id 3by52teb3q-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 28 Oct 2021 01:00:17 +0000 X-Received: from g9t2301.houston.hpecorp.net (g9t2301.houston.hpecorp.net [16.220.97.129]) by g9t5008.houston.hpe.com (Postfix) with ESMTP id 96DA070; Thu, 28 Oct 2021 01:00:16 +0000 (UTC) X-Received: from SAC2XFT1JT.asiapacific.hpqcorp.net (unknown [10.43.62.133]) by g9t2301.houston.hpecorp.net (Postfix) with ESMTP id 5DC694D; Thu, 28 Oct 2021 01:00:15 +0000 (UTC) From: "Abner Chang" To: devel@edk2.groups.io Cc: nickle.wang@hpe.com, Liming Gao Subject: [edk2-devel] [PATCH] edk2-staging/RedfishPkg: Implementation of EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL Date: Thu, 28 Oct 2021 09:00:13 +0800 Message-Id: <20211028010013.35964-1-abner.chang@hpe.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: 9DHbBPQXXbKt41pRTcyNbHJyrXk-m7aY X-Proofpoint-GUID: 9DHbBPQXXbKt41pRTcyNbHJyrXk-m7aY X-HPE-SCL: -1 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,abner.chang@hpe.com X-Gm-Message-State: JjoRz0TR4ZaQzo75foVeCZ14x1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1635382869; bh=ktqpgNoZk38kpv1Ed89HAsQReIGItXthm6erpQrIVKI=; h=Cc:Date:From:Reply-To:Subject:To; b=Fr/WzhvyLEMXm13f665LLWZu+tUBgIddC0LEaBo2Bh+2JcMXr9cNwbkUMC6/XY5jyzl UxXA5yXsnFaIp9Y5kxk/9CSuZbBEwviFvcX58l6+4BvdTtwu1Knrb5OoR6hhE/oTAXc1u Ij1DN6ReazvgQqXatpvLUDNQF7BnKdd+5Sc= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1635382871857100002 Content-Type: text/plain; charset="utf-8" This is the Implementation of EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL, which is the EDKII Redfish Platform Config driver instance that accesses EDK2 HII configuration format and storage. Signed-off-by: Nickle Wang Cc: Abner Chang Cc: Liming Gao --- .../RedfishPlatformConfigDxe.inf | 53 + .../RedfishPlatformConfigDxe.h | 64 + .../RedfishPlatformConfigImpl.h | 274 ++++ .../RedfishPlatformConfigDxe.c | 1304 +++++++++++++++++ .../RedfishPlatformConfigImpl.c | 1240 ++++++++++++++++ 5 files changed, 2935 insertions(+) create mode 100644 RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConf= igDxe.inf create mode 100644 RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConf= igDxe.h create mode 100644 RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConf= igImpl.h create mode 100644 RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConf= igDxe.c create mode 100644 RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConf= igImpl.c diff --git a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.i= nf b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.inf new file mode 100644 index 00000000000..16739bef7a3 --- /dev/null +++ b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.inf @@ -0,0 +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 =3D 0x00010005 + BASE_NAME =3D RedfishPlatformConfigDxe + FILE_GUID =3D BEAEFFE1-0633-41B5-913C-9389339C2927 + MODULE_TYPE =3D DXE_DRIVER + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D RedfishPlatformConfigDxeEntryPoint + UNLOAD_IMAGE =3D 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/RedfishPlatformConfigDxe.h= b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.h new file mode 100644 index 00000000000..99a613d229c --- /dev/null +++ b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.h @@ -0,0 +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 ev= ent. + VOID *Registration; // Protocol notification re= gistration. +} 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/RedfishPlatformConfigImpl.= h b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.h new file mode 100644 index 00000000000..e0ba0fb2d3d --- /dev/null +++ b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.h @@ -0,0 +1,274 @@ +/** @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 =3D=3D NULL ||= a[0] =3D=3D 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, RED= FISH_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 forms= et data. + EFI_GUID Guid; // Formset GUID. + EFI_HII_HANDLE HiiHandle; // Hii Handle of this f= ormset. + 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 suppo= rted 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 toke= n of form title. + REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *ParentFormset; + HII_FORM *HiiForm; // Pointer to = HII form data. + LIST_ENTRY StatementList; // Statement l= ist that keep statement under this form. +} REDFISH_PLATFORM_CONFIG_FORM_PRIVATE; + +#define REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK(a) BASE_CR (a, REDFISH_PLA= TFORM_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 cach= e for search function. +} REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE; + +#define REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK(a) BASE_CR (a, REDFIS= H_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, RE= DFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF, Link) + +// +// Definition of REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST +// +typedef struct { + LIST_ENTRY StatementList; // List of REDFISH_PLATFORM_CONFIG_STA= TEMENT_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 recentl= y 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 h= andle 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 recentl= y 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 stateme= nt 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 p= atthern + 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 *RegularExpressionPr= otocol, + 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 NU= LL. + +**/ +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 respon= sible + 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 st= ring 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 diff --git a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.c= b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.c new file mode 100644 index 00000000000..67818cccd24 --- /dev/null +++ b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.c @@ -0,0 +1,1304 @@ +/** @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 =3D 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 sec= ond value. + -1 is returned when second value is greater than f= irst value. + +**/ +UINTN +CompareHiiStatementValue ( + IN HII_STATEMENT_VALUE *Value1, + IN HII_STATEMENT_VALUE *Value2 + ) +{ + INTN Result; + UINT64 Data1; + UINT64 Data2; + + if (Value1 =3D=3D NULL || Value2 =3D=3D NULL) { + return 0xFF; + } + + switch (Value1->Type) { + case EFI_IFR_TYPE_NUM_SIZE_8: + Data1 =3D Value1->Value.u8; + break; + case EFI_IFR_TYPE_NUM_SIZE_16: + Data1 =3D Value1->Value.u16; + break; + case EFI_IFR_TYPE_NUM_SIZE_32: + Data1 =3D Value1->Value.u32; + break; + case EFI_IFR_TYPE_NUM_SIZE_64: + Data1 =3D Value1->Value.u64; + break; + case EFI_IFR_TYPE_BOOLEAN: + Data1 =3D (Value1->Value.b ? 1 : 0); + break; + default: + return 0xFF; + } + + switch (Value2->Type) { + case EFI_IFR_TYPE_NUM_SIZE_8: + Data2 =3D Value2->Value.u8; + break; + case EFI_IFR_TYPE_NUM_SIZE_16: + Data2 =3D Value2->Value.u16; + break; + case EFI_IFR_TYPE_NUM_SIZE_32: + Data2 =3D Value2->Value.u32; + break; + case EFI_IFR_TYPE_NUM_SIZE_64: + Data2 =3D Value2->Value.u64; + break; + case EFI_IFR_TYPE_BOOLEAN: + Data2 =3D (Value2->Value.b ? 1 : 0); + break; + default: + return 0xFF; + } + + Result =3D (Data1 =3D=3D 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 !=3D EFI_IFR_ONE_OF_OP) { + return 0; + } + + if (IsListEmpty (&Statement->HiiStatement->OptionListHead)) { + return 0; + } + + Link =3D GetFirstNode (&Statement->HiiStatement->OptionListHead); + while (!IsNull (&Statement->HiiStatement->OptionListHead, Link)) { + Option =3D HII_QUESTION_OPTION_FROM_LINK (Link); + + if (CompareHiiStatementValue (&Statement->HiiStatement->Value, &Option= ->Value) =3D=3D 0) { + return Option->Text; + } + + Link =3D 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 =3D=3D NULL || IS_EMPTY_STRING (HiiString) || Value =3D=3D= NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Statement->HiiStatement->Operand !=3D EFI_IFR_ONE_OF_OP) { + return EFI_UNSUPPORTED; + } + + if (IsListEmpty (&Statement->HiiStatement->OptionListHead)) { + return EFI_NOT_FOUND; + } + + Found =3D FALSE; + Link =3D GetFirstNode (&Statement->HiiStatement->OptionListHead); + while (!IsNull (&Statement->HiiStatement->OptionListHead, Link)) { + Option =3D HII_QUESTION_OPTION_FROM_LINK (Link); + + TmpString =3D HiiGetRedfishString (Statement->ParentForm->ParentFormse= t->HiiHandle, Schema, Option->Text); + if (TmpString !=3D NULL) { + if (StrCmp (TmpString, HiiString) =3D=3D 0) { + CopyMem (Value, &Option->Value, sizeof (HII_STATEMENT_VALUE)); + Found =3D TRUE; + } + FreePool (TmpString); + } + + if (Found) { + return EFI_SUCCESS; + } + + Link =3D 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 =3D=3D NULL || RedfishValue =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + switch (Value->Type) { + case EFI_IFR_TYPE_NUM_SIZE_8: + RedfishValue->Type =3D REDFISH_VALUE_TYPE_INTEGER; + RedfishValue->Value.Integer =3D (INT64)Value->Value.u8; + break; + case EFI_IFR_TYPE_NUM_SIZE_16: + RedfishValue->Type =3D REDFISH_VALUE_TYPE_INTEGER; + RedfishValue->Value.Integer =3D (INT64)Value->Value.u16; + break; + case EFI_IFR_TYPE_NUM_SIZE_32: + RedfishValue->Type =3D REDFISH_VALUE_TYPE_INTEGER; + RedfishValue->Value.Integer =3D (INT64)Value->Value.u32; + break; + case EFI_IFR_TYPE_NUM_SIZE_64: + RedfishValue->Type =3D REDFISH_VALUE_TYPE_INTEGER; + RedfishValue->Value.Integer =3D (INT64)Value->Value.u64; + break; + case EFI_IFR_TYPE_BOOLEAN: + RedfishValue->Type =3D REDFISH_VALUE_TYPE_BOOLEAN; + RedfishValue->Value.Boolean =3D Value->Value.b; + break; + default: + RedfishValue->Type =3D 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 =3D=3D NULL || RedfishValue =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + switch (RedfishValue->Type) { + case REDFISH_VALUE_TYPE_INTEGER: + Value->Type =3D EFI_IFR_TYPE_NUM_SIZE_64; + Value->Value.u64 =3D (UINT64)RedfishValue->Value.Integer; + break; + case REDFISH_VALUE_TYPE_BOOLEAN: + Value->Type =3D EFI_IFR_TYPE_BOOLEAN; + Value->Value.b =3D RedfishValue->Value.Boolean; + break; + default: + Value->Type =3D 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 =3D AsciiStrSize(CONFIGURE_LANGUAGE_PREFIX) + AsciiStrSize (Schema)= + AsciiStrSize (Version); + + FullName =3D AllocatePool (Size); + if (FullName =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "%a, out-of-resource\n", __FUNCTION__)); + return NULL; + } + + AsciiSPrint (FullName, Size, "%a%a.%a", CONFIGURE_LANGUAGE_PREFIX, Schem= a, 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 refe= rs 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 *RedfishPlatformConfig= Private, + 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 =3D=3D NULL || IS_EMPTY_STRING (Schema)= || IS_EMPTY_STRING (ConfigureLang) || Statement =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + *Statement =3D NULL; + + Status =3D ProcessPendingList (&RedfishPlatformConfigPrivate->FormsetLis= t, &RedfishPlatformConfigPrivate->PendingList); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, ProcessPendingList failure: %r\n", __FUNCTIO= N__, Status)); + return Status; + } + + TargetStatement =3D GetStatementPrivateByConfigureLang (&RedfishPlatform= ConfigPrivate->FormsetList, Schema, ConfigureLang); + if (TargetStatement =3D=3D 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 =3D 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 =3D=3D EFI_IFR_TYPE_UNDEFI= NED) { + return EFI_DEVICE_ERROR; + } + + // + // Return Value. + // + *Statement =3D TargetStatement; + + return EFI_SUCCESS; +} + +/** + Get Redfish value with the given Schema and Configure Language. + + @param[in] This Pointer to EDKII_REDFISH_PLATFORM_CONFI= G_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 confi= gure 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 =3D=3D NULL || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Ver= sion) || IS_EMPTY_STRING (ConfigureLang) || Value =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + RedfishPlatformConfigPrivate =3D REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_TH= IS (This); + Value->Type =3D REDFISH_VALUE_TYPE_UNKNOWN; + FullSchema =3D NULL; + HiiString =3D NULL; + + FullSchema =3D GetFullSchemaString (Schema, Version); + if (FullSchema =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status =3D RedfishPlatformConfigGetStatementCommon (RedfishPlatformConfi= gPrivate, FullSchema, ConfigureLang, &TargetStatement); + if (EFI_ERROR (Status)) { + goto RELEASE_RESOURCE; + } + + switch (TargetStatement->HiiStatement->Operand) { + case EFI_IFR_ONE_OF_OP: + StringId =3D HiiValueToOneOfOptionStringId (TargetStatement); + if (StringId =3D=3D 0) { + ASSERT (FALSE); + Status =3D EFI_DEVICE_ERROR; + goto RELEASE_RESOURCE; + } + + HiiString =3D HiiGetRedfishString (TargetStatement->ParentForm->Pare= ntFormset->HiiHandle, FullSchema, StringId); + if (HiiString =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "%a, Can not find string ID: 0x%x with %a\n",= __FUNCTION__, StringId, FullSchema)); + Status =3D EFI_NOT_FOUND; + goto RELEASE_RESOURCE; + } + + Size =3D StrLen (HiiString) + 1; + Value->Value.Buffer =3D AllocatePool (Size); + if (Value->Value.Buffer =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto RELEASE_RESOURCE; + } + + UnicodeStrToAsciiStrS (HiiString, Value->Value.Buffer, Size); + Value->Type =3D REDFISH_VALUE_TYPE_STRING; + + break; + case EFI_IFR_STRING_OP: + if (TargetStatement->HiiStatement->Value.Type !=3D EFI_IFR_TYPE_STRI= NG) { + ASSERT (FALSE); + Status =3D EFI_DEVICE_ERROR; + goto RELEASE_RESOURCE; + } + + Value->Type =3D REDFISH_VALUE_TYPE_STRING; + Value->Value.Buffer =3D AllocateCopyPool (StrSize ((CHAR16 *)TargetS= tatement->HiiStatement->Value.Buffer), TargetStatement->HiiStatement->Value= .Buffer); + if (Value->Value.Buffer =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto RELEASE_RESOURCE; + } + break; + case EFI_IFR_CHECKBOX_OP: + case EFI_IFR_NUMERIC_OP: + Status =3D HiiValueToRedfishNumeric (&TargetStatement->HiiStatement-= >Value, Value); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, failed to convert HII value to Redfish v= alue: %r\n", __FUNCTION__, Status)); + goto RELEASE_RESOURCE; + } + break; + default: + DEBUG ((DEBUG_ERROR, "%a, catch unsupported type: 0x%x! Please conta= ct with author if we need to support this type.\n", __FUNCTION__, TargetSta= tement->HiiStatement->Operand)); + ASSERT (FALSE); + Status =3D EFI_UNSUPPORTED; + goto RELEASE_RESOURCE; + } + +RELEASE_RESOURCE: + + if (FullSchema !=3D NULL) { + FreePool (FullSchema); + } + + if (HiiString !=3D 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 =3D=3D NULL || HiiForm =3D=3D NULL || HiiStatement =3D=3D= NULL || Value =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + Status =3D SetQuestionValue ( + HiiFormset, + HiiForm, + HiiStatement, + Value + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, failed to set question value: %r\n", __FUNCT= ION__, Status)); + return Status; + } + + Status =3D 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 refe= rs 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 =3D=3D NULL || IS_EMPTY_STRING (Schema)= || IS_EMPTY_STRING (ConfigureLang) || StatementValue =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + TempBuffer =3D NULL; + + Status =3D ProcessPendingList (&RedfishPlatformConfigPrivate->FormsetLis= t, &RedfishPlatformConfigPrivate->PendingList); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, ProcessPendingList failure: %r\n", __FUNCTIO= N__, Status)); + return Status; + } + + TargetStatement =3D GetStatementPrivateByConfigureLang (&RedfishPlatform= ConfigPrivate->FormsetList, Schema, ConfigureLang); + if (TargetStatement =3D=3D 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 !=3D 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 =3D=3D EFI_IFR_ONE_OF_OP &&= StatementValue->Type =3D=3D EFI_IFR_TYPE_STRING) { + TempBuffer =3D AllocatePool (StatementValue->BufferLen * sizeof (CHA= R16)); + if (TempBuffer =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + AsciiStrToUnicodeStrS (StatementValue->Buffer, TempBuffer, Statement= Value->BufferLen); + FreePool (StatementValue->Buffer); + StatementValue->Buffer =3D NULL; + StatementValue->BufferLen =3D 0; + + Status =3D HiiStringToOneOfOptionValue (TargetStatement, Schema, Tem= pBuffer, 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 =3D=3D EFI_IFR_NUMER= IC_OP && StatementValue->Type =3D=3D EFI_IFR_TYPE_NUM_SIZE_64) { + // + // Redfish only has numeric value type and it does not care about th= e value size. + // Do a patch here so we have proper value size applied. + // + StatementValue->Type =3D 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, Targe= tStatement->HiiStatement->Value.Type)); + ASSERT (FALSE); + } + } + + Status =3D 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", __FUNC= TION__, Status)); + return Status; + } + + return EFI_SUCCESS; +} + +/** + Set Redfish value with the given Schema and Configure Language. + + @param[in] This Pointer to EDKII_REDFISH_PLATFORM_CONFI= G_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 confi= gure 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 =3D=3D NULL || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Ver= sion) || IS_EMPTY_STRING (ConfigureLang)) { + return EFI_INVALID_PARAMETER; + } + + if (Value.Type =3D=3D REDFISH_VALUE_TYPE_UNKNOWN || Value.Type >=3D REDF= ISH_VALUE_TYPE_MAX) { + return EFI_INVALID_PARAMETER; + } + + RedfishPlatformConfigPrivate =3D REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_TH= IS (This); + FullSchema =3D NULL; + + FullSchema =3D GetFullSchemaString (Schema, Version); + if (FullSchema =3D=3D 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 =3D RedfishNumericToHiiValue (&Value, &NewValue); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, failed to convert Redfish value to Hii v= alue: %r\n", __FUNCTION__, Status)); + goto RELEASE_RESOURCE; + } + break; + case REDFISH_VALUE_TYPE_STRING: + NewValue.Type =3D EFI_IFR_TYPE_STRING; + NewValue.BufferLen =3D (UINT16)AsciiStrSize (Value.Value.Buffer); + NewValue.Buffer =3D AllocateCopyPool (NewValue.BufferLen, Value.Valu= e.Buffer); + if (NewValue.Buffer =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto RELEASE_RESOURCE; + } + break; + default: + ASSERT (FALSE); + break; + } + + Status =3D RedfishPlatformConfigSetStatementCommon (RedfishPlatformConfi= gPrivate, FullSchema, ConfigureLang, &NewValue); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, failed to set value to statement: %r\n", __F= UNCTION__, Status)); + } + +RELEASE_RESOURCE: + + if (FullSchema !=3D NULL) { + FreePool (FullSchema); + } + + return Status; +} + +/** + Get the list of Configure Language from platform configuration by the gi= ven Schema and Pattern. + + @param[in] This Pointer to EDKII_REDFISH_PLATFORM_CONFI= G_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 Con= figureLangList. + + @retval EFI_SUCCESS ConfigureLangList is returned successfu= lly. + @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 *RedfishPlatformConfigPr= ivate; + 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 =3D=3D NULL || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Ver= sion) || Count =3D=3D NULL || ConfigureLangList =3D=3D NULL || IS_EMPTY_STR= ING (Pattern)) { + return EFI_INVALID_PARAMETER; + } + + *Count =3D 0; + *ConfigureLangList =3D NULL; + FullSchema =3D NULL; + RedfishPlatformConfigPrivate =3D REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_TH= IS (This); + + Status =3D ProcessPendingList (&RedfishPlatformConfigPrivate->FormsetLis= t, &RedfishPlatformConfigPrivate->PendingList); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, ProcessPendingList failure: %r\n", __FUNCTIO= N__, Status)); + return Status; + } + + FullSchema =3D GetFullSchemaString (Schema, Version); + if (FullSchema =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status =3D GetStatementPrivateByConfigureLangRegex ( + RedfishPlatformConfigPrivate->RegularExpressionProtocol, + &RedfishPlatformConfigPrivate->FormsetList, + FullSchema, + Pattern, + &StatementList + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, GetStatementPrivateByConfigureLangRegex fail= ure: %r\n", __FUNCTION__, Status)); + goto RELEASE_RESOURCE; + } + + if (!IsListEmpty (&StatementList.StatementList)) { + + TmpConfigureLangList =3D AllocateZeroPool (sizeof (CHAR16 *) * Stateme= ntList.Count); + if (TmpConfigureLangList =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto RELEASE_RESOURCE; + } + + Index =3D 0; + NextLink =3D GetFirstNode (&StatementList.StatementList); + while (!IsNull (&StatementList.StatementList, NextLink)) { + StatementRef =3D REDFISH_PLATFORM_CONFIG_STATEMENT_REF_FROM_LINK (Ne= xtLink); + NextLink =3D GetNextNode (&StatementList.StatementList, NextLink); + + ASSERT (StatementRef->Statement->Description !=3D 0); + if (StatementRef->Statement->Description !=3D 0) { + TmpString =3D HiiGetRedfishString (StatementRef->Statement->Parent= Form->ParentFormset->HiiHandle, FullSchema, StatementRef->Statement->Descri= ption); + ASSERT (TmpString !=3D NULL); + if (TmpString !=3D NULL) { + TmpConfigureLangList[Index] =3D AllocateCopyPool (StrSize (TmpSt= ring), TmpString); + ASSERT (TmpConfigureLangList[Index] !=3D NULL); + FreePool (TmpString); + ++Index; + } + } + } + } + + *Count =3D StatementList.Count; + *ConfigureLangList =3D TmpConfigureLangList; + +RELEASE_RESOURCE: + + if (FullSchema !=3D 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_CONFI= G_PROTOCOL instance. + @param[in] HiiHandle The target handle to search. If handle = is NULL, + this function return all schema from HI= I database. + @param[out] SupportedSchema The supported schema list which is sepa= rated by ';'. + The SupportedSchema is allocated by the= callee. It's caller's + responsibility to free this buffer usin= g 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 =3D=3D NULL || SupportedSchema =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + *SupportedSchema =3D NULL; + + RedfishPlatformConfigPrivate =3D REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_TH= IS (This); + + Status =3D ProcessPendingList (&RedfishPlatformConfigPrivate->FormsetLis= t, &RedfishPlatformConfigPrivate->PendingList); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, ProcessPendingList failure: %r\n", __FUNCTIO= N__, Status)); + return Status; + } + + if (IsListEmpty (&RedfishPlatformConfigPrivate->FormsetList)) { + return EFI_NOT_FOUND; + } + + // + // Calculate for string buffer size. + // + StringSize =3D 0; + HiiFormsetLink =3D GetFirstNode (&RedfishPlatformConfigPrivate->FormsetL= ist); + while (!IsNull (&RedfishPlatformConfigPrivate->FormsetList, HiiFormsetLi= nk)) { + HiiFormsetNextLink =3D GetNextNode (&RedfishPlatformConfigPrivate->For= msetList, HiiFormsetLink); + HiiFormsetPrivate =3D REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFo= rmsetLink); + + if (HiiHandle !=3D NULL && HiiHandle !=3D HiiFormsetPrivate->HiiHandle= ) { + HiiFormsetLink =3D HiiFormsetNextLink; + continue; + } + + if (HiiFormsetPrivate->SupportedSchema.Count > 0) { + for (Index =3D 0; Index < HiiFormsetPrivate->SupportedSchema.Count; = Index++) { + StringSize +=3D AsciiStrSize (HiiFormsetPrivate->SupportedSchema.S= chemaList[Index]); + } + } + + HiiFormsetLink =3D HiiFormsetNextLink; + } + + if (StringSize =3D=3D 0) { + return EFI_NOT_FOUND; + } + + StringBuffer =3D AllocatePool (StringSize); + if (StringBuffer =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + StringIndex =3D 0; + HiiFormsetLink =3D GetFirstNode (&RedfishPlatformConfigPrivate->FormsetL= ist); + while (!IsNull (&RedfishPlatformConfigPrivate->FormsetList, HiiFormsetLi= nk)) { + HiiFormsetNextLink =3D GetNextNode (&RedfishPlatformConfigPrivate->For= msetList, HiiFormsetLink); + HiiFormsetPrivate =3D REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFo= rmsetLink); + + if (HiiHandle !=3D NULL && HiiHandle !=3D HiiFormsetPrivate->HiiHandle= ) { + HiiFormsetLink =3D HiiFormsetNextLink; + continue; + } + + if (HiiFormsetPrivate->SupportedSchema.Count > 0) { + for (Index =3D 0; Index < HiiFormsetPrivate->SupportedSchema.Count; = Index++) { + AsciiStrCpyS (&StringBuffer[StringIndex], (StringSize - StringInde= x), HiiFormsetPrivate->SupportedSchema.SchemaList[Index]); + StringIndex +=3D AsciiStrLen (HiiFormsetPrivate->SupportedSchema.S= chemaList[Index]); + StringBuffer[StringIndex] =3D ';'; + ++StringIndex; + } + } + + HiiFormsetLink =3D HiiFormsetNextLink; + } + + StringBuffer[--StringIndex] =3D '\0'; + + *SupportedSchema =3D 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 =3D=3D EFI_HII_DATABASE_NOTIFY_NEW_PACK || NotifyType =3D= =3D EFI_HII_DATABASE_NOTIFY_ADD_PACK) { + // + // HII formset on this handle is updated by driver during run-time. Th= e formset needs to be reloaded. + // + Status =3D NotifyFormsetUpdate (Handle, &mRedfishPlatformConfigPrivate= ->PendingList); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, failed to notify updated formset of HII ha= ndle: 0x%x\n", __FUNCTION__, Handle)); + return Status; + } + } else if (NotifyType =3D=3D EFI_HII_DATABASE_NOTIFY_REMOVE_PACK) { + // + // HII resource is removed. The formset is no longer exist. + // + Status =3D NotifyFormsetDeleted (Handle, &mRedfishPlatformConfigPrivat= e->PendingList); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, failed to notify deleted formset of HII ha= ndle: 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 =3D 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 =3D 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 =3D 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 =3D mRedfishPlatformConfigPrivate->HiiDatabase->RegisterPackageNo= tify ( + mRedfishPlatformConfigPrivate= ->HiiDatabase, + EFI_HII_PACKAGE_FORMS, + NULL, + RedfishPlatformConfigFormUpda= teNotify, + EFI_HII_DATABASE_NOTIFY_NEW_P= ACK, + &mRedfishPlatformConfigPrivat= e->NotifyHandle + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, RegisterPackageNotify for EFI_HII_DATABASE_N= OTIFY_NEW_PACK failure: %r\n", __FUNCTION__, Status)); + } + + // + // Register package notification when new form package is updated. + // + Status =3D mRedfishPlatformConfigPrivate->HiiDatabase->RegisterPackageNo= tify ( + mRedfishPlatformConfigPrivate= ->HiiDatabase, + EFI_HII_PACKAGE_FORMS, + NULL, + RedfishPlatformConfigFormUpda= teNotify, + EFI_HII_DATABASE_NOTIFY_ADD_P= ACK, + &mRedfishPlatformConfigPrivat= e->NotifyHandle + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, RegisterPackageNotify for EFI_HII_DATABASE_N= OTIFY_NEW_PACK failure: %r\n", __FUNCTION__, Status)); + } + +#if REDFISH_PLATFORM_CONFIG_DELETE_EXPIRED_FORMSET + // + // Register package notification when new form package is removed. + // + Status =3D mRedfishPlatformConfigPrivate->HiiDatabase->RegisterPackageNo= tify ( + mRedfishPlatformConfigPrivate= ->HiiDatabase, + EFI_HII_PACKAGE_FORMS, + NULL, + RedfishPlatformConfigFormUpda= teNotify, + EFI_HII_DATABASE_NOTIFY_REMOV= E_PACK, + &mRedfishPlatformConfigPrivat= e->NotifyHandle + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, RegisterPackageNotify for EFI_HII_DATABASE_N= OTIFY_NEW_PACK failure: %r\n", __FUNCTION__, Status)); + } +#endif + + gBS->CloseEvent (Event); + mRedfishPlatformConfigPrivate->HiiDbNotify.ProtocolEvent =3D 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 =3D gBS->LocateProtocol ( + &gEfiRegularExpressionProtocolGuid, + NULL, + (VOID **)&mRedfishPlatformConfigPrivate->RegularExpressi= onProtocol + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, locate EFI_REGULAR_EXPRESSION_PROTOCOL failu= re: %r\n", __FUNCTION__, Status)); + return; + } + + gBS->CloseEvent (Event); + mRedfishPlatformConfigPrivate->RegexNotify.ProtocolEvent =3D NULL; + +} + +/** + Unloads an image. + + @param ImageHandle Handle that identifies the image to be unl= oaded. + + @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 !=3D NULL) { + Status =3D gBS->UninstallProtocolInterface ( + mRedfishPlatformConfigPrivate->ImageHandle, + &gEdkIIRedfishPlatformConfigProtocolGuid, + (VOID*)&mRedfishPlatformConfigPrivate->Protocol + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, can not uninstall gEdkIIRedfishPlatformCon= figProtocolGuid: %r\n", __FUNCTION__, Status)); + ASSERT (FALSE); + } + + // + // Close events + // + if (mRedfishPlatformConfigPrivate->HiiDbNotify.ProtocolEvent !=3D NULL= ) { + gBS->CloseEvent (mRedfishPlatformConfigPrivate->HiiDbNotify.Protocol= Event); + } + if (mRedfishPlatformConfigPrivate->HiiStringNotify.ProtocolEvent !=3D = NULL) { + gBS->CloseEvent (mRedfishPlatformConfigPrivate->HiiStringNotify.Prot= ocolEvent); + } + if (mRedfishPlatformConfigPrivate->RegexNotify.ProtocolEvent !=3D NULL= ) { + gBS->CloseEvent (mRedfishPlatformConfigPrivate->RegexNotify.Protocol= Event); + } + + // + // Unregister package notification. + // + if (mRedfishPlatformConfigPrivate->NotifyHandle !=3D NULL) { + mRedfishPlatformConfigPrivate->HiiDatabase->UnregisterPackageNotify ( + mRedfishPlatformConfigPrivate->H= iiDatabase, + mRedfishPlatformConfigPrivate->N= otifyHandle + ); + } + + ReleaseFormsetList (&mRedfishPlatformConfigPrivate->FormsetList); + FreePool (mRedfishPlatformConfigPrivate); + mRedfishPlatformConfigPrivate =3D 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 includ= ing + 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 =3D (REDFISH_PLATFORM_CONFIG_PRIVATE *)All= ocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_PRIVATE)); + if (mRedfishPlatformConfigPrivate =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "%a, can not allocate pool for REDFISH_PLATFORM_C= ONFIG_PRIVATE\n", __FUNCTION__)); + ASSERT (FALSE); + return EFI_OUT_OF_RESOURCES; + } + + // + // Protocol initialization + // + mRedfishPlatformConfigPrivate->ImageHandle =3D ImageHandle; + mRedfishPlatformConfigPrivate->Protocol.GetValue =3D RedfishPlatformConf= igProtocolGetValue; + mRedfishPlatformConfigPrivate->Protocol.SetValue =3D RedfishPlatformConf= igProtocolSetValue; + mRedfishPlatformConfigPrivate->Protocol.GetConfigureLang =3D RedfishPlat= formConfigProtocolGetConfigureLang; + mRedfishPlatformConfigPrivate->Protocol.GetSupportedSchema =3D RedfishPl= atformConfigProtocolGetSupportedSchema; + + InitializeListHead (&mRedfishPlatformConfigPrivate->FormsetList); + InitializeListHead (&mRedfishPlatformConfigPrivate->PendingList); + + Status =3D gBS->InstallProtocolInterface ( + &ImageHandle, + &gEdkIIRedfishPlatformConfigProtocolGuid, + EFI_NATIVE_INTERFACE, + (VOID*)&mRedfishPlatformConfigPrivate->Protocol + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, can not install gEdkIIRedfishPlatformConfigP= rotocolGuid: %r\n", __FUNCTION__, Status)); + ASSERT (FALSE); + } + + // + // Install protocol notification if HII database protocol is installed. + // + mRedfishPlatformConfigPrivate->HiiDbNotify.ProtocolEvent =3D EfiCreatePr= otocolNotifyEvent ( + &gEfiHiiData= baseProtocolGuid, + TPL_CALLBACK, + HiiDatabaseP= rotocolInstalled, + NULL, + &mRedfishPla= tformConfigPrivate->HiiDbNotify.Registration + ); + if (mRedfishPlatformConfigPrivate->HiiDbNotify.ProtocolEvent =3D=3D NULL= ) { + DEBUG ((DEBUG_ERROR, "%a, failed to create protocol notification for g= EfiHiiDatabaseProtocolGuid\n", __FUNCTION__)); + ASSERT (FALSE); + } + + // + // Install protocol notification if HII string protocol is installed. + // + mRedfishPlatformConfigPrivate->HiiStringNotify.ProtocolEvent =3D EfiCrea= teProtocolNotifyEvent ( + &gEfiHii= StringProtocolGuid, + TPL_CALL= BACK, + HiiStrin= gProtocolInstalled, + NULL, + &mRedfis= hPlatformConfigPrivate->HiiStringNotify.Registration + ); + if (mRedfishPlatformConfigPrivate->HiiStringNotify.ProtocolEvent =3D=3D = NULL) { + DEBUG ((DEBUG_ERROR, "%a, failed to create protocol notification for g= EfiHiiStringProtocolGuid\n", __FUNCTION__)); + ASSERT (FALSE); + } + + // + // Install protocol notification if regular expression protocol is insta= lled. + // + mRedfishPlatformConfigPrivate->RegexNotify.ProtocolEvent =3D EfiCreatePr= otocolNotifyEvent ( + &gEfiRegular= ExpressionProtocolGuid, + TPL_CALLBACK, + RegexProtoco= lInstalled, + NULL, + &mRedfishPla= tformConfigPrivate->RegexNotify.Registration + ); + if (mRedfishPlatformConfigPrivate->RegexNotify.ProtocolEvent =3D=3D NULL= ) { + DEBUG ((DEBUG_ERROR, "%a, failed to create protocol notification for g= EfiRegularExpressionProtocolGuid\n", __FUNCTION__)); + ASSERT (FALSE); + } + + return EFI_SUCCESS; +} diff --git a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.= c b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.c new file mode 100644 index 00000000000..d9eab6c883e --- /dev/null +++ b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.c @@ -0,0 +1,1240 @@ +/** @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 =3D=3D NULL || StringId =3D=3D 0) { + DEBUG ((DEBUG_INFO, "???")); + return EFI_INVALID_PARAMETER; + } + + String =3D HiiGetString (HiiHandle, StringId, NULL); + if (String =3D=3D 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 =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + Index =3D 0; + HiiFormLink =3D GetFirstNode (&FormsetPrivate->HiiFormList); + while (!IsNull (&FormsetPrivate->HiiFormList, HiiFormLink)) { + HiiFormPrivate =3D REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK (HiiFormLink= ); + HiiNextFormLink =3D GetNextNode (&FormsetPrivate->HiiFormList, HiiForm= Link); + + DEBUG ((DEBUG_INFO, " [%d] form: %d title: ", ++Index, HiiFormPrivate= ->Id)); + DumpHiiString (FormsetPrivate->HiiHandle, HiiFormPrivate->Title); + DEBUG ((DEBUG_INFO, "\n")); + + HiiStatementLink =3D GetFirstNode (&HiiFormPrivate->StatementList); + while (!IsNull (&HiiFormPrivate->StatementList, HiiStatementLink)) { + HiiStatementPrivate =3D REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK = (HiiStatementLink); + HiiNextStatementLink =3D GetNextNode (&HiiFormPrivate->StatementList= , HiiStatementLink); + + DEBUG ((DEBUG_INFO, " QID: 0x%x Prompt: ", HiiStatementPrivate->Q= uestionId)); + DumpHiiString (FormsetPrivate->HiiHandle, HiiStatementPrivate->Descr= iption); + DEBUG ((DEBUG_INFO, "\n")); + + HiiStatementLink =3D HiiNextStatementLink; + } + + HiiFormLink =3D 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 =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + if (IsListEmpty (FormsetList)) { + DEBUG ((DEBUG_INFO, "%a, Empty formset list\n", __FUNCTION__)); + return EFI_SUCCESS; + } + + Index =3D 0; + HiiFormsetLink =3D GetFirstNode (FormsetList); + while (!IsNull (FormsetList, HiiFormsetLink)) { + HiiFormsetNextLink =3D GetNextNode (FormsetList, HiiFormsetLink); + HiiFormsetPrivate =3D REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFo= rmsetLink); + + DEBUG ((DEBUG_INFO, "[%d] HII Handle: 0x%x formset: %g at %s\n", ++Ind= ex, HiiFormsetPrivate->HiiHandle, &HiiFormsetPrivate->Guid, HiiFormsetPriva= te->DevicePathStr)); + DumpFormset (HiiFormsetPrivate); + + HiiFormsetLink =3D 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 respon= sible + 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 st= ring 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 =3D=3D NULL || HiiHandle = =3D=3D NULL || StringId =3D=3D 0 || IS_EMPTY_STRING (Language)) { + ASSERT (FALSE); + return NULL; + } + + // + // Retrieve the size of the string in the string package for the BestLan= guage + // + StringSize =3D 0; + Status =3D 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 G= etString() + // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is n= ot present + // in the HII Database + // + if (Status !=3D EFI_BUFFER_TOO_SMALL) { + return NULL; + } + + // + // Allocate a buffer for the return string + // + String =3D AllocateZeroPool (StringSize); + if (String =3D=3D NULL) { + return NULL; + } + + // + // Retrieve the string from the string package + // + Status =3D 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 =3D 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 st= ring 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 ot= herwise. + +**/ +BOOLEAN +CheckSupportedSchema ( + IN REDFISH_PLATFORM_CONFIG_SCHEMA *SupportedSchema, + IN CHAR8 *Schema + ) +{ + UINTN Index; + + if (SupportedSchema =3D=3D NULL || IS_EMPTY_STRING (Schema)) { + return FALSE; + } + + if (SupportedSchema->Count =3D=3D 0) { + return FALSE; + } + + for (Index =3D 0; Index < SupportedSchema->Count; Index++) { + if (AsciiStrCmp (SupportedSchema->SchemaList[Index], Schema) =3D=3D 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 NU= LL. + @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 =3D=3D NULL || SupportedSchema =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + SupportedSchema->Count =3D 0; + + SupportedLanguages =3D HiiGetSupportedLanguages (HiiHandle); + if (SupportedLanguages =3D=3D NULL) { + return EFI_NOT_FOUND; + } + + Index =3D 0; + LangIndex =3D 0; + Count =3D 0; + while (TRUE) { + if (SupportedLanguages[Index] =3D=3D ';' || SupportedLanguages[Index] = =3D=3D '\0') { + if (AsciiStrnCmp (&SupportedLanguages[LangIndex], X_UEFI_SCHEMA_PREF= IX, AsciiStrLen (X_UEFI_SCHEMA_PREFIX)) =3D=3D 0) { + ++Count; + } + LangIndex =3D Index + 1; + } + + if (SupportedLanguages[Index] =3D=3D '\0') { + break; + } + + ++Index; + } + + if (Count =3D=3D 0) { + return EFI_NOT_FOUND; + } + + SupportedSchema->Count =3D Count; + SupportedSchema->SchemaList =3D AllocatePool (sizeof (CHAR8 *) * Count); + if (SupportedSchema->SchemaList =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Index =3D 0; + LangIndex =3D 0; + ListIndex =3D 0; + while (TRUE) { + + if (SupportedLanguages[Index] =3D=3D ';' || SupportedLanguages[Index] = =3D=3D '\0') { + if (AsciiStrnCmp (&SupportedLanguages[LangIndex], X_UEFI_SCHEMA_PREF= IX, AsciiStrLen (X_UEFI_SCHEMA_PREFIX)) =3D=3D 0) { + StrSize =3D Index - LangIndex; + SupportedSchema->SchemaList[ListIndex] =3D AllocateCopyPool ((StrS= ize + 1), &SupportedLanguages[LangIndex]); + SupportedSchema->SchemaList[ListIndex][StrSize] =3D '\0'; + ++ListIndex; + } + + LangIndex =3D Index + 1; + } + + if (SupportedLanguages[Index] =3D=3D '\0') { + break; + } + + ++Index; + } + + return EFI_SUCCESS; +} + +/** + Search and find statement private instance by given regular expression p= atthern + 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 *RegularExpressionPr= otocol, + 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 =3D=3D NULL || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRI= NG (Pattern) || StatementList =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + if (RegularExpressionProtocol =3D=3D NULL) { + return EFI_NOT_READY; + } + + StatementList->Count =3D 0; + InitializeListHead (&StatementList->StatementList); + + if (IsListEmpty (FormsetList)) { + return EFI_NOT_FOUND; + } + + HiiFormsetLink =3D GetFirstNode (FormsetList); + while (!IsNull (FormsetList, HiiFormsetLink)) { + HiiFormsetNextLink =3D GetNextNode (FormsetList, HiiFormsetLink); + HiiFormsetPrivate =3D REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFo= rmsetLink); + + // + // Performance check. + // If there is no desired Redfish schema found, skip this formset. + // + if (!CheckSupportedSchema (&HiiFormsetPrivate->SupportedSchema, Schema= )) { + HiiFormsetLink =3D HiiFormsetNextLink; + continue; + } + + HiiFormLink =3D GetFirstNode (&HiiFormsetPrivate->HiiFormList); + while (!IsNull (&HiiFormsetPrivate->HiiFormList, HiiFormLink)) { + HiiNextFormLink =3D GetNextNode (&HiiFormsetPrivate->HiiFormList, Hi= iFormLink); + HiiFormPrivate =3D REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK (HiiFormLi= nk); + + HiiStatementLink =3DGetFirstNode (&HiiFormPrivate->StatementList); + while (!IsNull (&HiiFormPrivate->StatementList, HiiStatementLink)) { + HiiNextStatementLink =3D GetNextNode (&HiiFormPrivate->StatementLi= st, HiiStatementLink); + HiiStatementPrivate =3D REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LIN= K (HiiStatementLink); + + if (HiiStatementPrivate->Description !=3D 0) { + TmpString =3D HiiGetRedfishString (HiiFormsetPrivate->HiiHandle,= Schema, HiiStatementPrivate->Description); + if (TmpString !=3D NULL) { + Status =3D RegularExpressionProtocol->MatchString ( + RegularExpressionProtoco= l, + TmpString, + Pattern, + &gEfiRegexSyntaxTypePerl= Guid, + &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 =3D AllocateZeroPool (sizeof (REDFISH_PLATFORM_= CONFIG_STATEMENT_PRIVATE_REF)); + if (StatementRef =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + StatementRef->Statement =3D HiiStatementPrivate; + InsertTailList (&StatementList->StatementList, &StatementRef= ->Link); + ++StatementList->Count; + } + + FreePool (TmpString); + } + } + + HiiStatementLink =3D HiiNextStatementLink; + } + + HiiFormLink =3D HiiNextFormLink; + } + + HiiFormsetLink =3D 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 stateme= nt 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 =3D=3D NULL || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRI= NG (ConfigureLang)) { + return NULL; + } + + if (IsListEmpty (FormsetList)) { + return NULL; + } + + HiiFormsetLink =3D GetFirstNode (FormsetList); + while (!IsNull (FormsetList, HiiFormsetLink)) { + HiiFormsetNextLink =3D GetNextNode (FormsetList, HiiFormsetLink); + HiiFormsetPrivate =3D REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFo= rmsetLink); + + // + // Performance check. + // If there is no desired Redfish schema found, skip this formset. + // + if (!CheckSupportedSchema (&HiiFormsetPrivate->SupportedSchema, Schema= )) { + HiiFormsetLink =3D HiiFormsetNextLink; + continue; + } + + HiiFormLink =3D GetFirstNode (&HiiFormsetPrivate->HiiFormList); + while (!IsNull (&HiiFormsetPrivate->HiiFormList, HiiFormLink)) { + HiiNextFormLink =3D GetNextNode (&HiiFormsetPrivate->HiiFormList, Hi= iFormLink); + HiiFormPrivate =3D REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK (HiiFormLi= nk); + + HiiStatementLink =3DGetFirstNode (&HiiFormPrivate->StatementList); + while (!IsNull (&HiiFormPrivate->StatementList, HiiStatementLink)) { + HiiNextStatementLink =3D GetNextNode (&HiiFormPrivate->StatementLi= st, HiiStatementLink); + HiiStatementPrivate =3D REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LIN= K (HiiStatementLink); + + DEBUG_CODE ( + STATIC UINTN Index =3D 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 !=3D 0) { + TmpString =3D HiiGetRedfishString (HiiFormsetPrivate->HiiHandle,= Schema, HiiStatementPrivate->Description); + if (TmpString !=3D NULL) { + if (StrCmp (TmpString, ConfigureLang) =3D=3D 0) { + FreePool (TmpString); + return HiiStatementPrivate; + } + + FreePool (TmpString); + } + } + + HiiStatementLink =3D HiiNextStatementLink; + } + + HiiFormLink =3D HiiNextFormLink; + } + + HiiFormsetLink =3D 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 =3D=3D NULL || FormsetList =3D=3D NULL) { + return NULL; + } + + if (IsListEmpty (FormsetList)) { + return NULL; + } + + HiiFormsetLink =3D GetFirstNode (FormsetList); + while (!IsNull (FormsetList, HiiFormsetLink)) { + HiiFormsetNextLink =3D GetNextNode (FormsetList, HiiFormsetLink); + HiiFormsetPrivate =3D REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFo= rmsetLink); + + if (HiiFormsetPrivate->HiiHandle =3D=3D HiiHandle) { + return HiiFormsetPrivate; + } + + HiiFormsetLink =3D HiiFormsetNextLink; + } + + return NULL; +} + +/** + Release formset and all the forms and statements that belong to this for= mset. + + @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 =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + HiiFormLink =3D GetFirstNode (&FormsetPrivate->HiiFormList); + while (!IsNull (&FormsetPrivate->HiiFormList, HiiFormLink)) { + HiiFormPrivate =3D REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK (HiiFormLink= ); + HiiNextFormLink =3D GetNextNode (&FormsetPrivate->HiiFormList, HiiForm= Link); + + HiiStatementLink =3D GetFirstNode (&HiiFormPrivate->StatementList); + while (!IsNull (&HiiFormPrivate->StatementList, HiiStatementLink)) { + HiiStatementPrivate =3D REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK = (HiiStatementLink); + HiiNextStatementLink =3D GetNextNode (&HiiFormPrivate->StatementList= , HiiStatementLink); + + // + // HiiStatementPrivate->HiiStatement will be released in DestroyForm= Set(). + // + + if (HiiStatementPrivate->DesStringCache !=3D NULL) { + FreePool (HiiStatementPrivate->DesStringCache); + HiiStatementPrivate->DesStringCache =3D NULL; + } + + RemoveEntryList (&HiiStatementPrivate->Link); + FreePool (HiiStatementPrivate); + HiiStatementLink =3D HiiNextStatementLink; + } + + // + // HiiStatementPrivate->HiiForm will be released in DestroyFormSet(). + // + + RemoveEntryList (&HiiFormPrivate->Link); + FreePool (HiiFormPrivate); + HiiFormLink =3D HiiNextFormLink; + } + + if (FormsetPrivate->HiiFormSet !=3D NULL) { + DestroyFormSet (FormsetPrivate->HiiFormSet); + FormsetPrivate->HiiFormSet =3D NULL; + } + + FreePool (FormsetPrivate->DevicePathStr); + + // + // Release schema list + // + if (FormsetPrivate->SupportedSchema.SchemaList !=3D NULL) { + for (Index =3D 0; Index < FormsetPrivate->SupportedSchema.Count; Index= ++) { + FreePool (FormsetPrivate->SupportedSchema.SchemaList[Index]); + } + + FreePool (FormsetPrivate->SupportedSchema.SchemaList); + FormsetPrivate->SupportedSchema.SchemaList =3D NULL; + FormsetPrivate->SupportedSchema.Count =3D 0; + } + + return EFI_SUCCESS; +} + +/** + Create new form-set instance. + + @retval REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE * Pointer to newly cr= eated form-set private instance. + +**/ +REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE * +NewFormsetPrivate ( + VOID + ) +{ + REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *NewFormsetPrivate; + + NewFormsetPrivate =3D AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_= FORM_SET_PRIVATE)); + if (NewFormsetPrivate =3D=3D 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 =3D=3D NULL || FormsetPrivate =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + + HiiFormSet =3D AllocateZeroPool (sizeof (HII_FORMSET)); + if (HiiFormSet =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Find HII formset by the given HII handle. + // + ZeroMem (&ZeroGuid, sizeof (ZeroGuid)); + Status =3D CreateFormSetFromHiiHandle (HiiHandle, &ZeroGuid, HiiFormSet); + if (EFI_ERROR (Status) || IsListEmpty (&HiiFormSet->FormListHead)) { + Status =3D EFI_NOT_FOUND; + goto ErrorExit; + } + + // + // Initialize formset + // + InitializeFormSet (HiiFormSet); + + // + // Initialize formset private data. + // + FormsetPrivate->HiiFormSet =3D HiiFormSet; + FormsetPrivate->HiiHandle =3D HiiHandle; + CopyGuid (&FormsetPrivate->Guid, &HiiFormSet->Guid); + FormsetPrivate->DevicePathStr =3D ConvertDevicePathToText (HiiFormSet->D= evicePath, FALSE, FALSE); + Status =3D GetSupportedSchema (FormsetPrivate->HiiHandle, &FormsetPrivat= e->SupportedSchema); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "%a, No schema from HII handle: 0x%x found: %r\n",= __FUNCTION__, FormsetPrivate->HiiHandle, Status)); + } + + HiiFormLink =3D GetFirstNode (&HiiFormSet->FormListHead); + while (!IsNull (&HiiFormSet->FormListHead, HiiFormLink)) { + HiiForm =3D HII_FORM_FROM_LINK (HiiFormLink); + + HiiFormPrivate =3D AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_F= ORM_PRIVATE)); + if (HiiFormPrivate =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + + // + // Initialize form private data. + // + HiiFormPrivate->HiiForm =3D HiiForm; + HiiFormPrivate->Id =3D HiiForm->FormId; + HiiFormPrivate->Title =3D HiiForm->FormTitle; + HiiFormPrivate->ParentFormset =3D FormsetPrivate; + InitializeListHead (&HiiFormPrivate->StatementList); + + HiiStatementLink =3D GetFirstNode (&HiiForm->StatementListHead); + while (!IsNull (&HiiForm->StatementListHead, HiiStatementLink)) { + HiiStatement =3D HII_STATEMENT_FROM_LINK (HiiStatementLink); + + HiiStatementPrivate =3D AllocateZeroPool (sizeof (REDFISH_PLATFORM_C= ONFIG_STATEMENT_PRIVATE)); + if (HiiStatementPrivate =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + // + // Initialize statement private data. + // + HiiStatementPrivate->HiiStatement =3D HiiStatement; + HiiStatementPrivate->QuestionId =3D HiiStatement->QuestionId; + HiiStatementPrivate->Description =3D HiiStatement->Prompt; + HiiStatementPrivate->ParentForm =3D HiiFormPrivate; + + // + // Attach to statement list. + // + InsertTailList (&HiiFormPrivate->StatementList, &HiiStatementPrivate= ->Link); + HiiStatementLink =3D GetNextNode (&HiiForm->StatementListHead, HiiSt= atementLink); + } + // + // Attach to form list. + // + InsertTailList (&FormsetPrivate->HiiFormList, &HiiFormPrivate->Link); + HiiFormLink =3D GetNextNode (&HiiFormSet->FormListHead, HiiFormLink); + } + + return EFI_SUCCESS; + +ErrorExit: + + // + // Release HiiFormSet if HiiFormSet is not linked to FormsetPrivate yet. + // + if (HiiFormSet !=3D NULL && FormsetPrivate->HiiFormSet !=3D 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 =3D=3D NULL || FormsetList =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + FormsetPrivate =3D GetFormsetPrivateByHiiHandle (HiiHandle, FormsetList); + if (FormsetPrivate !=3D NULL) { + return EFI_ALREADY_STARTED; + } + + FormsetPrivate =3D NewFormsetPrivate (); + if (FormsetPrivate =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__)); + return EFI_OUT_OF_RESOURCES; + } + + // + // Load formset on the given HII handle. + // + Status =3D 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 =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + if (IsListEmpty (FormsetList)) { + return EFI_SUCCESS; + } + + HiiFormsetLink =3D GetFirstNode (FormsetList); + while (!IsNull (FormsetList, HiiFormsetLink)) { + HiiFormsetNextLink =3D GetNextNode (FormsetList, HiiFormsetLink); + HiiFormsetPrivate =3D REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFo= rmsetLink); + + // + // Detach from list. + // + RemoveEntryList (&HiiFormsetPrivate->Link); + ReleaseFormset (HiiFormsetPrivate); + FreePool (HiiFormsetPrivate); + HiiFormsetLink =3D 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 =3D=3D NULL || PendingList =3D=3D NULL) { + return NULL; + } + + if (IsListEmpty (PendingList)) { + return NULL; + } + + PendingListLink =3D GetFirstNode (PendingList); + while (!IsNull (PendingList, PendingListLink)) { + Target =3D REDFISH_PLATFORM_CONFIG_PENDING_LIST_FROM_LINK (PendingList= Link); + + if (Target->HiiHandle =3D=3D HiiHandle) { + return Target; + } + + PendingListLink =3D 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 recentl= y 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 =3D=3D NULL || PendingList =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check and see if this HII handle is processed already. + // + TargetPendingList =3D GetPendingList (HiiHandle, PendingList); + if (TargetPendingList !=3D NULL) { + TargetPendingList->IsDeleted =3D FALSE; + DEBUG_CODE ( + DEBUG ((DEBUG_INFO, "%a, HII handle: 0x%x is updated\n", __FUNCTION__,= HiiHandle)); + ); + return EFI_SUCCESS; + } + + TargetPendingList=3D AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_P= ENDING_LIST)); + if (TargetPendingList =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + TargetPendingList->HiiHandle =3D HiiHandle; + TargetPendingList->IsDeleted =3D 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 h= andle 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 recentl= y 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 =3D=3D NULL || PendingList =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check and see if this HII handle is processed already. + // + TargetPendingList =3D GetPendingList (HiiHandle, PendingList); + if (TargetPendingList !=3D NULL) { + TargetPendingList->IsDeleted =3D TRUE; + DEBUG_CODE ( + DEBUG ((DEBUG_INFO, "%a, HII handle: 0x%x is updated and deleted\n",= __FUNCTION__, HiiHandle)); + ); + return EFI_SUCCESS; + } + + TargetPendingList=3D AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_P= ENDING_LIST)); + if (TargetPendingList =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + TargetPendingList->HiiHandle =3D HiiHandle; + TargetPendingList->IsDeleted =3D 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 NU= LL. + +**/ +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 =3D=3D NULL || PendingList =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + if (IsListEmpty (PendingList)) { + return EFI_SUCCESS; + } + + PendingListLink =3D GetFirstNode (PendingList); + while (!IsNull (PendingList, PendingListLink)) { + PendingListNextLink =3D GetNextNode (PendingList, PendingListLink); + Target =3D REDFISH_PLATFORM_CONFIG_PENDING_LIST_FROM_LINK (PendingList= Link); + + if (Target->IsDeleted) { + // + // The HII resource on this HII handle is removed. Release the forms= et. + // + FormsetPrivate =3D GetFormsetPrivateByHiiHandle (Target->HiiHandle, = FormsetList); + if (FormsetPrivate !=3D NULL) { + DEBUG ((DEBUG_INFO, "%a, formset: %g is removed because driver rel= ease 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 al= ready\n", __FUNCTION__, Target->HiiHandle)); + } + } else { + // + // The HII resource on this HII handle is updated/removed. + // + FormsetPrivate =3D GetFormsetPrivateByHiiHandle (Target->HiiHandle, = FormsetList); + if (FormsetPrivate !=3D NULL) { + // + // HII formset already exist, release it and query again. + // + DEBUG ((DEBUG_INFO, "%a, formset: %g is updated. Release current f= ormset\n", __FUNCTION__, &FormsetPrivate->Guid)); + RemoveEntryList (&FormsetPrivate->Link); + ReleaseFormset (FormsetPrivate); + FreePool (FormsetPrivate); + } + + Status =3D LoadFormsetList (Target->HiiHandle, FormsetList); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, load formset from HII handle: 0x%x faile= d: %r\n", __FUNCTION__, Target->HiiHandle, Status)); + } + } + + // + // Detach it from list first. + // + RemoveEntryList (&Target->Link); + FreePool (Target); + + PendingListLink =3D 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 =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + if (IsListEmpty (&StatementList->StatementList)) { + return EFI_SUCCESS; + } + + NextLink =3D GetFirstNode (&StatementList->StatementList); + while (!IsNull (&StatementList->StatementList, NextLink)) { + StatementRef =3D REDFISH_PLATFORM_CONFIG_STATEMENT_REF_FROM_LINK (Next= Link); + NextLink =3D GetNextNode (&StatementList->StatementList, NextLink); + + RemoveEntryList (&StatementRef->Link); + FreePool (StatementRef); + } + + return EFI_SUCCESS; +} --=20 2.21.0.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#82767): https://edk2.groups.io/g/devel/message/82767 Mute This Topic: https://groups.io/mt/86642880/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-