Browse Source

RedfishPkg/RedfishRestExDxe: Two PCDs for controlling the requests

Since BIOS should work with different BMC implementation chunked requests
as well as Expect header should be optional.
 - One PCD is used to enable/disable Expect header.
 - Another PCD is used to enable/disable chunked requests.

Reviewed-by: Abner Chang <abner.chang@amd.com>
Cc: Abner Chang <abner.chang@amd.com>
Cc: Nickle Wang <nicklew@nvidia.com>
Signed-off-by: Igor Kulchytskyy <igork@ami.com>
Abner Chang 1 year ago
parent
commit
39254d922e

+ 11 - 0
RedfishPkg/RedfishPkg.dec

@@ -3,6 +3,7 @@
 #
 # Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
 # (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+# Copyright (c) 2023, American Megatrends International LLC.
 #
 # SPDX-License-Identifier: BSD-2-Clause-Patent
 ##
@@ -97,3 +98,13 @@
   # protocol instance.
   #
   gEfiRedfishPkgTokenSpaceGuid.PcdRedfishDiscoverAccessModeInBand|FALSE|BOOLEAN|0x00001002
+  #
+  # This PCD indicates if the EFI REST EX sends chunk request to Redfish service.
+  # Default is set to non chunk mode.
+  #
+  gEfiRedfishPkgTokenSpaceGuid.PcdRedfishRestExChunkRequestMode|FALSE|BOOLEAN|0x00001003
+  #
+  # This PCD indicates if the EFI REST EX adds Expect header to the POST, PATCH, PUT requests to Redfish service.
+  # Default is set to not add.
+  #
+  gEfiRedfishPkgTokenSpaceGuid.PcdRedfishRestExAddingExpect|FALSE|BOOLEAN|0x00001004

+ 4 - 1
RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf

@@ -3,6 +3,7 @@
 #
 #  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
 #  (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+#  Copyright (c) 2023, American Megatrends International LLC.
 #
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
 #
@@ -56,7 +57,9 @@
   gEfiDevicePathProtocolGuid                      ## TO_START
 
 [Pcd]
-  gEfiRedfishPkgTokenSpaceGuid.PcdRedfishRestExServiceAccessModeInBand   ## CONSUMES
+  gEfiRedfishPkgTokenSpaceGuid.PcdRedfishRestExServiceAccessModeInBand ## CONSUMES
+  gEfiRedfishPkgTokenSpaceGuid.PcdRedfishRestExChunkRequestMode        ## CONSUMES
+  gEfiRedfishPkgTokenSpaceGuid.PcdRedfishRestExAddingExpect            ## CONSUMES
 
 [UserExtensions.TianoCore."ExtraFiles"]
   RedfishRestExDxeExtra.uni

+ 16 - 8
RedfishPkg/RedfishRestExDxe/RedfishRestExImpl.c

@@ -3,6 +3,7 @@
 
   Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
   (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+  Copyright (c) 2023, American Megatrends International LLC.
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
@@ -140,9 +141,6 @@ RedfishHttpAddExpectation (
   }
 
   *ItsWrite = FALSE;
-  if (PreservedRequestHeaders != NULL) {
-    *PreservedRequestHeaders = RequestMessage->Headers;
-  }
 
   if ((RequestMessage->Data.Request->Method != HttpMethodPut) && (RequestMessage->Data.Request->Method != HttpMethodPost) &&
       (RequestMessage->Data.Request->Method != HttpMethodPatch))
@@ -152,10 +150,20 @@ RedfishHttpAddExpectation (
 
   *ItsWrite = TRUE;
 
-  NewHeaders = AllocateZeroPool ((RequestMessage->HeaderCount + 1) * sizeof (EFI_HTTP_HEADER));
-  CopyMem ((VOID *)NewHeaders, (VOID *)RequestMessage->Headers, RequestMessage->HeaderCount * sizeof (EFI_HTTP_HEADER));
-  HttpSetFieldNameAndValue (NewHeaders + RequestMessage->HeaderCount, HTTP_HEADER_EXPECT, HTTP_EXPECT_100_CONTINUE);
-  RequestMessage->HeaderCount++;
-  RequestMessage->Headers = NewHeaders;
+  //
+  // Check PCD before adding Expect header
+  //
+  if (FixedPcdGetBool (PcdRedfishRestExAddingExpect)) {
+    if (PreservedRequestHeaders != NULL) {
+      *PreservedRequestHeaders = RequestMessage->Headers;
+    }
+
+    NewHeaders = AllocateZeroPool ((RequestMessage->HeaderCount + 1) * sizeof (EFI_HTTP_HEADER));
+    CopyMem ((VOID *)NewHeaders, (VOID *)RequestMessage->Headers, RequestMessage->HeaderCount * sizeof (EFI_HTTP_HEADER));
+    HttpSetFieldNameAndValue (NewHeaders + RequestMessage->HeaderCount, HTTP_HEADER_EXPECT, HTTP_EXPECT_100_CONTINUE);
+    RequestMessage->HeaderCount++;
+    RequestMessage->Headers = NewHeaders;
+  }
+
   return EFI_SUCCESS;
 }

+ 85 - 53
RedfishPkg/RedfishRestExDxe/RedfishRestExProtocol.c

@@ -3,6 +3,7 @@
 
    Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
   (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+  Copyright (c) 2023, American Megatrends International LLC.
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
@@ -66,11 +67,13 @@ RedfishRestExSendReceive (
   HTTP_IO_SEND_NON_CHUNK_PROCESS  SendNonChunkProcess;
   EFI_HTTP_MESSAGE                ChunkTransferRequestMessage;
 
-  Status               = EFI_SUCCESS;
-  ResponseData         = NULL;
-  IsGetChunkedTransfer = FALSE;
-  SendChunkProcess     = HttpIoSendChunkNone;
-  SendNonChunkProcess  = HttpIoSendNonChunkNone;
+  Status                  = EFI_SUCCESS;
+  ResponseData            = NULL;
+  IsGetChunkedTransfer    = FALSE;
+  SendChunkProcess        = HttpIoSendChunkNone;
+  SendNonChunkProcess     = HttpIoSendNonChunkNone;
+  ItsWrite                = FALSE;
+  PreservedRequestHeaders = NULL;
 
   //
   // Validate the parameters
@@ -94,67 +97,84 @@ RedfishRestExSendReceive (
   DEBUG ((DEBUG_INFO, "\nRedfishRestExSendReceive():\n"));
   DEBUG ((DEBUG_INFO, "*** Perform HTTP Request Method - %d, URL: %s\n", RequestMessage->Data.Request->Method, RequestMessage->Data.Request->Url));
 
-  //
-  // Add header "Expect" to server, only for URL write.
-  //
-  Status = RedfishHttpAddExpectation (This, RequestMessage, &PreservedRequestHeaders, &ItsWrite);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
+  if (FixedPcdGetBool (PcdRedfishRestExChunkRequestMode)) {
+    //
+    // Add header "Expect" to server, only for URL write.
+    //
+    Status = RedfishHttpAddExpectation (This, RequestMessage, &PreservedRequestHeaders, &ItsWrite);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
 
-  if (ItsWrite == TRUE) {
-    if (RequestMessage->BodyLength > HTTP_IO_MAX_SEND_PAYLOAD) {
-      //
-      // Send chunked transfer.
-      //
-      SendChunkProcess++;
-      CopyMem ((VOID *)&ChunkTransferRequestMessage, (VOID *)RequestMessage, sizeof (EFI_HTTP_MESSAGE));
-    } else {
-      SendNonChunkProcess++;
+    if (ItsWrite == TRUE) {
+      if (RequestMessage->BodyLength > HTTP_IO_MAX_SEND_PAYLOAD) {
+        //
+        // Send chunked transfer.
+        //
+        SendChunkProcess++;
+        CopyMem ((VOID *)&ChunkTransferRequestMessage, (VOID *)RequestMessage, sizeof (EFI_HTTP_MESSAGE));
+      } else {
+        SendNonChunkProcess++;
+      }
     }
   }
 
 ReSendRequest:;
-  //
-  // Send out the request to REST service.
-  //
-  if (ItsWrite == TRUE) {
+
+  if (FixedPcdGetBool (PcdRedfishRestExChunkRequestMode)) {
     //
-    // This is write to URI
+    // Send the chunked request to REST service.
     //
-    if (SendChunkProcess > HttpIoSendChunkNone) {
+    if (ItsWrite == TRUE) {
       //
-      // This is chunk transfer for writing large payload.
-      // Send request header first and then handle the
-      // following request message body using chunk transfer.
+      // This is write to URI
       //
-      do {
-        Status = HttpIoSendChunkedTransfer (
+      if (SendChunkProcess > HttpIoSendChunkNone) {
+        //
+        // This is chunk transfer for writing large payload.
+        // Send request header first and then handle the
+        // following request message body using chunk transfer.
+        //
+        do {
+          Status = HttpIoSendChunkedTransfer (
+                     &(Instance->HttpIo),
+                     &SendChunkProcess,
+                     &ChunkTransferRequestMessage
+                     );
+          if (EFI_ERROR (Status)) {
+            goto ON_EXIT;
+          }
+        } while (SendChunkProcess == HttpIoSendChunkContent || SendChunkProcess == HttpIoSendChunkEndChunk);
+      } else {
+        //
+        // This is the non-chunk transfer, send request header first and then
+        // handle the following request message body using chunk transfer.
+        //
+        Status = HttpIoSendRequest (
                    &(Instance->HttpIo),
-                   &SendChunkProcess,
-                   &ChunkTransferRequestMessage
+                   (SendNonChunkProcess == HttpIoSendNonChunkContent) ? NULL : RequestMessage->Data.Request,
+                   (SendNonChunkProcess == HttpIoSendNonChunkContent) ? 0 : RequestMessage->HeaderCount,
+                   (SendNonChunkProcess == HttpIoSendNonChunkContent) ? NULL : RequestMessage->Headers,
+                   (SendNonChunkProcess == HttpIoSendNonChunkHeaderZeroContent) ? 0 : RequestMessage->BodyLength,
+                   (SendNonChunkProcess == HttpIoSendNonChunkHeaderZeroContent) ? NULL : RequestMessage->Body
                    );
-        if (EFI_ERROR (Status)) {
-          goto ON_EXIT;
-        }
-      } while (SendChunkProcess == HttpIoSendChunkContent || SendChunkProcess == HttpIoSendChunkEndChunk);
+      }
     } else {
       //
-      // This is the non-chunk transfer, send request header first and then
-      // handle the following request message body using chunk transfer.
+      // This is read from URI.
       //
       Status = HttpIoSendRequest (
                  &(Instance->HttpIo),
-                 (SendNonChunkProcess == HttpIoSendNonChunkContent) ? NULL : RequestMessage->Data.Request,
-                 (SendNonChunkProcess == HttpIoSendNonChunkContent) ? 0 : RequestMessage->HeaderCount,
-                 (SendNonChunkProcess == HttpIoSendNonChunkContent) ? NULL : RequestMessage->Headers,
-                 (SendNonChunkProcess == HttpIoSendNonChunkHeaderZeroContent) ? 0 : RequestMessage->BodyLength,
-                 (SendNonChunkProcess == HttpIoSendNonChunkHeaderZeroContent) ? NULL : RequestMessage->Body
+                 RequestMessage->Data.Request,
+                 RequestMessage->HeaderCount,
+                 RequestMessage->Headers,
+                 RequestMessage->BodyLength,
+                 RequestMessage->Body
                  );
     }
   } else {
     //
-    // This is read from URI.
+    // This is normal request to URI.
     //
     Status = HttpIoSendRequest (
                &(Instance->HttpIo),
@@ -213,7 +233,7 @@ ReSendRequest:;
   //
   // Restore the headers if it ever changed in RedfishHttpAddExpectation().
   //
-  if (RequestMessage->Headers != PreservedRequestHeaders) {
+  if (FixedPcdGetBool (PcdRedfishRestExAddingExpect) && (RequestMessage->Headers != PreservedRequestHeaders)) {
     FreePool (RequestMessage->Headers);
     RequestMessage->Headers = PreservedRequestHeaders; // Restore headers before we adding "Expect".
     RequestMessage->HeaderCount--;                     // Minus one header count for "Expect".
@@ -223,11 +243,23 @@ ReSendRequest:;
   if (ResponseData->Response.StatusCode == HTTP_STATUS_200_OK) {
     DEBUG ((DEBUG_INFO, "HTTP_STATUS_200_OK\n"));
 
-    if (SendChunkProcess == HttpIoSendChunkHeaderZeroContent) {
-      DEBUG ((DEBUG_INFO, "This is chunk transfer, start to send all chunks."));
+    if (FixedPcdGetBool (PcdRedfishRestExChunkRequestMode) && (SendChunkProcess == HttpIoSendChunkHeaderZeroContent)) {
+      DEBUG ((DEBUG_INFO, "This is chunk transfer, start to send all chunks - %d.", ResponseData->Response.StatusCode));
+      SendChunkProcess++;
+      goto ReSendRequest;
+    }
+  } else if (ResponseData->Response.StatusCode == HTTP_STATUS_204_NO_CONTENT) {
+    DEBUG ((DEBUG_INFO, "HTTP_STATUS_204_NO_CONTENT\n"));
+
+    if (FixedPcdGetBool (PcdRedfishRestExChunkRequestMode) && (SendChunkProcess == HttpIoSendChunkHeaderZeroContent)) {
+      DEBUG ((DEBUG_INFO, "This is chunk transfer, start to send all chunks - %d.", ResponseData->Response.StatusCode));
       SendChunkProcess++;
       goto ReSendRequest;
     }
+  } else if (ResponseData->Response.StatusCode == HTTP_STATUS_201_CREATED) {
+    DEBUG ((DEBUG_INFO, "HTTP_STATUS_201_CREATED\n"));
+  } else if (ResponseData->Response.StatusCode == HTTP_STATUS_202_ACCEPTED) {
+    DEBUG ((DEBUG_INFO, "HTTP_STATUS_202_ACCEPTED\n"));
   } else if (ResponseData->Response.StatusCode == HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE) {
     DEBUG ((DEBUG_INFO, "HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE\n"));
 
@@ -240,14 +272,14 @@ ReSendRequest:;
     goto ON_EXIT;
   } else if (ResponseData->Response.StatusCode == HTTP_STATUS_400_BAD_REQUEST) {
     DEBUG ((DEBUG_INFO, "HTTP_STATUS_400_BAD_REQUEST\n"));
-    if (SendChunkProcess == HttpIoSendChunkHeaderZeroContent) {
+    if (FixedPcdGetBool (PcdRedfishRestExChunkRequestMode) && (SendChunkProcess == HttpIoSendChunkHeaderZeroContent)) {
       DEBUG ((DEBUG_INFO, "Bad request may caused by zero length chunk. Try to send all chunks...\n"));
       SendChunkProcess++;
       goto ReSendRequest;
     }
   } else if (ResponseData->Response.StatusCode == HTTP_STATUS_100_CONTINUE) {
     DEBUG ((DEBUG_INFO, "HTTP_STATUS_100_CONTINUE\n"));
-    if (SendChunkProcess == HttpIoSendChunkHeaderZeroContent) {
+    if (FixedPcdGetBool (PcdRedfishRestExChunkRequestMode) && (SendChunkProcess == HttpIoSendChunkHeaderZeroContent)) {
       //
       // We get HTTP_STATUS_100_CONTINUE to send the body using chunk transfer.
       //
@@ -256,7 +288,7 @@ ReSendRequest:;
       goto ReSendRequest;
     }
 
-    if (SendNonChunkProcess == HttpIoSendNonChunkHeaderZeroContent) {
+    if (FixedPcdGetBool (PcdRedfishRestExChunkRequestMode) && (SendNonChunkProcess == HttpIoSendNonChunkHeaderZeroContent)) {
       DEBUG ((DEBUG_INFO, "HTTP_STATUS_100_CONTINUE for non chunk transfer...\n"));
       SendNonChunkProcess++;
       goto ReSendRequest;
@@ -394,7 +426,7 @@ ReSendRequest:;
       TotalReceivedSize += ResponseData->BodyLength;
     }
 
-    DEBUG ((DEBUG_INFO, "Total of lengh of Response :%d\n", TotalReceivedSize));
+    DEBUG ((DEBUG_INFO, "Total of length of Response :%d\n", TotalReceivedSize));
   }
 
   DEBUG ((DEBUG_INFO, "RedfishRestExSendReceive()- EFI_STATUS: %r\n", Status));