Hi Abner,

Thank you for the clarification.

Regards,
Mike.

On Fri, Jan 5, 2024 at 12:03 PM Chang, Abner <abner.ch...@amd.com> wrote:
>
> [AMD Official Use Only - General]
>
> Hi Mike,
> This PCD is introduced for the platform that connects to the Redfish service 
> which doesn't support ETag.
> We disable the client code that handles ETag with setting this PCD to FALSE. 
> So client will just consume any Redfish property from service even there is 
> nothing changed. This knob doesn't control Redfish service behavior on BMC.
> Yes, there is no method to detect if Redfish service supports ETag or not. So 
> we introduce a client side knob to disable ETag checking although it mentions 
> the service "should" support ETag in Redfish spec. However, a simple Redfish 
> services may not implementing ETag HTTP header.
> Does above clarify the question?
>
> Thanks
> Abner
>
> > -----Original Message-----
> > From: Mike Maslenkin <mike.maslen...@gmail.com>
> > Sent: Friday, January 5, 2024 8:20 AM
> > To: devel@edk2.groups.io; Chang, Abner <abner.ch...@amd.com>
> > Cc: Nickle Wang <nick...@nvidia.com>; Igor Kulchytskyy <ig...@ami.com>
> > Subject: Re: [edk2-devel] [edk2-redfish-client][PATCH V2] RedfishClientPkg:
> > Add ETag PCD and revise Redfish ETag functions
> >
> > Caution: This message originated from an External Source. Use proper caution
> > when opening attachments, clicking links, or responding.
> >
> >
> > Looks good to me.
> >
> > But could it be possible to rephrase "ETAG is not supported on Redfish
> > service." ?
> > May be I misunderstand, but I assume "Redfish service" is a service at
> > BMC side, while we are disabling ETAG functionality at Redfish client
> > side.
> > README.md says "Redfish service hosted by Board Management Controller
> > (BMC) in server".
> > Currently there is no method to get server features (AFAIR), so we
> > disable a work with those explicitly on the client side.
> >
> > Regards,
> > Mike.
> >
> > On Thu, Jan 4, 2024 at 11:57 AM Chang, Abner via groups.io
> > <abner.chang=amd....@groups.io> wrote:
> > >
> > > From: Abner Chang <abner.ch...@amd.com>
> > >
> > > Add PCD to disable ETag capability for the case Redfish
> > > service doesn't support ETag.
> > >
> > > Signed-off-by: Abner Chang <abner.ch...@amd.com>
> > > Cc: Nickle Wang <nick...@nvidia.com>
> > > Cc: Igor Kulchytskyy <ig...@ami.com>
> > > Cc: Mike Maslenkin <mike.maslen...@gmail.com>
> > > ---
> > >  RedfishClientPkg/RedfishClientPkg.dec         |   2 +
> > >  .../RedfishFeatureUtilityLib.inf              |   1 +
> > >  .../Library/RedfishFeatureUtilityLib.h        |  46 +++-
> > >  .../Features/Bios/v1_0_9/Dxe/BiosDxe.c        |  18 +-
> > >  .../v1_0_4/Common/BootOptionCommon.c          |   4 +-
> > >  .../BootOption/v1_0_4/Dxe/BootOptionDxe.c     |  16 +-
> > >  .../v1_5_0/Dxe/ComputerSystemDxe.c            |  16 +-
> > >  .../Features/Memory/V1_7_1/Dxe/MemoryDxe.c    |  16 +-
> > >  .../RedfishFeatureUtilityLib.c                | 208 ++++++++++++------
> > >  9 files changed, 197 insertions(+), 130 deletions(-)
> > >
> > > diff --git a/RedfishClientPkg/RedfishClientPkg.dec
> > b/RedfishClientPkg/RedfishClientPkg.dec
> > > index b350facae0..8adef327fb 100644
> > > --- a/RedfishClientPkg/RedfishClientPkg.dec
> > > +++ b/RedfishClientPkg/RedfishClientPkg.dec
> > > @@ -76,6 +76,8 @@
> > >
> > gEfiRedfishClientPkgTokenSpaceGuid.PcdDefaultRedfishVersion|L"v1"|VOID*
> > |0x10000004
> > >    ## The number of seconds that the firmware will wait before system 
> > > reboot
> > >
> > gEfiRedfishClientPkgTokenSpaceGuid.PcdRedfishSystemRebootTimeout|5|UI
> > NT16|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.i
> > nf
> > b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.i
> > nf
> > > index 718273b248..fde6a176d0 100644
> > > ---
> > a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.i
> > nf
> > > +++
> > b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.i
> > nf
> > > @@ -54,6 +54,7 @@
> > >
> > >  [Pcd]
> > >    gEfiRedfishClientPkgTokenSpaceGuid.PcdRedfishSystemRebootRequired
> > > +  gEfiRedfishClientPkgTokenSpaceGuid.PcdRedfishServiceEtagSupported
> > >
> > >  [Guids]
> > >
> > > diff --git a/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
> > b/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
> > > index 9513a65617..834ea0fcfe 100644
> > > --- a/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
> > > +++ b/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
> > > @@ -81,7 +81,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 +559,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 +944,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..14e854c861 100644
> > > --- a/RedfishClientPkg/Features/Bios/v1_0_9/Dxe/BiosDxe.c
> > > +++ b/RedfishClientPkg/Features/Bios/v1_0_9/Dxe/BiosDxe.c
> > > @@ -153,14 +153,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 +361,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/BootOptionCom
> > mon.c
> > b/RedfishClientPkg/Features/BootOption/v1_0_4/Common/BootOptionCom
> > mon.c
> > > index 0d4c2162c6..0b9a72abc3 100644
> > > ---
> > a/RedfishClientPkg/Features/BootOption/v1_0_4/Common/BootOptionCom
> > mon.c
> > > +++
> > b/RedfishClientPkg/Features/BootOption/v1_0_4/Common/BootOptionCom
> > mon.c
> > > @@ -455,9 +455,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..204c6b0757 100644
> > > --- a/RedfishClientPkg/Features/BootOption/v1_0_4/Dxe/BootOptionDxe.c
> > > +++
> > b/RedfishClientPkg/Features/BootOption/v1_0_4/Dxe/BootOptionDxe.c
> > > @@ -154,12 +154,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 +354,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/ComputerSyste
> > mDxe.c
> > b/RedfishClientPkg/Features/ComputerSystem/v1_5_0/Dxe/ComputerSyste
> > mDxe.c
> > > index 0bbaa92bf4..7805bcf36b 100644
> > > ---
> > a/RedfishClientPkg/Features/ComputerSystem/v1_5_0/Dxe/ComputerSyste
> > mDxe.c
> > > +++
> > b/RedfishClientPkg/Features/ComputerSystem/v1_5_0/Dxe/ComputerSyste
> > mDxe.c
> > > @@ -149,12 +149,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 +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 ((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..b87da775b3 100644
> > > --- a/RedfishClientPkg/Features/Memory/V1_7_1/Dxe/MemoryDxe.c
> > > +++ b/RedfishClientPkg/Features/Memory/V1_7_1/Dxe/MemoryDxe.c
> > > @@ -149,12 +149,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 +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 ((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..7709a9d1a2 100644
> > > ---
> > a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.
> > c
> > > +++
> > b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.
> > c
> > > @@ -133,6 +133,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 +162,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 +246,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 +296,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 +1741,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 +1803,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 +1914,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 +1929,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 +1938,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 +1946,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 +1992,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 +2000,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 +2027,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 +3184,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 (#113275): https://edk2.groups.io/g/devel/message/113275
Mute This Topic: https://groups.io/mt/103519287/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-


Reply via email to