public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [edk2-devel] [edk2-redfish-client][PATCH V3] RedfishClientPkg: Add ETag PCD and revise Redfish ETag functions
@ 2024-01-04  9:09 Chang, Abner via groups.io
  2024-01-04 14:58 ` Igor Kulchytskyy via groups.io
  0 siblings, 1 reply; 4+ messages in thread
From: Chang, Abner via groups.io @ 2024-01-04  9:09 UTC (permalink / raw)
  To: devel; +Cc: Nickle Wang, Igor Kulchytskyy, Mike Maslenkin

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..f767b4d875 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 proerty 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 propertyfrom 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 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 (#113156): https://edk2.groups.io/g/devel/message/113156
Mute This Topic: https://groups.io/mt/103519370/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2024-01-08 14:45 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-01-04  9:09 [edk2-devel] [edk2-redfish-client][PATCH V3] RedfishClientPkg: Add ETag PCD and revise Redfish ETag functions Chang, Abner via groups.io
2024-01-04 14:58 ` Igor Kulchytskyy via groups.io
2024-01-08  2:42   ` Chang, Abner via groups.io
2024-01-08 14:45     ` Igor Kulchytskyy via groups.io

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox