[edk2-devel] [edk2-redfish-client][PATCH V4] RedfishClientPkg: Add ETag PCD and revise Redfish ETag functions

Chang, Abner via groups.io posted 1 patch 3 months, 3 weeks ago
Failed in applying to current master (apply log)
RedfishClientPkg/RedfishClientPkg.dec         |   3 +
.../RedfishFeatureUtilityLib.inf              |   2 +
.../Library/RedfishFeatureUtilityLib.h        |  47 +++-
.../Features/Bios/v1_0_9/Dxe/BiosDxe.c        |  19 +-
.../v1_0_4/Common/BootOptionCommon.c          |   5 +-
.../BootOption/v1_0_4/Dxe/BootOptionDxe.c     |  17 +-
.../v1_5_0/Dxe/ComputerSystemDxe.c            |  13 +-
.../Features/Memory/V1_7_1/Dxe/MemoryDxe.c    |  17 +-
.../RedfishFeatureUtilityLib.c                | 209 ++++++++++++------
9 files changed, 204 insertions(+), 128 deletions(-)
[edk2-devel] [edk2-redfish-client][PATCH V4] RedfishClientPkg: Add ETag PCD and revise Redfish ETag functions
Posted by Chang, Abner via groups.io 3 months, 3 weeks ago
From: Abner Chang <abner.chang@amd.com>

Add PCD to disable ETag capability for the case Redfish
service doesn't support ETag.

Signed-off-by: Abner Chang <abner.chang@amd.com>
Cc: Nickle Wang <nicklew@nvidia.com>
Cc: Igor Kulchytskyy <igork@ami.com>
Cc: Mike Maslenkin <mike.maslenkin@gmail.com>
---
 RedfishClientPkg/RedfishClientPkg.dec         |   3 +
 .../RedfishFeatureUtilityLib.inf              |   2 +
 .../Library/RedfishFeatureUtilityLib.h        |  47 +++-
 .../Features/Bios/v1_0_9/Dxe/BiosDxe.c        |  19 +-
 .../v1_0_4/Common/BootOptionCommon.c          |   5 +-
 .../BootOption/v1_0_4/Dxe/BootOptionDxe.c     |  17 +-
 .../v1_5_0/Dxe/ComputerSystemDxe.c            |  13 +-
 .../Features/Memory/V1_7_1/Dxe/MemoryDxe.c    |  17 +-
 .../RedfishFeatureUtilityLib.c                | 209 ++++++++++++------
 9 files changed, 204 insertions(+), 128 deletions(-)

diff --git a/RedfishClientPkg/RedfishClientPkg.dec b/RedfishClientPkg/RedfishClientPkg.dec
index b350facae0..ce3b6d9752 100644
--- a/RedfishClientPkg/RedfishClientPkg.dec
+++ b/RedfishClientPkg/RedfishClientPkg.dec
@@ -3,6 +3,7 @@
 #
 # (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>
 # Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
 #
 # SPDX-License-Identifier: BSD-2-Clause-Patent
 ##
@@ -76,6 +77,8 @@
   gEfiRedfishClientPkgTokenSpaceGuid.PcdDefaultRedfishVersion|L"v1"|VOID*|0x10000004
   ## The number of seconds that the firmware will wait before system reboot
   gEfiRedfishClientPkgTokenSpaceGuid.PcdRedfishSystemRebootTimeout|5|UINT16|0x20000002
+  ## Default capability of Redfish service side ETAG support
+  gEfiRedfishClientPkgTokenSpaceGuid.PcdRedfishServiceEtagSupported|TRUE|BOOLEAN|0x10000005
 
 [PcdsDynamicEx]
   ## The flag used to indicate that system reboot is required due to system configuration change
diff --git a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.inf b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.inf
index 718273b248..63330c8e9d 100644
--- a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.inf
+++ b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.inf
@@ -3,6 +3,7 @@
 #
 #  (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>
 #  Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+#  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
 #
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
 #
@@ -54,6 +55,7 @@
 
 [Pcd]
   gEfiRedfishClientPkgTokenSpaceGuid.PcdRedfishSystemRebootRequired
+  gEfiRedfishClientPkgTokenSpaceGuid.PcdRedfishServiceEtagSupported
 
 [Guids]
 
diff --git a/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h b/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
index 9513a65617..0f8aede5c4 100644
--- a/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
+++ b/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
@@ -3,6 +3,7 @@
 
   (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>
   Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
@@ -81,7 +82,7 @@ CopyConfiglanguageList (
 
 /**
 
-  Get number of node from the string. Node is seperated by '/'.
+  Get number of node from the string. Node is separated by '/'.
 
   @param[in]  NodeString             The node string to parse.
 
@@ -559,6 +560,19 @@ GetEtagWithUri (
   IN  EFI_STRING  Uri
   );
 
+/**
+
+  This function returns a boolean of ETAG support on Redfish service side.
+
+  @retval     TRUE    ETAG is supported on Redfish service.
+  @retval     FALSE   ETAG is not supported on Redfish service.
+
+**/
+BOOLEAN
+CheckIsServerEtagSupported (
+  VOID
+  );
+
 /**
 
   Get @odata.id from give HTTP payload. It's call responsibility to release returned buffer.
@@ -931,22 +945,33 @@ CompareRedfishPropertyVagueValues (
   );
 
 /**
+  Find "ETag" from either HTTP header or Redfish response.
 
-  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[in]  Response    HTTP response
-  @param[out] Etag        String buffer to return ETag
-  @param[out] Location    String buffer to return Location
+  @retval  EFI_SUCCESS            ETag is returned in Etag
+  @retval  EFI_UNSUPPORTED        ETag is unsupported
+  @retval  EFI_INVALID_PARAMETER  Response, Etag or both are NULL.
 
-  @retval     EFI_SUCCESS     Data is found and returned.
-  @retval     Others          Errors occur.
+**/
+EFI_STATUS
+GetHttpResponseEtag (
+  IN  REDFISH_RESPONSE  *Response,
+  OUT CHAR8             **Etag
+  );
+
+/**
+  Find "Location" from either HTTP header or Redfish response.
+
+  @param[in]  Response        HTTP response
+  @param[out] Location        String buffer to return Location
 
 **/
 EFI_STATUS
-GetEtagAndLocation (
-  IN  REDFISH_RESPONSE *Response,
-  OUT CHAR8 **Etag, OPTIONAL
-  OUT EFI_STRING        *Location    OPTIONAL
+GetHttpResponseLocation (
+  IN  REDFISH_RESPONSE  *Response,
+  OUT EFI_STRING        *Location
   );
 
 /**
diff --git a/RedfishClientPkg/Features/Bios/v1_0_9/Dxe/BiosDxe.c b/RedfishClientPkg/Features/Bios/v1_0_9/Dxe/BiosDxe.c
index 2a49c5cd22..f40f2d85af 100644
--- a/RedfishClientPkg/Features/Bios/v1_0_9/Dxe/BiosDxe.c
+++ b/RedfishClientPkg/Features/Bios/v1_0_9/Dxe/BiosDxe.c
@@ -3,6 +3,7 @@
 
   (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>
   Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved.
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
@@ -153,14 +154,10 @@ RedfishResourceConsumeResource (
   ASSERT (Private->Json != NULL);
 
   //
-  // Find etag in HTTP response header
+  // Searching for etag in HTTP response header
   //
-  Etag   = NULL;
-  Status = GetEtagAndLocation (ExpectedResponse, &Etag, NULL);
-  if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "%a, failed to get ETag from HTTP header\n", __func__));
-  }
-
+  Etag = NULL;
+  GetHttpResponseEtag (ExpectedResponse, &Etag);
   Status = RedfishConsumeResourceCommon (Private, Private->Json, Etag);
   if (EFI_ERROR (Status)) {
     if (Status != EFI_ALREADY_STARTED) {
@@ -365,12 +362,8 @@ RedfishResourceCheck (
   //
   // Find etag in HTTP response header
   //
-  Etag   = NULL;
-  Status = GetEtagAndLocation (&Response, &Etag, NULL);
-  if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "%a: failed to get ETag from HTTP header\n", __func__));
-  }
-
+  Etag = NULL;
+  GetHttpResponseEtag (&Response, &Etag);
   Status = RedfishCheckResourceCommon (Private, Private->Json, Etag);
   if (EFI_ERROR (Status)) {
     DEBUG ((DEBUG_ERROR, "%a, failed to check resource from: %s: %r\n", __func__, Uri, Status));
diff --git a/RedfishClientPkg/Features/BootOption/v1_0_4/Common/BootOptionCommon.c b/RedfishClientPkg/Features/BootOption/v1_0_4/Common/BootOptionCommon.c
index 0d4c2162c6..0b9f2bf284 100644
--- a/RedfishClientPkg/Features/BootOption/v1_0_4/Common/BootOptionCommon.c
+++ b/RedfishClientPkg/Features/BootOption/v1_0_4/Common/BootOptionCommon.c
@@ -3,6 +3,7 @@
 
   (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>
   Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
@@ -455,9 +456,9 @@ RedfishProvisioningResourceCommon (
   }
 
   //
-  // per Redfish spec. the URL of new resource will be returned in "Location" header.
+  // Per Redfish spec. the URL of new resource will be returned in "Location" header.
   //
-  Status = GetEtagAndLocation (&Response, NULL, &NewResourceLocation);
+  Status = GetHttpResponseLocation (&Response, &NewResourceLocation);
   if (EFI_ERROR (Status)) {
     DEBUG ((DEBUG_ERROR, "%a: cannot find new location: %r\n", __func__, Status));
     goto RELEASE_RESOURCE;
diff --git a/RedfishClientPkg/Features/BootOption/v1_0_4/Dxe/BootOptionDxe.c b/RedfishClientPkg/Features/BootOption/v1_0_4/Dxe/BootOptionDxe.c
index ba090c51d3..dc2bd9da85 100644
--- a/RedfishClientPkg/Features/BootOption/v1_0_4/Dxe/BootOptionDxe.c
+++ b/RedfishClientPkg/Features/BootOption/v1_0_4/Dxe/BootOptionDxe.c
@@ -3,6 +3,7 @@
 
   (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>
   Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
@@ -154,12 +155,8 @@ RedfishResourceConsumeResource (
   //
   // Find etag in HTTP response header
   //
-  Etag   = NULL;
-  Status = GetEtagAndLocation (ExpectedResponse, &Etag, NULL);
-  if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "%a: failed to get ETag from HTTP header\n", __func__));
-  }
-
+  Etag = NULL;
+  GetHttpResponseEtag (ExpectedResponse, &Etag);
   Status = RedfishConsumeResourceCommon (Private, Private->Json, Etag);
   if (EFI_ERROR (Status)) {
     DEBUG ((DEBUG_ERROR, "%a: failed to consume resource from: %s: %r\n", __func__, Private->Uri, Status));
@@ -358,12 +355,8 @@ RedfishResourceCheck (
   //
   // Find etag in HTTP response header
   //
-  Etag   = NULL;
-  Status = GetEtagAndLocation (&Response, &Etag, NULL);
-  if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "%a: failed to get ETag from HTTP header\n", __func__));
-  }
-
+  Etag = NULL;
+  GetHttpResponseEtag (&Response, &Etag);
   Status = RedfishCheckResourceCommon (Private, Private->Json, Etag);
   if (EFI_ERROR (Status)) {
     DEBUG ((REDFISH_BOOT_OPTION_DEBUG_TRACE, "%a: failed to check resource from: %s: %r\n", __func__, Uri, Status));
diff --git a/RedfishClientPkg/Features/ComputerSystem/v1_5_0/Dxe/ComputerSystemDxe.c b/RedfishClientPkg/Features/ComputerSystem/v1_5_0/Dxe/ComputerSystemDxe.c
index 0bbaa92bf4..5927b5fa7a 100644
--- a/RedfishClientPkg/Features/ComputerSystem/v1_5_0/Dxe/ComputerSystemDxe.c
+++ b/RedfishClientPkg/Features/ComputerSystem/v1_5_0/Dxe/ComputerSystemDxe.c
@@ -3,6 +3,7 @@
 
   (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>
   Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
@@ -150,11 +151,7 @@ RedfishResourceConsumeResource (
   // Find etag in HTTP response header
   //
   Etag   = NULL;
-  Status = GetEtagAndLocation (ExpectedResponse, &Etag, NULL);
-  if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "%a, failed to get ETag from HTTP header\n", __func__));
-  }
-
+  GetHttpResponseEtag (ExpectedResponse, &Etag);
   Status = RedfishConsumeResourceCommon (Private, Private->Json, Etag);
   if (EFI_ERROR (Status)) {
     if (Status != EFI_ALREADY_STARTED) {
@@ -360,11 +357,7 @@ RedfishResourceCheck (
   // Find etag in HTTP response header
   //
   Etag   = NULL;
-  Status = GetEtagAndLocation (&Response, &Etag, NULL);
-  if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "%a: failed to get ETag from HTTP header\n", __func__));
-  }
-
+  GetHttpResponseEtag (&Response, &Etag);
   Status = RedfishCheckResourceCommon (Private, Private->Json, Etag);
   if (EFI_ERROR (Status)) {
     DEBUG ((DEBUG_ERROR, "%a, failed to check resource from: %s: %r\n", __func__, Uri, Status));
diff --git a/RedfishClientPkg/Features/Memory/V1_7_1/Dxe/MemoryDxe.c b/RedfishClientPkg/Features/Memory/V1_7_1/Dxe/MemoryDxe.c
index 9230078051..4a6e342879 100644
--- a/RedfishClientPkg/Features/Memory/V1_7_1/Dxe/MemoryDxe.c
+++ b/RedfishClientPkg/Features/Memory/V1_7_1/Dxe/MemoryDxe.c
@@ -3,6 +3,7 @@
 
   (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>
   Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
@@ -149,12 +150,8 @@ RedfishResourceConsumeResource (
   //
   // Find etag in HTTP response header
   //
-  Etag   = NULL;
-  Status = GetEtagAndLocation (ExpectedResponse, &Etag, NULL);
-  if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "%a, failed to get ETag from HTTP header\n", __func__));
-  }
-
+  Etag = NULL;
+  GetHttpResponseEtag (ExpectedResponse, &Etag);
   Status = RedfishConsumeResourceCommon (Private, Private->Json, Etag);
   if (EFI_ERROR (Status)) {
     if (Status != EFI_ALREADY_STARTED) {
@@ -359,12 +356,8 @@ RedfishResourceCheck (
   //
   // Find etag in HTTP response header
   //
-  Etag   = NULL;
-  Status = GetEtagAndLocation (&Response, &Etag, NULL);
-  if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "%a: failed to get ETag from HTTP header\n", __func__));
-  }
-
+  Etag = NULL;
+  GetHttpResponseEtag (&Response, &Etag);
   Status = RedfishCheckResourceCommon (Private, Private->Json, Etag);
   if (EFI_ERROR (Status)) {
     DEBUG ((DEBUG_ERROR, "%a, failed to check resource from: %s: %r\n", __func__, Uri, Status));
diff --git a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.c b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.c
index 1c2d40f622..aa723264e8 100644
--- a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.c
+++ b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.c
@@ -3,6 +3,7 @@
 
   (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>
   Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
@@ -133,6 +134,11 @@ SetEtagFromUri (
   REDFISH_RESPONSE  Response;
   EFI_STRING        PendingSettingUri;
 
+  if (!CheckIsServerEtagSupported ()) {
+    DEBUG ((DEBUG_INFO, "%a: WARNING - ETAG is not supported\n", __func__));
+    return EFI_SUCCESS;
+  }
+
   if ((RedfishService == NULL) || IS_EMPTY_STRING (Uri)) {
     return EFI_INVALID_PARAMETER;
   }
@@ -157,9 +163,9 @@ SetEtagFromUri (
   //
   // Find etag in HTTP response header
   //
-  Status = GetEtagAndLocation (&Response, &Etag, NULL);
-  if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "%a: failed to get ETag from HTTP header\n", __func__));
+  Status = GetHttpResponseEtag (&Response, &Etag);
+  if (EFI_ERROR (Status) && (Status != EFI_UNSUPPORTED)) {
+    DEBUG ((DEBUG_ERROR, "%a: Failed to get ETag from HTTP header\n", __func__));
     Status = EFI_NOT_FOUND;
     goto ON_RELEASE;
   }
@@ -241,6 +247,11 @@ SetEtagWithUri (
   EFI_STATUS  Status;
   CHAR8       *AsciiUri;
 
+  if (!CheckIsServerEtagSupported ()) {
+    DEBUG ((DEBUG_INFO, "%a: WARNING - ETAG is not supported\n", __func__));
+    return EFI_SUCCESS;
+  }
+
   if (IS_EMPTY_STRING (EtagStr) || IS_EMPTY_STRING (Uri)) {
     return EFI_INVALID_PARAMETER;
   }
@@ -286,6 +297,11 @@ GetEtagWithUri (
     return NULL;
   }
 
+  if (!CheckIsServerEtagSupported ()) {
+    DEBUG ((DEBUG_INFO, "%a: WARNING - ETAG is not supported\n", __func__));
+    return NULL;
+  }
+
   Status = RedfishLocateProtocol ((VOID **)&mEtagProtocol, &gEdkIIRedfishETagProtocolGuid);
   if (EFI_ERROR (Status)) {
     DEBUG ((DEBUG_ERROR, "%a: fail to locate gEdkIIRedfishETagProtocolGuid: %r\n", __func__, Status));
@@ -1726,44 +1742,39 @@ RedfishFeatureGetUnifiedArrayTypeConfigureLang (
 }
 
 /**
+  Find "ETag" from either HTTP header or Redfish response.
 
-  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[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.
+  @retval  EFI_SUCCESS            ETag is returned in Etag
+  @retval  EFI_UNSUPPORTED        ETag is unsupported
+  @retval  EFI_INVALID_PARAMETER  Response, Etag or both are NULL.
 
 **/
 EFI_STATUS
-GetEtagAndLocation (
-  IN  REDFISH_RESPONSE *Response,
-  OUT CHAR8 **Etag, OPTIONAL
-  OUT EFI_STRING        *Location    OPTIONAL
+GetHttpResponseEtag (
+  IN  REDFISH_RESPONSE  *Response,
+  OUT CHAR8             **Etag
   )
 {
+  EFI_STATUS        Status;
   EDKII_JSON_VALUE  JsonValue;
   EDKII_JSON_VALUE  OdataValue;
   CHAR8             *OdataString;
-  CHAR8             *AsciiLocation;
   EFI_HTTP_HEADER   *Header;
-  EFI_STATUS        Status;
 
-  if (Response == NULL) {
+  if ((Response == NULL) || (Etag == NULL)) {
     return EFI_INVALID_PARAMETER;
   }
 
-  if ((Etag == NULL) && (Location == NULL)) {
-    return EFI_SUCCESS;
-  }
-
   Status = EFI_SUCCESS;
-
-  if (Etag != NULL) {
-    *Etag = NULL;
-
+  *Etag  = NULL;
+  if (!CheckIsServerEtagSupported ()) {
+    // Don't look for ETAG header or property in this case.
+    DEBUG ((DEBUG_INFO, "%a: WARNING - No ETag support on Redfish service.\n", __func__));
+    return EFI_UNSUPPORTED;
+  } else {
     if (*(Response->StatusCode) == HTTP_STATUS_200_OK) {
       Header = HttpFindHeader (Response->HeaderCount, Response->Headers, HTTP_HEADER_ETAG);
       if (Header != NULL) {
@@ -1793,51 +1804,94 @@ GetEtagAndLocation (
 
     if (*Etag == NULL) {
       Status = EFI_NOT_FOUND;
+      DEBUG ((DEBUG_ERROR, "%a: Failed to retrieve ETag from HTTP response paylaod.\n", __func__));
     }
   }
 
-  if (Location != NULL) {
-    *Location     = NULL;
-    AsciiLocation = NULL;
+  return Status;
+}
 
-    if (*(Response->StatusCode) == HTTP_STATUS_200_OK) {
-      Header = HttpFindHeader (Response->HeaderCount, Response->Headers, HTTP_HEADER_LOCATION);
-      if (Header != NULL) {
-        AsciiLocation = AllocateCopyPool (AsciiStrSize (Header->FieldValue), Header->FieldValue);
-        ASSERT (AsciiLocation != NULL);
-      }
+/**
+  Find "Location" from either HTTP header or Redfish response.
+
+  @param[in]  Response        HTTP response
+  @param[out] Location        String buffer to return Location
+
+**/
+EFI_STATUS
+GetHttpResponseLocation (
+  IN  REDFISH_RESPONSE  *Response,
+  OUT EFI_STRING        *Location
+  )
+{
+  EFI_STATUS        Status;
+  EDKII_JSON_VALUE  JsonValue;
+  EDKII_JSON_VALUE  OdataValue;
+  CHAR8             *OdataString;
+  CHAR8             *AsciiLocation;
+  EFI_HTTP_HEADER   *Header;
+
+  if ((Response == NULL) || (Location == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status        = EFI_SUCCESS;
+  *Location     = NULL;
+  AsciiLocation = NULL;
+  if (*(Response->StatusCode) == HTTP_STATUS_200_OK) {
+    Header = HttpFindHeader (Response->HeaderCount, Response->Headers, HTTP_HEADER_LOCATION);
+    if (Header != NULL) {
+      AsciiLocation = AllocateCopyPool (AsciiStrSize (Header->FieldValue), Header->FieldValue);
+      ASSERT (AsciiLocation != NULL);
     }
+  }
 
-    //
-    // No header is returned. Search payload for location.
-    //
-    if ((*Location == NULL) && (Response->Payload != NULL)) {
-      JsonValue = RedfishJsonInPayload (Response->Payload);
-      if (JsonValue != NULL) {
-        OdataValue = JsonObjectGetValue (JsonValueGetObject (JsonValue), "@odata.id");
-        if (OdataValue != NULL) {
-          OdataString = (CHAR8 *)JsonValueGetAsciiString (OdataValue);
-          if (OdataString != NULL) {
-            AsciiLocation = AllocateCopyPool (AsciiStrSize (OdataString), OdataString);
-            ASSERT (AsciiLocation != NULL);
-          }
+  //
+  // No header is returned. Search payload for location.
+  //
+  if ((*Location == NULL) && (Response->Payload != NULL)) {
+    JsonValue = RedfishJsonInPayload (Response->Payload);
+    if (JsonValue != NULL) {
+      OdataValue = JsonObjectGetValue (JsonValueGetObject (JsonValue), "@odata.id");
+      if (OdataValue != NULL) {
+        OdataString = (CHAR8 *)JsonValueGetAsciiString (OdataValue);
+        if (OdataString != NULL) {
+          AsciiLocation = AllocateCopyPool (AsciiStrSize (OdataString), OdataString);
+          ASSERT (AsciiLocation != NULL);
         }
-
-        JsonValueFree (JsonValue);
       }
-    }
 
-    if (AsciiLocation != NULL) {
-      *Location = StrAsciiToUnicode (AsciiLocation);
-      FreePool (AsciiLocation);
-    } else {
-      Status = EFI_NOT_FOUND;
+      JsonValueFree (JsonValue);
     }
   }
 
+  if (AsciiLocation != NULL) {
+    *Location = StrAsciiToUnicode (AsciiLocation);
+    FreePool (AsciiLocation);
+  } else {
+    Status = EFI_NOT_FOUND;
+    DEBUG ((DEBUG_ERROR, "%a: Failed to retrieve Location from HTTP response paylaod.\n", __func__));
+  }
+
   return Status;
 }
 
+/**
+
+  This function returns a boolean of ETAG support on Redfish service side.
+
+  @retval     TRUE    ETAG is supported on Redfish service.
+  @retval     FALSE   ETAG is not supported on Redfish service.
+
+**/
+BOOLEAN
+CheckIsServerEtagSupported (
+  VOID
+  )
+{
+  return FixedPcdGetBool (PcdRedfishServiceEtagSupported);
+}
+
 /**
 
   Create HTTP payload and send them to redfish service with PATCH method.
@@ -1861,7 +1915,7 @@ CreatePayloadToPatchResource (
 {
   REDFISH_PAYLOAD   Payload;
   EDKII_JSON_VALUE  ResourceJsonValue;
-  REDFISH_RESPONSE  PostResponse;
+  REDFISH_RESPONSE  PatchResponse;
   EFI_STATUS        Status;
 
   if ((Service == NULL) || (TargetPayload == NULL) || IS_EMPTY_STRING (Json)) {
@@ -1876,8 +1930,8 @@ CreatePayloadToPatchResource (
     goto EXIT_FREE_JSON_VALUE;
   }
 
-  ZeroMem (&PostResponse, sizeof (REDFISH_RESPONSE));
-  Status = RedfishPatchToPayload (TargetPayload, Payload, &PostResponse);
+  ZeroMem (&PatchResponse, sizeof (REDFISH_RESPONSE));
+  Status = RedfishPatchToPayload (TargetPayload, Payload, &PatchResponse);
   if (EFI_ERROR (Status)) {
     DEBUG ((DEBUG_ERROR, "%a:%d Failed to PATCH payload to Redfish service.\n", __func__, __LINE__));
 
@@ -1885,7 +1939,7 @@ CreatePayloadToPatchResource (
     DEBUG ((DEBUG_ERROR, "%a: Request:\n", __func__));
     DumpRedfishPayload (DEBUG_ERROR, Payload);
     DEBUG ((DEBUG_ERROR, "%a: Response:\n", __func__));
-    DumpRedfishResponse (__func__, DEBUG_ERROR, &PostResponse);
+    DumpRedfishResponse (__func__, DEBUG_ERROR, &PatchResponse);
     DEBUG_CODE_END ();
     goto EXIT_FREE_JSON_VALUE;
   }
@@ -1893,16 +1947,20 @@ CreatePayloadToPatchResource (
   //
   // Find ETag
   //
-  Status = GetEtagAndLocation (&PostResponse, Etag, NULL);
-  if (EFI_ERROR (Status)) {
+  Status = GetHttpResponseEtag (&PatchResponse, Etag);
+  if (Status == EFI_UNSUPPORTED) {
+    Status = EFI_SUCCESS;
+    DEBUG ((DEBUG_INFO, "%a: WARNING - ETAG is not supported on Redfish service.\n", __func__));
+  } else {
     Status = EFI_DEVICE_ERROR;
+    DEBUG ((DEBUG_ERROR, "%a: Fail to get Location header nor Location property from HTTP response payload.\n", __func__));
   }
 
   RedfishFreeResponse (
-    PostResponse.StatusCode,
-    PostResponse.HeaderCount,
-    PostResponse.Headers,
-    PostResponse.Payload
+    PatchResponse.StatusCode,
+    PatchResponse.HeaderCount,
+    PatchResponse.Headers,
+    PatchResponse.Payload
     );
 
 EXIT_FREE_JSON_VALUE:
@@ -1935,7 +1993,7 @@ CreatePayloadToPostResource (
   IN  REDFISH_PAYLOAD  *TargetPayload,
   IN  CHAR8            *Json,
   OUT EFI_STRING       *Location,
-  OUT CHAR8            **Etag
+  OUT CHAR8            **Etag OPTIONAL
   )
 {
   REDFISH_PAYLOAD   Payload;
@@ -1943,7 +2001,7 @@ CreatePayloadToPostResource (
   REDFISH_RESPONSE  PostResponse;
   EFI_STATUS        Status;
 
-  if ((Service == NULL) || (TargetPayload == NULL) || IS_EMPTY_STRING (Json) || (Location == NULL) || (Etag == NULL)) {
+  if ((Service == NULL) || (TargetPayload == NULL) || IS_EMPTY_STRING (Json) || (Location == NULL)) {
     return EFI_INVALID_PARAMETER;
   }
 
@@ -1970,12 +2028,22 @@ CreatePayloadToPostResource (
     goto EXIT_FREE_JSON_VALUE;
   }
 
+  Status = GetHttpResponseEtag (&PostResponse, Etag);
+  if (Status == EFI_UNSUPPORTED) {
+    Status = EFI_SUCCESS;
+    DEBUG ((DEBUG_INFO, "%a: WARNING - ETAG is not supported on Redfish service.\n", __func__));
+  } else if (EFI_ERROR (Status)) {
+    Status = EFI_DEVICE_ERROR;
+    DEBUG ((DEBUG_ERROR, "%a: Fail to get ETAG header nor ETAG property from HTTP response payload.\n", __func__));
+  }
+
   //
   // per Redfish spec. the URL of new resource will be returned in "Location" header.
   //
-  Status = GetEtagAndLocation (&PostResponse, Etag, Location);
+  Status = GetHttpResponseLocation (&PostResponse, Location);
   if (EFI_ERROR (Status)) {
     Status = EFI_DEVICE_ERROR;
+    DEBUG ((DEBUG_ERROR, "%a: Fail to get Location header nor Location proerty from HTTP response payload.\n", __func__));
   }
 
   RedfishFreeResponse (
@@ -3117,6 +3185,11 @@ CheckEtag (
 {
   CHAR8  *EtagInDb;
 
+  if (!CheckIsServerEtagSupported ()) {
+    DEBUG ((DEBUG_INFO, "%a: WARNING - ETAG is not supported, always returns FALSE to consume resource (Performance would be reduced).\n", __func__));
+    return FALSE;
+  }
+
   if (IS_EMPTY_STRING (Uri)) {
     return FALSE;
   }
-- 
2.37.1.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#113344): https://edk2.groups.io/g/devel/message/113344
Mute This Topic: https://groups.io/mt/103590679/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Re: [edk2-devel] [edk2-redfish-client][PATCH V4] RedfishClientPkg: Add ETag PCD and revise Redfish ETag functions
Posted by Igor Kulchytskyy via groups.io 3 months, 3 weeks ago
Reviewed-by: Igor Kulchytskyy <igork@ami.com>

Regards,
Igor

-----Original Message-----
From: abner.chang@amd.com <abner.chang@amd.com>
Sent: Sunday, January 07, 2024 9:49 PM
To: devel@edk2.groups.io
Cc: Nickle Wang <nicklew@nvidia.com>; Igor Kulchytskyy <igork@ami.com>; Mike Maslenkin <mike.maslenkin@gmail.com>
Subject: [EXTERNAL] [edk2-redfish-client][PATCH V4] RedfishClientPkg: Add ETag PCD and revise Redfish ETag functions


**CAUTION: The e-mail below is from an external source. Please exercise caution before opening attachments, clicking links, or following guidance.**

From: Abner Chang <abner.chang@amd.com>

Add PCD to disable ETag capability for the case Redfish
service doesn't support ETag.

Signed-off-by: Abner Chang <abner.chang@amd.com>
Cc: Nickle Wang <nicklew@nvidia.com>
Cc: Igor Kulchytskyy <igork@ami.com>
Cc: Mike Maslenkin <mike.maslenkin@gmail.com>
---
 RedfishClientPkg/RedfishClientPkg.dec         |   3 +
 .../RedfishFeatureUtilityLib.inf              |   2 +
 .../Library/RedfishFeatureUtilityLib.h        |  47 +++-
 .../Features/Bios/v1_0_9/Dxe/BiosDxe.c        |  19 +-
 .../v1_0_4/Common/BootOptionCommon.c          |   5 +-
 .../BootOption/v1_0_4/Dxe/BootOptionDxe.c     |  17 +-
 .../v1_5_0/Dxe/ComputerSystemDxe.c            |  13 +-
 .../Features/Memory/V1_7_1/Dxe/MemoryDxe.c    |  17 +-
 .../RedfishFeatureUtilityLib.c                | 209 ++++++++++++------
 9 files changed, 204 insertions(+), 128 deletions(-)

diff --git a/RedfishClientPkg/RedfishClientPkg.dec b/RedfishClientPkg/RedfishClientPkg.dec
index b350facae0..ce3b6d9752 100644
--- a/RedfishClientPkg/RedfishClientPkg.dec
+++ b/RedfishClientPkg/RedfishClientPkg.dec
@@ -3,6 +3,7 @@
 #
 # (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>
 # Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
 #
 # SPDX-License-Identifier: BSD-2-Clause-Patent
 ##
@@ -76,6 +77,8 @@
   gEfiRedfishClientPkgTokenSpaceGuid.PcdDefaultRedfishVersion|L"v1"|VOID*|0x10000004
   ## The number of seconds that the firmware will wait before system reboot
   gEfiRedfishClientPkgTokenSpaceGuid.PcdRedfishSystemRebootTimeout|5|UINT16|0x20000002
+  ## Default capability of Redfish service side ETAG support
+  gEfiRedfishClientPkgTokenSpaceGuid.PcdRedfishServiceEtagSupported|TRUE|BOOLEAN|0x10000005

 [PcdsDynamicEx]
   ## The flag used to indicate that system reboot is required due to system configuration change
diff --git a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.inf b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.inf
index 718273b248..63330c8e9d 100644
--- a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.inf
+++ b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.inf
@@ -3,6 +3,7 @@
 #
 #  (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>
 #  Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+#  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
 #
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
 #
@@ -54,6 +55,7 @@

 [Pcd]
   gEfiRedfishClientPkgTokenSpaceGuid.PcdRedfishSystemRebootRequired
+  gEfiRedfishClientPkgTokenSpaceGuid.PcdRedfishServiceEtagSupported

 [Guids]

diff --git a/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h b/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
index 9513a65617..0f8aede5c4 100644
--- a/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
+++ b/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
@@ -3,6 +3,7 @@

   (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>
   Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

   SPDX-License-Identifier: BSD-2-Clause-Patent

@@ -81,7 +82,7 @@ CopyConfiglanguageList (

 /**

-  Get number of node from the string. Node is seperated by '/'.
+  Get number of node from the string. Node is separated by '/'.

   @param[in]  NodeString             The node string to parse.

@@ -559,6 +560,19 @@ GetEtagWithUri (
   IN  EFI_STRING  Uri
   );

+/**
+
+  This function returns a boolean of ETAG support on Redfish service side.
+
+  @retval     TRUE    ETAG is supported on Redfish service.
+  @retval     FALSE   ETAG is not supported on Redfish service.
+
+**/
+BOOLEAN
+CheckIsServerEtagSupported (
+  VOID
+  );
+
 /**

   Get @odata.id from give HTTP payload. It's call responsibility to release returned buffer.
@@ -931,22 +945,33 @@ CompareRedfishPropertyVagueValues (
   );

 /**
+  Find "ETag" from either HTTP header or Redfish response.

-  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[in]  Response    HTTP response
-  @param[out] Etag        String buffer to return ETag
-  @param[out] Location    String buffer to return Location
+  @retval  EFI_SUCCESS            ETag is returned in Etag
+  @retval  EFI_UNSUPPORTED        ETag is unsupported
+  @retval  EFI_INVALID_PARAMETER  Response, Etag or both are NULL.

-  @retval     EFI_SUCCESS     Data is found and returned.
-  @retval     Others          Errors occur.
+**/
+EFI_STATUS
+GetHttpResponseEtag (
+  IN  REDFISH_RESPONSE  *Response,
+  OUT CHAR8             **Etag
+  );
+
+/**
+  Find "Location" from either HTTP header or Redfish response.
+
+  @param[in]  Response        HTTP response
+  @param[out] Location        String buffer to return Location

 **/
 EFI_STATUS
-GetEtagAndLocation (
-  IN  REDFISH_RESPONSE *Response,
-  OUT CHAR8 **Etag, OPTIONAL
-  OUT EFI_STRING        *Location    OPTIONAL
+GetHttpResponseLocation (
+  IN  REDFISH_RESPONSE  *Response,
+  OUT EFI_STRING        *Location
   );

 /**
diff --git a/RedfishClientPkg/Features/Bios/v1_0_9/Dxe/BiosDxe.c b/RedfishClientPkg/Features/Bios/v1_0_9/Dxe/BiosDxe.c
index 2a49c5cd22..f40f2d85af 100644
--- a/RedfishClientPkg/Features/Bios/v1_0_9/Dxe/BiosDxe.c
+++ b/RedfishClientPkg/Features/Bios/v1_0_9/Dxe/BiosDxe.c
@@ -3,6 +3,7 @@

   (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>
   Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved.
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

   SPDX-License-Identifier: BSD-2-Clause-Patent

@@ -153,14 +154,10 @@ RedfishResourceConsumeResource (
   ASSERT (Private->Json != NULL);

   //
-  // Find etag in HTTP response header
+  // Searching for etag in HTTP response header
   //
-  Etag   = NULL;
-  Status = GetEtagAndLocation (ExpectedResponse, &Etag, NULL);
-  if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "%a, failed to get ETag from HTTP header\n", __func__));
-  }
-
+  Etag = NULL;
+  GetHttpResponseEtag (ExpectedResponse, &Etag);
   Status = RedfishConsumeResourceCommon (Private, Private->Json, Etag);
   if (EFI_ERROR (Status)) {
     if (Status != EFI_ALREADY_STARTED) {
@@ -365,12 +362,8 @@ RedfishResourceCheck (
   //
   // Find etag in HTTP response header
   //
-  Etag   = NULL;
-  Status = GetEtagAndLocation (&Response, &Etag, NULL);
-  if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "%a: failed to get ETag from HTTP header\n", __func__));
-  }
-
+  Etag = NULL;
+  GetHttpResponseEtag (&Response, &Etag);
   Status = RedfishCheckResourceCommon (Private, Private->Json, Etag);
   if (EFI_ERROR (Status)) {
     DEBUG ((DEBUG_ERROR, "%a, failed to check resource from: %s: %r\n", __func__, Uri, Status));
diff --git a/RedfishClientPkg/Features/BootOption/v1_0_4/Common/BootOptionCommon.c b/RedfishClientPkg/Features/BootOption/v1_0_4/Common/BootOptionCommon.c
index 0d4c2162c6..0b9f2bf284 100644
--- a/RedfishClientPkg/Features/BootOption/v1_0_4/Common/BootOptionCommon.c
+++ b/RedfishClientPkg/Features/BootOption/v1_0_4/Common/BootOptionCommon.c
@@ -3,6 +3,7 @@

   (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>
   Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

   SPDX-License-Identifier: BSD-2-Clause-Patent

@@ -455,9 +456,9 @@ RedfishProvisioningResourceCommon (
   }

   //
-  // per Redfish spec. the URL of new resource will be returned in "Location" header.
+  // Per Redfish spec. the URL of new resource will be returned in "Location" header.
   //
-  Status = GetEtagAndLocation (&Response, NULL, &NewResourceLocation);
+  Status = GetHttpResponseLocation (&Response, &NewResourceLocation);
   if (EFI_ERROR (Status)) {
     DEBUG ((DEBUG_ERROR, "%a: cannot find new location: %r\n", __func__, Status));
     goto RELEASE_RESOURCE;
diff --git a/RedfishClientPkg/Features/BootOption/v1_0_4/Dxe/BootOptionDxe.c b/RedfishClientPkg/Features/BootOption/v1_0_4/Dxe/BootOptionDxe.c
index ba090c51d3..dc2bd9da85 100644
--- a/RedfishClientPkg/Features/BootOption/v1_0_4/Dxe/BootOptionDxe.c
+++ b/RedfishClientPkg/Features/BootOption/v1_0_4/Dxe/BootOptionDxe.c
@@ -3,6 +3,7 @@

   (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>
   Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

   SPDX-License-Identifier: BSD-2-Clause-Patent

@@ -154,12 +155,8 @@ RedfishResourceConsumeResource (
   //
   // Find etag in HTTP response header
   //
-  Etag   = NULL;
-  Status = GetEtagAndLocation (ExpectedResponse, &Etag, NULL);
-  if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "%a: failed to get ETag from HTTP header\n", __func__));
-  }
-
+  Etag = NULL;
+  GetHttpResponseEtag (ExpectedResponse, &Etag);
   Status = RedfishConsumeResourceCommon (Private, Private->Json, Etag);
   if (EFI_ERROR (Status)) {
     DEBUG ((DEBUG_ERROR, "%a: failed to consume resource from: %s: %r\n", __func__, Private->Uri, Status));
@@ -358,12 +355,8 @@ RedfishResourceCheck (
   //
   // Find etag in HTTP response header
   //
-  Etag   = NULL;
-  Status = GetEtagAndLocation (&Response, &Etag, NULL);
-  if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "%a: failed to get ETag from HTTP header\n", __func__));
-  }
-
+  Etag = NULL;
+  GetHttpResponseEtag (&Response, &Etag);
   Status = RedfishCheckResourceCommon (Private, Private->Json, Etag);
   if (EFI_ERROR (Status)) {
     DEBUG ((REDFISH_BOOT_OPTION_DEBUG_TRACE, "%a: failed to check resource from: %s: %r\n", __func__, Uri, Status));
diff --git a/RedfishClientPkg/Features/ComputerSystem/v1_5_0/Dxe/ComputerSystemDxe.c b/RedfishClientPkg/Features/ComputerSystem/v1_5_0/Dxe/ComputerSystemDxe.c
index 0bbaa92bf4..5927b5fa7a 100644
--- a/RedfishClientPkg/Features/ComputerSystem/v1_5_0/Dxe/ComputerSystemDxe.c
+++ b/RedfishClientPkg/Features/ComputerSystem/v1_5_0/Dxe/ComputerSystemDxe.c
@@ -3,6 +3,7 @@

   (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>
   Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

   SPDX-License-Identifier: BSD-2-Clause-Patent

@@ -150,11 +151,7 @@ RedfishResourceConsumeResource (
   // Find etag in HTTP response header
   //
   Etag   = NULL;
-  Status = GetEtagAndLocation (ExpectedResponse, &Etag, NULL);
-  if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "%a, failed to get ETag from HTTP header\n", __func__));
-  }
-
+  GetHttpResponseEtag (ExpectedResponse, &Etag);
   Status = RedfishConsumeResourceCommon (Private, Private->Json, Etag);
   if (EFI_ERROR (Status)) {
     if (Status != EFI_ALREADY_STARTED) {
@@ -360,11 +357,7 @@ RedfishResourceCheck (
   // Find etag in HTTP response header
   //
   Etag   = NULL;
-  Status = GetEtagAndLocation (&Response, &Etag, NULL);
-  if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "%a: failed to get ETag from HTTP header\n", __func__));
-  }
-
+  GetHttpResponseEtag (&Response, &Etag);
   Status = RedfishCheckResourceCommon (Private, Private->Json, Etag);
   if (EFI_ERROR (Status)) {
     DEBUG ((DEBUG_ERROR, "%a, failed to check resource from: %s: %r\n", __func__, Uri, Status));
diff --git a/RedfishClientPkg/Features/Memory/V1_7_1/Dxe/MemoryDxe.c b/RedfishClientPkg/Features/Memory/V1_7_1/Dxe/MemoryDxe.c
index 9230078051..4a6e342879 100644
--- a/RedfishClientPkg/Features/Memory/V1_7_1/Dxe/MemoryDxe.c
+++ b/RedfishClientPkg/Features/Memory/V1_7_1/Dxe/MemoryDxe.c
@@ -3,6 +3,7 @@

   (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>
   Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

   SPDX-License-Identifier: BSD-2-Clause-Patent

@@ -149,12 +150,8 @@ RedfishResourceConsumeResource (
   //
   // Find etag in HTTP response header
   //
-  Etag   = NULL;
-  Status = GetEtagAndLocation (ExpectedResponse, &Etag, NULL);
-  if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "%a, failed to get ETag from HTTP header\n", __func__));
-  }
-
+  Etag = NULL;
+  GetHttpResponseEtag (ExpectedResponse, &Etag);
   Status = RedfishConsumeResourceCommon (Private, Private->Json, Etag);
   if (EFI_ERROR (Status)) {
     if (Status != EFI_ALREADY_STARTED) {
@@ -359,12 +356,8 @@ RedfishResourceCheck (
   //
   // Find etag in HTTP response header
   //
-  Etag   = NULL;
-  Status = GetEtagAndLocation (&Response, &Etag, NULL);
-  if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "%a: failed to get ETag from HTTP header\n", __func__));
-  }
-
+  Etag = NULL;
+  GetHttpResponseEtag (&Response, &Etag);
   Status = RedfishCheckResourceCommon (Private, Private->Json, Etag);
   if (EFI_ERROR (Status)) {
     DEBUG ((DEBUG_ERROR, "%a, failed to check resource from: %s: %r\n", __func__, Uri, Status));
diff --git a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.c b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.c
index 1c2d40f622..aa723264e8 100644
--- a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.c
+++ b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.c
@@ -3,6 +3,7 @@

   (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>
   Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

   SPDX-License-Identifier: BSD-2-Clause-Patent

@@ -133,6 +134,11 @@ SetEtagFromUri (
   REDFISH_RESPONSE  Response;
   EFI_STRING        PendingSettingUri;

+  if (!CheckIsServerEtagSupported ()) {
+    DEBUG ((DEBUG_INFO, "%a: WARNING - ETAG is not supported\n", __func__));
+    return EFI_SUCCESS;
+  }
+
   if ((RedfishService == NULL) || IS_EMPTY_STRING (Uri)) {
     return EFI_INVALID_PARAMETER;
   }
@@ -157,9 +163,9 @@ SetEtagFromUri (
   //
   // Find etag in HTTP response header
   //
-  Status = GetEtagAndLocation (&Response, &Etag, NULL);
-  if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "%a: failed to get ETag from HTTP header\n", __func__));
+  Status = GetHttpResponseEtag (&Response, &Etag);
+  if (EFI_ERROR (Status) && (Status != EFI_UNSUPPORTED)) {
+    DEBUG ((DEBUG_ERROR, "%a: Failed to get ETag from HTTP header\n", __func__));
     Status = EFI_NOT_FOUND;
     goto ON_RELEASE;
   }
@@ -241,6 +247,11 @@ SetEtagWithUri (
   EFI_STATUS  Status;
   CHAR8       *AsciiUri;

+  if (!CheckIsServerEtagSupported ()) {
+    DEBUG ((DEBUG_INFO, "%a: WARNING - ETAG is not supported\n", __func__));
+    return EFI_SUCCESS;
+  }
+
   if (IS_EMPTY_STRING (EtagStr) || IS_EMPTY_STRING (Uri)) {
     return EFI_INVALID_PARAMETER;
   }
@@ -286,6 +297,11 @@ GetEtagWithUri (
     return NULL;
   }

+  if (!CheckIsServerEtagSupported ()) {
+    DEBUG ((DEBUG_INFO, "%a: WARNING - ETAG is not supported\n", __func__));
+    return NULL;
+  }
+
   Status = RedfishLocateProtocol ((VOID **)&mEtagProtocol, &gEdkIIRedfishETagProtocolGuid);
   if (EFI_ERROR (Status)) {
     DEBUG ((DEBUG_ERROR, "%a: fail to locate gEdkIIRedfishETagProtocolGuid: %r\n", __func__, Status));
@@ -1726,44 +1742,39 @@ RedfishFeatureGetUnifiedArrayTypeConfigureLang (
 }

 /**
+  Find "ETag" from either HTTP header or Redfish response.

-  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[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.
+  @retval  EFI_SUCCESS            ETag is returned in Etag
+  @retval  EFI_UNSUPPORTED        ETag is unsupported
+  @retval  EFI_INVALID_PARAMETER  Response, Etag or both are NULL.

 **/
 EFI_STATUS
-GetEtagAndLocation (
-  IN  REDFISH_RESPONSE *Response,
-  OUT CHAR8 **Etag, OPTIONAL
-  OUT EFI_STRING        *Location    OPTIONAL
+GetHttpResponseEtag (
+  IN  REDFISH_RESPONSE  *Response,
+  OUT CHAR8             **Etag
   )
 {
+  EFI_STATUS        Status;
   EDKII_JSON_VALUE  JsonValue;
   EDKII_JSON_VALUE  OdataValue;
   CHAR8             *OdataString;
-  CHAR8             *AsciiLocation;
   EFI_HTTP_HEADER   *Header;
-  EFI_STATUS        Status;

-  if (Response == NULL) {
+  if ((Response == NULL) || (Etag == NULL)) {
     return EFI_INVALID_PARAMETER;
   }

-  if ((Etag == NULL) && (Location == NULL)) {
-    return EFI_SUCCESS;
-  }
-
   Status = EFI_SUCCESS;
-
-  if (Etag != NULL) {
-    *Etag = NULL;
-
+  *Etag  = NULL;
+  if (!CheckIsServerEtagSupported ()) {
+    // Don't look for ETAG header or property in this case.
+    DEBUG ((DEBUG_INFO, "%a: WARNING - No ETag support on Redfish service.\n", __func__));
+    return EFI_UNSUPPORTED;
+  } else {
     if (*(Response->StatusCode) == HTTP_STATUS_200_OK) {
       Header = HttpFindHeader (Response->HeaderCount, Response->Headers, HTTP_HEADER_ETAG);
       if (Header != NULL) {
@@ -1793,51 +1804,94 @@ GetEtagAndLocation (

     if (*Etag == NULL) {
       Status = EFI_NOT_FOUND;
+      DEBUG ((DEBUG_ERROR, "%a: Failed to retrieve ETag from HTTP response paylaod.\n", __func__));
     }
   }

-  if (Location != NULL) {
-    *Location     = NULL;
-    AsciiLocation = NULL;
+  return Status;
+}

-    if (*(Response->StatusCode) == HTTP_STATUS_200_OK) {
-      Header = HttpFindHeader (Response->HeaderCount, Response->Headers, HTTP_HEADER_LOCATION);
-      if (Header != NULL) {
-        AsciiLocation = AllocateCopyPool (AsciiStrSize (Header->FieldValue), Header->FieldValue);
-        ASSERT (AsciiLocation != NULL);
-      }
+/**
+  Find "Location" from either HTTP header or Redfish response.
+
+  @param[in]  Response        HTTP response
+  @param[out] Location        String buffer to return Location
+
+**/
+EFI_STATUS
+GetHttpResponseLocation (
+  IN  REDFISH_RESPONSE  *Response,
+  OUT EFI_STRING        *Location
+  )
+{
+  EFI_STATUS        Status;
+  EDKII_JSON_VALUE  JsonValue;
+  EDKII_JSON_VALUE  OdataValue;
+  CHAR8             *OdataString;
+  CHAR8             *AsciiLocation;
+  EFI_HTTP_HEADER   *Header;
+
+  if ((Response == NULL) || (Location == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status        = EFI_SUCCESS;
+  *Location     = NULL;
+  AsciiLocation = NULL;
+  if (*(Response->StatusCode) == HTTP_STATUS_200_OK) {
+    Header = HttpFindHeader (Response->HeaderCount, Response->Headers, HTTP_HEADER_LOCATION);
+    if (Header != NULL) {
+      AsciiLocation = AllocateCopyPool (AsciiStrSize (Header->FieldValue), Header->FieldValue);
+      ASSERT (AsciiLocation != NULL);
     }
+  }

-    //
-    // No header is returned. Search payload for location.
-    //
-    if ((*Location == NULL) && (Response->Payload != NULL)) {
-      JsonValue = RedfishJsonInPayload (Response->Payload);
-      if (JsonValue != NULL) {
-        OdataValue = JsonObjectGetValue (JsonValueGetObject (JsonValue), "@odata.id");
-        if (OdataValue != NULL) {
-          OdataString = (CHAR8 *)JsonValueGetAsciiString (OdataValue);
-          if (OdataString != NULL) {
-            AsciiLocation = AllocateCopyPool (AsciiStrSize (OdataString), OdataString);
-            ASSERT (AsciiLocation != NULL);
-          }
+  //
+  // No header is returned. Search payload for location.
+  //
+  if ((*Location == NULL) && (Response->Payload != NULL)) {
+    JsonValue = RedfishJsonInPayload (Response->Payload);
+    if (JsonValue != NULL) {
+      OdataValue = JsonObjectGetValue (JsonValueGetObject (JsonValue), "@odata.id");
+      if (OdataValue != NULL) {
+        OdataString = (CHAR8 *)JsonValueGetAsciiString (OdataValue);
+        if (OdataString != NULL) {
+          AsciiLocation = AllocateCopyPool (AsciiStrSize (OdataString), OdataString);
+          ASSERT (AsciiLocation != NULL);
         }
-
-        JsonValueFree (JsonValue);
       }
-    }

-    if (AsciiLocation != NULL) {
-      *Location = StrAsciiToUnicode (AsciiLocation);
-      FreePool (AsciiLocation);
-    } else {
-      Status = EFI_NOT_FOUND;
+      JsonValueFree (JsonValue);
     }
   }

+  if (AsciiLocation != NULL) {
+    *Location = StrAsciiToUnicode (AsciiLocation);
+    FreePool (AsciiLocation);
+  } else {
+    Status = EFI_NOT_FOUND;
+    DEBUG ((DEBUG_ERROR, "%a: Failed to retrieve Location from HTTP response paylaod.\n", __func__));
+  }
+
   return Status;
 }

+/**
+
+  This function returns a boolean of ETAG support on Redfish service side.
+
+  @retval     TRUE    ETAG is supported on Redfish service.
+  @retval     FALSE   ETAG is not supported on Redfish service.
+
+**/
+BOOLEAN
+CheckIsServerEtagSupported (
+  VOID
+  )
+{
+  return FixedPcdGetBool (PcdRedfishServiceEtagSupported);
+}
+
 /**

   Create HTTP payload and send them to redfish service with PATCH method.
@@ -1861,7 +1915,7 @@ CreatePayloadToPatchResource (
 {
   REDFISH_PAYLOAD   Payload;
   EDKII_JSON_VALUE  ResourceJsonValue;
-  REDFISH_RESPONSE  PostResponse;
+  REDFISH_RESPONSE  PatchResponse;
   EFI_STATUS        Status;

   if ((Service == NULL) || (TargetPayload == NULL) || IS_EMPTY_STRING (Json)) {
@@ -1876,8 +1930,8 @@ CreatePayloadToPatchResource (
     goto EXIT_FREE_JSON_VALUE;
   }

-  ZeroMem (&PostResponse, sizeof (REDFISH_RESPONSE));
-  Status = RedfishPatchToPayload (TargetPayload, Payload, &PostResponse);
+  ZeroMem (&PatchResponse, sizeof (REDFISH_RESPONSE));
+  Status = RedfishPatchToPayload (TargetPayload, Payload, &PatchResponse);
   if (EFI_ERROR (Status)) {
     DEBUG ((DEBUG_ERROR, "%a:%d Failed to PATCH payload to Redfish service.\n", __func__, __LINE__));

@@ -1885,7 +1939,7 @@ CreatePayloadToPatchResource (
     DEBUG ((DEBUG_ERROR, "%a: Request:\n", __func__));
     DumpRedfishPayload (DEBUG_ERROR, Payload);
     DEBUG ((DEBUG_ERROR, "%a: Response:\n", __func__));
-    DumpRedfishResponse (__func__, DEBUG_ERROR, &PostResponse);
+    DumpRedfishResponse (__func__, DEBUG_ERROR, &PatchResponse);
     DEBUG_CODE_END ();
     goto EXIT_FREE_JSON_VALUE;
   }
@@ -1893,16 +1947,20 @@ CreatePayloadToPatchResource (
   //
   // Find ETag
   //
-  Status = GetEtagAndLocation (&PostResponse, Etag, NULL);
-  if (EFI_ERROR (Status)) {
+  Status = GetHttpResponseEtag (&PatchResponse, Etag);
+  if (Status == EFI_UNSUPPORTED) {
+    Status = EFI_SUCCESS;
+    DEBUG ((DEBUG_INFO, "%a: WARNING - ETAG is not supported on Redfish service.\n", __func__));
+  } else {
     Status = EFI_DEVICE_ERROR;
+    DEBUG ((DEBUG_ERROR, "%a: Fail to get Location header nor Location property from HTTP response payload.\n", __func__));
   }

   RedfishFreeResponse (
-    PostResponse.StatusCode,
-    PostResponse.HeaderCount,
-    PostResponse.Headers,
-    PostResponse.Payload
+    PatchResponse.StatusCode,
+    PatchResponse.HeaderCount,
+    PatchResponse.Headers,
+    PatchResponse.Payload
     );

 EXIT_FREE_JSON_VALUE:
@@ -1935,7 +1993,7 @@ CreatePayloadToPostResource (
   IN  REDFISH_PAYLOAD  *TargetPayload,
   IN  CHAR8            *Json,
   OUT EFI_STRING       *Location,
-  OUT CHAR8            **Etag
+  OUT CHAR8            **Etag OPTIONAL
   )
 {
   REDFISH_PAYLOAD   Payload;
@@ -1943,7 +2001,7 @@ CreatePayloadToPostResource (
   REDFISH_RESPONSE  PostResponse;
   EFI_STATUS        Status;

-  if ((Service == NULL) || (TargetPayload == NULL) || IS_EMPTY_STRING (Json) || (Location == NULL) || (Etag == NULL)) {
+  if ((Service == NULL) || (TargetPayload == NULL) || IS_EMPTY_STRING (Json) || (Location == NULL)) {
     return EFI_INVALID_PARAMETER;
   }

@@ -1970,12 +2028,22 @@ CreatePayloadToPostResource (
     goto EXIT_FREE_JSON_VALUE;
   }

+  Status = GetHttpResponseEtag (&PostResponse, Etag);
+  if (Status == EFI_UNSUPPORTED) {
+    Status = EFI_SUCCESS;
+    DEBUG ((DEBUG_INFO, "%a: WARNING - ETAG is not supported on Redfish service.\n", __func__));
+  } else if (EFI_ERROR (Status)) {
+    Status = EFI_DEVICE_ERROR;
+    DEBUG ((DEBUG_ERROR, "%a: Fail to get ETAG header nor ETAG property from HTTP response payload.\n", __func__));
+  }
+
   //
   // per Redfish spec. the URL of new resource will be returned in "Location" header.
   //
-  Status = GetEtagAndLocation (&PostResponse, Etag, Location);
+  Status = GetHttpResponseLocation (&PostResponse, Location);
   if (EFI_ERROR (Status)) {
     Status = EFI_DEVICE_ERROR;
+    DEBUG ((DEBUG_ERROR, "%a: Fail to get Location header nor Location proerty from HTTP response payload.\n", __func__));
   }

   RedfishFreeResponse (
@@ -3117,6 +3185,11 @@ CheckEtag (
 {
   CHAR8  *EtagInDb;

+  if (!CheckIsServerEtagSupported ()) {
+    DEBUG ((DEBUG_INFO, "%a: WARNING - ETAG is not supported, always returns FALSE to consume resource (Performance would be reduced).\n", __func__));
+    return FALSE;
+  }
+
   if (IS_EMPTY_STRING (Uri)) {
     return FALSE;
   }
--
2.37.1.windows.1

-The information contained in this message may be confidential and proprietary to American Megatrends (AMI). This communication is intended to be read only by the individual or entity to whom it is addressed or by their designee. If the reader of this message is not the intended recipient, you are on notice that any distribution of this message, in any form, is strictly prohibited. Please promptly notify the sender by reply e-mail or by telephone at 770-246-8600, and then delete or destroy all copies of the transmission.


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#113399): https://edk2.groups.io/g/devel/message/113399
Mute This Topic: https://groups.io/mt/103590679/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-