From: "Chang, Abner via groups.io" <abner.chang=amd.com@groups.io>
To: Nickle Wang <nicklew@nvidia.com>,
"devel@edk2.groups.io" <devel@edk2.groups.io>
Cc: Igor Kulchytskyy <igork@ami.com>, Nick Ramirez <nramirez@nvidia.com>
Subject: Re: [edk2-devel] [edk2-redfish-client][PATCH] RedfishClientPkg/RedfishLib: align with edk2 RedfishLib
Date: Wed, 1 Nov 2023 04:00:05 +0000 [thread overview]
Message-ID: <MN2PR12MB39666004BF48B5E8E16B8907EAA7A@MN2PR12MB3966.namprd12.prod.outlook.com> (raw)
In-Reply-To: <20231026083503.20169-1-nicklew@nvidia.com>
[AMD Official Use Only - General]
Reviewed-by: Abner Chang <abner.chang@amd.com>
> -----Original Message-----
> From: Nickle Wang <nicklew@nvidia.com>
> Sent: Thursday, October 26, 2023 4:35 PM
> To: devel@edk2.groups.io
> Cc: Chang, Abner <Abner.Chang@amd.com>; Igor Kulchytskyy
> <igork@ami.com>; Nick Ramirez <nramirez@nvidia.com>
> Subject: [edk2-redfish-client][PATCH] RedfishClientPkg/RedfishLib: align with
> edk2 RedfishLib
>
> Caution: This message originated from an External Source. Use proper caution
> when opening attachments, clicking links, or responding.
>
>
> Update RedfishLib to align with RedfishLib in edk2 repository.
> RedfishLib commits on edk2:
> cf68ff61 RedfishPkg/RedfishLib: introduce new interfaces.
> 1cbdd6e9 RedfishPkg/libredfish: introduce new interfaces.
> 8765f3eb RedfishPkg/RedfishLib: return HTTP headers to caller.
>
> Signed-off-by: Nickle Wang <nicklew@nvidia.com>
> Cc: Abner Chang <abner.chang@amd.com>
> Cc: Igor Kulchytskyy <igork@ami.com>
> Cc: Nick Ramirez <nramirez@nvidia.com>
> ---
> .../PrivateLibrary/RedfishLib/RedfishLib.inf | 1 +
> .../edk2libredfish/include/redfishPayload.h | 32 +-
> .../edk2libredfish/include/redfishService.h | 21 +
> .../PrivateLibrary/RedfishLib/RedfishLib.c | 345 +++++++++++-
> .../PrivateLibrary/RedfishLib/RedfishMisc.c | 13 +-
> .../RedfishLib/edk2libredfish/src/payload.c | 124 +---
> .../RedfishLib/edk2libredfish/src/service.c | 531 ++++++------------
> 7 files changed, 527 insertions(+), 540 deletions(-)
>
> diff --git a/RedfishClientPkg/PrivateLibrary/RedfishLib/RedfishLib.inf
> b/RedfishClientPkg/PrivateLibrary/RedfishLib/RedfishLib.inf
> index a54e397d..79d8792f 100644
> --- a/RedfishClientPkg/PrivateLibrary/RedfishLib/RedfishLib.inf
> +++ b/RedfishClientPkg/PrivateLibrary/RedfishLib/RedfishLib.inf
> @@ -3,6 +3,7 @@
> #
> # Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> # (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
> +# Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights
> reserved.
> #
> # SPDX-License-Identifier: BSD-2-Clause-Patent
> #
> diff --git
> a/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfishP
> ayload.h
> b/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfishP
> ayload.h
> index 8403d693..f7917603 100644
> ---
> a/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfishP
> ayload.h
> +++
> b/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfishP
> ayload.h
> @@ -10,6 +10,7 @@
>
> Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>
> + Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights
> reserved.
>
> SPDX-License-Identifier: BSD-2-Clause-Patent
>
> @@ -19,7 +20,7 @@
> #define LIBREDFISH_REDFISH_PAYLOAD_H_
>
> #include <Include/Library/RedfishCrtLib.h>
> -
> +#include <Library/JsonLib.h>
> #include <jansson.h>
> #include <redfishService.h>
> #include <redpath.h>
> @@ -65,15 +66,6 @@ patchPayload (
> EFI_HTTP_STATUS_CODE **StatusCode
> );
>
> -redfishPayload *
> -patchPayloadEx (
> - redfishPayload *target,
> - redfishPayload *payload,
> - EFI_HTTP_HEADER **Headers,
> - UINTN *HeaderCount,
> - EFI_HTTP_STATUS_CODE **StatusCode
> - );
> -
> redfishPayload *
> postContentToPayload (
> redfishPayload *target,
> @@ -83,17 +75,6 @@ postContentToPayload (
> EFI_HTTP_STATUS_CODE **StatusCode
> );
>
> -redfishPayload *
> -postContentToPayloadEx (
> - redfishPayload *target,
> - const char *data,
> - size_t dataSize,
> - const char *contentType,
> - EFI_HTTP_HEADER **Headers,
> - UINTN *HeaderCount,
> - EFI_HTTP_STATUS_CODE **StatusCode
> - );
> -
> redfishPayload *
> postPayload (
> redfishPayload *target,
> @@ -101,15 +82,6 @@ postPayload (
> EFI_HTTP_STATUS_CODE **StatusCode
> );
>
> -redfishPayload *
> -postPayloadEx (
> - redfishPayload *target,
> - redfishPayload *payload,
> - EFI_HTTP_HEADER **Headers,
> - UINTN *HeaderCount,
> - EFI_HTTP_STATUS_CODE **StatusCode
> - );
> -
> void
> cleanupPayload (
> redfishPayload *payload
> diff --git
> a/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfishS
> ervice.h
> b/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfishS
> ervice.h
> index c41c0d14..c2e0fd32 100644
> ---
> a/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfishS
> ervice.h
> +++
> b/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfishS
> ervice.h
> @@ -10,6 +10,7 @@
>
> Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>
> + Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights
> reserved.
>
> SPDX-License-Identifier: BSD-2-Clause-Patent
>
> @@ -153,6 +154,18 @@ postUriFromServiceEx (
> EFI_HTTP_STATUS_CODE **StatusCode
> );
>
> +json_t *
> +putUriFromServiceEx (
> + redfishService *service,
> + const char *uri,
> + const char *content,
> + size_t contentLength,
> + const char *contentType,
> + EFI_HTTP_HEADER **Headers,
> + UINTN *HeaderCount,
> + EFI_HTTP_STATUS_CODE **StatusCode
> + );
> +
> json_t *
> deleteUriFromService (
> redfishService *service,
> @@ -160,6 +173,14 @@ deleteUriFromService (
> EFI_HTTP_STATUS_CODE **StatusCode
> );
>
> +json_t *
> +deleteUriFromServiceEx (
> + redfishService *service,
> + const char *uri,
> + const char *content,
> + EFI_HTTP_STATUS_CODE **StatusCode
> + );
> +
> redfishPayload *
> getRedfishServiceRoot (
> redfishService *service,
> diff --git a/RedfishClientPkg/PrivateLibrary/RedfishLib/RedfishLib.c
> b/RedfishClientPkg/PrivateLibrary/RedfishLib/RedfishLib.c
> index c00b15f6..8a4483b4 100644
> --- a/RedfishClientPkg/PrivateLibrary/RedfishLib/RedfishLib.c
> +++ b/RedfishClientPkg/PrivateLibrary/RedfishLib/RedfishLib.c
> @@ -4,6 +4,7 @@
>
> Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>
> + Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights
> reserved.
>
> SPDX-License-Identifier: BSD-2-Clause-Patent
>
> @@ -167,6 +168,30 @@ RedfishJsonInPayload (
> return ((redfishPayload *)Payload)->json;
> }
>
> +/**
> + This function returns the Redfish service of a REDFISH_PAYLOAD.
> +
> + Caller doesn't need to free the returned JSON value because it will be
> released
> + in corresponding RedfishCleanupService() function.
> +
> + @param[in] Payload A REDFISH_PAYLOAD instance.
> +
> + @return Redfish service of the payload.
> +
> +**/
> +REDFISH_SERVICE
> +EFIAPI
> +RedfishServiceInPayload (
> + IN REDFISH_PAYLOAD Payload
> + )
> +{
> + if (Payload == NULL) {
> + return NULL;
> + }
> +
> + return ((redfishPayload *)Payload)->service;
> +}
> +
> /**
> Fill the input RedPath string with system UUID from SMBIOS table or use the
> customized
> ID if FromSmbios == FALSE.
> @@ -244,7 +269,7 @@ RedfishBuildPathWithSystemUuid (
> from the root node.
> @param[out] RedResponse Pointer to the Redfish response data.
>
> - @retval EFI_SUCCESS The opeartion is successful, indicates the HTTP
> StatusCode is not
> + @retval EFI_SUCCESS The operation is successful, indicates the HTTP
> StatusCode is not
> NULL and the value is 2XX. The corresponding redfish
> resource has
> been returned in Payload within RedResponse.
> @retval EFI_INVALID_PARAMETER RedfishService, RedPath, or
> RedResponse is NULL.
> @@ -304,7 +329,7 @@ RedfishGetByService (
> @param[in] Uri String to address a resource.
> @param[out] RedResponse Pointer to the Redfish response data.
>
> - @retval EFI_SUCCESS The opeartion is successful, indicates the HTTP
> StatusCode is not
> + @retval EFI_SUCCESS The operation is successful, indicates the HTTP
> StatusCode is not
> NULL and the value is 2XX. The corresponding redfish
> resource has
> been returned in Payload within RedResponse.
> @retval EFI_INVALID_PARAMETER RedfishService, RedPath, or
> RedResponse is NULL.
> @@ -367,7 +392,7 @@ RedfishGetByUri (
> @param[in] RedPath Relative RedPath string to address a resource
> inside Payload.
> @param[out] RedResponse Pointer to the Redfish response data.
>
> - @retval EFI_SUCCESS The opeartion is successful:
> + @retval EFI_SUCCESS The operation is successful:
> 1. The HTTP StatusCode is NULL and the returned Payload in
> RedResponse is not NULL, indicates the Redfish resource has
> been parsed from the input payload directly.
> @@ -440,7 +465,7 @@ RedfishGetByPayload (
> @param[in] Content JSON represented properties to be update.
> @param[out] RedResponse Pointer to the Redfish response data.
>
> - @retval EFI_SUCCESS The opeartion is successful, indicates the HTTP
> StatusCode is not
> + @retval EFI_SUCCESS The operation is successful, indicates the HTTP
> StatusCode is not
> NULL and the value is 2XX. The Redfish resource will be
> returned
> in Payload within RedResponse if server send it back in the
> HTTP
> response message body.
> @@ -473,10 +498,12 @@ RedfishPatchToUri (
>
> ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));
>
> - JsonValue = (EDKII_JSON_VALUE)patchUriFromService (
> + JsonValue = (EDKII_JSON_VALUE)patchUriFromServiceEx (
> RedfishService,
> Uri,
> Content,
> + &(RedResponse->Headers),
> + &(RedResponse->HeaderCount),
> &(RedResponse->StatusCode)
> );
>
> @@ -527,10 +554,10 @@ ON_EXIT:
> redfish response data.
>
> @param[in] Target The target payload to be updated.
> - @param[in] Payload Palyoad with properties to be changed.
> + @param[in] Payload Payload with properties to be changed.
> @param[out] RedResponse Pointer to the Redfish response data.
>
> - @retval EFI_SUCCESS The opeartion is successful, indicates the HTTP
> StatusCode is not
> + @retval EFI_SUCCESS The operation is successful, indicates the HTTP
> StatusCode is not
> NULL and the value is 2XX. The Redfish resource will be
> returned
> in Payload within RedResponse if server send it back in the
> HTTP
> response message body.
> @@ -556,11 +583,9 @@ RedfishPatchToPayload (
>
> ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));
>
> - RedResponse->Payload = (REDFISH_PAYLOAD)patchPayloadEx (
> + RedResponse->Payload = (REDFISH_PAYLOAD)patchPayload (
> Target,
> Payload,
> - &RedResponse->Headers,
> - &RedResponse->HeaderCount,
> &(RedResponse->StatusCode)
> );
>
> @@ -585,6 +610,104 @@ RedfishPatchToPayload (
> return EFI_SUCCESS;
> }
>
> +/**
> + Use HTTP POST to create new Redfish resource in the Resource Collection.
> +
> + The POST request should be submitted to the Resource Collection in which
> the new resource
> + is to belong. The Resource Collection is addressed by URI. The Redfish may
> + ignore any service controlled properties. The corresponding redfish
> response will returned,
> + including HTTP StatusCode, Headers and Payload which record any HTTP
> response messages.
> +
> + Callers are responsible for freeing the HTTP StatusCode, Headers and
> Payload returned in
> + redfish response data.
> +
> + @param[in] RedfishService The Service to access the Redfish resources.
> + @param[in] Uri Relative path to address the resource.
> + @param[in] Content JSON represented properties to be update.
> + @param[in] ContentSize Size of the Content to be send to Redfish
> service
> + @param[in] ContentType Type of the Content to be send to Redfish
> service
> + @param[out] RedResponse Pointer to the Redfish response data.
> +
> + @retval EFI_SUCCESS The operation is successful, indicates the HTTP
> StatusCode is not
> + NULL and the value is 2XX. The Redfish resource will be
> returned
> + in Payload within RedResponse if server send it back in the
> HTTP
> + response message body.
> + @retval EFI_INVALID_PARAMETER RedfishService, Uri, Content, or
> RedResponse is NULL.
> + @retval EFI_DEVICE_ERROR An unexpected system or network error
> occurred. Callers can get
> + more error info from returned HTTP StatusCode, Headers
> and Payload
> + within RedResponse:
> + 1. If the returned StatusCode is NULL, indicates any error
> happen.
> + 2. If the returned StatusCode is not NULL and the value is
> not 2XX,
> + indicates any error happen.
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishPostToUri (
> + IN REDFISH_SERVICE RedfishService,
> + IN CONST CHAR8 *Uri,
> + IN CONST CHAR8 *Content,
> + IN UINTN ContentSize OPTIONAL,
> + IN CONST CHAR8 *ContentType OPTIONAL,
> + OUT REDFISH_RESPONSE *RedResponse
> + )
> +{
> + EFI_STATUS Status;
> + EDKII_JSON_VALUE JsonValue;
> +
> + Status = EFI_SUCCESS;
> + JsonValue = NULL;
> +
> + if ((RedfishService == NULL) || (Uri == NULL) || (Content == NULL) ||
> (RedResponse == NULL)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));
> +
> + JsonValue = (EDKII_JSON_VALUE)postUriFromServiceEx (
> + RedfishService,
> + Uri,
> + Content,
> + ContentSize,
> + ContentType,
> + &(RedResponse->Headers),
> + &(RedResponse->HeaderCount),
> + &(RedResponse->StatusCode)
> + );
> +
> + //
> + // 1. If the returned StatusCode is NULL, indicates any error happen.
> + //
> + if (RedResponse->StatusCode == NULL) {
> + Status = EFI_DEVICE_ERROR;
> + goto ON_EXIT;
> + }
> +
> + //
> + // 2. If the returned StatusCode is not NULL and the value is not 2XX,
> indicates any error happen.
> + // NOTE: If there is any error message returned from server, it will be
> returned in
> + // Payload within RedResponse.
> + //
> + if ((*(RedResponse->StatusCode) < HTTP_STATUS_200_OK) || \
> + (*(RedResponse->StatusCode) > HTTP_STATUS_206_PARTIAL_CONTENT))
> + {
> + Status = EFI_DEVICE_ERROR;
> + }
> +
> +ON_EXIT:
> + if (JsonValue != NULL) {
> + RedResponse->Payload = createRedfishPayload (JsonValue,
> RedfishService);
> + if (RedResponse->Payload == NULL) {
> + //
> + // Ignore the error when create RedfishPayload, just free the JsonValue
> since it's not what
> + // we care about if the returned StatusCode is 2XX.
> + //
> + JsonValueFree (JsonValue);
> + }
> + }
> +
> + return Status;
> +}
> +
> /**
> Use HTTP POST to create a new resource in target payload.
>
> @@ -600,7 +723,7 @@ RedfishPatchToPayload (
> @param[in] Payload The new resource to be created.
> @param[out] RedResponse Pointer to the Redfish response data.
>
> - @retval EFI_SUCCESS The opeartion is successful, indicates the HTTP
> StatusCode is not
> + @retval EFI_SUCCESS The operation is successful, indicates the HTTP
> StatusCode is not
> NULL and the value is 2XX. The Redfish resource will be
> returned
> in Payload within RedResponse if server send it back in the
> HTTP
> response message body.
> @@ -626,11 +749,9 @@ RedfishPostToPayload (
>
> ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));
>
> - RedResponse->Payload = (REDFISH_PAYLOAD)postPayloadEx (
> + RedResponse->Payload = (REDFISH_PAYLOAD)postPayload (
> Target,
> Payload,
> - &RedResponse->Headers,
> - &RedResponse->HeaderCount,
> &(RedResponse->StatusCode)
> );
>
> @@ -670,7 +791,7 @@ RedfishPostToPayload (
> @param[in] Uri Relative path to address the resource.
> @param[out] RedResponse Pointer to the Redfish response data.
>
> - @retval EFI_SUCCESS The opeartion is successful, indicates the HTTP
> StatusCode is not
> + @retval EFI_SUCCESS The operation is successful, indicates the HTTP
> StatusCode is not
> NULL and the value is 2XX, the Redfish resource has been
> removed.
> If there is any message returned from server, it will be
> returned
> in Payload within RedResponse.
> @@ -742,6 +863,96 @@ ON_EXIT:
> return Status;
> }
>
> +/**
> + Use HTTP DELETE to remove a resource.
> +
> + This function uses the RedfishService to remove a Redfish resource which is
> addressed
> + by input Uri (only the relative path is required). The corresponding redfish
> response will
> + returned, including HTTP StatusCode, Headers and Payload which record
> any HTTP response
> + messages.
> +
> + Callers are responsible for freeing the HTTP StatusCode, Headers and
> Payload returned in
> + redfish response data.
> +
> + @param[in] RedfishService The Service to access the Redfish resources.
> + @param[in] Uri Relative path to address the resource.
> + @param[in] Content JSON represented properties to be deleted.
> + @param[out] RedResponse Pointer to the Redfish response data.
> +
> + @retval EFI_SUCCESS The operation is successful, indicates the HTTP
> StatusCode is not
> + NULL and the value is 2XX, the Redfish resource has been
> removed.
> + If there is any message returned from server, it will be
> returned
> + in Payload within RedResponse.
> + @retval EFI_INVALID_PARAMETER RedfishService, Uri, or RedResponse is
> NULL.
> + @retval EFI_DEVICE_ERROR An unexpected system or network error
> occurred. Callers can get
> + more error info from returned HTTP StatusCode, Headers
> and Payload
> + within RedResponse:
> + 1. If the returned StatusCode is NULL, indicates any error
> happen.
> + 2. If the returned StatusCode is not NULL and the value is
> not 2XX,
> + indicates any error happen.
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishDeleteByUriEx (
> + IN REDFISH_SERVICE RedfishService,
> + IN CONST CHAR8 *Uri,
> + IN CONST CHAR8 *Content,
> + OUT REDFISH_RESPONSE *RedResponse
> + )
> +{
> + EFI_STATUS Status;
> + EDKII_JSON_VALUE JsonValue;
> +
> + Status = EFI_SUCCESS;
> + JsonValue = NULL;
> +
> + if ((RedfishService == NULL) || (Content == NULL) || (Uri == NULL) ||
> (RedResponse == NULL)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));
> +
> + JsonValue = (EDKII_JSON_VALUE)deleteUriFromServiceEx (
> + RedfishService,
> + Uri,
> + Content,
> + &(RedResponse->StatusCode)
> + );
> +
> + //
> + // 1. If the returned StatusCode is NULL, indicates any error happen.
> + //
> + if (RedResponse->StatusCode == NULL) {
> + Status = EFI_DEVICE_ERROR;
> + goto ON_EXIT;
> + }
> +
> + //
> + // 2. If the returned StatusCode is not NULL and the value is not 2XX,
> indicates any error happen.
> + // NOTE: If there is any error message returned from server, it will be
> returned in
> + // Payload within RedResponse.
> + //
> + if ((*(RedResponse->StatusCode) < HTTP_STATUS_200_OK) || \
> + (*(RedResponse->StatusCode) > HTTP_STATUS_206_PARTIAL_CONTENT))
> + {
> + Status = EFI_DEVICE_ERROR;
> + }
> +
> +ON_EXIT:
> + if (JsonValue != NULL) {
> + RedResponse->Payload = createRedfishPayload (JsonValue,
> RedfishService);
> + if (RedResponse->Payload == NULL) {
> + //
> + // Ignore the error when create RedfishPayload, just free the JsonValue
> since it's not what
> + // we care about if the returned StatusCode is 2XX.
> + //
> + JsonValueFree (JsonValue);
> + }
> + }
> +
> + return Status;
> +}
> +
> /**
> Dump text in fractions.
>
> @@ -878,7 +1089,7 @@ RedfishFreeResponse (
> Check if the "@odata.type" in Payload is valid or not.
>
> @param[in] Payload The Redfish payload to be checked.
> - @param[in] OdataTypeName OdataType will be retrived from
> mapping list.
> + @param[in] OdataTypeName OdataType will be retrieved from
> mapping list.
> @param[in] OdataTypeMappingList The list of OdataType.
> @param[in] OdataTypeMappingListSize The number of mapping list
>
> @@ -945,7 +1156,7 @@ RedfishIsPayloadCollection (
> @param[in] Payload The Redfish collection payload
> @param[in] CollectionSize Size of this collection
>
> - @return EFI_SUCCESS Coolection size is returned in CollectionSize
> + @return EFI_SUCCESS Collection size is returned in CollectionSize
> @return EFI_INVALID_PARAMETER The payload is not a collection.
> **/
> EFI_STATUS
> @@ -1035,3 +1246,103 @@ RedfishCheckIfRedpathExist (
>
> return EFI_SUCCESS;
> }
> +
> +/**
> + Use HTTP PUT to create new Redfish resource in the Resource Collection.
> +
> + This function uses the RedfishService to put a Redfish resource addressed by
> + Uri (only the relative path is required). Changes to one or more properties
> within
> + the target resource are represented in the input Content, properties not
> specified
> + in Content won't be changed by this request. The corresponding redfish
> response will
> + returned, including HTTP StatusCode, Headers and Payload which record
> any HTTP response
> + messages.
> +
> + Callers are responsible for freeing the HTTP StatusCode, Headers and
> Payload returned in
> + redfish response data.
> +
> + @param[in] RedfishService The Service to access the Redfish resources.
> + @param[in] Uri Relative path to address the resource.
> + @param[in] Content JSON represented properties to be update.
> + @param[in] ContentSize Size of the Content to be send to Redfish
> service
> + @param[in] ContentType Type of the Content to be send to Redfish
> service
> + @param[out] RedResponse Pointer to the Redfish response data.
> +
> + @retval EFI_SUCCESS The operation is successful, indicates the HTTP
> StatusCode is not
> + NULL and the value is 2XX. The Redfish resource will be
> returned
> + in Payload within RedResponse if server send it back in the
> HTTP
> + response message body.
> + @retval EFI_INVALID_PARAMETER RedfishService, Uri, Content, or
> RedResponse is NULL.
> + @retval EFI_DEVICE_ERROR An unexpected system or network error
> occurred. Callers can get
> + more error info from returned HTTP StatusCode, Headers
> and Payload
> + within RedResponse:
> + 1. If the returned StatusCode is NULL, indicates any error
> happen.
> + 2. If the returned StatusCode is not NULL and the value is
> not 2XX,
> + indicates any error happen.
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishPutToUri (
> + IN REDFISH_SERVICE RedfishService,
> + IN CONST CHAR8 *Uri,
> + IN CONST CHAR8 *Content,
> + IN UINTN ContentSize OPTIONAL,
> + IN CONST CHAR8 *ContentType OPTIONAL,
> + OUT REDFISH_RESPONSE *RedResponse
> + )
> +{
> + EFI_STATUS Status;
> + EDKII_JSON_VALUE JsonValue;
> +
> + Status = EFI_SUCCESS;
> + JsonValue = NULL;
> +
> + if ((RedfishService == NULL) || (Uri == NULL) || (Content == NULL) ||
> (RedResponse == NULL)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));
> +
> + JsonValue = (EDKII_JSON_VALUE)putUriFromServiceEx (
> + RedfishService,
> + Uri,
> + Content,
> + ContentSize,
> + ContentType,
> + &(RedResponse->Headers),
> + &(RedResponse->HeaderCount),
> + &(RedResponse->StatusCode)
> + );
> +
> + //
> + // 1. If the returned StatusCode is NULL, indicates any error happen.
> + //
> + if (RedResponse->StatusCode == NULL) {
> + Status = EFI_DEVICE_ERROR;
> + goto ON_EXIT;
> + }
> +
> + //
> + // 2. If the returned StatusCode is not NULL and the value is not 2XX,
> indicates any error happen.
> + // NOTE: If there is any error message returned from server, it will be
> returned in
> + // Payload within RedResponse.
> + //
> + if ((*(RedResponse->StatusCode) < HTTP_STATUS_200_OK) || \
> + (*(RedResponse->StatusCode) > HTTP_STATUS_206_PARTIAL_CONTENT))
> + {
> + Status = EFI_DEVICE_ERROR;
> + }
> +
> +ON_EXIT:
> + if (JsonValue != NULL) {
> + RedResponse->Payload = createRedfishPayload (JsonValue,
> RedfishService);
> + if (RedResponse->Payload == NULL) {
> + //
> + // Ignore the error when create RedfishPayload, just free the JsonValue
> since it's not what
> + // we care about if the returned StatusCode is 2XX.
> + //
> + JsonValueFree (JsonValue);
> + }
> + }
> +
> + return Status;
> +}
> diff --git a/RedfishClientPkg/PrivateLibrary/RedfishLib/RedfishMisc.c
> b/RedfishClientPkg/PrivateLibrary/RedfishLib/RedfishMisc.c
> index 0eb23196..b6e9a111 100644
> --- a/RedfishClientPkg/PrivateLibrary/RedfishLib/RedfishMisc.c
> +++ b/RedfishClientPkg/PrivateLibrary/RedfishLib/RedfishMisc.c
> @@ -3,6 +3,7 @@
>
> Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
> + Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights
> reserved.
>
> SPDX-License-Identifier: BSD-2-Clause-Patent
>
> @@ -168,18 +169,18 @@ RedfishGetAuthInfo (
> /**
> This function returns the string of Redfish service version.
>
> - @param[in] ServiceVerisonStr The string of Redfish service version.
> + @param[in] ServiceVersionStr The string of Redfish service version.
> @param[in] Url The URL to build Redpath with ID.
> Start with "/", for example "/Registries"
> @param[in] Id ID string
> - @param[out] Redpath Pointer to retrive Redpath, caller has to free
> + @param[out] Redpath Pointer to retrieved Redpath, caller has to free
> the memory allocated for this string.
> @return EFI_STATUS
>
> **/
> EFI_STATUS
> RedfishBuildRedpathUseId (
> - IN CHAR8 *ServiceVerisonStr,
> + IN CHAR8 *ServiceVersionStr,
> IN CHAR8 *Url,
> IN CHAR8 *Id,
> OUT CHAR8 **Redpath
> @@ -187,12 +188,12 @@ RedfishBuildRedpathUseId (
> {
> UINTN RedpathSize;
>
> - if ((Redpath == NULL) || (ServiceVerisonStr == NULL) || (Url == NULL) || (Id
> == NULL)) {
> + if ((Redpath == NULL) || (ServiceVersionStr == NULL) || (Url == NULL) || (Id
> == NULL)) {
> return EFI_INVALID_PARAMETER;
> }
>
> RedpathSize = AsciiStrLen ("/") +
> - AsciiStrLen (ServiceVerisonStr) +
> + AsciiStrLen (ServiceVersionStr) +
> AsciiStrLen (Url) +
> AsciiStrLen ("[Id=]") +
> AsciiStrLen (Id) + 1;
> @@ -201,6 +202,6 @@ RedfishBuildRedpathUseId (
> return EFI_OUT_OF_RESOURCES;
> }
>
> - AsciiSPrint (*Redpath, RedpathSize, "/%a%a[Id=%a]", ServiceVerisonStr, Url,
> Id);
> + AsciiSPrint (*Redpath, RedpathSize, "/%a%a[Id=%a]", ServiceVersionStr, Url,
> Id);
> return EFI_SUCCESS;
> }
> diff --git
> a/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/payload.c
> b/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/payload.c
> index 8ec2ed4a..39803575 100644
> --- a/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/payload.c
> +++
> b/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/payload.c
> @@ -10,6 +10,7 @@
>
> Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>
> + Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights
> reserved.
>
> SPDX-License-Identifier: BSD-2-Clause-Patent
>
> @@ -379,45 +380,6 @@ getPayloadForPathString (
> return ret;
> }
>
> -redfishPayload *
> -patchPayloadEx (
> - redfishPayload *target,
> - redfishPayload *payload,
> - EFI_HTTP_HEADER **Headers,
> - UINTN *HeaderCount,
> - EFI_HTTP_STATUS_CODE **StatusCode
> - )
> -{
> - json_t *json;
> - char *content;
> - char *uri;
> -
> - if (!target || !payload || (StatusCode == NULL)) {
> - return NULL;
> - }
> -
> - *StatusCode = NULL;
> -
> - json = json_object_get (target->json, "@odata.id");
> - if (json == NULL) {
> - return NULL;
> - }
> -
> - uri = strdup (json_string_value (json));
> -
> - content = json_dumps (payload->json, 0);
> - json_decref (json);
> -
> - json = patchUriFromServiceEx (target->service, uri, content, Headers,
> HeaderCount, StatusCode);
> - free (uri);
> - free (content);
> - if (json == NULL) {
> - return NULL;
> - }
> -
> - return createRedfishPayload (json, target->service);
> -}
> -
> redfishPayload *
> patchPayload (
> redfishPayload *target,
> @@ -455,44 +417,6 @@ patchPayload (
> return createRedfishPayload (json, target->service);
> }
>
> -redfishPayload *
> -postContentToPayloadEx (
> - redfishPayload *target,
> - const char *data,
> - size_t dataSize,
> - const char *contentType,
> - EFI_HTTP_HEADER **Headers,
> - UINTN *HeaderCount,
> - EFI_HTTP_STATUS_CODE **StatusCode
> - )
> -{
> - json_t *json;
> - char *uri;
> -
> - if (!target || !data || (StatusCode == NULL)) {
> - return NULL;
> - }
> -
> - *StatusCode = NULL;
> -
> - json = json_object_get (target->json, "@odata.id");
> - if (json == NULL) {
> - json = json_object_get (target->json, "target");
> - if (json == NULL) {
> - return NULL;
> - }
> - }
> -
> - uri = strdup (json_string_value (json));
> - json = postUriFromServiceEx (target->service, uri, data, dataSize,
> contentType, Headers, HeaderCount, StatusCode);
> - free (uri);
> - if (json == NULL) {
> - return NULL;
> - }
> -
> - return createRedfishPayload (json, target->service);
> -}
> -
> redfishPayload *
> postContentToPayload (
> redfishPayload *target,
> @@ -529,34 +453,6 @@ postContentToPayload (
> return createRedfishPayload (json, target->service);
> }
>
> -redfishPayload *
> -postPayloadEx (
> - redfishPayload *target,
> - redfishPayload *payload,
> - EFI_HTTP_HEADER **Headers,
> - UINTN *HeaderCount,
> - EFI_HTTP_STATUS_CODE **StatusCode
> - )
> -{
> - char *content;
> - redfishPayload *ret;
> -
> - if (!target || !payload || (StatusCode == NULL)) {
> - return NULL;
> - }
> -
> - *StatusCode = NULL;
> -
> - if (!json_is_object (payload->json)) {
> - return NULL;
> - }
> -
> - content = payloadToString (payload, false);
> - ret = postContentToPayloadEx (target, content, strlen (content), NULL,
> Headers, HeaderCount, StatusCode);
> - free (content);
> - return ret;
> -}
> -
> redfishPayload *
> postPayload (
> redfishPayload *target,
> @@ -629,7 +525,7 @@ getOpResult (
> }
>
> stringProp = prop->json;
> - jsonType = json_get_type (prop->json);
> + jsonType = JsonGetType (prop->json);
> switch (jsonType) {
> case JSON_OBJECT:
> stringProp = json_object_get (prop->json, propName);
> @@ -725,6 +621,7 @@ collectionEvalOp (
> if (((*StatusCode == NULL) && (members == NULL)) ||
> ((*StatusCode != NULL) && ((**StatusCode < HTTP_STATUS_200_OK) ||
> (**StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT))))
> {
> + free (valid);
> return members;
> }
>
> @@ -738,6 +635,7 @@ collectionEvalOp (
> if (((*StatusCode == NULL) && (tmp == NULL)) ||
> ((*StatusCode != NULL) && ((**StatusCode < HTTP_STATUS_200_OK) ||
> (**StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT))))
> {
> + free (valid);
> return tmp;
> }
>
> @@ -763,19 +661,15 @@ collectionEvalOp (
>
> cleanupPayload (members);
> if (validCount == 0) {
> - free (valid);
> - return NULL;
> - }
> -
> - if (validCount == 1) {
> + ret = NULL;
> + } else if (validCount == 1) {
> ret = valid[0];
> - free (valid);
> - return ret;
> } else {
> ret = createCollection (payload->service, validCount, valid);
> - free (valid);
> - return ret;
> }
> +
> + free (valid);
> + return ret;
> }
>
> static redfishPayload *
> diff --git
> a/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/service.c
> b/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/service.c
> index a38bdfbe..58c23e8c 100644
> --- a/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/service.c
> +++
> b/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/service.c
> @@ -10,6 +10,7 @@
>
> Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>
> + Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights
> reserved.
>
> SPDX-License-Identifier: BSD-2-Clause-Patent
>
> @@ -279,9 +280,9 @@ DecodeResponseContent (
> **/
> EFI_STATUS
> RedfishBuildUrl (
> - IN REDFISH_CONFIG_SERVICE_INFORMATION *RedfishConfigServiceInfo,
> - IN CHAR16 *RelativePath, OPTIONAL
> - OUT CHAR16 **HttpUrl
> + IN REDFISH_CONFIG_SERVICE_INFORMATION *RedfishConfigServiceInfo,
> + IN CHAR16 *RelativePath OPTIONAL,
> + OUT CHAR16 **HttpUrl
> )
> {
> CHAR16 *Url;
> @@ -434,8 +435,8 @@ json_t *
> getUriFromServiceEx (
> redfishService *service,
> const char *uri,
> - EFI_HTTP_HEADER **Headers,
> - UINTN *HeaderCount,
> + EFI_HTTP_HEADER **Headers OPTIONAL,
> + UINTN *HeaderCount OPTIONAL,
> EFI_HTTP_STATUS_CODE **StatusCode
> )
> {
> @@ -448,20 +449,25 @@ getUriFromServiceEx (
> EFI_HTTP_MESSAGE ResponseMsg;
> EFI_HTTP_HEADER *ContentEncodedHeader;
>
> - if ((service == NULL) || (uri == NULL) || (Headers == NULL) || (HeaderCount
> == NULL) || (StatusCode == NULL)) {
> + if ((service == NULL) || (uri == NULL) || (StatusCode == NULL)) {
> return NULL;
> }
>
> - *StatusCode = NULL;
> - *HeaderCount = 0;
> - *Headers = NULL;
> + *StatusCode = NULL;
> + if (HeaderCount != NULL) {
> + *HeaderCount = 0;
> + }
> +
> + if (Headers != NULL) {
> + *Headers = NULL;
> + }
>
> url = makeUrlForService (service, uri);
> if (!url) {
> return NULL;
> }
>
> - DEBUG ((DEBUG_MANAGEABILITY, "libredfish: getUriFromServiceEx():
> %a\n", url));
> + DEBUG ((DEBUG_MANAGEABILITY, "%a: %a\n", __func__, url));
>
> //
> // Step 1: Create HTTP request message with 4 headers:
> @@ -524,166 +530,23 @@ getUriFromServiceEx (
> Status = service->RestEx->SendReceive (service->RestEx, RequestMsg,
> &ResponseMsg);
> if (EFI_ERROR (Status)) {
> ret = NULL;
> - goto ON_EXIT;
> - }
> -
> - //
> - // Step 5: Return the HTTP StatusCode and Body message.
> - //
> - if (ResponseMsg.Data.Response != NULL) {
> - *StatusCode = AllocateZeroPool (sizeof (EFI_HTTP_STATUS_CODE));
> - if (*StatusCode == NULL) {
> - ret = NULL;
> - goto ON_EXIT;
> - }
>
> //
> - // The caller shall take the responsibility to free the buffer.
> + // Deliver status code to caller when error happens so caller can do error
> handling.
> //
> - **StatusCode = ResponseMsg.Data.Response->StatusCode;
> - }
> -
> - if (ResponseMsg.Headers != NULL) {
> - *Headers = cloneHttpHeaders (&ResponseMsg, HeaderCount);
> - }
> -
> - if ((ResponseMsg.BodyLength != 0) && (ResponseMsg.Body != NULL)) {
> - //
> - // Check if data is encoded.
> - //
> - ContentEncodedHeader = HttpFindHeader (ResponseMsg.HeaderCount,
> ResponseMsg.Headers, HTTP_HEADER_CONTENT_ENCODING);
> - if (ContentEncodedHeader != NULL) {
> - //
> - // The content is encoded.
> - //
> - Status = DecodeResponseContent (ContentEncodedHeader->FieldValue,
> &ResponseMsg.Body, &ResponseMsg.BodyLength);
> - if (EFI_ERROR (Status)) {
> - DEBUG ((DEBUG_ERROR, "%a: Failed to decompress the response
> content %r\n.", __func__, Status));
> + if (ResponseMsg.Data.Response != NULL) {
> + *StatusCode = AllocateZeroPool (sizeof (EFI_HTTP_STATUS_CODE));
> + if (*StatusCode == NULL) {
> ret = NULL;
> goto ON_EXIT;
> }
> - }
> -
> - ret = json_loadb (ResponseMsg.Body, ResponseMsg.BodyLength, 0, NULL);
> - } else {
> - //
> - // There is no message body returned from server.
> - //
> - ret = NULL;
> - }
>
> -ON_EXIT:
> - if (url != NULL) {
> - free (url);
> - }
> -
> - if (HttpIoHeader != NULL) {
> - HttpIoFreeHeader (HttpIoHeader);
> - }
> -
> - if (RequestData != NULL) {
> - RestConfigFreeHttpRequestData (RequestData);
> - }
> -
> - if (RequestMsg != NULL) {
> - FreePool (RequestMsg);
> - }
> -
> - RestConfigFreeHttpMessage (&ResponseMsg, FALSE);
> -
> - return ret;
> -}
> -
> -json_t *
> -getUriFromService (
> - redfishService *service,
> - const char *uri,
> - EFI_HTTP_STATUS_CODE **StatusCode
> - )
> -{
> - char *url;
> - json_t *ret;
> - HTTP_IO_HEADER *HttpIoHeader = NULL;
> - EFI_STATUS Status;
> - EFI_HTTP_REQUEST_DATA *RequestData = NULL;
> - EFI_HTTP_MESSAGE *RequestMsg = NULL;
> - EFI_HTTP_MESSAGE ResponseMsg;
> - EFI_HTTP_HEADER *ContentEncodedHeader;
> -
> - if ((service == NULL) || (uri == NULL) || (StatusCode == NULL)) {
> - return NULL;
> - }
> -
> - *StatusCode = NULL;
> -
> - url = makeUrlForService (service, uri);
> - if (!url) {
> - return NULL;
> - }
> -
> - DEBUG ((DEBUG_MANAGEABILITY, "libredfish: getUriFromService(): %a\n",
> url));
> -
> - //
> - // Step 1: Create HTTP request message with 4 headers:
> - //
> - HttpIoHeader = HttpIoCreateHeader ((service->sessionToken || service-
> >basicAuthStr) ? 6 : 5);
> - if (HttpIoHeader == NULL) {
> - ret = NULL;
> - goto ON_EXIT;
> - }
> -
> - if (service->sessionToken) {
> - Status = HttpIoSetHeader (HttpIoHeader, "X-Auth-Token", service-
> >sessionToken);
> - ASSERT_EFI_ERROR (Status);
> - } else if (service->basicAuthStr) {
> - Status = HttpIoSetHeader (HttpIoHeader, "Authorization", service-
> >basicAuthStr);
> - ASSERT_EFI_ERROR (Status);
> - }
> -
> - Status = HttpIoSetHeader (HttpIoHeader, "Host", service-
> >HostHeaderValue);
> - ASSERT_EFI_ERROR (Status);
> - Status = HttpIoSetHeader (HttpIoHeader, "OData-Version", "4.0");
> - ASSERT_EFI_ERROR (Status);
> - Status = HttpIoSetHeader (HttpIoHeader, "Accept", "application/json");
> - ASSERT_EFI_ERROR (Status);
> - Status = HttpIoSetHeader (HttpIoHeader, "User-Agent", "libredfish");
> - ASSERT_EFI_ERROR (Status);
> - Status = HttpIoSetHeader (HttpIoHeader, "Connection", "Keep-Alive");
> - ASSERT_EFI_ERROR (Status);
> -
> - //
> - // Step 2: build the rest of HTTP request info.
> - //
> - RequestData = AllocateZeroPool (sizeof (EFI_HTTP_REQUEST_DATA));
> - if (RequestData == NULL) {
> - ret = NULL;
> - goto ON_EXIT;
> - }
> -
> - RequestData->Method = HttpMethodGet;
> - RequestData->Url = C8ToC16 (url);
> -
> - //
> - // Step 3: fill in EFI_HTTP_MESSAGE
> - //
> - RequestMsg = AllocateZeroPool (sizeof (EFI_HTTP_MESSAGE));
> - if (RequestMsg == NULL) {
> - ret = NULL;
> - goto ON_EXIT;
> - }
> -
> - RequestMsg->Data.Request = RequestData;
> - RequestMsg->HeaderCount = HttpIoHeader->HeaderCount;
> - RequestMsg->Headers = HttpIoHeader->Headers;
> -
> - ZeroMem (&ResponseMsg, sizeof (ResponseMsg));
> + //
> + // The caller shall take the responsibility to free the buffer.
> + //
> + **StatusCode = ResponseMsg.Data.Response->StatusCode;
> + }
>
> - //
> - // Step 4: call RESTEx to get response from REST service.
> - //
> - Status = service->RestEx->SendReceive (service->RestEx, RequestMsg,
> &ResponseMsg);
> - if (EFI_ERROR (Status)) {
> - ret = NULL;
> goto ON_EXIT;
> }
>
> @@ -703,6 +566,10 @@ getUriFromService (
> **StatusCode = ResponseMsg.Data.Response->StatusCode;
> }
>
> + if ((ResponseMsg.Headers != NULL) && (Headers != NULL) &&
> (HeaderCount != NULL)) {
> + *Headers = cloneHttpHeaders (&ResponseMsg, HeaderCount);
> + }
> +
> if ((ResponseMsg.BodyLength != 0) && (ResponseMsg.Body != NULL)) {
> //
> // Check if data is encoded.
> @@ -751,12 +618,14 @@ ON_EXIT:
> }
>
> json_t *
> -patchUriFromServiceEx (
> +putUriFromServiceEx (
> redfishService *service,
> const char *uri,
> const char *content,
> - EFI_HTTP_HEADER **Headers,
> - UINTN *HeaderCount,
> + size_t contentLength,
> + const char *contentType,
> + EFI_HTTP_HEADER **Headers OPTIONAL,
> + UINTN *HeaderCount OPTIONAL,
> EFI_HTTP_STATUS_CODE **StatusCode
> )
> {
> @@ -776,18 +645,29 @@ patchUriFromServiceEx (
> }
>
> *StatusCode = NULL;
> + if (HeaderCount != NULL) {
> + *HeaderCount = 0;
> + }
> +
> + if (Headers != NULL) {
> + *Headers = NULL;
> + }
>
> url = makeUrlForService (service, uri);
> - if (!url) {
> + if (url == NULL) {
> return NULL;
> }
>
> - DEBUG ((DEBUG_MANAGEABILITY, "libredfish: patchUriFromService():
> %a\n", url));
> + DEBUG ((DEBUG_MANAGEABILITY, "%a: %a\n", __func__, url));
> +
> + if (contentLength == 0) {
> + contentLength = strlen (content);
> + }
>
> //
> // Step 1: Create HTTP request message with 4 headers:
> //
> - HttpIoHeader = HttpIoCreateHeader ((service->sessionToken || service-
> >basicAuthStr) ? 9 : 8);
> + HttpIoHeader = HttpIoCreateHeader ((service->sessionToken != NULL ||
> service->basicAuthStr != NULL) ? 9 : 8);
> if (HttpIoHeader == NULL) {
> ret = NULL;
> goto ON_EXIT;
> @@ -801,6 +681,14 @@ patchUriFromServiceEx (
> ASSERT_EFI_ERROR (Status);
> }
>
> + if (contentType == NULL) {
> + Status = HttpIoSetHeader (HttpIoHeader, "Content-Type",
> "application/json");
> + ASSERT_EFI_ERROR (Status);
> + } else {
> + Status = HttpIoSetHeader (HttpIoHeader, "Content-Type", (CHAR8
> *)contentType);
> + ASSERT_EFI_ERROR (Status);
> + }
> +
> Status = HttpIoSetHeader (HttpIoHeader, "Host", service->HostHeaderValue);
> ASSERT_EFI_ERROR (Status);
> Status = HttpIoSetHeader (HttpIoHeader, "Content-Type",
> "application/json");
> @@ -816,7 +704,7 @@ patchUriFromServiceEx (
> ContentLengthStr,
> sizeof (ContentLengthStr),
> "%lu",
> - (UINT64)strlen (content)
> + (UINT64)contentLength
> );
> Status = HttpIoSetHeader (HttpIoHeader, "Content-Length",
> ContentLengthStr);
> ASSERT_EFI_ERROR (Status);
> @@ -832,7 +720,7 @@ patchUriFromServiceEx (
> goto ON_EXIT;
> }
>
> - RequestData->Method = HttpMethodPatch;
> + RequestData->Method = HttpMethodPut;
> RequestData->Url = C8ToC16 (url);
>
> //
> @@ -845,7 +733,7 @@ patchUriFromServiceEx (
> }
>
> EncodedContent = (CHAR8 *)content;
> - EncodedContentLen = strlen (content);
> + EncodedContentLen = contentLength;
> //
> // We currently only support gzip Content-Encoding.
> //
> @@ -896,7 +784,7 @@ patchUriFromServiceEx (
> **StatusCode = ResponseMsg.Data.Response->StatusCode;
> }
>
> - if (ResponseMsg.Headers != NULL) {
> + if ((ResponseMsg.Headers != NULL) && (Headers != NULL) &&
> (HeaderCount != NULL)) {
> *Headers = cloneHttpHeaders (&ResponseMsg, HeaderCount);
> }
>
> @@ -936,10 +824,12 @@ ON_EXIT:
> }
>
> json_t *
> -patchUriFromService (
> +patchUriFromServiceEx (
> redfishService *service,
> const char *uri,
> const char *content,
> + EFI_HTTP_HEADER **Headers OPTIONAL,
> + UINTN *HeaderCount OPTIONAL,
> EFI_HTTP_STATUS_CODE **StatusCode
> )
> {
> @@ -959,13 +849,20 @@ patchUriFromService (
> }
>
> *StatusCode = NULL;
> + if (HeaderCount != NULL) {
> + *HeaderCount = 0;
> + }
> +
> + if (Headers != NULL) {
> + *Headers = NULL;
> + }
>
> url = makeUrlForService (service, uri);
> if (!url) {
> return NULL;
> }
>
> - DEBUG ((DEBUG_MANAGEABILITY, "libredfish: patchUriFromService():
> %a\n", url));
> + DEBUG ((DEBUG_MANAGEABILITY, "%a: %a\n", __func__, url));
>
> //
> // Step 1: Create HTTP request message with 4 headers:
> @@ -1079,6 +976,10 @@ patchUriFromService (
> **StatusCode = ResponseMsg.Data.Response->StatusCode;
> }
>
> + if ((ResponseMsg.Headers != NULL) && (Headers != NULL) &&
> (HeaderCount != NULL)) {
> + *Headers = cloneHttpHeaders (&ResponseMsg, HeaderCount);
> + }
> +
> if (EncodedContent != content) {
> FreePool (EncodedContent);
> }
> @@ -1121,8 +1022,8 @@ postUriFromServiceEx (
> const char *content,
> size_t contentLength,
> const char *contentType,
> - EFI_HTTP_HEADER **Headers,
> - UINTN *HeaderCount,
> + EFI_HTTP_HEADER **Headers OPTIONAL,
> + UINTN *HeaderCount OPTIONAL,
> EFI_HTTP_STATUS_CODE **StatusCode
> )
> {
> @@ -1143,13 +1044,20 @@ postUriFromServiceEx (
> }
>
> *StatusCode = NULL;
> + if (HeaderCount != NULL) {
> + *HeaderCount = 0;
> + }
> +
> + if (Headers != NULL) {
> + *Headers = NULL;
> + }
>
> url = makeUrlForService (service, uri);
> if (!url) {
> return NULL;
> }
>
> - DEBUG ((DEBUG_MANAGEABILITY, "libredfish: postUriFromService():
> %a\n", url));
> + DEBUG ((DEBUG_MANAGEABILITY, "%a: %a\n", __func__, url));
>
> if (contentLength == 0) {
> contentLength = strlen (content);
> @@ -1230,7 +1138,12 @@ postUriFromServiceEx (
> //
> Status = service->RestEx->SendReceive (service->RestEx, RequestMsg,
> &ResponseMsg);
> if (EFI_ERROR (Status)) {
> - goto ON_EXIT;
> + //
> + // If there is no response to handle, go to error exit.
> + //
> + if (ResponseMsg.Data.Response == NULL) {
> + goto ON_EXIT;
> + }
> }
>
> //
> @@ -1248,7 +1161,7 @@ postUriFromServiceEx (
> **StatusCode = ResponseMsg.Data.Response->StatusCode;
> }
>
> - if (ResponseMsg.Headers != NULL) {
> + if ((ResponseMsg.Headers != NULL) && (Headers != NULL) &&
> (HeaderCount != NULL)) {
> *Headers = cloneHttpHeaders (&ResponseMsg, HeaderCount);
> }
>
> @@ -1257,10 +1170,11 @@ postUriFromServiceEx (
> }
>
> //
> - // Step 6: Parsing the HttpHeader to retrive the X-Auth-Token if the HTTP
> StatusCode is correct.
> + // Step 6: Parsing the HttpHeader to retrieve the X-Auth-Token if the HTTP
> StatusCode is correct.
> //
> - if ((ResponseMsg.Data.Response->StatusCode == HTTP_STATUS_200_OK)
> ||
> - (ResponseMsg.Data.Response->StatusCode ==
> HTTP_STATUS_204_NO_CONTENT))
> + if ((ResponseMsg.Data.Response != NULL) &&
> + ((ResponseMsg.Data.Response->StatusCode == HTTP_STATUS_200_OK)
> ||
> + (ResponseMsg.Data.Response->StatusCode ==
> HTTP_STATUS_204_NO_CONTENT)))
> {
> HttpHeader = HttpFindHeader (ResponseMsg.HeaderCount,
> ResponseMsg.Headers, "X-Auth-Token");
> if (HttpHeader != NULL) {
> @@ -1270,19 +1184,6 @@ postUriFromServiceEx (
>
> service->sessionToken = AllocateCopyPool (AsciiStrSize (HttpHeader-
> >FieldValue), HttpHeader->FieldValue);
> }
> -
> - /*
> - //
> - // Below opeation seems to be unnecessary.
> - // Besides, the FieldValue for the Location is the full HTTP URI
> (Http://0.0.0.0:5000/XXX), so we can't use it as the
> - // parameter of getUriFromService () directly.
> - //
> - HttpHeader = HttpFindHeader (ResponseMsg.HeaderCount,
> ResponseMsg.Headers, "Location");
> - if (HttpHeader != NULL) {
> - ret = getUriFromService(service, HttpHeader->FieldValue);
> - goto ON_EXIT;
> - }
> - */
> }
>
> ON_EXIT:
> @@ -1307,6 +1208,27 @@ ON_EXIT:
> return ret;
> }
>
> +json_t *
> +getUriFromService (
> + redfishService *service,
> + const char *uri,
> + EFI_HTTP_STATUS_CODE **StatusCode
> + )
> +{
> + return getUriFromServiceEx (service, uri, NULL, NULL, StatusCode);
> +}
> +
> +json_t *
> +patchUriFromService (
> + redfishService *service,
> + const char *uri,
> + const char *content,
> + EFI_HTTP_STATUS_CODE **StatusCode
> + )
> +{
> + return patchUriFromServiceEx (service, uri, content, NULL, NULL,
> StatusCode);
> +}
> +
> json_t *
> postUriFromService (
> redfishService *service,
> @@ -1317,187 +1239,14 @@ postUriFromService (
> EFI_HTTP_STATUS_CODE **StatusCode
> )
> {
> - char *url = NULL;
> - json_t *ret;
> - HTTP_IO_HEADER *HttpIoHeader = NULL;
> - EFI_STATUS Status;
> - EFI_HTTP_REQUEST_DATA *RequestData = NULL;
> - EFI_HTTP_MESSAGE *RequestMsg = NULL;
> - EFI_HTTP_MESSAGE ResponseMsg;
> - CHAR8 ContentLengthStr[80];
> - EFI_HTTP_HEADER *HttpHeader = NULL;
> -
> - ret = NULL;
> -
> - if ((service == NULL) || (uri == NULL) || (content == NULL) || (StatusCode ==
> NULL)) {
> - return NULL;
> - }
> -
> - *StatusCode = NULL;
> -
> - url = makeUrlForService (service, uri);
> - if (!url) {
> - return NULL;
> - }
> -
> - DEBUG ((DEBUG_MANAGEABILITY, "libredfish: postUriFromService():
> %a\n", url));
> -
> - if (contentLength == 0) {
> - contentLength = strlen (content);
> - }
> -
> - //
> - // Step 1: Create HTTP request message with 4 headers:
> - //
> - HttpIoHeader = HttpIoCreateHeader ((service->sessionToken || service-
> >basicAuthStr) ? 8 : 7);
> - if (HttpIoHeader == NULL) {
> - goto ON_EXIT;
> - }
> -
> - if (service->sessionToken) {
> - Status = HttpIoSetHeader (HttpIoHeader, "X-Auth-Token", service-
> >sessionToken);
> - ASSERT_EFI_ERROR (Status);
> - } else if (service->basicAuthStr) {
> - Status = HttpIoSetHeader (HttpIoHeader, "Authorization", service-
> >basicAuthStr);
> - ASSERT_EFI_ERROR (Status);
> - }
> -
> - if (contentType == NULL) {
> - Status = HttpIoSetHeader (HttpIoHeader, "Content-Type",
> "application/json");
> - ASSERT_EFI_ERROR (Status);
> - } else {
> - Status = HttpIoSetHeader (HttpIoHeader, "Content-Type", (CHAR8
> *)contentType);
> - ASSERT_EFI_ERROR (Status);
> - }
> -
> - Status = HttpIoSetHeader (HttpIoHeader, "Host", service-
> >HostHeaderValue);
> - ASSERT_EFI_ERROR (Status);
> - Status = HttpIoSetHeader (HttpIoHeader, "Accept", "application/json");
> - ASSERT_EFI_ERROR (Status);
> - Status = HttpIoSetHeader (HttpIoHeader, "User-Agent", "libredfish");
> - ASSERT_EFI_ERROR (Status);
> - Status = HttpIoSetHeader (HttpIoHeader, "Connection", "Keep-Alive");
> - ASSERT_EFI_ERROR (Status);
> - AsciiSPrint (
> - ContentLengthStr,
> - sizeof (ContentLengthStr),
> - "%lu",
> - (UINT64)contentLength
> - );
> - Status = HttpIoSetHeader (HttpIoHeader, "Content-Length",
> ContentLengthStr);
> - ASSERT_EFI_ERROR (Status);
> - Status = HttpIoSetHeader (HttpIoHeader, "OData-Version", "4.0");
> - ASSERT_EFI_ERROR (Status);
> -
> - //
> - // Step 2: build the rest of HTTP request info.
> - //
> - RequestData = AllocateZeroPool (sizeof (EFI_HTTP_REQUEST_DATA));
> - if (RequestData == NULL) {
> - goto ON_EXIT;
> - }
> -
> - RequestData->Method = HttpMethodPost;
> - RequestData->Url = C8ToC16 (url);
> -
> - //
> - // Step 3: fill in EFI_HTTP_MESSAGE
> - //
> - RequestMsg = AllocateZeroPool (sizeof (EFI_HTTP_MESSAGE));
> - if (RequestMsg == NULL) {
> - goto ON_EXIT;
> - }
> -
> - RequestMsg->Data.Request = RequestData;
> - RequestMsg->HeaderCount = HttpIoHeader->HeaderCount;
> - RequestMsg->Headers = HttpIoHeader->Headers;
> - RequestMsg->BodyLength = contentLength;
> - RequestMsg->Body = (VOID *)content;
> -
> - ZeroMem (&ResponseMsg, sizeof (ResponseMsg));
> -
> - //
> - // Step 4: call RESTEx to get response from REST service.
> - //
> - Status = service->RestEx->SendReceive (service->RestEx, RequestMsg,
> &ResponseMsg);
> - if (EFI_ERROR (Status)) {
> - goto ON_EXIT;
> - }
> -
> - //
> - // Step 5: Return the HTTP StatusCode and Body message.
> - //
> - if (ResponseMsg.Data.Response != NULL) {
> - *StatusCode = AllocateZeroPool (sizeof (EFI_HTTP_STATUS_CODE));
> - if (*StatusCode == NULL) {
> - goto ON_EXIT;
> - }
> -
> - //
> - // The caller shall take the responsibility to free the buffer.
> - //
> - **StatusCode = ResponseMsg.Data.Response->StatusCode;
> - }
> -
> - if ((ResponseMsg.BodyLength != 0) && (ResponseMsg.Body != NULL)) {
> - ret = json_loadb (ResponseMsg.Body, ResponseMsg.BodyLength, 0, NULL);
> - }
> -
> - //
> - // Step 6: Parsing the HttpHeader to retrive the X-Auth-Token if the HTTP
> StatusCode is correct.
> - //
> - if ((ResponseMsg.Data.Response->StatusCode == HTTP_STATUS_200_OK)
> ||
> - (ResponseMsg.Data.Response->StatusCode ==
> HTTP_STATUS_204_NO_CONTENT))
> - {
> - HttpHeader = HttpFindHeader (ResponseMsg.HeaderCount,
> ResponseMsg.Headers, "X-Auth-Token");
> - if (HttpHeader != NULL) {
> - if (service->sessionToken) {
> - free (service->sessionToken);
> - }
> -
> - service->sessionToken = AllocateCopyPool (AsciiStrSize (HttpHeader-
> >FieldValue), HttpHeader->FieldValue);
> - }
> -
> - /*
> - //
> - // Below opeation seems to be unnecessary.
> - // Besides, the FieldValue for the Location is the full HTTP URI
> (Http://0.0.0.0:5000/XXX), so we can't use it as the
> - // parameter of getUriFromService () directly.
> - //
> - HttpHeader = HttpFindHeader (ResponseMsg.HeaderCount,
> ResponseMsg.Headers, "Location");
> - if (HttpHeader != NULL) {
> - ret = getUriFromService(service, HttpHeader->FieldValue);
> - goto ON_EXIT;
> - }
> - */
> - }
> -
> -ON_EXIT:
> - if (url != NULL) {
> - free (url);
> - }
> -
> - if (HttpIoHeader != NULL) {
> - HttpIoFreeHeader (HttpIoHeader);
> - }
> -
> - if (RequestData != NULL) {
> - RestConfigFreeHttpRequestData (RequestData);
> - }
> -
> - if (RequestMsg != NULL) {
> - FreePool (RequestMsg);
> - }
> -
> - RestConfigFreeHttpMessage (&ResponseMsg, FALSE);
> -
> - return ret;
> + return postUriFromServiceEx (service, uri, content, contentLength,
> contentType, NULL, NULL, StatusCode);
> }
>
> json_t *
> -deleteUriFromService (
> +deleteUriFromServiceEx (
> redfishService *service,
> const char *uri,
> + const char *content,
> EFI_HTTP_STATUS_CODE **StatusCode
> )
> {
> @@ -1508,6 +1257,8 @@ deleteUriFromService (
> EFI_HTTP_REQUEST_DATA *RequestData = NULL;
> EFI_HTTP_MESSAGE *RequestMsg = NULL;
> EFI_HTTP_MESSAGE ResponseMsg;
> + CHAR8 ContentLengthStr[80];
> + size_t contentLength;
>
> ret = NULL;
>
> @@ -1527,7 +1278,7 @@ deleteUriFromService (
> //
> // Step 1: Create HTTP request message with 4 headers:
> //
> - HttpIoHeader = HttpIoCreateHeader ((service->sessionToken || service-
> >basicAuthStr) ? 5 : 4);
> + HttpIoHeader = HttpIoCreateHeader ((service->sessionToken || service-
> >basicAuthStr) ? 8 : 7);
> if (HttpIoHeader == NULL) {
> ret = NULL;
> goto ON_EXIT;
> @@ -1550,6 +1301,23 @@ deleteUriFromService (
> Status = HttpIoSetHeader (HttpIoHeader, "Connection", "Keep-Alive");
> ASSERT_EFI_ERROR (Status);
>
> + Status = HttpIoSetHeader (HttpIoHeader, "Content-Type",
> "application/json");
> + ASSERT_EFI_ERROR (Status);
> +
> + if (content != NULL) {
> + contentLength = strlen (content);
> + AsciiSPrint (
> + ContentLengthStr,
> + sizeof (ContentLengthStr),
> + "%lu",
> + (UINT64)contentLength
> + );
> + Status = HttpIoSetHeader (HttpIoHeader, "Content-Length",
> ContentLengthStr);
> + ASSERT_EFI_ERROR (Status);
> + Status = HttpIoSetHeader (HttpIoHeader, "OData-Version", "4.0");
> + ASSERT_EFI_ERROR (Status);
> + }
> +
> //
> // Step 2: build the rest of HTTP request info.
> //
> @@ -1575,6 +1343,11 @@ deleteUriFromService (
> RequestMsg->HeaderCount = HttpIoHeader->HeaderCount;
> RequestMsg->Headers = HttpIoHeader->Headers;
>
> + if (content != NULL) {
> + RequestMsg->BodyLength = contentLength;
> + RequestMsg->Body = (VOID *)content;
> + }
> +
> ZeroMem (&ResponseMsg, sizeof (ResponseMsg));
>
> //
> @@ -1628,6 +1401,16 @@ ON_EXIT:
> return ret;
> }
>
> +json_t *
> +deleteUriFromService (
> + redfishService *service,
> + const char *uri,
> + EFI_HTTP_STATUS_CODE **StatusCode
> + )
> +{
> + return deleteUriFromServiceEx (service, uri, NULL, StatusCode);
> +}
> +
> redfishPayload *
> getRedfishServiceRoot (
> redfishService *service,
> @@ -2034,6 +1817,10 @@ makeUrlForService (
> }
>
> url = (char *)malloc (strlen (service->host)+strlen (uri)+1);
> + if (url == NULL) {
> + return NULL;
> + }
> +
> strcpy (url, service->host);
> strcat (url, uri);
> return url;
> --
> 2.17.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#110465): https://edk2.groups.io/g/devel/message/110465
Mute This Topic: https://groups.io/mt/102196088/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
prev parent reply other threads:[~2023-11-01 4:00 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-10-26 8:35 [edk2-devel] [edk2-redfish-client][PATCH] RedfishClientPkg/RedfishLib: align with edk2 RedfishLib Nickle Wang via groups.io
2023-11-01 4:00 ` Chang, Abner via groups.io [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=MN2PR12MB39666004BF48B5E8E16B8907EAA7A@MN2PR12MB3966.namprd12.prod.outlook.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox