From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from NAM10-DM6-obe.outbound.protection.outlook.com (NAM10-DM6-obe.outbound.protection.outlook.com [40.107.93.52]) by mx.groups.io with SMTP id smtpd.web08.28629.1658978041059441779 for ; Wed, 27 Jul 2022 20:14:01 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@amd.com header.s=selector1 header.b=pmljiphr; spf=permerror, err=parse error for token &{10 18 %{i}._ip.%{h}._ehlo.%{d}._spf.vali.email}: invalid domain name (domain: amd.com, ip: 40.107.93.52, mailfrom: abner.chang@amd.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=G3wBnw037hsPVpP/YAxQHx7KNcF+rz5Uj88djCP4NJeY0OSrZtPUIGe/41S8HFQEObCiyK7cXDQFb3s5yJYfUxe8RElA3ft4O9Uso9drA0xsHJj4mvM/kqYZ0ww1vNf8Gd5DH3fsSaOJ0AOfHE6j97EEfQq47xQp5oMDe9qQ1baYceXDXcbQAtm9ELgnr9IhntKIEc/bXBUHIqwXJKAfaWXO8qGXGSYrBFzFhtESPFAcLdVUIPUoLQ7WvX4hkUxuxelu/vHEOVhNemtfWfeUybGA+LeRSwMafoHRFrVCQtGItoa/VZ7kRFDSfPGChWesXe2tyELuwv4b3xr1tjAJZQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=fLaAHYnxoF65sNh5EbYpu3nMRFb+kabLSBzDBdinrYE=; b=kwjAf/Xgjx1Z4hNi+xFZHJdXNvaIFEdUlDmgJw1pbBXT9HX9OxoXP1nTaCSoutEPa9j4YKgVcxviDJDnSW6aEd5+YhfVvmF5mmo5fX0ZVx0r8jDH4hWp5RHSJmfJo8PkyE1DgkTyN38Asd9C0Ej4G1DMA0d71WC68btJet/p8jQIWKM4cJsewKgHNYM0Fli8zVBhhzs7QUAS2nJLlWQ0AKayihM2RGMvG7aNXAYrDY2WL0qn7BytDk3k/EhHgejSVfNBsFXlIf/d/+50uBrqz0uBgfWFSHgN3jGxMAt9f01PoNp2lruM8aILLqPr/DSLpmWeABo16Q3PsEgnyAOhPQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=amd.com; dmarc=pass action=none header.from=amd.com; dkim=pass header.d=amd.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=fLaAHYnxoF65sNh5EbYpu3nMRFb+kabLSBzDBdinrYE=; b=pmljiphrwKyyujS6We39af0QcczPyalxLDOICaAzYwG5on9jegoN0BT+EwSVbKka54jjFiNfuRHN7wV572R9/1V8sgDfm7p79C83WnyAQkwi3NctO7F/0yrlEyJqQA8tUUsTWh7dFxGZw83fc9492oA+yuzGWRX/MvrVjFHtU8Q= Received: from MN2PR12MB3966.namprd12.prod.outlook.com (2603:10b6:208:165::18) by BL1PR12MB5126.namprd12.prod.outlook.com (2603:10b6:208:312::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5458.19; Thu, 28 Jul 2022 03:13:55 +0000 Received: from MN2PR12MB3966.namprd12.prod.outlook.com ([fe80::605a:11f4:fc16:8b06]) by MN2PR12MB3966.namprd12.prod.outlook.com ([fe80::605a:11f4:fc16:8b06%5]) with mapi id 15.20.5458.025; Thu, 28 Jul 2022 03:13:55 +0000 From: "Chang, Abner" To: Nickle Wang , "devel@edk2.groups.io" CC: "Yang, Atom" , Nick Ramirez Subject: Re: [edk2-staging][PATCH v3 10/15] edk2-staging/RedfishClientPkg: Update Redfish feature utility library Thread-Topic: [edk2-staging][PATCH v3 10/15] edk2-staging/RedfishClientPkg: Update Redfish feature utility library Thread-Index: AQHYoVmTzO36UUC10UGuS527kqPynK2THO9w Date: Thu, 28 Jul 2022 03:13:55 +0000 Message-ID: References: <20220727013802.247-1-nickle.wang@hpe.com> <20220727013802.247-11-nickle.wang@hpe.com> In-Reply-To: <20220727013802.247-11-nickle.wang@hpe.com> Accept-Language: zh-CN, en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: msip_labels: MSIP_Label_4342314e-0df4-4b58-84bf-38bed6170a0f_Enabled=true; MSIP_Label_4342314e-0df4-4b58-84bf-38bed6170a0f_SetDate=2022-07-28T03:13:52Z; MSIP_Label_4342314e-0df4-4b58-84bf-38bed6170a0f_Method=Standard; MSIP_Label_4342314e-0df4-4b58-84bf-38bed6170a0f_Name=General; MSIP_Label_4342314e-0df4-4b58-84bf-38bed6170a0f_SiteId=3dd8961f-e488-4e60-8e11-a82d994e183d; MSIP_Label_4342314e-0df4-4b58-84bf-38bed6170a0f_ActionId=c224b789-8c64-4325-9c4c-a80af08321c3; MSIP_Label_4342314e-0df4-4b58-84bf-38bed6170a0f_ContentBits=1 authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=amd.com; x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: 93acf6ef-e187-429f-ad07-08da704734c6 x-ms-traffictypediagnostic: BL1PR12MB5126:EE_ x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: GKqxStZ3wD9w5u8N0vRqi4R720LLjOljOrcjVYD6tgfxH8K6eVmQclIYd7zZWJ9eOCu4JlClyVp3OREmWGm1ieyfkAThvdkKoTZE9dCi5vdFFzMhdi1YpMXXrCV5fK+Zs4J5OpywHELHhgvVF3QRzzA5oOEn1NyTillLl1kjQ5hc31/ZTGwvpVzJNUT3/6sLl+gkV5LZtBFAMDOBVvKfWuYDhSJ1z/xX/7zCkjVsvFwo3Cw1ybxjcdQUT/wSP/mvm5vjQOVmLRz5xpfQDiql+cj/r46SR+GA9L22zIit329jqTnMI9BTAA7VYN3DqLLtm9H0A3qVXsjZDq51qvhTkergyY7J1145hl02w8yQzvBIrFbu2Mt3mgE+PCCYN1jo/wANTQLUN6rHAq/yulF3BYY37LCulUHKUvy1fbT1qf1yaeI+pKg6nwJfvc5HH+ch6VTpl3lcMjuwvt+tuGUkUhxY1Jd+woFcc81gr9J0+eQDxqqEYKaXKSDbn/QtFck8EEpkTVBCct5VotI5e4vvbwLcCq8NJy0Oi8BR1uW+Lv4Ve64nlgWRXuRxsfmcXiC0SwRX26CLdFmssQfNDemKViy28EZRwyu5tWyWRYJNkF8IKWI+MSxRiOY/GSnsKbUWK6erNTJ8gmhmsqF9n54/1ippFRoNEIdQQF1tRCXciuz5UH+P3oPKRJNCE34umVSTualMxrGAYW2WrGIr9qDoICKYP8CKYxuUzTkK/FUkSX35OL17jzYF0uVSNtKDYBp9yk9q0CU5azgMzycqMXvG+e99NaUF8oQBMtq7AtdxRdUgwsA7EmwCNMEbWxVQId8m x-forefront-antispam-report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:MN2PR12MB3966.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230016)(4636009)(366004)(396003)(39860400002)(346002)(136003)(376002)(53546011)(66476007)(76116006)(66446008)(30864003)(4326008)(71200400001)(8676002)(66556008)(66946007)(8936002)(40140700001)(26005)(52536014)(9686003)(5660300002)(64756008)(296002)(316002)(15650500001)(38100700002)(478600001)(33656002)(55016003)(6506007)(41300700001)(86362001)(38070700005)(122000001)(54906003)(186003)(83380400001)(19627235002)(2906002)(7696005)(110136005)(559001)(579004);DIR:OUT;SFP:1101; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?us-ascii?Q?eJSUrQyUzjYxyQojJBYZKOFAAkBX+DuFkO3GlAFiSrmKL2pfo2Y8wuwSOhEy?= =?us-ascii?Q?0mZgWnfB2UzvXGek1S4TT/h0iPft2zNxhOeWqQsgH8TuQH1DWrxoQ0GxUmBA?= =?us-ascii?Q?rX001sEn04Fp/2LHQpa7aw4zDoeNtuuR5FQNhvUrkhvxNqhfGcj3wGWNLYbU?= =?us-ascii?Q?2ZTD2l7QbJYNp2PDnvwRVxC/NV6xhYzoZk1drGzYfFj6rC6KHXNPj51bszWw?= =?us-ascii?Q?eYV9Y38h5a0KUH3cKvwSoFAi796GjMjljjWVPUIkPbMoHsGAoCDyKmpgg4bB?= =?us-ascii?Q?eI4z80+nPn5woW7iBAOqf7hTuripS617bbcgxVhvRtla0S2xxkAY1ORbT5Xi?= =?us-ascii?Q?24QTZlHXK4daXQ2iYyfUnD+dR0EEo9eLsY51VZrDom6G5rvvuOEDsy8lxiRN?= =?us-ascii?Q?L6/B2N3P/N7wZLYRMuhiobk/8oJV8Ui/iuARyruNBZmcrsoVbSnWjuz2K52i?= =?us-ascii?Q?QdzvzWL5s751sNyJvSWFWdwMCUn/LidSfVHoC7H/o50sN8kK8YCsmqfaB+cz?= =?us-ascii?Q?KXe4oBZf4GlFQdcKcHpCQLe8WSDHQ8ChQlhQiOxCDYAnQJial43QaGx42tQW?= =?us-ascii?Q?cTjkfUtmWpQWcCZbxLafuOC/TZmoe9tCYfhIKl3vyv2V6spGAsK1A8VkJejd?= =?us-ascii?Q?Qlh1s8wftRVdyQj4RqzDLeh2WNioX4e6zgihsQR6RIq6BoAepMvQWYOkd1SK?= =?us-ascii?Q?6q+dgMnErUPKnAa9NZYvnkSHBXmK/laUzUWY9SN5xF1nKzm7D3s7pcVx96Om?= =?us-ascii?Q?aGzT0LX2sw5NVjqxYHg/wP+q8zpSJUTbAKph1UP6fn735zn9K7PVF/A7SVol?= =?us-ascii?Q?hPl8X9HpvGBVQzaTh8WIou5WnCoXmrAa4h2ay0cNKgOAO1WWcnjD+WWSqmBB?= =?us-ascii?Q?h5pPgm41QOH+SS/fcIPJb1xqrSNNi6/QMBws6wd0zA9cUfMgRFGRQ56wNLgM?= =?us-ascii?Q?u8Tm/KMcZ6hN5JpsBuUWKk2VVhaQ7rv7A74OxnRaMwz0wS234WLh6iGJGto8?= =?us-ascii?Q?EFvyP17h7Bf6g730HHVZHRQrXEAYWquwfde8J5hsA4nWlyXJbZ+wqEpLON7z?= =?us-ascii?Q?xRrFf7IGY/IHlNdP6WMuHuBgS1/iojOreioZaNDFNb4QYmQs5LTcqfV5o5tT?= =?us-ascii?Q?dCrdPM3aqhxcHkrXv1g+ft09RvhCxpCqaDQ8hdeBAhZ5+F31KFEOvKw9pr7i?= =?us-ascii?Q?dKT9jyHzb9V9olC6WDyCRDRE7GYOWu1griRM1y8E+r5ioMpuL2MSz/RsIyOE?= =?us-ascii?Q?dYWF1Ve07G32wyvEuDwUaTBL5jKPKL6uybXtq4ehU3DfFhn70mr5dRU3Sj8R?= =?us-ascii?Q?q8zKlYdIfO3ebPE63nks51ft9FUldcmoVT32A81MBXFUy1jc7qktNQ/9uzYI?= =?us-ascii?Q?lFiU5JZKXNVM31xhZB1WBKPhrSTRa9EVm5SIp9DLZLEuopLhbU18b0kOizl0?= =?us-ascii?Q?Sz02tSkWNmMjsf6PV6gbdJfaVkH/uinet9co1Qq1VDibyjSgKZ+52oHnwkYy?= =?us-ascii?Q?DC1Ho5l7bIWVomkvz9FTifwWGNYDfY947Q2ImDnsHvnQviS/1jAdk6cWE6Wb?= =?us-ascii?Q?3z+rKxSDX2t3BzPdtQzuqV9jZ+QuC2IUs4GSIyug?= MIME-Version: 1.0 X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: MN2PR12MB3966.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: 93acf6ef-e187-429f-ad07-08da704734c6 X-MS-Exchange-CrossTenant-originalarrivaltime: 28 Jul 2022 03:13:55.6146 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: MCxsQfFZK3uDWoPkWJ3I92bXnuAbUXEy/uZLpMOxyteqJpCCnQEyFvDgGn2AbYC3PeuxD8VAx/AFnnAvt/sMyQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: BL1PR12MB5126 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable [AMD Official Use Only - General] Please search [Chang, Abner] for the comment. > -----Original Message----- > From: Nickle Wang > Sent: Wednesday, July 27, 2022 9:38 AM > To: devel@edk2.groups.io > Cc: Chang, Abner ; Yang, Atom > ; Nick Ramirez > Subject: [edk2-staging][PATCH v3 10/15] edk2-staging/RedfishClientPkg: > Update Redfish feature utility library >=20 > [CAUTION: External Email] >=20 > Update Redfish feature utility library in order to support array type > of resource. Some helper functions are introduced to get Redfish data. > Also expose RedfishCsCommon.h so that feature utility library can work > with Redfish C data structure without redundant structure conversion. >=20 > Signed-off-by: Nickle Wang > Cc: Abner Chang > Cc: Yang Atom > Cc: Nick Ramirez > --- > .../Library/RedfishFeatureUtilityLib.h | 756 +++- > .../RedfishJsonStructure/RedfishCsCommon.h | 14 + > .../RedfishFeatureUtilityInternal.h | 16 +- > .../RedfishFeatureUtilityLib.c | 3662 +++++++++++++---- > .../RedfishFeatureUtilityLib.inf | 20 +- > 5 files changed, 3470 insertions(+), 998 deletions(-) > create mode 100644 > RedfishClientPkg/Include/RedfishJsonStructure/RedfishCsCommon.h >=20 > diff --git a/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h > b/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h > index 50ff82c70f..1325976d8c 100644 > --- a/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h > +++ b/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h > @@ -1,7 +1,7 @@ > /** @file > This file defines the Redfish Feature Utility Library interface. >=20 > - (C) Copyright 2021 Hewlett Packard Enterprise Development LP
> + (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP
>=20 > SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > @@ -10,8 +10,9 @@ > #ifndef REDFISH_FEATURE_UTILITY_LIB_H_ > #define REDFISH_FEATURE_UTILITY_LIB_H_ >=20 > -#include > -#include > +#include > +#include > +#include >=20 > // > // Definition of REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG > @@ -31,10 +32,10 @@ typedef struct { >=20 > /** >=20 > - Read redfish resource by given resource path. > + Read redfish resource by given resource URI. >=20 > @param[in] Service Redfish srvice instacne to make query. > - @param[in] ResourcePath Target resource path. > + @param[in] ResourceUri Target resource URI. > @param[out] Response HTTP response from redfish service. >=20 > @retval EFI_SUCCESS Resrouce is returned successfully. > @@ -42,12 +43,34 @@ typedef struct { >=20 > **/ > EFI_STATUS > -GetResourceByPath ( > +GetResourceByUri ( > IN REDFISH_SERVICE *Service, > - IN CHAR8 *ResourcePath, > + IN EFI_STRING ResourceUri, > OUT REDFISH_RESPONSE *Response > ); >=20 > +/** > + > + Check if this is the Redpath array. Usually the Redpath array represen= ts > + the collection member. Return > + > + @param[in] ConfigureLang The Redpath to check > + @param[out] ArraySignatureOpen String to the open of array sign= ature. > + @param[out] ArraySignatureClose String to the close of array sig= nature. > + > + @retval EFI_SUCCESS Index is found. > + @retval EFI_NOT_FOUND The non-array configure language st= ring is > retured. > + @retval EFI_INVALID_PARAMETER The format of input ConfigureLang i= s > wrong. > + @retval Others Errors occur. > + > +**/ > +EFI_STATUS > +IsRedpathArray ( > + IN EFI_STRING ConfigureLang, > + OUT EFI_STRING *ArraySignatureOpen, > + OUT EFI_STRING *ArraySignatureClose > + ); > + > /** >=20 > Search HII database with given Configure Language pattern. Data is han= dled > and > @@ -72,76 +95,142 @@ RedfishFeatureGetUnifiedArrayTypeConfigureLang ( >=20 > /** >=20 > - Get array key by parsing the URI. > + Clone the configure language list. >=20 > - @param[in] Uri URI with array key. > - @param[out] ArrayKey Array key in given URI string. > + @param[in] ConfigureLangList The source > REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST. > + @param[out] DestConfigureLangList The destination > REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST. >=20 > - @retval EFI_SUCCESS Array key is found. > - @retval Others Errors occur. > + @retval EFI_SUCCESS > REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST is copied. > + @retval Others Errors occur. >=20 > **/ > EFI_STATUS > -GetArraykeyFromUri ( > - IN CHAR8 *Uri, > - OUT CHAR8 **ArrayKey > +CopyConfiglanguageList ( > + IN REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST > *SourceConfigureLangList, > + OUT REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST > *DestConfigureLangList > ); >=20 > /** >=20 > - Keep configure language with given key in UEFI variable. > + Get number of node from the string. Node is seperated by '/'. >=20 > - @param[in] Schema Schema name. > - @param[in] Version Schema version. > - @param[in] Key Key string. > - @param[in] ConfigureLangIndex Index value. > + @param[in] NodeString The node string to parse. >=20 > - @retval EFI_SUCCESS Data is saved in UEFI variable. > - @retval Others Errors occur. > + @retval UINTN Number of nodes in the string. > + > +**/ > +UINTN > +GetNumberOfRedpathNodes ( > + IN EFI_STRING NodeString > + ); > + > +/** > + > + Get the node string by index > + > + @param[in] NodeString The node string to parse. > + @param[in] Index Index of the node. > + @param[out] EndOfNodePtr Pointer to receive the poitner to > + the last character of node string. > + > + @retval EFI_STRING the begining of the node string. > + > +**/ > +EFI_STRING > +GetRedpathNodeByIndex ( > + IN EFI_STRING NodeString, > + IN UINTN Index, > + OUT EFI_STRING *EndOfNodePtr OPTIONAL > + ); > + > +/** > + > + Find array index from given configure language string. > + > + @param[in] ConfigureLang Configure language string to parse. > + @param[out] UnifiedConfigureLang The configure language in array. > + @param[out] Index The array index number. > + > + @retval EFI_SUCCESS Index is found. > + @retval EFI_NOT_FOUND The non-array configure language st= ring is > retured. > + @retval EFI_INVALID_PARAMETER The format of input ConfigureLang i= s > wrong. > + @retval Others Errors occur. >=20 > **/ > EFI_STATUS > -SetConfigureLangWithkey ( > - IN CHAR8 *Schema, > - IN CHAR8 *Version, > - IN CHAR8 *Key, > - IN UINTN ConfigureLangIndex > +GetArrayIndexFromArrayTypeConfigureLang ( > + IN CHAR16 *ConfigureLang, > + OUT CHAR16 **UnifiedConfigureLang, > + OUT UINTN *Index > ); >=20 > /** >=20 > - Find configure language with input key string. > + Clone the configure language list. > + > + @param[in] ConfigureLang The pointer to configuration language. >=20 > - @param[in] Schema Schema name. > - @param[in] Version Schema version. > - @param[in] Property Property name. > - @param[in] Key Key string. > + @retval UINTN The index of collection member instance. > + Value of 0 means no instance is found. > +**/ > +UINTN > +ConfiglanguageGetInstanceIndex ( > + IN EFI_STRING ConfigureLang > + ); >=20 > - @retval CHAR16 * Corresponding configure langauge > - @retval NULL No configure language is found > +/** > + > + Destroy the configure language list. > + > + @param[in] ConfigureLangList The > REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST > + instance to destroy. > + > + @retval EFI_SUCCESS > REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST is copied. > + @retval Others Errors occur. >=20 > **/ > -CHAR16 * > -GetConfigureLangByKey ( > - IN CHAR8 *Schema, > - IN CHAR8 *Version, > - IN CHAR8 *Property, > - IN CHAR8 *Key > +EFI_STATUS > +DestroyConfiglanguageList ( > + IN REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST > *ConfigureLangList > ); >=20 > /** >=20 > - Convert HII string value to string value in JSON format. > + Set the node instance. >=20 > - @param[in] HiiStringValue String in HII format. > + @param[in] DestConfigLang Pointer to the node's configure lang= uage > string. > + The memory pointed by ConfigLang mus= t be allocated > + through memory allocation interface.= Becasue we will > replace > + the pointer in this function. > + @param[in] MaxtLengthConfigLang The maximum length of ConfigLang. > + @param[in] ConfigLangInstance Pointer to Collection member instanc= e. >=20 > - @retval CHAR8 * String in JSON format. > - @retval NULL Errors occur. > + @retval EFI_SUCCESS The instance is inserted to the configure > language. > + @retval Others Errors occur. >=20 > **/ > -CHAR8 * > -ConvertHiiStringValueToJsonStringValue ( > - IN EFI_STRING HiiStringValue > +EFI_STATUS > +SetResourceConfigLangMemberInstance ( > + IN EFI_STRING *DestConfigLang, > + IN UINTN MaxtLengthConfigLang, > + IN REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG *ConfigLangInstance > + ); > + > +/** > + > + Get array key by parsing the URI. > + > + @param[in] Uri URI with array key. > + @param[out] ArrayKey Array key in given URI string. > + > + @retval EFI_SUCCESS Array key is found. > + @retval Others Errors occur. > + > +**/ > +EFI_STATUS > +GetArraykeyFromUri ( > + IN CHAR8 *Uri, > + OUT CHAR8 **ArrayKey > ); >=20 > /** > @@ -209,125 +298,157 @@ ApplyFeatureSettingsBooleanType ( >=20 > /** >=20 > - Create HTTP payload and send them to redfish service with POST method. > + Apply property value to UEFI HII database in vague type. >=20 > - @param[in] Service Redfish service. > - @param[in] TargetPayload Target payload > - @param[in] Json Data in JSON format. > - @param[out] Location Returned location string from Redfish serv= ice. > - @param[out] Etag Returned ETAG string from Redfish service. > + @param[in] Schema Property schema. > + @param[in] Version Property schema version. > + @param[in] ConfigureLang Configure language refers to this property= . > + @param[in] VagueValuePtr Pointer of vague values to to set. > + @param[in] NumVagueValues Number of vague values. >=20 > - @retval EFI_SUCCESS Data is sent to redfish service successful= ly. > + @retval EFI_SUCCESS New value is applied successfully. > @retval Others Errors occur. >=20 > **/ > EFI_STATUS > -CreatePayloadToPostResource ( > - IN REDFISH_SERVICE *Service, > - IN REDFISH_PAYLOAD *TargetPayload, > - IN CHAR8 *Json, > - OUT CHAR8 **Location, > - OUT CHAR8 **Etag > +ApplyFeatureSettingsVagueType ( > + IN CHAR8 *Schema, > + IN CHAR8 *Version, > + IN EFI_STRING ConfigureLang, > + IN RedfishCS_EmptyProp_KeyValue *VagueValuePtr, > + IN UINT32 NumberOfVagueValues > ); >=20 > /** >=20 > - Create HTTP payload and send them to redfish service with PATCH method= . > + Apply property value to UEFI HII database in string array type. >=20 > - @param[in] Service Redfish service. > - @param[in] TargetPayload Target payload > - @param[in] Json Data in JSON format. > - @param[out] Etag Returned ETAG string from Redfish service. > + @param[in] Schema Property schema. > + @param[in] Version Property schema version. > + @param[in] ConfigureLang Configure language refers to this property. > + @param[in] ArrayHead Head of array value. >=20 > - @retval EFI_SUCCESS Data is sent to redfish service successful= ly. > + @retval EFI_SUCCESS New value is applied successfully. > @retval Others Errors occur. >=20 > **/ > EFI_STATUS > -CreatePayloadToPatchResource ( > - IN REDFISH_SERVICE *Service, > - IN REDFISH_PAYLOAD *TargetPayload, > - IN CHAR8 *Json, > - OUT CHAR8 **Etag > +ApplyFeatureSettingsStringArrayType ( > + IN CHAR8 *Schema, > + IN CHAR8 *Version, > + IN EFI_STRING ConfigureLang, > + IN RedfishCS_char_Array *ArrayHead > ); >=20 > /** >=20 > - Find Redfish Resource Config Protocol that supports given schema and > version. > + Apply property value to UEFI HII database in numeric array type (INT64= ). >=20 > - @param[in] Schema Schema name. > - @param[in] Major Schema version major number. > - @param[in] Minor Schema version minor number. > - @param[in] Errata Schema version errata number. > + @param[in] Schema Property schema. > + @param[in] Version Property schema version. > + @param[in] ConfigureLang Configure language refers to this property. > + @param[in] ArrayHead Head of array value. >=20 > - @retval EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL * Pointer to > protocol > - @retval NULL No protocol fo= und. > + @retval EFI_SUCCESS New value is applied successfully. > + @retval Others Errors occur. >=20 > **/ > -EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL * > -GetRedfishResourceConfigProtocol ( > - IN CHAR8 *Schema, > - IN CHAR8 *Major, > - IN CHAR8 *Minor, > - IN CHAR8 *Errata > +EFI_STATUS > +ApplyFeatureSettingsNumericArrayType ( > + IN CHAR8 *Schema, > + IN CHAR8 *Version, > + IN EFI_STRING ConfigureLang, > + IN RedfishCS_int64_Array *ArrayHead > ); >=20 > /** >=20 > - Get supported schema list by given specify schema name. > + Apply property value to UEFI HII database in boolean array type (INT64= ). >=20 > - @param[in] Schema Schema type name. > - @param[out] SchemaInfo Returned schema information. > + @param[in] Schema Property schema. > + @param[in] Version Property schema version. > + @param[in] ConfigureLang Configure language refers to this property. > + @param[in] ArrayHead Head of Redfich CS boolean array value. >=20 > - @retval EFI_SUCCESS Schema information is returned success= fully. > - @retval Others Errors occur. > + @retval EFI_SUCCESS New value is applied successfully. > + @retval Others Errors occur. >=20 > **/ > EFI_STATUS > -GetSupportedSchemaVersion ( > - IN CHAR8 *Schema, > - OUT REDFISH_SCHEMA_INFO *SchemaInfo > +ApplyFeatureSettingsBooleanArrayType ( > + IN CHAR8 *Schema, > + IN CHAR8 *Version, > + IN EFI_STRING ConfigureLang, > + IN RedfishCS_bool_Array *ArrayHead > ); >=20 > /** >=20 > - Return system root path > + Create HTTP payload and send them to redfish service with POST method. > + > + @param[in] Service Redfish service. > + @param[in] TargetPayload Target payload > + @param[in] Json Data in JSON format. > + @param[out] Location Returned location string from Redfish serv= ice. > + @param[out] Etag Returned ETAG string from Redfish service. >=20 > - @retval NULL Can not find system root path. > - @retval Other System root path is returned. > + @retval EFI_SUCCESS Data is sent to redfish service successful= ly. > + @retval Others Errors occur. >=20 > **/ > -CHAR8 * > -RedfishGetSystemRootPath ( > - VOID > +EFI_STATUS > +CreatePayloadToPostResource ( > + IN REDFISH_SERVICE *Service, > + IN REDFISH_PAYLOAD *TargetPayload, > + IN CHAR8 *Json, > + OUT EFI_STRING *Location, > + OUT CHAR8 **Etag > ); >=20 > /** >=20 > - Get schema information by given protocol and service instance. > + Create HTTP payload and send them to redfish service with PATCH method= . >=20 > - @param[in] RedfishService Pointer to Redfish service instance. > - @param[in] JsonStructProtocol Json Structure protocol instance. > - @param[in] Uri Target URI. > - @param[out] SchemaInfo Returned schema information. > + @param[in] Service Redfish service. > + @param[in] TargetPayload Target payload > + @param[in] Json Data in JSON format. > + @param[out] Etag Returned ETAG string from Redfish service. >=20 > - @retval EFI_SUCCESS Schema information is returned success= fully. > - @retval Others Errors occur. > + @retval EFI_SUCCESS Data is sent to redfish service successful= ly. > + @retval Others Errors occur. >=20 > **/ > EFI_STATUS > -GetRedfishSchemaInfo ( > - IN REDFISH_SERVICE *RedfishService, > - IN EFI_REST_JSON_STRUCTURE_PROTOCOL *JsonStructProtocol, > - IN CHAR8 *Uri, > - OUT REDFISH_SCHEMA_INFO *SchemaInfo > +CreatePayloadToPatchResource ( > + IN REDFISH_SERVICE *Service, > + IN REDFISH_PAYLOAD *TargetPayload, > + IN CHAR8 *Json, > + OUT CHAR8 **Etag > + ); > + > +/** > + > + Save Redfish URI in database for further use. > + > + @param[in] ConfigLang ConfigLang to save > + @param[in] Uri Redfish Uri to save > + > + @retval EFI_INVALID_PARAMETR SystemId is NULL or EMPTY > + @retval EFI_SUCCESS Redfish uri is saved > + > +**/ > +EFI_STATUS > +RedfisSetRedfishUri ( > + IN EFI_STRING ConfigLang, > + IN EFI_STRING Uri > ); >=20 > /** >=20 > Get the property name by given Configure Langauge. >=20 > - @param[in] ConfigureLang Configure Language string. > + @param[in] ResourceUri URI of root of resource. > + @param[in] ConfigureLang Configure Language string. >=20 > @retval EFI_STRING Pointer to property name. > @retval NULL There is error. > @@ -335,6 +456,7 @@ GetRedfishSchemaInfo ( > **/ > EFI_STRING > GetPropertyFromConfigureLang ( > + IN EFI_STRING ResourceUri, > IN EFI_STRING ConfigureLang > ); >=20 > @@ -417,25 +539,6 @@ PropertyChecker ( > IN BOOLEAN ProvisionMode > ); >=20 > -/** > - > - Check and see if we need to do provisioning for this two properties. > - > - @param[in] PropertyBuffer1 Pointer to property instance 1. > - @param[in] PropertyBuffer2 Pointer to property instance 2. > - @param[in] ProvisionMode TRUE if we are in provision mode. FALSE > otherwise. > - > - @retval TRUE Provision is required. > - @retval FALSE Provision is not required. > - > -**/ > -BOOLEAN > -PropertyChecker2Parm ( > - IN VOID *PropertyBuffer1, > - IN VOID *PropertyBuffer2, > - IN BOOLEAN ProvisionMode > - ); > - > /** >=20 > Keep ETAG string and URI string in database. > @@ -450,7 +553,7 @@ PropertyChecker2Parm ( > EFI_STATUS > SetEtagWithUri ( > IN CHAR8 *EtagStr, > - IN CHAR8 *Uri > + IN EFI_STRING Uri > ); >=20 > /** > @@ -465,7 +568,396 @@ SetEtagWithUri ( > **/ > CHAR8 * > GetEtagWithUri ( > - IN CHAR8 *Uri > + IN EFI_STRING Uri > + ); > + > +/** > + > + Get @odata.id from give HTTP payload. It's call responsibility to rele= ase > returned buffer. > + > + @param[in] Payload HTTP payload > + > + @retval NULL Can not find @odata.id from given payl= oad. > + @retval Others odata.id string is returned. > + > +**/ > +EFI_STRING > +GetOdataId ( > + IN REDFISH_PAYLOAD *Payload > + ); > + > +/** > + > + Return config language from given URI and prperty name. It's call > responsibility to release returned buffer. > + > + @param[in] Uri The URI to match > + @param[in] PropertyName The property name of resource. This is > optional. > + > + @retval NULL Can not find redfish uri. > + @retval Other redfish uri is returned. > + > +**/ > +EFI_STRING > +GetConfigureLang ( > + IN CHAR8 *Uri, > + IN CHAR8 *PropertyName OPTIONAL > + ); > + > +/** > + > + Return redfish URI by given config language. It's call responsibility = to > release returned buffer. > + > + @param[in] ConfigLang ConfigLang to search. > + > + @retval NULL Can not find redfish uri. > + @retval Other redfish uri is returned. > + > +**/ > +EFI_STRING > +RedfishGetUri ( > + IN EFI_STRING ConfigLang > + ); > + > +/** > + > + Return config language by given URI. It's call responsibility to relea= se > returned buffer. > + > + @param[in] Uri Uri to search. > + > + @retval NULL Can not find redfish uri. > + @retval Other redfish uri is returned. > + > +**/ > +EFI_STRING > +RedfishGetConfigLanguage ( > + IN EFI_STRING Uri > + ); > + > +/** > + > + Convert Unicode string to ASCII string. It's call responsibility to re= lease > returned buffer. > + > + @param[in] UnicodeStr Unicode string to convert. > + > + @retval CHAR8 * ASCII string returned. > + @retval NULL Errors occur. > + > +**/ > +CHAR8 * > +StrUnicodeToAscii ( > + IN EFI_STRING UnicodeStr > + ); > + > +/** > + > + Convert ASCII string to Unicode string. It's call responsibility to re= lease > returned buffer. > + > + @param[in] AsciiStr ASCII string to convert. > + > + @retval EFI_STRING Unicode string returned. > + @retval NULL Errors occur. > + > +**/ > +EFI_STRING > +StrAsciiToUnicode ( > + IN CHAR8 *AsciiStr > + ); > + > +/** > + > + Check and see if ETAG is identical to what we keep in system. > + > + @param[in] Uri URI requested > + @param[in] EtagInHeader ETAG string returned from HTTP request. > + @param[in] EtagInJson ETAG string in JSON body. > + > + @retval TRUE ETAG is identical. > + @retval FALSE ETAG is changed. > + > +**/ > +BOOLEAN > +CheckEtag ( > + IN EFI_STRING Uri, > + IN CHAR8 *EtagInHeader, > + IN CHAR8 *EtagInJson > + ); > + > +/** > + > + Get the property string value in array type. > + > + @param[in] Schema Schema of this property. > + @param[in] Version Schema version. > + @param[in] PropertyName Property name. > + @param[in] ConfigureLang Configure Language of this property. > + @param[out] ArraySize The size of returned array. > + > + @retval CHAR8 ** Returned string array. NULL while error happ= ens. > + > +**/ > +CHAR8 ** > +GetPropertyStringArrayValue ( > + IN CHAR8 *Schema, > + IN CHAR8 *Version, > + IN EFI_STRING PropertyName, > + IN EFI_STRING ConfigureLang, > + OUT UINTN *ArraySize > + ); > + > +/** > + > + Get the property numeric value in array type. > + > + @param[in] Schema Schema of this property. > + @param[in] Version Schema version. > + @param[in] PropertyName Property name. > + @param[in] ConfigureLang Configure Language of this property. > + @param[out] ArraySize The size of returned array. > + > + @retval INT64 ** Returned integer array. NULL while error hap= pens. > + > +**/ > +INT64 * > +GetPropertyNumericArrayValue ( > + IN CHAR8 *Schema, > + IN CHAR8 *Version, > + IN EFI_STRING PropertyName, > + IN EFI_STRING ConfigureLang, > + OUT UINTN *ArraySize > + ); > + > +/** > + > + Get the property boolean value in array type. > + > + @param[in] Schema Schema of this property. > + @param[in] Version Schema version. > + @param[in] PropertyName Property name. > + @param[in] ConfigureLang Configure Language of this property. > + @param[out] ArraySize The size of returned array. > + > + @retval BOOLEAN * Returned boolean array. NULL while error > happens. > + > +**/ > +BOOLEAN * > +GetPropertyBooleanArrayValue ( > + IN CHAR8 *Schema, > + IN CHAR8 *Version, > + IN EFI_STRING PropertyName, > + IN EFI_STRING ConfigureLang, > + OUT UINTN *ArraySize > + ); > + > +/** > + > + Get the property value in the vague type. > + > + @param[in] Schema Schema of this property. > + @param[in] Version Schema version. > + @param[in] PropertyName Property name. > + @param[in] ConfigureLang Configure Language of this property. > + @param[out] NumberOfValues Return the number of vague type of > values > + > + @retval RedfishCS_EmptyProp_KeyValue The pointer to the structur= e > + of vague type of values. > + > +**/ > +RedfishCS_EmptyProp_KeyValue * > +GetPropertyVagueValue ( > + IN CHAR8 *Schema, > + IN CHAR8 *Version, > + IN EFI_STRING PropertyName, > + IN EFI_STRING ConfigureLang, > + OUT UINT32 *NumberOfValues > + ); > + > +/** > + > + Free the list of empty property key values. > + > + @param[in] EmptyPropKeyValueListHead The head of > RedfishCS_EmptyProp_KeyValue > + > +**/ > +VOID > +FreeEmptyPropKeyValueList ( > + RedfishCS_EmptyProp_KeyValue *EmptyPropKeyValueListHead > + ); > + > +/** > + > + Check and see if given property is in JSON context or not > + > + @param[in] Property Property name string > + @param[in] Json The JSON context to search. > + > + @retval TRUE Property is found in JSON context > + @retval FALSE Property is not in JSON context > + > +**/ > +BOOLEAN > +MatchPropertyWithJsonContext ( > + IN EFI_STRING Property, > + IN CHAR8 *Json > +); > + > +/** > + > + Create string array and append to arry node in Redfish JSON convert > format. > + > + @param[in,out] Head The head of string array. > + @param[in] StringArray Input string array. > + @param[in] ArraySize The size of StringArray. > + > + @retval EFI_SUCCESS String array is created successfully. > + @retval Others Error happens > + > +**/ > +EFI_STATUS > +AddRedfishCharArray ( > + IN OUT RedfishCS_char_Array **Head, > + IN CHAR8 **StringArray, > + IN UINTN ArraySize > + ); > + > +/** > + > + Create numeric array and append to arry node in Redfish JSON convert > format. > + > + @param[in,out] Head The head of string array. > + @param[in] NumericArray Input numeric array. > + @param[in] ArraySize The size of StringArray. > + > + @retval EFI_SUCCESS String array is created successfully. > + @retval Others Error happens > + > +**/ > +EFI_STATUS > +AddRedfishNumericArray ( > + IN OUT RedfishCS_int64_Array **Head, > + IN INT64 *NumericArray, > + IN UINTN ArraySize > + ); > + > +/** > + > + Create boolean array and append to arry node in Redfish JSON convert > format. > + > + @param[in,out] Head The head of string array. > + @param[in] BooleanArray Input boolean array. > + @param[in] ArraySize The size of BooleanArray. > + > + @retval EFI_SUCCESS String array is created successfully. > + @retval Others Error happens > + > +**/ > +EFI_STATUS > +AddRedfishBooleanArray ( > + IN OUT RedfishCS_bool_Array **Head, > + IN BOOLEAN *BooleanArray, > + IN UINTN ArraySize > + ); > +/** > + > + Check and see if value in Redfish string array are all the same as the= one > + from HII configuration. > + > + @param[in] Head The head of string array. > + @param[in] StringArray Input string array. > + @param[in] ArraySize The size of StringArray. > + > + @retval TRUE All string in Redfish array are as same as s= tring > + in HII configuration array. > + FALSE These two array are not identical. > + > +**/ > +BOOLEAN > +CompareRedfishStringArrayValues ( > + IN RedfishCS_char_Array *Head, > + IN CHAR8 **StringArray, > + IN UINTN ArraySize > + ); > + > +/** > + > + Check and see if value in Redfish numeric array are all the same as th= e one > + from HII configuration. > + > + @param[in] Head The head of Redfish CS numeraic array. > + @param[in] NumericArray Input numeric array. > + @param[in] ArraySize The size of NumericArray. > + > + @retval TRUE All string in Redfish array are as same as i= nteger > + in HII configuration array. > + FALSE These two array are not identical. > + > +**/ > +BOOLEAN > +CompareRedfishNumericArrayValues ( > + IN RedfishCS_int64_Array *Head, > + IN INT64 *NumericArray, > + IN UINTN ArraySize > + ); > + > +/** > + > + Check and see if value in Redfish boolean array are all the same as th= e one > + from HII configuration. > + > + @param[in] Head The head of Redfish CS boolean array. > + @param[in] BooleanArray Input boolean array. > + @param[in] ArraySize The size of BooleanArray. > + > + @retval TRUE All string in Redfish array are as same as i= nteger > + in HII configuration array. > + FALSE These two array are not identical. > + > +**/ > +BOOLEAN > +CompareRedfishBooleanArrayValues ( > + IN RedfishCS_bool_Array *Head, > + IN BOOLEAN *BooleanArray, > + IN UINTN ArraySize > + ); > + > +/** > + > + Check and see if any difference between two vague value set. > + This is just a simple check. > + > + @param[in] RedfishVagueKeyValuePtr The vague key value sets on > Redfish service. > + @param[in] RedfishVagueKeyValueNumber The numebr of vague key > value sets > + @param[in] ConfigVagueKeyValuePtr The vague configuration on > platform. > + @param[in] ConfigVagueKeyValueNumber The numebr of vague key > value sets > + > + @retval TRUE All values are the same. > + FALSE There is some difference. > + > +**/ > +BOOLEAN > +CompareRedfishPropertyVagueValues ( > + IN RedfishCS_EmptyProp_KeyValue *RedfishVagueKeyValuePtr, > + IN UINT32 RedfishVagueKeyValueNumber, > + IN RedfishCS_EmptyProp_KeyValue *ConfigVagueKeyValuePtr, > + IN UINT32 ConfigVagueKeyValueNumber > + ); > + > +/** > + > + Find "ETag" and "Location" from either HTTP header or Redfish response= . > + > + @param[in] Response HTTP response > + @param[out] Etag String buffer to return ETag > + @param[out] Location String buffer to return Location > + > + @retval EFI_SUCCESS Data is found and returned. > + @retval Others Errors occur. > + > +**/ > +EFI_STATUS > +GetEtagAndLocation ( > + IN REDFISH_RESPONSE *Response, > + OUT CHAR8 **Etag, OPTIONAL > + OUT EFI_STRING *Location OPTIONAL > ); >=20 > #endif > diff --git > a/RedfishClientPkg/Include/RedfishJsonStructure/RedfishCsCommon.h > b/RedfishClientPkg/Include/RedfishJsonStructure/RedfishCsCommon.h > new file mode 100644 > index 0000000000..4d0ae50fc8 > --- /dev/null > +++ b/RedfishClientPkg/Include/RedfishJsonStructure/RedfishCsCommon.h > @@ -0,0 +1,14 @@ > +/** @file > + Wrapper file for RedfishCsCommon.h > + > + (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP
> + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef WRAPPER_REDFISH_CS_COMMON_H_ > +#define WRAPPER_REDFISH_CS_COMMON_H_ > + > +#include "ConverterLib/include/RedfishCsCommon.h" > + > +#endif > diff --git > a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtility= Int > ernal.h > b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtility= Int > ernal.h > index 7d38d327ef..38d2af52b2 100644 > --- > a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtility= Int > ernal.h > +++ > b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtility= Int > ernal.h > @@ -1,7 +1,7 @@ > /** @file > Common header file for RedfishFeatureUtilityLib driver. >=20 > - (C) Copyright 2020-2021 Hewlett Packard Enterprise Development LP
> + (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP
>=20 > SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > @@ -11,33 +11,39 @@ > #define REDFISH_FEATURE_INTERNAL_H_ >=20 > #include > +#include > + > +#include >=20 > #include > #include > #include > #include > #include > -#include > -#include > #include > #include > #include > #include > #include > #include > +#include > +#include >=20 > #include >=20 > #include > +#include >=20 > #define INDEX_VARIABLE_SIZE 64 > #define INDEX_STRING_SIZE 16 > -#define IS_EMPTY_STRING(a) (a =3D=3D NULL || a[0] =3D=3D '\0') > #define INDEX_STRING L"{%d}" > #define SCHEMA_NAME_PREFIX "x-uefi-redfish-" > #define SCHEMA_NAME_PREFIX_OFFSET (AsciiStrLen > (SCHEMA_NAME_PREFIX)) > -#define REDFISH_SYSTEM_ROOT_PATH "/v1/Systems[UUID~%g]" > +#define REDFISH_ROOT_PATH "/v1" > +#define REDFISH_ROOT_PATH_UNICODE L"/v1" > #define MAX_CONF_LANG_LEN 128 > +#define MAX_REDFISH_URL_LEN 255 > +#define REGULAR_EXPRESSION_ARRAY L"\\[.*\\]/.*" >=20 > #define BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE > L"{" > #define BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_END_SIGNATURE > L"}" > diff --git > a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtility= Lib > .c > b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtility= Lib > .c > index cf8696e5f0..2bd7f58f9c 100644 > --- > a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtility= Lib > .c > +++ > b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtility= Lib > .c > @@ -1,7 +1,7 @@ > /** @file > Redfish feature utility library implementation >=20 > - (C) Copyright 2020-2021 Hewlett Packard Enterprise Development LP
> + (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP
>=20 > SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > @@ -9,7 +9,34 @@ >=20 > #include "RedfishFeatureUtilityInternal.h" >=20 > -EDKII_REDFISH_ETAG_PROTOCOL *mEtagProtocol; > +EDKII_REDFISH_ETAG_PROTOCOL *mEtagProtocol =3D NULL; > +EDKII_REDFISH_CONFIG_LANG_MAP_PROTOCOL > *mConfigLangMapProtocol =3D NULL; > + > + > +EFI_STATUS > +RedfishLocateProtocol ( [Chang, Abner]=20 The function header is missed. Abner > + IN VOID **ProtocolInstance, > + IN EFI_GUID *ProtocolGuid > + ) > +{ > + EFI_STATUS Status; > + > + if (ProtocolInstance =3D=3D NULL || ProtocolGuid =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + if (*ProtocolInstance !=3D NULL) { > + return EFI_SUCCESS; > + } > + > + Status =3D gBS->LocateProtocol ( > + ProtocolGuid, > + NULL, > + ProtocolInstance > + ); > + return Status; > +} > + >=20 > /** >=20 > @@ -71,227 +98,168 @@ GetArraykeyFromUri ( >=20 > /** >=20 > - Keep configure language with given key in UEFI variable. > + Keep ETAG string and URI string in database. >=20 > - @param[in] Schema Schema name. > - @param[in] Version Schema version. > - @param[in] Key Key string. > - @param[in] ConfigureLangIndex Index value. > + @param[in] EtagStr ETAG string. > + @param[in] Uri URI string. >=20 > - @retval EFI_SUCCESS Data is saved in UEFI variable. > - @retval Others Errors occur. > + @retval EFI_SUCCESS ETAG and URI are applied successfully. > + @retval Others Errors occur. >=20 > **/ > EFI_STATUS > -SetConfigureLangWithkey ( > - IN CHAR8 *Schema, > - IN CHAR8 *Version, > - IN CHAR8 *Key, > - IN UINTN ConfigureLangIndex > +SetEtagWithUri ( > + IN CHAR8 *EtagStr, > + IN EFI_STRING Uri > ) > { > - CHAR16 IndexString[INDEX_STRING_SIZE]; > - CHAR16 VarName[INDEX_VARIABLE_SIZE]; > - CHAR16 *VarData; > - EFI_STATUS Status; > - // > - // Variable content. > - // > - UnicodeSPrint (IndexString, sizeof (IndexString), INDEX_STRING, > ConfigureLangIndex); > + EFI_STATUS Status; > + CHAR8 *AsciiUri; >=20 > - // > - // Variable name. > - // > - UnicodeSPrint (VarName, sizeof (VarName), L"%a_%a_%a", Schema, > Version, Key); > + if (IS_EMPTY_STRING (EtagStr) || IS_EMPTY_STRING (Uri)) { > + return EFI_INVALID_PARAMETER; > + } >=20 > - // > - // Check if it exists already. > - // > - Status =3D GetVariable2 ( > - VarName, > - &gEfiCallerIdGuid, > - (VOID *)&VarData, > - NULL > - ); > - if (!EFI_ERROR (Status)) { > - DEBUG ((DEBUG_INFO, "%a, remove stale data: %s\n", __FUNCTION__, > VarData)); > - FreePool (VarData); > - gRT->SetVariable (VarName, &gEfiCallerIdGuid, > VARIABLE_ATTRIBUTE_NV_BS, 0, NULL); > + Status =3D RedfishLocateProtocol ((VOID **)&mEtagProtocol, > &gEdkIIRedfishETagProtocolGuid); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a, fail to locate > gEdkIIRedfishETagProtocolGuid: %r\n", __FUNCTION__, Status)); > + return Status; > } >=20 > - return gRT->SetVariable (VarName, &gEfiCallerIdGuid, > VARIABLE_ATTRIBUTE_NV_BS, StrSize (IndexString), (VOID *)&IndexString); > + AsciiUri =3D StrUnicodeToAscii (Uri); > + if (AsciiUri =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + mEtagProtocol->Set (mEtagProtocol, AsciiUri, EtagStr); > + mEtagProtocol->Flush (mEtagProtocol); > + > + FreePool (AsciiUri); > + > + return EFI_SUCCESS; > } >=20 > /** >=20 > - Find configure language with input key string. > + Find ETAG string that refers to given URI. >=20 > - @param[in] Schema Schema name. > - @param[in] Version Schema version. > - @param[in] Property Property name. > - @param[in] Key Key string. > + @param[in] Uri Target URI string. >=20 > - @retval CHAR16 * Corresponding configure langauge > - @retval NULL No configure language is found > + @retval CHAR8 * ETAG string > + @retval NULL No ETAG is found. >=20 > **/ > -CHAR16 * > -GetConfigureLangByKey ( > - IN CHAR8 *Schema, > - IN CHAR8 *Version, > - IN CHAR8 *Property, OPTIONAL > - IN CHAR8 *Key > +CHAR8 * > +GetEtagWithUri ( > + IN EFI_STRING Uri > ) > { > - EFI_STATUS Status; > - CHAR16 VariableName[64]; > - UINTN VariableSize; > - CHAR16 *CollectionIndex; > - CHAR16 *ConfigureLang; > - UINTN ConfigureLangLen; > + EFI_STATUS Status; > + CHAR8 *AsciiUri; > + CHAR8 *EtagStr; >=20 > - if (Schema =3D=3D NULL || Version =3D=3D NULL || Key =3D=3D NULL) { > + if (IS_EMPTY_STRING (Uri)) { > return NULL; > } >=20 > - CollectionIndex =3D NULL; > - ConfigureLang =3D NULL; > - > - UnicodeSPrint (VariableName, 64, L"%a_%a_%a", Schema, Version, Key); > - > - Status =3D GetVariable2 ( > - VariableName, > - &gEfiCallerIdGuid, > - (VOID *)&CollectionIndex, > - &VariableSize > - ); > + Status =3D RedfishLocateProtocol ((VOID **)&mEtagProtocol, > &gEdkIIRedfishETagProtocolGuid); > if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a, fail to locate > gEdkIIRedfishETagProtocolGuid: %r\n", __FUNCTION__, Status)); > return NULL; > } >=20 > - ConfigureLangLen =3D AsciiStrLen (Schema) + StrLen (CollectionIndex) + > (Property =3D=3D NULL ? 0 : AsciiStrLen (Property)) + 3 + 1; > - ConfigureLang =3D AllocatePool (sizeof (CHAR16) * ConfigureLangLen); > - ASSERT (ConfigureLang); > - > - if (Property !=3D NULL) { > - UnicodeSPrint (ConfigureLang, sizeof (CHAR16) * ConfigureLangLen, > L"/%a/%s/%a", Schema, CollectionIndex, Property); > - } else { > - UnicodeSPrint (ConfigureLang, sizeof (CHAR16) * ConfigureLangLen, > L"/%a/%s", Schema, CollectionIndex); > + AsciiUri =3D StrUnicodeToAscii (Uri); > + if (AsciiUri =3D=3D NULL) { > + return NULL; > } >=20 > - FreePool (CollectionIndex); > - > - return ConfigureLang; > -} > - > -/** > - > - Keep ETAG string and URI string in database. > - > - @param[in] EtagStr ETAG string. > - @param[in] Uri URI string. > - > - @retval EFI_SUCCESS ETAG and URI are applied successfully. > - @retval Others Errors occur. > - > -**/ > -EFI_STATUS > -SetEtagWithUri ( > - IN CHAR8 *EtagStr, > - IN CHAR8 *Uri > - ) > -{ > - EFI_STATUS Status; > + Status =3D mEtagProtocol->Get (mEtagProtocol, AsciiUri, &EtagStr); >=20 > - if (IS_EMPTY_STRING (EtagStr) || IS_EMPTY_STRING (Uri)) { > - return EFI_INVALID_PARAMETER; > - } > + FreePool (AsciiUri); >=20 > - if (mEtagProtocol =3D=3D NULL) { > - Status =3D gBS->LocateProtocol ( > - &gEdkIIRedfishETagProtocolGuid, > - NULL, > - (VOID **)&mEtagProtocol > - ); > - if (EFI_ERROR (Status)) { > - return Status; > - } > + if (EFI_ERROR (Status)) { > + return NULL; > } >=20 > - mEtagProtocol->Set (mEtagProtocol, Uri, EtagStr); > - mEtagProtocol->Flush (mEtagProtocol); > - > - return EFI_SUCCESS; > + return EtagStr; > } >=20 > /** >=20 > - Find ETAG string that refers to given URI. > + Convert Unicode string to ASCII string. It's call responsibility to re= lease > returned buffer. >=20 > - @param[in] Uri Target URI string. > + @param[in] UnicodeStr Unicode string to convert. >=20 > - @retval CHAR8 * ETAG string > - @retval NULL No ETAG is found. > + @retval CHAR8 * ASCII string returned. > + @retval NULL Errors occur. >=20 > **/ > CHAR8 * > -GetEtagWithUri ( > - IN CHAR8 *Uri > +StrUnicodeToAscii ( > + IN EFI_STRING UnicodeStr > ) > { > - EFI_STATUS Status; > - CHAR8 *EtagStr; > + CHAR8 *AsciiStr; > + UINTN AsciiStrSize; > + EFI_STATUS Status; >=20 > - if (IS_EMPTY_STRING (Uri)) { > + if (IS_EMPTY_STRING (UnicodeStr)) { > return NULL; > } >=20 > - if (mEtagProtocol =3D=3D NULL) { > - Status =3D gBS->LocateProtocol ( > - &gEdkIIRedfishETagProtocolGuid, > - NULL, > - (VOID **)&mEtagProtocol > - ); > - if (EFI_ERROR (Status)) { > - return NULL; > - } > + AsciiStrSize =3D StrLen (UnicodeStr) + 1; > + AsciiStr =3D AllocatePool (AsciiStrSize); > + if (AsciiStr =3D=3D NULL) { > + return NULL; > } >=20 > - Status =3D mEtagProtocol->Get (mEtagProtocol, Uri, &EtagStr); > + Status =3D UnicodeStrToAsciiStrS (UnicodeStr, AsciiStr, AsciiStrSize); > if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "UnicodeStrToAsciiStrS failed: %r\n", Status)); > + FreePool (AsciiStr); > return NULL; > } >=20 > - return EtagStr; > + return AsciiStr; > } >=20 > /** >=20 > - Convert HII string value to string value in JSON format. > + Convert ASCII string to Unicode string. It's call responsibility to re= lease > returned buffer. >=20 > - @param[in] HiiStringValue String in HII format. > + @param[in] AsciiStr ASCII string to convert. >=20 > - @retval CHAR8 * String in JSON format. > + @retval EFI_STRING Unicode string returned. > @retval NULL Errors occur. >=20 > **/ > -CHAR8 * > -ConvertHiiStringValueToJsonStringValue ( > - IN EFI_STRING HiiStringValue > +EFI_STRING > +StrAsciiToUnicode ( > + IN CHAR8 *AsciiStr > ) > { > - CHAR8 *JsonValue; > - UINTN JsonValueSize; > + EFI_STRING UnicodeStr; > + UINTN UnicodeStrSize; > + EFI_STATUS Status; >=20 > - if (IS_EMPTY_STRING (HiiStringValue)) { > + if (IS_EMPTY_STRING (AsciiStr)) { > return NULL; > } >=20 > - JsonValueSize =3D StrLen (HiiStringValue) + 1; > - JsonValue =3D AllocatePool (JsonValueSize); > - UnicodeStrToAsciiStrS (HiiStringValue, JsonValue, JsonValueSize); > + UnicodeStrSize =3D (AsciiStrLen (AsciiStr) + 1) * sizeof (CHAR16); > + UnicodeStr =3D AllocatePool (UnicodeStrSize); > + if (UnicodeStr =3D=3D NULL) { > + return NULL; > + } > + > + Status =3D AsciiStrToUnicodeStrS (AsciiStr, UnicodeStr, UnicodeStrSize= ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "t failed: %r\n", Status)); > + FreePool (UnicodeStr); > + return NULL; > + } >=20 > - return JsonValue; > + return UnicodeStr; > } >=20 > /** > @@ -480,997 +448,2979 @@ ApplyFeatureSettingsBooleanType ( >=20 > /** >=20 > - Read redfish resource by given resource path. > + Apply property value to UEFI HII database in vague type. >=20 > - @param[in] Service Redfish srvice instacne to make query. > - @param[in] ResourcePath Target resource path. > - @param[out] Response HTTP response from redfish service. > + @param[in] Schema Property schema. > + @param[in] Version Property schema version. > + @param[in] ConfigureLang Configure language refers to this property= . > + @param[in] VagueValuePtr Pointer of vague values to to set. > + @param[in] NumVagueValues Number of vague values. >=20 > - @retval EFI_SUCCESS Resrouce is returned successfully. > + @retval EFI_SUCCESS New value is applied successfully. > @retval Others Errors occur. >=20 > **/ > EFI_STATUS > -GetResourceByPath ( > - IN REDFISH_SERVICE *Service, > - IN CHAR8 *ResourcePath, > - OUT REDFISH_RESPONSE *Response > +ApplyFeatureSettingsVagueType ( > + IN CHAR8 *Schema, > + IN CHAR8 *Version, > + IN EFI_STRING ConfigureLang, > + IN RedfishCS_EmptyProp_KeyValue *VagueValuePtr, > + IN UINT32 NumberOfVagueValues > ) > { > - EFI_STATUS Status; > - > - if (Service =3D=3D NULL || Response =3D=3D NULL || IS_EMPTY_STRING > (ResourcePath)) { > + EFI_STATUS Status; > + UINTN StrSize; > + CHAR8 *ConfigureLangAscii; > + CHAR8 *ConfigureLangKeyAscii; > + EFI_STRING ConfigureKeyLang; > + EDKII_REDFISH_VALUE RedfishValue; > + EDKII_REDFISH_VALUE_TYPES PropertyDatatype; > + RedfishCS_EmptyProp_KeyValue *CurrentVagueValuePtr; > + > + if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || > IS_EMPTY_STRING (ConfigureLang) || VagueValuePtr =3D=3D NULL || > NumberOfVagueValues =3D=3D 0) { > return EFI_INVALID_PARAMETER; > } >=20 > - // > - // Get resource from redfish service. > - // > - Status =3D RedfishGetByService ( > - Service, > - ResourcePath, > - Response > - ); > + ConfigureLangAscii =3D AllocatePool (StrLen (ConfigureLang) + 1); > + if (ConfigureLangAscii =3D=3D NULL) { > + Status =3D EFI_OUT_OF_RESOURCES; > + DEBUG ((DEBUG_ERROR, "%a, Allocate memory for generate > ConfigureLang of vague key of %a.%a %s failed: %r\n", __FUNCTION__, > Schema, Version, ConfigureLang, Status)); > + return Status; > + } > + Status =3D UnicodeStrToAsciiStrS (ConfigureLang, ConfigureLangAscii, S= trLen > (ConfigureLang) + 1); > if (EFI_ERROR (Status)) { > - DEBUG ((DEBUG_ERROR, "%a, RedfishGetByService to %a failed: %r\n", > __FUNCTION__, ResourcePath, Status)); > - if (Response->Payload !=3D NULL) { > - RedfishDumpPayload (Response->Payload); > - RedfishFreeResponse ( > - NULL, > - 0, > - NULL, > - Response->Payload > - ); > - Response->Payload =3D NULL; > - } > - > + DEBUG ((DEBUG_ERROR, "%a, Convert the configureLang of vague key of > %a.%a %s failed: %r\n", __FUNCTION__, Schema, Version, ConfigureLang, > Status)); > return Status; > } >=20 > + CurrentVagueValuePtr =3D VagueValuePtr; > + while (CurrentVagueValuePtr !=3D NULL) { > + // > + // Generate ConfigureLang with the key name > + // > + //ConfigureKeyLang =3D GetConfigureLang (ConfigureLangAscii, > CurrentVagueValuePtr->KeyNamePtr); > + StrSize =3D AsciiStrLen (ConfigureLangAscii) + AsciiStrLen > (CurrentVagueValuePtr->KeyNamePtr) + 2; > + ConfigureLangKeyAscii =3D AllocateZeroPool (StrSize); > + ConfigureKeyLang =3D AllocateZeroPool (StrSize * sizeof (CHAR16)); > + if (ConfigureLangKeyAscii =3D=3D NULL || ConfigureKeyLang =3D=3D NUL= L) { > + DEBUG ((DEBUG_ERROR, "%a, Generate ConfigureLang of vague key of > %a.%a %s %a failed!\n", __FUNCTION__, Schema, Version, ConfigureLang, > CurrentVagueValuePtr->KeyNamePtr)); > + goto ErrorContinue; > + } > + AsciiStrCatS(ConfigureLangKeyAscii, StrSize, ConfigureLangAscii); > + AsciiStrCatS(ConfigureLangKeyAscii, StrSize, "/"); > + AsciiStrCatS(ConfigureLangKeyAscii, StrSize, CurrentVagueValuePtr- > >KeyNamePtr); > + AsciiStrToUnicodeStrS(ConfigureLangKeyAscii, ConfigureKeyLang, StrSi= ze); > + FreePool (ConfigureLangKeyAscii); > + ConfigureLangKeyAscii =3D NULL; > + // > + // Initial property data type and value. > + // > + if (CurrentVagueValuePtr->Value->DataType =3D=3D > RedfishCS_Vague_DataType_String) { > + PropertyDatatype =3D REDFISH_VALUE_TYPE_STRING; > + } else if (CurrentVagueValuePtr->Value->DataType =3D=3D > RedfishCS_Vague_DataType_Bool) { > + PropertyDatatype =3D REDFISH_VALUE_TYPE_BOOLEAN; > + } else if (CurrentVagueValuePtr->Value->DataType =3D=3D > RedfishCS_Vague_DataType_Int64) { > + PropertyDatatype =3D REDFISH_VALUE_TYPE_INTEGER; > + } else { > + DEBUG((DEBUG_ERROR, "%a, %a.%a %s Unsupported Redfish property > data type\n", __FUNCTION__, Schema, Version, ConfigureLang)); > + goto ErrorContinue; > + } > + > + // > + // Get the current value from HII > + // > + Status =3D RedfishPlatformConfigGetValue (Schema, Version, > ConfigureKeyLang, &RedfishValue); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a, %a.%a %s failed: %r\n", __FUNCTION__, > Schema, Version, ConfigureKeyLang, Status)); > + } else { > + if (RedfishValue.Type !=3D PropertyDatatype) { > + DEBUG((DEBUG_ERROR, "%a, %a.%a %s mismatched data type\n", > __FUNCTION__, Schema, Version, ConfigureKeyLang)); > + goto ErrorContinue; > + } > + if (PropertyDatatype =3D=3D REDFISH_VALUE_TYPE_STRING) { > + // > + // This is a string property. > + // > + if (AsciiStrCmp (CurrentVagueValuePtr->Value->DataValue.CharPtr, > RedfishValue.Value.Buffer) !=3D 0) { > + // > + // Apply settings from redfish > + // > + DEBUG ((DEBUG_INFO, "%a, %a.%a apply %s from %a to %a\n", > __FUNCTION__, Schema, Version, ConfigureKeyLang, > RedfishValue.Value.Buffer, CurrentVagueValuePtr->Value- > >DataValue.CharPtr)); > + FreePool (RedfishValue.Value.Buffer); > + RedfishValue.Value.Buffer =3D CurrentVagueValuePtr->Value- > >DataValue.CharPtr; > + Status =3D RedfishPlatformConfigSetValue (Schema, Version, > ConfigureKeyLang, RedfishValue); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a, apply %a to %a failed: %r\n", > __FUNCTION__, ConfigureKeyLang, CurrentVagueValuePtr->Value- > >DataValue.CharPtr, Status)); > + } > + } else { > + DEBUG ((DEBUG_INFO, "%a, %a.%a %s value is: %a\n", > __FUNCTION__, Schema, Version, ConfigureKeyLang, > RedfishValue.Value.Buffer, Status)); > + } > + } else if (PropertyDatatype =3D=3D REDFISH_VALUE_TYPE_BOOLEAN) { > + // > + // This is a boolean property. > + // > + if (RedfishValue.Value.Boolean !=3D *CurrentVagueValuePtr->Value= - > >DataValue.BoolPtr) { > + // > + // Apply settings from redfish > + // > + DEBUG ((DEBUG_INFO, "%a, %a.%a apply %s from %a to %a\n", > + __FUNCTION__, > + Schema, > + Version, > + ConfigureKeyLang, > + (RedfishValue.Value.Boolean ? "True" : "False"), > + (*CurrentVagueValuePtr->Value->DataValue.BoolPtr ? "Tr= ue" : > "False"))); > + > + RedfishValue.Value.Boolean =3D (BOOLEAN)*CurrentVagueValuePtr- > >Value->DataValue.BoolPtr; > + Status =3D RedfishPlatformConfigSetValue (Schema, Version, > ConfigureKeyLang, RedfishValue); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a, apply %s to %a failed: %r\n", > __FUNCTION__, ConfigureKeyLang, (*CurrentVagueValuePtr->Value- > >DataValue.BoolPtr ? "True" : "False"), Status)); > + } > + } else { > + DEBUG ((DEBUG_INFO, "%a, %a.%a %s value is: %a\n", > __FUNCTION__, Schema, Version, ConfigureKeyLang, > (RedfishValue.Value.Boolean ? "True" : "False"), Status)); > + } > + } else if (PropertyDatatype =3D=3D REDFISH_VALUE_TYPE_INTEGER) { > + // > + // This is a integer property. > + // > + if (RedfishValue.Value.Integer !=3D *CurrentVagueValuePtr->Value= - > >DataValue.Int64Ptr) { > + // > + // Apply settings from redfish > + // > + DEBUG ((DEBUG_INFO, "%a, %a.%a apply %s from 0x%x to 0x%x\n", > __FUNCTION__, Schema, Version, ConfigureKeyLang, > RedfishValue.Value.Integer, *CurrentVagueValuePtr->Value- > >DataValue.Int64Ptr)); > + > + RedfishValue.Value.Integer =3D (INT64)*CurrentVagueValuePtr->V= alue- > >DataValue.Int64Ptr; > + Status =3D RedfishPlatformConfigSetValue (Schema, Version, > ConfigureKeyLang, RedfishValue); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a, apply %s to 0x%x failed: %r\n", > __FUNCTION__, ConfigureKeyLang, *CurrentVagueValuePtr->Value- > >DataValue.Int64Ptr, Status)); > + } > + } else { > + DEBUG ((DEBUG_INFO, "%a, %a.%a %s value is: 0x%x\n", > __FUNCTION__, Schema, Version, ConfigureKeyLang, > RedfishValue.Value.Integer, Status)); > + } > + } else { > + DEBUG((DEBUG_ERROR, "%a, %a.%a %s Unsupported Redfish property > data type\n", __FUNCTION__, Schema, Version, ConfigureLang)); > + goto ErrorContinue; > + } > + } > + > +ErrorContinue:; > + if (ConfigureLangKeyAscii !=3D NULL) { > + FreePool (ConfigureLangKeyAscii); > + ConfigureLangKeyAscii =3D NULL; > + } > + if (ConfigureKeyLang !=3D NULL) { > + FreePool (ConfigureKeyLang); > + ConfigureKeyLang =3D NULL; > + } > + CurrentVagueValuePtr =3D CurrentVagueValuePtr->NextKeyValuePtr; > + }; > + > + if (ConfigureLangAscii !=3D NULL) { > + FreePool (ConfigureLangAscii); > + } > + if (ConfigureLangKeyAscii !=3D NULL) { > + FreePool (ConfigureLangKeyAscii); > + } > + if (ConfigureKeyLang !=3D NULL) { > + FreePool (ConfigureKeyLang); > + } > return EFI_SUCCESS; > } >=20 > /** >=20 > - Find array index from given configure language string. > - > - @param[in] ConfigureLang Configure language string to parse. > - @param[out] UnifiedConfigureLang The configure language in array. > - @param[out] Index The array index number. > + Release the memory in RedfishValue while value type is array. >=20 > - @retval EFI_SUCCESS Index is found. > - @retval Others Errors occur. > + @param[in] RedfishValue Pointer to Redfish value >=20 > **/ > -EFI_STATUS > -GetArrayIndexFromArrayTypeConfigureLang ( > - IN CHAR16 *ConfigureLang, > - OUT CHAR16 **UnifiedConfigureLang, > - OUT UINTN *Index > +VOID > +FreeArrayTypeRedfishValue ( > + EDKII_REDFISH_VALUE *RedfishValue > ) > { > - CHAR16 *TmpConfigureLang; > - CHAR16 *IndexString; > - CHAR16 *TmpString; > - > - if (ConfigureLang =3D=3D NULL || UnifiedConfigureLang =3D=3D NULL || I= ndex =3D=3D > NULL) { > - return EFI_INVALID_PARAMETER; > - } > - > - TmpConfigureLang =3D AllocateCopyPool (StrSize (ConfigureLang), > ConfigureLang); > - if (TmpConfigureLang =3D=3D NULL) { > - return EFI_OUT_OF_RESOURCES; > - } > + UINTN Index; >=20 > - // > - // looking for index signature "{"" > - // > - IndexString =3D StrStr (TmpConfigureLang, > BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE); > - if (IndexString =3D=3D NULL) { > - return EFI_NOT_FOUND; > + if (RedfishValue =3D=3D NULL) { > + return; > } >=20 > - // > - // Skip "{" > - // > - TmpString =3D IndexString + StrLen > (BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE); > - > - // > - // Looking for "}" > - // > - TmpString =3D StrStr (TmpString, > BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_END_SIGNATURE); > - if (TmpString =3D=3D NULL) { > - return EFI_NOT_FOUND; > + if (RedfishValue->Type !=3D REDFISH_VALUE_TYPE_INTEGER_ARRAY && > RedfishValue->Type !=3D REDFISH_VALUE_TYPE_STRING_ARRAY) { > + return; > } >=20 > - // > - // Append '\0' for converting decimal string to integer. > - // > - TmpString[0] =3D '\0'; > + switch (RedfishValue->Type) { > + case REDFISH_VALUE_TYPE_STRING_ARRAY: > + for (Index =3D 0; Index < RedfishValue->ArrayCount; Index++) { > + FreePool (RedfishValue->Value.StringArray[Index]); > + } > + FreePool (RedfishValue->Value.StringArray); > + RedfishValue->Value.StringArray =3D NULL; > + break; >=20 > - // > - // Convert decimal string to integer > - // > - *Index =3D StrDecimalToUintn (IndexString + StrLen > (BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE)); > + case REDFISH_VALUE_TYPE_INTEGER_ARRAY: > + FreePool (RedfishValue->Value.IntegerArray); > + RedfishValue->Value.IntegerArray =3D NULL; > + break; >=20 > - // > - // Resotre the '}' character and remove rest of string. > - // > - TmpString[0] =3D L'}'; > - TmpString[1] =3D '\0'; > + case REDFISH_VALUE_TYPE_BOOLEAN_ARRAY: > + FreePool (RedfishValue->Value.BooleanArray); > + RedfishValue->Value.BooleanArray =3D NULL; > + break; >=20 > - *UnifiedConfigureLang =3D TmpConfigureLang; > + default: > + return; > + } >=20 > - return EFI_SUCCESS; > + RedfishValue->ArrayCount =3D 0; > } >=20 > + > /** >=20 > - Search HII database with given Configure Language pattern. Data is han= dled > and > - returned in array. > + Apply property value to UEFI HII database in string array type. >=20 > - @param[in] Schema The schema to search. > - @param[in] Version The schema version. > - @param[in] Pattern Configure Language pattern to se= arch. > - @param[out] UnifiedConfigureLangList The data returned by HII databas= e. > + @param[in] Schema Property schema. > + @param[in] Version Property schema version. > + @param[in] ConfigureLang Configure language refers to this property. > + @param[in] ArrayHead Head of array value. >=20 > - @retval EFI_SUCCESS Data is found and returned. > + @retval EFI_SUCCESS New value is applied successfully. > @retval Others Errors occur. >=20 > **/ > EFI_STATUS > -RedfishFeatureGetUnifiedArrayTypeConfigureLang ( > - IN CHAR8 *Schema, > - IN CHAR8 *Version, > - IN EFI_STRING Pattern, OPTIONAL > - OUT REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST > *UnifiedConfigureLangList > +ApplyFeatureSettingsStringArrayType ( > + IN CHAR8 *Schema, > + IN CHAR8 *Version, > + IN EFI_STRING ConfigureLang, > + IN RedfishCS_char_Array *ArrayHead > ) > { > - EFI_STATUS Status; > - EFI_STRING *ConfigureLangList; > - UINTN Count; > - UINTN Index; > - UINTN Index2; > - UINTN ArrayIndex; > - EFI_STRING UnifiedConfigureLang; > - BOOLEAN Duplicated; > - REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG > UnifiedConfigureLangPool[BIOS_CONFIG_TO_REDFISH_REDPATH_POOL_SIZ > E]; > + EFI_STATUS Status; > + EDKII_REDFISH_VALUE RedfishValue; > + UINTN Index; > + RedfishCS_char_Array *Buffer; >=20 > - if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || > UnifiedConfigureLangList =3D=3D NULL) { > + if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || > IS_EMPTY_STRING (ConfigureLang) || ArrayHead =3D=3D NULL) { > return EFI_INVALID_PARAMETER; > } >=20 > - UnifiedConfigureLangList->Count =3D 0; > - UnifiedConfigureLangList->List =3D NULL; > - ZeroMem (UnifiedConfigureLangPool, sizeof (UnifiedConfigureLangPool)); > - > - Status =3D RedfishPlatformConfigGetConfigureLang (Schema, Version, > Pattern, &ConfigureLangList, &Count); > + // > + // Get the current value from HII > + // > + Status =3D RedfishPlatformConfigGetValue (Schema, Version, ConfigureLa= ng, > &RedfishValue); > if (EFI_ERROR (Status)) { > - DEBUG ((DEBUG_ERROR, "%a, RedfishFeatureGetConfigureLangRegex > failed: %r\n", __FUNCTION__, Status)); > - return Status; > - } > + DEBUG ((DEBUG_ERROR, "%a, %a.%a %s failed: %r\n", __FUNCTION__, > Schema, Version, ConfigureLang, Status)); > + } else { >=20 > - if (Count =3D=3D 0) { > - return EFI_NOT_FOUND; > + if (RedfishValue.Type !=3D REDFISH_VALUE_TYPE_STRING_ARRAY) { > + DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string array > type\n", __FUNCTION__, Schema, Version, ConfigureLang)); > + return EFI_DEVICE_ERROR; > + } > + > + // > + // If there is no change in array, do nothing > + // > + if (!CompareRedfishStringArrayValues (ArrayHead, > RedfishValue.Value.StringArray, RedfishValue.ArrayCount)) { > + // > + // Apply settings from redfish > + // > + DEBUG ((DEBUG_INFO, "%a, %a.%a apply %s for array\n", > __FUNCTION__, Schema, Version, ConfigureLang)); > + FreeArrayTypeRedfishValue (&RedfishValue); > + > + // > + // Convert array from RedfishCS_char_Array to EDKII_REDFISH_VALUE > + // > + RedfishValue.ArrayCount =3D 0; > + Buffer =3D ArrayHead; > + while (Buffer !=3D NULL) { > + RedfishValue.ArrayCount +=3D 1; > + Buffer =3D Buffer->Next; > + } > + > + // > + // Allocate pool for new values > + // > + RedfishValue.Value.StringArray =3D AllocatePool > (RedfishValue.ArrayCount *sizeof (CHAR8 *)); > + if (RedfishValue.Value.StringArray =3D=3D NULL) { > + ASSERT (FALSE); > + return EFI_OUT_OF_RESOURCES; > + } > + > + Buffer =3D ArrayHead; > + Index =3D 0; > + while (Buffer !=3D NULL) { > + RedfishValue.Value.StringArray[Index] =3D AllocateCopyPool (Asci= iStrSize > (Buffer->ArrayValue), Buffer->ArrayValue); > + if (RedfishValue.Value.StringArray[Index] =3D=3D NULL) { > + ASSERT (FALSE); > + return EFI_OUT_OF_RESOURCES; > + } > + Buffer =3D Buffer->Next; > + Index++; > + } > + > + ASSERT (Index <=3D RedfishValue.ArrayCount); > + > + Status =3D RedfishPlatformConfigSetValue (Schema, Version, > ConfigureLang, RedfishValue); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a, apply %s array failed: %r\n", > __FUNCTION__, ConfigureLang, Status)); > + } > + } else { > + DEBUG ((DEBUG_ERROR, "%a, %a.%a %s array value has no change\n", > __FUNCTION__, Schema, Version, ConfigureLang)); > + } > } >=20 > - for (Index =3D 0; Index < Count; Index++) { > - Status =3D GetArrayIndexFromArrayTypeConfigureLang > (ConfigureLangList[Index], &UnifiedConfigureLang, &ArrayIndex); > - if (EFI_ERROR (Status)) { > - ASSERT (FALSE); > - continue; > + return Status; > +} > + > +/** > + > + Apply property value to UEFI HII database in numeric array type (INT64= ). > + > + @param[in] Schema Property schema. > + @param[in] Version Property schema version. > + @param[in] ConfigureLang Configure language refers to this property. > + @param[in] ArrayHead Head of array value. > + > + @retval EFI_SUCCESS New value is applied successfully. > + @retval Others Errors occur. > + > +**/ > +EFI_STATUS > +ApplyFeatureSettingsNumericArrayType ( > + IN CHAR8 *Schema, > + IN CHAR8 *Version, > + IN EFI_STRING ConfigureLang, > + IN RedfishCS_int64_Array *ArrayHead > + ) > +{ > + EFI_STATUS Status; > + EDKII_REDFISH_VALUE RedfishValue; > + UINTN Index; > + RedfishCS_int64_Array *Buffer; > + > + if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || > IS_EMPTY_STRING (ConfigureLang) || ArrayHead =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // Get the current value from HII > + // > + Status =3D RedfishPlatformConfigGetValue (Schema, Version, ConfigureLa= ng, > &RedfishValue); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a, %a.%a %s failed: %r\n", __FUNCTION__, > Schema, Version, ConfigureLang, Status)); > + } else { > + > + if (RedfishValue.Type !=3D REDFISH_VALUE_TYPE_INTEGER_ARRAY) { > + DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string array type\= n", > __FUNCTION__, Schema, Version, ConfigureLang)); > + return EFI_DEVICE_ERROR; > } >=20 > // > - // Check if this configure language is duplicated. > + // If there is no change in array, do nothing > // > - Duplicated =3D FALSE; > - for (Index2 =3D 0; Index2 < > BIOS_CONFIG_TO_REDFISH_REDPATH_POOL_SIZE; Index2++) { > - if (UnifiedConfigureLangPool[Index2].ConfigureLang =3D=3D NULL) { > - break; > + if (!CompareRedfishNumericArrayValues (ArrayHead, > RedfishValue.Value.IntegerArray, RedfishValue.ArrayCount)) { > + // > + // Apply settings from redfish > + // > + DEBUG ((DEBUG_INFO, "%a, %a.%a apply %s for array\n", > __FUNCTION__, Schema, Version, ConfigureLang)); > + FreeArrayTypeRedfishValue (&RedfishValue); > + > + // > + // Convert array from RedfishCS_int64_Array to EDKII_REDFISH_VALUE > + // > + RedfishValue.ArrayCount =3D 0; > + Buffer =3D ArrayHead; > + while (Buffer !=3D NULL) { > + RedfishValue.ArrayCount +=3D 1; > + Buffer =3D Buffer->Next; > + } > + > + // > + // Allocate pool for new values > + // > + RedfishValue.Value.IntegerArray =3D AllocatePool > (RedfishValue.ArrayCount * sizeof (INT64)); > + if (RedfishValue.Value.IntegerArray =3D=3D NULL) { > + ASSERT (FALSE); > + return EFI_OUT_OF_RESOURCES; > + } > + > + Buffer =3D ArrayHead; > + Index =3D 0; > + while (Buffer !=3D NULL) { > + RedfishValue.Value.IntegerArray[Index] =3D (INT64)*Buffer->Array= Value; > + Buffer =3D Buffer->Next; > + Index++; > + } > + > + ASSERT (Index <=3D RedfishValue.ArrayCount); > + > + Status =3D RedfishPlatformConfigSetValue (Schema, Version, > ConfigureLang, RedfishValue); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a, apply %s array failed: %r\n", > __FUNCTION__, ConfigureLang, Status)); > + } > + } else { > + DEBUG ((DEBUG_ERROR, "%a, %a.%a %s array value has no change\n", > __FUNCTION__, Schema, Version, ConfigureLang)); > + } > + } > + > + return Status; > +} > + > +/** > + > + Apply property value to UEFI HII database in boolean array type (INT64= ). > + > + @param[in] Schema Property schema. > + @param[in] Version Property schema version. > + @param[in] ConfigureLang Configure language refers to this property. > + @param[in] ArrayHead Head of Redfich CS boolean array value. > + > + @retval EFI_SUCCESS New value is applied successfully. > + @retval Others Errors occur. > + > +**/ > +EFI_STATUS > +ApplyFeatureSettingsBooleanArrayType ( > + IN CHAR8 *Schema, > + IN CHAR8 *Version, > + IN EFI_STRING ConfigureLang, > + IN RedfishCS_bool_Array *ArrayHead > + ) > +{ > + EFI_STATUS Status; > + EDKII_REDFISH_VALUE RedfishValue; > + UINTN Index; > + RedfishCS_bool_Array *Buffer; > + > + if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || > IS_EMPTY_STRING (ConfigureLang) || ArrayHead =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // Get the current value from HII > + // > + Status =3D RedfishPlatformConfigGetValue (Schema, Version, ConfigureLa= ng, > &RedfishValue); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a, %a.%a %s failed: %r\n", __FUNCTION__, > Schema, Version, ConfigureLang, Status)); > + } else { > + > + if (RedfishValue.Type !=3D REDFISH_VALUE_TYPE_BOOLEAN_ARRAY) { > + DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string array type\= n", > __FUNCTION__, Schema, Version, ConfigureLang)); > + return EFI_DEVICE_ERROR; > + } > + > + // > + // If there is no change in array, do nothing > + // > + if (!CompareRedfishBooleanArrayValues (ArrayHead, > RedfishValue.Value.BooleanArray, RedfishValue.ArrayCount)) { > + // > + // Apply settings from redfish > + // > + DEBUG ((DEBUG_INFO, "%a, %a.%a apply %s for array\n", > __FUNCTION__, Schema, Version, ConfigureLang)); > + FreeArrayTypeRedfishValue (&RedfishValue); > + > + // > + // Convert array from RedfishCS_int64_Array to EDKII_REDFISH_VALUE > + // > + RedfishValue.ArrayCount =3D 0; > + Buffer =3D ArrayHead; > + while (Buffer !=3D NULL) { > + RedfishValue.ArrayCount +=3D 1; > + Buffer =3D Buffer->Next; > + } > + > + // > + // Allocate pool for new values > + // > + RedfishValue.Value.BooleanArray =3D AllocatePool > (RedfishValue.ArrayCount * sizeof (BOOLEAN)); > + if (RedfishValue.Value.BooleanArray =3D=3D NULL) { > + ASSERT (FALSE); > + return EFI_OUT_OF_RESOURCES; > + } > + > + Buffer =3D ArrayHead; > + Index =3D 0; > + while (Buffer !=3D NULL) { > + RedfishValue.Value.BooleanArray[Index] =3D (BOOLEAN)*Buffer- > >ArrayValue; > + Buffer =3D Buffer->Next; > + Index++; > + } > + > + ASSERT (Index <=3D RedfishValue.ArrayCount); > + > + Status =3D RedfishPlatformConfigSetValue (Schema, Version, > ConfigureLang, RedfishValue); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a, apply %s array failed: %r\n", > __FUNCTION__, ConfigureLang, Status)); > + } > + } else { > + DEBUG ((DEBUG_ERROR, "%a, %a.%a %s array value has no change\n", > __FUNCTION__, Schema, Version, ConfigureLang)); > + } > + } > + > + return Status; > +} > + > +/** > + > + Read redfish resource by given resource URI. > + > + @param[in] Service Redfish srvice instacne to make query. > + @param[in] ResourceUri Target resource URI. > + @param[out] Response HTTP response from redfish service. > + > + @retval EFI_SUCCESS Resrouce is returned successfully. > + @retval Others Errors occur. > + > +**/ > +EFI_STATUS > +GetResourceByUri ( > + IN REDFISH_SERVICE *Service, > + IN EFI_STRING ResourceUri, > + OUT REDFISH_RESPONSE *Response > + ) > +{ > + EFI_STATUS Status; > + CHAR8 *AsciiResourceUri; > + > + if (Service =3D=3D NULL || Response =3D=3D NULL || IS_EMPTY_STRING > (ResourceUri)) { > + return EFI_INVALID_PARAMETER; > + } > + > + AsciiResourceUri =3D StrUnicodeToAscii (ResourceUri); > + if (AsciiResourceUri =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + // > + // Get resource from redfish service. > + // > + Status =3D RedfishGetByUri ( > + Service, > + AsciiResourceUri, > + Response > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a, RedfishGetByUri to %a failed: %r\n", > __FUNCTION__, AsciiResourceUri, Status)); > + if (Response->Payload !=3D NULL) { > + RedfishDumpPayload (Response->Payload); > + RedfishFreeResponse ( > + NULL, > + 0, > + NULL, > + Response->Payload > + ); > + Response->Payload =3D NULL; > + } > + } > + > + if (AsciiResourceUri !=3D NULL) { > + FreePool (AsciiResourceUri); > + } > + > + return Status; > +} > + > +/** > + > + Check if this is the Redpath array. Usually the Redpath array represen= ts > + the collection member. Return > + > + @param[in] ConfigureLang The Redpath to check > + @param[out] ArraySignatureOpen String to the open of array sign= ature. > + @param[out] ArraySignatureClose String to the close of array sig= nature. > + > + @retval EFI_SUCCESS Index is found. > + @retval EFI_NOT_FOUND The non-array configure language st= ring is > retured. > + @retval EFI_INVALID_PARAMETER The format of input ConfigureLang i= s > wrong. > + @retval Others Errors occur. > + > +**/ > +EFI_STATUS > +IsRedpathArray ( > + IN EFI_STRING ConfigureLang, > + OUT EFI_STRING *ArraySignatureOpen OPTIONAL, > + OUT EFI_STRING *ArraySignatureClose OPTIONAL > + ) > +{ > + CHAR16 *IndexString; > + > + if (ConfigureLang =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + if (ArraySignatureOpen !=3D NULL) { > + *ArraySignatureOpen =3D NULL; > + } > + if (ArraySignatureClose !=3D NULL) { > + *ArraySignatureClose =3D NULL; > + } > + > + // > + // looking for index signature "{"" > + // > + IndexString =3D StrStr (ConfigureLang, > BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE); > + if (IndexString !=3D NULL) { > + if (ArraySignatureOpen !=3D NULL) { > + *ArraySignatureOpen =3D IndexString; > + } > + // > + // Skip "{" > + // > + IndexString =3D IndexString + StrLen > (BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE); > + // > + // Looking for "}" > + // > + IndexString =3D StrStr (IndexString, > BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_END_SIGNATURE); > + if (IndexString =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + if (ArraySignatureClose !=3D NULL) { > + *ArraySignatureClose =3D IndexString; > + } > + return EFI_SUCCESS; > + } > + return EFI_NOT_FOUND; > +} > + > +/** > + > + Get number of node from the string. Node is seperated by '/'. > + > + @param[in] NodeString The node string to parse. > + > + @retval UINTN Number of nodes in the string. > + > +**/ > +UINTN > +GetNumberOfRedpathNodes ( > + IN EFI_STRING NodeString > + ) > +{ > + UINTN Index; > + UINTN NumberNodes; > + UINTN StringLen; > + > + NumberNodes =3D 0; > + StringLen =3D StrLen (NodeString); > + Index =3D 1; // ConfigLang always starts with '/'. > + while (Index < StringLen) { > + if (*(NodeString + Index) =3D=3D L'/') { > + NumberNodes ++; > + } > + Index ++; > + }; > + NumberNodes ++; > + > + return (NumberNodes); > +} > + > +/** > + > + Get the node string by index > + > + @param[in] NodeString The node string to parse. > + @param[in] Index Zero-based index of the node. > + @param[out] EndOfNodePtr Pointer to receive the poitner to > + the last character of node string. > + > + @retval EFI_STRING the begining of the node string. > + > +**/ > +EFI_STRING > +GetRedpathNodeByIndex ( > + IN EFI_STRING NodeString, > + IN UINTN Index, > + OUT EFI_STRING *EndOfNodePtr OPTIONAL > + ) > +{ > + UINTN NumberNodes; > + UINTN StringLen; > + UINTN StringIndex; > + EFI_STRING NodeStart; > + EFI_STRING NodeEnd; > + > + NumberNodes =3D 0; > + StringLen =3D StrLen (NodeString); > + StringIndex =3D 1; // ConfigLang always starts with '/'. > + NodeStart =3D NodeString; > + if (EndOfNodePtr !=3D NULL) { > + *EndOfNodePtr =3D NULL; > + } > + while (StringIndex < StringLen) { > + if (*(NodeString + StringIndex) =3D=3D L'/') { > + NodeEnd =3D NodeString + StringIndex - 1; > + if (NumberNodes =3D=3D Index) { > + if (EndOfNodePtr !=3D NULL) { > + *EndOfNodePtr =3D NodeEnd; > + } > + return NodeStart; > + } else { > + NodeStart =3D NodeString + StringIndex + 1; > } > + } > + StringIndex ++; > + }; > + return (NULL); > +} > + > +/** > + > + Find array index from given configure language string. > + > + @param[in] ConfigureLang Configure language string to parse. > + @param[out] UnifiedConfigureLang The configure language in array. > + @param[out] Index The array index number. > + > + @retval EFI_SUCCESS Index is found. > + @retval EFI_NOT_FOUND The non-array configure language st= ring is > retured. > + @retval EFI_INVALID_PARAMETER The format of input ConfigureLang i= s > wrong. > + @retval Others Errors occur. > + > +**/ > +EFI_STATUS > +GetArrayIndexFromArrayTypeConfigureLang ( > + IN CHAR16 *ConfigureLang, > + OUT CHAR16 **UnifiedConfigureLang, > + OUT UINTN *Index > + ) > +{ > + EFI_STATUS Status; > + CHAR16 *TmpConfigureLang; > + CHAR16 *ArrayOpenStr; > + CHAR16 *ArrayCloseStr; > + INTN StringIndex; > + > + if (ConfigureLang =3D=3D NULL || UnifiedConfigureLang =3D=3D NULL || I= ndex =3D=3D > NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + TmpConfigureLang =3D AllocateCopyPool (StrSize (ConfigureLang), > ConfigureLang); > + if (TmpConfigureLang =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + Status =3D IsRedpathArray (TmpConfigureLang, &ArrayOpenStr, > &ArrayCloseStr); > + if (!EFI_ERROR (Status)) { > + // > + // Append '\0' for converting decimal string to integer. > + // > + ArrayCloseStr[0] =3D '\0'; > + > + // > + // Convert decimal string to integer > + // > + *Index =3D StrDecimalToUintn (ArrayOpenStr + StrLen > (BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE)); > + > + // > + // Resotre the '}' character and remove rest of string. > + // > + ArrayCloseStr[0] =3D L'}'; > + ArrayCloseStr[1] =3D '\0'; > + *UnifiedConfigureLang =3D TmpConfigureLang; > + } else { > + if (Status =3D=3D EFI_NOT_FOUND) { > + // > + // This is not the redpath array. Search "/" for the parent root. > + // > + *Index =3D 0; > + StringIndex =3D StrLen (TmpConfigureLang) - 1; > + while (StringIndex >=3D 0 && *(TmpConfigureLang + StringIndex) != =3D '/') { > + StringIndex --; > + }; > + if (StringIndex >=3D 0 ) { > + *(TmpConfigureLang + StringIndex) =3D '\0'; > + *UnifiedConfigureLang =3D TmpConfigureLang; > + Status =3D EFI_SUCCESS; > + } else { > + Status =3D EFI_INVALID_PARAMETER; > + } > + } > + } > + return Status; > +} > + > +/** > + > + Clone the configure language list. > + > + @param[in] ConfigureLangList The source > REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST. > + @param[out] DestConfigureLangList The destination > REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST. > + > + @retval EFI_SUCCESS > REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST is copied. > + @retval Others Errors occur. > + > +**/ > +EFI_STATUS > +CopyConfiglanguageList ( > + IN REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST > *SourceConfigureLangList, > + OUT REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST > *DestConfigureLangList > + ) > +{ > + UINTN Index; > + > + if (SourceConfigureLangList =3D=3D NULL || DestConfigureLangList =3D= =3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + DestConfigureLangList->Count =3D SourceConfigureLangList->Count; > + DestConfigureLangList->List =3D > + (REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG *)AllocateZeroPool > (sizeof (REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG) * > DestConfigureLangList->Count); > + if (DestConfigureLangList->List =3D=3D NULL) { > + DEBUG ((DEBUG_ERROR, "%a, Fail to allocate memory for > REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG.\n", __FUNCTION__)); > + return EFI_OUT_OF_RESOURCES; > + } > + for (Index =3D 0; Index < SourceConfigureLangList->Count; Index++) { > + DestConfigureLangList->List [Index].Index =3D SourceConfigureLangLis= t- > >List[Index].Index; > + DestConfigureLangList->List [Index].ConfigureLang =3D > + (EFI_STRING)AllocateCopyPool(StrSize(SourceConfigureLangList- > >List[Index].ConfigureLang), (VOID *)SourceConfigureLangList- > >List[Index].ConfigureLang); > + } > + return EFI_SUCCESS; > +} > + > +/** > + > + Clone the configure language list. > + > + @param[in] ConfigureLang The pointer to configuration language. > + > + @retval UINTN The index of collection member instance. > + Value of 0 means no instance is found. > +**/ > +UINTN > +ConfiglanguageGetInstanceIndex ( > + IN EFI_STRING ConfigureLang > + ) > +{ > + INTN LeftBracketIndex; > + INTN RightBracketIndex; > + INTN Index; > + UINT64 Instance; > + EFI_STATUS Status; > + > + if (ConfigureLang =3D=3D NULL) { > + return 0; > + } > + LeftBracketIndex =3D 0; > + RightBracketIndex =3D 0; > + Index =3D StrLen (ConfigureLang) - 1; > + while (Index >=3D 0) { > + if (*(ConfigureLang + Index) =3D=3D L'{') { > + LeftBracketIndex =3D Index; > + break; > + } > + if (*(ConfigureLang + Index) =3D=3D L'}') { > + RightBracketIndex =3D Index; > + } > + Index --; > + }; > + if ((RightBracketIndex - LeftBracketIndex) <=3D 1) { > + return 0; > + } > + *(ConfigureLang + RightBracketIndex) =3D 0; > + Status =3D StrDecimalToUint64S (ConfigureLang + LeftBracketIndex + 1, = NULL, > &Instance); > + if (EFI_ERROR(Status)) { > + Instance =3D 0; > + } > + // > + // Restore right curly bracket. > + // > + *(ConfigureLang + RightBracketIndex) =3D L'}'; > + return (UINTN)Instance; > +} > + > +/** > + > + Destroy the configure language list. > + > + @param[in] ConfigureLangList The > REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST > + instance to destroy. > + > + @retval EFI_SUCCESS > REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST is copied. > + @retval Others Errors occur. > + > +**/ > +EFI_STATUS > +DestroyConfiglanguageList ( > + IN REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST > *ConfigureLangList > + ) > +{ > + UINTN Index; > + > + if (ConfigureLangList =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + if (ConfigureLangList->List !=3D NULL) { > + for (Index =3D 0; Index < ConfigureLangList->Count; Index++) { > + if (ConfigureLangList->List [Index].ConfigureLang !=3D NULL) { > + FreePool (ConfigureLangList->List [Index].ConfigureLang); > + } > + } > + FreePool (ConfigureLangList->List); > + ConfigureLangList->List =3D NULL; > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + > + Set the node instance. > + > + @param[in] DestConfigLang Pointer to the node's configure lang= uage > string. > + The memory pointed by ConfigLang mus= t be allocated > + through memory allocation interface.= Becasue we will > replace > + the pointer in this function. > + @param[in] MaxtLengthConfigLang The maximum length of ConfigLang. > + @param[in] ConfigLangInstance Pointer to Collection member instanc= e. > + > + @retval EFI_SUCCESS The instance is inserted to the configure > language. > + @retval Others Errors occur. > + > +**/ > +EFI_STATUS > +SetResourceConfigLangMemberInstance ( > + IN EFI_STRING *DestConfigLang, > + IN UINTN MaxtLengthConfigLang, > + IN REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG *ConfigLangInstance > + ) > +{ > + EFI_STRING ThisConfigLang; > + EFI_STRING NewConfigLang; > + CHAR16 InstanceStr [10]; > + INTN Index; > + UINTN Length; > + UINTN MaxStrLength; > + > + if (DestConfigLang =3D=3D NULL || ConfigLangInstance =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + UnicodeSPrint ((CHAR16 *)&InstanceStr, 10, L"%d", ConfigLangInstance- > >Index); > + > + ThisConfigLang =3D *DestConfigLang; > + if (ThisConfigLang [0] =3D=3D 0) { > + // > + // Return ConfigLangInstance->ConfigureLang > + // > + if (ConfigLangInstance->ConfigureLang =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } else { > + StrCatS(*DestConfigLang, MaxtLengthConfigLang, ConfigLangInstance- > >ConfigureLang); > + return EFI_SUCCESS; > + } > + } > + > + MaxStrLength =3D StrSize (ThisConfigLang) + StrSize > ((EFI_STRING)&InstanceStr); > + NewConfigLang =3D ThisConfigLang; > + if (MaxtLengthConfigLang < MaxStrLength) { > + NewConfigLang =3D (EFI_STRING)AllocateZeroPool(MaxStrLength); > + if (NewConfigLang =3D=3D NULL) { > + DEBUG ((DEBUG_ERROR, "%a, Fail to allocate memory for > NewConfigLang.\n", __FUNCTION__)); > + return EFI_OUT_OF_RESOURCES; > + } > + } > + // > + // Search the last "{" > + // > + Index =3D StrLen (ThisConfigLang) - 1; > + while ((ThisConfigLang[Index] !=3D '{') && (Index >=3D 0)) { > + Index --; > + }; > + if (Index =3D=3D -1) { > + if (NewConfigLang !=3D ThisConfigLang) { > + FreePool(NewConfigLang); > + } > + return EFI_NOT_FOUND; > + } > + > + // > + // Copy the string to a new string. > + // > + Length =3D 0; > + while (Index >=3D 0) { > + NewConfigLang [Index] =3D ThisConfigLang[Index]; > + Index --; > + Length ++; > + }; > + UnicodeSPrint ((CHAR16 *)(NewConfigLang + Length), MaxStrLength, > L"%d", ConfigLangInstance->Index); > + StrCatS (NewConfigLang, MaxStrLength, L"}"); > + if (NewConfigLang !=3D ThisConfigLang) { > + FreePool (ThisConfigLang); > + } > + *DestConfigLang =3D NewConfigLang; > + return EFI_SUCCESS; > +} > + > +/** > + > + Search HII database with given Configure Language pattern. Data is > handled and > + returned in array. > + > + @param[in] Schema The schema to search. > + @param[in] Version The schema version. > + @param[in] Pattern Configure Language pattern to se= arch. > + @param[out] UnifiedConfigureLangList The data returned by HII databas= e. > + > + @retval EFI_SUCCESS Data is found and returned. > + @retval Others Errors occur. > + > +**/ > +EFI_STATUS > +RedfishFeatureGetUnifiedArrayTypeConfigureLang ( > + IN CHAR8 *Schema, > + IN CHAR8 *Version, > + IN EFI_STRING Pattern, OPTIONAL > + OUT REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST > *UnifiedConfigureLangList > + ) > +{ > + EFI_STATUS Status; > + EFI_STRING *ConfigureLangList; > + UINTN Count; > + UINTN Index; > + UINTN Index2; > + UINTN ArrayIndex; > + EFI_STRING UnifiedConfigureLang; > + BOOLEAN Duplicated; > + REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG > UnifiedConfigureLangPool[BIOS_CONFIG_TO_REDFISH_REDPATH_POOL_SIZ > E]; > + > + if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || > UnifiedConfigureLangList =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + UnifiedConfigureLangList->Count =3D 0; > + UnifiedConfigureLangList->List =3D NULL; > + ZeroMem (UnifiedConfigureLangPool, sizeof (UnifiedConfigureLangPool)); > + > + Status =3D RedfishPlatformConfigGetConfigureLang (Schema, Version, > Pattern, &ConfigureLangList, &Count); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a, RedfishFeatureGetConfigureLangRegex > failed: %r\n", __FUNCTION__, Status)); > + return Status; > + } > + > + if (Count =3D=3D 0) { > + return EFI_NOT_FOUND; > + } > + > + for (Index =3D 0; Index < Count; Index++) { > + Status =3D GetArrayIndexFromArrayTypeConfigureLang > (ConfigureLangList[Index], &UnifiedConfigureLang, &ArrayIndex); > + if (EFI_ERROR (Status) && Status =3D=3D EFI_INVALID_PARAMETER) { > + ASSERT (FALSE); > + continue; > + } > + > + // > + // Check if this configure language is duplicated. > + // > + Duplicated =3D FALSE; > + for (Index2 =3D 0; Index2 < > BIOS_CONFIG_TO_REDFISH_REDPATH_POOL_SIZE; Index2++) { > + if (UnifiedConfigureLangPool[Index2].ConfigureLang =3D=3D NULL) { > + break; > + } > + > + if (StrCmp (UnifiedConfigureLangPool[Index2].ConfigureLang, > UnifiedConfigureLang) =3D=3D 0) { > + Duplicated =3D TRUE; > + break; > + } > + } > + > + if (Duplicated) { > + FreePool (UnifiedConfigureLang); > + continue; > + } > + > + if (UnifiedConfigureLangList->Count >=3D > BIOS_CONFIG_TO_REDFISH_REDPATH_POOL_SIZE) { > + FreePool (UnifiedConfigureLang); > + Status =3D EFI_BUFFER_TOO_SMALL; > + break; > + } > + > + // > + // New configure language. Keep it in Pool > + // > + > + UnifiedConfigureLangPool[UnifiedConfigureLangList- > >Count].ConfigureLang =3D UnifiedConfigureLang; > + UnifiedConfigureLangPool[UnifiedConfigureLangList->Count].Index =3D > ArrayIndex; > + ++UnifiedConfigureLangList->Count; > + } > + > + FreePool (ConfigureLangList); > + > + // > + // Prepare the result to caller. > + // > + UnifiedConfigureLangList->List =3D AllocateCopyPool (sizeof > (REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG) * > UnifiedConfigureLangList->Count, UnifiedConfigureLangPool); > + > + return Status; > +} > + > +/** > + > + Find "ETag" and "Location" from either HTTP header or Redfish response= . > + > + @param[in] Response HTTP response > + @param[out] Etag String buffer to return ETag > + @param[out] Location String buffer to return Location > + > + @retval EFI_SUCCESS Data is found and returned. > + @retval Others Errors occur. > + > +**/ > +EFI_STATUS > +GetEtagAndLocation ( > + IN REDFISH_RESPONSE *Response, > + OUT CHAR8 **Etag, OPTIONAL > + OUT EFI_STRING *Location OPTIONAL > + ) > +{ > + EDKII_JSON_VALUE JsonValue; > + EDKII_JSON_VALUE OdataValue; > + CHAR8 *OdataString; > + CHAR8 *AsciiLocation; > + EFI_HTTP_HEADER *Header; > + EFI_STATUS Status; > + > + if (Response =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + if (Etag =3D=3D NULL && Location =3D=3D NULL) { > + return EFI_SUCCESS; > + } > + > + Status =3D EFI_SUCCESS; > + > + if (Etag !=3D NULL) { > + *Etag =3D NULL; > + > + if (*(Response->StatusCode) =3D=3D HTTP_STATUS_200_OK) { > + Header =3D HttpFindHeader (Response->HeaderCount, Response- > >Headers, HTTP_HEADER_ETAG); > + if (Header !=3D NULL) { > + *Etag =3D AllocateCopyPool (AsciiStrSize (Header->FieldValue), H= eader- > >FieldValue); > + ASSERT (*Etag !=3D NULL); > + } > + } > + > + // > + // No header is returned. Search payload for location. > + // > + if (*Etag =3D=3D NULL && Response->Payload !=3D NULL) { > + JsonValue =3D RedfishJsonInPayload (Response->Payload); > + if (JsonValue !=3D NULL) { > + OdataValue =3D JsonObjectGetValue (JsonValueGetObject (JsonValue= ), > "@odata.etag"); > + if (OdataValue !=3D NULL) { > + OdataString =3D (CHAR8 *)JsonValueGetAsciiString (OdataValue); > + if (OdataString !=3D NULL) { > + *Etag =3D AllocateCopyPool (AsciiStrSize (OdataString), Odat= aString); > + ASSERT (*Etag !=3D NULL); > + } > + } > + > + JsonValueFree (JsonValue); > + } > + } > + > + if (*Etag =3D=3D NULL) { > + Status =3D EFI_NOT_FOUND; > + } > + } > + > + if (Location !=3D NULL) { > + *Location =3D NULL; > + > + if (*(Response->StatusCode) =3D=3D HTTP_STATUS_200_OK) { > + Header =3D HttpFindHeader (Response->HeaderCount, Response- > >Headers, HTTP_HEADER_LOCATION); > + if (Header !=3D NULL) { > + AsciiLocation =3D AllocateCopyPool (AsciiStrSize (Header->FieldV= alue), > Header->FieldValue); > + ASSERT (AsciiLocation !=3D NULL); > + } > + } > + > + // > + // No header is returned. Search payload for location. > + // > + if (*Location =3D=3D NULL && Response->Payload !=3D NULL) { > + JsonValue =3D RedfishJsonInPayload (Response->Payload); > + if (JsonValue !=3D NULL) { > + OdataValue =3D JsonObjectGetValue (JsonValueGetObject (JsonValue= ), > "@odata.id"); > + if (OdataValue !=3D NULL) { > + OdataString =3D (CHAR8 *)JsonValueGetAsciiString (OdataValue); > + if (OdataString !=3D NULL) { > + AsciiLocation =3D AllocateCopyPool (AsciiStrSize (OdataStrin= g), > OdataString); > + ASSERT (AsciiLocation !=3D NULL); > + } > + } > + > + JsonValueFree (JsonValue); > + } > + } > + > + if (AsciiLocation !=3D NULL) { > + *Location =3D StrAsciiToUnicode (AsciiLocation); > + FreePool (AsciiLocation); > + } else { > + Status =3D EFI_NOT_FOUND; > + } > + } > + > + return Status; > +} > +/** > + > + Create HTTP payload and send them to redfish service with PATCH method= . > + > + @param[in] Service Redfish service. > + @param[in] TargetPayload Target payload > + @param[in] Json Data in JSON format. > + @param[out] Etag Returned ETAG string from Redfish service. > + > + @retval EFI_SUCCESS Data is sent to redfish service successful= ly. > + @retval Others Errors occur. > + > +**/ > +EFI_STATUS > +CreatePayloadToPatchResource ( > + IN REDFISH_SERVICE *Service, > + IN REDFISH_PAYLOAD *TargetPayload, > + IN CHAR8 *Json, > + OUT CHAR8 **Etag > + ) > +{ > + REDFISH_PAYLOAD Payload; > + EDKII_JSON_VALUE ResourceJsonValue; > + REDFISH_RESPONSE PostResponse; > + EFI_STATUS Status; > + > + if (Service =3D=3D NULL || TargetPayload =3D=3D NULL || IS_EMPTY_STRIN= G (Json) > || Etag =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + ResourceJsonValue =3D JsonLoadString (Json, 0, NULL); > + Payload =3D RedfishCreatePayload (ResourceJsonValue, Service); > + if (Payload =3D=3D NULL) { > + DEBUG ((DEBUG_ERROR, "%a:%d Failed to create JSON payload from > JSON value!\n",__FUNCTION__, __LINE__)); > + Status =3D EFI_DEVICE_ERROR; > + goto EXIT_FREE_JSON_VALUE; > + } > + > + ZeroMem (&PostResponse, sizeof (REDFISH_RESPONSE)); > + Status =3D RedfishPatchToPayload (TargetPayload, Payload, &PostRespons= e); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a:%d Failed to PATCH payload to Redfish > service.\n",__FUNCTION__, __LINE__)); > + goto EXIT_FREE_JSON_VALUE; > + } > + > + // > + // Find ETag > + // > + Status =3D GetEtagAndLocation (&PostResponse, Etag, NULL); > + if (EFI_ERROR (Status)) { > + Status =3D EFI_DEVICE_ERROR; > + } > + > + RedfishFreeResponse ( > + PostResponse.StatusCode, > + PostResponse.HeaderCount, > + PostResponse.Headers, > + PostResponse.Payload > + ); > + > +EXIT_FREE_JSON_VALUE: > + if (Payload !=3D NULL) { > + RedfishCleanupPayload (Payload); > + } > + > + JsonValueFree (ResourceJsonValue); > + > + return Status; > +} > + > +/** > + > + Create HTTP payload and send them to redfish service with POST method. > + > + @param[in] Service Redfish service. > + @param[in] TargetPayload Target payload > + @param[in] Json Data in JSON format. > + @param[out] Location Returned location string from Redfish serv= ice. > + @param[out] Etag Returned ETAG string from Redfish service. > + > + @retval EFI_SUCCESS Data is sent to redfish service successful= ly. > + @retval Others Errors occur. > + > +**/ > +EFI_STATUS > +CreatePayloadToPostResource ( > + IN REDFISH_SERVICE *Service, > + IN REDFISH_PAYLOAD *TargetPayload, > + IN CHAR8 *Json, > + OUT EFI_STRING *Location, > + OUT CHAR8 **Etag > + ) > +{ > + REDFISH_PAYLOAD Payload; > + EDKII_JSON_VALUE ResourceJsonValue; > + REDFISH_RESPONSE PostResponse; > + EFI_STATUS Status; > + > + if (Service =3D=3D NULL || TargetPayload =3D=3D NULL || IS_EMPTY_STRIN= G (Json) > || Location =3D=3D NULL || Etag =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + ResourceJsonValue =3D JsonLoadString (Json, 0, NULL); > + Payload =3D RedfishCreatePayload (ResourceJsonValue, Service); > + if (Payload =3D=3D NULL) { > + DEBUG ((DEBUG_ERROR, "%a:%d Failed to create JSON payload from > JSON value!\n",__FUNCTION__, __LINE__)); > + Status =3D EFI_DEVICE_ERROR; > + goto EXIT_FREE_JSON_VALUE; > + } > + > + ZeroMem (&PostResponse, sizeof (REDFISH_RESPONSE)); > + Status =3D RedfishPostToPayload (TargetPayload, Payload, &PostResponse= ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a:%d Failed to POST Attribute Registry to > Redfish service.\n",__FUNCTION__, __LINE__)); > + goto EXIT_FREE_JSON_VALUE; > + } > + > + // > + // per Redfish spec. the URL of new eresource will be returned in > "Location" header. > + // > + Status =3D GetEtagAndLocation (&PostResponse, Etag, Location); > + if (EFI_ERROR (Status)) { > + Status =3D EFI_DEVICE_ERROR; > + } > + > + RedfishFreeResponse ( > + PostResponse.StatusCode, > + PostResponse.HeaderCount, > + PostResponse.Headers, > + PostResponse.Payload > + ); > + > + RedfishCleanupPayload (Payload); > + > +EXIT_FREE_JSON_VALUE: > + JsonValueFree (ResourceJsonValue); > + > + return Status; > +} > + > +/** > + > + Return redfish URI by given config language. It's call responsibility = to > release returned buffer. > + > + @param[in] ConfigLang ConfigLang to search. > + > + @retval NULL Can not find redfish uri. > + @retval Other redfish uri is returned. > + > +**/ > +EFI_STRING > +RedfishGetUri ( > + IN EFI_STRING ConfigLang > + ) > +{ > + EFI_STATUS Status; > + EFI_STRING Target; > + EFI_STRING Found; > + EFI_STRING TempStr; > + EFI_STRING ResultStr; > + EFI_STRING Head; > + EFI_STRING CloseBracket; > + UINTN TempStrSize; > + UINTN RemainingLen; > + UINTN ConfigLangLen; > + > + Status =3D RedfishLocateProtocol ((VOID **)&mConfigLangMapProtocol, > &gEdkIIRedfishConfigLangMapProtocolGuid); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a, fail to locate > gEdkIIRedfishConfigLangMapProtocolGuid: %r\n", __FUNCTION__, Status)); > + return NULL; > + } > + > + DEBUG ((REDFISH_DEBUG_TRACE, "%a, Get: %s\n", __FUNCTION__, > ConfigLang)); > + > + CloseBracket =3D StrStr (ConfigLang, L"{"); > + if (CloseBracket =3D=3D NULL) { > + return AllocateCopyPool (StrSize (ConfigLang), ConfigLang); > + } > + > + // > + // Remove leading "/v1" or "/redfish/v1" because we don't code > + // configure language in this way. > + // > + Head =3D StrStr (ConfigLang, REDFISH_ROOT_PATH_UNICODE); > + if (Head =3D=3D NULL) { > + Head =3D ConfigLang; > + } else { > + Head +=3D 3; > + } > + > + ResultStr =3D AllocateZeroPool (sizeof (CHAR16) * MAX_REDFISH_URL_LEN)= ; > + if (ResultStr =3D=3D NULL) { > + return NULL; > + } > + > + // > + // Go though ConfigLang and replace each {} with URL > + // > + do { > + ConfigLangLen =3D StrLen (Head); > + Target =3D CloseBracket; > + > + // > + // Look for next ConfigLang > + // > + do { > + Target +=3D 1; > + } while (*Target !=3D '\0' && *Target !=3D '}'); > + > + // > + // Invalid format. No '}' found > + // > + if (*Target =3D=3D '\0') { > + DEBUG ((DEBUG_ERROR, "%a, invalid format: %s\n", __FUNCTION__, > ConfigLang)); > + return NULL; > + } > + > + // > + // Copy current ConfigLang to temporary string and do a query > + // > + Target +=3D 1; > + RemainingLen =3D StrLen (Target); > + TempStrSize =3D (ConfigLangLen - RemainingLen + 1) * sizeof (CHAR16)= ; > + TempStr =3D AllocateCopyPool (TempStrSize, Head); > + if (TempStr =3D=3D NULL) { > + return NULL; > + } > + TempStr[ConfigLangLen - RemainingLen] =3D '\0'; > + > + Status =3D mConfigLangMapProtocol->Get ( > + mConfigLangMapProtocol, > + RedfishGetTypeConfigLang, > + TempStr, > + &Found > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a, Can not find: %s\n", __FUNCTION__, > TempStr)); > + return NULL; > + } > + > + DEBUG ((REDFISH_DEBUG_TRACE, "%a, Found: %s\n", __FUNCTION__, > Found)); > + > + // > + // Keep result in final string pool > + // > + StrCatS (ResultStr, MAX_REDFISH_URL_LEN, Found); > + FreePool (TempStr); > + > + // > + // Prepare for next ConfigLang > + // > + Head =3D Target; > + CloseBracket =3D StrStr (Head, L"{"); > + } while (CloseBracket !=3D NULL); > + > + // > + // String which has no ConfigLang remaining > + // > + if (Head !=3D '\0') { > + StrCatS (ResultStr, MAX_REDFISH_URL_LEN, Head); > + } > + > + DEBUG ((REDFISH_DEBUG_TRACE, "%a, return: %s\n", __FUNCTION__, > ResultStr)); > + > + return ResultStr; > +} > + > +/** > + > + Return config language by given URI. It's call responsibility to relea= se > returned buffer. > + > + @param[in] Uri Uri to search. > + > + @retval NULL Can not find redfish uri. > + @retval Other redfish uri is returned. > + > +**/ > +EFI_STRING > +RedfishGetConfigLanguage ( > + IN EFI_STRING Uri > + ) > +{ > + EFI_STATUS Status; > + EFI_STRING ConfigLang; > + > + if (IS_EMPTY_STRING (Uri)) { > + return NULL; > + } > + > + DEBUG ((REDFISH_DEBUG_TRACE, "%a, search config lang for URI: %s\n", > __FUNCTION__, Uri)); > + > + Status =3D RedfishLocateProtocol ((VOID **)&mConfigLangMapProtocol, > &gEdkIIRedfishConfigLangMapProtocolGuid); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a, fail to locate > gEdkIIRedfishConfigLangMapProtocolGuid: %r\n", __FUNCTION__, Status)); > + return NULL; > + } > + > + ConfigLang =3D NULL; > + Status =3D mConfigLangMapProtocol->Get ( > + mConfigLangMapProtocol, > + RedfishGetTypeUri, > + Uri, > + &ConfigLang > + ); > + > + > + return ConfigLang; > +} > + > +/** > + > + Return config language from given URI and prperty name. It's call > responsibility to release returned buffer. > + > + @param[in] Uri The URI to match > + @param[in] PropertyName The property name of resource. This is > optional. > + > + @retval NULL Can not find redfish uri. > + @retval Other redfish uri is returned. > + > +**/ > +EFI_STRING > +GetConfigureLang ( > + IN CHAR8 *Uri, > + IN CHAR8 *PropertyName OPTIONAL > + ) > +{ > + EFI_STRING ConfigLang; > + UINTN StringSize; > + EFI_STRING ResultStr; > + EFI_STRING UnicodeUri; > + EFI_STATUS Status; > + > + if (IS_EMPTY_STRING (Uri)) { > + return NULL; > + } > + > + StringSize =3D AsciiStrSize (Uri); > + UnicodeUri =3D AllocatePool (StringSize * sizeof (CHAR16)); > + if (UnicodeUri =3D=3D NULL) { > + return NULL; > + } > + > + Status =3D AsciiStrToUnicodeStrS (Uri, UnicodeUri, StringSize); > + if (EFI_ERROR (Status)) { > + return NULL; > + } > + > + ConfigLang =3D RedfishGetConfigLanguage (UnicodeUri); > + if (ConfigLang =3D=3D NULL) { > + return NULL; > + } > + > + if (IS_EMPTY_STRING (PropertyName)) { > + return ConfigLang; > + } > + > + StringSize =3D StrSize (ConfigLang) + ((AsciiStrLen (PropertyName) + 1= ) * > sizeof (CHAR16)); > + ResultStr =3D AllocatePool (StringSize); > + if (ResultStr =3D=3D NULL) { > + return NULL; > + } > + > + UnicodeSPrint (ResultStr, StringSize, L"%s/%a", ConfigLang, > PropertyName); > + > + return ResultStr; > +} > + > +/** > + > + Save Redfish URI in database for further use. > + > + @param[in] ConfigLang ConfigLang to save > + @param[in] Uri Redfish Uri to save > + > + @retval EFI_INVALID_PARAMETR SystemId is NULL or EMPTY > + @retval EFI_SUCCESS Redfish uri is saved > + > +**/ > +EFI_STATUS > +RedfisSetRedfishUri ( > + IN EFI_STRING ConfigLang, > + IN EFI_STRING Uri > + ) > +{ > + EFI_STATUS Status; > + > + if (IS_EMPTY_STRING (ConfigLang) || IS_EMPTY_STRING (Uri)) { > + return EFI_INVALID_PARAMETER; > + } > + > + Status =3D RedfishLocateProtocol ((VOID **)&mConfigLangMapProtocol, > &gEdkIIRedfishConfigLangMapProtocolGuid); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a, fail to locate > gEdkIIRedfishConfigLangMapProtocolGuid: %r\n", __FUNCTION__, Status)); > + return Status; > + } > + > + DEBUG ((REDFISH_DEBUG_TRACE, "%a, Saved: %s -> %s\n", > __FUNCTION__, ConfigLang, Uri)); > + > + return mConfigLangMapProtocol->Set (mConfigLangMapProtocol, > ConfigLang, Uri); > +} > + > +/** > + > + Get @odata.id from give HTTP payload. It's call responsibility to rele= ase > returned buffer. > + > + @param[in] Payload HTTP payload > + > + @retval NULL Can not find @odata.id from given payl= oad. > + @retval Others odata.id string is returned. > + > +**/ > +EFI_STRING > +GetOdataId ( > + IN REDFISH_PAYLOAD *Payload > + ) > +{ > + EDKII_JSON_VALUE *JsonValue; > + EDKII_JSON_VALUE *OdataId; > + EFI_STRING OdataIdString; > + > + if (Payload =3D=3D NULL) { > + return NULL; > + } > + > + JsonValue =3D RedfishJsonInPayload (Payload); > + if (!JsonValueIsObject (JsonValue)) { > + return NULL; > + } > + > + OdataId =3D JsonObjectGetValue (JsonValueGetObject (JsonValue), > "@odata.id"); > + if (!JsonValueIsString (OdataId)) { > + return NULL; > + } > + > + OdataIdString =3D JsonValueGetUnicodeString (OdataId); > + if (OdataIdString =3D=3D NULL) { > + return NULL; > + } > + > + return AllocateCopyPool (StrSize (OdataIdString), OdataIdString); > +} > + > + > +/** > + > + Get the property name by given Configure Langauge. > + > + @param[in] ResourceUri URI of root of resource. > + @param[in] ConfigureLang Configure Language string. > + > + @retval EFI_STRING Pointer to property name. > + @retval NULL There is error. > + > +**/ > +EFI_STRING > +GetPropertyFromConfigureLang ( > + IN EFI_STRING ResourceUri, > + IN EFI_STRING ConfigureLang > + ) > +{ > + EFI_STATUS Status; > + EFI_STRING TempString; > + > + if (ConfigureLang =3D=3D NULL || ResourceUri =3D=3D NULL) { > + return NULL; > + } > + > + Status =3D IsRedpathArray (ConfigureLang, NULL, &TempString); > + if (!EFI_ERROR(Status)) { > + TempString +=3D 2; // Advance two characters for '}' and '/' > + return TempString; > + } > + if (Status !=3D EFI_NOT_FOUND) { > + return NULL; > + } > + // > + // The ConigLang has no '{}' > + // > + if (GetNumberOfRedpathNodes (ConfigureLang) =3D=3D 1) { > + return NULL; > + } > + > + if (GetRedpathNodeByIndex (ConfigureLang, 0, &TempString) =3D=3D NULL)= { > + return NULL; > + } > + // > + // Advance two characters to the starting > + // pointer of next node. > + // > + return TempString + 2; > +} > + > +/** > + > + Get the property value in string type. > + > + @param[in] Schema Schema of this property. > + @param[in] Version Schema version. > + @param[in] PropertyName Property name. > + @param[in] ConfigureLang Configure Language of this property. > + > + @retval CHAR8* Pointer to the CHAR8 buffer. > + @retval NULL There is error. > + > +**/ > +CHAR8 * > +GetPropertyStringValue ( > + IN CHAR8 *Schema, > + IN CHAR8 *Version, > + IN EFI_STRING PropertyName, > + IN EFI_STRING ConfigureLang > + ) > +{ > + EFI_STATUS Status; > + EDKII_REDFISH_VALUE RedfishValue; > + EFI_STRING ConfigureLangBuffer; > + UINTN BufferSize; > + CHAR8 *AsciiStringValue; > + > + if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || > IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)) { > + return NULL; > + } > + > + // > + // Configure Language buffer. > + // > + BufferSize =3D sizeof (CHAR16) * MAX_CONF_LANG_LEN; > + ConfigureLangBuffer =3D AllocatePool (BufferSize); > + if (ConfigureLangBuffer =3D=3D NULL) { > + return NULL; > + } > + > + UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLan= g, > PropertyName); > + Status =3D RedfishPlatformConfigGetValue (Schema, Version, > ConfigureLangBuffer, &RedfishValue); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed: > %r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status)); > + return NULL; > + } > + > + if (RedfishValue.Type !=3D REDFISH_VALUE_TYPE_STRING) { > + DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string type\n", > __FUNCTION__, Schema, Version, ConfigureLang)); > + return NULL; > + } > + > + AsciiStringValue =3D AllocateCopyPool (AsciiStrSize > (RedfishValue.Value.Buffer), RedfishValue.Value.Buffer); > + ASSERT (AsciiStringValue !=3D NULL); > + > + return AsciiStringValue; > +} > + > +/** > + > + Get the property value in numeric type. > + > + @param[in] Schema Schema of this property. > + @param[in] Version Schema version. > + @param[in] PropertyName Property name. > + @param[in] ConfigureLang Configure Language of this property. > + > + @retval INT64* Pointer to the INT64 value. > + @retval NULL There is error. > + > +**/ > +INT64 * > +GetPropertyNumericValue ( > + IN CHAR8 *Schema, > + IN CHAR8 *Version, > + IN EFI_STRING PropertyName, > + IN EFI_STRING ConfigureLang > + ) > +{ > + EFI_STATUS Status; > + EDKII_REDFISH_VALUE RedfishValue; > + EFI_STRING ConfigureLangBuffer; > + UINTN BufferSize; > + INT64 *ResultValue; > + > + if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || > IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)) { > + return NULL; > + } > + > + // > + // Configure Language buffer. > + // > + BufferSize =3D sizeof (CHAR16) * MAX_CONF_LANG_LEN; > + ConfigureLangBuffer =3D AllocatePool (BufferSize); > + if (ConfigureLangBuffer =3D=3D NULL) { > + return NULL; > + } > + > + UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLan= g, > PropertyName); > + Status =3D RedfishPlatformConfigGetValue (Schema, Version, > ConfigureLangBuffer, &RedfishValue); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed: > %r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status)); > + return NULL; > + } > + > + if (RedfishValue.Type !=3D REDFISH_VALUE_TYPE_INTEGER) { > + DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not numeric type\n", > __FUNCTION__, Schema, Version, ConfigureLang)); > + return NULL; > + } > + > + ResultValue =3D AllocatePool (sizeof (INT64)); > + ASSERT (ResultValue !=3D NULL); > + if (ResultValue =3D=3D NULL) { > + return NULL; > + } > + > + *ResultValue =3D RedfishValue.Value.Integer; > + > + return ResultValue; > +} > + > +/** > + > + Get the property value in Boolean type. > + > + @param[in] Schema Schema of this property. > + @param[in] Version Schema version. > + @param[in] PropertyName Property name. > + @param[in] ConfigureLang Configure Language of this property. > + > + @retval BOOLEAN Boolean value returned by this property. > + > +**/ > +BOOLEAN * > +GetPropertyBooleanValue ( > + IN CHAR8 *Schema, > + IN CHAR8 *Version, > + IN EFI_STRING PropertyName, > + IN EFI_STRING ConfigureLang > + ) > +{ > + EFI_STATUS Status; > + EDKII_REDFISH_VALUE RedfishValue; > + EFI_STRING ConfigureLangBuffer; > + UINTN BufferSize; > + BOOLEAN *ResultValue; > + > + if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || > IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)) { > + return NULL; > + } > + > + // > + // Configure Language buffer. > + // > + BufferSize =3D sizeof (CHAR16) * MAX_CONF_LANG_LEN; > + ConfigureLangBuffer =3D AllocatePool (BufferSize); > + if (ConfigureLangBuffer =3D=3D NULL) { > + return NULL; > + } > + > + UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLan= g, > PropertyName); > + Status =3D RedfishPlatformConfigGetValue (Schema, Version, > ConfigureLangBuffer, &RedfishValue); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed: > %r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status)); > + return NULL; > + } > + > + if (RedfishValue.Type !=3D REDFISH_VALUE_TYPE_BOOLEAN) { > + DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not boolean type\n", > __FUNCTION__, Schema, Version, ConfigureLang)); > + return NULL; > + } > + > + ResultValue =3D AllocatePool (sizeof (BOOLEAN)); > + ASSERT (ResultValue !=3D NULL); > + if (ResultValue =3D=3D NULL) { > + return NULL; > + } > + > + *ResultValue =3D RedfishValue.Value.Boolean; > + > + return ResultValue; > +} > + > +/** > + > + Return the last string of configure language. Any modification to retu= rned > + string will change ConfigureLanguage. > + > + @param[in] ConfigureLanguage Configure language string > + > + @retval EFI_STRING Attribute name is returned > + @retval NULL Error occurs > + > +**/ > +EFI_STRING > +GetAttributeNameFromConfigLanguage ( > + IN EFI_STRING ConfigureLanguage > + ) > +{ > + UINTN StringLen; > + UINTN Index; > + > + if (IS_EMPTY_STRING (ConfigureLanguage)) { > + return NULL; > + } > + > + StringLen =3D StrLen (ConfigureLanguage); > + for (Index =3D StringLen - 1; Index >=3D 0; Index--) { > + if (ConfigureLanguage[Index] =3D=3D '/') { > + return &ConfigureLanguage[Index + 1]; > + } > + } > + > + return NULL; > +} > + > +/** > + > + Get the property string value in array type. > + > + @param[in] Schema Schema of this property. > + @param[in] Version Schema version. > + @param[in] PropertyName Property name. > + @param[in] ConfigureLang Configure Language of this property. > + @param[out] ArraySize The size of returned array. > + > + @retval CHAR8 ** Returned string array. NULL while error happ= ens. > + > +**/ > +CHAR8 ** > +GetPropertyStringArrayValue ( > + IN CHAR8 *Schema, > + IN CHAR8 *Version, > + IN EFI_STRING PropertyName, > + IN EFI_STRING ConfigureLang, > + OUT UINTN *ArraySize > + ) > +{ > + EFI_STATUS Status; > + EDKII_REDFISH_VALUE RedfishValue; > + EFI_STRING ConfigureLangBuffer; > + UINTN BufferSize; > + CHAR8 **StringArray; > + UINTN Index; > + > + if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || > IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName) > || ArraySize =3D=3D NULL) { > + return NULL; > + } > + > + *ArraySize =3D 0; > + > + // > + // Configure Language buffer. > + // > + BufferSize =3D sizeof (CHAR16) * MAX_CONF_LANG_LEN; > + ConfigureLangBuffer =3D AllocatePool (BufferSize); > + if (ConfigureLangBuffer =3D=3D NULL) { > + DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__)); > + return NULL; > + } > + > + UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLan= g, > PropertyName); > + Status =3D RedfishPlatformConfigGetValue (Schema, Version, > ConfigureLangBuffer, &RedfishValue); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed: > %r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status)); > + return NULL; > + } > + > + if (RedfishValue.Type !=3D REDFISH_VALUE_TYPE_STRING_ARRAY) { > + DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string array type\n"= , > __FUNCTION__, Schema, Version, ConfigureLang)); > + return NULL; > + } > + > + StringArray =3D AllocatePool (sizeof (CHAR8 *) * RedfishValue.ArrayCou= nt); > + if (StringArray =3D=3D NULL) { > + DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__)); > + return NULL; > + } > + > + *ArraySize =3D RedfishValue.ArrayCount; > + for (Index =3D 0; Index < RedfishValue.ArrayCount; Index++) { > + StringArray[Index] =3D RedfishValue.Value.StringArray[Index]; > + } > + > + return StringArray; > +} > + > +/** > + > + Get the property numeric value in array type. > + > + @param[in] Schema Schema of this property. > + @param[in] Version Schema version. > + @param[in] PropertyName Property name. > + @param[in] ConfigureLang Configure Language of this property. > + @param[out] ArraySize The size of returned array. > + > + @retval INT64 * Returned integer array. NULL while error happ= ens. > + > +**/ > +INT64 * > +GetPropertyNumericArrayValue ( > + IN CHAR8 *Schema, > + IN CHAR8 *Version, > + IN EFI_STRING PropertyName, > + IN EFI_STRING ConfigureLang, > + OUT UINTN *ArraySize > + ) > +{ > + EFI_STATUS Status; > + EDKII_REDFISH_VALUE RedfishValue; > + EFI_STRING ConfigureLangBuffer; > + UINTN BufferSize; > + INT64 *IntegerArray; > + UINTN Index; > + > + if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || > IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName) > || ArraySize =3D=3D NULL) { > + return NULL; > + } > + > + *ArraySize =3D 0; > + > + // > + // Configure Language buffer. > + // > + BufferSize =3D sizeof (CHAR16) * MAX_CONF_LANG_LEN; > + ConfigureLangBuffer =3D AllocatePool (BufferSize); > + if (ConfigureLangBuffer =3D=3D NULL) { > + DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__)); > + return NULL; > + } > + > + UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLan= g, > PropertyName); > + Status =3D RedfishPlatformConfigGetValue (Schema, Version, > ConfigureLangBuffer, &RedfishValue); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed: > %r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status)); > + return NULL; > + } > + > + if (RedfishValue.Type !=3D REDFISH_VALUE_TYPE_INTEGER_ARRAY) { > + DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string array type\n"= , > __FUNCTION__, Schema, Version, ConfigureLang)); > + return NULL; > + } > + > + IntegerArray =3D AllocatePool (sizeof (INT64) * RedfishValue.ArrayCoun= t); > + if (IntegerArray =3D=3D NULL) { > + DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__)); > + return NULL; > + } > + > + *ArraySize =3D RedfishValue.ArrayCount; > + for (Index =3D 0; Index < RedfishValue.ArrayCount; Index++) { > + IntegerArray[Index] =3D RedfishValue.Value.IntegerArray[Index]; > + } > + > + return IntegerArray; > +} > + > +/** > + > + Get the property boolean value in array type. > + > + @param[in] Schema Schema of this property. > + @param[in] Version Schema version. > + @param[in] PropertyName Property name. > + @param[in] ConfigureLang Configure Language of this property. > + @param[out] ArraySize The size of returned array. > + > + @retval BOOLEAN * Returned boolean array. NULL while error > happens. > + > +**/ > +BOOLEAN * > +GetPropertyBooleanArrayValue ( > + IN CHAR8 *Schema, > + IN CHAR8 *Version, > + IN EFI_STRING PropertyName, > + IN EFI_STRING ConfigureLang, > + OUT UINTN *ArraySize > + ) > +{ > + EFI_STATUS Status; > + EDKII_REDFISH_VALUE RedfishValue; > + EFI_STRING ConfigureLangBuffer; > + UINTN BufferSize; > + BOOLEAN *BooleanArray; > + UINTN Index; > + > + if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || > IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName) > || ArraySize =3D=3D NULL) { > + return NULL; > + } > + > + *ArraySize =3D 0; > + > + // > + // Configure Language buffer. > + // > + BufferSize =3D sizeof (CHAR16) * MAX_CONF_LANG_LEN; > + ConfigureLangBuffer =3D AllocatePool (BufferSize); > + if (ConfigureLangBuffer =3D=3D NULL) { > + DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__)); > + return NULL; > + } > + > + UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLan= g, > PropertyName); > + Status =3D RedfishPlatformConfigGetValue (Schema, Version, > ConfigureLangBuffer, &RedfishValue); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed: > %r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status)); > + return NULL; > + } > + > + if (RedfishValue.Type !=3D REDFISH_VALUE_TYPE_BOOLEAN_ARRAY) { > + DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string array type\n"= , > __FUNCTION__, Schema, Version, ConfigureLang)); > + return NULL; > + } > + > + BooleanArray =3D AllocatePool (sizeof (INT64) * RedfishValue.ArrayCoun= t); > + if (BooleanArray =3D=3D NULL) { > + DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__)); > + return NULL; > + } > + > + *ArraySize =3D RedfishValue.ArrayCount; > + for (Index =3D 0; Index < RedfishValue.ArrayCount; Index++) { > + BooleanArray[Index] =3D RedfishValue.Value.BooleanArray[Index]; > + } > + > + return BooleanArray; > +} > + > +/** > + > + Free the list of empty property key values. > + > + @param[in] EmptyPropKeyValueListHead The head of > RedfishCS_EmptyProp_KeyValue > + > +**/ > +VOID > +FreeEmptyPropKeyValueList ( > + RedfishCS_EmptyProp_KeyValue *EmptyPropKeyValueListHead > + ) > +{ > + RedfishCS_EmptyProp_KeyValue *NextEmptyPropKeyValueList; >=20 > - if (StrCmp (UnifiedConfigureLangPool[Index2].ConfigureLang, > UnifiedConfigureLang) =3D=3D 0) { > - Duplicated =3D TRUE; > - break; > - } > + while (EmptyPropKeyValueListHead !=3D NULL) { > + NextEmptyPropKeyValueList =3D EmptyPropKeyValueListHead- > >NextKeyValuePtr; > + if (EmptyPropKeyValueListHead->Value->DataValue.CharPtr !=3D NULL) { > + FreePool(EmptyPropKeyValueListHead->Value->DataValue.CharPtr); > } > - > - if (Duplicated) { > - FreePool (UnifiedConfigureLang); > - continue; > + if (EmptyPropKeyValueListHead->Value !=3D NULL) { > + FreePool(EmptyPropKeyValueListHead->Value); > } > - > - if (UnifiedConfigureLangList->Count >=3D > BIOS_CONFIG_TO_REDFISH_REDPATH_POOL_SIZE) { > - FreePool (UnifiedConfigureLang); > - Status =3D EFI_BUFFER_TOO_SMALL; > - break; > + if (EmptyPropKeyValueListHead->KeyNamePtr !=3D NULL) { > + FreePool(EmptyPropKeyValueListHead->KeyNamePtr); > } > + FreePool (EmptyPropKeyValueListHead); > + EmptyPropKeyValueListHead =3D NextEmptyPropKeyValueList; > + }; > +} >=20 > - // > - // New configure language. Keep it in Pool > - // > +/** >=20 > - UnifiedConfigureLangPool[UnifiedConfigureLangList- > >Count].ConfigureLang =3D UnifiedConfigureLang; > - UnifiedConfigureLangPool[UnifiedConfigureLangList->Count].Index =3D > ArrayIndex; > - ++UnifiedConfigureLangList->Count; > - } > + Create a new entry of RedfishCS_EmptyProp_KeyValue >=20 > - FreePool (ConfigureLangList); > + @param[in] KeyName The key name. > + @param[in] RedfishValue Redfish vale of this key. >=20 > - // > - // Prepare the result to caller. > - // > - UnifiedConfigureLangList->List =3D AllocateCopyPool (sizeof > (REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG) * > UnifiedConfigureLangList->Count, UnifiedConfigureLangPool); > +* @retval RedfishCS_EmptyProp_KeyValue Return the new > RedfishCS_EmptyProp_KeyValue. > +* NULL means no new entry is = created. >=20 > - return Status; > +**/ > +RedfishCS_EmptyProp_KeyValue * > +NewEmptyPropKeyValueFromRedfishValue ( > + IN EFI_STRING KeyName, > + IN EDKII_REDFISH_VALUE *RedfishValue > + ) > +{ > + RedfishCS_EmptyProp_KeyValue *EmptyPropKeyValue; > + RedfishCS_Vague *VagueValue; > + RedfishCS_char *KeyNameChar; > + VOID *Data; > + UINTN DataSize; > + INT32 Bool32; > + > + KeyNameChar =3D StrUnicodeToAscii(KeyName); > + if (KeyNameChar =3D=3D NULL) { > + DEBUG ((DEBUG_ERROR, "%a, Failed to convert unicode to ASCII.\n", > __FUNCTION__)); > + return NULL; > + } > + EmptyPropKeyValue =3D (RedfishCS_EmptyProp_KeyValue > *)AllocateZeroPool (sizeof (RedfishCS_EmptyProp_KeyValue)); > + if (EmptyPropKeyValue =3D=3D NULL) { > + DEBUG ((DEBUG_ERROR, "%a, Failed to allocate memory for > EmptyPropKeyValue\n", __FUNCTION__)); > + return NULL; > + } > + VagueValue =3D (RedfishCS_Vague *)AllocateZeroPool (sizeof > (RedfishCS_Vague)); > + if (VagueValue =3D=3D NULL) { > + DEBUG ((DEBUG_ERROR, "%a, Failed to allocate memory for > VagueValue\n", __FUNCTION__)); > + FreePool (EmptyPropKeyValue); > + return NULL; > + } > + > + if (RedfishValue->Type =3D=3D REDFISH_VALUE_TYPE_BOOLEAN) { > + VagueValue->DataType =3D RedfishCS_Vague_DataType_Bool; > + DataSize =3D sizeof (BOOLEAN); > + // > + // Redfish JSON to C strcuture converter uses > + // "int" for the BOOLEAN. > + // > + Bool32 =3D (INT32)RedfishValue->Value.Boolean; > + Data =3D (VOID *)&Bool32; > + } else if (RedfishValue->Type =3D=3D REDFISH_VALUE_TYPE_INTEGER) { > + VagueValue->DataType =3D RedfishCS_Vague_DataType_Int64; > + DataSize =3D sizeof (INT64); > + Data =3D (VOID *)&RedfishValue->Value.Integer; > + } else if (RedfishValue->Type =3D=3D REDFISH_VALUE_TYPE_STRING) { > + VagueValue->DataType =3D RedfishCS_Vague_DataType_String; > + DataSize =3D AsciiStrSize(RedfishValue->Value.Buffer); > + Data =3D (VOID *)RedfishValue->Value.Buffer; > + } else { > + DEBUG ((DEBUG_ERROR, "%a, wrong type of RedfishValue: %x\n", > __FUNCTION__, RedfishValue->Type)); > + FreePool (VagueValue); > + FreePool (EmptyPropKeyValue); > + return NULL; > + } > + VagueValue->DataValue.CharPtr =3D (RedfishCS_char > *)AllocateCopyPool(DataSize, Data); > + EmptyPropKeyValue->Value =3D VagueValue; > + EmptyPropKeyValue->KeyNamePtr =3D KeyNameChar; > + return EmptyPropKeyValue; > } >=20 > /** >=20 > - Create HTTP payload and send them to redfish service with PATCH method= . > + Get the property value in the vague type. >=20 > - @param[in] Service Redfish service. > - @param[in] TargetPayload Target payload > - @param[in] Json Data in JSON format. > - @param[out] Etag Returned ETAG string from Redfish service. > + @param[in] Schema Schema of this property. > + @param[in] Version Schema version. > + @param[in] PropertyName Property name. > + @param[in] ConfigureLang Configure Language of this property. > + @param[out] NumberOfValues Return the number of vague type of > values >=20 > - @retval EFI_SUCCESS Data is sent to redfish service successful= ly. > - @retval Others Errors occur. > + @retval RedfishCS_EmptyProp_KeyValue The pointer to the structur= e > + of vague type of values. >=20 > **/ > -EFI_STATUS > -CreatePayloadToPatchResource ( > - IN REDFISH_SERVICE *Service, > - IN REDFISH_PAYLOAD *TargetPayload, > - IN CHAR8 *Json, > - OUT CHAR8 **Etag > +RedfishCS_EmptyProp_KeyValue * > +GetPropertyVagueValue ( > + IN CHAR8 *Schema, > + IN CHAR8 *Version, > + IN EFI_STRING PropertyName, > + IN EFI_STRING ConfigureLang, > + OUT UINT32 *NumberOfValues > ) > { > - REDFISH_PAYLOAD Payload; > - EDKII_JSON_VALUE ResourceJsonValue; > - REDFISH_RESPONSE PostResponse; > - EFI_STATUS Status; > - UINTN Index; > - EDKII_JSON_VALUE JsonValue; > - EDKII_JSON_VALUE OdataIdValue; > - CHAR8 *OdataIdString; > + EFI_STATUS Status; > + RedfishCS_EmptyProp_KeyValue *EmptyPropKeyValueList; > + RedfishCS_EmptyProp_KeyValue *PreEmptyPropKeyValueList; > + RedfishCS_EmptyProp_KeyValue *FirstEmptyPropKeyValueList; > + EDKII_REDFISH_VALUE RedfishValue; > + EFI_STRING ConfigureLangBuffer; > + EFI_STRING KeyName; > + EFI_STRING *ConfigureLangList; > + EFI_STRING SearchPattern; > + UINTN BufferSize; > + UINTN ConfigListCount; > + UINTN ConfigListCountIndex; >=20 > - if (Service =3D=3D NULL || TargetPayload =3D=3D NULL || IS_EMPTY_STRIN= G (Json) > || Etag =3D=3D NULL) { > - return EFI_INVALID_PARAMETER; > + if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || > IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)) { > + return NULL; > } >=20 > - ResourceJsonValue =3D JsonLoadString (Json, 0, NULL); > - Payload =3D RedfishCreatePayload (ResourceJsonValue, Service); > - if (Payload =3D=3D NULL) { > - DEBUG ((DEBUG_ERROR, "%a:%d Failed to create JSON payload from > JSON value!\n",__FUNCTION__, __LINE__)); > - Status =3D EFI_DEVICE_ERROR; > - goto EXIT_FREE_JSON_VALUE; > + // > + // Configure Language buffer. > + // > + BufferSize =3D sizeof (CHAR16) * MAX_CONF_LANG_LEN; > + ConfigureLangBuffer =3D AllocatePool (BufferSize); > + if (ConfigureLangBuffer =3D=3D NULL) { > + DEBUG ((DEBUG_ERROR, "%a, Failed to allocate memory for > ConfigureLangBuffer\n", __FUNCTION__)); > + return NULL; > } > + UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLan= g, > PropertyName); >=20 > - ZeroMem (&PostResponse, sizeof (REDFISH_RESPONSE)); > - Status =3D RedfishPatchToPayload (TargetPayload, Payload, &PostRespons= e); > + // > + // Initial search pattern > + // > + BufferSize =3D (StrLen (ConfigureLangBuffer) + StrLen (L"/.*") + 1) * = sizeof > (CHAR16); // Increase one for the NULL terminator. > + SearchPattern =3D AllocatePool (BufferSize); > + if (SearchPattern =3D=3D NULL) { > + DEBUG ((DEBUG_ERROR, "%a, Failed to allocate memory for > SearchPattern\n", __FUNCTION__)); > + FreePool (ConfigureLangBuffer); > + return NULL; > + } > + BufferSize =3D BufferSize / sizeof (CHAR16); > + StrCpyS (SearchPattern, BufferSize, ConfigureLangBuffer); > + StrCatS (SearchPattern, BufferSize, L"/.*"); > + Status =3D RedfishPlatformConfigGetConfigureLang (Schema, Version, > SearchPattern, &ConfigureLangList, &ConfigListCount); > if (EFI_ERROR (Status)) { > - DEBUG ((DEBUG_ERROR, "%a:%d Failed to PATCH payload to Redfish > service.\n",__FUNCTION__, __LINE__)); > - goto EXIT_FREE_JSON_VALUE; > + DEBUG ((DEBUG_ERROR, "%a, %a.%a Get configure language of vague > type values of %s failed: %r\n", __FUNCTION__, Schema, Version, > ConfigureLangBuffer, Status)); > + goto ErrorLeave; > } >=20 > - > // > - // Keep etag. > + // Build up the list of RedfishCS_EmptyProp_KeyValue. > // > - *Etag =3D NULL; > - if (*PostResponse.StatusCode =3D=3D HTTP_STATUS_200_OK) { > - if (PostResponse.HeaderCount !=3D 0) { > - for (Index =3D 0; Index < PostResponse.HeaderCount; Index++) { > - if (AsciiStrnCmp (PostResponse.Headers[Index].FieldName, "ETag",= 4) > =3D=3D 0) { > - *Etag =3D AllocateCopyPool (AsciiStrSize > (PostResponse.Headers[Index].FieldValue), > PostResponse.Headers[Index].FieldValue); > - } > - } > - } else if (PostResponse.Payload !=3D NULL) { > - // > - // No header is returned. Search payload for location. > - // > - JsonValue =3D RedfishJsonInPayload (PostResponse.Payload); > - if (JsonValue !=3D NULL) { > - OdataIdValue =3D JsonObjectGetValue (JsonValueGetObject (JsonVal= ue), > "@odata.etag"); > - if (OdataIdValue !=3D NULL) { > - OdataIdString =3D (CHAR8 *)JsonValueGetAsciiString (OdataIdVal= ue); > - if (OdataIdString !=3D NULL) { > - *Etag =3D AllocateCopyPool (AsciiStrSize (OdataIdString), Od= ataIdString); > - } > - } > - } > + ConfigListCountIndex =3D 0; > + PreEmptyPropKeyValueList =3D NULL; > + FirstEmptyPropKeyValueList =3D NULL; > + while (ConfigListCountIndex < ConfigListCount) { > + Status =3D RedfishPlatformConfigGetValue(Schema, Version, > ConfigureLangList [ConfigListCountIndex], &RedfishValue); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s faile= d: > %r\n", __FUNCTION__, Schema, Version, ConfigureLangList > [ConfigListCountIndex], Status)); > + goto ErrorLeave; > } > - } > - > - RedfishFreeResponse ( > - PostResponse.StatusCode, > - PostResponse.HeaderCount, > - PostResponse.Headers, > - PostResponse.Payload > - ); > + // > + // Get the key name. > + // > + KeyName =3D GetAttributeNameFromConfigLanguage (ConfigureLangList > [ConfigListCountIndex]); > + // > + // Create an entry of RedfishCS_EmptyProp_KeyValue. > + // > + EmptyPropKeyValueList =3D NewEmptyPropKeyValueFromRedfishValue > (KeyName, &RedfishValue); > + if (EmptyPropKeyValueList =3D=3D NULL) { > + DEBUG ((DEBUG_ERROR, "%a, Failed to create an entry of > EmptyPropKeyValueList\n", __FUNCTION__)); > + ConfigListCountIndex ++; > + continue; > + } > + // > + // Link the RedfishCS_EmptyProp_KeyValue list. > + // > + if (PreEmptyPropKeyValueList !=3D NULL) { > + PreEmptyPropKeyValueList->NextKeyValuePtr =3D > EmptyPropKeyValueList; > + } else { > + FirstEmptyPropKeyValueList =3D EmptyPropKeyValueList; > + } > + PreEmptyPropKeyValueList =3D EmptyPropKeyValueList; > + ConfigListCountIndex ++; > + }; > + goto LeaveFunction; >=20 > -EXIT_FREE_JSON_VALUE: > - if (Payload !=3D NULL) { > - RedfishCleanupPayload (Payload); > +ErrorLeave:; > + if (FirstEmptyPropKeyValueList !=3D NULL) { > + FreeEmptyPropKeyValueList (FirstEmptyPropKeyValueList); > } > + FirstEmptyPropKeyValueList =3D NULL; >=20 > - JsonValueFree (ResourceJsonValue); > +LeaveFunction: > + if (SearchPattern !=3D NULL) { > + FreePool (SearchPattern); > + } > + if (ConfigureLangBuffer !=3D NULL) { > + FreePool (ConfigureLangBuffer); > + } > + FreePool (ConfigureLangList); >=20 > - return Status; > + *NumberOfValues =3D (UINT32)ConfigListCount; > + return FirstEmptyPropKeyValueList; > } >=20 > /** >=20 > - Create HTTP payload and send them to redfish service with POST method. > + Check and see if we need to do provisioning for this property. >=20 > - @param[in] Service Redfish service. > - @param[in] TargetPayload Target payload > - @param[in] Json Data in JSON format. > - @param[out] Location Returned location string from Redfish serv= ice. > - @param[out] Etag Returned ETAG string from Redfish service. > + @param[in] PropertyBuffer Pointer to property instance. > + @param[in] ProvisionMode TRUE if we are in provision mode. FALSE > otherwise. >=20 > - @retval EFI_SUCCESS Data is sent to redfish service successful= ly. > - @retval Others Errors occur. > + @retval TRUE Provision is required. > + @retval FALSE Provision is not required. >=20 > **/ > -EFI_STATUS > -CreatePayloadToPostResource ( > - IN REDFISH_SERVICE *Service, > - IN REDFISH_PAYLOAD *TargetPayload, > - IN CHAR8 *Json, > - OUT CHAR8 **Location, > - OUT CHAR8 **Etag > +BOOLEAN > +PropertyChecker ( > + IN VOID *PropertyBuffer, > + IN BOOLEAN ProvisionMode > ) > { > - REDFISH_PAYLOAD Payload; > - EDKII_JSON_VALUE ResourceJsonValue; > - REDFISH_RESPONSE PostResponse; > - EFI_STATUS Status; > - UINTN Index; > - EDKII_JSON_VALUE JsonValue; > - EDKII_JSON_VALUE OdataIdValue; > - CHAR8 *OdataIdString; > + if (ProvisionMode) { > + return TRUE; > + } >=20 > - if (Service =3D=3D NULL || TargetPayload =3D=3D NULL || IS_EMPTY_STRIN= G (Json) > || Location =3D=3D NULL || Etag =3D=3D NULL) { > - return EFI_INVALID_PARAMETER; > + if (!ProvisionMode && PropertyBuffer !=3D NULL) { > + return TRUE; > } >=20 > - ResourceJsonValue =3D JsonLoadString (Json, 0, NULL); > - Payload =3D RedfishCreatePayload (ResourceJsonValue, Service); > - if (Payload =3D=3D NULL) { > - DEBUG ((DEBUG_ERROR, "%a:%d Failed to create JSON payload from > JSON value!\n",__FUNCTION__, __LINE__)); > - Status =3D EFI_DEVICE_ERROR; > - goto EXIT_FREE_JSON_VALUE; > + return FALSE; > +} > + > +/** > + > + Check and see if ETAG is identical to what we keep in system. > + > + @param[in] Uri URI requested > + @param[in] EtagInHeader ETAG string returned from HTTP request. > + @param[in] EtagInJson ETAG string in JSON body. > + > + @retval TRUE ETAG is identical. > + @retval FALSE ETAG is changed. > + > +**/ > +BOOLEAN > +CheckEtag ( > + IN EFI_STRING Uri, > + IN CHAR8 *EtagInHeader, > + IN CHAR8 *EtagInJson > + ) > +{ > + CHAR8 *EtagInDb; > + > + if (IS_EMPTY_STRING (Uri)) { > + return FALSE; > } >=20 > - ZeroMem (&PostResponse, sizeof (REDFISH_RESPONSE)); > - Status =3D RedfishPostToPayload (TargetPayload, Payload, &PostResponse= ); > - if (EFI_ERROR (Status)) { > - DEBUG ((DEBUG_ERROR, "%a:%d Failed to POST Attribute Registry to > Redfish service.\n",__FUNCTION__, __LINE__)); > - goto EXIT_FREE_JSON_VALUE; > + if (IS_EMPTY_STRING (EtagInHeader) && IS_EMPTY_STRING (EtagInJson)) > { > + return FALSE; > } >=20 > // > - // per Redfish spec. the URL of new eresource will be returned in > "Location" header. > + // Check ETAG to see if we need to consume it > // > - *Location =3D NULL; > - *Etag =3D NULL; > - if (*PostResponse.StatusCode =3D=3D HTTP_STATUS_200_OK) { > - if (PostResponse.HeaderCount !=3D 0) { > - for (Index =3D 0; Index < PostResponse.HeaderCount; Index++) { > - if (AsciiStrnCmp (PostResponse.Headers[Index].FieldName, "Locati= on", > 8) =3D=3D 0) { > - *Location =3D AllocateCopyPool (AsciiStrSize > (PostResponse.Headers[Index].FieldValue), > PostResponse.Headers[Index].FieldValue); > - } else if (AsciiStrnCmp (PostResponse.Headers[Index].FieldName, > "ETag", 4) =3D=3D 0) { > - *Etag =3D AllocateCopyPool (AsciiStrSize > (PostResponse.Headers[Index].FieldValue), > PostResponse.Headers[Index].FieldValue); > - } > - } > - } else if (PostResponse.Payload !=3D NULL) { > - // > - // No header is returned. Search payload for location. > - // > - JsonValue =3D RedfishJsonInPayload (PostResponse.Payload); > - if (JsonValue !=3D NULL) { > - OdataIdValue =3D JsonObjectGetValue (JsonValueGetObject (JsonVal= ue), > "@odata.id"); > - if (OdataIdValue !=3D NULL) { > - OdataIdString =3D (CHAR8 *)JsonValueGetAsciiString (OdataIdVal= ue); > - if (OdataIdString !=3D NULL) { > - *Location =3D AllocateCopyPool (AsciiStrSize (OdataIdString)= , > OdataIdString); > - } > - } > + EtagInDb =3D NULL; > + EtagInDb =3D GetEtagWithUri (Uri); > + if (EtagInDb =3D=3D NULL) { > + DEBUG ((REDFISH_DEBUG_TRACE, "%a, no ETAG record cound be found > for: %s\n", __FUNCTION__, Uri)); > + return FALSE; > + } >=20 > - OdataIdValue =3D JsonObjectGetValue (JsonValueGetObject (JsonVal= ue), > "@odata.etag"); > - if (OdataIdValue !=3D NULL) { > - OdataIdString =3D (CHAR8 *)JsonValueGetAsciiString (OdataIdVal= ue); > - if (OdataIdString !=3D NULL) { > - *Etag =3D AllocateCopyPool (AsciiStrSize (OdataIdString), Od= ataIdString); > - } > - } > - } > + if (EtagInHeader !=3D NULL) { > + if (AsciiStrCmp (EtagInDb, EtagInHeader) =3D=3D 0) { > + FreePool (EtagInDb); > + return TRUE; > } > } >=20 > - // > - // This is not expected as service does not follow spec. > - // > - if (*Location =3D=3D NULL) { > - Status =3D EFI_DEVICE_ERROR; > + if (EtagInJson !=3D NULL) { > + if (AsciiStrCmp (EtagInDb, EtagInJson) =3D=3D 0) { > + FreePool (EtagInDb); > + return TRUE; > + } > } >=20 > - RedfishFreeResponse ( > - PostResponse.StatusCode, > - PostResponse.HeaderCount, > - PostResponse.Headers, > - PostResponse.Payload > - ); > - > - RedfishCleanupPayload (Payload); > - > -EXIT_FREE_JSON_VALUE: > - JsonValueFree (JsonValue); > - JsonValueFree (ResourceJsonValue); > + FreePool (EtagInDb); >=20 > - return Status; > + return FALSE; > } >=20 > /** > + Check and see if given ObjectName can be found in JsonObj or not >=20 > - Find Redfish Resource Config Protocol that supports given schema and > version. > + @param[in] JsonObj JSON object to search > + @param[in] ObjectName Object name >=20 > - @param[in] Schema Schema name. > - @param[in] Major Schema version major number. > - @param[in] Minor Schema version minor number. > - @param[in] Errata Schema version errata number. > - > - @retval EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL * Pointer to > protocol > - @retval NULL No protocol fo= und. > + @retval EDKII_JSON_VALUE * Pointer to Json object is found. NULL > otherwise. >=20 > **/ > -EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL * > -GetRedfishResourceConfigProtocol ( > - IN CHAR8 *Schema, > - IN CHAR8 *Major, > - IN CHAR8 *Minor, > - IN CHAR8 *Errata > +EDKII_JSON_VALUE * > +MatchJsonObject ( > + IN EDKII_JSON_VALUE *JsonObj, > + IN CHAR8 *ObjectName > ) > { > - EFI_STATUS Status; > - EFI_HANDLE *HandleBuffer; > - UINTN NumberOfHandles; > - UINTN Index; > - EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL *Protocol; > - REDFISH_SCHEMA_INFO SchemaInfo; > - BOOLEAN Found; > + EDKII_JSON_VALUE N; > + CHAR8 *Key; > + EDKII_JSON_VALUE Value; >=20 > - if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Major) || > IS_EMPTY_STRING (Minor) || IS_EMPTY_STRING (Errata)) { > + if (JsonObj =3D=3D NULL || IS_EMPTY_STRING (ObjectName)) { > return NULL; > } >=20 > - Status =3D gBS->LocateHandleBuffer ( > - ByProtocol, > - &gEdkIIRedfishResourceConfigProtocolGuid, > - NULL, > - &NumberOfHandles, > - &HandleBuffer > - ); > - if (EFI_ERROR (Status)) { > + if (!JsonValueIsObject (JsonObj)) { > return NULL; > } >=20 > - Found =3D FALSE; > - > - for (Index =3D 0; Index < NumberOfHandles; Index++) { > - Status =3D gBS->HandleProtocol ( > - HandleBuffer[Index], > - &gEdkIIRedfishResourceConfigProtocolGuid, > - (VOID **) &Protocol > - ); > - if (EFI_ERROR (Status)) { > - continue; > - } > - > - Status =3D Protocol->GetInfo (Protocol, &SchemaInfo); > - if (EFI_ERROR (Status)) { > - continue; > + EDKII_JSON_OBJECT_FOREACH_SAFE (JsonObj, N, Key, Value) { > + if (AsciiStrCmp (Key, ObjectName) =3D=3D 0) { > + return Value; > } > - > - if (AsciiStrCmp (Schema, SchemaInfo.Schema) =3D=3D 0 && > - AsciiStrCmp (Major, SchemaInfo.Major) =3D=3D 0 && > - AsciiStrCmp (Minor, SchemaInfo.Minor) =3D=3D 0 && > - AsciiStrCmp (Errata, SchemaInfo.Errata) =3D=3D 0) { > - Found =3D TRUE; > - break; > - } > } >=20 > - FreePool (HandleBuffer); > - > - return (Found ? Protocol : NULL); > + return NULL; > } >=20 > /** >=20 > - Get supported schema list by given specify schema name. > + Check and see if given property is in JSON context or not >=20 > - @param[in] Schema Schema type name. > - @param[out] SchemaInfo Returned schema information. > + @param[in] Property Property name string > + @param[in] Json The JSON context to search. >=20 > - @retval EFI_SUCCESS Schema information is returned success= fully. > - @retval Others Errors occur. > + @retval TRUE Property is found in JSON context > + @retval FALSE Property is not in JSON context >=20 > **/ > -EFI_STATUS > -GetSupportedSchemaVersion ( > - IN CHAR8 *Schema, > - OUT REDFISH_SCHEMA_INFO *SchemaInfo > +BOOLEAN > +MatchPropertyWithJsonContext ( > + IN EFI_STRING Property, > + IN CHAR8 *Json > ) > { > - EFI_STATUS Status; > - CHAR8 *SupportSchema; > - CHAR8 *SchemaName; > - UINTN Index; > - UINTN Index2; > - BOOLEAN Found; > + CHAR8 *AsciiProperty; > + CHAR8 *PropertyNode; > + UINTN Index; > + EDKII_JSON_VALUE *JsonObj; > + EDKII_JSON_VALUE *MatchObj; > + EDKII_JSON_TYPE JsonType; >=20 > - if (IS_EMPTY_STRING (Schema) || SchemaInfo =3D=3D NULL) { > - return EFI_INVALID_PARAMETER; > + if (IS_EMPTY_STRING (Property) || IS_EMPTY_STRING (Json)) { > + return FALSE; > } >=20 > - Status =3D RedfishPlatformConfigGetSupportedSchema (NULL, > &SupportSchema); > - if (EFI_ERROR (Status)) { > - return Status; > + JsonObj =3D JsonLoadString (Json, 0, NULL); > + if (JsonObj =3D=3D NULL || !JsonValueIsObject (JsonObj)) { > + return FALSE; > } >=20 > - DEBUG ((DEBUG_INFO, "Supported schema: %a\n", SupportSchema)); > - > - Index =3D 0; > - Found =3D FALSE; > - SchemaName =3D SupportSchema; > - while (TRUE) { > - > - if (SupportSchema[Index] =3D=3D ';' || SupportSchema[Index] =3D=3D '= \0') { > - if (AsciiStrnCmp (&SchemaName[SCHEMA_NAME_PREFIX_OFFSET], > Schema, AsciiStrLen (Schema)) =3D=3D 0) { > - Found =3D TRUE; > - SupportSchema[Index] =3D '\0'; > - break; > - } > - > - SchemaName =3D &SupportSchema[Index + 1]; > - } > - > - if (SupportSchema[Index] =3D=3D '\0') { > - break; > - } > - > - ++Index; > + AsciiProperty =3D StrUnicodeToAscii (Property); > + if (AsciiProperty =3D=3D NULL) { > + return FALSE; > } >=20 > - if (Found) { > - > - AsciiStrCpyS (SchemaInfo->Schema, REDFISH_SCHEMA_STRING_SIZE, > Schema); > - > - // > - // forward to '.' > - // > - Index =3D 0; > - while (SchemaName[Index] !=3D '\0' && SchemaName[Index] !=3D '.') { > - ++Index; > - } > - ASSERT (SchemaName[Index] !=3D '\0'); > + Index =3D 0; > + PropertyNode =3D AsciiProperty; > + MatchObj =3D JsonObj; >=20 > - // > - // Skip '.' and 'v' > - // > - Index +=3D 2; > + // > + // Walk through property and find corresponding object in JSON input > + // > + while (AsciiProperty[Index] !=3D '\0') { >=20 > - // > - // forward to '_' > - // > - Index2 =3D Index; > - while (SchemaName[Index2] !=3D '\0' && SchemaName[Index2] !=3D '_')= { > - ++Index2; > + if (AsciiProperty[Index] =3D=3D '/') { > + AsciiProperty[Index] =3D '\0'; > + MatchObj =3D MatchJsonObject (MatchObj, PropertyNode); > + if (MatchObj =3D=3D NULL) { > + PropertyNode =3D NULL; > + break; > + } > + > + PropertyNode =3D &AsciiProperty[Index + 1]; > } > - ASSERT (SchemaName[Index2] !=3D '\0'); >=20 > - AsciiStrnCpyS (SchemaInfo->Major, REDFISH_SCHEMA_VERSION_SIZE, > &SchemaName[Index], (Index2 - Index)); > - Index =3D Index2; > + Index++; > + } >=20 > - // > - // Skip '_' > - // > - ++Index; > + if (PropertyNode !=3D NULL) { > + MatchObj =3D MatchJsonObject (MatchObj, PropertyNode); > + } >=20 > + // > + // Value check > + // > + if (MatchObj !=3D NULL) { > // > - // forward to '_' > + // If object has empty value, treat it as not matching > // > - Index2 =3D Index; > - while (SchemaName[Index2] !=3D '\0' && SchemaName[Index2] !=3D '_')= { > - ++Index2; > + JsonType =3D JsonGetType (MatchObj); > + switch (JsonType) { > + case EdkiiJsonTypeObject: > + if (JsonValueIsNull (MatchObj)) { > + MatchObj =3D NULL; > + } > + break; > + case EdkiiJsonTypeArray: > + if (JsonArrayCount (MatchObj) =3D=3D 0) { > + MatchObj =3D NULL; > + } > + break; > + case EdkiiJsonTypeString: > + if (IS_EMPTY_STRING (JsonValueGetString (MatchObj))) { > + MatchObj =3D NULL; > + } > + break; > + case EdkiiJsonTypeNull: > + MatchObj =3D NULL; > + break; > + default: > + break; > } > - ASSERT (SchemaName[Index2] !=3D '\0'); > - > - AsciiStrnCpyS (SchemaInfo->Minor, REDFISH_SCHEMA_VERSION_SIZE, > &SchemaName[Index], (Index2 - Index)); > - Index =3D Index2; > - > - // > - // Skip '_' > - // > - ++Index; > - > - AsciiStrCpyS (SchemaInfo->Errata, REDFISH_SCHEMA_VERSION_SIZE, > &SchemaName[Index]); > } >=20 > - FreePool (SupportSchema); > - > - return (Found ? EFI_SUCCESS : EFI_NOT_FOUND); > -} > - > -/** > - > - Return system root path. This is dummy function now. > + FreePool (AsciiProperty); >=20 > - @retval NULL Can not find system root path. > - @retval Other System root path is returned. > - > -**/ > -CHAR8 * > -RedfishGetSystemRootPath ( > - VOID > - ) > -{ > - return AllocateCopyPool (AsciiStrSize (REDFISH_SYSTEM_ROOT_PATH), > REDFISH_SYSTEM_ROOT_PATH); > + return (MatchObj =3D=3D NULL ? FALSE : TRUE); > } >=20 > /** >=20 > - Get schema information by given protocol and service instance. > + Create string array and append to arry node in Redfish JSON convert > format. >=20 > - @param[in] RedfishService Pointer to Redfish service instance. > - @param[in] JsonStructProtocol Json Structure protocol instance. > - @param[in] Uri Target URI. > - @param[out] SchemaInfo Returned schema information. > + @param[in,out] Head The head of string array. > + @param[in] StringArray Input string array. > + @param[in] ArraySize The size of StringArray. >=20 > - @retval EFI_SUCCESS Schema information is returned success= fully. > - @retval Others Errors occur. > + @retval EFI_SUCCESS String array is created successfully. > + @retval Others Error happens >=20 > **/ > EFI_STATUS > -GetRedfishSchemaInfo ( > - IN REDFISH_SERVICE *RedfishService, > - IN EFI_REST_JSON_STRUCTURE_PROTOCOL *JsonStructProtocol, > - IN CHAR8 *Uri, > - OUT REDFISH_SCHEMA_INFO *SchemaInfo > +AddRedfishCharArray ( > + IN OUT RedfishCS_char_Array **Head, > + IN CHAR8 **StringArray, > + IN UINTN ArraySize > ) > { > - EFI_STATUS Status; > - REDFISH_RESPONSE Response; > - REDFISH_PAYLOAD Payload; > - CHAR8 *JsonText; > - EFI_REST_JSON_STRUCTURE_HEADER *Header; > + UINTN Index; > + RedfishCS_char_Array *CharArrayBuffer; > + RedfishCS_char_Array *PreArrayBuffer; >=20 > - if (RedfishService =3D=3D NULL || JsonStructProtocol =3D=3D NULL || > IS_EMPTY_STRING (Uri) || SchemaInfo =3D=3D NULL) { > + if (Head =3D=3D NULL || StringArray =3D=3D NULL || ArraySize =3D=3D 0)= { > return EFI_INVALID_PARAMETER; > } >=20 > - Status =3D GetResourceByPath (RedfishService, Uri, &Response); > - if (EFI_ERROR (Status)) { > - DEBUG ((DEBUG_ERROR, "%a, failed to get resource from %a %r", > __FUNCTION__, Uri, Status)); > - return Status; > - } > - > - Payload =3D Response.Payload; > - ASSERT (Payload !=3D NULL); > + PreArrayBuffer =3D NULL; > + for (Index =3D 0; Index < ArraySize; Index++) { > + CharArrayBuffer =3D AllocatePool (sizeof (RedfishCS_char_Array)); > + if (CharArrayBuffer =3D=3D NULL) { > + ASSERT (CharArrayBuffer !=3D NULL); > + continue; > + } >=20 > - JsonText =3D JsonDumpString (RedfishJsonInPayload (Payload), > EDKII_JSON_COMPACT); > - ASSERT (JsonText !=3D NULL); > + if (Index =3D=3D 0) { > + *Head =3D CharArrayBuffer; > + } >=20 > - // > - // Convert JSON text to C structure. > - // > - Status =3D JsonStructProtocol->ToStructure ( > - JsonStructProtocol, > - NULL, > - JsonText, > - &Header > - ); > - if (EFI_ERROR (Status)) { > - DEBUG ((DEBUG_ERROR, "%a, ToStructure() failed: %r\n", > __FUNCTION__, Status)); > - return Status; > + CharArrayBuffer->ArrayValue =3D StringArray[Index]; > + CharArrayBuffer->Next =3D NULL; > + if (PreArrayBuffer !=3D NULL) { > + PreArrayBuffer->Next =3D CharArrayBuffer; > + } > + PreArrayBuffer =3D CharArrayBuffer; > } >=20 > - AsciiStrCpyS (SchemaInfo->Schema, REDFISH_SCHEMA_STRING_SIZE, > Header->JsonRsrcIdentifier.NameSpace.ResourceTypeName); > - AsciiStrCpyS (SchemaInfo->Major, REDFISH_SCHEMA_VERSION_SIZE, > Header->JsonRsrcIdentifier.NameSpace.MajorVersion); > - AsciiStrCpyS (SchemaInfo->Minor, REDFISH_SCHEMA_VERSION_SIZE, > Header->JsonRsrcIdentifier.NameSpace.MinorVersion); > - AsciiStrCpyS (SchemaInfo->Errata, REDFISH_SCHEMA_VERSION_SIZE, > Header->JsonRsrcIdentifier.NameSpace.ErrataVersion); > - > - // > - // Release resource. > - // > - JsonStructProtocol->DestoryStructure (JsonStructProtocol, Header); > - FreePool (JsonText); > - RedfishFreeResponse (Response.StatusCode, Response.HeaderCount, > Response.Headers, Response.Payload); > - > return EFI_SUCCESS; > } >=20 > /** >=20 > - Get the property name by given Configure Langauge. > + Create numeric array and append to arry node in Redfish JSON convert > format. >=20 > - @param[in] ConfigureLang Configure Language string. > + @param[in,out] Head The head of string array. > + @param[in] NumericArray Input numeric array. > + @param[in] ArraySize The size of NumericArray. >=20 > - @retval EFI_STRING Pointer to property name. > - @retval NULL There is error. > + @retval EFI_SUCCESS String array is created successfully. > + @retval Others Error happens >=20 > **/ > -EFI_STRING > -GetPropertyFromConfigureLang ( > - IN EFI_STRING ConfigureLang > +EFI_STATUS > +AddRedfishNumericArray ( > + IN OUT RedfishCS_int64_Array **Head, > + IN INT64 *NumericArray, > + IN UINTN ArraySize > ) > { > - EFI_STRING Property; > - UINTN Index; > + UINTN Index; > + RedfishCS_int64_Array *NumericArrayBuffer; > + RedfishCS_int64_Array *PreArrayBuffer; >=20 > - if (ConfigureLang =3D=3D NULL) { > - return NULL; > + if (Head =3D=3D NULL || NumericArray =3D=3D NULL || ArraySize =3D=3D 0= ) { > + return EFI_INVALID_PARAMETER; > } >=20 > - Index =3D 0; > - Property =3D ConfigureLang; > - > - while (ConfigureLang[Index] !=3D '\0') { > - if (ConfigureLang[Index] =3D=3D L'/') { > - Property =3D &ConfigureLang[Index]; > + PreArrayBuffer =3D NULL; > + for (Index =3D 0; Index < ArraySize; Index++) { > + NumericArrayBuffer =3D AllocatePool (sizeof (RedfishCS_int64_Array))= ; > + if (NumericArrayBuffer =3D=3D NULL) { > + ASSERT (NumericArrayBuffer !=3D NULL); > + continue; > } >=20 > - ++Index; > + if (Index =3D=3D 0) { > + *Head =3D NumericArrayBuffer; > + } > + NumericArrayBuffer->ArrayValue =3D AllocatePool (sizeof > (RedfishCS_int64)); > + if (NumericArrayBuffer->ArrayValue =3D=3D NULL) { > + ASSERT (NumericArrayBuffer->ArrayValue !=3D NULL); > + continue; > + } > + *NumericArrayBuffer->ArrayValue =3D NumericArray[Index]; > + NumericArrayBuffer->Next =3D NULL; > + if (PreArrayBuffer !=3D NULL) { > + PreArrayBuffer->Next =3D NumericArrayBuffer; > + } > + PreArrayBuffer =3D NumericArrayBuffer; > } >=20 > - ++Property; > - > - return Property; > + return EFI_SUCCESS; > } >=20 > /** >=20 > - Get the property value in string type. > + Create boolean array and append to arry node in Redfish JSON convert > format. >=20 > - @param[in] Schema Schema of this property. > - @param[in] Version Schema version. > - @param[in] PropertyName Property name. > - @param[in] ConfigureLang Configure Language of this property. > + @param[in,out] Head The head of string array. > + @param[in] BooleanArray Input boolean array. > + @param[in] ArraySize The size of BooleanArray. >=20 > - @retval CHAR8* Pointer to the CHAR8 buffer. > - @retval NULL There is error. > + @retval EFI_SUCCESS String array is created successfully. > + @retval Others Error happens >=20 > **/ > -CHAR8 * > -GetPropertyStringValue ( > - IN CHAR8 *Schema, > - IN CHAR8 *Version, > - IN EFI_STRING PropertyName, > - IN EFI_STRING ConfigureLang > +EFI_STATUS > +AddRedfishBooleanArray ( > + IN OUT RedfishCS_bool_Array **Head, > + IN BOOLEAN *BooleanArray, > + IN UINTN ArraySize > ) > { > - EFI_STATUS Status; > - EDKII_REDFISH_VALUE RedfishValue; > - EFI_STRING ConfigureLangBuffer; > - UINTN BufferSize; > - CHAR8 *AsciiStringValue; > + UINTN Index; > + RedfishCS_bool_Array *BooleanArrayBuffer; > + RedfishCS_bool_Array *PreArrayBuffer; >=20 > - if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || > IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)) { > - return NULL; > + if (Head =3D=3D NULL || BooleanArrayBuffer =3D=3D NULL || ArraySize = =3D=3D 0) { > + return EFI_INVALID_PARAMETER; > } >=20 > - // > - // Configure Language buffer. > - // > - BufferSize =3D sizeof (CHAR16) * MAX_CONF_LANG_LEN; > - ConfigureLangBuffer =3D AllocatePool (BufferSize); > - if (ConfigureLangBuffer =3D=3D NULL) { > - return NULL; > - } > + PreArrayBuffer =3D NULL; > + for (Index =3D 0; Index < ArraySize; Index++) { > + BooleanArrayBuffer =3D AllocatePool (sizeof (RedfishCS_bool_Array)); > + if (BooleanArrayBuffer =3D=3D NULL) { > + ASSERT (BooleanArrayBuffer !=3D NULL); > + continue; > + } >=20 > - UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLan= g, > PropertyName); > - Status =3D RedfishPlatformConfigGetValue (Schema, Version, > ConfigureLangBuffer, &RedfishValue); > - if (EFI_ERROR (Status)) { > - DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed: > %r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status)); > - return NULL; > - } > + if (Index =3D=3D 0) { > + *Head =3D BooleanArrayBuffer; > + } >=20 > - if (RedfishValue.Type !=3D REDFISH_VALUE_TYPE_STRING) { > - DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string type\n", > __FUNCTION__, Schema, Version, ConfigureLang)); > - return NULL; > + BooleanArrayBuffer->ArrayValue =3D AllocatePool (sizeof > (RedfishCS_bool)); > + if (BooleanArrayBuffer->ArrayValue =3D=3D NULL) { > + ASSERT (BooleanArrayBuffer->ArrayValue !=3D NULL); > + continue; > + } > + *BooleanArrayBuffer->ArrayValue =3D BooleanArray[Index]; > + BooleanArrayBuffer->Next =3D NULL; > + if (PreArrayBuffer !=3D NULL) { > + PreArrayBuffer->Next =3D BooleanArrayBuffer; > + } > + PreArrayBuffer =3D BooleanArrayBuffer; > } >=20 > - AsciiStringValue =3D AllocateCopyPool (AsciiStrSize > (RedfishValue.Value.Buffer), RedfishValue.Value.Buffer); > - ASSERT (AsciiStringValue !=3D NULL); > - > - return AsciiStringValue; > + return EFI_SUCCESS; > } >=20 > /** >=20 > - Get the property value in numeric type. > + Check and see if value in Redfish string array are all the same as the= one > + from HII configuration. >=20 > - @param[in] Schema Schema of this property. > - @param[in] Version Schema version. > - @param[in] PropertyName Property name. > - @param[in] ConfigureLang Configure Language of this property. > + @param[in] Head The head of string array. > + @param[in] StringArray Input string array. > + @param[in] ArraySize The size of StringArray. >=20 > - @retval INT64* Pointer to the INT64 value. > - @retval NULL There is error. > + @retval TRUE All string in Redfish array are as same as s= tring > + in HII configuration array. > + FALSE These two array are not identical. >=20 > **/ > -INT64 * > -GetPropertyNumericValue ( > - IN CHAR8 *Schema, > - IN CHAR8 *Version, > - IN EFI_STRING PropertyName, > - IN EFI_STRING ConfigureLang > +BOOLEAN > +CompareRedfishStringArrayValues ( > + IN RedfishCS_char_Array *Head, > + IN CHAR8 **StringArray, > + IN UINTN ArraySize > ) > { > - EFI_STATUS Status; > - EDKII_REDFISH_VALUE RedfishValue; > - EFI_STRING ConfigureLangBuffer; > - UINTN BufferSize; > - INT64 *ResultValue; > + UINTN Index; > + RedfishCS_char_Array *CharArrayBuffer; >=20 > - if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || > IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)) { > - return NULL; > + if (Head =3D=3D NULL || StringArray =3D=3D NULL || ArraySize =3D=3D 0)= { > + return FALSE; > } >=20 > - // > - // Configure Language buffer. > - // > - BufferSize =3D sizeof (CHAR16) * MAX_CONF_LANG_LEN; > - ConfigureLangBuffer =3D AllocatePool (BufferSize); > - if (ConfigureLangBuffer =3D=3D NULL) { > - return NULL; > - } > + CharArrayBuffer =3D Head; > + Index =3D 0; > + while (CharArrayBuffer !=3D NULL && Index < ArraySize) { >=20 > - UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLan= g, > PropertyName); > - Status =3D RedfishPlatformConfigGetValue (Schema, Version, > ConfigureLangBuffer, &RedfishValue); > - if (EFI_ERROR (Status)) { > - DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed: > %r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status)); > - return NULL; > - } > + if (AsciiStrCmp (StringArray[Index], CharArrayBuffer->ArrayValue) != =3D 0) { > + break; > + } >=20 > - if (RedfishValue.Type !=3D REDFISH_VALUE_TYPE_INTEGER) { > - DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not numeric type\n", > __FUNCTION__, Schema, Version, ConfigureLang)); > - return NULL; > + Index++; > + CharArrayBuffer =3D CharArrayBuffer->Next; > } >=20 > - ResultValue =3D AllocatePool (sizeof (INT64)); > - ASSERT (ResultValue !=3D NULL); > - if (ResultValue =3D=3D NULL) { > - return NULL; > + if (CharArrayBuffer !=3D NULL || Index < ArraySize) { > + return FALSE; > } >=20 > - *ResultValue =3D RedfishValue.Value.Integer; > - > - return ResultValue; > + return TRUE; > } >=20 > /** >=20 > - Get the property value in Boolean type. > + Check and see if value in Redfish numeric array are all the same as th= e one > + from HII configuration. >=20 > - @param[in] Schema Schema of this property. > - @param[in] Version Schema version. > - @param[in] PropertyName Property name. > - @param[in] ConfigureLang Configure Language of this property. > + @param[in] Head The head of Redfish CS numeraic array. > + @param[in] NumericArray Input numeric array. > + @param[in] ArraySize The size of NumericArray. >=20 > - @retval BOOLEAN Boolean value returned by this property. > + @retval TRUE All string in Redfish array are as same as i= nteger > + in HII configuration array. > + FALSE These two array are not identical. >=20 > **/ > -BOOLEAN * > -GetPropertyBooleanValue ( > - IN CHAR8 *Schema, > - IN CHAR8 *Version, > - IN EFI_STRING PropertyName, > - IN EFI_STRING ConfigureLang > +BOOLEAN > +CompareRedfishNumericArrayValues ( > + IN RedfishCS_int64_Array *Head, > + IN INT64 *NumericArray, > + IN UINTN ArraySize > ) > { > - EFI_STATUS Status; > - EDKII_REDFISH_VALUE RedfishValue; > - EFI_STRING ConfigureLangBuffer; > - UINTN BufferSize; > - BOOLEAN *ResultValue; > - > - if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || > IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)) { > - return NULL; > - } > + UINTN Index; > + RedfishCS_int64_Array *NumericArrayBuffer; >=20 > - // > - // Configure Language buffer. > - // > - BufferSize =3D sizeof (CHAR16) * MAX_CONF_LANG_LEN; > - ConfigureLangBuffer =3D AllocatePool (BufferSize); > - if (ConfigureLangBuffer =3D=3D NULL) { > - return NULL; > + if (Head =3D=3D NULL || NumericArray =3D=3D NULL || ArraySize =3D=3D 0= ) { > + return FALSE; > } >=20 > - UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLan= g, > PropertyName); > - Status =3D RedfishPlatformConfigGetValue (Schema, Version, > ConfigureLangBuffer, &RedfishValue); > - if (EFI_ERROR (Status)) { > - DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed: > %r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status)); > - return NULL; > - } > + NumericArrayBuffer =3D Head; > + Index =3D 0; > + while (NumericArrayBuffer !=3D NULL && Index < ArraySize) { > + if (NumericArray[Index] !=3D *NumericArrayBuffer->ArrayValue) { > + break; > + } >=20 > - if (RedfishValue.Type !=3D REDFISH_VALUE_TYPE_BOOLEAN) { > - DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not boolean type\n", > __FUNCTION__, Schema, Version, ConfigureLang)); > - return NULL; > + Index++; > + NumericArrayBuffer =3D NumericArrayBuffer->Next; > } >=20 > - ResultValue =3D AllocatePool (sizeof (BOOLEAN)); > - ASSERT (ResultValue !=3D NULL); > - if (ResultValue =3D=3D NULL) { > - return NULL; > + if (NumericArrayBuffer !=3D NULL || Index < ArraySize) { > + return FALSE; > } >=20 > - *ResultValue =3D RedfishValue.Value.Boolean; > - > - return ResultValue; > + return TRUE; > } >=20 > /** >=20 > - Check and see if we need to do provisioning for this property. > + Check and see if value in Redfish boolean array are all the same as th= e one > + from HII configuration. >=20 > - @param[in] PropertyBuffer Pointer to property instance. > - @param[in] ProvisionMode TRUE if we are in provision mode. FALSE > otherwise. > + @param[in] Head The head of Redfish CS boolean array. > + @param[in] BooleanArray Input boolean array. > + @param[in] ArraySize The size of BooleanArray. >=20 > - @retval TRUE Provision is required. > - @retval FALSE Provision is not required. > + @retval TRUE All string in Redfish array are as same as i= nteger > + in HII configuration array. > + FALSE These two array are not identical. >=20 > **/ > BOOLEAN > -PropertyChecker ( > - IN VOID *PropertyBuffer, > - IN BOOLEAN ProvisionMode > +CompareRedfishBooleanArrayValues ( > + IN RedfishCS_bool_Array *Head, > + IN BOOLEAN *BooleanArray, > + IN UINTN ArraySize > ) > { > - if (ProvisionMode && PropertyBuffer =3D=3D NULL) { > - return TRUE; > + UINTN Index; > + RedfishCS_bool_Array *BooleanArrayBuffer; > + > + if (Head =3D=3D NULL || BooleanArray =3D=3D NULL || ArraySize =3D=3D 0= ) { > + return FALSE; > } >=20 > - if (!ProvisionMode && PropertyBuffer !=3D NULL) { > - return TRUE; > + BooleanArrayBuffer =3D Head; > + Index =3D 0; > + while (BooleanArrayBuffer !=3D NULL && Index < ArraySize) { > + if (BooleanArray[Index] !=3D *BooleanArrayBuffer->ArrayValue) { > + break; > + } > + > + Index++; > + BooleanArrayBuffer =3D BooleanArrayBuffer->Next; > } >=20 > - return FALSE; > + if (BooleanArrayBuffer !=3D NULL || Index < ArraySize) { > + return FALSE; > + } > + > + return TRUE; > } >=20 > /** >=20 > - Check and see if we need to do provisioning for this two properties. > + Check and see if any difference between two vague value set. > + This is just a simple check. >=20 > - @param[in] PropertyBuffer1 Pointer to property instance 1. > - @param[in] PropertyBuffer2 Pointer to property instance 2. > - @param[in] ProvisionMode TRUE if we are in provision mode. FALSE > otherwise. > + @param[in] RedfishVagueKeyValuePtr The vague key value sets on > Redfish service. > + @param[in] RedfishVagueKeyValueNumber The numebr of vague key > value sets > + @param[in] ConfigVagueKeyValuePtr The vague configuration on > platform. > + @param[in] ConfigVagueKeyValueNumber The numebr of vague key > value sets >=20 > - @retval TRUE Provision is required. > - @retval FALSE Provision is not required. > + @retval TRUE All values are the same. > + FALSE There is some difference. >=20 > **/ > BOOLEAN > -PropertyChecker2Parm ( > - IN VOID *PropertyBuffer1, > - IN VOID *PropertyBuffer2, > - IN BOOLEAN ProvisionMode > +CompareRedfishPropertyVagueValues ( > + IN RedfishCS_EmptyProp_KeyValue *RedfishVagueKeyValuePtr, > + IN UINT32 RedfishVagueKeyValueNumber, > + IN RedfishCS_EmptyProp_KeyValue *ConfigVagueKeyValuePtr, > + IN UINT32 ConfigVagueKeyValueNumber > ) > -{ > - if (ProvisionMode && (PropertyBuffer1 =3D=3D NULL || PropertyBuffer2 = =3D=3D > NULL)) { > - return TRUE; > - } > + { > + RedfishCS_EmptyProp_KeyValue *ThisConfigVagueKeyValuePtr; > + RedfishCS_EmptyProp_KeyValue *ThisRedfishVagueKeyValuePtr; >=20 > - if (!ProvisionMode && PropertyBuffer1 !=3D NULL && PropertyBuffer2 != =3D > NULL) { > - return TRUE; > + if (RedfishVagueKeyValueNumber !=3D ConfigVagueKeyValueNumber) { > + return FALSE; > } >=20 > - return FALSE; > + ThisConfigVagueKeyValuePtr =3D ConfigVagueKeyValuePtr; > + // > + // Loop through all key/value on system. > + // > + while (ThisConfigVagueKeyValuePtr !=3D NULL) { > + ThisRedfishVagueKeyValuePtr =3D RedfishVagueKeyValuePtr; > + // > + // Loop through all key/value on Redfish service.. > + // > + while (ThisRedfishVagueKeyValuePtr !=3D NULL) { > + if (AsciiStrCmp(ThisConfigVagueKeyValuePtr->KeyNamePtr, > ThisRedfishVagueKeyValuePtr->KeyNamePtr) =3D=3D 0) { > + // > + // Check the type of value. > + // > + if (ThisConfigVagueKeyValuePtr->Value->DataType !=3D > ThisRedfishVagueKeyValuePtr->Value->DataType) { > + return FALSE; > + } > + // > + // Check the value. > + // > + if (ThisConfigVagueKeyValuePtr->Value->DataType =3D=3D > RedfishCS_Vague_DataType_String) { > + // > + // Is the string identical? > + // > + if (AsciiStrCmp (ThisConfigVagueKeyValuePtr->Value- > >DataValue.CharPtr, > + ThisRedfishVagueKeyValuePtr->Value->DataValue= .CharPtr > + ) =3D=3D 0) { > + break; > + } else{ > + return FALSE; > + } > + } else if (ThisConfigVagueKeyValuePtr->Value->DataType =3D=3D > RedfishCS_Vague_DataType_Int64) { > + if (*ThisConfigVagueKeyValuePtr->Value->DataValue.Int64Ptr =3D= =3D > *ThisRedfishVagueKeyValuePtr->Value->DataValue.Int64Ptr) { > + break; > + } else { > + return FALSE; > + } > + } else if (ThisConfigVagueKeyValuePtr->Value->DataType =3D=3D > RedfishCS_Vague_DataType_Bool) { > + if ((UINT8)*ThisConfigVagueKeyValuePtr->Value->DataValue.BoolP= tr > =3D=3D (UINT8)*ThisRedfishVagueKeyValuePtr->Value->DataValue.BoolPtr) { > + break; > + } else { > + return FALSE; > + } > + } else { > + return FALSE; > + } > + } > + ThisRedfishVagueKeyValuePtr =3D ThisRedfishVagueKeyValuePtr- > >NextKeyValuePtr; > + }; > + if (ThisRedfishVagueKeyValuePtr =3D=3D NULL) { > + // > + // No matched key name. Threat these two vague value set is differ= ent. > + // > + return FALSE; > + } > + ThisConfigVagueKeyValuePtr =3D ThisConfigVagueKeyValuePtr- > >NextKeyValuePtr; > + }; > + return TRUE; > } >=20 > /** > diff --git > a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtility= Lib > .inf > b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtility= Lib > .inf > index f9f283fdcc..84f338e680 100644 > --- > a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtility= Lib > .inf > +++ > b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtility= Lib > .inf > @@ -1,6 +1,6 @@ > ## @file > # > -# (C) Copyright 2020-2021 Hewlett Packard Enterprise Development LP
> +# (C) Copyright 2020-2022 Hewlett Packard Enterprise Development > LP
> # > # SPDX-License-Identifier: BSD-2-Clause-Patent > # > @@ -27,6 +27,7 @@ > [Packages] > MdePkg/MdePkg.dec > MdeModulePkg/MdeModulePkg.dec > + NetworkPkg/NetworkPkg.dec > RedfishPkg/RedfishPkg.dec > RedfishClientPkg/RedfishClientPkg.dec >=20 > @@ -35,16 +36,25 @@ > BaseMemoryLib > DebugLib > MemoryAllocationLib > - PrintLib > RedfishLib > RedfishPlatformConfigLib > UefiLib > UefiBootServicesTableLib > UefiRuntimeServicesTableLib > + PrintLib > + HttpLib >=20 > [Protocols] > - gEdkIIRedfishETagProtocolGuid ## CONSUMED ## > + gEdkIIRedfishETagProtocolGuid ## CONSUMED ## > + gEdkIIRedfishConfigLangMapProtocolGuid ## CONSUMED ## >=20 > [Pcd] > - gEfiRedfishClientPkgTokenSpaceGuid.PcdMaxRedfishSchemaStringSize > - gEfiRedfishClientPkgTokenSpaceGuid.PcdMaxRedfishSchemaVersionSize > + > +[Guids] > + > +[BuildOptions] > + # > + # NOTE: /wd4706 disables the following Visual Studio compiler warning = in > Jansson: > + # "C4706: assignment within conditional expression" > + # > + MSFT:*_*_*_CC_FLAGS =3D /wd4706 > -- > 2.32.0.windows.2