diff --git a/RedfishClientPkg/Features/Bios/v1_0_9/Common/BiosCommon.c b/RedfishClientPkg/Features/Bios/v1_0_9/Common/BiosCommon.c index f96c90cc9..3b6eab3fd 100644 --- a/RedfishClientPkg/Features/Bios/v1_0_9/Common/BiosCommon.c +++ b/RedfishClientPkg/Features/Bios/v1_0_9/Common/BiosCommon.c @@ -267,18 +267,22 @@ ProvisioningBiosResource ( IN EFI_STRING ConfigureLang ) { - CHAR8 *Json; - CHAR8 *JsonWithAddendum; - EFI_STATUS Status; - EFI_STRING NewResourceLocation; - CHAR8 *EtagStr; - CHAR8 ResourceId[16]; + CHAR8 *Json; + CHAR8 *JsonWithAddendum; + EFI_STATUS Status; + EFI_STRING NewResourceLocation; + CHAR8 *EtagStr; + CHAR8 ResourceId[16]; + REDFISH_RESPONSE Response; if (IS_EMPTY_STRING (ConfigureLang) || (Private == NULL)) { return EFI_INVALID_PARAMETER; } - EtagStr = NULL; + EtagStr = NULL; + Json = NULL; + NewResourceLocation = NULL; + ZeroMem (&Response, sizeof (REDFISH_RESPONSE)); AsciiSPrint (ResourceId, sizeof (ResourceId), "%d", Index); Status = ProvisioningBiosProperties ( @@ -326,19 +330,25 @@ ProvisioningBiosResource ( JsonWithAddendum = NULL; } - Status = CreatePayloadToPostResource (Private->RedfishService, Private->Payload, Json, &NewResourceLocation, &EtagStr); + Status = RedfishHttpPostResource (Private->RedfishService, Private->Uri, Json, &Response); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a, post Bios resource for %s failed: %r\n", __func__, ConfigureLang, Status)); goto RELEASE_RESOURCE; } + Status = GetEtagAndLocation (&Response, &EtagStr, &NewResourceLocation); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, get ETag and location failed: %r\n", __func__, Status)); + goto RELEASE_RESOURCE; + } + ASSERT (NewResourceLocation != NULL); // // Keep location of new resource. // if (NewResourceLocation != NULL) { - RedfisSetRedfishUri (ConfigureLang, NewResourceLocation); + RedfishSetRedfishUri (ConfigureLang, NewResourceLocation); } // @@ -359,6 +369,8 @@ ProvisioningBiosResource ( FreePool (Json); } + RedfishHttpFreeResource (&Response); + return Status; } @@ -401,11 +413,12 @@ ProvisioningBiosExistResource ( IN REDFISH_RESOURCE_COMMON_PRIVATE *Private ) { - EFI_STATUS Status; - EFI_STRING ConfigureLang; - CHAR8 *EtagStr; - CHAR8 *Json; - CHAR8 *JsonWithAddendum; + EFI_STATUS Status; + EFI_STRING ConfigureLang; + CHAR8 *EtagStr; + CHAR8 *Json; + CHAR8 *JsonWithAddendum; + REDFISH_RESPONSE Response; if (Private == NULL) { return EFI_INVALID_PARAMETER; @@ -414,6 +427,7 @@ ProvisioningBiosExistResource ( EtagStr = NULL; Json = NULL; ConfigureLang = NULL; + ZeroMem (&Response, sizeof (REDFISH_RESPONSE)); ConfigureLang = RedfishGetConfigLanguage (Private->Uri); if (ConfigureLang == NULL) { @@ -472,13 +486,19 @@ ProvisioningBiosExistResource ( DEBUG ((REDFISH_DEBUG_TRACE, "%a, provisioning existing resource for %s\n", __func__, ConfigureLang)); // - // PUT back to instance + // PATCH back to instance // - Status = CreatePayloadToPatchResource (Private->RedfishService, Private->Payload, Json, &EtagStr); + Status = RedfishHttpPatchResource (Private->RedfishService, Private->Uri, Json, &Response); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a, patch resource for %s failed: %r\n", __func__, ConfigureLang, Status)); } + Status = GetEtagAndLocation (&Response, &EtagStr, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, get ETag failed: %r\n", __func__, Status)); + goto ON_RELEASE; + } + // // Handle Etag // @@ -497,6 +517,8 @@ ProvisioningBiosExistResource ( FreePool (ConfigureLang); } + RedfishHttpFreeResource (&Response); + return Status; } @@ -595,11 +617,12 @@ RedfishUpdateResourceCommon ( IN CHAR8 *InputJson ) { - EFI_STATUS Status; - CHAR8 *Json; - CHAR8 *JsonWithAddendum; - EFI_STRING ConfigureLang; - CHAR8 *EtagStr; + EFI_STATUS Status; + CHAR8 *Json; + CHAR8 *JsonWithAddendum; + EFI_STRING ConfigureLang; + CHAR8 *EtagStr; + REDFISH_RESPONSE Response; if ((Private == NULL) || IS_EMPTY_STRING (InputJson)) { return EFI_INVALID_PARAMETER; @@ -608,6 +631,7 @@ RedfishUpdateResourceCommon ( EtagStr = NULL; Json = NULL; ConfigureLang = NULL; + ZeroMem (&Response, sizeof (REDFISH_RESPONSE)); ConfigureLang = RedfishGetConfigLanguage (Private->Uri); if (ConfigureLang == NULL) { @@ -666,13 +690,19 @@ RedfishUpdateResourceCommon ( DEBUG ((REDFISH_DEBUG_TRACE, "%a, update resource for %s\n", __func__, ConfigureLang)); // - // PUT back to instance + // PATCH back to instance // - Status = CreatePayloadToPatchResource (Private->RedfishService, Private->Payload, Json, &EtagStr); + Status = RedfishHttpPatchResource (Private->RedfishService, Private->Uri, Json, &Response); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a, patch resource for %s failed: %r\n", __func__, ConfigureLang, Status)); } + Status = GetEtagAndLocation (&Response, &EtagStr, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, get ETag failed: %r\n", __func__, Status)); + goto ON_RELEASE; + } + // // Handle Etag // @@ -691,6 +721,8 @@ RedfishUpdateResourceCommon ( FreePool (ConfigureLang); } + RedfishHttpFreeResource (&Response); + return Status; } @@ -745,7 +777,7 @@ RedfishIdentifyResourceCommon ( // // Keep URI and ConfigLang mapping // - RedfisSetRedfishUri (ConfigLangList.List[0].ConfigureLang, Private->Uri); + RedfishSetRedfishUri (ConfigLangList.List[0].ConfigureLang, Private->Uri); // // Set the configuration language in the RESOURCE_INFORMATION_EXCHANGE. // This information is sent back to the parent resource (e.g. the collection driver). diff --git a/RedfishClientPkg/Features/Bios/v1_0_9/Dxe/BiosDxe.c b/RedfishClientPkg/Features/Bios/v1_0_9/Dxe/BiosDxe.c index 9b336d3de..ee294c4bb 100644 --- a/RedfishClientPkg/Features/Bios/v1_0_9/Dxe/BiosDxe.c +++ b/RedfishClientPkg/Features/Bios/v1_0_9/Dxe/BiosDxe.c @@ -56,7 +56,8 @@ RedfishResourceProvisioningResource ( return EFI_NOT_READY; } - Status = GetResourceByUri (Private->RedfishService, Uri, &Response); + ZeroMem (&Response, sizeof (Response)); + Status = RedfishHttpGetResource (Private->RedfishService, Uri, &Response, TRUE); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a, get resource from: %s failed\n", __func__, Uri)); return Status; @@ -72,12 +73,7 @@ RedfishResourceProvisioningResource ( // Release resource // if (Private->Payload != NULL) { - RedfishFreeResponse ( - Response.StatusCode, - Response.HeaderCount, - Response.Headers, - Response.Payload - ); + RedfishHttpFreeResource (&Response); Private->Payload = NULL; } @@ -122,7 +118,8 @@ RedfishResourceConsumeResource ( return EFI_NOT_READY; } - Status = GetResourceByUri (Private->RedfishService, Uri, &Response); + ZeroMem (&Response, sizeof (Response)); + Status = RedfishHttpGetResource (Private->RedfishService, Uri, &Response, TRUE); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a, get resource from: %s failed\n", __func__, Uri)); return Status; @@ -151,7 +148,7 @@ RedfishResourceConsumeResource ( // RedfishSettingsUri = JsonValueGetUnicodeString (JsonValue); - Status = GetResourceByUri (Private->RedfishService, RedfishSettingsUri, &RedfishSettingsResponse); + Status = RedfishHttpGetResource (Private->RedfishService, RedfishSettingsUri, &RedfishSettingsResponse, TRUE); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a, @Redfish.Settings exists, get resource from: %s failed\n", __FUNCTION__, RedfishSettingsUri)); } else { @@ -195,21 +192,11 @@ RedfishResourceConsumeResource ( // if (Private->Payload != NULL) { if (Response.Payload != NULL) { - RedfishFreeResponse ( - Response.StatusCode, - Response.HeaderCount, - Response.Headers, - Response.Payload - ); + RedfishHttpFreeResource (&Response); } if (RedfishSettingsResponse.Payload != NULL) { - RedfishFreeResponse ( - RedfishSettingsResponse.StatusCode, - RedfishSettingsResponse.HeaderCount, - RedfishSettingsResponse.Headers, - RedfishSettingsResponse.Payload - ); + RedfishHttpFreeResource (&RedfishSettingsResponse); } Private->Payload = NULL; @@ -290,7 +277,8 @@ RedfishResourceUpdate ( return EFI_NOT_READY; } - Status = GetResourceByUri (Private->RedfishService, Uri, &Response); + ZeroMem (&Response, sizeof (Response)); + Status = RedfishHttpGetResource (Private->RedfishService, Uri, &Response, TRUE); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a, get resource from: %s failed\n", __func__, Uri)); return Status; @@ -312,12 +300,7 @@ RedfishResourceUpdate ( // Release resource // if (Private->Payload != NULL) { - RedfishFreeResponse ( - Response.StatusCode, - Response.HeaderCount, - Response.Headers, - Response.Payload - ); + RedfishHttpFreeResource (&Response); Private->Payload = NULL; } @@ -360,7 +343,8 @@ RedfishResourceCheck ( return EFI_NOT_READY; } - Status = GetResourceByUri (Private->RedfishService, Uri, &Response); + ZeroMem (&Response, sizeof (Response)); + Status = RedfishHttpGetResource (Private->RedfishService, Uri, &Response, TRUE); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a, get resource from: %s failed\n", __func__, Uri)); return Status; @@ -382,12 +366,7 @@ RedfishResourceCheck ( // Release resource // if (Private->Payload != NULL) { - RedfishFreeResponse ( - Response.StatusCode, - Response.HeaderCount, - Response.Headers, - Response.Payload - ); + RedfishHttpFreeResource (&Response); Private->Payload = NULL; } @@ -431,7 +410,8 @@ RedfishResourceIdentify ( return EFI_NOT_READY; } - Status = GetResourceByUri (Private->RedfishService, Uri, &Response); + ZeroMem (&Response, sizeof (Response)); + Status = RedfishHttpGetResource (Private->RedfishService, Uri, &Response, TRUE); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a, get resource from: %s failed\n", __func__, Uri)); return Status; @@ -453,12 +433,7 @@ RedfishResourceIdentify ( // Release resource // if (Private->Payload != NULL) { - RedfishFreeResponse ( - Response.StatusCode, - Response.HeaderCount, - Response.Headers, - Response.Payload - ); + RedfishHttpFreeResource (&Response); Private->Payload = NULL; } diff --git a/RedfishClientPkg/Features/Bios/v1_0_9/Dxe/BiosDxe.inf b/RedfishClientPkg/Features/Bios/v1_0_9/Dxe/BiosDxe.inf index 37346e50f..dbb032923 100644 --- a/RedfishClientPkg/Features/Bios/v1_0_9/Dxe/BiosDxe.inf +++ b/RedfishClientPkg/Features/Bios/v1_0_9/Dxe/BiosDxe.inf @@ -39,6 +39,7 @@ UefiLib UefiDriverEntryPoint RedfishAddendumLib + RedfishHttpLib [Protocols] gEdkIIRedfishConfigHandlerProtocolGuid ## PRODUCED diff --git a/RedfishClientPkg/Features/ComputerSystem/v1_5_0/Common/ComputerSystemCommon.c b/RedfishClientPkg/Features/ComputerSystem/v1_5_0/Common/ComputerSystemCommon.c index 7ed1bd55e..4f0a81aec 100644 --- a/RedfishClientPkg/Features/ComputerSystem/v1_5_0/Common/ComputerSystemCommon.c +++ b/RedfishClientPkg/Features/ComputerSystem/v1_5_0/Common/ComputerSystemCommon.c @@ -2,6 +2,7 @@ Redfish feature driver implementation - common functions (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP
+ Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. SPDX-License-Identifier: BSD-2-Clause-Patent @@ -1236,17 +1237,21 @@ ProvisioningComputerSystemResource ( IN EFI_STRING ConfigureLang ) { - CHAR8 *Json; - EFI_STATUS Status; - EFI_STRING NewResourceLocation; - CHAR8 *EtagStr; - CHAR8 ResourceId[16]; + CHAR8 *Json; + EFI_STATUS Status; + EFI_STRING NewResourceLocation; + CHAR8 *EtagStr; + CHAR8 ResourceId[16]; + REDFISH_RESPONSE Response; if (IS_EMPTY_STRING (ConfigureLang) || (Private == NULL)) { return EFI_INVALID_PARAMETER; } - EtagStr = NULL; + EtagStr = NULL; + Json = NULL; + NewResourceLocation = NULL; + ZeroMem (&Response, sizeof (REDFISH_RESPONSE)); AsciiSPrint (ResourceId, sizeof (ResourceId), "%d", Index); Status = ProvisioningComputerSystemProperties ( @@ -1262,19 +1267,25 @@ ProvisioningComputerSystemResource ( return Status; } - Status = CreatePayloadToPostResource (Private->RedfishService, Private->Payload, Json, &NewResourceLocation, &EtagStr); + Status = RedfishHttpPostResource (Private->RedfishService, Private->Uri, Json, &Response); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a, post ComputerSystem resource for %s failed: %r\n", __func__, ConfigureLang, Status)); goto RELEASE_RESOURCE; } + Status = GetEtagAndLocation (&Response, &EtagStr, &NewResourceLocation); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, get ETag and location failed: %r\n", __func__, Status)); + goto RELEASE_RESOURCE; + } + ASSERT (NewResourceLocation != NULL); // // Keep location of new resource. // if (NewResourceLocation != NULL) { - RedfisSetRedfishUri (ConfigureLang, NewResourceLocation); + RedfishSetRedfishUri (ConfigureLang, NewResourceLocation); } // @@ -1295,6 +1306,8 @@ ProvisioningComputerSystemResource ( FreePool (Json); } + RedfishHttpFreeResource (&Response); + return Status; } @@ -1337,10 +1350,11 @@ ProvisioningComputerSystemExistResource ( IN REDFISH_RESOURCE_COMMON_PRIVATE *Private ) { - EFI_STATUS Status; - EFI_STRING ConfigureLang; - CHAR8 *EtagStr; - CHAR8 *Json; + EFI_STATUS Status; + EFI_STRING ConfigureLang; + CHAR8 *EtagStr; + CHAR8 *Json; + REDFISH_RESPONSE Response; if (Private == NULL) { return EFI_INVALID_PARAMETER; @@ -1349,6 +1363,7 @@ ProvisioningComputerSystemExistResource ( EtagStr = NULL; Json = NULL; ConfigureLang = NULL; + ZeroMem (&Response, sizeof (REDFISH_RESPONSE)); ConfigureLang = RedfishGetConfigLanguage (Private->Uri); if (ConfigureLang == NULL) { @@ -1375,13 +1390,19 @@ ProvisioningComputerSystemExistResource ( DEBUG ((REDFISH_DEBUG_TRACE, "%a, provisioning existing resource for %s\n", __func__, ConfigureLang)); // - // PUT back to instance + // PATCH back to instance // - Status = CreatePayloadToPatchResource (Private->RedfishService, Private->Payload, Json, &EtagStr); + Status = RedfishHttpPatchResource (Private->RedfishService, Private->Uri, Json, &Response); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a, patch resource for %s failed: %r\n", __func__, ConfigureLang, Status)); } + Status = GetEtagAndLocation (&Response, &EtagStr, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, get ETag failed: %r\n", __func__, Status)); + goto ON_RELEASE; + } + // // Handle Etag // @@ -1400,6 +1421,8 @@ ProvisioningComputerSystemExistResource ( FreePool (ConfigureLang); } + RedfishHttpFreeResource (&Response); + return Status; } @@ -1498,10 +1521,11 @@ RedfishUpdateResourceCommon ( IN CHAR8 *InputJson ) { - EFI_STATUS Status; - CHAR8 *Json; - EFI_STRING ConfigureLang; - CHAR8 *EtagStr; + EFI_STATUS Status; + CHAR8 *Json; + EFI_STRING ConfigureLang; + CHAR8 *EtagStr; + REDFISH_RESPONSE Response; if ((Private == NULL) || IS_EMPTY_STRING (InputJson)) { return EFI_INVALID_PARAMETER; @@ -1510,6 +1534,7 @@ RedfishUpdateResourceCommon ( EtagStr = NULL; Json = NULL; ConfigureLang = NULL; + ZeroMem (&Response, sizeof (REDFISH_RESPONSE)); ConfigureLang = RedfishGetConfigLanguage (Private->Uri); if (ConfigureLang == NULL) { @@ -1536,13 +1561,19 @@ RedfishUpdateResourceCommon ( DEBUG ((REDFISH_DEBUG_TRACE, "%a, update resource for %s\n", __func__, ConfigureLang)); // - // PUT back to instance + // PATCH back to instance // - Status = CreatePayloadToPatchResource (Private->RedfishService, Private->Payload, Json, &EtagStr); + Status = RedfishHttpPatchResource (Private->RedfishService, Private->Uri, Json, &Response); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a, patch resource for %s failed: %r\n", __func__, ConfigureLang, Status)); } + Status = GetEtagAndLocation (&Response, &EtagStr, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, get ETag failed: %r\n", __func__, Status)); + goto ON_RELEASE; + } + // // Handle Etag // @@ -1561,6 +1592,8 @@ RedfishUpdateResourceCommon ( FreePool (ConfigureLang); } + RedfishHttpFreeResource (&Response); + return Status; } @@ -1621,7 +1654,7 @@ RedfishIdentifyResourceCommon ( // // Keep URI and ConfigLang mapping // - RedfisSetRedfishUri (ConfigLangList.List[0].ConfigureLang, Private->Uri); + RedfishSetRedfishUri (ConfigLangList.List[0].ConfigureLang, Private->Uri); // // Set the configuration language in the RESOURCE_INFORMATION_EXCHANGE. // This information is sent back to the parent resource (e.g. the collection driver). diff --git a/RedfishClientPkg/Features/ComputerSystem/v1_5_0/Dxe/ComputerSystemDxe.c b/RedfishClientPkg/Features/ComputerSystem/v1_5_0/Dxe/ComputerSystemDxe.c index 5c2a4eadf..b28082fee 100644 --- a/RedfishClientPkg/Features/ComputerSystem/v1_5_0/Dxe/ComputerSystemDxe.c +++ b/RedfishClientPkg/Features/ComputerSystem/v1_5_0/Dxe/ComputerSystemDxe.c @@ -50,7 +50,8 @@ RedfishResourceProvisioningResource ( return EFI_NOT_READY; } - Status = GetResourceByUri (Private->RedfishService, Uri, &Response); + ZeroMem (&Response, sizeof (Response)); + Status = RedfishHttpGetResource (Private->RedfishService, Uri, &Response, TRUE); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a, get resource from: %s failed\n", __func__, Uri)); return Status; @@ -66,12 +67,7 @@ RedfishResourceProvisioningResource ( // Release resource // if (Private->Payload != NULL) { - RedfishFreeResponse ( - Response.StatusCode, - Response.HeaderCount, - Response.Headers, - Response.Payload - ); + RedfishHttpFreeResource (&Response); Private->Payload = NULL; } @@ -110,7 +106,8 @@ RedfishResourceConsumeResource ( return EFI_NOT_READY; } - Status = GetResourceByUri (Private->RedfishService, Uri, &Response); + ZeroMem (&Response, sizeof (Response)); + Status = RedfishHttpGetResource (Private->RedfishService, Uri, &Response, TRUE); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a, get resource from: %s failed\n", __func__, Uri)); return Status; @@ -150,12 +147,7 @@ RedfishResourceConsumeResource ( // Release resource // if (Private->Payload != NULL) { - RedfishFreeResponse ( - Response.StatusCode, - Response.HeaderCount, - Response.Headers, - Response.Payload - ); + RedfishHttpFreeResource (&Response); Private->Payload = NULL; } @@ -234,7 +226,8 @@ RedfishResourceUpdate ( return EFI_NOT_READY; } - Status = GetResourceByUri (Private->RedfishService, Uri, &Response); + ZeroMem (&Response, sizeof (Response)); + Status = RedfishHttpGetResource (Private->RedfishService, Uri, &Response, TRUE); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a, get resource from: %s failed\n", __func__, Uri)); return Status; @@ -256,12 +249,7 @@ RedfishResourceUpdate ( // Release resource // if (Private->Payload != NULL) { - RedfishFreeResponse ( - Response.StatusCode, - Response.HeaderCount, - Response.Headers, - Response.Payload - ); + RedfishHttpFreeResource (&Response); Private->Payload = NULL; } @@ -304,7 +292,8 @@ RedfishResourceCheck ( return EFI_NOT_READY; } - Status = GetResourceByUri (Private->RedfishService, Uri, &Response); + ZeroMem (&Response, sizeof (Response)); + Status = RedfishHttpGetResource (Private->RedfishService, Uri, &Response, TRUE); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a, get resource from: %s failed\n", __func__, Uri)); return Status; @@ -326,12 +315,7 @@ RedfishResourceCheck ( // Release resource // if (Private->Payload != NULL) { - RedfishFreeResponse ( - Response.StatusCode, - Response.HeaderCount, - Response.Headers, - Response.Payload - ); + RedfishHttpFreeResource (&Response); Private->Payload = NULL; } @@ -375,7 +359,8 @@ RedfishResourceIdentify ( return EFI_NOT_READY; } - Status = GetResourceByUri (Private->RedfishService, Uri, &Response); + ZeroMem (&Response, sizeof (Response)); + Status = RedfishHttpGetResource (Private->RedfishService, Uri, &Response, TRUE); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a, get resource from: %s failed\n", __func__, Uri)); return Status; @@ -397,12 +382,7 @@ RedfishResourceIdentify ( // Release resource // if (Private->Payload != NULL) { - RedfishFreeResponse ( - Response.StatusCode, - Response.HeaderCount, - Response.Headers, - Response.Payload - ); + RedfishHttpFreeResource (&Response); Private->Payload = NULL; } diff --git a/RedfishClientPkg/Features/ComputerSystem/v1_5_0/Dxe/ComputerSystemDxe.inf b/RedfishClientPkg/Features/ComputerSystem/v1_5_0/Dxe/ComputerSystemDxe.inf index 67412f5f3..2c8882995 100644 --- a/RedfishClientPkg/Features/ComputerSystem/v1_5_0/Dxe/ComputerSystemDxe.inf +++ b/RedfishClientPkg/Features/ComputerSystem/v1_5_0/Dxe/ComputerSystemDxe.inf @@ -1,6 +1,7 @@ ## @file # # (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP
+# Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. # # SPDX-License-Identifier: BSD-2-Clause-Patent # @@ -36,7 +37,7 @@ RedfishResourceIdentifyLib UefiLib UefiDriverEntryPoint - + RedfishHttpLib [Protocols] gEdkIIRedfishConfigHandlerProtocolGuid ## PRODUCED diff --git a/RedfishClientPkg/Features/ComputerSystemCollectionDxe/ComputerSystemCollectionDxe.c b/RedfishClientPkg/Features/ComputerSystemCollectionDxe/ComputerSystemCollectionDxe.c index 1e362d49c..e4fe6965a 100644 --- a/RedfishClientPkg/Features/ComputerSystemCollectionDxe/ComputerSystemCollectionDxe.c +++ b/RedfishClientPkg/Features/ComputerSystemCollectionDxe/ComputerSystemCollectionDxe.c @@ -247,16 +247,7 @@ ReleaseCollectionResource ( // Release resource // if (Private->RedResponse.Payload != NULL) { - RedfishFreeResponse ( - Private->RedResponse.StatusCode, - Private->RedResponse.HeaderCount, - Private->RedResponse.Headers, - Private->RedResponse.Payload - ); - Private->RedResponse.StatusCode = NULL; - Private->RedResponse.HeaderCount = 0; - Private->RedResponse.Headers = NULL; - Private->RedResponse.Payload = NULL; + RedfishHttpFreeResource (&Private->RedResponse); } if (Private->CollectionJson != NULL) { @@ -288,7 +279,8 @@ CollectionHandler ( // // Query collection from Redfish service. // - Status = GetResourceByUri (Private->RedfishService, Private->CollectionUri, &Private->RedResponse); + ZeroMem (&Private->RedResponse, sizeof (Private->RedResponse)); + Status = RedfishHttpGetResource (Private->RedfishService, Private->CollectionUri, &Private->RedResponse, TRUE); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a, unable to get resource from: %s :%r\n", __func__, Private->CollectionUri, Status)); goto ON_RELEASE; diff --git a/RedfishClientPkg/Features/ComputerSystemCollectionDxe/ComputerSystemCollectionDxe.inf b/RedfishClientPkg/Features/ComputerSystemCollectionDxe/ComputerSystemCollectionDxe.inf index 107d6c076..4d5e47ca9 100644 --- a/RedfishClientPkg/Features/ComputerSystemCollectionDxe/ComputerSystemCollectionDxe.inf +++ b/RedfishClientPkg/Features/ComputerSystemCollectionDxe/ComputerSystemCollectionDxe.inf @@ -3,6 +3,7 @@ # Redfish ComputerSystemCollection collection driver. # # (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP
+# Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. # # SPDX-License-Identifier: BSD-2-Clause-Patent # @@ -40,6 +41,7 @@ UefiBootServicesTableLib EdkIIRedfishResourceConfigLib RedfishVersionLib + RedfishHttpLib [Protocols] gEdkIIRedfishConfigHandlerProtocolGuid ## CONSUMED diff --git a/RedfishClientPkg/Features/Memory/V1_7_1/Common/MemoryCommon.c b/RedfishClientPkg/Features/Memory/V1_7_1/Common/MemoryCommon.c index b74340362..5e4aeeb21 100644 --- a/RedfishClientPkg/Features/Memory/V1_7_1/Common/MemoryCommon.c +++ b/RedfishClientPkg/Features/Memory/V1_7_1/Common/MemoryCommon.c @@ -2,6 +2,7 @@ Redfish feature driver implementation - common functions (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP
+ Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. SPDX-License-Identifier: BSD-2-Clause-Patent @@ -2152,17 +2153,21 @@ ProvisioningMemoryResource ( IN EFI_STRING ConfigureLang ) { - CHAR8 *Json; - EFI_STATUS Status; - EFI_STRING NewResourceLocation; - CHAR8 *EtagStr; - CHAR8 ResourceId[16]; + CHAR8 *Json; + EFI_STATUS Status; + EFI_STRING NewResourceLocation; + CHAR8 *EtagStr; + CHAR8 ResourceId[16]; + REDFISH_RESPONSE Response; if (IS_EMPTY_STRING (ConfigureLang) || (Private == NULL)) { return EFI_INVALID_PARAMETER; } - EtagStr = NULL; + EtagStr = NULL; + Json = NULL; + NewResourceLocation = NULL; + ZeroMem (&Response, sizeof (REDFISH_RESPONSE)); AsciiSPrint (ResourceId, sizeof (ResourceId), "%d", Index); Status = ProvisioningMemoryProperties ( @@ -2178,19 +2183,25 @@ ProvisioningMemoryResource ( return Status; } - Status = CreatePayloadToPostResource (Private->RedfishService, Private->Payload, Json, &NewResourceLocation, &EtagStr); + Status = RedfishHttpPostResource (Private->RedfishService, Private->Uri, Json, &Response); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a, post Memory resource for %s failed: %r\n", __func__, ConfigureLang, Status)); goto RELEASE_RESOURCE; } + Status = GetEtagAndLocation (&Response, &EtagStr, &NewResourceLocation); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, get ETag and location failed: %r\n", __func__, Status)); + goto RELEASE_RESOURCE; + } + ASSERT (NewResourceLocation != NULL); // // Keep location of new resource. // if (NewResourceLocation != NULL) { - RedfisSetRedfishUri (ConfigureLang, NewResourceLocation); + RedfishSetRedfishUri (ConfigureLang, NewResourceLocation); } // @@ -2211,6 +2222,8 @@ ProvisioningMemoryResource ( FreePool (Json); } + RedfishHttpFreeResource (&Response); + return Status; } @@ -2253,10 +2266,11 @@ ProvisioningMemoryExistResource ( IN REDFISH_RESOURCE_COMMON_PRIVATE *Private ) { - EFI_STATUS Status; - EFI_STRING ConfigureLang; - CHAR8 *EtagStr; - CHAR8 *Json; + EFI_STATUS Status; + EFI_STRING ConfigureLang; + CHAR8 *EtagStr; + CHAR8 *Json; + REDFISH_RESPONSE Response; if (Private == NULL) { return EFI_INVALID_PARAMETER; @@ -2265,6 +2279,7 @@ ProvisioningMemoryExistResource ( EtagStr = NULL; Json = NULL; ConfigureLang = NULL; + ZeroMem (&Response, sizeof (REDFISH_RESPONSE)); ConfigureLang = RedfishGetConfigLanguage (Private->Uri); if (ConfigureLang == NULL) { @@ -2291,13 +2306,19 @@ ProvisioningMemoryExistResource ( DEBUG ((REDFISH_DEBUG_TRACE, "%a, provisioning existing resource for %s\n", __func__, ConfigureLang)); // - // PUT back to instance + // PATCH back to instance // - Status = CreatePayloadToPatchResource (Private->RedfishService, Private->Payload, Json, &EtagStr); + Status = RedfishHttpPatchResource (Private->RedfishService, Private->Uri, Json, &Response); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a, patch resource for %s failed: %r\n", __func__, ConfigureLang, Status)); } + Status = GetEtagAndLocation (&Response, &EtagStr, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, get ETag failed: %r\n", __func__, Status)); + goto ON_RELEASE; + } + // // Handle Etag // @@ -2316,6 +2337,8 @@ ProvisioningMemoryExistResource ( FreePool (ConfigureLang); } + RedfishHttpFreeResource (&Response); + return Status; } @@ -2414,10 +2437,11 @@ RedfishUpdateResourceCommon ( IN CHAR8 *InputJson ) { - EFI_STATUS Status; - CHAR8 *Json; - EFI_STRING ConfigureLang; - CHAR8 *EtagStr; + EFI_STATUS Status; + CHAR8 *Json; + EFI_STRING ConfigureLang; + CHAR8 *EtagStr; + REDFISH_RESPONSE Response; if ((Private == NULL) || IS_EMPTY_STRING (InputJson)) { return EFI_INVALID_PARAMETER; @@ -2426,6 +2450,7 @@ RedfishUpdateResourceCommon ( EtagStr = NULL; Json = NULL; ConfigureLang = NULL; + ZeroMem (&Response, sizeof (REDFISH_RESPONSE)); ConfigureLang = RedfishGetConfigLanguage (Private->Uri); if (ConfigureLang == NULL) { @@ -2452,13 +2477,19 @@ RedfishUpdateResourceCommon ( DEBUG ((REDFISH_DEBUG_TRACE, "%a, update resource for %s\n", __func__, ConfigureLang)); // - // PUT back to instance + // PATCH back to instance // - Status = CreatePayloadToPatchResource (Private->RedfishService, Private->Payload, Json, &EtagStr); + Status = RedfishHttpPatchResource (Private->RedfishService, Private->Uri, Json, &Response); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a, patch resource for %s failed: %r\n", __func__, ConfigureLang, Status)); } + Status = GetEtagAndLocation (&Response, &EtagStr, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a, get ETag failed: %r\n", __func__, Status)); + goto ON_RELEASE; + } + // // Handle Etag // @@ -2477,6 +2508,8 @@ RedfishUpdateResourceCommon ( FreePool (ConfigureLang); } + RedfishHttpFreeResource (&Response); + return Status; } @@ -2537,7 +2570,7 @@ RedfishIdentifyResourceCommon ( // // Keep URI and ConfigLang mapping // - RedfisSetRedfishUri (ConfigLangList.List[0].ConfigureLang, Private->Uri); + RedfishSetRedfishUri (ConfigLangList.List[0].ConfigureLang, Private->Uri); // // Set the configuration language in the RESOURCE_INFORMATION_EXCHANGE. // This information is sent back to the parent resource (e.g. the collection driver). diff --git a/RedfishClientPkg/Features/Memory/V1_7_1/Dxe/MemoryDxe.c b/RedfishClientPkg/Features/Memory/V1_7_1/Dxe/MemoryDxe.c index f34f3266f..b09727092 100644 --- a/RedfishClientPkg/Features/Memory/V1_7_1/Dxe/MemoryDxe.c +++ b/RedfishClientPkg/Features/Memory/V1_7_1/Dxe/MemoryDxe.c @@ -50,7 +50,8 @@ RedfishResourceProvisioningResource ( return EFI_NOT_READY; } - Status = GetResourceByUri (Private->RedfishService, Uri, &Response); + ZeroMem (&Response, sizeof (Response)); + Status = RedfishHttpGetResource (Private->RedfishService, Uri, &Response, TRUE); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a, get resource from: %s failed\n", __func__, Uri)); return Status; @@ -66,12 +67,7 @@ RedfishResourceProvisioningResource ( // Release resource // if (Private->Payload != NULL) { - RedfishFreeResponse ( - Response.StatusCode, - Response.HeaderCount, - Response.Headers, - Response.Payload - ); + RedfishHttpFreeResource (&Response); Private->Payload = NULL; } @@ -110,7 +106,8 @@ RedfishResourceConsumeResource ( return EFI_NOT_READY; } - Status = GetResourceByUri (Private->RedfishService, Uri, &Response); + ZeroMem (&Response, sizeof (Response)); + Status = RedfishHttpGetResource (Private->RedfishService, Uri, &Response, TRUE); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a, get resource from: %s failed\n", __func__, Uri)); return Status; @@ -150,12 +147,7 @@ RedfishResourceConsumeResource ( // Release resource // if (Private->Payload != NULL) { - RedfishFreeResponse ( - Response.StatusCode, - Response.HeaderCount, - Response.Headers, - Response.Payload - ); + RedfishHttpFreeResource (&Response); Private->Payload = NULL; } @@ -234,7 +226,8 @@ RedfishResourceUpdate ( return EFI_NOT_READY; } - Status = GetResourceByUri (Private->RedfishService, Uri, &Response); + ZeroMem (&Response, sizeof (Response)); + Status = RedfishHttpGetResource (Private->RedfishService, Uri, &Response, TRUE); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a, get resource from: %s failed\n", __func__, Uri)); return Status; @@ -256,12 +249,7 @@ RedfishResourceUpdate ( // Release resource // if (Private->Payload != NULL) { - RedfishFreeResponse ( - Response.StatusCode, - Response.HeaderCount, - Response.Headers, - Response.Payload - ); + RedfishHttpFreeResource (&Response); Private->Payload = NULL; } @@ -304,7 +292,8 @@ RedfishResourceCheck ( return EFI_NOT_READY; } - Status = GetResourceByUri (Private->RedfishService, Uri, &Response); + ZeroMem (&Response, sizeof (Response)); + Status = RedfishHttpGetResource (Private->RedfishService, Uri, &Response, TRUE); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a, get resource from: %s failed\n", __func__, Uri)); return Status; @@ -326,12 +315,7 @@ RedfishResourceCheck ( // Release resource // if (Private->Payload != NULL) { - RedfishFreeResponse ( - Response.StatusCode, - Response.HeaderCount, - Response.Headers, - Response.Payload - ); + RedfishHttpFreeResource (&Response); Private->Payload = NULL; } @@ -375,7 +359,8 @@ RedfishResourceIdentify ( return EFI_NOT_READY; } - Status = GetResourceByUri (Private->RedfishService, Uri, &Response); + ZeroMem (&Response, sizeof (Response)); + Status = RedfishHttpGetResource (Private->RedfishService, Uri, &Response, TRUE); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a, get resource from: %s failed\n", __func__, Uri)); return Status; @@ -397,12 +382,7 @@ RedfishResourceIdentify ( // Release resource // if (Private->Payload != NULL) { - RedfishFreeResponse ( - Response.StatusCode, - Response.HeaderCount, - Response.Headers, - Response.Payload - ); + RedfishHttpFreeResource (&Response); Private->Payload = NULL; } diff --git a/RedfishClientPkg/Features/Memory/V1_7_1/Dxe/MemoryDxe.inf b/RedfishClientPkg/Features/Memory/V1_7_1/Dxe/MemoryDxe.inf index 594a87490..ab862f694 100644 --- a/RedfishClientPkg/Features/Memory/V1_7_1/Dxe/MemoryDxe.inf +++ b/RedfishClientPkg/Features/Memory/V1_7_1/Dxe/MemoryDxe.inf @@ -1,6 +1,7 @@ ## @file # # (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP
+# Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. # # SPDX-License-Identifier: BSD-2-Clause-Patent # @@ -36,7 +37,7 @@ RedfishResourceIdentifyLib UefiLib UefiDriverEntryPoint - + RedfishHttpLib [Protocols] gEdkIIRedfishConfigHandlerProtocolGuid ## PRODUCED diff --git a/RedfishClientPkg/Features/MemoryCollectionDxe/MemoryCollectionDxe.c b/RedfishClientPkg/Features/MemoryCollectionDxe/MemoryCollectionDxe.c index 1b755cde0..dce555af6 100644 --- a/RedfishClientPkg/Features/MemoryCollectionDxe/MemoryCollectionDxe.c +++ b/RedfishClientPkg/Features/MemoryCollectionDxe/MemoryCollectionDxe.c @@ -247,16 +247,7 @@ ReleaseCollectionResource ( // Release resource // if (Private->RedResponse.Payload != NULL) { - RedfishFreeResponse ( - Private->RedResponse.StatusCode, - Private->RedResponse.HeaderCount, - Private->RedResponse.Headers, - Private->RedResponse.Payload - ); - Private->RedResponse.StatusCode = NULL; - Private->RedResponse.HeaderCount = 0; - Private->RedResponse.Headers = NULL; - Private->RedResponse.Payload = NULL; + RedfishHttpFreeResource (&Private->RedResponse); } if (Private->CollectionJson != NULL) { @@ -288,7 +279,8 @@ CollectionHandler ( // // Query collection from Redfish service. // - Status = GetResourceByUri (Private->RedfishService, Private->CollectionUri, &Private->RedResponse); + ZeroMem (&Private->RedResponse, sizeof (Private->RedResponse)); + Status = RedfishHttpGetResource (Private->RedfishService, Private->CollectionUri, &Private->RedResponse, TRUE); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a, unable to get resource from: %s :%r\n", __func__, Private->CollectionUri, Status)); goto ON_RELEASE; diff --git a/RedfishClientPkg/Features/MemoryCollectionDxe/MemoryCollectionDxe.inf b/RedfishClientPkg/Features/MemoryCollectionDxe/MemoryCollectionDxe.inf index 05e05712e..099116783 100644 --- a/RedfishClientPkg/Features/MemoryCollectionDxe/MemoryCollectionDxe.inf +++ b/RedfishClientPkg/Features/MemoryCollectionDxe/MemoryCollectionDxe.inf @@ -3,6 +3,7 @@ # Redfish MemoryCollection collection driver. # # (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP
+# Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. # # SPDX-License-Identifier: BSD-2-Clause-Patent # @@ -40,6 +41,7 @@ UefiBootServicesTableLib EdkIIRedfishResourceConfigLib RedfishVersionLib + RedfishHttpLib [Protocols] gEdkIIRedfishConfigHandlerProtocolGuid ## CONSUMED diff --git a/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h b/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h index e2f728b26..4906a55ab 100644 --- a/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h +++ b/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h @@ -11,32 +11,13 @@ #ifndef REDFISH_FEATURE_UTILITY_LIB_H_ #define REDFISH_FEATURE_UTILITY_LIB_H_ -#include #include #include #include +#include #define REDFISH_ENABLE_SYSTEM_REBOOT() PcdSetBoolS(PcdRedfishSystemRebootRequired, TRUE) -/** - - Read redfish resource by given resource URI. - - @param[in] Service Redfish srvice instacne to make query. - @param[in] ResourceUri Target resource URI. - @param[out] Response HTTP response from redfish service. - - @retval EFI_SUCCESS Resrouce is returned successfully. - @retval Others Errors occur. - -**/ -EFI_STATUS -GetResourceByUri ( - IN REDFISH_SERVICE *Service, - IN EFI_STRING ResourceUri, - OUT REDFISH_RESPONSE *Response - ); - /** Check if this is the Redpath array. Usually the Redpath array represents @@ -47,7 +28,7 @@ GetResourceByUri ( @param[out] ArraySignatureClose String to the close of array signature. @retval EFI_SUCCESS Index is found. - @retval EFI_NOT_FOUND The non-array configure language string is retured. + @retval EFI_NOT_FOUND The non-array configure language string is returned. @retval EFI_INVALID_PARAMETER The format of input ConfigureLang is wrong. @retval Others Errors occur. @@ -100,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. @@ -118,10 +99,10 @@ GetNumberOfRedpathNodes ( @param[in] NodeString The node string to parse. @param[in] Index Index of the node. - @param[out] EndOfNodePtr Pointer to receive the poitner to + @param[out] EndOfNodePtr Pointer to receive the pointer to the last character of node string. - @retval EFI_STRING the begining of the node string. + @retval EFI_STRING the beginning of the node string. **/ EFI_STRING @@ -140,7 +121,7 @@ GetRedpathNodeByIndex ( @param[out] Index The array index number. @retval EFI_SUCCESS Index is found. - @retval EFI_NOT_FOUND The non-array configure language string is retured. + @retval EFI_NOT_FOUND The non-array configure language string is returned. @retval EFI_INVALID_PARAMETER The format of input ConfigureLang is wrong. @retval Others Errors occur. @@ -188,7 +169,7 @@ DestroyConfiglanguageList ( @param[in] DestConfigLang Pointer to the node's configure language string. The memory pointed by ConfigLang must be allocated - through memory allocation interface. Becasue we will replace + through memory allocation interface. Because we will replace the pointer in this function. @param[in] MaxtLengthConfigLang The maximum length of ConfigLang. @param[in] ConfigLangInstance Pointer to Collection member instance. @@ -244,7 +225,7 @@ ApplyFeatureSettingsStringType ( /** - Apply property value to UEFI HII database in numric type. + Apply property value to UEFI HII database in numeric type. @param[in] Schema Property schema. @param[in] Version Property schema version. @@ -356,7 +337,7 @@ ApplyFeatureSettingsNumericArrayType ( @param[in] Schema Property schema. @param[in] Version Property schema version. @param[in] ConfigureLang Configure language refers to this property. - @param[in] ArrayHead Head of Redfich CS boolean array value. + @param[in] ArrayHead Head of Redfish CS boolean array value. @retval EFI_SUCCESS New value is applied successfully. @retval Others Errors occur. @@ -370,50 +351,6 @@ ApplyFeatureSettingsBooleanArrayType ( IN RedfishCS_bool_Array *ArrayHead ); -/** - - Create HTTP payload and send them to redfish service with POST method. - - @param[in] Service Redfish service. - @param[in] TargetPayload Target payload - @param[in] Json Data in JSON format. - @param[out] Location Returned location string from Redfish service. - @param[out] Etag Returned ETAG string from Redfish service. - - @retval EFI_SUCCESS Data is sent to redfish service successfully. - @retval Others Errors occur. - -**/ -EFI_STATUS -CreatePayloadToPostResource ( - IN REDFISH_SERVICE *Service, - IN REDFISH_PAYLOAD *TargetPayload, - IN CHAR8 *Json, - OUT EFI_STRING *Location, - OUT CHAR8 **Etag - ); - -/** - - Create HTTP payload and send them to redfish service with PATCH method. - - @param[in] Service Redfish service. - @param[in] TargetPayload Target payload - @param[in] Json Data in JSON format. - @param[out] Etag Returned ETAG string from Redfish service. - - @retval EFI_SUCCESS Data is sent to redfish service successfully. - @retval Others Errors occur. - -**/ -EFI_STATUS -CreatePayloadToPatchResource ( - IN REDFISH_SERVICE *Service, - IN REDFISH_PAYLOAD *TargetPayload, - IN CHAR8 *Json, - OUT CHAR8 **Etag - ); - /** Save Redfish URI in database for further use. @@ -421,19 +358,19 @@ CreatePayloadToPatchResource ( @param[in] ConfigLang ConfigLang to save @param[in] Uri Redfish Uri to save - @retval EFI_INVALID_PARAMETR SystemId is NULL or EMPTY + @retval EFI_INVALID_PARAMETER SystemId is NULL or EMPTY @retval EFI_SUCCESS Redfish uri is saved **/ EFI_STATUS -RedfisSetRedfishUri ( +RedfishSetRedfishUri ( IN EFI_STRING ConfigLang, IN EFI_STRING Uri ); /** - Get the property name by given Configure Langauge. + Get the property name by given Configure Language. @param[in] ResourceUri URI of root of resource. @param[in] ConfigureLang Configure Language string. @@ -576,7 +513,7 @@ GetOdataId ( /** - Return config language from given URI and prperty name. It's call responsibility to release returned buffer. + Return config language from given URI and property name. It's call responsibility to release returned buffer. @param[in] Uri The URI to match @param[in] PropertyName The property name of resource. This is optional. @@ -790,7 +727,7 @@ MatchPropertyWithJsonContext ( /** - Create string array and append to arry node in Redfish JSON convert format. + Create string array and append to array node in Redfish JSON convert format. @param[in,out] Head The head of string array. @param[in] StringArray Input string array. @@ -809,7 +746,7 @@ AddRedfishCharArray ( /** - Create numeric array and append to arry node in Redfish JSON convert format. + Create numeric array and append to array node in Redfish JSON convert format. @param[in,out] Head The head of string array. @param[in] NumericArray Input numeric array. @@ -828,7 +765,7 @@ AddRedfishNumericArray ( /** - Create boolean array and append to arry node in Redfish JSON convert format. + Create boolean array and append to array node in Redfish JSON convert format. @param[in,out] Head The head of string array. @param[in] BooleanArray Input boolean array. @@ -871,7 +808,7 @@ CompareRedfishStringArrayValues ( Check and see if value in Redfish numeric array are all the same as the one from HII configuration. - @param[in] Head The head of Redfish CS numeraic array. + @param[in] Head The head of Redfish CS numeric array. @param[in] NumericArray Input numeric array. @param[in] ArraySize The size of NumericArray. @@ -914,9 +851,9 @@ CompareRedfishBooleanArrayValues ( This is just a simple check. @param[in] RedfishVagueKeyValuePtr The vague key value sets on Redfish service. - @param[in] RedfishVagueKeyValueNumber The numebr of vague key value sets + @param[in] RedfishVagueKeyValueNumber The number of vague key value sets @param[in] ConfigVagueKeyValuePtr The vague configuration on platform. - @param[in] ConfigVagueKeyValueNumber The numebr of vague key value sets + @param[in] ConfigVagueKeyValueNumber The number of vague key value sets @retval TRUE All values are the same. FALSE There is some difference. diff --git a/RedfishClientPkg/Include/Library/RedfishHttpLib.h b/RedfishClientPkg/Include/Library/RedfishHttpLib.h new file mode 100644 index 000000000..ab7cf0a80 --- /dev/null +++ b/RedfishClientPkg/Include/Library/RedfishHttpLib.h @@ -0,0 +1,150 @@ +/** @file + This file defines the Redfish HTTP library interface. + + Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef REDFISH_HTTP_LIB_H_ +#define REDFISH_HTTP_LIB_H_ + +#include + +/** + This function free resources in Response. Response is no longer available + after this function returns successfully. + + @param[in] Response HTTP response to be released. + + @retval EFI_SUCCESS Resrouce is released successfully. + @retval Others Errors occur. + +**/ +EFI_STATUS +RedfishHttpFreeResource ( + IN REDFISH_RESPONSE *Response + ); + +/** + Get redfish resource from given resource URI with cache mechanism + supported. It's caller's responsibility to Response by calling + RedfishHttpFreeResource (). + + @param[in] Service Redfish service instance to make query. + @param[in] Uri Target resource URI. + @param[out] Response HTTP response from redfish service. + @param[in] UseCache If it is TRUE, this function will search for + cache first. If it is FALSE, this function + will query Redfish URI directly. + + @retval EFI_SUCCESS Resrouce is returned successfully. + @retval Others Errors occur. + +**/ +EFI_STATUS +RedfishHttpGetResource ( + IN REDFISH_SERVICE Service, + IN EFI_STRING Uri, + OUT REDFISH_RESPONSE *Response, + IN BOOLEAN UseCache + ); + +/** + This function expire the cached response of given URI. + + @param[in] Uri Target response of URI. + + @retval EFI_SUCCESS Target response is expired successfully. + @retval Others Errors occur. + +**/ +EFI_STATUS +RedfishHttpExpireResponse ( + IN EFI_STRING Uri + ); + +/** + Perform HTTP PATCH to send redfish resource to given resource URI. + It's caller's responsibility to free Response by calling FreeResponse (). + + @param[in] Service Redfish service instance to make query. + @param[in] Uri Target resource URI. + @param[in] Content Data to patch. + @param[out] Response HTTP response from redfish service. + + @retval EFI_SUCCESS Resrouce is returned successfully. + @retval Others Errors occur. + +**/ +EFI_STATUS +RedfishHttpPatchResource ( + IN REDFISH_SERVICE Service, + IN EFI_STRING Uri, + IN CHAR8 *Content, + OUT REDFISH_RESPONSE *Response + ); + +/** + Perform HTTP PUT to send redfish resource to given resource URI. + It's caller's responsibility to free Response by calling FreeResponse (). + + @param[in] Service Redfish service instance to make query. + @param[in] Uri Target resource URI. + @param[in] Content Data to put. + @param[out] Response HTTP response from redfish service. + + @retval EFI_SUCCESS Resrouce is returned successfully. + @retval Others Errors occur. + +**/ +EFI_STATUS +RedfishHttpPutResource ( + IN REDFISH_SERVICE Service, + IN EFI_STRING Uri, + IN CHAR8 *Content, + OUT REDFISH_RESPONSE *Response + ); + +/** + Perform HTTP POST to send redfish resource to given resource URI. + It's caller's responsibility to free Response by calling FreeResponse (). + + @param[in] Service Redfish service instance to make query. + @param[in] Uri Target resource URI. + @param[in] Content Data to post. + @param[out] Response HTTP response from redfish service. + + @retval EFI_SUCCESS Resrouce is returned successfully. + @retval Others Errors occur. + +**/ +EFI_STATUS +RedfishHttpPostResource ( + IN REDFISH_SERVICE Service, + IN EFI_STRING Uri, + IN CHAR8 *Content, + OUT REDFISH_RESPONSE *Response + ); + +/** + Perform HTTP DELETE to delete redfish resource on given resource URI. + It's caller's responsibility to free Response by calling FreeResponse (). + + @param[in] Service Redfish service instance to make query. + @param[in] Uri Target resource URI. + @param[out] Response HTTP response from redfish service. + + @retval EFI_SUCCESS Resrouce is returned successfully. + @retval Others Errors occur. + +**/ +EFI_STATUS +RedfishHttpDeleteResource ( + IN REDFISH_SERVICE Service, + IN EFI_STRING Uri, + OUT REDFISH_RESPONSE *Response + ); + +#endif diff --git a/RedfishClientPkg/Include/Library/RedfishVersionLib.h b/RedfishClientPkg/Include/Library/RedfishVersionLib.h index 319f22bd3..020d14d6f 100644 --- a/RedfishClientPkg/Include/Library/RedfishVersionLib.h +++ b/RedfishClientPkg/Include/Library/RedfishVersionLib.h @@ -2,6 +2,7 @@ This file defines the Redfish version Library interface. (C) Copyright 2022 Hewlett Packard Enterprise Development LP
+ Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. SPDX-License-Identifier: BSD-2-Clause-Patent @@ -10,9 +11,11 @@ #ifndef REDFISH_VERSION_LIB_H_ #define REDFISH_VERSION_LIB_H_ +#include + /** Query HTTP request to BMC with given redfish service and return redfish - version information. If there is troulbe to get Redfish version on BMC, + version information. If there is trouble to get Redfish version on BMC, The value of PcdDefaultRedfishVersion is returned. It's call responsibility to release returned buffer. diff --git a/RedfishClientPkg/Include/Protocol/EdkIIRedfishHttpProtocol.h b/RedfishClientPkg/Include/Protocol/EdkIIRedfishHttpProtocol.h new file mode 100644 index 000000000..910c115dc --- /dev/null +++ b/RedfishClientPkg/Include/Protocol/EdkIIRedfishHttpProtocol.h @@ -0,0 +1,192 @@ +/** @file + This file defines the EDKII_REDFISH_HTTP_PROTOCOL interface. + + Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef EDKII_REDFISH_HTTP_PROTOCOL_H_ +#define EDKII_REDFISH_HTTP_PROTOCOL_H_ + +#include +#include + +typedef struct _EDKII_REDFISH_HTTP_PROTOCOL EDKII_REDFISH_HTTP_PROTOCOL; + +/** + Perform HTTP GET to Get redfish resource from given resource URI with + cache mechanism supported. It's caller's responsibility to free Response + by calling FreeResponse (). + + @param[in] This Pointer to EDKII_REDFISH_HTTP_PROTOCOL instance. + @param[in] Service Redfish service instance to make query. + @param[in] Uri Target resource URI. + @param[out] Response HTTP response from redfish service. + @param[in] UseCache If it is TRUE, this function will search for + cache first. If it is FALSE, this function + will query Redfish URI directly. + + @retval EFI_SUCCESS Resrouce is returned successfully. + @retval Others Errors occur. + +**/ +typedef +EFI_STATUS +(EFIAPI *REDFISH_HTTP_GET_RESOURCE)( + IN EDKII_REDFISH_HTTP_PROTOCOL *This, + IN REDFISH_SERVICE Service, + IN EFI_STRING Uri, + OUT REDFISH_RESPONSE *Response, + IN BOOLEAN UseCache + ); + +/** + This function free resources in Response. Response is no longer available + after this function returns successfully. + + @param[in] This Pointer to EDKII_REDFISH_HTTP_PROTOCOL instance. + @param[in] Response HTTP response to be released. + + @retval EFI_SUCCESS Resrouce is released successfully. + @retval Others Errors occur. + +**/ +typedef +EFI_STATUS +(EFIAPI *REDFISH_HTTP_FREE_RESPONSE)( + IN EDKII_REDFISH_HTTP_PROTOCOL *This, + IN REDFISH_RESPONSE *Response + ); + +/** + This function expire the cached response of given URI. + + @param[in] This Pointer to EDKII_REDFISH_HTTP_PROTOCOL instance. + @param[in] Uri Target response of URI. + + @retval EFI_SUCCESS Target response is expired successfully. + @retval Others Errors occur. + +**/ +typedef +EFI_STATUS +(EFIAPI *REDFISH_HTTP_EXPIRE_RESPONSE)( + IN EDKII_REDFISH_HTTP_PROTOCOL *This, + IN EFI_STRING Uri + ); + +/** + Perform HTTP PATCH to send redfish resource to given resource URI. + It's caller's responsibility to free Response by calling FreeResponse (). + + @param[in] This Pointer to EDKII_REDFISH_HTTP_PROTOCOL instance. + @param[in] Service Redfish service instance to make query. + @param[in] Uri Target resource URI. + @param[in] Content Data to patch. + @param[out] Response HTTP response from redfish service. + + @retval EFI_SUCCESS Resrouce is returned successfully. + @retval Others Errors occur. + +**/ +typedef +EFI_STATUS +(EFIAPI *REDFISH_HTTP_PATCH_RESOURCE)( + IN EDKII_REDFISH_HTTP_PROTOCOL *This, + IN REDFISH_SERVICE Service, + IN EFI_STRING Uri, + IN CHAR8 *Content, + OUT REDFISH_RESPONSE *Response + ); + +/** + Perform HTTP PUT to send redfish resource to given resource URI. + It's caller's responsibility to free Response by calling FreeResponse (). + + @param[in] This Pointer to EDKII_REDFISH_HTTP_PROTOCOL instance. + @param[in] Service Redfish service instance to make query. + @param[in] Uri Target resource URI. + @param[in] Content Data to put. + @param[out] Response HTTP response from redfish service. + + @retval EFI_SUCCESS Resrouce is returned successfully. + @retval Others Errors occur. + +**/ +typedef +EFI_STATUS +(EFIAPI *REDFISH_HTTP_PUT_RESOURCE)( + IN EDKII_REDFISH_HTTP_PROTOCOL *This, + IN REDFISH_SERVICE Service, + IN EFI_STRING Uri, + IN CHAR8 *Content, + OUT REDFISH_RESPONSE *Response + ); + +/** + Perform HTTP POST to send redfish resource to given resource URI. + It's caller's responsibility to free Response by calling FreeResponse (). + + @param[in] This Pointer to EDKII_REDFISH_HTTP_PROTOCOL instance. + @param[in] Service Redfish service instance to make query. + @param[in] Uri Target resource URI. + @param[in] Content Data to post. + @param[out] Response HTTP response from redfish service. + + @retval EFI_SUCCESS Resrouce is returned successfully. + @retval Others Errors occur. + +**/ +typedef +EFI_STATUS +(EFIAPI *REDFISH_HTTP_POST_RESOURCE)( + IN EDKII_REDFISH_HTTP_PROTOCOL *This, + IN REDFISH_SERVICE Service, + IN EFI_STRING Uri, + IN CHAR8 *Content, + OUT REDFISH_RESPONSE *Response + ); + +/** + Perform HTTP DELETE to delete redfish resource on given resource URI. + It's caller's responsibility to free Response by calling FreeResponse (). + + @param[in] This Pointer to EDKII_REDFISH_HTTP_PROTOCOL instance. + @param[in] Service Redfish service instance to make query. + @param[in] Uri Target resource URI. + @param[out] Response HTTP response from redfish service. + + @retval EFI_SUCCESS Resrouce is returned successfully. + @retval Others Errors occur. + +**/ +typedef +EFI_STATUS +(EFIAPI *REDFISH_HTTP_DELETE_RESOURCE)( + IN EDKII_REDFISH_HTTP_PROTOCOL *This, + IN REDFISH_SERVICE Service, + IN EFI_STRING Uri, + OUT REDFISH_RESPONSE *Response + ); + +/// +/// Definition of _EDKII_REDFISH_HTTP_PROTOCOL. +/// +struct _EDKII_REDFISH_HTTP_PROTOCOL { + UINT32 Version; + REDFISH_HTTP_GET_RESOURCE GetResource; + REDFISH_HTTP_PATCH_RESOURCE PatchResource; + REDFISH_HTTP_PUT_RESOURCE PutResource; + REDFISH_HTTP_POST_RESOURCE PostResource; + REDFISH_HTTP_DELETE_RESOURCE DeleteResource; + REDFISH_HTTP_FREE_RESPONSE FreeResponse; + REDFISH_HTTP_EXPIRE_RESPONSE ExpireResponse; +}; + +#define EDKII_REDFISH_HTTP_PROTOCOL_REVISION 0x00001000 + +extern EFI_GUID gEdkIIRedfishHttpProtocolGuid; + +#endif diff --git a/RedfishClientPkg/Include/RedfishCollectionCommon.h b/RedfishClientPkg/Include/RedfishCollectionCommon.h index 59cc3607f..f7730aef0 100644 --- a/RedfishClientPkg/Include/RedfishCollectionCommon.h +++ b/RedfishClientPkg/Include/RedfishCollectionCommon.h @@ -2,6 +2,7 @@ Redfish feature driver collection common header file. (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP
+ Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. SPDX-License-Identifier: BSD-2-Clause-Patent @@ -26,6 +27,7 @@ #include #include #include +#include // // Protocols diff --git a/RedfishClientPkg/Include/RedfishResourceCommon.h b/RedfishClientPkg/Include/RedfishResourceCommon.h index b006755d6..6c20aa072 100644 --- a/RedfishClientPkg/Include/RedfishResourceCommon.h +++ b/RedfishClientPkg/Include/RedfishResourceCommon.h @@ -32,6 +32,7 @@ #include #include #include +#include // // Protocols diff --git a/RedfishClientPkg/Library/EdkIIRedfishResourceConfigLib/EdkIIRedfishResourceConfigLib.c b/RedfishClientPkg/Library/EdkIIRedfishResourceConfigLib/EdkIIRedfishResourceConfigLib.c index ce86ce701..d2560e925 100644 --- a/RedfishClientPkg/Library/EdkIIRedfishResourceConfigLib/EdkIIRedfishResourceConfigLib.c +++ b/RedfishClientPkg/Library/EdkIIRedfishResourceConfigLib/EdkIIRedfishResourceConfigLib.c @@ -16,6 +16,7 @@ #include #include #include +#include EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL *mRedfishResourceConfigProtocol = NULL; EFI_HANDLE mCachedHandle; @@ -56,7 +57,8 @@ GetRedfishSchemaInfo ( return EFI_INVALID_PARAMETER; } - Status = GetResourceByUri (RedfishService, Uri, &Response); + ZeroMem (&Response, sizeof (Response)); + Status = RedfishHttpGetResource (RedfishService, Uri, &Response, TRUE); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a, failed to get resource from %s: %r", __func__, Uri, Status)); return Status; @@ -90,6 +92,10 @@ GetRedfishSchemaInfo ( // // Release resource. // + if (Response.Payload != NULL) { + RedfishHttpFreeResource (&Response); + } + JsonStructProtocol->DestoryStructure (JsonStructProtocol, Header); FreePool (JsonText); RedfishFreeResponse (Response.StatusCode, Response.HeaderCount, Response.Headers, Response.Payload); diff --git a/RedfishClientPkg/Library/EdkIIRedfishResourceConfigLib/EdkIIRedfishResourceConfigLib.inf b/RedfishClientPkg/Library/EdkIIRedfishResourceConfigLib/EdkIIRedfishResourceConfigLib.inf index 0da3423d2..f526dc619 100644 --- a/RedfishClientPkg/Library/EdkIIRedfishResourceConfigLib/EdkIIRedfishResourceConfigLib.inf +++ b/RedfishClientPkg/Library/EdkIIRedfishResourceConfigLib/EdkIIRedfishResourceConfigLib.inf @@ -38,6 +38,7 @@ MemoryAllocationLib RedfishFeatureUtilityLib RedfishPlatformConfigLib + RedfishHttpLib [Protocols] gEdkIIRedfishResourceConfigProtocolGuid ## CONSUMES ## diff --git a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.c b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.c index 13e29902d..d6ebc7fdf 100644 --- a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.c +++ b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.c @@ -1040,66 +1040,6 @@ ApplyFeatureSettingsBooleanArrayType ( return Status; } -/** - - Read redfish resource by given resource URI. - - @param[in] Service Redfish service instance to make query. - @param[in] ResourceUri Target resource URI. - @param[out] Response HTTP response from redfish service. - - @retval EFI_SUCCESS Resrouce is returned successfully. - @retval Others Errors occur. - -**/ -EFI_STATUS -GetResourceByUri ( - IN REDFISH_SERVICE *Service, - IN EFI_STRING ResourceUri, - OUT REDFISH_RESPONSE *Response - ) -{ - EFI_STATUS Status; - CHAR8 *AsciiResourceUri; - - if ((Service == NULL) || (Response == NULL) || IS_EMPTY_STRING (ResourceUri)) { - return EFI_INVALID_PARAMETER; - } - - AsciiResourceUri = StrUnicodeToAscii (ResourceUri); - if (AsciiResourceUri == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - // - // Get resource from redfish service. - // - Status = RedfishGetByUri ( - Service, - AsciiResourceUri, - Response - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a: RedfishGetByUri to %a failed: %r\n", __func__, AsciiResourceUri, Status)); - if (Response->Payload != NULL) { - RedfishDumpPayload (Response->Payload); - RedfishFreeResponse ( - NULL, - 0, - NULL, - Response->Payload - ); - Response->Payload = NULL; - } - } - - if (AsciiResourceUri != NULL) { - FreePool (AsciiResourceUri); - } - - return Status; -} - /** Check if this is the Redpath array. Usually the Redpath array represents @@ -1773,161 +1713,6 @@ GetEtagAndLocation ( return Status; } -/** - - Create HTTP payload and send them to redfish service with PATCH method. - - @param[in] Service Redfish service. - @param[in] TargetPayload Target payload - @param[in] Json Data in JSON format. - @param[out] Etag Returned ETAG string from Redfish service. - - @retval EFI_SUCCESS Data is sent to redfish service successfully. - @retval Others Errors occur. - -**/ -EFI_STATUS -CreatePayloadToPatchResource ( - IN REDFISH_SERVICE *Service, - IN REDFISH_PAYLOAD *TargetPayload, - IN CHAR8 *Json, - OUT CHAR8 **Etag - ) -{ - REDFISH_PAYLOAD Payload; - EDKII_JSON_VALUE ResourceJsonValue; - REDFISH_RESPONSE PostResponse; - EFI_STATUS Status; - - if ((Service == NULL) || (TargetPayload == NULL) || IS_EMPTY_STRING (Json) || (Etag == NULL)) { - return EFI_INVALID_PARAMETER; - } - - ResourceJsonValue = JsonLoadString (Json, 0, NULL); - Payload = RedfishCreatePayload (ResourceJsonValue, Service); - if (Payload == NULL) { - DEBUG ((DEBUG_ERROR, "%a:%d Failed to create JSON payload from JSON value!\n", __func__, __LINE__)); - Status = EFI_DEVICE_ERROR; - goto EXIT_FREE_JSON_VALUE; - } - - ZeroMem (&PostResponse, sizeof (REDFISH_RESPONSE)); - Status = RedfishPatchToPayload (TargetPayload, Payload, &PostResponse); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a:%d Failed to PATCH payload to Redfish service.\n", __func__, __LINE__)); - - DEBUG_CODE_BEGIN (); - DEBUG ((DEBUG_ERROR, "%a: Request:\n", __func__)); - DumpRedfishPayload (DEBUG_ERROR, Payload); - DEBUG ((DEBUG_ERROR, "%a: Response:\n", __func__)); - DumpRedfishResponse (__func__, DEBUG_ERROR, &PostResponse); - DEBUG_CODE_END (); - goto EXIT_FREE_JSON_VALUE; - } - - // - // Find ETag - // - Status = GetEtagAndLocation (&PostResponse, Etag, NULL); - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - } - - RedfishFreeResponse ( - PostResponse.StatusCode, - PostResponse.HeaderCount, - PostResponse.Headers, - PostResponse.Payload - ); - -EXIT_FREE_JSON_VALUE: - if (Payload != NULL) { - RedfishCleanupPayload (Payload); - } - - JsonValueFree (ResourceJsonValue); - - return Status; -} - -/** - - Create HTTP payload and send them to redfish service with POST method. - - @param[in] Service Redfish service. - @param[in] TargetPayload Target payload - @param[in] Json Data in JSON format. - @param[out] Location Returned location string from Redfish service. - @param[out] Etag Returned ETAG string from Redfish service. - - @retval EFI_SUCCESS Data is sent to redfish service successfully. - @retval Others Errors occur. - -**/ -EFI_STATUS -CreatePayloadToPostResource ( - IN REDFISH_SERVICE *Service, - IN REDFISH_PAYLOAD *TargetPayload, - IN CHAR8 *Json, - OUT EFI_STRING *Location, - OUT CHAR8 **Etag - ) -{ - REDFISH_PAYLOAD Payload; - EDKII_JSON_VALUE ResourceJsonValue; - REDFISH_RESPONSE PostResponse; - EFI_STATUS Status; - - if ((Service == NULL) || (TargetPayload == NULL) || IS_EMPTY_STRING (Json) || (Location == NULL) || (Etag == NULL)) { - return EFI_INVALID_PARAMETER; - } - - ResourceJsonValue = JsonLoadString (Json, 0, NULL); - Payload = RedfishCreatePayload (ResourceJsonValue, Service); - if (Payload == NULL) { - DEBUG ((DEBUG_ERROR, "%a:%d Failed to create JSON payload from JSON value!\n", __func__, __LINE__)); - Status = EFI_DEVICE_ERROR; - goto EXIT_FREE_JSON_VALUE; - } - - ZeroMem (&PostResponse, sizeof (REDFISH_RESPONSE)); - Status = RedfishPostToPayload (TargetPayload, Payload, &PostResponse); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a:%d Failed to POST payload to Redfish service.\n", __func__, __LINE__)); - - DEBUG_CODE_BEGIN (); - DEBUG ((DEBUG_ERROR, "%a: Request:\n", __func__)); - DumpRedfishPayload (DEBUG_ERROR, Payload); - DEBUG ((DEBUG_ERROR, "%a: Response:\n", __func__)); - DumpRedfishResponse (__func__, DEBUG_ERROR, &PostResponse); - DEBUG_CODE_END (); - - goto EXIT_FREE_JSON_VALUE; - } - - // - // per Redfish spec. the URL of new resource will be returned in "Location" header. - // - Status = GetEtagAndLocation (&PostResponse, Etag, Location); - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - } - - RedfishFreeResponse ( - PostResponse.StatusCode, - PostResponse.HeaderCount, - PostResponse.Headers, - PostResponse.Payload - ); - - RedfishCleanupPayload (Payload); - -EXIT_FREE_JSON_VALUE: - JsonValueFree (ResourceJsonValue); - - return Status; -} - /** Return redfish URI by given config language. It's call responsibility to release returned buffer. @@ -2191,7 +1976,7 @@ GetConfigureLang ( **/ EFI_STATUS -RedfisSetRedfishUri ( +RedfishSetRedfishUri ( IN EFI_STRING ConfigLang, IN EFI_STRING Uri ) diff --git a/RedfishClientPkg/Library/RedfishHttpLib/RedfishHttpLib.c b/RedfishClientPkg/Library/RedfishHttpLib/RedfishHttpLib.c new file mode 100644 index 000000000..433e85741 --- /dev/null +++ b/RedfishClientPkg/Library/RedfishHttpLib/RedfishHttpLib.c @@ -0,0 +1,299 @@ +/** @file + Redfish HTTP cache library helps Redfish application to get Redfish resource + from BMC with cache mechanism enabled. + + Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include + +EDKII_REDFISH_HTTP_PROTOCOL *mRedfishHttpProtocol = NULL; + +/** + This function free resources in Response. Response is no longer available + after this function returns successfully. + + @param[in] Response HTTP response to be released. + + @retval EFI_SUCCESS Resrouce is released successfully. + @retval Others Errors occur. + +**/ +EFI_STATUS +RedfishHttpFreeResource ( + IN REDFISH_RESPONSE *Response + ) +{ + if (mRedfishHttpProtocol == NULL) { + return EFI_NOT_READY; + } + + return mRedfishHttpProtocol->FreeResponse ( + mRedfishHttpProtocol, + Response + ); +} + +/** + Get redfish resource from given resource URI with cache mechanism + supported. It's caller's responsibility to Response by calling + RedfishHttpFreeResource (). + + @param[in] Service Redfish service instance to make query. + @param[in] Uri Target resource URI. + @param[out] Response HTTP response from redfish service. + @param[in] UseCache If it is TRUE, this function will search for + cache first. If it is FALSE, this function + will query Redfish URI directly. + + @retval EFI_SUCCESS Resrouce is returned successfully. + @retval Others Errors occur. + +**/ +EFI_STATUS +RedfishHttpGetResource ( + IN REDFISH_SERVICE Service, + IN EFI_STRING Uri, + OUT REDFISH_RESPONSE *Response, + IN BOOLEAN UseCache + ) +{ + if (mRedfishHttpProtocol == NULL) { + return EFI_NOT_READY; + } + + return mRedfishHttpProtocol->GetResource ( + mRedfishHttpProtocol, + Service, + Uri, + Response, + UseCache + ); +} + +/** + This function expire the cached response of given URI. + + @param[in] Uri Target response of URI. + + @retval EFI_SUCCESS Target response is expired successfully. + @retval Others Errors occur. + +**/ +EFI_STATUS +RedfishHttpExpireResponse ( + IN EFI_STRING Uri + ) +{ + if (mRedfishHttpProtocol == NULL) { + return EFI_NOT_READY; + } + + return mRedfishHttpProtocol->ExpireResponse ( + mRedfishHttpProtocol, + Uri + ); +} + +/** + Perform HTTP PATCH to send redfish resource to given resource URI. + It's caller's responsibility to free Response by calling FreeResponse (). + + @param[in] Service Redfish service instance to make query. + @param[in] Uri Target resource URI. + @param[in] Content Data to patch. + @param[out] Response HTTP response from redfish service. + + @retval EFI_SUCCESS Resrouce is returned successfully. + @retval Others Errors occur. + +**/ +EFI_STATUS +RedfishHttpPatchResource ( + IN REDFISH_SERVICE Service, + IN EFI_STRING Uri, + IN CHAR8 *Content, + OUT REDFISH_RESPONSE *Response + ) +{ + if (mRedfishHttpProtocol == NULL) { + return EFI_NOT_READY; + } + + return mRedfishHttpProtocol->PatchResource ( + mRedfishHttpProtocol, + Service, + Uri, + Content, + Response + ); +} + +/** + Perform HTTP PUT to send redfish resource to given resource URI. + It's caller's responsibility to free Response by calling FreeResponse (). + + @param[in] Service Redfish service instance to make query. + @param[in] Uri Target resource URI. + @param[in] Content Data to put. + @param[out] Response HTTP response from redfish service. + + @retval EFI_SUCCESS Resrouce is returned successfully. + @retval Others Errors occur. + +**/ +EFI_STATUS +RedfishHttpPutResource ( + IN REDFISH_SERVICE Service, + IN EFI_STRING Uri, + IN CHAR8 *Content, + OUT REDFISH_RESPONSE *Response + ) +{ + if (mRedfishHttpProtocol == NULL) { + return EFI_NOT_READY; + } + + return mRedfishHttpProtocol->PutResource ( + mRedfishHttpProtocol, + Service, + Uri, + Content, + Response + ); +} + +/** + Perform HTTP POST to send redfish resource to given resource URI. + It's caller's responsibility to free Response by calling FreeResponse (). + + @param[in] Service Redfish service instance to make query. + @param[in] Uri Target resource URI. + @param[in] Content Data to post. + @param[out] Response HTTP response from redfish service. + + @retval EFI_SUCCESS Resrouce is returned successfully. + @retval Others Errors occur. + +**/ +EFI_STATUS +RedfishHttpPostResource ( + IN REDFISH_SERVICE Service, + IN EFI_STRING Uri, + IN CHAR8 *Content, + OUT REDFISH_RESPONSE *Response + ) +{ + if (mRedfishHttpProtocol == NULL) { + return EFI_NOT_READY; + } + + return mRedfishHttpProtocol->PostResource ( + mRedfishHttpProtocol, + Service, + Uri, + Content, + Response + ); +} + +/** + Perform HTTP DELETE to delete redfish resource on given resource URI. + It's caller's responsibility to free Response by calling FreeResponse (). + + @param[in] Service Redfish service instance to make query. + @param[in] Uri Target resource URI. + @param[out] Response HTTP response from redfish service. + + @retval EFI_SUCCESS Resrouce is returned successfully. + @retval Others Errors occur. + +**/ +EFI_STATUS +RedfishHttpDeleteResource ( + IN REDFISH_SERVICE Service, + IN EFI_STRING Uri, + OUT REDFISH_RESPONSE *Response + ) +{ + if (mRedfishHttpProtocol == NULL) { + return EFI_NOT_READY; + } + + return mRedfishHttpProtocol->DeleteResource ( + mRedfishHttpProtocol, + Service, + Uri, + Response + ); +} + +/** + Callback function when gEdkIIRedfishHttpProtocolGuid is installed. + + @param[in] Event Event whose notification function is being invoked. + @param[in] Context Pointer to the notification function's context. +**/ +VOID +EFIAPI +RedfishHttpProtocolIsReady ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + + if (mRedfishHttpProtocol != NULL) { + gBS->CloseEvent (Event); + return; + } + + Status = gBS->LocateProtocol ( + &gEdkIIRedfishHttpProtocolGuid, + NULL, + (VOID **)&mRedfishHttpProtocol + ); + if (EFI_ERROR (Status)) { + return; + } + + gBS->CloseEvent (Event); +} + +/** + + Initial HTTP library instance. + + @param[in] ImageHandle The image handle. + @param[in] SystemTable The system table. + + @retval EFI_SUCCESS Initial library successfully. + @retval Other Return error status. + +**/ +EFI_STATUS +EFIAPI +RedfishHttpConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + VOID *Registration; + + EfiCreateProtocolNotifyEvent ( + &gEdkIIRedfishHttpProtocolGuid, + TPL_CALLBACK, + RedfishHttpProtocolIsReady, + NULL, + &Registration + ); + + return EFI_SUCCESS; +} diff --git a/RedfishClientPkg/Library/RedfishHttpLib/RedfishHttpLib.inf b/RedfishClientPkg/Library/RedfishHttpLib/RedfishHttpLib.inf new file mode 100644 index 000000000..cef888408 --- /dev/null +++ b/RedfishClientPkg/Library/RedfishHttpLib/RedfishHttpLib.inf @@ -0,0 +1,44 @@ +## @file +# Redfish HTTP library is wrapper library for application to call Redfish +# HTTP protocol easily. +# +# Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = RedfishHttpLib + FILE_GUID = 76FD14A1-D404-4FA9-8F3C-384FC8C09A82 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = RedfishHttpLib| DXE_DRIVER UEFI_DRIVER + CONSTRUCTOR = RedfishHttpConstructor + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + RedfishHttpLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + RedfishPkg/RedfishPkg.dec + RedfishClientPkg/RedfishClientPkg.dec + +[LibraryClasses] + BaseLib + DebugLib + UefiLib + UefiBootServicesTableLib + +[Protocols] + gEdkIIRedfishHttpProtocolGuid ## CONSUMES ## + +[depex] + TRUE + diff --git a/RedfishClientPkg/Library/RedfishVersionLib/RedfishVersionLib.c b/RedfishClientPkg/Library/RedfishVersionLib/RedfishVersionLib.c index 45e156ca9..b47836818 100644 --- a/RedfishClientPkg/Library/RedfishVersionLib/RedfishVersionLib.c +++ b/RedfishClientPkg/Library/RedfishVersionLib/RedfishVersionLib.c @@ -2,6 +2,7 @@ Redfish version library implementation (C) Copyright 2022 Hewlett Packard Enterprise Development LP
+ Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. SPDX-License-Identifier: BSD-2-Clause-Patent @@ -10,15 +11,17 @@ #include #include #include +#include #include #include #include #include #include #include +#include #define REDFISH_VERSION_DEFAULT_STRING L"v1" -#define REDFISH_ROOT_URI "/redfish" +#define REDFISH_ROOT_URI L"/redfish" REDFISH_SERVICE *mCacheService; EFI_STRING mVersionCache; @@ -26,7 +29,7 @@ UINTN mVersionStringSize; /** Cache the redfish service version for later use so we don't have to query - HTTP request everytime. + HTTP request every time. @param[in] Service Redfish service instance @param[in] Version Version string to cache @@ -66,7 +69,7 @@ CacheVersion ( /** Query HTTP request to BMC with given redfish service and return redfish - version information. If there is troulbe to get Redfish version on BMC, + version information. If there is trouble to get Redfish version on BMC, The value of PcdDefaultRedfishVersion is returned. It's call responsibility to release returned buffer. @@ -105,22 +108,17 @@ RedfishGetVersion ( // // Get resource from redfish service. // - Status = RedfishGetByUri ( + ZeroMem (&Response, sizeof (Response)); + Status = RedfishHttpGetResource ( Service, REDFISH_ROOT_URI, - &Response + &Response, + TRUE ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a, RedfishGetByService to %a failed: %r\n", __func__, REDFISH_ROOT_URI, Status)); if (Response.Payload != NULL) { RedfishDumpPayload (Response.Payload); - RedfishFreeResponse ( - NULL, - 0, - NULL, - Response.Payload - ); - Response.Payload = NULL; } goto ON_ERROR; @@ -150,6 +148,10 @@ RedfishGetVersion ( VersionString = REDFISH_VERSION_DEFAULT_STRING; } + if (Response.Payload != NULL) { + RedfishHttpFreeResource (&Response); + } + return AllocateCopyPool (StrSize (VersionString), VersionString); } diff --git a/RedfishClientPkg/Library/RedfishVersionLib/RedfishVersionLib.inf b/RedfishClientPkg/Library/RedfishVersionLib/RedfishVersionLib.inf index 34d13d64f..eba8a0823 100644 --- a/RedfishClientPkg/Library/RedfishVersionLib/RedfishVersionLib.inf +++ b/RedfishClientPkg/Library/RedfishVersionLib/RedfishVersionLib.inf @@ -31,10 +31,11 @@ [LibraryClasses] BaseLib + BaseMemoryLib DebugLib MemoryAllocationLib PcdLib - RedfishLib + RedfishHttpLib JsonLib [Protocols] diff --git a/RedfishClientPkg/RedfishClient.fdf.inc b/RedfishClientPkg/RedfishClient.fdf.inc index afa6555a7..5f89bc14c 100644 --- a/RedfishClientPkg/RedfishClient.fdf.inc +++ b/RedfishClientPkg/RedfishClient.fdf.inc @@ -15,6 +15,7 @@ INF RedfishClientPkg/RedfishFeatureCoreDxe/RedfishFeatureCoreDxe.inf INF RedfishClientPkg/RedfishETagDxe/RedfishETagDxe.inf INF RedfishClientPkg/RedfishConfigLangMapDxe/RedfishConfigLangMapDxe.inf + INF RedfishClientPkg/RedfishHttpDxe/RedfishHttpDxe.inf INF RedfishClientPkg/Features/Memory/V1_7_1/Dxe/MemoryDxe.inf INF RedfishClientPkg/Features/MemoryCollectionDxe/MemoryCollectionDxe.inf INF RedfishClientPkg/Features/ComputerSystem/v1_5_0/Dxe/ComputerSystemDxe.inf diff --git a/RedfishClientPkg/RedfishClientComponents.dsc.inc b/RedfishClientPkg/RedfishClientComponents.dsc.inc index 0e27198af..0aa2a8082 100644 --- a/RedfishClientPkg/RedfishClientComponents.dsc.inc +++ b/RedfishClientPkg/RedfishClientComponents.dsc.inc @@ -17,6 +17,7 @@ RedfishClientPkg/RedfishFeatureCoreDxe/RedfishFeatureCoreDxe.inf RedfishClientPkg/RedfishETagDxe/RedfishETagDxe.inf RedfishClientPkg/RedfishConfigLangMapDxe/RedfishConfigLangMapDxe.inf + RedfishClientPkg/RedfishHttpDxe/RedfishHttpDxe.inf RedfishClientPkg/HiiToRedfishMemoryDxe/HiiToRedfishMemoryDxe.inf RedfishClientPkg/HiiToRedfishBootDxe/HiiToRedfishBootDxe.inf RedfishClientPkg/HiiToRedfishBiosDxe/HiiToRedfishBiosDxe.inf diff --git a/RedfishClientPkg/RedfishClientLibs.dsc.inc b/RedfishClientPkg/RedfishClientLibs.dsc.inc index 5eae6711a..506635a7a 100644 --- a/RedfishClientPkg/RedfishClientLibs.dsc.inc +++ b/RedfishClientPkg/RedfishClientLibs.dsc.inc @@ -40,3 +40,4 @@ RedfishVersionLib|RedfishClientPkg/Library/RedfishVersionLib/RedfishVersionLib.inf RedfishAddendumLib|RedfishClientPkg/Library/RedfishAddendumLib/RedfishAddendumLib.inf RedfishDebugLib|RedfishPkg/Library/RedfishDebugLib/RedfishDebugLib.inf + RedfishHttpLib|RedfishClientPkg/Library/RedfishHttpLib/RedfishHttpLib.inf diff --git a/RedfishClientPkg/RedfishClientPkg.dec b/RedfishClientPkg/RedfishClientPkg.dec index eccbc22ef..3e8abe947 100644 --- a/RedfishClientPkg/RedfishClientPkg.dec +++ b/RedfishClientPkg/RedfishClientPkg.dec @@ -26,6 +26,7 @@ EdkIIRedfishResourceConfigLib|Include/Library/EdkIIRedfishResourceConfigLib.h RedfishEventLib|Include/Library/RedfishEventLib.h RedfishVersionLib|Include/Library/RedfishVersionLib.h + RedfishHttpLib|Include/Library/RedfishHttpLib.h [LibraryClasses.Common.Private] ## @libraryclass Redfish Helper Library @@ -45,6 +46,8 @@ gEdkIIRedfishFeatureInterchangeDataProtocolGuid = { 0x4B8FF71C, 0x4A7B, 0x9478, { 0xB7, 0x81, 0x35, 0x9B, 0x0A, 0xF2, 0x00, 0x91 } } ## Include/Protocol/EdkIIRedfishResourceAddendumProtocol.h gEdkIIRedfishResourceAddendumProtocolGuid = { 0xda36b12b, 0xaad4, 0x4e90, { 0xba, 0xcb, 0xe3, 0xb5, 0x3b, 0x08, 0xbc, 0x54 } } + ## Include/Protocol/EdkIIRedfishHttpProtocol.h + gEdkIIRedfishHttpProtocolGuid = { 0xc3194dd2, 0xc796, 0x4abe, { 0xbd, 0x39, 0x9d, 0xf2, 0xe0, 0x4b, 0x86, 0xbc } } [Guids] ## Include/Guid/RedfishClientPkgTokenSpace.h @@ -73,6 +76,20 @@ gEfiRedfishClientPkgTokenSpaceGuid.PcdDefaultRedfishVersion|L"v1"|VOID*|0x10000004 ## The number of seconds that the firmware will wait before system reboot gEfiRedfishClientPkgTokenSpaceGuid.PcdRedfishSystemRebootTimeout|5|UINT16|0x20000002 + ## The number of retry when HTTP GET request failed. If the value is 0, there is no retry enabled. + gEfiRedfishClientPkgTokenSpaceGuid.PcdHttpGetRetry|0|UINT16|0x20000003 + ## The number of retry when HTTP PUT request failed. If the value is 0, there is no retry enabled. + gEfiRedfishClientPkgTokenSpaceGuid.PcdHttpPutRetry|0|UINT16|0x20000004 + ## The number of retry when HTTP PATCH request failed. If the value is 0, there is no retry enabled. + gEfiRedfishClientPkgTokenSpaceGuid.PcdHttpPatchRetry|0|UINT16|0x20000005 + ## The number of retry when HTTP POST request failed. If the value is 0, there is no retry enabled. + gEfiRedfishClientPkgTokenSpaceGuid.PcdHttpPostRetry|0|UINT16|0x20000006 + ## The number of retry when HTTP DELETE request failed. If the value is 0, there is no retry enabled. + gEfiRedfishClientPkgTokenSpaceGuid.PcdHttpDeleteRetry|0|UINT16|0x20000007 + ## The number of second to wait before driver retry HTTP request. If the value is 0, there is no wait before next retry. + gEfiRedfishClientPkgTokenSpaceGuid.PcdHttpRetryWaitInSecond|1|UINT16|0x20000008 + ## This is used to disable Redfish HTTP cache function and every request will be sent to Redfish service. + gEfiRedfishClientPkgTokenSpaceGuid.PcdHttpCacheDisabled|FALSE|BOOLEAN|0x20000009 [PcdsDynamicEx] ## The flag used to indicate that system reboot is required due to system configuration change diff --git a/RedfishClientPkg/RedfishClientPkg.dsc b/RedfishClientPkg/RedfishClientPkg.dsc index e16c91b83..6eb706530 100644 --- a/RedfishClientPkg/RedfishClientPkg.dsc +++ b/RedfishClientPkg/RedfishClientPkg.dsc @@ -61,5 +61,6 @@ RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.inf RedfishClientPkg/PrivateLibrary/RedfishLib/RedfishLib.inf RedfishClientPkg/Library/RedfishAddendumLib/RedfishAddendumLib.inf + RedfishClientPkg/Library/RedfishHttpLib/RedfishHttpLib.inf !include RedfishClientPkg/RedfishClient.dsc.inc diff --git a/RedfishClientPkg/RedfishHttpDxe/RedfishHttpData.c b/RedfishClientPkg/RedfishHttpDxe/RedfishHttpData.c new file mode 100644 index 000000000..733388c32 --- /dev/null +++ b/RedfishClientPkg/RedfishHttpDxe/RedfishHttpData.c @@ -0,0 +1,449 @@ +/** @file + RedfishHttpDxe produces EdkIIRedfishHttpProtocol + for EDK2 Redfish Feature driver to do HTTP operations. + + Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "RedfishHttpData.h" + +/** + This function copy the data in SrcResponse to DstResponse. + + @param[in] SrcResponse Source Response to copy. + @param[out] DstResponse Destination Response. + + @retval EFI_SUCCESS Response is copied successfully. + @retval Others Error occurs. + +**/ +EFI_STATUS +CopyRedfishResponse ( + IN REDFISH_RESPONSE *SrcResponse, + OUT REDFISH_RESPONSE *DstResponse + ) +{ + EDKII_JSON_VALUE JsonValue; + REDFISH_SERVICE Service; + UINTN Index; + + if ((SrcResponse == NULL) || (DstResponse == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (SrcResponse == DstResponse) { + return EFI_SUCCESS; + } + + // + // Status code + // + if (SrcResponse->StatusCode != NULL) { + DstResponse->StatusCode = AllocateCopyPool (sizeof (EFI_HTTP_STATUS_CODE), SrcResponse->StatusCode); + if (DstResponse->StatusCode == NULL) { + goto ON_ERROR; + } + } + + // + // Header + // + if ((SrcResponse->HeaderCount > 0) && (SrcResponse->Headers != NULL)) { + DstResponse->HeaderCount = 0; + DstResponse->Headers = AllocateZeroPool (sizeof (EFI_HTTP_HEADER) * SrcResponse->HeaderCount); + if (DstResponse->Headers == NULL) { + goto ON_ERROR; + } + + for (Index = 0; Index < SrcResponse->HeaderCount; Index++) { + DstResponse->Headers[Index].FieldName = AllocateCopyPool (AsciiStrSize (SrcResponse->Headers[Index].FieldName), SrcResponse->Headers[Index].FieldName); + if (DstResponse->Headers[Index].FieldName == NULL) { + goto ON_ERROR; + } + + DstResponse->Headers[Index].FieldValue = AllocateCopyPool (AsciiStrSize (SrcResponse->Headers[Index].FieldValue), SrcResponse->Headers[Index].FieldValue); + if (DstResponse->Headers[Index].FieldValue == NULL) { + goto ON_ERROR; + } + + DstResponse->HeaderCount += 1; + } + } + + // + // Payload + // + if (SrcResponse->Payload != NULL) { + Service = RedfishServiceInPayload (SrcResponse->Payload); + JsonValue = RedfishJsonInPayload (SrcResponse->Payload); + DstResponse->Payload = RedfishCreatePayload (JsonValue, Service); + if (DstResponse->Payload == NULL) { + goto ON_ERROR; + } + } + + return EFI_SUCCESS; + +ON_ERROR: + + RedfishFreeResponse ( + DstResponse->StatusCode, + DstResponse->HeaderCount, + DstResponse->Headers, + DstResponse->Payload + ); + + return EFI_OUT_OF_RESOURCES; +} + +/** + This function clone input response and return to caller + + @param[in] Response Response to clone. + + @retval REDFISH_RESPONSE * Response is cloned. + @retval NULL Errors occur. + +**/ +REDFISH_RESPONSE * +CloneRedfishResponse ( + IN REDFISH_RESPONSE *Response + ) +{ + EFI_STATUS Status; + REDFISH_RESPONSE *NewResponse; + + if (Response == NULL) { + return NULL; + } + + NewResponse = AllocateZeroPool (sizeof (REDFISH_RESPONSE)); + if (NewResponse == NULL) { + return NULL; + } + + Status = CopyRedfishResponse (Response, NewResponse); + if (EFI_ERROR (Status)) { + FreePool (NewResponse); + return NULL; + } + + return NewResponse; +} + +/** + Release REDFISH_HTTP_CACHE_DATA resource + + @param[in] Data Pointer to REDFISH_HTTP_CACHE_DATA instance + + @retval EFI_SUCCESS REDFISH_HTTP_CACHE_DATA is released successfully. + @retval EFI_INVALID_PARAMETER Data is NULL + +**/ +EFI_STATUS +ReleaseHttpCacheData ( + IN REDFISH_HTTP_CACHE_DATA *Data + ) +{ + if (Data == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Data->Uri != NULL) { + FreePool (Data->Uri); + } + + if (Data->Response != NULL) { + if (Data->Response->Payload != NULL) { + RedfishFreeResponse ( + Data->Response->StatusCode, + Data->Response->HeaderCount, + Data->Response->Headers, + Data->Response->Payload + ); + FreePool (Data->Response); + } + } + + FreePool (Data); + + return EFI_SUCCESS; +} + +/** + Create new cache data. + + @param[in] Uri The URI string matching to this cache data. + @param[in] Response HTTP response. + + @retval REDFISH_HTTP_CACHE_DATA * Pointer to newly created cache data. + @retval NULL No memory available. + +**/ +REDFISH_HTTP_CACHE_DATA * +NewHttpCacheData ( + IN EFI_STRING Uri, + IN REDFISH_RESPONSE *Response + ) +{ + REDFISH_HTTP_CACHE_DATA *NewData; + UINTN Size; + + if (IS_EMPTY_STRING (Uri) || (Response == NULL)) { + return NULL; + } + + NewData = AllocateZeroPool (sizeof (REDFISH_HTTP_CACHE_DATA)); + if (NewData == NULL) { + return NULL; + } + + Size = StrSize (Uri); + NewData->Uri = AllocateCopyPool (Size, Uri); + if (NewData->Uri == NULL) { + goto ON_ERROR; + } + + NewData->Response = Response; + NewData->HitCount = 1; + + return NewData; + +ON_ERROR: + + if (NewData != NULL) { + ReleaseHttpCacheData (NewData); + } + + return NULL; +} + +/** + Search on given ListHeader for given URI string. + + @param[in] ListHeader Target list to search. + @param[in] Uri Target URI to search. + + @retval REDFISH_HTTP_CACHE_DATA Target cache data is found. + @retval NULL No cache data with given URI is found. + +**/ +REDFISH_HTTP_CACHE_DATA * +FindHttpCacheData ( + IN LIST_ENTRY *ListHeader, + IN EFI_STRING Uri + ) +{ + LIST_ENTRY *List; + REDFISH_HTTP_CACHE_DATA *Data; + + if (IS_EMPTY_STRING (Uri)) { + return NULL; + } + + if (IsListEmpty (ListHeader)) { + return NULL; + } + + Data = NULL; + List = GetFirstNode (ListHeader); + while (!IsNull (ListHeader, List)) { + Data = REDFISH_HTTP_CACHE_FROM_LIST (List); + + if (StrCmp (Data->Uri, Uri) == 0) { + return Data; + } + + List = GetNextNode (ListHeader, List); + } + + return NULL; +} + +/** + Search on given ListHeader and return cache data with minimum hit count. + + @param[in] ListHeader Target list to search. + + @retval REDFISH_HTTP_CACHE_DATA Target cache data is returned. + @retval NULL No cache data is found. + +**/ +REDFISH_HTTP_CACHE_DATA * +FindUnusedHttpCacheData ( + IN LIST_ENTRY *ListHeader + ) +{ + LIST_ENTRY *List; + REDFISH_HTTP_CACHE_DATA *Data; + REDFISH_HTTP_CACHE_DATA *UnusedData; + UINTN HitCount; + + if (IsListEmpty (ListHeader)) { + return NULL; + } + + Data = NULL; + UnusedData = NULL; + HitCount = 0; + + List = GetFirstNode (ListHeader); + Data = REDFISH_HTTP_CACHE_FROM_LIST (List); + UnusedData = Data; + HitCount = Data->HitCount; + List = GetNextNode (ListHeader, List); + + while (!IsNull (ListHeader, List)) { + Data = REDFISH_HTTP_CACHE_FROM_LIST (List); + + if (Data->HitCount < HitCount) { + HitCount = Data->HitCount; + UnusedData = Data; + } + + List = GetNextNode (ListHeader, List); + } + + return UnusedData; +} + +/** + Delete a cache data by given cache instance. + + @param[in] List Target cache list to be removed. + @param[in] Data Pointer to the instance to be deleted. + + @retval EFI_SUCCESS Cache data is removed. + @retval Others Fail to remove cache data. + +**/ +EFI_STATUS +DeleteHttpCacheData ( + IN REDFISH_HTTP_CACHE_LIST *List, + IN REDFISH_HTTP_CACHE_DATA *Data + ) +{ + if ((List == NULL) || (Data == NULL)) { + return EFI_INVALID_PARAMETER; + } + + DEBUG ((REDFISH_HTTP_CACHE_DEBUG, "%a: delete: %s\n", __func__, Data->Uri)); + + RemoveEntryList (&Data->List); + --List->Count; + + return ReleaseHttpCacheData (Data); +} + +/** + Add new cache by given URI and HTTP response to specify List. + + @param[in] List Target cache list to add. + @param[in] Uri The URI string matching to this cache data. + @param[in] Response HTTP response. + + @retval EFI_SUCCESS Cache data is added. + @retval Others Fail to add cache data. + +**/ +EFI_STATUS +AddHttpCacheData ( + IN REDFISH_HTTP_CACHE_LIST *List, + IN EFI_STRING Uri, + IN REDFISH_RESPONSE *Response + ) +{ + REDFISH_HTTP_CACHE_DATA *NewData; + REDFISH_HTTP_CACHE_DATA *OldData; + REDFISH_HTTP_CACHE_DATA *UnusedData; + REDFISH_RESPONSE *NewResponse; + + if ((List == NULL) || IS_EMPTY_STRING (Uri) || (Response == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // If same cache data exist, replace it with latest one. + // + OldData = FindHttpCacheData (&List->Head, Uri); + if (OldData != NULL) { + DeleteHttpCacheData (List, OldData); + } + + // + // Check capacity + // + if (List->Count >= List->Capacity) { + DEBUG ((REDFISH_HTTP_CACHE_DEBUG, "%a: list is full and retire unused cache\n", __func__)); + UnusedData = FindUnusedHttpCacheData (&List->Head); + if (UnusedData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + DeleteHttpCacheData (List, UnusedData); + } + + // + // Clone a local copy + // + NewResponse = CloneRedfishResponse (Response); + if (NewResponse == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + NewData = NewHttpCacheData (Uri, NewResponse); + if (NewData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + InsertTailList (&List->Head, &NewData->List); + ++List->Count; + + DEBUG ((REDFISH_HTTP_CACHE_DEBUG, "%a: cache(%d/%d) %s\n", __func__, List->Count, List->Capacity, NewData->Uri)); + + return EFI_SUCCESS; +} + +/** + Release all cache from list. + + @param[in] CacheList The list to be released. + + @retval EFI_SUCCESS All cache data are released. + @retval EFI_INVALID_PARAMETER CacheList is NULL. + +**/ +EFI_STATUS +ReleaseCacheList ( + IN REDFISH_HTTP_CACHE_LIST *CacheList + ) +{ + LIST_ENTRY *List; + LIST_ENTRY *Next; + REDFISH_HTTP_CACHE_DATA *Data; + + if (CacheList == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (IsListEmpty (&CacheList->Head)) { + return EFI_SUCCESS; + } + + Data = NULL; + Next = NULL; + List = GetFirstNode (&CacheList->Head); + while (!IsNull (&CacheList->Head, List)) { + Data = REDFISH_HTTP_CACHE_FROM_LIST (List); + Next = GetNextNode (&CacheList->Head, List); + + DeleteHttpCacheData (CacheList, Data); + + List = Next; + } + + return EFI_SUCCESS; +} diff --git a/RedfishClientPkg/RedfishHttpDxe/RedfishHttpData.h b/RedfishClientPkg/RedfishHttpDxe/RedfishHttpData.h new file mode 100644 index 000000000..35f86468c --- /dev/null +++ b/RedfishClientPkg/RedfishHttpDxe/RedfishHttpData.h @@ -0,0 +1,141 @@ +/** @file + Definitions of RedfishHttpData + + Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef EDKII_REDFISH_HTTP_DATA_H_ +#define EDKII_REDFISH_HTTP_DATA_H_ + +#include "RedfishHttpDxe.h" + +/// +/// Definition of REDFISH_HTTP_CACHE_DATA +/// +typedef struct { + LIST_ENTRY List; + EFI_STRING Uri; + UINTN HitCount; + REDFISH_RESPONSE *Response; +} REDFISH_HTTP_CACHE_DATA; + +#define REDFISH_HTTP_CACHE_FROM_LIST(a) BASE_CR (a, REDFISH_HTTP_CACHE_DATA, List) + +/// +/// Definition of REDFISH_HTTP_CACHE_LIST +/// +typedef struct { + LIST_ENTRY Head; + UINTN Count; + UINTN Capacity; +} REDFISH_HTTP_CACHE_LIST; + +/// +/// Definition of REDFISH_HTTP_RETRY_SETTING +/// +typedef struct { + UINT16 MaximumRetryGet; + UINT16 MaximumRetryPut; + UINT16 MaximumRetryPost; + UINT16 MaximumRetryPatch; + UINT16 MaximumRetryDelete; + UINTN RetryWait; +} REDFISH_HTTP_RETRY_SETTING; + +/// +/// Definition of REDFISH_HTTP_CACHE_PRIVATE +/// +typedef struct { + EFI_HANDLE ImageHandle; + BOOLEAN CacheDisabled; + REDFISH_HTTP_CACHE_LIST CacheList; + EDKII_REDFISH_HTTP_PROTOCOL Protocol; + REDFISH_HTTP_RETRY_SETTING RetrySetting; +} REDFISH_HTTP_CACHE_PRIVATE; + +#define REDFISH_HTTP_CACHE_PRIVATE_FROM_THIS(a) BASE_CR (a, REDFISH_HTTP_CACHE_PRIVATE, Protocol) + +/** + Search on given ListHeader for given URI string. + + @param[in] ListHeader Target list to search. + @param[in] Uri Target URI to search. + + @retval REDFISH_HTTP_CACHE_DATA Target cache data is found. + @retval NULL No cache data with given URI is found. + +**/ +REDFISH_HTTP_CACHE_DATA * +FindHttpCacheData ( + IN LIST_ENTRY *ListHeader, + IN EFI_STRING Uri + ); + +/** + This function copy the data in SrcResponse to DstResponse. + + @param[in] SrcResponse Source Response to copy. + @param[out] DstResponse Destination Response. + + @retval EFI_SUCCESS Response is copied successfully. + @retval Others Error occurs. + +**/ +EFI_STATUS +CopyRedfishResponse ( + IN REDFISH_RESPONSE *SrcResponse, + OUT REDFISH_RESPONSE *DstResponse + ); + +/** + Release all cache from list. + + @param[in] CacheList The list to be released. + + @retval EFI_SUCCESS All cache data are released. + @retval EFI_INVALID_PARAMETER CacheList is NULL. + +**/ +EFI_STATUS +ReleaseCacheList ( + IN REDFISH_HTTP_CACHE_LIST *CacheList + ); + +/** + Add new cache by given URI and HTTP response to specify List. + + @param[in] List Target cache list to add. + @param[in] Uri The URI string matching to this cache data. + @param[in] Response HTTP response. + + @retval EFI_SUCCESS Cache data is added. + @retval Others Fail to add cache data. + +**/ +EFI_STATUS +AddHttpCacheData ( + IN REDFISH_HTTP_CACHE_LIST *List, + IN EFI_STRING Uri, + IN REDFISH_RESPONSE *Response + ); + +/** + Delete a cache data by given cache instance. + + @param[in] List Target cache list to be removed. + @param[in] Data Pointer to the instance to be deleted. + + @retval EFI_SUCCESS Cache data is removed. + @retval Others Fail to remove cache data. + +**/ +EFI_STATUS +DeleteHttpCacheData ( + IN REDFISH_HTTP_CACHE_LIST *List, + IN REDFISH_HTTP_CACHE_DATA *Data + ); + +#endif diff --git a/RedfishClientPkg/RedfishHttpDxe/RedfishHttpDxe.c b/RedfishClientPkg/RedfishHttpDxe/RedfishHttpDxe.c new file mode 100644 index 000000000..a08a25c3d --- /dev/null +++ b/RedfishClientPkg/RedfishHttpDxe/RedfishHttpDxe.c @@ -0,0 +1,986 @@ +/** @file + RedfishHttpDxe produces EdkIIRedfishHttpProtocol + for EDK2 Redfish Feature driver to do HTTP operations. + + Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "RedfishHttpDxe.h" +#include "RedfishHttpData.h" + +REDFISH_HTTP_CACHE_PRIVATE *mRedfishHttpCachePrivate = NULL; + +/** + Debug output the cache list. + + @param[in] Msg Debug message string. + @param[in] ErrorLevel Output error level. + @param[in] CacheList Target list to dump. + + @retval EFI_SUCCESS Debug dump finished. + @retval EFI_INVALID_PARAMETER HttpCacheList is NULL. + +**/ +EFI_STATUS +DumpHttpCacheList ( + IN CONST CHAR8 *Msg, + IN UINTN ErrorLevel, + IN REDFISH_HTTP_CACHE_LIST *CacheList + ) +{ + LIST_ENTRY *List; + REDFISH_HTTP_CACHE_DATA *Data; + UINTN Index; + + if (CacheList == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (!IS_EMPTY_STRING (Msg)) { + DEBUG ((ErrorLevel, "%a\n", Msg)); + } + + if (IsListEmpty (&CacheList->Head)) { + DEBUG ((ErrorLevel, "list is empty\n")); + return EFI_NOT_FOUND; + } + + DEBUG ((ErrorLevel, "list count: %d capacity: %d\n", CacheList->Count, CacheList->Capacity)); + Data = NULL; + Index = 0; + List = GetFirstNode (&CacheList->Head); + while (!IsNull (&CacheList->Head, List)) { + Data = REDFISH_HTTP_CACHE_FROM_LIST (List); + + DEBUG ((ErrorLevel, "%d) Uri: %s Hit: %d\n", ++Index, Data->Uri, Data->HitCount)); + + List = GetNextNode (&CacheList->Head, List); + } + + return EFI_SUCCESS; +} + +/** + + Check HTTP status code to see if we like to retry HTTP request or not. + + @param[in] StatusCode HTTP status code. + + @retval BOOLEAN Return true when we like to retry request. + Return false when we don't want to retry request. + +**/ +BOOLEAN +RedfishRetryRequired ( + IN EFI_HTTP_STATUS_CODE *StatusCode + ) +{ + if (StatusCode == NULL) { + return TRUE; + } + + if ((*StatusCode == HTTP_STATUS_500_INTERNAL_SERVER_ERROR) || + (*StatusCode == HTTP_STATUS_UNSUPPORTED_STATUS)) + { + return TRUE; + } + + return FALSE; +} + +/** + + Convert Unicode string to ASCII string. It's call responsibility to release returned buffer. + + @param[in] UnicodeStr Unicode string to convert. + + @retval CHAR8 * ASCII string returned. + @retval NULL Errors occur. + +**/ +CHAR8 * +StringUnicodeToAscii ( + IN EFI_STRING UnicodeStr + ) +{ + CHAR8 *AsciiStr; + UINTN AsciiStrSize; + EFI_STATUS Status; + + if (IS_EMPTY_STRING (UnicodeStr)) { + return NULL; + } + + AsciiStrSize = StrLen (UnicodeStr) + 1; + AsciiStr = AllocatePool (AsciiStrSize); + if (AsciiStr == NULL) { + return NULL; + } + + Status = UnicodeStrToAsciiStrS (UnicodeStr, AsciiStr, AsciiStrSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "UnicodeStrToAsciiStrS failed: %r\n", Status)); + FreePool (AsciiStr); + return NULL; + } + + return AsciiStr; +} + +/** + Return HTTP method in ASCII string. Caller does not need + to free returned string buffer. + + @param[in] Method HTTP method. + + @retval CHAR8 * Method in string. +**/ +CHAR8 * +HttpMethodToString ( + IN EFI_HTTP_METHOD Method + ) +{ + switch (Method) { + case HttpMethodGet: + return HTTP_METHOD_GET; + break; + case HttpMethodPost: + return HTTP_METHOD_POST; + break; + case HttpMethodPatch: + return HTTP_METHOD_PATCH; + break; + case HttpMethodPut: + return HTTP_METHOD_PUT; + break; + case HttpMethodDelete: + return HTTP_METHOD_DELETE; + break; + default: + break; + } + + return "Unknown"; +} + +/** + Report HTTP communication error via report status code. + + @param[in] Method HTTP method. + @param[in] Uri The URI which has failure. + @param[in] HttpStatusCode HTTP status code. + +**/ +VOID +ReportHttpError ( + IN EFI_HTTP_METHOD Method, + IN CHAR8 *Uri, + IN EFI_HTTP_STATUS_CODE *HttpStatusCode OPTIONAL + ) +{ + CHAR8 ErrorMsg[REDFISH_ERROR_MSG_MAX]; + + if (IS_EMPTY_STRING (Uri)) { + DEBUG ((DEBUG_ERROR, "%a: no URI to report error status\n", __func__)); + return; + } + + // + // Report failure of URI and HTTP status code. + // + AsciiSPrint (ErrorMsg, sizeof (ErrorMsg), REDFISH_HTTP_ERROR_REPORT, HttpMethodToString (Method), (HttpStatusCode == NULL ? HTTP_STATUS_UNSUPPORTED_STATUS : *HttpStatusCode), Uri); + + REPORT_STATUS_CODE_WITH_EXTENDED_DATA ( + EFI_ERROR_CODE | EFI_ERROR_MAJOR, + EFI_COMPUTING_UNIT_MANAGEABILITY | EFI_MANAGEABILITY_EC_REDFISH_COMMUNICATION_ERROR, + ErrorMsg, + AsciiStrSize (ErrorMsg) + ); +} + +/** + Perform HTTP GET to Get redfish resource from given resource URI with + cache mechanism supported. It's caller's responsibility to free Response + by calling FreeResponse (). + + @param[in] This Pointer to EDKII_REDFISH_HTTP_PROTOCOL instance. + @param[in] Service Redfish service instance to make query. + @param[in] Uri Target resource URI. + @param[out] Response HTTP response from redfish service. + @param[in] UseCache If it is TRUE, this function will search for + cache first. If it is FALSE, this function + will query Redfish URI directly. + + @retval EFI_SUCCESS Resrouce is returned successfully. + @retval Others Errors occur. + +**/ +EFI_STATUS +EFIAPI +RedfishHttpGetResource ( + IN EDKII_REDFISH_HTTP_PROTOCOL *This, + IN REDFISH_SERVICE Service, + IN EFI_STRING Uri, + OUT REDFISH_RESPONSE *Response, + IN BOOLEAN UseCache + ) +{ + EFI_STATUS Status; + CHAR8 *AsciiUri; + REDFISH_HTTP_CACHE_DATA *CacheData; + UINTN RetryCount; + REDFISH_HTTP_CACHE_PRIVATE *Private; + + if ((This == NULL) || (Service == NULL) || (Response == NULL) || IS_EMPTY_STRING (Uri)) { + return EFI_INVALID_PARAMETER; + } + + DEBUG ((REDFISH_HTTP_CACHE_DEBUG, "%a: Get URI: %s cache: %a\n", __func__, Uri, (UseCache ? "true" : "false"))); + + Private = REDFISH_HTTP_CACHE_PRIVATE_FROM_THIS (This); + AsciiUri = NULL; + CacheData = NULL; + RetryCount = 0; + ZeroMem (Response, sizeof (REDFISH_RESPONSE)); + + if (Private->CacheDisabled) { + UseCache = FALSE; + DEBUG ((REDFISH_HTTP_CACHE_DEBUG, "%a: cache is disabled by PCD!\n", __func__)); + } + + // + // Search for cache list. + // + if (UseCache) { + CacheData = FindHttpCacheData (&Private->CacheList.Head, Uri); + if (CacheData != NULL) { + DEBUG ((REDFISH_HTTP_CACHE_DEBUG_REQUEST, "%a: cache hit! %s\n", __func__, Uri)); + + // + // Copy cached response to caller's buffer. + // + Status = CopyRedfishResponse (CacheData->Response, Response); + CacheData->HitCount += 1; + return Status; + } + } + + AsciiUri = StringUnicodeToAscii (Uri); + if (AsciiUri == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Get resource from redfish service. + // + do { + RetryCount += 1; + Status = RedfishGetByUri ( + Service, + AsciiUri, + Response + ); + DEBUG ((REDFISH_HTTP_CACHE_DEBUG_REQUEST, "%a: HTTP request: %a :%r\n", __func__, AsciiUri, Status)); + if (!EFI_ERROR (Status) || (RetryCount >= Private->RetrySetting.MaximumRetryGet)) { + break; + } + + // + // Retry when BMC is not ready. + // + if ((Response->StatusCode != NULL)) { + DEBUG_CODE ( + DumpRedfishResponse (NULL, DEBUG_ERROR, Response); + ); + + if (!RedfishRetryRequired (Response->StatusCode)) { + break; + } + + // + // Release response for next round of request. + // + This->FreeResponse (This, Response); + } + + DEBUG ((DEBUG_WARN, "%a: RedfishGetByUri failed, retry (%d/%d)\n", __func__, RetryCount, Private->RetrySetting.MaximumRetryGet)); + if (Private->RetrySetting.RetryWait > 0) { + gBS->Stall (Private->RetrySetting.RetryWait); + } + } while (TRUE); + + if (EFI_ERROR (Status)) { + DEBUG_CODE ( + DumpRedfishResponse (NULL, DEBUG_ERROR, Response); + ); + // + // Report status code for Redfish failure + // + ReportHttpError (HttpMethodGet, AsciiUri, Response->StatusCode); + DEBUG ((DEBUG_ERROR, "%a: get %a failed (%d/%d): %r\n", __func__, AsciiUri, RetryCount, Private->RetrySetting.MaximumRetryGet, Status)); + goto ON_RELEASE; + } + + if (!Private->CacheDisabled) { + // + // Keep response in cache list + // + Status = AddHttpCacheData (&Private->CacheList, Uri, Response); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: failed to cache %s: %r\n", __func__, Uri, Status)); + goto ON_RELEASE; + } + + DEBUG_CODE ( + DumpHttpCacheList (__func__, REDFISH_HTTP_CACHE_DEBUG_DUMP, &Private->CacheList); + ); + } + +ON_RELEASE: + + if (AsciiUri != NULL) { + FreePool (AsciiUri); + } + + return Status; +} + +/** + This function free resources in given Response. + + @param[in] This Pointer to EDKII_REDFISH_HTTP_PROTOCOL instance. + @param[in] Response HTTP response to be released. + + @retval EFI_SUCCESS Resrouce is released successfully. + @retval Others Errors occur. + +**/ +EFI_STATUS +EFIAPI +RedfishHttpFreeResponse ( + IN EDKII_REDFISH_HTTP_PROTOCOL *This, + IN REDFISH_RESPONSE *Response + ) +{ + if ((This == NULL) || (Response == NULL)) { + return EFI_INVALID_PARAMETER; + } + + DEBUG ((REDFISH_HTTP_CACHE_DEBUG, "%a: entry\n", __func__)); + + // + // Call function in RedfishLib to release resource. + // + RedfishFreeResponse ( + Response->StatusCode, + Response->HeaderCount, + Response->Headers, + Response->Payload + ); + + return EFI_SUCCESS; +} + +/** + This function expire the cached response of given URI. + + @param[in] This Pointer to EDKII_REDFISH_HTTP_PROTOCOL instance. + @param[in] Uri Target response of URI. + + @retval EFI_SUCCESS Target response is expired successfully. + @retval Others Errors occur. + +**/ +EFI_STATUS +EFIAPI +RedfishHttpExpireResponse ( + IN EDKII_REDFISH_HTTP_PROTOCOL *This, + IN EFI_STRING Uri + ) +{ + REDFISH_HTTP_CACHE_PRIVATE *Private; + REDFISH_HTTP_CACHE_DATA *CacheData; + + if ((This == NULL) || IS_EMPTY_STRING (Uri)) { + return EFI_INVALID_PARAMETER; + } + + DEBUG ((REDFISH_HTTP_CACHE_DEBUG, "%a: expire URI: %s\n", __func__, Uri)); + + Private = REDFISH_HTTP_CACHE_PRIVATE_FROM_THIS (This); + + CacheData = FindHttpCacheData (&Private->CacheList.Head, Uri); + if (CacheData == NULL) { + return EFI_NOT_FOUND; + } + + return DeleteHttpCacheData (&Private->CacheList, CacheData); +} + +/** + Perform HTTP PATCH to send redfish resource to given resource URI. + It's caller's responsibility to free Response by calling FreeResponse (). + + @param[in] This Pointer to EDKII_REDFISH_HTTP_PROTOCOL instance. + @param[in] Service Redfish service instance to make query. + @param[in] Uri Target resource URI. + @param[in] Content Data to patch. + @param[out] Response HTTP response from redfish service. + + @retval EFI_SUCCESS Resrouce is returned successfully. + @retval Others Errors occur. + +**/ +EFI_STATUS +EFIAPI +RedfishHttpPatchResource ( + IN EDKII_REDFISH_HTTP_PROTOCOL *This, + IN REDFISH_SERVICE Service, + IN EFI_STRING Uri, + IN CHAR8 *Content, + OUT REDFISH_RESPONSE *Response + ) +{ + EFI_STATUS Status; + CHAR8 *AsciiUri; + UINTN RetryCount; + REDFISH_HTTP_CACHE_PRIVATE *Private; + + if ((This == NULL) || (Service == NULL) || (Response == NULL) || IS_EMPTY_STRING (Uri) || IS_EMPTY_STRING (Content)) { + return EFI_INVALID_PARAMETER; + } + + DEBUG ((REDFISH_HTTP_CACHE_DEBUG, "%a: Patch URI: %s\n", __func__, Uri)); + + Private = REDFISH_HTTP_CACHE_PRIVATE_FROM_THIS (This); + AsciiUri = NULL; + RetryCount = 0; + ZeroMem (Response, sizeof (REDFISH_RESPONSE)); + + AsciiUri = StringUnicodeToAscii (Uri); + if (AsciiUri == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Patch resource to redfish service. + // + do { + RetryCount += 1; + Status = RedfishPatchToUri ( + Service, + AsciiUri, + Content, + Response + ); + DEBUG ((REDFISH_HTTP_CACHE_DEBUG_REQUEST, "%a: HTTP request: %a :%r\n", __func__, AsciiUri, Status)); + if (!EFI_ERROR (Status) || (RetryCount >= Private->RetrySetting.MaximumRetryPatch)) { + break; + } + + // + // Retry when BMC is not ready. + // + if ((Response->StatusCode != NULL)) { + DEBUG_CODE ( + DumpRedfishResponse (NULL, DEBUG_ERROR, Response); + ); + + if (!RedfishRetryRequired (Response->StatusCode)) { + break; + } + + // + // Release response for next round of request. + // + This->FreeResponse (This, Response); + } + + DEBUG ((DEBUG_WARN, "%a: RedfishPatchToUri failed, retry (%d/%d)\n", __func__, RetryCount, Private->RetrySetting.MaximumRetryPatch)); + if (Private->RetrySetting.RetryWait > 0) { + gBS->Stall (Private->RetrySetting.RetryWait); + } + } while (TRUE); + + // + // Redfish resource is updated. Automatically expire the cached response + // so application can directly get resource from Redfish service again. + // + DEBUG ((REDFISH_HTTP_CACHE_DEBUG, "%a: Resource is updated, expire URI: %s\n", __func__, Uri)); + RedfishHttpExpireResponse (This, Uri); + + if (EFI_ERROR (Status)) { + DEBUG_CODE ( + DumpRedfishResponse (NULL, DEBUG_ERROR, Response); + ); + // + // Report status code for Redfish failure + // + ReportHttpError (HttpMethodPatch, AsciiUri, Response->StatusCode); + DEBUG ((DEBUG_ERROR, "%a: patch %a failed (%d/%d): %r\n", __func__, AsciiUri, RetryCount, Private->RetrySetting.MaximumRetryGet, Status)); + goto ON_RELEASE; + } + +ON_RELEASE: + + if (AsciiUri != NULL) { + FreePool (AsciiUri); + } + + return Status; +} + +/** + Perform HTTP PUT to send redfish resource to given resource URI. + It's caller's responsibility to free Response by calling FreeResponse (). + + @param[in] This Pointer to EDKII_REDFISH_HTTP_PROTOCOL instance. + @param[in] Service Redfish service instance to make query. + @param[in] Uri Target resource URI. + @param[in] Content Data to put. + @param[out] Response HTTP response from redfish service. + + @retval EFI_SUCCESS Resrouce is returned successfully. + @retval Others Errors occur. + +**/ +EFI_STATUS +EFIAPI +RedfishHttpPutResource ( + IN EDKII_REDFISH_HTTP_PROTOCOL *This, + IN REDFISH_SERVICE Service, + IN EFI_STRING Uri, + IN CHAR8 *Content, + OUT REDFISH_RESPONSE *Response + ) +{ + EFI_STATUS Status; + CHAR8 *AsciiUri; + UINTN RetryCount; + REDFISH_HTTP_CACHE_PRIVATE *Private; + + if ((This == NULL) || (Service == NULL) || (Response == NULL) || IS_EMPTY_STRING (Uri) || IS_EMPTY_STRING (Content)) { + return EFI_INVALID_PARAMETER; + } + + DEBUG ((REDFISH_HTTP_CACHE_DEBUG, "%a: Put URI: %s\n", __func__, Uri)); + + Private = REDFISH_HTTP_CACHE_PRIVATE_FROM_THIS (This); + AsciiUri = NULL; + RetryCount = 0; + ZeroMem (Response, sizeof (REDFISH_RESPONSE)); + + AsciiUri = StringUnicodeToAscii (Uri); + if (AsciiUri == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Patch resource to redfish service. + // + do { + RetryCount += 1; + Status = RedfishPutToUri ( + Service, + AsciiUri, + Content, + 0, + NULL, + Response + ); + DEBUG ((REDFISH_HTTP_CACHE_DEBUG_REQUEST, "%a: HTTP request: %a :%r\n", __func__, AsciiUri, Status)); + if (!EFI_ERROR (Status) || (RetryCount >= Private->RetrySetting.MaximumRetryPut)) { + break; + } + + // + // Retry when BMC is not ready. + // + if ((Response->StatusCode != NULL)) { + DEBUG_CODE ( + DumpRedfishResponse (NULL, DEBUG_ERROR, Response); + ); + + if (!RedfishRetryRequired (Response->StatusCode)) { + break; + } + + // + // Release response for next round of request. + // + This->FreeResponse (This, Response); + } + + DEBUG ((DEBUG_WARN, "%a: RedfishPutToUri failed, retry (%d/%d)\n", __func__, RetryCount, Private->RetrySetting.MaximumRetryPut)); + if (Private->RetrySetting.RetryWait > 0) { + gBS->Stall (Private->RetrySetting.RetryWait); + } + } while (TRUE); + + // + // Redfish resource is updated. Automatically expire the cached response + // so application can directly get resource from Redfish service again. + // + DEBUG ((REDFISH_HTTP_CACHE_DEBUG, "%a: Resource is updated, expire URI: %s\n", __func__, Uri)); + RedfishHttpExpireResponse (This, Uri); + + if (EFI_ERROR (Status)) { + DEBUG_CODE ( + DumpRedfishResponse (NULL, DEBUG_ERROR, Response); + ); + // + // Report status code for Redfish failure + // + ReportHttpError (HttpMethodPut, AsciiUri, Response->StatusCode); + DEBUG ((DEBUG_ERROR, "%a: put %a failed (%d/%d): %r\n", __func__, AsciiUri, RetryCount, Private->RetrySetting.MaximumRetryGet, Status)); + goto ON_RELEASE; + } + +ON_RELEASE: + + if (AsciiUri != NULL) { + FreePool (AsciiUri); + } + + return Status; +} + +/** + Perform HTTP POST to send redfish resource to given resource URI. + It's caller's responsibility to free Response by calling FreeResponse (). + + @param[in] This Pointer to EDKII_REDFISH_HTTP_PROTOCOL instance. + @param[in] Service Redfish service instance to make query. + @param[in] Uri Target resource URI. + @param[in] Content Data to post. + @param[out] Response HTTP response from redfish service. + + @retval EFI_SUCCESS Resrouce is returned successfully. + @retval Others Errors occur. + +**/ +EFI_STATUS +EFIAPI +RedfishHttpPostResource ( + IN EDKII_REDFISH_HTTP_PROTOCOL *This, + IN REDFISH_SERVICE Service, + IN EFI_STRING Uri, + IN CHAR8 *Content, + OUT REDFISH_RESPONSE *Response + ) +{ + EFI_STATUS Status; + CHAR8 *AsciiUri; + UINTN RetryCount; + REDFISH_HTTP_CACHE_PRIVATE *Private; + + if ((This == NULL) || (Service == NULL) || (Response == NULL) || IS_EMPTY_STRING (Uri) || IS_EMPTY_STRING (Content)) { + return EFI_INVALID_PARAMETER; + } + + DEBUG ((REDFISH_HTTP_CACHE_DEBUG, "%a: Post URI: %s\n", __func__, Uri)); + + Private = REDFISH_HTTP_CACHE_PRIVATE_FROM_THIS (This); + AsciiUri = NULL; + RetryCount = 0; + ZeroMem (Response, sizeof (REDFISH_RESPONSE)); + + AsciiUri = StringUnicodeToAscii (Uri); + if (AsciiUri == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Patch resource to redfish service. + // + do { + RetryCount += 1; + Status = RedfishPostToUri ( + Service, + AsciiUri, + Content, + 0, + NULL, + Response + ); + DEBUG ((REDFISH_HTTP_CACHE_DEBUG_REQUEST, "%a: HTTP request: %a :%r\n", __func__, AsciiUri, Status)); + if (!EFI_ERROR (Status) || (RetryCount >= Private->RetrySetting.MaximumRetryPut)) { + break; + } + + // + // Retry when BMC is not ready. + // + if ((Response->StatusCode != NULL)) { + DEBUG_CODE ( + DumpRedfishResponse (NULL, DEBUG_ERROR, Response); + ); + + if (!RedfishRetryRequired (Response->StatusCode)) { + break; + } + + // + // Release response for next round of request. + // + This->FreeResponse (This, Response); + } + + DEBUG ((DEBUG_WARN, "%a: RedfishPostToUri failed, retry (%d/%d)\n", __func__, RetryCount, Private->RetrySetting.MaximumRetryPut)); + if (Private->RetrySetting.RetryWait > 0) { + gBS->Stall (Private->RetrySetting.RetryWait); + } + } while (TRUE); + + // + // Redfish resource is updated. Automatically expire the cached response + // so application can directly get resource from Redfish service again. + // + DEBUG ((REDFISH_HTTP_CACHE_DEBUG, "%a: Resource is updated, expire URI: %s\n", __func__, Uri)); + RedfishHttpExpireResponse (This, Uri); + + if (EFI_ERROR (Status)) { + DEBUG_CODE ( + DumpRedfishResponse (NULL, DEBUG_ERROR, Response); + ); + // + // Report status code for Redfish failure + // + ReportHttpError (HttpMethodPost, AsciiUri, Response->StatusCode); + DEBUG ((DEBUG_ERROR, "%a: post %a failed (%d/%d): %r\n", __func__, AsciiUri, RetryCount, Private->RetrySetting.MaximumRetryGet, Status)); + goto ON_RELEASE; + } + +ON_RELEASE: + + if (AsciiUri != NULL) { + FreePool (AsciiUri); + } + + return Status; +} + +/** + Perform HTTP DELETE to delete redfish resource on given resource URI. + It's caller's responsibility to free Response by calling FreeResponse (). + + @param[in] This Pointer to EDKII_REDFISH_HTTP_PROTOCOL instance. + @param[in] Service Redfish service instance to make query. + @param[in] Uri Target resource URI. + @param[out] Response HTTP response from redfish service. + + @retval EFI_SUCCESS Resrouce is returned successfully. + @retval Others Errors occur. + +**/ +EFI_STATUS +EFIAPI +RedfishHttpDeleteResource ( + IN EDKII_REDFISH_HTTP_PROTOCOL *This, + IN REDFISH_SERVICE Service, + IN EFI_STRING Uri, + OUT REDFISH_RESPONSE *Response + ) +{ + EFI_STATUS Status; + CHAR8 *AsciiUri; + UINTN RetryCount; + REDFISH_HTTP_CACHE_PRIVATE *Private; + + if ((This == NULL) || (Service == NULL) || (Response == NULL) || IS_EMPTY_STRING (Uri)) { + return EFI_INVALID_PARAMETER; + } + + DEBUG ((REDFISH_HTTP_CACHE_DEBUG, "%a: Delete URI: %s\n", __func__, Uri)); + + Private = REDFISH_HTTP_CACHE_PRIVATE_FROM_THIS (This); + AsciiUri = NULL; + RetryCount = 0; + ZeroMem (Response, sizeof (REDFISH_RESPONSE)); + + AsciiUri = StringUnicodeToAscii (Uri); + if (AsciiUri == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Patch resource to redfish service. + // + do { + RetryCount += 1; + Status = RedfishDeleteByUri ( + Service, + AsciiUri, + Response + ); + DEBUG ((REDFISH_HTTP_CACHE_DEBUG_REQUEST, "%a: HTTP request: %a :%r\n", __func__, AsciiUri, Status)); + if (!EFI_ERROR (Status) || (RetryCount >= Private->RetrySetting.MaximumRetryDelete)) { + break; + } + + // + // Retry when BMC is not ready. + // + if ((Response->StatusCode != NULL)) { + DEBUG_CODE ( + DumpRedfishResponse (NULL, DEBUG_ERROR, Response); + ); + + if (!RedfishRetryRequired (Response->StatusCode)) { + break; + } + + // + // Release response for next round of request. + // + This->FreeResponse (This, Response); + } + + DEBUG ((DEBUG_WARN, "%a: RedfishDeleteByUri failed, retry (%d/%d)\n", __func__, RetryCount, Private->RetrySetting.MaximumRetryDelete)); + if (Private->RetrySetting.RetryWait > 0) { + gBS->Stall (Private->RetrySetting.RetryWait); + } + } while (TRUE); + + // + // Redfish resource is updated. Automatically expire the cached response + // so application can directly get resource from Redfish service again. + // + DEBUG ((REDFISH_HTTP_CACHE_DEBUG, "%a: Resource is updated, expire URI: %s\n", __func__, Uri)); + RedfishHttpExpireResponse (This, Uri); + + if (EFI_ERROR (Status)) { + DEBUG_CODE ( + DumpRedfishResponse (NULL, DEBUG_ERROR, Response); + ); + // + // Report status code for Redfish failure + // + ReportHttpError (HttpMethodDelete, AsciiUri, Response->StatusCode); + DEBUG ((DEBUG_ERROR, "%a: delete %a failed (%d/%d): %r\n", __func__, AsciiUri, RetryCount, Private->RetrySetting.MaximumRetryGet, Status)); + goto ON_RELEASE; + } + +ON_RELEASE: + + if (AsciiUri != NULL) { + FreePool (AsciiUri); + } + + return Status; +} + +EDKII_REDFISH_HTTP_PROTOCOL mRedfishHttpProtocol = { + EDKII_REDFISH_HTTP_PROTOCOL_REVISION, + RedfishHttpGetResource, + RedfishHttpPatchResource, + RedfishHttpPutResource, + RedfishHttpPostResource, + RedfishHttpDeleteResource, + RedfishHttpFreeResponse, + RedfishHttpExpireResponse +}; + +/** + Unloads an image. + + @param[in] ImageHandle Handle that identifies the image to be unloaded. + + @retval EFI_SUCCESS The image has been unloaded. + @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle. + +**/ +EFI_STATUS +EFIAPI +RedfishHttpDriverUnload ( + IN EFI_HANDLE ImageHandle + ) +{ + if (mRedfishHttpCachePrivate == NULL) { + return EFI_SUCCESS; + } + + if (!IsListEmpty (&mRedfishHttpCachePrivate->CacheList.Head)) { + ReleaseCacheList (&mRedfishHttpCachePrivate->CacheList); + } + + gBS->UninstallMultipleProtocolInterfaces ( + ImageHandle, + &gEdkIIRedfishHttpProtocolGuid, + &mRedfishHttpCachePrivate->Protocol, + NULL + ); + + FreePool (mRedfishHttpCachePrivate); + mRedfishHttpCachePrivate = NULL; + + return EFI_SUCCESS; +} + +/** + Main entry for this driver. + + @param[in] ImageHandle Image handle this driver. + @param[in] SystemTable Pointer to SystemTable. + + @retval EFI_SUCCESS This function always complete successfully. + +**/ +EFI_STATUS +EFIAPI +RedfishHttpEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + if (mRedfishHttpCachePrivate != NULL) { + return EFI_ALREADY_STARTED; + } + + mRedfishHttpCachePrivate = AllocateZeroPool (sizeof (REDFISH_HTTP_CACHE_PRIVATE)); + if (mRedfishHttpCachePrivate == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Initial cache list and protocol instance. + // + mRedfishHttpCachePrivate->ImageHandle = ImageHandle; + CopyMem (&mRedfishHttpCachePrivate->Protocol, &mRedfishHttpProtocol, sizeof (EDKII_REDFISH_HTTP_PROTOCOL)); + mRedfishHttpCachePrivate->CacheList.Capacity = REDFISH_HTTP_CACHE_LIST_SIZE; + mRedfishHttpCachePrivate->CacheList.Count = 0x00; + mRedfishHttpCachePrivate->CacheDisabled = PcdGetBool (PcdHttpCacheDisabled); + InitializeListHead (&mRedfishHttpCachePrivate->CacheList.Head); + + // + // Get retry settings + // + mRedfishHttpCachePrivate->RetrySetting.MaximumRetryGet = PcdGet16 (PcdHttpGetRetry); + mRedfishHttpCachePrivate->RetrySetting.MaximumRetryPut = PcdGet16 (PcdHttpPutRetry); + mRedfishHttpCachePrivate->RetrySetting.MaximumRetryPatch = PcdGet16 (PcdHttpPatchRetry); + mRedfishHttpCachePrivate->RetrySetting.MaximumRetryPost = PcdGet16 (PcdHttpPostRetry); + mRedfishHttpCachePrivate->RetrySetting.MaximumRetryDelete = PcdGet16 (PcdHttpDeleteRetry); + mRedfishHttpCachePrivate->RetrySetting.RetryWait = PcdGet16 (PcdHttpRetryWaitInSecond) * 1000000U; + + // + // Install the gEdkIIRedfishHttpProtocolGuid onto Handle. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &mRedfishHttpCachePrivate->ImageHandle, + &gEdkIIRedfishHttpProtocolGuid, + &mRedfishHttpCachePrivate->Protocol, + NULL + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: cannot install Redfish http protocol: %r\n", __func__, Status)); + RedfishHttpDriverUnload (ImageHandle); + return Status; + } + + return EFI_SUCCESS; +} diff --git a/RedfishClientPkg/RedfishHttpDxe/RedfishHttpDxe.h b/RedfishClientPkg/RedfishHttpDxe/RedfishHttpDxe.h new file mode 100644 index 000000000..6a746aebe --- /dev/null +++ b/RedfishClientPkg/RedfishHttpDxe/RedfishHttpDxe.h @@ -0,0 +1,38 @@ +/** @file + Definitions of RedfishHttpDxe + + Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef EDKII_REDFISH_HTTP_DXE_H_ +#define EDKII_REDFISH_HTTP_DXE_H_ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define REDFISH_HTTP_CACHE_LIST_SIZE 0x80 +#define REDFISH_ERROR_MSG_MAX 128 +#define REDFISH_HTTP_ERROR_REPORT "Redfish HTTP %a failure(0x%x): %a" +#define REDFISH_HTTP_CACHE_DEBUG DEBUG_MANAGEABILITY +#define REDFISH_HTTP_CACHE_DEBUG_DUMP DEBUG_MANAGEABILITY +#define REDFISH_HTTP_CACHE_DEBUG_REQUEST DEBUG_MANAGEABILITY + +#endif diff --git a/RedfishClientPkg/RedfishHttpDxe/RedfishHttpDxe.inf b/RedfishClientPkg/RedfishHttpDxe/RedfishHttpDxe.inf new file mode 100644 index 000000000..2221b64e0 --- /dev/null +++ b/RedfishClientPkg/RedfishHttpDxe/RedfishHttpDxe.inf @@ -0,0 +1,64 @@ +## @file +# RedfishHttpDxe is the DXE driver which provides +# EdkIIRedfishHttpProtocol to EDK2 Redfish Feature +# drivers for HTTP operation. +# +# Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x0001000b + BASE_NAME = RedfishHttpDxe + FILE_GUID = 9B9CB3B9-AC38-49A9-B62E-C42B7B464835 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = RedfishHttpEntryPoint + UNLOAD_IMAGE = RedfishHttpDriverUnload + +# +# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 RISCV64 +# + +[Sources] + RedfishHttpData.c + RedfishHttpData.h + RedfishHttpDxe.c + RedfishHttpDxe.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + NetworkPkg/NetworkPkg.dec + RedfishPkg/RedfishPkg.dec + RedfishClientPkg/RedfishClientPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + MemoryAllocationLib + PrintLib + RedfishLib + RedfishDebugLib + ReportStatusCodeLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UefiLib + +[Protocols] + gEdkIIRedfishHttpProtocolGuid ## PRODUCED + +[Pcd] + gEfiRedfishClientPkgTokenSpaceGuid.PcdHttpGetRetry + gEfiRedfishClientPkgTokenSpaceGuid.PcdHttpPutRetry + gEfiRedfishClientPkgTokenSpaceGuid.PcdHttpPatchRetry + gEfiRedfishClientPkgTokenSpaceGuid.PcdHttpPostRetry + gEfiRedfishClientPkgTokenSpaceGuid.PcdHttpDeleteRetry + gEfiRedfishClientPkgTokenSpaceGuid.PcdHttpRetryWaitInSecond + gEfiRedfishClientPkgTokenSpaceGuid.PcdHttpCacheDisabled + +[Depex] + TRUE