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>
This commit is contained in:
Abner Chang 2023-02-10 02:05:12 +08:00 committed by mergify[bot]
parent 289d93b79c
commit 39254d922e
4 changed files with 116 additions and 62 deletions

View File

@ -3,6 +3,7 @@
# #
# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> # Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
# (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR> # (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
# Copyright (c) 2023, American Megatrends International LLC.
# #
# SPDX-License-Identifier: BSD-2-Clause-Patent # SPDX-License-Identifier: BSD-2-Clause-Patent
## ##
@ -97,3 +98,13 @@
# protocol instance. # protocol instance.
# #
gEfiRedfishPkgTokenSpaceGuid.PcdRedfishDiscoverAccessModeInBand|FALSE|BOOLEAN|0x00001002 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

View File

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

View File

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

View File

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