* [PATCH] RedfishPkg/RedfishRestExDxe: Implementation of EFI REST EX Protocol
@ 2020-12-07 6:54 Abner Chang
2020-12-10 3:08 ` Nickle Wang
0 siblings, 1 reply; 2+ messages in thread
From: Abner Chang @ 2020-12-07 6:54 UTC (permalink / raw)
To: devel
Cc: Jiaxin Wu, Siyuan Fu, Fan Wang, Jiewen Yao, Nickle Wang,
Peter O'Hanley
BZ#: 2908
https://bugzilla.tianocore.org/show_bug.cgi?id=2908
Implementation of EFI EX Protocol according to UEFI spec
2.8 Section 29.7.2 EFI REST EX Protocol.
This is the network stack based EFI REST EX protocol instance.
Signed-off-by: Jiaxin Wu <jiaxin.wu@intel.com>
Signed-off-by: Siyuan Fu <siyuan.fu@intel.com>
Signed-off-by: Fan Wang <fan.wang@intel.com>
Signed-off-by: Ting Ye <ting.ye@intel.com>
Signed-off-by: Abner Chang <abner.chang@hpe.com>
Cc: Jiaxin Wu <jiaxin.wu@intel.com>
Cc: Siyuan Fu <siyuan.fu@intel.com>
Cc: Fan Wang <fan.wang@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Nickle Wang <nickle.wang@hpe.com>
Cc: Peter O'Hanley <peter.ohanley@hpe.com>
---
RedfishPkg/Redfish.fdf.inc | 1 +
RedfishPkg/RedfishComponents.dsc.inc | 1 +
RedfishPkg/RedfishPkg.dsc | 4 +
RedfishPkg/RedfishRestExDxe/ComponentName.c | 222 +++++
.../RedfishRestExDxe/RedfishRestExDriver.c | 831 ++++++++++++++++++
.../RedfishRestExDxe/RedfishRestExDriver.h | 650 ++++++++++++++
.../RedfishRestExDxe/RedfishRestExDxe.inf | 63 ++
.../RedfishRestExDxe/RedfishRestExDxe.uni | 16 +
| 15 +
.../RedfishRestExDxe/RedfishRestExImpl.c | 157 ++++
.../RedfishRestExDxe/RedfishRestExInternal.h | 611 +++++++++++++
.../RedfishRestExDxe/RedfishRestExProtocol.c | 735 ++++++++++++++++
12 files changed, 3306 insertions(+)
create mode 100644 RedfishPkg/RedfishRestExDxe/ComponentName.c
create mode 100644 RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.c
create mode 100644 RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.h
create mode 100644 RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf
create mode 100644 RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.uni
create mode 100644 RedfishPkg/RedfishRestExDxe/RedfishRestExDxeExtra.uni
create mode 100644 RedfishPkg/RedfishRestExDxe/RedfishRestExImpl.c
create mode 100644 RedfishPkg/RedfishRestExDxe/RedfishRestExInternal.h
create mode 100644 RedfishPkg/RedfishRestExDxe/RedfishRestExProtocol.c
diff --git a/RedfishPkg/Redfish.fdf.inc b/RedfishPkg/Redfish.fdf.inc
index 19de479a80..429156aa78 100644
--- a/RedfishPkg/Redfish.fdf.inc
+++ b/RedfishPkg/Redfish.fdf.inc
@@ -13,4 +13,5 @@
!if $(REDFISH_ENABLE) == TRUE
INF RedfishPkg/RestJsonStructureDxe/RestJsonStructureDxe.inf
INF RedfishPkg/RedfishHostInterfaceDxe/RedfishHostInterfaceDxe.inf
+ INF RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf
!endif
diff --git a/RedfishPkg/RedfishComponents.dsc.inc b/RedfishPkg/RedfishComponents.dsc.inc
index ac1b57ed8f..3b9429db09 100644
--- a/RedfishPkg/RedfishComponents.dsc.inc
+++ b/RedfishPkg/RedfishComponents.dsc.inc
@@ -15,4 +15,5 @@
!if $(REDFISH_ENABLE) == TRUE
RedfishPkg/RestJsonStructureDxe/RestJsonStructureDxe.inf
RedfishPkg/RedfishHostInterfaceDxe/RedfishHostInterfaceDxe.inf
+ RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf
!endif
diff --git a/RedfishPkg/RedfishPkg.dsc b/RedfishPkg/RedfishPkg.dsc
index 94e7127bc6..c05e81af7b 100644
--- a/RedfishPkg/RedfishPkg.dsc
+++ b/RedfishPkg/RedfishPkg.dsc
@@ -32,6 +32,10 @@
DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
RedfishPlatformHostInterfaceLib|RedfishPkg/Library/PlatformHostInterfaceLibNull/PlatformHostInterfaceLibNull.inf
+ HttpLib|NetworkPkg/Library/DxeHttpLib/DxeHttpLib.inf
+ HttpIoLib|NetworkPkg/Library/DxeHttpIoLib/DxeHttpIoLib.inf
+ NetLib|NetworkPkg/Library/DxeNetLib/DxeNetLib.inf
+ DpcLib|NetworkPkg/Library/DxeDpcLib/DxeDpcLib.inf
[LibraryClasses.ARM, LibraryClasses.AARCH64]
#
diff --git a/RedfishPkg/RedfishRestExDxe/ComponentName.c b/RedfishPkg/RedfishRestExDxe/ComponentName.c
new file mode 100644
index 0000000000..3674178412
--- /dev/null
+++ b/RedfishPkg/RedfishRestExDxe/ComponentName.c
@@ -0,0 +1,222 @@
+/** @file
+ Implementation of EFI_COMPONENT_NAME_PROTOCOL and EFI_COMPONENT_NAME2_PROTOCOL
+ protocol.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Uefi.h>
+
+#include <Library/UefiLib.h>
+
+#include <Protocol/ComponentName.h>
+#include <Protocol/ComponentName2.h>
+
+//
+// EFI Component Name Functions
+//
+/**
+ Retrieves a Unicode string that is the user-readable name of the EFI Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] Language A pointer to a three-character ISO 639-2 language identifier.
+ This is the language of the driver name that that the caller
+ is requesting, and it must match one of the languages specified
+ in SupportedLanguages. The number of languages supported by a
+ driver is up to the driver writer.
+ @param[out] DriverName A pointer to the Unicode string to return. This Unicode string
+ is the name of the driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by This
+ and the language specified by Language was returned
+ in DriverName.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the
+ language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by an EFI Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of a controller that the driver specified by
+ This is managing. This handle specifies the controller
+ whose name is to be returned.
+ @param[in] ChildHandle The handle of the child controller to retrieve the name
+ of. This is an optional parameter that may be NULL. It
+ will be NULL for device drivers. It will also be NULL
+ for a bus drivers that wish to retrieve the name of the
+ bus controller. It will not be NULL for a bus driver
+ that wishes to retrieve the name of a child controller.
+ @param[in] Language A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the controller name
+ that the caller is requesting, and it must match one
+ of the languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up to the
+ driver writer.
+ @param[out] ControllerName A pointer to the Unicode string to return. This Unicode
+ string is the name of the controller specified by
+ ControllerHandle and ChildHandle in the language specified
+ by Language, from the point of view of the driver specified
+ by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user-readable name in the
+ language specified by Language for the driver
+ specified by This was returned in DriverName.
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently managing
+ the controller specified by ControllerHandle and
+ ChildHandle.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the
+ language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+///
+/// Component Name Protocol instance
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_COMPONENT_NAME_PROTOCOL gRedfishRestExComponentName = {
+ RedfishRestExComponentNameGetDriverName,
+ RedfishRestExComponentNameGetControllerName,
+ "eng"
+};
+
+///
+/// Component Name 2 Protocol instance
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_COMPONENT_NAME2_PROTOCOL gRedfishRestExComponentName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) RedfishRestExComponentNameGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) RedfishRestExComponentNameGetControllerName,
+ "en"
+};
+
+///
+/// Table of driver names
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_UNICODE_STRING_TABLE mRedfishRestExDriverNameTable[] = {
+ { "eng;en", (CHAR16 *)L"Redfish RestEx Network Service Driver" },
+ { NULL, NULL }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE *gRedfishRestExControllerNameTable = NULL;
+
+/**
+ Retrieves a Unicode string that is the user-readable name of the EFI Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] Language A pointer to a three-character ISO 639-2 language identifier.
+ This is the language of the driver name that that the caller
+ is requesting, and it must match one of the languages specified
+ in SupportedLanguages. The number of languages supported by a
+ driver is up to the driver writer.
+ @param[out] DriverName A pointer to the Unicode string to return. This Unicode string
+ is the name of the driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by This
+ and the language specified by Language was returned
+ in DriverName.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the
+ language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mRedfishRestExDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This == &gRedfishRestExComponentName)
+ );
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by an EFI Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of a controller that the driver specified by
+ This is managing. This handle specifies the controller
+ whose name is to be returned.
+ @param[in] ChildHandle The handle of the child controller to retrieve the name
+ of. This is an optional parameter that may be NULL. It
+ will be NULL for device drivers. It will also be NULL
+ for a bus drivers that wish to retrieve the name of the
+ bus controller. It will not be NULL for a bus driver
+ that wishes to retrieve the name of a child controller.
+ @param[in] Language A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the controller name
+ that the caller is requesting, and it must match one
+ of the languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up to the
+ driver writer.
+ @param[out] ControllerName A pointer to the Unicode string to return. This Unicode
+ string is the name of the controller specified by
+ ControllerHandle and ChildHandle in the language specified
+ by Language, from the point of view of the driver specified
+ by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user-readable name in the
+ language specified by Language for the driver
+ specified by This was returned in DriverName.
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently managing
+ the controller specified by ControllerHandle and
+ ChildHandle.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the
+ language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ return EFI_UNSUPPORTED;
+}
diff --git a/RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.c b/RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.c
new file mode 100644
index 0000000000..87327a8549
--- /dev/null
+++ b/RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.c
@@ -0,0 +1,831 @@
+/** @file
+ The driver binding and service binding protocol for Redfish RestExDxe driver.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include "RedfishRestExDriver.h"
+
+EFI_DRIVER_BINDING_PROTOCOL gRedfishRestExDriverBinding = {
+ RedfishRestExDriverBindingSupported,
+ RedfishRestExDriverBindingStart,
+ RedfishRestExDriverBindingStop,
+ REDFISH_RESTEX_DRIVER_VERSION,
+ NULL,
+ NULL
+};
+
+EFI_SERVICE_BINDING_PROTOCOL mRedfishRestExServiceBinding = {
+ RedfishRestExServiceBindingCreateChild,
+ RedfishRestExServiceBindingDestroyChild
+};
+
+/**
+ Callback function which provided by user to remove one node in NetDestroyLinkList process.
+
+ @param[in] Entry The entry to be removed.
+ @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
+
+ @retval EFI_SUCCESS The entry has been removed successfully.
+ @retval Others Fail to remove the entry.
+
+**/
+EFI_STATUS
+EFIAPI
+RestExDestroyChildEntryInHandleBuffer (
+ IN LIST_ENTRY *Entry,
+ IN VOID *Context
+ )
+{
+ RESTEX_INSTANCE *Instance;
+ EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
+ UINTN NumberOfChildren;
+ EFI_HANDLE *ChildHandleBuffer;
+
+ if (Entry == NULL || Context == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Instance = NET_LIST_USER_STRUCT_S (Entry, RESTEX_INSTANCE, Link, RESTEX_INSTANCE_SIGNATURE);
+ ServiceBinding = ((RESTEX_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ServiceBinding;
+ NumberOfChildren = ((RESTEX_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->NumberOfChildren;
+ ChildHandleBuffer = ((RESTEX_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ChildHandleBuffer;
+
+ if (!NetIsInHandleBuffer (Instance->ChildHandle, NumberOfChildren, ChildHandleBuffer)) {
+ return EFI_SUCCESS;
+ }
+
+ return ServiceBinding->DestroyChild (ServiceBinding, Instance->ChildHandle);
+}
+
+/**
+ Destroy the RestEx instance and recycle the resources.
+
+ @param[in] Instance The pointer to the RestEx instance.
+
+**/
+VOID
+RestExDestroyInstance (
+ IN RESTEX_INSTANCE *Instance
+ )
+{
+ HttpIoDestroyIo (&(Instance->HttpIo));
+
+ FreePool (Instance);
+}
+
+/**
+ Create the RestEx instance and initialize it.
+
+ @param[in] Service The pointer to the RestEx service.
+ @param[out] Instance The pointer to the RestEx instance.
+
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
+ @retval EFI_SUCCESS The RestEx instance is created.
+
+**/
+EFI_STATUS
+RestExCreateInstance (
+ IN RESTEX_SERVICE *Service,
+ OUT RESTEX_INSTANCE **Instance
+ )
+{
+ RESTEX_INSTANCE *RestExIns;
+ EFI_STATUS Status;
+
+ *Instance = NULL;
+ Status = EFI_SUCCESS;
+
+ RestExIns = AllocateZeroPool (sizeof (RESTEX_INSTANCE));
+ if (RestExIns == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ RestExIns->Signature = RESTEX_INSTANCE_SIGNATURE;
+ InitializeListHead (&RestExIns->Link);
+ RestExIns->InDestroy = FALSE;
+ RestExIns->Service = Service;
+
+ CopyMem (&RestExIns->RestEx, &mRedfishRestExProtocol, sizeof (RestExIns->RestEx));
+
+ //
+ // Create a HTTP_IO to access the HTTP service.
+ //
+ Status = HttpIoCreateIo (
+ RestExIns->Service->ImageHandle,
+ RestExIns->Service->ControllerHandle,
+ IP_VERSION_4,
+ NULL,
+ NULL,
+ NULL,
+ &(RestExIns->HttpIo)
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (RestExIns);
+ return Status;
+ }
+
+ *Instance = RestExIns;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Release all the resource used the RestEx service binding instance.
+
+ @param[in] RestExSb The RestEx service binding instance.
+
+**/
+VOID
+RestExDestroyService (
+ IN RESTEX_SERVICE *RestExSb
+ )
+{
+ if (RestExSb->HttpChildHandle != NULL) {
+ gBS->CloseProtocol (
+ RestExSb->HttpChildHandle,
+ &gEfiHttpProtocolGuid,
+ RestExSb->ImageHandle,
+ RestExSb->ControllerHandle
+ );
+
+ NetLibDestroyServiceChild (
+ RestExSb->ControllerHandle,
+ RestExSb->ImageHandle,
+ &gEfiHttpServiceBindingProtocolGuid,
+ RestExSb->HttpChildHandle
+ );
+
+ RestExSb->HttpChildHandle = NULL;
+ }
+
+ gBS->UninstallProtocolInterface (
+ RestExSb->ControllerHandle,
+ &gEfiCallerIdGuid,
+ &RestExSb->Id
+ );
+
+ FreePool (RestExSb);
+}
+
+/**
+ Check the NIC controller handle represents an in-band or out-of-band Redfish host
+ interface device. If not in-band, treat it as out-of-band interface device.
+
+ @param[in] Controller The NIC controller handle needs to be checked.
+
+ @return EFI_REST_EX_SERVICE_ACCESS_MODE of the device.
+
+**/
+EFI_REST_EX_SERVICE_ACCESS_MODE
+RestExServiceAccessMode (
+ IN EFI_HANDLE Controller
+ )
+{
+ //
+ // This is EFI REST EX driver instance to connect
+ // to Redfish service using HTTP in out of band.
+ //
+ if (FixedPcdGetBool (PcdRedfishRestExServiceAccessModeInBand)) {
+ return EfiRestExServiceInBandAccess;
+ } else {
+ return EfiRestExServiceOutOfBandAccess;
+ }
+}
+
+/**
+ Create then initialize a RestEx service binding instance.
+
+ @param[in] Controller The controller to install the RestEx service
+ binding on.
+ @param[in] Image The driver binding image of the RestEx driver.
+ @param[out] Service The variable to receive the created service
+ binding instance.
+
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the instance.
+ @retval EFI_SUCCESS The service instance is created for the controller.
+
+**/
+EFI_STATUS
+RestExCreateService (
+ IN EFI_HANDLE Controller,
+ IN EFI_HANDLE Image,
+ OUT RESTEX_SERVICE **Service
+ )
+{
+ EFI_STATUS Status;
+ RESTEX_SERVICE *RestExSb;
+
+ Status = EFI_SUCCESS;
+ RestExSb = NULL;
+
+ *Service = NULL;
+
+ RestExSb = AllocateZeroPool (sizeof (RESTEX_SERVICE));
+ if (RestExSb == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ RestExSb->Signature = RESTEX_SERVICE_SIGNATURE;
+
+ RestExSb->ServiceBinding = mRedfishRestExServiceBinding;
+
+ RestExSb->RestExChildrenNum = 0;
+ InitializeListHead (&RestExSb->RestExChildrenList);
+
+ RestExSb->ControllerHandle = Controller;
+ RestExSb->ImageHandle = Image;
+
+ RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.EfiRestExServiceInfoHeader.Length = sizeof (EFI_REST_EX_SERVICE_INFO);
+ RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.EfiRestExServiceInfoHeader.RestServiceInfoVer.Major = 1;
+ RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.EfiRestExServiceInfoHeader.RestServiceInfoVer.Minor = 0;
+ RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.RestServiceType = EfiRestExServiceRedfish;
+ RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.RestServiceAccessMode = RestExServiceAccessMode (Controller);
+ RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.RestExConfigType = EfiRestExConfigHttp;
+ RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.RestExConfigDataLength = sizeof (EFI_REST_EX_HTTP_CONFIG_DATA);
+
+ Status = gBS->InstallProtocolInterface (
+ &Controller,
+ &gEfiCallerIdGuid,
+ EFI_NATIVE_INTERFACE,
+ &RestExSb->Id
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (RestExSb);
+ RestExSb = NULL;
+ }
+
+ *Service = RestExSb;
+ return Status;
+}
+
+/**
+ This is the declaration of an EFI image entry point. This entry point is
+ the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
+ both device drivers and bus drivers.
+
+ @param[in] ImageHandle The firmware allocated handle for the UEFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval Others An unexpected error occurred.
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Install the RestEx Driver Binding Protocol.
+ //
+ Status = EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gRedfishRestExDriverBinding,
+ ImageHandle,
+ &gRedfishRestExComponentName,
+ &gRedfishRestExComponentName2
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return Status;
+}
+
+/**
+ Tests to see if this driver supports a given controller. If a child device is provided,
+ it further tests to see if this driver supports creating a handle for the specified child device.
+
+ This function checks to see if the driver specified by This supports the device specified by
+ ControllerHandle. Drivers will typically use the device path attached to
+ ControllerHandle and/or the services from the bus I/O abstraction attached to
+ ControllerHandle to determine if the driver supports ControllerHandle. This function
+ may be called many times during platform initialization. In order to reduce boot times, the tests
+ performed by this function must be very small, and take as little time as possible to execute. This
+ function must not change the state of any hardware devices, and this function must be aware that the
+ device specified by ControllerHandle may already be managed by the same driver or a
+ different driver. This function must match its calls to AllocatePages() with FreePages(),
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+ Because ControllerHandle may have been previously started by the same driver, if a protocol is
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required
+ to guarantee the state of ControllerHandle is not modified by this function.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For bus drivers, if this parameter is not NULL, then
+ the bus driver must determine if the bus controller specified
+ by ControllerHandle and the child controller specified
+ by RemainingDevicePath are both supported by this
+ bus driver.
+
+ @retval EFI_SUCCESS The device specified by ControllerHandle and
+ RemainingDevicePath is supported by the driver specified by This.
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by the driver
+ specified by This.
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by a different
+ driver or an application that requires exclusive access.
+ Currently not implemented.
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
+ RemainingDevicePath is not supported by the driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ )
+{
+
+ //
+ // Test for the HttpServiceBinding Protocol.
+ //
+ return gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiHttpServiceBindingProtocolGuid,
+ NULL,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+
+}
+
+/**
+ Starts a device controller or a bus controller.
+
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().
+ As a result, much of the error checking on the parameters to Start() has been moved into this
+ common boot service. It is legal to call Start() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE.
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+ EFI_DEVICE_PATH_PROTOCOL.
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to start. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For a bus driver, if this parameter is NULL, then handles
+ for all the children of Controller are created by this driver.
+ If this parameter is not NULL and the first Device Path Node is
+ not the End of Device Path Node, then only the handle for the
+ child device specified by the first Device Path Node of
+ RemainingDevicePath is created by this driver.
+ If the first Device Path Node of RemainingDevicePath is
+ the End of Device Path Node, no child handle is created by this
+ driver.
+
+ @retval EFI_SUCCESS The device was started.
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval Others The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ )
+{
+ RESTEX_SERVICE *RestExSb;
+ EFI_STATUS Status;
+ UINT32 *Id;
+ VOID *Interface;
+
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiCallerIdGuid,
+ (VOID **) &Id,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ Status = RestExCreateService (ControllerHandle, This->DriverBindingHandle, &RestExSb);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ASSERT (RestExSb != NULL);
+
+ //
+ // Create a Http child instance, but do not configure it.
+ // This will establish the parent-child relationship.
+ //
+ Status = NetLibCreateServiceChild (
+ ControllerHandle,
+ This->DriverBindingHandle,
+ &gEfiHttpServiceBindingProtocolGuid,
+ &RestExSb->HttpChildHandle
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ Status = gBS->OpenProtocol (
+ RestExSb->HttpChildHandle,
+ &gEfiHttpProtocolGuid,
+ &Interface,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ //
+ // Install the RestEx ServiceBinding Protocol onto ControllerHandle.
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ControllerHandle,
+ &gEfiRestExServiceBindingProtocolGuid,
+ &RestExSb->ServiceBinding,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ return EFI_SUCCESS;
+
+ON_ERROR:
+ RestExDestroyService (RestExSb);
+
+ return Status;
+}
+
+/**
+ Stops a device controller or a bus controller.
+
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+ As a result, much of the error checking on the parameters to Stop() has been moved
+ into this common boot service. It is legal to call Stop() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+ same driver's Start() function.
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+ Start() function, and the Start() function must have called OpenProtocol() on
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must
+ support a bus specific I/O protocol for the driver
+ to use to stop the device.
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
+ if NumberOfChildren is 0.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
+ )
+{
+ EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
+ RESTEX_SERVICE *RestExSb;
+ EFI_HANDLE NicHandle;
+ EFI_STATUS Status;
+ LIST_ENTRY *List;
+ RESTEX_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;
+
+ //
+ // RestEx driver opens HTTP child, So, Controller is a HTTP
+ // child handle. Locate the Nic handle first. Then get the
+ // RestEx private data back.
+ //
+ NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiHttpProtocolGuid);
+ if (NicHandle == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ Status = gBS->OpenProtocol (
+ NicHandle,
+ &gEfiRestExServiceBindingProtocolGuid,
+ (VOID **) &ServiceBinding,
+ This->DriverBindingHandle,
+ NicHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ RestExSb = RESTEX_SERVICE_FROM_THIS (ServiceBinding);
+
+ if (!IsListEmpty (&RestExSb->RestExChildrenList)) {
+ //
+ // Destroy the RestEx child instance in ChildHandleBuffer.
+ //
+ List = &RestExSb->RestExChildrenList;
+ Context.ServiceBinding = ServiceBinding;
+ Context.NumberOfChildren = NumberOfChildren;
+ Context.ChildHandleBuffer = ChildHandleBuffer;
+ Status = NetDestroyLinkList (
+ List,
+ RestExDestroyChildEntryInHandleBuffer,
+ &Context,
+ NULL
+ );
+ }
+
+ if (NumberOfChildren == 0 && IsListEmpty (&RestExSb->RestExChildrenList)) {
+ gBS->UninstallProtocolInterface (
+ NicHandle,
+ &gEfiRestExServiceBindingProtocolGuid,
+ ServiceBinding
+ );
+
+ RestExDestroyService (RestExSb);
+
+ if (gRedfishRestExControllerNameTable != NULL) {
+ FreeUnicodeStringTable (gRedfishRestExControllerNameTable);
+ gRedfishRestExControllerNameTable = NULL;
+ }
+
+ Status = EFI_SUCCESS;
+ }
+
+ return Status;
+}
+
+/**
+ Creates a child handle and installs a protocol.
+
+ The CreateChild() function installs a protocol on ChildHandle.
+ If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
+ If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
+
+ @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+ @param[in] ChildHandle Pointer to the handle of the child to create. If it is NULL,
+ then a new handle is created. If it is a pointer to an existing UEFI handle,
+ then the protocol is added to the existing UEFI handle.
+
+ @retval EFI_SUCCES The protocol was added to ChildHandle.
+ @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create
+ the child
+ @retval other The child handle was not created
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExServiceBindingCreateChild (
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE *ChildHandle
+ )
+{
+ RESTEX_SERVICE *RestExSb;
+ RESTEX_INSTANCE *Instance;
+ EFI_STATUS Status;
+ EFI_TPL OldTpl;
+ VOID *Http;
+
+ if ((This == NULL) || (ChildHandle == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ RestExSb = RESTEX_SERVICE_FROM_THIS (This);
+
+ Status = RestExCreateInstance (RestExSb, &Instance);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ ASSERT (Instance != NULL);
+
+ //
+ // Install the RestEx protocol onto ChildHandle
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ ChildHandle,
+ &gEfiRestExProtocolGuid,
+ &Instance->RestEx,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ Instance->ChildHandle = *ChildHandle;
+
+ //
+ // Open the Http protocol BY_CHILD.
+ //
+ Status = gBS->OpenProtocol (
+ RestExSb->HttpChildHandle,
+ &gEfiHttpProtocolGuid,
+ (VOID **) &Http,
+ gRedfishRestExDriverBinding.DriverBindingHandle,
+ Instance->ChildHandle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->UninstallMultipleProtocolInterfaces (
+ Instance->ChildHandle,
+ &gEfiRestExProtocolGuid,
+ &Instance->RestEx,
+ NULL
+ );
+
+ goto ON_ERROR;
+ }
+
+ //
+ // Open the Http protocol by child.
+ //
+ Status = gBS->OpenProtocol (
+ Instance->HttpIo.Handle,
+ &gEfiHttpProtocolGuid,
+ (VOID **) &Http,
+ gRedfishRestExDriverBinding.DriverBindingHandle,
+ Instance->ChildHandle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // Close the Http protocol.
+ //
+ gBS->CloseProtocol (
+ RestExSb->HttpChildHandle,
+ &gEfiHttpProtocolGuid,
+ gRedfishRestExDriverBinding.DriverBindingHandle,
+ ChildHandle
+ );
+
+ gBS->UninstallMultipleProtocolInterfaces (
+ Instance->ChildHandle,
+ &gEfiRestExProtocolGuid,
+ &Instance->RestEx,
+ NULL
+ );
+
+ goto ON_ERROR;
+ }
+
+ //
+ // Add it to the parent's child list.
+ //
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ InsertTailList (&RestExSb->RestExChildrenList, &Instance->Link);
+ RestExSb->RestExChildrenNum++;
+
+ gBS->RestoreTPL (OldTpl);
+
+ return EFI_SUCCESS;
+
+ON_ERROR:
+
+ RestExDestroyInstance (Instance);
+ return Status;
+}
+
+/**
+ Destroys a child handle with a protocol installed on it.
+
+ The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
+ that was installed by CreateChild() from ChildHandle. If the removed protocol is the
+ last protocol on ChildHandle, then ChildHandle is destroyed.
+
+ @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+ @param[in] ChildHandle Handle of the child to destroy
+
+ @retval EFI_SUCCES The protocol was removed from ChildHandle.
+ @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
+ @retval EFI_INVALID_PARAMETER Child handle is NULL.
+ @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
+ because its services are being used.
+ @retval other The child handle was not destroyed
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExServiceBindingDestroyChild (
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ChildHandle
+ )
+{
+ RESTEX_SERVICE *RestExSb;
+ RESTEX_INSTANCE *Instance;
+
+ EFI_REST_EX_PROTOCOL *RestEx;
+ EFI_STATUS Status;
+ EFI_TPL OldTpl;
+
+ if ((This == NULL) || (ChildHandle == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Retrieve the private context data structures
+ //
+ Status = gBS->OpenProtocol (
+ ChildHandle,
+ &gEfiRestExProtocolGuid,
+ (VOID **) &RestEx,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Instance = RESTEX_INSTANCE_FROM_THIS (RestEx);
+ RestExSb = RESTEX_SERVICE_FROM_THIS (This);
+
+ if (Instance->Service != RestExSb) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Instance->InDestroy) {
+ return EFI_SUCCESS;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ Instance->InDestroy = TRUE;
+
+ //
+ // Close the Http protocol.
+ //
+ gBS->CloseProtocol (
+ RestExSb->HttpChildHandle,
+ &gEfiHttpProtocolGuid,
+ gRedfishRestExDriverBinding.DriverBindingHandle,
+ ChildHandle
+ );
+
+ gBS->CloseProtocol (
+ Instance->HttpIo.Handle,
+ &gEfiHttpProtocolGuid,
+ gRedfishRestExDriverBinding.DriverBindingHandle,
+ ChildHandle
+ );
+
+
+ gBS->RestoreTPL (OldTpl);
+
+ //
+ // Uninstall the RestEx protocol first to enable a top down destruction.
+ //
+ Status = gBS->UninstallProtocolInterface (
+ ChildHandle,
+ &gEfiRestExProtocolGuid,
+ RestEx
+ );
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ if (EFI_ERROR (Status)) {
+ Instance->InDestroy = FALSE;
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+ }
+
+ RemoveEntryList (&Instance->Link);
+ RestExSb->RestExChildrenNum--;
+
+ gBS->RestoreTPL (OldTpl);
+
+ RestExDestroyInstance (Instance);
+ return EFI_SUCCESS;
+}
+
diff --git a/RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.h b/RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.h
new file mode 100644
index 0000000000..6743ced23c
--- /dev/null
+++ b/RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.h
@@ -0,0 +1,650 @@
+/** @file
+ RedfishRestExDxe support functions definitions.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef EFI_REDFISH_RESTEX_DRIVER_H_
+#define EFI_REDFISH_RESTEX_DRIVER_H_
+
+///
+/// Libraries classes
+///
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HttpIoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/NetLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+
+///
+/// UEFI Driver Model Protocols
+///
+#include <Protocol/DriverBinding.h>
+#include <Protocol/RestEx.h>
+#include <Protocol/ServiceBinding.h>
+
+///
+/// Protocol instances
+///
+extern EFI_COMPONENT_NAME_PROTOCOL gRedfishRestExComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gRedfishRestExComponentName2;
+extern EFI_UNICODE_STRING_TABLE *gRedfishRestExControllerNameTable;
+
+extern EFI_DRIVER_BINDING_PROTOCOL gRedfishRestExDriverBinding;
+extern EFI_SERVICE_BINDING_PROTOCOL mRedfishRestExServiceBinding;
+extern EFI_REST_EX_PROTOCOL mRedfishRestExProtocol;
+///
+/// RestEx service block
+///
+typedef struct _RESTEX_SERVICE RESTEX_SERVICE;
+
+///
+/// RestEx instance block
+///
+typedef struct _RESTEX_INSTANCE RESTEX_INSTANCE;
+
+///
+/// Driver Version
+///
+#define REDFISH_RESTEX_DRIVER_VERSION 0x0100
+
+#define RESTEX_SERVICE_SIGNATURE SIGNATURE_32 ('R', 'E', 'S', 'S')
+#define RESTEX_INSTANCE_SIGNATURE SIGNATURE_32 ('R', 'E', 'I', 'S')
+
+#define RESTEX_SERVICE_FROM_THIS(a) \
+ CR (a, RESTEX_SERVICE, ServiceBinding, RESTEX_SERVICE_SIGNATURE)
+
+#define RESTEX_INSTANCE_FROM_THIS(a) \
+ CR (a, RESTEX_INSTANCE, RestEx, RESTEX_INSTANCE_SIGNATURE)
+
+
+#define RESTEX_STATE_UNCONFIGED 0
+#define RESTEX_STATE_CONFIGED 1
+
+struct _RESTEX_SERVICE {
+ UINT32 Signature;
+ EFI_SERVICE_BINDING_PROTOCOL ServiceBinding;
+
+ UINT16 RestExChildrenNum;
+ LIST_ENTRY RestExChildrenList;
+
+ EFI_HANDLE ControllerHandle;
+ EFI_HANDLE ImageHandle;
+
+ //
+ // Use to establish the parent-child relationship.
+ //
+ EFI_HANDLE HttpChildHandle;
+
+ UINT32 Id;
+
+ EFI_REST_EX_SERVICE_INFO RestExServiceInfo;
+};
+
+#define RESTEX_INSTANCE_FLAGS_TLS_RETRY 0x00000001
+#define RESTEX_INSTANCE_FLAGS_TCP_ERROR_RETRY 0x00000002
+
+struct _RESTEX_INSTANCE {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+
+ EFI_REST_EX_PROTOCOL RestEx;
+
+ INTN State;
+ BOOLEAN InDestroy;
+
+ RESTEX_SERVICE *Service;
+ EFI_HANDLE ChildHandle;
+
+ EFI_REST_EX_CONFIG_DATA ConfigData;
+
+ //
+ // HTTP_IO to access the HTTP service
+ //
+ HTTP_IO HttpIo;
+
+ UINT32 Flags;
+};
+
+typedef struct {
+ EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
+ UINTN NumberOfChildren;
+ EFI_HANDLE *ChildHandleBuffer;
+} RESTEX_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT;
+
+/**
+ Provides a simple HTTP-like interface to send and receive resources from a REST service.
+
+ The SendReceive() function sends an HTTP request to this REST service, and returns a
+ response when the data is retrieved from the service. RequestMessage contains the HTTP
+ request to the REST resource identified by RequestMessage.Request.Url. The
+ ResponseMessage is the returned HTTP response for that request, including any HTTP
+ status.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[in] RequestMessage Pointer to the HTTP request data for this resource
+ @param[out] ResponseMessage Pointer to the HTTP response data obtained for this requested.
+
+ @retval EFI_SUCCESS operation succeeded.
+ @retval EFI_INVALID_PARAMETER This, RequestMessage, or ResponseMessage are NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExSendReceive (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage,
+ OUT EFI_HTTP_MESSAGE *ResponseMessage
+ );
+
+/**
+ Obtain the current time from this REST service instance.
+
+ The GetServiceTime() function is an optional interface to obtain the current time from
+ this REST service instance. If this REST service does not support to retrieve the time,
+ this function returns EFI_UNSUPPORTED. This function must returns EFI_UNSUPPORTED if
+ EFI_REST_EX_SERVICE_TYPE returned in EFI_REST_EX_SERVICE_INFO from GetService() is
+ EFI_REST_EX_SERVICE_UNSPECIFIC.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[out] Time A pointer to storage to receive a snapshot of the current time of
+ the REST service.
+
+ @retval EFI_SUCCESS operation succeeded.
+ @retval EFI_INVALID_PARAMETER This or Time are NULL.
+ @retval EFI_UNSUPPORTED The RESTful service does not support returning the time.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must
+ be executed and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExGetServiceTime (
+ IN EFI_REST_EX_PROTOCOL *This,
+ OUT EFI_TIME *Time
+ );
+
+/**
+ This function returns the information of REST service provided by this EFI REST EX driver instance.
+
+ The information such as the type of REST service and the access mode of REST EX driver instance
+ (In-band or Out-of-band) are described in EFI_REST_EX_SERVICE_INFO structure. For the vendor-specific
+ REST service, vendor-specific REST service information is returned in VendorSpecifcData.
+ REST EX driver designer is well know what REST service this REST EX driver instance intends to
+ communicate with. The designer also well know this driver instance is used to talk to BMC through
+ specific platform mechanism or talk to REST server through UEFI HTTP protocol. REST EX driver is
+ responsible to fill up the correct information in EFI_REST_EX_SERVICE_INFO. EFI_REST_EX_SERVICE_INFO
+ is referred by EFI REST clients to pickup the proper EFI REST EX driver instance to get and set resource.
+ GetService() is a basic and mandatory function which must be able to use even Configure() is not invoked
+ in previously.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[out] RestExServiceInfo Pointer to receive a pointer to EFI_REST_EX_SERVICE_INFO structure. The
+ format of EFI_REST_EX_SERVICE_INFO is version controlled for the future
+ extension. The version of EFI_REST_EX_SERVICE_INFO structure is returned
+ in the header within this structure. EFI REST client refers to the correct
+ format of structure according to the version number. The pointer to
+ EFI_REST_EX_SERVICE_INFO is a memory block allocated by EFI REST EX driver
+ instance. That is caller's responsibility to free this memory when this
+ structure is no longer needed. Refer to Related Definitions below for the
+ definitions of EFI_REST_EX_SERVICE_INFO structure.
+
+ @retval EFI_SUCCESS EFI_REST_EX_SERVICE_INFO is returned in RestExServiceInfo. This function
+ is not supported in this REST EX Protocol driver instance.
+ @retval EFI_UNSUPPORTED This function is not supported in this REST EX Protocol driver instance.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExGetService (
+ IN EFI_REST_EX_PROTOCOL *This,
+ OUT EFI_REST_EX_SERVICE_INFO **RestExServiceInfo
+ );
+
+/**
+ This function returns operational configuration of current EFI REST EX child instance.
+
+ This function returns the current configuration of EFI REST EX child instance. The format of
+ operational configuration depends on the implementation of EFI REST EX driver instance. For
+ example, HTTP-aware EFI REST EX driver instance uses EFI HTTP protocol as the undying protocol
+ to communicate with REST service. In this case, the type of configuration is
+ EFI_REST_EX_CONFIG_TYPE_HTTP returned from GetService(). EFI_HTTP_CONFIG_DATA is used as EFI REST
+ EX configuration format and returned to EFI REST client. User has to type cast RestExConfigData
+ to EFI_HTTP_CONFIG_DATA. For those non HTTP-aware REST EX driver instances, the type of configuration
+ is EFI_REST_EX_CONFIG_TYPE_UNSPECIFIC returned from GetService(). In this case, the format of
+ returning data could be non industrial. Instead, the format of configuration data is system/platform
+ specific definition such as BMC mechanism used in EFI REST EX driver instance. EFI REST client and
+ EFI REST EX driver instance have to refer to the specific system /platform spec which is out of UEFI scope.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[out] RestExConfigData Pointer to receive a pointer to EFI_REST_EX_CONFIG_DATA.
+ The memory allocated for configuration data should be freed
+ by caller. See Related Definitions for the details.
+
+ @retval EFI_SUCCESS EFI_REST_EX_CONFIG_DATA is returned in successfully.
+ @retval EFI_UNSUPPORTED This function is not supported in this REST EX Protocol driver instance.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must be
+ executed and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExGetModeData (
+ IN EFI_REST_EX_PROTOCOL *This,
+ OUT EFI_REST_EX_CONFIG_DATA *RestExConfigData
+ );
+
+/**
+ This function is used to configure EFI REST EX child instance.
+
+ This function is used to configure the setting of underlying protocol of REST EX child
+ instance. The type of configuration is according to the implementation of EFI REST EX
+ driver instance. For example, HTTP-aware EFI REST EX driver instance uses EFI HTTP protocol
+ as the undying protocol to communicate with REST service. The type of configuration is
+ EFI_REST_EX_CONFIG_TYPE_HTTP and RestExConfigData is the same format with EFI_HTTP_CONFIG_DATA.
+ Akin to HTTP configuration, REST EX child instance can be configure to use different HTTP
+ local access point for the data transmission. Multiple REST clients may use different
+ configuration of HTTP to distinguish themselves, such as to use the different TCP port.
+ For those non HTTP-aware REST EX driver instance, the type of configuration is
+ EFI_REST_EX_CONFIG_TYPE_UNSPECIFIC. RestExConfigData refers to the non industrial standard.
+ Instead, the format of configuration data is system/platform specific definition such as BMC.
+ In this case, EFI REST client and EFI REST EX driver instance have to refer to the specific
+ system/platform spec which is out of the UEFI scope. Besides GetService()function, no other
+ EFI REST EX functions can be executed by this instance until Configure()is executed and returns
+ successfully. All other functions must returns EFI_NOT_READY if this instance is not configured
+ yet. Set RestExConfigData to NULL means to put EFI REST EX child instance into the unconfigured
+ state.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[in] RestExConfigData Pointer to EFI_REST_EX_CONFIG_DATA. See Related Definitions in
+ GetModeData() protocol interface.
+
+ @retval EFI_SUCCESS EFI_REST_EX_CONFIG_DATA is set in successfully.
+ @retval EFI_DEVICE_ERROR Configuration for this REST EX child instance is failed with the given
+ EFI_REST_EX_CONFIG_DATA.
+ @retval EFI_UNSUPPORTED This function is not supported in this REST EX Protocol driver instance.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExConfigure (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_REST_EX_CONFIG_DATA RestExConfigData
+ );
+
+/**
+ This function sends REST request to REST service and signal caller's event asynchronously when
+ the final response is received by REST EX Protocol driver instance.
+
+ The essential design of this function is to handle asynchronous send/receive implicitly according
+ to REST service asynchronous request mechanism. Caller will get the notification once the response
+ is returned from REST service.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[in] RequestMessage This is the HTTP request message sent to REST service. Set RequestMessage
+ to NULL to cancel the previous asynchronous request associated with the
+ corresponding RestExToken. See descriptions for the details.
+ @param[in] RestExToken REST EX token which REST EX Protocol instance uses to notify REST client
+ the status of response of asynchronous REST request. See related definition
+ of EFI_REST_EX_TOKEN.
+ @param[in] TimeOutInMilliSeconds The pointer to the timeout in milliseconds which REST EX Protocol driver
+ instance refers as the duration to drop asynchronous REST request. NULL
+ pointer means no timeout for this REST request. REST EX Protocol driver
+ signals caller's event with EFI_STATUS set to EFI_TIMEOUT in RestExToken
+ if REST EX Protocol can't get the response from REST service within
+ TimeOutInMilliSeconds.
+
+ @retval EFI_SUCCESS Asynchronous REST request is established.
+ @retval EFI_UNSUPPORTED This REST EX Protocol driver instance doesn't support asynchronous request.
+ @retval EFI_TIMEOUT Asynchronous REST request is not established and timeout is expired.
+ @retval EFI_ABORT Previous asynchronous REST request has been canceled.
+ @retval EFI_DEVICE_ERROR Otherwise, returns EFI_DEVICE_ERROR for other errors according to HTTP Status Code.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must be executed
+ and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExAyncSendReceive (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage OPTIONAL,
+ IN EFI_REST_EX_TOKEN *RestExToken,
+ IN UINTN *TimeOutInMilliSeconds OPTIONAL
+ );
+
+/**
+ This function sends REST request to a REST Event service and signals caller's event
+ token asynchronously when the URI resource change event is received by REST EX
+ Protocol driver instance.
+
+ The essential design of this function is to monitor event implicitly according to
+ REST service event service mechanism. Caller will get the notification if certain
+ resource is changed.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[in] RequestMessage This is the HTTP request message sent to REST service. Set RequestMessage
+ to NULL to cancel the previous event service associated with the corresponding
+ RestExToken. See descriptions for the details.
+ @param[in] RestExToken REST EX token which REST EX Protocol driver instance uses to notify REST client
+ the URI resource which monitored by REST client has been changed. See the related
+ definition of EFI_REST_EX_TOKEN in EFI_REST_EX_PROTOCOL.AsyncSendReceive().
+
+ @retval EFI_SUCCESS Asynchronous REST request is established.
+ @retval EFI_UNSUPPORTED This REST EX Protocol driver instance doesn't support asynchronous request.
+ @retval EFI_ABORT Previous asynchronous REST request has been canceled or event subscription has been
+ delete from service.
+ @retval EFI_DEVICE_ERROR Otherwise, returns EFI_DEVICE_ERROR for other errors according to HTTP Status Code.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must be executed
+ and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExEventService (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage OPTIONAL,
+ IN EFI_REST_EX_TOKEN *RestExToken
+ );
+/**
+ Create a new TLS session becuase the previous on is closed.
+ status.
+
+ @param[in] Instance Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @retval EFI_SUCCESS operation succeeded.
+ @retval EFI Errors Other errors.
+
+**/
+EFI_STATUS
+ResetHttpTslSession (
+ IN RESTEX_INSTANCE *Instance
+);
+
+
+/**
+ Callback function which provided by user to remove one node in NetDestroyLinkList process.
+
+ @param[in] Entry The entry to be removed.
+ @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
+
+ @retval EFI_SUCCESS The entry has been removed successfully.
+ @retval Others Fail to remove the entry.
+
+**/
+EFI_STATUS
+EFIAPI
+RestExDestroyChildEntryInHandleBuffer (
+ IN LIST_ENTRY *Entry,
+ IN VOID *Context
+ );
+
+/**
+ Destroy the RestEx instance and recycle the resources.
+
+ @param[in] Instance The pointer to the RestEx instance.
+
+**/
+VOID
+RestExDestroyInstance (
+ IN RESTEX_INSTANCE *Instance
+ );
+
+/**
+ Create the RestEx instance and initialize it.
+
+ @param[in] Service The pointer to the RestEx service.
+ @param[out] Instance The pointer to the RestEx instance.
+
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
+ @retval EFI_SUCCESS The RestEx instance is created.
+
+**/
+EFI_STATUS
+RestExCreateInstance (
+ IN RESTEX_SERVICE *Service,
+ OUT RESTEX_INSTANCE **Instance
+ );
+
+
+/**
+ Release all the resource used the RestEx service binding instance.
+
+ @param RestExSb The RestEx service binding instance.
+
+**/
+VOID
+RestExDestroyService (
+ IN RESTEX_SERVICE *RestExSb
+ );
+
+/**
+ Create then initialize a RestEx service binding instance.
+
+ @param[in] Controller The controller to install the RestEx service
+ binding on.
+ @param[in] Image The driver binding image of the RestEx driver.
+ @param[out] Service The variable to receive the created service
+ binding instance.
+
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the instance.
+ @retval EFI_SUCCESS The service instance is created for the controller.
+
+**/
+EFI_STATUS
+RestExCreateService (
+ IN EFI_HANDLE Controller,
+ IN EFI_HANDLE Image,
+ OUT RESTEX_SERVICE **Service
+ );
+
+/**
+ This is the declaration of an EFI image entry point. This entry point is
+ the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
+ both device drivers and bus drivers.
+
+ @param[in] ImageHandle The firmware allocated handle for the UEFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval Others An unexpected error occurred.
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Tests to see if this driver supports a given controller. If a child device is provided,
+ it further tests to see if this driver supports creating a handle for the specified child device.
+
+ This function checks to see if the driver specified by This supports the device specified by
+ ControllerHandle. Drivers will typically use the device path attached to
+ ControllerHandle and/or the services from the bus I/O abstraction attached to
+ ControllerHandle to determine if the driver supports ControllerHandle. This function
+ may be called many times during platform initialization. In order to reduce boot times, the tests
+ performed by this function must be very small, and take as little time as possible to execute. This
+ function must not change the state of any hardware devices, and this function must be aware that the
+ device specified by ControllerHandle may already be managed by the same driver or a
+ different driver. This function must match its calls to AllocatePages() with FreePages(),
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+ Because ControllerHandle may have been previously started by the same driver, if a protocol is
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required
+ to guarantee the state of ControllerHandle is not modified by this function.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For bus drivers, if this parameter is not NULL, then
+ the bus driver must determine if the bus controller specified
+ by ControllerHandle and the child controller specified
+ by RemainingDevicePath are both supported by this
+ bus driver.
+
+ @retval EFI_SUCCESS The device specified by ControllerHandle and
+ RemainingDevicePath is supported by the driver specified by This.
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by the driver
+ specified by This.
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by a different
+ driver or an application that requires exclusive access.
+ Currently not implemented.
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
+ RemainingDevicePath is not supported by the driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ );
+
+/**
+ Starts a device controller or a bus controller.
+
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().
+ As a result, much of the error checking on the parameters to Start() has been moved into this
+ common boot service. It is legal to call Start() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE.
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+ EFI_DEVICE_PATH_PROTOCOL.
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to start. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For a bus driver, if this parameter is NULL, then handles
+ for all the children of Controller are created by this driver.
+ If this parameter is not NULL and the first Device Path Node is
+ not the End of Device Path Node, then only the handle for the
+ child device specified by the first Device Path Node of
+ RemainingDevicePath is created by this driver.
+ If the first Device Path Node of RemainingDevicePath is
+ the End of Device Path Node, no child handle is created by this
+ driver.
+
+ @retval EFI_SUCCESS The device was started.
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval Others The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ );
+
+/**
+ Stops a device controller or a bus controller.
+
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+ As a result, much of the error checking on the parameters to Stop() has been moved
+ into this common boot service. It is legal to call Stop() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+ same driver's Start() function.
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+ Start() function, and the Start() function must have called OpenProtocol() on
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must
+ support a bus specific I/O protocol for the driver
+ to use to stop the device.
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
+ if NumberOfChildren is 0.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
+ );
+
+/**
+ Creates a child handle and installs a protocol.
+
+ The CreateChild() function installs a protocol on ChildHandle.
+ If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
+ If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
+
+ @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+ @param[in] ChildHandle Pointer to the handle of the child to create. If it is NULL,
+ then a new handle is created. If it is a pointer to an existing UEFI handle,
+ then the protocol is added to the existing UEFI handle.
+
+ @retval EFI_SUCCES The protocol was added to ChildHandle.
+ @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create
+ the child
+ @retval other The child handle was not created
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExServiceBindingCreateChild (
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE *ChildHandle
+ );
+
+/**
+ Destroys a child handle with a protocol installed on it.
+
+ The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
+ that was installed by CreateChild() from ChildHandle. If the removed protocol is the
+ last protocol on ChildHandle, then ChildHandle is destroyed.
+
+ @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+ @param[in] ChildHandle Handle of the child to destroy
+
+ @retval EFI_SUCCES The protocol was removed from ChildHandle.
+ @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
+ @retval EFI_INVALID_PARAMETER Child handle is NULL.
+ @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
+ because its services are being used.
+ @retval other The child handle was not destroyed
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExServiceBindingDestroyChild (
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ChildHandle
+ );
+#endif
diff --git a/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf b/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf
new file mode 100644
index 0000000000..75437b086a
--- /dev/null
+++ b/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf
@@ -0,0 +1,63 @@
+## @file
+# Implementation of Redfish EFI_REST_EX_PROTOCOL interfaces.
+#
+# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001b
+ BASE_NAME = RedfishRestExDxe
+ FILE_GUID = B64702DA-E6B5-43c8-8CE8-D253071E9D6C
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = RedfishRestExDriverEntryPoint
+ UNLOAD_IMAGE = NetLibDefaultUnload
+ MODULE_UNI_FILE = RedfishRestExDxe.uni
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ NetworkPkg/NetworkPkg.dec
+ RedfishPkg/RedfishPkg.dec
+
+[Sources]
+ ComponentName.c
+ RedfishRestExDriver.c
+ RedfishRestExDriver.h
+ RedfishRestExImpl.c
+ RedfishRestExProtocol.c
+ RedfishRestExInternal.h
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ DevicePathLib
+ DpcLib
+ HttpLib
+ HttpIoLib
+ PrintLib
+ MemoryAllocationLib
+ NetLib
+ UefiLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiRuntimeServicesTableLib
+
+[Protocols]
+ gEfiRestExServiceBindingProtocolGuid ## BY_START
+ gEfiRestExProtocolGuid ## BY_START
+ gEfiHttpServiceBindingProtocolGuid ## TO_START
+ gEfiHttpProtocolGuid ## TO_START
+ gEfiDevicePathProtocolGuid ## TO_START
+
+[Pcd]
+ gEfiRedfishPkgTokenSpaceGuid.PcdRedfishRestExServiceAccessModeInBand ## CONSUMES
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ RedfishRestExDxeExtra.uni
+
diff --git a/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.uni b/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.uni
new file mode 100644
index 0000000000..afa0c142a9
--- /dev/null
+++ b/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.uni
@@ -0,0 +1,16 @@
+// /** @file
+// Redfish UEFI RESTEX DXE Driver.
+//
+// This driver provides Redfish UEFI RESTEX protocols.
+//
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+// (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_MODULE_ABSTRACT #language en-US "UEFI Redfish RESTEX service"
+
+#string STR_MODULE_DESCRIPTION #language en-US "This driver provides Redfish EFI RESTEX Protocol and Redfish EFI RESREX Service Binding Protocol."
+
--git a/RedfishPkg/RedfishRestExDxe/RedfishRestExDxeExtra.uni b/RedfishPkg/RedfishRestExDxe/RedfishRestExDxeExtra.uni
new file mode 100644
index 0000000000..a8ecf8aede
--- /dev/null
+++ b/RedfishPkg/RedfishRestExDxe/RedfishRestExDxeExtra.uni
@@ -0,0 +1,15 @@
+// /** @file
+// RestExDxe Localized Strings and Content
+//
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+// (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"Redfish UEFI RESTEX DXE"
+
+
diff --git a/RedfishPkg/RedfishRestExDxe/RedfishRestExImpl.c b/RedfishPkg/RedfishRestExDxe/RedfishRestExImpl.c
new file mode 100644
index 0000000000..006b64adc0
--- /dev/null
+++ b/RedfishPkg/RedfishRestExDxe/RedfishRestExImpl.c
@@ -0,0 +1,157 @@
+/** @file
+ RestExDxe support functions implementation.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Uefi.h>
+#include "RedfishRestExInternal.h"
+
+/**
+ Create a new TLS session becuase the previous on is closed.
+ status.
+
+ @param[in] Instance Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @retval EFI_SUCCESS operation succeeded.
+ @retval EFI_ERROR Other errors.
+
+**/
+EFI_STATUS
+ResetHttpTslSession (
+ IN RESTEX_INSTANCE *Instance
+)
+{
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO, "%a: TCP connection is finished. Could be TSL session closure, reset HTTP instance for the new TLS session.\n", __FUNCTION__));
+
+ Status = Instance->HttpIo.Http->Configure (Instance->HttpIo.Http, NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Error to reset HTTP instance.\n", __FUNCTION__));
+ return Status;
+ }
+ Status = Instance->HttpIo.Http->Configure(Instance->HttpIo.Http, &((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConfigData);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Error to re-initiate HTTP instance.\n", __FUNCTION__));
+ }
+ return Status;
+}
+/**
+ This function check
+
+ @param[in] Instance Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[in] HttpIoReceiveStatus This is the status return from HttpIoRecvResponse
+
+ @retval EFI_SUCCESS The payload receive from Redfish service in sucessfully.
+ @retval EFI_NOT_READY May need to resend the HTTP request.
+ @retval EFI_DEVICE_ERROR Something wrong and can't be resolved.
+ @retval Others Other errors as indicated.
+
+**/
+EFI_STATUS
+RedfishCheckHttpReceiveStatus (
+ IN RESTEX_INSTANCE *Instance,
+ IN EFI_STATUS HttpIoReceiveStatus
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS ReturnStatus;
+
+ if (!EFI_ERROR (HttpIoReceiveStatus)){
+ ReturnStatus = EFI_SUCCESS;
+ } else if (EFI_ERROR (HttpIoReceiveStatus) && HttpIoReceiveStatus != EFI_CONNECTION_FIN) {
+ if ((Instance->Flags & RESTEX_INSTANCE_FLAGS_TCP_ERROR_RETRY) == 0) {
+ DEBUG ((DEBUG_ERROR, "%a: TCP error, reset HTTP session.\n", __FUNCTION__));
+ Instance->Flags |= RESTEX_INSTANCE_FLAGS_TCP_ERROR_RETRY;
+ gBS->Stall (500);
+ Status = ResetHttpTslSession (Instance);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Reset HTTP instance fail.\n", __FUNCTION__));
+ ReturnStatus = EFI_DEVICE_ERROR;
+ } else {
+ return EFI_NOT_READY;
+ }
+ } else {
+ ReturnStatus = EFI_DEVICE_ERROR;
+ }
+ } else {
+ if (HttpIoReceiveStatus == EFI_CONNECTION_FIN) {
+ if ((Instance->Flags & RESTEX_INSTANCE_FLAGS_TLS_RETRY) != 0) {
+ DEBUG ((DEBUG_ERROR, "%a: REST_EX Send and receive fail even with a new TLS session.\n", __FUNCTION__));
+ ReturnStatus = EFI_DEVICE_ERROR;
+ }
+ Instance->Flags |= RESTEX_INSTANCE_FLAGS_TLS_RETRY;
+ Status = ResetHttpTslSession (Instance);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Reset HTTP instance fail.\n", __FUNCTION__));
+ ReturnStatus = EFI_DEVICE_ERROR;
+ }
+ return EFI_NOT_READY;
+ }
+ }
+ //
+ // Clean TLS new session retry and error try flags.
+ //
+ Instance->Flags &= ~ (RESTEX_INSTANCE_FLAGS_TLS_RETRY | RESTEX_INSTANCE_FLAGS_TCP_ERROR_RETRY);
+ return ReturnStatus;
+}
+
+/**
+ This function send the HTTP request without body to see
+ if the write to URL is permitted by Redfish service. This function
+ checks if the HTTP request has Content-length in HTTP header. If yes,
+ set HTTP body to NULL and then send to service. Check the HTTP status
+ for the firther actions.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[in] RequestMessage Pointer to the HTTP request data for this resource
+ @param[in] PreservedRequestHeaders The pointer to save the request headers
+ @param[in] ItsWrite This is write method to URL.
+
+ @retval EFI_INVALID_PARAMETER Improper given parameters.
+ @retval EFI_SUCCESS This HTTP request is free to send to Redfish service.
+ @retval EFI_OUT_OF_RESOURCES NOt enough memory to process.
+ @retval EFI_ACCESS_DENIED Not allowed to write to this URL.
+
+ @retval Others Other errors as indicated.
+
+**/
+EFI_STATUS
+RedfishHttpAddExpectation (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage,
+ IN EFI_HTTP_HEADER **PreservedRequestHeaders,
+ IN BOOLEAN *ItsWrite
+ )
+{
+ EFI_HTTP_HEADER *NewHeaders;
+
+ if (This == NULL || RequestMessage == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *ItsWrite = FALSE;
+ if (PreservedRequestHeaders != NULL) {
+ *PreservedRequestHeaders = RequestMessage->Headers;
+ }
+
+ if ((RequestMessage->Data.Request->Method != HttpMethodPut) && (RequestMessage->Data.Request->Method != HttpMethodPost) &&
+ (RequestMessage->Data.Request->Method != HttpMethodPatch)) {
+ return EFI_SUCCESS;
+ }
+ *ItsWrite = TRUE;
+
+ NewHeaders = AllocateZeroPool((RequestMessage->HeaderCount + 1) * sizeof(EFI_HTTP_HEADER));
+ CopyMem ((VOID*)NewHeaders, (VOID *)RequestMessage->Headers, RequestMessage->HeaderCount * sizeof (EFI_HTTP_HEADER));
+ HttpSetFieldNameAndValue (NewHeaders + RequestMessage->HeaderCount, HTTP_HEADER_EXPECT, HTTP_EXPECT_100_CONTINUE);
+ RequestMessage->HeaderCount ++;
+ RequestMessage->Headers = NewHeaders;
+ return EFI_SUCCESS;
+}
+
diff --git a/RedfishPkg/RedfishRestExDxe/RedfishRestExInternal.h b/RedfishPkg/RedfishRestExDxe/RedfishRestExInternal.h
new file mode 100644
index 0000000000..a75985928c
--- /dev/null
+++ b/RedfishPkg/RedfishRestExDxe/RedfishRestExInternal.h
@@ -0,0 +1,611 @@
+/** @file
+ RedfishRestExDxe support functions definitions.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2019-2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef EFI_REDFISH_RESTEX_INTERNAL_H_
+#define EFI_REDFISH_RESTEX_INTERNAL_H_
+
+///
+/// Libraries classes
+///
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HttpIoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/NetLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+
+///
+/// UEFI Driver Model Protocols
+///
+#include <Protocol/DriverBinding.h>
+#include <Protocol/RestEx.h>
+#include <Protocol/ServiceBinding.h>
+
+#include "RedfishRestExDriver.h"
+
+/**
+ This function check
+
+ @param[in] Instance Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[in] HttpReceiveEfiStatus This is the status return from HttpIoRecvResponse
+
+ @retval EFI_SUCCESS The payload receive from Redfish service in sucessfully.
+ @retval EFI_NOT_READY May need to resend the HTTP request.
+ @retval EFI_DEVICE_ERROR Something wrong and can't be resolved.
+ @retval Others Other errors as indicated.
+
+**/
+EFI_STATUS
+RedfishCheckHttpReceiveStatus (
+ IN RESTEX_INSTANCE *Instance,
+ IN EFI_STATUS HttpIoReceiveStatus
+ );
+
+/**
+ This function send the HTTP request without body to see
+ if the write to URL is permitted by Redfish service. This function
+ checks if the HTTP request has Content-length in HTTP header. If yes,
+ set HTTP body to NULL and then send to service. Check the HTTP status
+ for the firther actions.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[in] RequestMessage Pointer to the HTTP request data for this resource
+ @param[in] PreservedRequestHeaders The pointer to save the request headers
+ @param[in] ItsWrite This is write method to URL.
+
+ @retval EFI_INVALID_PARAMETER Improper given parameters.
+ @retval EFI_SUCCESS This HTTP request is free to send to Redfish service.
+ @retval EFI_OUT_OF_RESOURCES NOt enough memory to process.
+ @retval EFI_ACCESS_DENIED Not allowed to write to this URL.
+
+ @retval Others Other errors as indicated.
+
+**/
+EFI_STATUS
+RedfishHttpAddExpectation (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage,
+ IN EFI_HTTP_HEADER **PreservedRequestHeaders,
+ IN BOOLEAN *ItsWrite
+ );
+
+/**
+ Provides a simple HTTP-like interface to send and receive resources from a REST service.
+
+ The SendReceive() function sends an HTTP request to this REST service, and returns a
+ response when the data is retrieved from the service. RequestMessage contains the HTTP
+ request to the REST resource identified by RequestMessage.Request.Url. The
+ ResponseMessage is the returned HTTP response for that request, including any HTTP
+ status.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[in] RequestMessage Pointer to the HTTP request data for this resource
+ @param[out] ResponseMessage Pointer to the HTTP response data obtained for this requested.
+
+ @retval EFI_SUCCESS operation succeeded.
+ @retval EFI_INVALID_PARAMETER This, RequestMessage, or ResponseMessage are NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExSendReceive (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage,
+ OUT EFI_HTTP_MESSAGE *ResponseMessage
+ );
+
+/**
+ Obtain the current time from this REST service instance.
+
+ The GetServiceTime() function is an optional interface to obtain the current time from
+ this REST service instance. If this REST service does not support to retrieve the time,
+ this function returns EFI_UNSUPPORTED. This function must returns EFI_UNSUPPORTED if
+ EFI_REST_EX_SERVICE_TYPE returned in EFI_REST_EX_SERVICE_INFO from GetService() is
+ EFI_REST_EX_SERVICE_UNSPECIFIC.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[out] Time A pointer to storage to receive a snapshot of the current time of
+ the REST service.
+
+ @retval EFI_SUCCESS operation succeeded.
+ @retval EFI_INVALID_PARAMETER This or Time are NULL.
+ @retval EFI_UNSUPPORTED The RESTful service does not support returning the time.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must
+ be executed and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExGetServiceTime (
+ IN EFI_REST_EX_PROTOCOL *This,
+ OUT EFI_TIME *Time
+ );
+
+/**
+ This function returns the information of REST service provided by this EFI REST EX driver instance.
+
+ The information such as the type of REST service and the access mode of REST EX driver instance
+ (In-band or Out-of-band) are described in EFI_REST_EX_SERVICE_INFO structure. For the vendor-specific
+ REST service, vendor-specific REST service information is returned in VendorSpecifcData.
+ REST EX driver designer is well know what REST service this REST EX driver instance intends to
+ communicate with. The designer also well know this driver instance is used to talk to BMC through
+ specific platform mechanism or talk to REST server through UEFI HTTP protocol. REST EX driver is
+ responsible to fill up the correct information in EFI_REST_EX_SERVICE_INFO. EFI_REST_EX_SERVICE_INFO
+ is referred by EFI REST clients to pickup the proper EFI REST EX driver instance to get and set resource.
+ GetService() is a basic and mandatory function which must be able to use even Configure() is not invoked
+ in previously.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[out] RestExServiceInfo Pointer to receive a pointer to EFI_REST_EX_SERVICE_INFO structure. The
+ format of EFI_REST_EX_SERVICE_INFO is version controlled for the future
+ extension. The version of EFI_REST_EX_SERVICE_INFO structure is returned
+ in the header within this structure. EFI REST client refers to the correct
+ format of structure according to the version number. The pointer to
+ EFI_REST_EX_SERVICE_INFO is a memory block allocated by EFI REST EX driver
+ instance. That is caller's responsibility to free this memory when this
+ structure is no longer needed. Refer to Related Definitions below for the
+ definitions of EFI_REST_EX_SERVICE_INFO structure.
+
+ @retval EFI_SUCCESS EFI_REST_EX_SERVICE_INFO is returned in RestExServiceInfo. This function
+ is not supported in this REST EX Protocol driver instance.
+ @retval EFI_UNSUPPORTED This function is not supported in this REST EX Protocol driver instance.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExGetService (
+ IN EFI_REST_EX_PROTOCOL *This,
+ OUT EFI_REST_EX_SERVICE_INFO **RestExServiceInfo
+ );
+
+/**
+ This function returns operational configuration of current EFI REST EX child instance.
+
+ This function returns the current configuration of EFI REST EX child instance. The format of
+ operational configuration depends on the implementation of EFI REST EX driver instance. For
+ example, HTTP-aware EFI REST EX driver instance uses EFI HTTP protocol as the undying protocol
+ to communicate with REST service. In this case, the type of configuration is
+ EFI_REST_EX_CONFIG_TYPE_HTTP returned from GetService(). EFI_HTTP_CONFIG_DATA is used as EFI REST
+ EX configuration format and returned to EFI REST client. User has to type cast RestExConfigData
+ to EFI_HTTP_CONFIG_DATA. For those non HTTP-aware REST EX driver instances, the type of configuration
+ is EFI_REST_EX_CONFIG_TYPE_UNSPECIFIC returned from GetService(). In this case, the format of
+ returning data could be non industrial. Instead, the format of configuration data is system/platform
+ specific definition such as BMC mechanism used in EFI REST EX driver instance. EFI REST client and
+ EFI REST EX driver instance have to refer to the specific system /platform spec which is out of UEFI scope.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[out] RestExConfigData Pointer to receive a pointer to EFI_REST_EX_CONFIG_DATA.
+ The memory allocated for configuration data should be freed
+ by caller. See Related Definitions for the details.
+
+ @retval EFI_SUCCESS EFI_REST_EX_CONFIG_DATA is returned in successfully.
+ @retval EFI_UNSUPPORTED This function is not supported in this REST EX Protocol driver instance.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must be
+ executed and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExGetModeData (
+ IN EFI_REST_EX_PROTOCOL *This,
+ OUT EFI_REST_EX_CONFIG_DATA *RestExConfigData
+ );
+
+/**
+ This function is used to configure EFI REST EX child instance.
+
+ This function is used to configure the setting of underlying protocol of REST EX child
+ instance. The type of configuration is according to the implementation of EFI REST EX
+ driver instance. For example, HTTP-aware EFI REST EX driver instance uses EFI HTTP protocol
+ as the undying protocol to communicate with REST service. The type of configuration is
+ EFI_REST_EX_CONFIG_TYPE_HTTP and RestExConfigData is the same format with EFI_HTTP_CONFIG_DATA.
+ Akin to HTTP configuration, REST EX child instance can be configure to use different HTTP
+ local access point for the data transmission. Multiple REST clients may use different
+ configuration of HTTP to distinguish themselves, such as to use the different TCP port.
+ For those non HTTP-aware REST EX driver instance, the type of configuration is
+ EFI_REST_EX_CONFIG_TYPE_UNSPECIFIC. RestExConfigData refers to the non industrial standard.
+ Instead, the format of configuration data is system/platform specific definition such as BMC.
+ In this case, EFI REST client and EFI REST EX driver instance have to refer to the specific
+ system/platform spec which is out of the UEFI scope. Besides GetService()function, no other
+ EFI REST EX functions can be executed by this instance until Configure()is executed and returns
+ successfully. All other functions must returns EFI_NOT_READY if this instance is not configured
+ yet. Set RestExConfigData to NULL means to put EFI REST EX child instance into the unconfigured
+ state.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[in] RestExConfigData Pointer to EFI_REST_EX_CONFIG_DATA. See Related Definitions in
+ GetModeData() protocol interface.
+
+ @retval EFI_SUCCESS EFI_REST_EX_CONFIG_DATA is set in successfully.
+ @retval EFI_DEVICE_ERROR Configuration for this REST EX child instance is failed with the given
+ EFI_REST_EX_CONFIG_DATA.
+ @retval EFI_UNSUPPORTED This function is not supported in this REST EX Protocol driver instance.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExConfigure (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_REST_EX_CONFIG_DATA RestExConfigData
+ );
+
+/**
+ This function sends REST request to REST service and signal caller's event asynchronously when
+ the final response is received by REST EX Protocol driver instance.
+
+ The essential design of this function is to handle asynchronous send/receive implicitly according
+ to REST service asynchronous request mechanism. Caller will get the notification once the response
+ is returned from REST service.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[in] RequestMessage This is the HTTP request message sent to REST service. Set RequestMessage
+ to NULL to cancel the previous asynchronous request associated with the
+ corresponding RestExToken. See descriptions for the details.
+ @param[in] RestExToken REST EX token which REST EX Protocol instance uses to notify REST client
+ the status of response of asynchronous REST request. See related definition
+ of EFI_REST_EX_TOKEN.
+ @param[in] TimeOutInMilliSeconds The pointer to the timeout in milliseconds which REST EX Protocol driver
+ instance refers as the duration to drop asynchronous REST request. NULL
+ pointer means no timeout for this REST request. REST EX Protocol driver
+ signals caller's event with EFI_STATUS set to EFI_TIMEOUT in RestExToken
+ if REST EX Protocol can't get the response from REST service within
+ TimeOutInMilliSeconds.
+
+ @retval EFI_SUCCESS Asynchronous REST request is established.
+ @retval EFI_UNSUPPORTED This REST EX Protocol driver instance doesn't support asynchronous request.
+ @retval EFI_TIMEOUT Asynchronous REST request is not established and timeout is expired.
+ @retval EFI_ABORT Previous asynchronous REST request has been canceled.
+ @retval EFI_DEVICE_ERROR Otherwise, returns EFI_DEVICE_ERROR for other errors according to HTTP Status Code.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must be executed
+ and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExAyncSendReceive (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage OPTIONAL,
+ IN EFI_REST_EX_TOKEN *RestExToken,
+ IN UINTN *TimeOutInMilliSeconds OPTIONAL
+ );
+
+/**
+ This function sends REST request to a REST Event service and signals caller's event
+ token asynchronously when the URI resource change event is received by REST EX
+ Protocol driver instance.
+
+ The essential design of this function is to monitor event implicitly according to
+ REST service event service mechanism. Caller will get the notification if certain
+ resource is changed.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[in] RequestMessage This is the HTTP request message sent to REST service. Set RequestMessage
+ to NULL to cancel the previous event service associated with the corresponding
+ RestExToken. See descriptions for the details.
+ @param[in] RestExToken REST EX token which REST EX Protocol driver instance uses to notify REST client
+ the URI resource which monitored by REST client has been changed. See the related
+ definition of EFI_REST_EX_TOKEN in EFI_REST_EX_PROTOCOL.AsyncSendReceive().
+
+ @retval EFI_SUCCESS Asynchronous REST request is established.
+ @retval EFI_UNSUPPORTED This REST EX Protocol driver instance doesn't support asynchronous request.
+ @retval EFI_ABORT Previous asynchronous REST request has been canceled or event subscription has been
+ delete from service.
+ @retval EFI_DEVICE_ERROR Otherwise, returns EFI_DEVICE_ERROR for other errors according to HTTP Status Code.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must be executed
+ and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExEventService (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage OPTIONAL,
+ IN EFI_REST_EX_TOKEN *RestExToken
+ );
+/**
+ Create a new TLS session becuase the previous on is closed.
+ status.
+
+ @param[in] Instance Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @retval EFI_SUCCESS operation succeeded.
+ @retval EFI Errors Other errors.
+
+**/
+EFI_STATUS
+ResetHttpTslSession (
+ IN RESTEX_INSTANCE *Instance
+);
+
+
+/**
+ Callback function which provided by user to remove one node in NetDestroyLinkList process.
+
+ @param[in] Entry The entry to be removed.
+ @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
+
+ @retval EFI_SUCCESS The entry has been removed successfully.
+ @retval Others Fail to remove the entry.
+
+**/
+EFI_STATUS
+EFIAPI
+RestExDestroyChildEntryInHandleBuffer (
+ IN LIST_ENTRY *Entry,
+ IN VOID *Context
+ );
+
+/**
+ Destroy the RestEx instance and recycle the resources.
+
+ @param[in] Instance The pointer to the RestEx instance.
+
+**/
+VOID
+RestExDestroyInstance (
+ IN RESTEX_INSTANCE *Instance
+ );
+
+/**
+ Create the RestEx instance and initialize it.
+
+ @param[in] Service The pointer to the RestEx service.
+ @param[out] Instance The pointer to the RestEx instance.
+
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
+ @retval EFI_SUCCESS The RestEx instance is created.
+
+**/
+EFI_STATUS
+RestExCreateInstance (
+ IN RESTEX_SERVICE *Service,
+ OUT RESTEX_INSTANCE **Instance
+ );
+
+
+/**
+ Release all the resource used the RestEx service binding instance.
+
+ @param[in] RestExSb The RestEx service binding instance.
+
+**/
+VOID
+RestExDestroyService (
+ IN RESTEX_SERVICE *RestExSb
+ );
+
+/**
+ Create then initialize a RestEx service binding instance.
+
+ @param[in] Controller The controller to install the RestEx service
+ binding on.
+ @param[in] Image The driver binding image of the RestEx driver.
+ @param[out] Service The variable to receive the created service
+ binding instance.
+
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the instance.
+ @retval EFI_SUCCESS The service instance is created for the controller.
+
+**/
+EFI_STATUS
+RestExCreateService (
+ IN EFI_HANDLE Controller,
+ IN EFI_HANDLE Image,
+ OUT RESTEX_SERVICE **Service
+ );
+
+/**
+ This is the declaration of an EFI image entry point. This entry point is
+ the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
+ both device drivers and bus drivers.
+
+ @param[in] ImageHandle The firmware allocated handle for the UEFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval Others An unexpected error occurred.
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Tests to see if this driver supports a given controller. If a child device is provided,
+ it further tests to see if this driver supports creating a handle for the specified child device.
+
+ This function checks to see if the driver specified by This supports the device specified by
+ ControllerHandle. Drivers will typically use the device path attached to
+ ControllerHandle and/or the services from the bus I/O abstraction attached to
+ ControllerHandle to determine if the driver supports ControllerHandle. This function
+ may be called many times during platform initialization. In order to reduce boot times, the tests
+ performed by this function must be very small, and take as little time as possible to execute. This
+ function must not change the state of any hardware devices, and this function must be aware that the
+ device specified by ControllerHandle may already be managed by the same driver or a
+ different driver. This function must match its calls to AllocatePages() with FreePages(),
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+ Because ControllerHandle may have been previously started by the same driver, if a protocol is
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required
+ to guarantee the state of ControllerHandle is not modified by this function.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For bus drivers, if this parameter is not NULL, then
+ the bus driver must determine if the bus controller specified
+ by ControllerHandle and the child controller specified
+ by RemainingDevicePath are both supported by this
+ bus driver.
+
+ @retval EFI_SUCCESS The device specified by ControllerHandle and
+ RemainingDevicePath is supported by the driver specified by This.
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by the driver
+ specified by This.
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by a different
+ driver or an application that requires exclusive access.
+ Currently not implemented.
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
+ RemainingDevicePath is not supported by the driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ );
+
+/**
+ Starts a device controller or a bus controller.
+
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().
+ As a result, much of the error checking on the parameters to Start() has been moved into this
+ common boot service. It is legal to call Start() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE.
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+ EFI_DEVICE_PATH_PROTOCOL.
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to start. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For a bus driver, if this parameter is NULL, then handles
+ for all the children of Controller are created by this driver.
+ If this parameter is not NULL and the first Device Path Node is
+ not the End of Device Path Node, then only the handle for the
+ child device specified by the first Device Path Node of
+ RemainingDevicePath is created by this driver.
+ If the first Device Path Node of RemainingDevicePath is
+ the End of Device Path Node, no child handle is created by this
+ driver.
+
+ @retval EFI_SUCCESS The device was started.
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval Others The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ );
+
+/**
+ Stops a device controller or a bus controller.
+
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+ As a result, much of the error checking on the parameters to Stop() has been moved
+ into this common boot service. It is legal to call Stop() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+ same driver's Start() function.
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+ Start() function, and the Start() function must have called OpenProtocol() on
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must
+ support a bus specific I/O protocol for the driver
+ to use to stop the device.
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
+ if NumberOfChildren is 0.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
+ );
+
+/**
+ Creates a child handle and installs a protocol.
+
+ The CreateChild() function installs a protocol on ChildHandle.
+ If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
+ If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
+
+ @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+ @param[in] ChildHandle Pointer to the handle of the child to create. If it is NULL,
+ then a new handle is created. If it is a pointer to an existing UEFI handle,
+ then the protocol is added to the existing UEFI handle.
+
+ @retval EFI_SUCCES The protocol was added to ChildHandle.
+ @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create
+ the child
+ @retval other The child handle was not created
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExServiceBindingCreateChild (
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE *ChildHandle
+ );
+
+/**
+ Destroys a child handle with a protocol installed on it.
+
+ The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
+ that was installed by CreateChild() from ChildHandle. If the removed protocol is the
+ last protocol on ChildHandle, then ChildHandle is destroyed.
+
+ @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+ @param[in] ChildHandle Handle of the child to destroy
+
+ @retval EFI_SUCCES The protocol was removed from ChildHandle.
+ @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
+ @retval EFI_INVALID_PARAMETER Child handle is NULL.
+ @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
+ because its services are being used.
+ @retval other The child handle was not destroyed
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExServiceBindingDestroyChild (
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ChildHandle
+ );
+#endif
diff --git a/RedfishPkg/RedfishRestExDxe/RedfishRestExProtocol.c b/RedfishPkg/RedfishRestExDxe/RedfishRestExProtocol.c
new file mode 100644
index 0000000000..65a5fe3713
--- /dev/null
+++ b/RedfishPkg/RedfishRestExDxe/RedfishRestExProtocol.c
@@ -0,0 +1,735 @@
+/** @file
+ Implementation of Redfish EFI_REST_EX_PROTOCOL interfaces.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Uefi.h>
+#include "RedfishRestExInternal.h"
+
+EFI_REST_EX_PROTOCOL mRedfishRestExProtocol = {
+ RedfishRestExSendReceive,
+ RedfishRestExGetServiceTime,
+ RedfishRestExGetService,
+ RedfishRestExGetModeData,
+ RedfishRestExConfigure,
+ RedfishRestExAyncSendReceive,
+ RedfishRestExEventService
+};
+
+/**
+ Provides a simple HTTP-like interface to send and receive resources from a REST service.
+
+ The SendReceive() function sends an HTTP request to this REST service, and returns a
+ response when the data is retrieved from the service. RequestMessage contains the HTTP
+ request to the REST resource identified by RequestMessage.Request.Url. The
+ ResponseMessage is the returned HTTP response for that request, including any HTTP
+ status.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[in] RequestMessage Pointer to the HTTP request data for this resource
+ @param[out] ResponseMessage Pointer to the HTTP response data obtained for this requested.
+
+ @retval EFI_SUCCESS operation succeeded.
+ @retval EFI_INVALID_PARAMETER This, RequestMessage, or ResponseMessage are NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+ @retval EFI_ACCESS_DENIED HTTP method is not allowed on this URL.
+ @retval EFI_BAD_BUFFER_SIZE The payload is to large to be handled on server side.
+ @retval EFI_UNSUPPORTED Unsupported HTTP response.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExSendReceive (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage,
+ OUT EFI_HTTP_MESSAGE *ResponseMessage
+ )
+{
+ EFI_STATUS Status;
+ RESTEX_INSTANCE *Instance;
+ HTTP_IO_RESPONSE_DATA *ResponseData;
+ UINTN TotalReceivedSize;
+ UINTN Index;
+ LIST_ENTRY *ChunkListLink;
+ HTTP_IO_CHUNKS *ThisChunk;
+ BOOLEAN CopyChunkData;
+ BOOLEAN MediaPresent;
+ EFI_HTTP_HEADER *PreservedRequestHeaders;
+ BOOLEAN ItsWrite;
+ BOOLEAN IsGetChunkedTransfer;
+ HTTP_IO_SEND_CHUNK_PROCESS SendChunkProcess;
+ HTTP_IO_SEND_NON_CHUNK_PROCESS SendNonChunkProcess;
+ EFI_HTTP_MESSAGE ChunkTransferRequestMessage;
+
+ Status = EFI_SUCCESS;
+ ResponseData = NULL;
+ IsGetChunkedTransfer = FALSE;
+ SendChunkProcess = HttpIoSendChunkNone;
+ SendNonChunkProcess = HttpIoSendNonChunkNone;
+
+ //
+ // Validate the parameters
+ //
+ if ((This == NULL) || (RequestMessage == NULL) || ResponseMessage == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Instance = RESTEX_INSTANCE_FROM_THIS (This);
+
+ //
+ // Check Media Status.
+ //
+ MediaPresent = TRUE;
+ NetLibDetectMedia (Instance->Service->ControllerHandle, &MediaPresent);
+ if (!MediaPresent) {
+ DEBUG ((DEBUG_INFO, "RedfishRestExSendReceive(): No MediaPresent.\n"));
+ return EFI_NO_MEDIA;
+ }
+
+ DEBUG ((DEBUG_INFO, "\nRedfishRestExSendReceive():\n"));
+ DEBUG ((DEBUG_INFO, "*** Perform HTTP Request Method - %d, URL: %s\n", RequestMessage->Data.Request->Method, RequestMessage->Data.Request->Url));
+
+ //
+ // Add header "Expect" to server, only for URL write.
+ //
+ Status = RedfishHttpAddExpectation (This, RequestMessage, &PreservedRequestHeaders, &ItsWrite);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (ItsWrite == TRUE) {
+ if (RequestMessage->BodyLength > HTTP_IO_MAX_SEND_PAYLOAD) {
+ //
+ // Send chunked transfer.
+ //
+ SendChunkProcess ++;
+ CopyMem ((VOID *)&ChunkTransferRequestMessage, (VOID *)RequestMessage, sizeof (EFI_HTTP_MESSAGE));
+ } else {
+ SendNonChunkProcess ++;
+ }
+ }
+ReSendRequest:;
+ //
+ // Send out the request to REST service.
+ //
+ if (ItsWrite == TRUE) {
+ //
+ // This is write to URI
+ //
+ if (SendChunkProcess > HttpIoSendChunkNone) {
+ //
+ // This is chunk transfer for writing large payload.
+ // Send request header first and then handle the
+ // following request message body using chunk transfer.
+ //
+ do {
+ Status = HttpIoSendChunkedTransfer(
+ &(Instance->HttpIo),
+ &SendChunkProcess,
+ &ChunkTransferRequestMessage
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+ } while (SendChunkProcess == HttpIoSendChunkContent || SendChunkProcess == HttpIoSendChunkEndChunk);
+ } else {
+ //
+ // This is the non-chunk transfer, send request header first and then
+ // handle the following request message body using chunk transfer.
+ //
+ Status = HttpIoSendRequest(
+ &(Instance->HttpIo),
+ (SendNonChunkProcess == HttpIoSendNonChunkContent)? NULL: RequestMessage->Data.Request,
+ (SendNonChunkProcess == HttpIoSendNonChunkContent)? 0: RequestMessage->HeaderCount,
+ (SendNonChunkProcess == HttpIoSendNonChunkContent)? NULL: RequestMessage->Headers,
+ (SendNonChunkProcess == HttpIoSendNonChunkHeaderZeroContent)? 0: RequestMessage->BodyLength,
+ (SendNonChunkProcess == HttpIoSendNonChunkHeaderZeroContent)? NULL: RequestMessage->Body
+ );
+ }
+ } else {
+ //
+ // This is read from URI.
+ //
+ Status = HttpIoSendRequest(
+ &(Instance->HttpIo),
+ RequestMessage->Data.Request,
+ RequestMessage->HeaderCount,
+ RequestMessage->Headers,
+ RequestMessage->BodyLength,
+ RequestMessage->Body
+ );
+ }
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ //
+ // ResponseMessage->Data.Response is to indicate whether to receive the HTTP header or not.
+ // ResponseMessage->BodyLength/ResponseMessage->Body are to indicate whether to receive the response body or not.
+ // Clean the previous buffers and all of them will be allocated later according to the actual situation.
+ //
+ if (ResponseMessage->Data.Response != NULL) {
+ FreePool(ResponseMessage->Data.Response);
+ ResponseMessage->Data.Response = NULL;
+ }
+
+ ResponseMessage->BodyLength = 0;
+ if (ResponseMessage->Body != NULL) {
+ FreePool(ResponseMessage->Body);
+ ResponseMessage->Body = NULL;
+ }
+
+ //
+ // Use zero BodyLength to only receive the response headers.
+ //
+ ResponseData = AllocateZeroPool (sizeof(HTTP_IO_RESPONSE_DATA));
+ if (ResponseData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+
+ DEBUG ((DEBUG_INFO, "Receiving HTTP response and headers...\n"));
+ Status = RedfishCheckHttpReceiveStatus (
+ Instance,
+ HttpIoRecvResponse (
+ &(Instance->HttpIo),
+ TRUE,
+ ResponseData
+ )
+ );
+ if (Status == EFI_NOT_READY) {
+ goto ReSendRequest;
+ } else if (Status == EFI_DEVICE_ERROR) {
+ goto ON_EXIT;
+ }
+ //
+ // Restore the headers if it ever changed in RedfishHttpAddExpectation().
+ //
+ if (RequestMessage->Headers != PreservedRequestHeaders) {
+ FreePool (RequestMessage->Headers);
+ RequestMessage->Headers = PreservedRequestHeaders; // Restore headers before we adding "Expect".
+ RequestMessage->HeaderCount --; // Minus one header count for "Expect".
+ }
+
+ DEBUG ((DEBUG_INFO, "HTTP Response StatusCode - %d:", ResponseData->Response.StatusCode));
+ if (ResponseData->Response.StatusCode == HTTP_STATUS_200_OK) {
+ DEBUG ((DEBUG_INFO, "HTTP_STATUS_200_OK\n"));
+
+ if (SendChunkProcess == HttpIoSendChunkHeaderZeroContent) {
+ DEBUG ((DEBUG_INFO, "This is chunk transfer, start to send all chunks.", ResponseData->Response.StatusCode));
+ SendChunkProcess ++;
+ goto ReSendRequest;
+ }
+ } else if (ResponseData->Response.StatusCode == HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE) {
+ DEBUG ((DEBUG_INFO, "HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE\n"));
+
+ Status = EFI_BAD_BUFFER_SIZE;
+ goto ON_EXIT;
+ } else if (ResponseData->Response.StatusCode == HTTP_STATUS_405_METHOD_NOT_ALLOWED){
+ DEBUG ((DEBUG_ERROR, "HTTP_STATUS_405_METHOD_NOT_ALLOWED\n"));
+
+ Status = EFI_ACCESS_DENIED;
+ goto ON_EXIT;
+ } else if (ResponseData->Response.StatusCode == HTTP_STATUS_400_BAD_REQUEST) {
+ DEBUG ((DEBUG_INFO, "HTTP_STATUS_400_BAD_REQUEST\n"));
+ if (SendChunkProcess == HttpIoSendChunkHeaderZeroContent) {
+ DEBUG ((DEBUG_INFO, "Bad request may caused by zero length chunk. Try to send all chunks...\n"));
+ SendChunkProcess ++;
+ goto ReSendRequest;
+ }
+ } else if (ResponseData->Response.StatusCode == HTTP_STATUS_100_CONTINUE) {
+ DEBUG ((DEBUG_INFO, "HTTP_STATUS_100_CONTINUE\n"));
+ if (SendChunkProcess == HttpIoSendChunkHeaderZeroContent) {
+ //
+ // We get HTTP_STATUS_100_CONTINUE to send the body using chunk transfer.
+ //
+ DEBUG ((DEBUG_INFO, "HTTP_STATUS_100_CONTINUE for chunk transfer...\n"));
+ SendChunkProcess ++;
+ goto ReSendRequest;
+ }
+ if (SendNonChunkProcess == HttpIoSendNonChunkHeaderZeroContent) {
+ DEBUG ((DEBUG_INFO, "HTTP_STATUS_100_CONTINUE for non chunk transfer...\n"));
+ SendNonChunkProcess ++;
+ goto ReSendRequest;
+ }
+ //
+ // It's the REST protocol's responsibility to handle the interim HTTP response (e.g. 100 Continue Informational),
+ // and return the final response content to the caller.
+ //
+ if (ResponseData->Headers != NULL && ResponseData->HeaderCount != 0) {
+ FreePool (ResponseData->Headers);
+ }
+ ZeroMem (ResponseData, sizeof(HTTP_IO_RESPONSE_DATA));
+ Status = HttpIoRecvResponse (
+ &(Instance->HttpIo),
+ TRUE,
+ ResponseData
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+ } else {
+ DEBUG ((DEBUG_ERROR, "This HTTP Status is not handled!\n"));
+ Status = EFI_UNSUPPORTED;
+ goto ON_EXIT;
+ }
+
+ //
+ // Ready to return the StatusCode, Header info and BodyLength.
+ //
+ ResponseMessage->Data.Response = AllocateZeroPool (sizeof (EFI_HTTP_RESPONSE_DATA));
+ if (ResponseMessage->Data.Response == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+
+ ResponseMessage->Data.Response->StatusCode = ResponseData->Response.StatusCode;
+ ResponseMessage->HeaderCount = ResponseData->HeaderCount;
+ ResponseMessage->Headers = ResponseData->Headers;
+
+ //
+ // Get response message body.
+ //
+ if (ResponseMessage->HeaderCount > 0) {
+ Status = HttpIoGetContentLength (ResponseMessage->HeaderCount, ResponseMessage->Headers, &ResponseMessage->BodyLength);
+ if (EFI_ERROR (Status) && Status != EFI_NOT_FOUND) {
+ goto ON_EXIT;
+ }
+
+ if (Status == EFI_NOT_FOUND) {
+ ASSERT (ResponseMessage->BodyLength == 0);
+ }
+
+ if (ResponseMessage->BodyLength == 0) {
+ //
+ // Check if Chunked Transfer Coding.
+ //
+ Status = HttpIoGetChunkedTransferContent (
+ &(Instance->HttpIo),
+ ResponseMessage->HeaderCount,
+ ResponseMessage->Headers,
+ &ChunkListLink,
+ &ResponseMessage->BodyLength
+ );
+ if (EFI_ERROR (Status) && Status != EFI_NOT_FOUND) {
+ goto ON_EXIT;
+ }
+ if (Status == EFI_SUCCESS &&
+ ChunkListLink != NULL &&
+ !IsListEmpty(ChunkListLink) &&
+ ResponseMessage->BodyLength != 0) {
+ IsGetChunkedTransfer = TRUE;
+ //
+ // Copy data to Message body.
+ //
+ CopyChunkData = TRUE;
+ ResponseMessage->Body = AllocateZeroPool (ResponseMessage->BodyLength);
+ if (ResponseMessage->Body == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ CopyChunkData = FALSE;
+ }
+ Index = 0;
+ while (!IsListEmpty(ChunkListLink)) {
+ ThisChunk = (HTTP_IO_CHUNKS *)GetFirstNode (ChunkListLink);
+ if (CopyChunkData) {
+ CopyMem(((UINT8 *)ResponseMessage->Body + Index), (UINT8 *)ThisChunk->Data, ThisChunk->Length);
+ Index += ThisChunk->Length;
+ }
+ RemoveEntryList (&ThisChunk->NextChunk);
+ FreePool ((VOID *)ThisChunk->Data);
+ FreePool ((VOID *)ThisChunk);
+ };
+ FreePool ((VOID *)ChunkListLink);
+ }
+ }
+ Status = EFI_SUCCESS;
+ }
+
+ //
+ // Ready to return the Body from REST service if have any.
+ //
+ if (ResponseMessage->BodyLength > 0 && !IsGetChunkedTransfer) {
+ ResponseData->HeaderCount = 0;
+ ResponseData->Headers = NULL;
+
+ ResponseMessage->Body = AllocateZeroPool (ResponseMessage->BodyLength);
+ if (ResponseMessage->Body == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+
+ //
+ // Only receive the Body.
+ //
+ TotalReceivedSize = 0;
+ while (TotalReceivedSize < ResponseMessage->BodyLength) {
+ ResponseData->BodyLength = ResponseMessage->BodyLength - TotalReceivedSize;
+ ResponseData->Body = (CHAR8 *) ResponseMessage->Body + TotalReceivedSize;
+ Status = HttpIoRecvResponse (
+ &(Instance->HttpIo),
+ FALSE,
+ ResponseData
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ TotalReceivedSize += ResponseData->BodyLength;
+ }
+ DEBUG ((DEBUG_INFO, "Total of lengh of Response :%d\n", TotalReceivedSize));
+ }
+ DEBUG ((DEBUG_INFO, "RedfishRestExSendReceive()- EFI_STATUS: %r\n", Status));
+
+ON_EXIT:
+
+ if (ResponseData != NULL) {
+ FreePool (ResponseData);
+ }
+
+ if (EFI_ERROR (Status)) {
+ if (ResponseMessage->Data.Response != NULL) {
+ FreePool (ResponseMessage->Data.Response);
+ ResponseMessage->Data.Response = NULL;
+ }
+
+ if (ResponseMessage->Body != NULL) {
+ FreePool (ResponseMessage->Body);
+ ResponseMessage->Body = NULL;
+ }
+ }
+ return Status;
+}
+
+/**
+ Obtain the current time from this REST service instance.
+
+ The GetServiceTime() function is an optional interface to obtain the current time from
+ this REST service instance. If this REST service does not support to retrieve the time,
+ this function returns EFI_UNSUPPORTED. This function must returns EFI_UNSUPPORTED if
+ EFI_REST_EX_SERVICE_TYPE returned in EFI_REST_EX_SERVICE_INFO from GetService() is
+ EFI_REST_EX_SERVICE_UNSPECIFIC.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[out] Time A pointer to storage to receive a snapshot of the current time of
+ the REST service.
+
+ @retval EFI_SUCCESS operation succeeded.
+ @retval EFI_INVALID_PARAMETER This or Time are NULL.
+ @retval EFI_UNSUPPORTED The RESTful service does not support returning the time.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must
+ be executed and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExGetServiceTime (
+ IN EFI_REST_EX_PROTOCOL *This,
+ OUT EFI_TIME *Time
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ This function returns the information of REST service provided by this EFI REST EX driver instance.
+
+ The information such as the type of REST service and the access mode of REST EX driver instance
+ (In-band or Out-of-band) are described in EFI_REST_EX_SERVICE_INFO structure. For the vendor-specific
+ REST service, vendor-specific REST service information is returned in VendorSpecifcData.
+ REST EX driver designer is well know what REST service this REST EX driver instance intends to
+ communicate with. The designer also well know this driver instance is used to talk to BMC through
+ specific platform mechanism or talk to REST server through UEFI HTTP protocol. REST EX driver is
+ responsible to fill up the correct information in EFI_REST_EX_SERVICE_INFO. EFI_REST_EX_SERVICE_INFO
+ is referred by EFI REST clients to pickup the proper EFI REST EX driver instance to get and set resource.
+ GetService() is a basic and mandatory function which must be able to use even Configure() is not invoked
+ in previously.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[out] RestExServiceInfo Pointer to receive a pointer to EFI_REST_EX_SERVICE_INFO structure. The
+ format of EFI_REST_EX_SERVICE_INFO is version controlled for the future
+ extension. The version of EFI_REST_EX_SERVICE_INFO structure is returned
+ in the header within this structure. EFI REST client refers to the correct
+ format of structure according to the version number. The pointer to
+ EFI_REST_EX_SERVICE_INFO is a memory block allocated by EFI REST EX driver
+ instance. That is caller's responsibility to free this memory when this
+ structure is no longer needed. Refer to Related Definitions below for the
+ definitions of EFI_REST_EX_SERVICE_INFO structure.
+
+ @retval EFI_SUCCESS EFI_REST_EX_SERVICE_INFO is returned in RestExServiceInfo. This function
+ is not supported in this REST EX Protocol driver instance.
+ @retval EFI_UNSUPPORTED This function is not supported in this REST EX Protocol driver instance.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExGetService (
+ IN EFI_REST_EX_PROTOCOL *This,
+ OUT EFI_REST_EX_SERVICE_INFO **RestExServiceInfo
+ )
+{
+ EFI_TPL OldTpl;
+ RESTEX_INSTANCE *Instance;
+ EFI_REST_EX_SERVICE_INFO *ServiceInfo;
+
+ ServiceInfo = NULL;
+
+ if (This == NULL || RestExServiceInfo == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ Instance = RESTEX_INSTANCE_FROM_THIS (This);
+
+ ServiceInfo = AllocateZeroPool (sizeof (EFI_REST_EX_SERVICE_INFO));
+ if (ServiceInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CopyMem (ServiceInfo, &(Instance->Service->RestExServiceInfo), sizeof (EFI_REST_EX_SERVICE_INFO));
+
+ *RestExServiceInfo = ServiceInfo;
+
+ gBS->RestoreTPL (OldTpl);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function returns operational configuration of current EFI REST EX child instance.
+
+ This function returns the current configuration of EFI REST EX child instance. The format of
+ operational configuration depends on the implementation of EFI REST EX driver instance. For
+ example, HTTP-aware EFI REST EX driver instance uses EFI HTTP protocol as the undying protocol
+ to communicate with REST service. In this case, the type of configuration is
+ EFI_REST_EX_CONFIG_TYPE_HTTP returned from GetService(). EFI_HTTP_CONFIG_DATA is used as EFI REST
+ EX configuration format and returned to EFI REST client. User has to type cast RestExConfigData
+ to EFI_HTTP_CONFIG_DATA. For those non HTTP-aware REST EX driver instances, the type of configuration
+ is EFI_REST_EX_CONFIG_TYPE_UNSPECIFIC returned from GetService(). In this case, the format of
+ returning data could be non industrial. Instead, the format of configuration data is system/platform
+ specific definition such as BMC mechanism used in EFI REST EX driver instance. EFI REST client and
+ EFI REST EX driver instance have to refer to the specific system /platform spec which is out of UEFI scope.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[out] RestExConfigData Pointer to receive a pointer to EFI_REST_EX_CONFIG_DATA.
+ The memory allocated for configuration data should be freed
+ by caller. See Related Definitions for the details.
+
+ @retval EFI_SUCCESS EFI_REST_EX_CONFIG_DATA is returned in successfully.
+ @retval EFI_UNSUPPORTED This function is not supported in this REST EX Protocol driver instance.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must be
+ executed and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExGetModeData (
+ IN EFI_REST_EX_PROTOCOL *This,
+ OUT EFI_REST_EX_CONFIG_DATA *RestExConfigData
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ This function is used to configure EFI REST EX child instance.
+
+ This function is used to configure the setting of underlying protocol of REST EX child
+ instance. The type of configuration is according to the implementation of EFI REST EX
+ driver instance. For example, HTTP-aware EFI REST EX driver instance uses EFI HTTP protocol
+ as the undying protocol to communicate with REST service. The type of configuration is
+ EFI_REST_EX_CONFIG_TYPE_HTTP and RestExConfigData is the same format with EFI_HTTP_CONFIG_DATA.
+ Akin to HTTP configuration, REST EX child instance can be configure to use different HTTP
+ local access point for the data transmission. Multiple REST clients may use different
+ configuration of HTTP to distinguish themselves, such as to use the different TCP port.
+ For those non HTTP-aware REST EX driver instance, the type of configuration is
+ EFI_REST_EX_CONFIG_TYPE_UNSPECIFIC. RestExConfigData refers to the non industrial standard.
+ Instead, the format of configuration data is system/platform specific definition such as BMC.
+ In this case, EFI REST client and EFI REST EX driver instance have to refer to the specific
+ system/platform spec which is out of the UEFI scope. Besides GetService()function, no other
+ EFI REST EX functions can be executed by this instance until Configure()is executed and returns
+ successfully. All other functions must returns EFI_NOT_READY if this instance is not configured
+ yet. Set RestExConfigData to NULL means to put EFI REST EX child instance into the unconfigured
+ state.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[in] RestExConfigData Pointer to EFI_REST_EX_CONFIG_DATA. See Related Definitions in
+ GetModeData() protocol interface.
+
+ @retval EFI_SUCCESS EFI_REST_EX_CONFIG_DATA is set in successfully.
+ @retval EFI_DEVICE_ERROR Configuration for this REST EX child instance is failed with the given
+ EFI_REST_EX_CONFIG_DATA.
+ @retval EFI_UNSUPPORTED This function is not supported in this REST EX Protocol driver instance.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExConfigure (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_REST_EX_CONFIG_DATA RestExConfigData
+ )
+{
+ EFI_STATUS Status;
+ EFI_TPL OldTpl;
+ RESTEX_INSTANCE *Instance;
+
+ EFI_HTTP_CONFIG_DATA *HttpConfigData;
+
+ Status = EFI_SUCCESS;
+ HttpConfigData = NULL;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ Instance = RESTEX_INSTANCE_FROM_THIS (This);
+
+ if (RestExConfigData == NULL) {
+ //
+ // Set RestExConfigData to NULL means to put EFI REST EX child instance into the unconfigured state.
+ //
+ HttpIoDestroyIo (&(Instance->HttpIo));
+
+ if (Instance->ConfigData != NULL) {
+ if (((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConfigData.AccessPoint.IPv4Node != NULL) {
+ FreePool(((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConfigData.AccessPoint.IPv4Node);
+ }
+ FreePool(Instance->ConfigData);
+ Instance->ConfigData = NULL;
+ }
+
+ Instance->State = RESTEX_STATE_UNCONFIGED;
+ } else {
+ HttpConfigData = &((EFI_REST_EX_HTTP_CONFIG_DATA *)RestExConfigData)->HttpConfigData;
+ Status = Instance->HttpIo.Http->Configure (Instance->HttpIo.Http, HttpConfigData);
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+ Instance->HttpIo.Timeout = ((EFI_REST_EX_HTTP_CONFIG_DATA *)RestExConfigData)->SendReceiveTimeout;
+
+ Instance->ConfigData = AllocateZeroPool (sizeof (EFI_REST_EX_HTTP_CONFIG_DATA));
+ if (Instance->ConfigData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+ CopyMem (Instance->ConfigData, RestExConfigData, sizeof (EFI_REST_EX_HTTP_CONFIG_DATA));
+ if (HttpConfigData->LocalAddressIsIPv6 == TRUE) {
+ ((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConfigData.AccessPoint.IPv6Node = AllocateZeroPool (sizeof (EFI_HTTPv6_ACCESS_POINT));
+ if (((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConfigData.AccessPoint.IPv6Node == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+ CopyMem (
+ ((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConfigData.AccessPoint.IPv6Node,
+ HttpConfigData->AccessPoint.IPv6Node,
+ sizeof (EFI_HTTPv6_ACCESS_POINT)
+ );
+ } else {
+ ((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConfigData.AccessPoint.IPv4Node = AllocateZeroPool (sizeof (EFI_HTTPv4_ACCESS_POINT));
+ if (((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConfigData.AccessPoint.IPv4Node == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+ CopyMem (
+ ((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConfigData.AccessPoint.IPv4Node,
+ HttpConfigData->AccessPoint.IPv4Node,
+ sizeof (EFI_HTTPv4_ACCESS_POINT)
+ );
+ }
+ Instance->State = RESTEX_STATE_CONFIGED;
+ }
+
+ON_EXIT:
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+}
+
+/**
+ This function sends REST request to REST service and signal caller's event asynchronously when
+ the final response is received by REST EX Protocol driver instance.
+
+ The essential design of this function is to handle asynchronous send/receive implicitly according
+ to REST service asynchronous request mechanism. Caller will get the notification once the response
+ is returned from REST service.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[in] RequestMessage This is the HTTP request message sent to REST service. Set RequestMessage
+ to NULL to cancel the previous asynchronous request associated with the
+ corresponding RestExToken. See descriptions for the details.
+ @param[in] RestExToken REST EX token which REST EX Protocol instance uses to notify REST client
+ the status of response of asynchronous REST request. See related definition
+ of EFI_REST_EX_TOKEN.
+ @param[in] TimeOutInMilliSeconds The pointer to the timeout in milliseconds which REST EX Protocol driver
+ instance refers as the duration to drop asynchronous REST request. NULL
+ pointer means no timeout for this REST request. REST EX Protocol driver
+ signals caller's event with EFI_STATUS set to EFI_TIMEOUT in RestExToken
+ if REST EX Protocol can't get the response from REST service within
+ TimeOutInMilliSeconds.
+
+ @retval EFI_SUCCESS Asynchronous REST request is established.
+ @retval EFI_UNSUPPORTED This REST EX Protocol driver instance doesn't support asynchronous request.
+ @retval EFI_TIMEOUT Asynchronous REST request is not established and timeout is expired.
+ @retval EFI_ABORT Previous asynchronous REST request has been canceled.
+ @retval EFI_DEVICE_ERROR Otherwise, returns EFI_DEVICE_ERROR for other errors according to HTTP Status Code.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must be executed
+ and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExAyncSendReceive (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage OPTIONAL,
+ IN EFI_REST_EX_TOKEN *RestExToken,
+ IN UINTN *TimeOutInMilliSeconds OPTIONAL
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ This function sends REST request to a REST Event service and signals caller's event
+ token asynchronously when the URI resource change event is received by REST EX
+ Protocol driver instance.
+
+ The essential design of this function is to monitor event implicitly according to
+ REST service event service mechanism. Caller will get the notification if certain
+ resource is changed.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[in] RequestMessage This is the HTTP request message sent to REST service. Set RequestMessage
+ to NULL to cancel the previous event service associated with the corresponding
+ RestExToken. See descriptions for the details.
+ @param[in] RestExToken REST EX token which REST EX Protocol driver instance uses to notify REST client
+ the URI resource which monitored by REST client has been changed. See the related
+ definition of EFI_REST_EX_TOKEN in EFI_REST_EX_PROTOCOL.AsyncSendReceive().
+
+ @retval EFI_SUCCESS Asynchronous REST request is established.
+ @retval EFI_UNSUPPORTED This REST EX Protocol driver instance doesn't support asynchronous request.
+ @retval EFI_ABORT Previous asynchronous REST request has been canceled or event subscription has been
+ delete from service.
+ @retval EFI_DEVICE_ERROR Otherwise, returns EFI_DEVICE_ERROR for other errors according to HTTP Status Code.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must be executed
+ and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExEventService (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage OPTIONAL,
+ IN EFI_REST_EX_TOKEN *RestExToken
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
--
2.17.1
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH] RedfishPkg/RedfishRestExDxe: Implementation of EFI REST EX Protocol
2020-12-07 6:54 [PATCH] RedfishPkg/RedfishRestExDxe: Implementation of EFI REST EX Protocol Abner Chang
@ 2020-12-10 3:08 ` Nickle Wang
0 siblings, 0 replies; 2+ messages in thread
From: Nickle Wang @ 2020-12-10 3:08 UTC (permalink / raw)
To: Chang, Abner (HPS SW/FW Technologist), devel@edk2.groups.io
Cc: Jiaxin Wu, Siyuan Fu, Fan Wang, Jiewen Yao,
O'Hanley, Peter (EXL)
Reviewed-by: Nickle Wang <nickle.wang@hpe.com>
> -----Original Message-----
> From: Chang, Abner (HPS SW/FW Technologist) <abner.chang@hpe.com>
> Sent: Monday, December 7, 2020 2:54 PM
> To: devel@edk2.groups.io
> Cc: Jiaxin Wu <jiaxin.wu@intel.com>; Siyuan Fu <siyuan.fu@intel.com>; Fan
> Wang <fan.wang@intel.com>; Jiewen Yao <jiewen.yao@intel.com>; Wang,
> Nickle (HPS SW) <nickle.wang@hpe.com>; O'Hanley, Peter (EXL)
> <peter.ohanley@hpe.com>
> Subject: [PATCH] RedfishPkg/RedfishRestExDxe: Implementation of EFI REST
> EX Protocol
>
> BZ#: 2908
> https://bugzilla.tianocore.org/show_bug.cgi?id=2908
>
> Implementation of EFI EX Protocol according to UEFI spec
> 2.8 Section 29.7.2 EFI REST EX Protocol.
> This is the network stack based EFI REST EX protocol instance.
>
> Signed-off-by: Jiaxin Wu <jiaxin.wu@intel.com>
> Signed-off-by: Siyuan Fu <siyuan.fu@intel.com>
> Signed-off-by: Fan Wang <fan.wang@intel.com>
> Signed-off-by: Ting Ye <ting.ye@intel.com>
> Signed-off-by: Abner Chang <abner.chang@hpe.com>
>
> Cc: Jiaxin Wu <jiaxin.wu@intel.com>
> Cc: Siyuan Fu <siyuan.fu@intel.com>
> Cc: Fan Wang <fan.wang@intel.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Nickle Wang <nickle.wang@hpe.com>
> Cc: Peter O'Hanley <peter.ohanley@hpe.com>
> ---
> RedfishPkg/Redfish.fdf.inc | 1 +
> RedfishPkg/RedfishComponents.dsc.inc | 1 +
> RedfishPkg/RedfishPkg.dsc | 4 +
> RedfishPkg/RedfishRestExDxe/ComponentName.c | 222 +++++
> .../RedfishRestExDxe/RedfishRestExDriver.c | 831 ++++++++++++++++++
> .../RedfishRestExDxe/RedfishRestExDriver.h | 650 ++++++++++++++
> .../RedfishRestExDxe/RedfishRestExDxe.inf | 63 ++
> .../RedfishRestExDxe/RedfishRestExDxe.uni | 16 +
> .../RedfishRestExDxeExtra.uni | 15 +
> .../RedfishRestExDxe/RedfishRestExImpl.c | 157 ++++
> .../RedfishRestExDxe/RedfishRestExInternal.h | 611 +++++++++++++
> .../RedfishRestExDxe/RedfishRestExProtocol.c | 735 ++++++++++++++++
> 12 files changed, 3306 insertions(+)
> create mode 100644 RedfishPkg/RedfishRestExDxe/ComponentName.c
> create mode 100644 RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.c
> create mode 100644 RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.h
> create mode 100644 RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf
> create mode 100644 RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.uni
> create mode 100644
> RedfishPkg/RedfishRestExDxe/RedfishRestExDxeExtra.uni
> create mode 100644 RedfishPkg/RedfishRestExDxe/RedfishRestExImpl.c
> create mode 100644 RedfishPkg/RedfishRestExDxe/RedfishRestExInternal.h
> create mode 100644 RedfishPkg/RedfishRestExDxe/RedfishRestExProtocol.c
>
> diff --git a/RedfishPkg/Redfish.fdf.inc b/RedfishPkg/Redfish.fdf.inc
> index 19de479a80..429156aa78 100644
> --- a/RedfishPkg/Redfish.fdf.inc
> +++ b/RedfishPkg/Redfish.fdf.inc
> @@ -13,4 +13,5 @@
> !if $(REDFISH_ENABLE) == TRUE
> INF RedfishPkg/RestJsonStructureDxe/RestJsonStructureDxe.inf
> INF RedfishPkg/RedfishHostInterfaceDxe/RedfishHostInterfaceDxe.inf
> + INF RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf
> !endif
> diff --git a/RedfishPkg/RedfishComponents.dsc.inc
> b/RedfishPkg/RedfishComponents.dsc.inc
> index ac1b57ed8f..3b9429db09 100644
> --- a/RedfishPkg/RedfishComponents.dsc.inc
> +++ b/RedfishPkg/RedfishComponents.dsc.inc
> @@ -15,4 +15,5 @@
> !if $(REDFISH_ENABLE) == TRUE
> RedfishPkg/RestJsonStructureDxe/RestJsonStructureDxe.inf
> RedfishPkg/RedfishHostInterfaceDxe/RedfishHostInterfaceDxe.inf
> + RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf
> !endif
> diff --git a/RedfishPkg/RedfishPkg.dsc b/RedfishPkg/RedfishPkg.dsc
> index 94e7127bc6..c05e81af7b 100644
> --- a/RedfishPkg/RedfishPkg.dsc
> +++ b/RedfishPkg/RedfishPkg.dsc
> @@ -32,6 +32,10 @@
>
> DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/Bas
> eDebugPrintErrorLevelLib.inf
> PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
>
> RedfishPlatformHostInterfaceLib|RedfishPkg/Library/PlatformHostInterface
> LibNull/PlatformHostInterfaceLibNull.inf
> + HttpLib|NetworkPkg/Library/DxeHttpLib/DxeHttpLib.inf
> + HttpIoLib|NetworkPkg/Library/DxeHttpIoLib/DxeHttpIoLib.inf
> + NetLib|NetworkPkg/Library/DxeNetLib/DxeNetLib.inf
> + DpcLib|NetworkPkg/Library/DxeDpcLib/DxeDpcLib.inf
>
> [LibraryClasses.ARM, LibraryClasses.AARCH64]
> #
> diff --git a/RedfishPkg/RedfishRestExDxe/ComponentName.c
> b/RedfishPkg/RedfishRestExDxe/ComponentName.c
> new file mode 100644
> index 0000000000..3674178412
> --- /dev/null
> +++ b/RedfishPkg/RedfishRestExDxe/ComponentName.c
> @@ -0,0 +1,222 @@
> +/** @file
> + Implementation of EFI_COMPONENT_NAME_PROTOCOL and
> EFI_COMPONENT_NAME2_PROTOCOL
> + protocol.
> +
> + Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> + (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +#include <Uefi.h>
> +
> +#include <Library/UefiLib.h>
> +
> +#include <Protocol/ComponentName.h>
> +#include <Protocol/ComponentName2.h>
> +
> +//
> +// EFI Component Name Functions
> +//
> +/**
> + Retrieves a Unicode string that is the user-readable name of the EFI Driver.
> +
> + @param[in] This A pointer to the
> EFI_COMPONENT_NAME_PROTOCOL instance.
> + @param[in] Language A pointer to a three-character ISO 639-2 language
> identifier.
> + This is the language of the driver name that that the caller
> + is requesting, and it must match one of the languages specified
> + in SupportedLanguages. The number of languages supported
> by a
> + driver is up to the driver writer.
> + @param[out] DriverName A pointer to the Unicode string to return. This
> Unicode string
> + is the name of the driver specified by This in the language
> + specified by Language.
> +
> + @retval EFI_SUCCESS The Unicode string for the Driver specified by This
> + and the language specified by Language was returned
> + in DriverName.
> + @retval EFI_INVALID_PARAMETER Language is NULL.
> + @retval EFI_INVALID_PARAMETER DriverName is NULL.
> + @retval EFI_UNSUPPORTED The driver specified by This does not
> support the
> + language specified by Language.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExComponentNameGetDriverName (
> + IN EFI_COMPONENT_NAME_PROTOCOL *This,
> + IN CHAR8 *Language,
> + OUT CHAR16 **DriverName
> + );
> +
> +/**
> + Retrieves a Unicode string that is the user readable name of the controller
> + that is being managed by an EFI Driver.
> +
> + @param[in] This A pointer to the
> EFI_COMPONENT_NAME_PROTOCOL instance.
> + @param[in] ControllerHandle The handle of a controller that the driver
> specified by
> + This is managing. This handle specifies the controller
> + whose name is to be returned.
> + @param[in] ChildHandle The handle of the child controller to retrieve
> the name
> + of. This is an optional parameter that may be NULL. It
> + will be NULL for device drivers. It will also be NULL
> + for a bus drivers that wish to retrieve the name of the
> + bus controller. It will not be NULL for a bus driver
> + that wishes to retrieve the name of a child controller.
> + @param[in] Language A pointer to a three character ISO 639-2
> language
> + identifier. This is the language of the controller name
> + that the caller is requesting, and it must match one
> + of the languages specified in SupportedLanguages. The
> + number of languages supported by a driver is up to the
> + driver writer.
> + @param[out] ControllerName A pointer to the Unicode string to return.
> This Unicode
> + string is the name of the controller specified by
> + ControllerHandle and ChildHandle in the language specified
> + by Language, from the point of view of the driver specified
> + by This.
> +
> + @retval EFI_SUCCESS The Unicode string for the user-readable name
> in the
> + language specified by Language for the driver
> + specified by This was returned in DriverName.
> + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
> + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a
> valid EFI_HANDLE.
> + @retval EFI_INVALID_PARAMETER Language is NULL.
> + @retval EFI_INVALID_PARAMETER ControllerName is NULL.
> + @retval EFI_UNSUPPORTED The driver specified by This is not currently
> managing
> + the controller specified by ControllerHandle and
> + ChildHandle.
> + @retval EFI_UNSUPPORTED The driver specified by This does not
> support the
> + language specified by Language.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExComponentNameGetControllerName (
> + IN EFI_COMPONENT_NAME_PROTOCOL *This,
> + IN EFI_HANDLE ControllerHandle,
> + IN EFI_HANDLE ChildHandle OPTIONAL,
> + IN CHAR8 *Language,
> + OUT CHAR16 **ControllerName
> + );
> +
> +///
> +/// Component Name Protocol instance
> +///
> +GLOBAL_REMOVE_IF_UNREFERENCED
> +EFI_COMPONENT_NAME_PROTOCOL gRedfishRestExComponentName = {
> + RedfishRestExComponentNameGetDriverName,
> + RedfishRestExComponentNameGetControllerName,
> + "eng"
> +};
> +
> +///
> +/// Component Name 2 Protocol instance
> +///
> +GLOBAL_REMOVE_IF_UNREFERENCED
> +EFI_COMPONENT_NAME2_PROTOCOL gRedfishRestExComponentName2
> = {
> + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)
> RedfishRestExComponentNameGetDriverName,
> + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)
> RedfishRestExComponentNameGetControllerName,
> + "en"
> +};
> +
> +///
> +/// Table of driver names
> +///
> +GLOBAL_REMOVE_IF_UNREFERENCED
> +EFI_UNICODE_STRING_TABLE mRedfishRestExDriverNameTable[] = {
> + { "eng;en", (CHAR16 *)L"Redfish RestEx Network Service Driver" },
> + { NULL, NULL }
> +};
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE
> *gRedfishRestExControllerNameTable = NULL;
> +
> +/**
> + Retrieves a Unicode string that is the user-readable name of the EFI Driver.
> +
> + @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL
> instance.
> + @param[in] Language A pointer to a three-character ISO 639-2 language
> identifier.
> + This is the language of the driver name that that the caller
> + is requesting, and it must match one of the languages specified
> + in SupportedLanguages. The number of languages supported
> by a
> + driver is up to the driver writer.
> + @param[out] DriverName A pointer to the Unicode string to return. This
> Unicode string
> + is the name of the driver specified by This in the language
> + specified by Language.
> +
> + @retval EFI_SUCCESS The Unicode string for the Driver specified by
> This
> + and the language specified by Language was returned
> + in DriverName.
> + @retval EFI_INVALID_PARAMETER Language is NULL.
> + @retval EFI_INVALID_PARAMETER DriverName is NULL.
> + @retval EFI_UNSUPPORTED The driver specified by This does not
> support the
> + language specified by Language.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExComponentNameGetDriverName (
> + IN EFI_COMPONENT_NAME_PROTOCOL *This,
> + IN CHAR8 *Language,
> + OUT CHAR16 **DriverName
> + )
> +{
> + return LookupUnicodeString2 (
> + Language,
> + This->SupportedLanguages,
> + mRedfishRestExDriverNameTable,
> + DriverName,
> + (BOOLEAN)(This == &gRedfishRestExComponentName)
> + );
> +}
> +
> +/**
> + Retrieves a Unicode string that is the user readable name of the controller
> + that is being managed by an EFI Driver.
> +
> + @param[in] This A pointer to the
> EFI_COMPONENT_NAME_PROTOCOL instance.
> + @param[in] ControllerHandle The handle of a controller that the driver
> specified by
> + This is managing. This handle specifies the controller
> + whose name is to be returned.
> + @param[in] ChildHandle The handle of the child controller to retrieve
> the name
> + of. This is an optional parameter that may be NULL. It
> + will be NULL for device drivers. It will also be NULL
> + for a bus drivers that wish to retrieve the name of the
> + bus controller. It will not be NULL for a bus driver
> + that wishes to retrieve the name of a child controller.
> + @param[in] Language A pointer to a three character ISO 639-2 language
> + identifier. This is the language of the controller name
> + that the caller is requesting, and it must match one
> + of the languages specified in SupportedLanguages. The
> + number of languages supported by a driver is up to the
> + driver writer.
> + @param[out] ControllerName A pointer to the Unicode string to return.
> This Unicode
> + string is the name of the controller specified by
> + ControllerHandle and ChildHandle in the language specified
> + by Language, from the point of view of the driver specified
> + by This.
> +
> + @retval EFI_SUCCESS The Unicode string for the user-readable name
> in the
> + language specified by Language for the driver
> + specified by This was returned in DriverName.
> + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
> + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a
> valid EFI_HANDLE.
> + @retval EFI_INVALID_PARAMETER Language is NULL.
> + @retval EFI_INVALID_PARAMETER ControllerName is NULL.
> + @retval EFI_UNSUPPORTED The driver specified by This is not currently
> managing
> + the controller specified by ControllerHandle and
> + ChildHandle.
> + @retval EFI_UNSUPPORTED The driver specified by This does not
> support the
> + language specified by Language.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExComponentNameGetControllerName (
> + IN EFI_COMPONENT_NAME_PROTOCOL *This,
> + IN EFI_HANDLE ControllerHandle,
> + IN EFI_HANDLE ChildHandle OPTIONAL,
> + IN CHAR8 *Language,
> + OUT CHAR16 **ControllerName
> + )
> +{
> + return EFI_UNSUPPORTED;
> +}
> diff --git a/RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.c
> b/RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.c
> new file mode 100644
> index 0000000000..87327a8549
> --- /dev/null
> +++ b/RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.c
> @@ -0,0 +1,831 @@
> +/** @file
> + The driver binding and service binding protocol for Redfish RestExDxe
> driver.
> +
> + Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> + (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Uefi.h>
> +#include "RedfishRestExDriver.h"
> +
> +EFI_DRIVER_BINDING_PROTOCOL gRedfishRestExDriverBinding = {
> + RedfishRestExDriverBindingSupported,
> + RedfishRestExDriverBindingStart,
> + RedfishRestExDriverBindingStop,
> + REDFISH_RESTEX_DRIVER_VERSION,
> + NULL,
> + NULL
> +};
> +
> +EFI_SERVICE_BINDING_PROTOCOL mRedfishRestExServiceBinding = {
> + RedfishRestExServiceBindingCreateChild,
> + RedfishRestExServiceBindingDestroyChild
> +};
> +
> +/**
> + Callback function which provided by user to remove one node in
> NetDestroyLinkList process.
> +
> + @param[in] Entry The entry to be removed.
> + @param[in] Context Pointer to the callback context corresponds to
> the Context in NetDestroyLinkList.
> +
> + @retval EFI_SUCCESS The entry has been removed successfully.
> + @retval Others Fail to remove the entry.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RestExDestroyChildEntryInHandleBuffer (
> + IN LIST_ENTRY *Entry,
> + IN VOID *Context
> + )
> +{
> + RESTEX_INSTANCE *Instance;
> + EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
> + UINTN NumberOfChildren;
> + EFI_HANDLE *ChildHandleBuffer;
> +
> + if (Entry == NULL || Context == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + Instance = NET_LIST_USER_STRUCT_S (Entry, RESTEX_INSTANCE, Link,
> RESTEX_INSTANCE_SIGNATURE);
> + ServiceBinding = ((RESTEX_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
> *) Context)->ServiceBinding;
> + NumberOfChildren =
> ((RESTEX_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)-
> >NumberOfChildren;
> + ChildHandleBuffer =
> ((RESTEX_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)-
> >ChildHandleBuffer;
> +
> + if (!NetIsInHandleBuffer (Instance->ChildHandle, NumberOfChildren,
> ChildHandleBuffer)) {
> + return EFI_SUCCESS;
> + }
> +
> + return ServiceBinding->DestroyChild (ServiceBinding, Instance-
> >ChildHandle);
> +}
> +
> +/**
> + Destroy the RestEx instance and recycle the resources.
> +
> + @param[in] Instance The pointer to the RestEx instance.
> +
> +**/
> +VOID
> +RestExDestroyInstance (
> + IN RESTEX_INSTANCE *Instance
> + )
> +{
> + HttpIoDestroyIo (&(Instance->HttpIo));
> +
> + FreePool (Instance);
> +}
> +
> +/**
> + Create the RestEx instance and initialize it.
> +
> + @param[in] Service The pointer to the RestEx service.
> + @param[out] Instance The pointer to the RestEx instance.
> +
> + @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
> + @retval EFI_SUCCESS The RestEx instance is created.
> +
> +**/
> +EFI_STATUS
> +RestExCreateInstance (
> + IN RESTEX_SERVICE *Service,
> + OUT RESTEX_INSTANCE **Instance
> + )
> +{
> + RESTEX_INSTANCE *RestExIns;
> + EFI_STATUS Status;
> +
> + *Instance = NULL;
> + Status = EFI_SUCCESS;
> +
> + RestExIns = AllocateZeroPool (sizeof (RESTEX_INSTANCE));
> + if (RestExIns == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + RestExIns->Signature = RESTEX_INSTANCE_SIGNATURE;
> + InitializeListHead (&RestExIns->Link);
> + RestExIns->InDestroy = FALSE;
> + RestExIns->Service = Service;
> +
> + CopyMem (&RestExIns->RestEx, &mRedfishRestExProtocol, sizeof
> (RestExIns->RestEx));
> +
> + //
> + // Create a HTTP_IO to access the HTTP service.
> + //
> + Status = HttpIoCreateIo (
> + RestExIns->Service->ImageHandle,
> + RestExIns->Service->ControllerHandle,
> + IP_VERSION_4,
> + NULL,
> + NULL,
> + NULL,
> + &(RestExIns->HttpIo)
> + );
> + if (EFI_ERROR (Status)) {
> + FreePool (RestExIns);
> + return Status;
> + }
> +
> + *Instance = RestExIns;
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Release all the resource used the RestEx service binding instance.
> +
> + @param[in] RestExSb The RestEx service binding instance.
> +
> +**/
> +VOID
> +RestExDestroyService (
> + IN RESTEX_SERVICE *RestExSb
> + )
> +{
> + if (RestExSb->HttpChildHandle != NULL) {
> + gBS->CloseProtocol (
> + RestExSb->HttpChildHandle,
> + &gEfiHttpProtocolGuid,
> + RestExSb->ImageHandle,
> + RestExSb->ControllerHandle
> + );
> +
> + NetLibDestroyServiceChild (
> + RestExSb->ControllerHandle,
> + RestExSb->ImageHandle,
> + &gEfiHttpServiceBindingProtocolGuid,
> + RestExSb->HttpChildHandle
> + );
> +
> + RestExSb->HttpChildHandle = NULL;
> + }
> +
> + gBS->UninstallProtocolInterface (
> + RestExSb->ControllerHandle,
> + &gEfiCallerIdGuid,
> + &RestExSb->Id
> + );
> +
> + FreePool (RestExSb);
> +}
> +
> +/**
> + Check the NIC controller handle represents an in-band or out-of-band
> Redfish host
> + interface device. If not in-band, treat it as out-of-band interface device.
> +
> + @param[in] Controller The NIC controller handle needs to be checked.
> +
> + @return EFI_REST_EX_SERVICE_ACCESS_MODE of the device.
> +
> +**/
> +EFI_REST_EX_SERVICE_ACCESS_MODE
> +RestExServiceAccessMode (
> + IN EFI_HANDLE Controller
> + )
> +{
> + //
> + // This is EFI REST EX driver instance to connect
> + // to Redfish service using HTTP in out of band.
> + //
> + if (FixedPcdGetBool (PcdRedfishRestExServiceAccessModeInBand)) {
> + return EfiRestExServiceInBandAccess;
> + } else {
> + return EfiRestExServiceOutOfBandAccess;
> + }
> +}
> +
> +/**
> + Create then initialize a RestEx service binding instance.
> +
> + @param[in] Controller The controller to install the RestEx service
> + binding on.
> + @param[in] Image The driver binding image of the RestEx driver.
> + @param[out] Service The variable to receive the created service
> + binding instance.
> +
> + @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the
> instance.
> + @retval EFI_SUCCESS The service instance is created for the controller.
> +
> +**/
> +EFI_STATUS
> +RestExCreateService (
> + IN EFI_HANDLE Controller,
> + IN EFI_HANDLE Image,
> + OUT RESTEX_SERVICE **Service
> + )
> +{
> + EFI_STATUS Status;
> + RESTEX_SERVICE *RestExSb;
> +
> + Status = EFI_SUCCESS;
> + RestExSb = NULL;
> +
> + *Service = NULL;
> +
> + RestExSb = AllocateZeroPool (sizeof (RESTEX_SERVICE));
> + if (RestExSb == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + RestExSb->Signature = RESTEX_SERVICE_SIGNATURE;
> +
> + RestExSb->ServiceBinding = mRedfishRestExServiceBinding;
> +
> + RestExSb->RestExChildrenNum = 0;
> + InitializeListHead (&RestExSb->RestExChildrenList);
> +
> + RestExSb->ControllerHandle = Controller;
> + RestExSb->ImageHandle = Image;
> +
> + RestExSb-
> >RestExServiceInfo.EfiRestExServiceInfoV10.EfiRestExServiceInfoHeader.Len
> gth = sizeof (EFI_REST_EX_SERVICE_INFO);
> + RestExSb-
> >RestExServiceInfo.EfiRestExServiceInfoV10.EfiRestExServiceInfoHeader.Res
> tServiceInfoVer.Major = 1;
> + RestExSb-
> >RestExServiceInfo.EfiRestExServiceInfoV10.EfiRestExServiceInfoHeader.Res
> tServiceInfoVer.Minor = 0;
> + RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.RestServiceType =
> EfiRestExServiceRedfish;
> + RestExSb-
> >RestExServiceInfo.EfiRestExServiceInfoV10.RestServiceAccessMode =
> RestExServiceAccessMode (Controller);
> + RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.RestExConfigType =
> EfiRestExConfigHttp;
> + RestExSb-
> >RestExServiceInfo.EfiRestExServiceInfoV10.RestExConfigDataLength =
> sizeof (EFI_REST_EX_HTTP_CONFIG_DATA);
> +
> + Status = gBS->InstallProtocolInterface (
> + &Controller,
> + &gEfiCallerIdGuid,
> + EFI_NATIVE_INTERFACE,
> + &RestExSb->Id
> + );
> + if (EFI_ERROR (Status)) {
> + FreePool (RestExSb);
> + RestExSb = NULL;
> + }
> +
> + *Service = RestExSb;
> + return Status;
> +}
> +
> +/**
> + This is the declaration of an EFI image entry point. This entry point is
> + the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
> + both device drivers and bus drivers.
> +
> + @param[in] ImageHandle The firmware allocated handle for the UEFI
> image.
> + @param[in] SystemTable A pointer to the EFI System Table.
> +
> + @retval EFI_SUCCESS The operation completed successfully.
> + @retval Others An unexpected error occurred.
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExDriverEntryPoint (
> + IN EFI_HANDLE ImageHandle,
> + IN EFI_SYSTEM_TABLE *SystemTable
> + )
> +{
> + EFI_STATUS Status;
> +
> + Status = EFI_SUCCESS;
> +
> + //
> + // Install the RestEx Driver Binding Protocol.
> + //
> + Status = EfiLibInstallDriverBindingComponentName2 (
> + ImageHandle,
> + SystemTable,
> + &gRedfishRestExDriverBinding,
> + ImageHandle,
> + &gRedfishRestExComponentName,
> + &gRedfishRestExComponentName2
> + );
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + return Status;
> +}
> +
> +/**
> + Tests to see if this driver supports a given controller. If a child device is
> provided,
> + it further tests to see if this driver supports creating a handle for the
> specified child device.
> +
> + This function checks to see if the driver specified by This supports the
> device specified by
> + ControllerHandle. Drivers will typically use the device path attached to
> + ControllerHandle and/or the services from the bus I/O abstraction
> attached to
> + ControllerHandle to determine if the driver supports ControllerHandle.
> This function
> + may be called many times during platform initialization. In order to reduce
> boot times, the tests
> + performed by this function must be very small, and take as little time as
> possible to execute. This
> + function must not change the state of any hardware devices, and this
> function must be aware that the
> + device specified by ControllerHandle may already be managed by the
> same driver or a
> + different driver. This function must match its calls to AllocatePages() with
> FreePages(),
> + AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
> + Because ControllerHandle may have been previously started by the same
> driver, if a protocol is
> + already in the opened state, then it must not be closed with
> CloseProtocol(). This is required
> + to guarantee the state of ControllerHandle is not modified by this function.
> +
> + @param[in] This A pointer to the
> EFI_DRIVER_BINDING_PROTOCOL instance.
> + @param[in] ControllerHandle The handle of the controller to test. This
> handle
> + must support a protocol interface that supplies
> + an I/O abstraction to the driver.
> + @param[in] RemainingDevicePath A pointer to the remaining portion of a
> device path. This
> + parameter is ignored by device drivers, and is optional for
> bus
> + drivers. For bus drivers, if this parameter is not NULL, then
> + the bus driver must determine if the bus controller
> specified
> + by ControllerHandle and the child controller specified
> + by RemainingDevicePath are both supported by this
> + bus driver.
> +
> + @retval EFI_SUCCESS The device specified by ControllerHandle and
> + RemainingDevicePath is supported by the driver specified
> by This.
> + @retval EFI_ALREADY_STARTED The device specified by
> ControllerHandle and
> + RemainingDevicePath is already being managed by the
> driver
> + specified by This.
> + @retval EFI_ACCESS_DENIED The device specified by ControllerHandle
> and
> + RemainingDevicePath is already being managed by a
> different
> + driver or an application that requires exclusive access.
> + Currently not implemented.
> + @retval EFI_UNSUPPORTED The device specified by ControllerHandle
> and
> + RemainingDevicePath is not supported by the driver
> specified by This.
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExDriverBindingSupported (
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
> + IN EFI_HANDLE ControllerHandle,
> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
> + )
> +{
> +
> + //
> + // Test for the HttpServiceBinding Protocol.
> + //
> + return gBS->OpenProtocol (
> + ControllerHandle,
> + &gEfiHttpServiceBindingProtocolGuid,
> + NULL,
> + This->DriverBindingHandle,
> + ControllerHandle,
> + EFI_OPEN_PROTOCOL_TEST_PROTOCOL
> + );
> +
> +}
> +
> +/**
> + Starts a device controller or a bus controller.
> +
> + The Start() function is designed to be invoked from the EFI boot service
> ConnectController().
> + As a result, much of the error checking on the parameters to Start() has
> been moved into this
> + common boot service. It is legal to call Start() from other locations,
> + but the following calling restrictions must be followed, or the system
> behavior will not be deterministic.
> + 1. ControllerHandle must be a valid EFI_HANDLE.
> + 2. If RemainingDevicePath is not NULL, then it must be a pointer to a
> naturally aligned
> + EFI_DEVICE_PATH_PROTOCOL.
> + 3. Prior to calling Start(), the Supported() function for the driver specified
> by This must
> + have been called with the same calling parameters, and Supported()
> must have returned EFI_SUCCESS.
> +
> + @param[in] This A pointer to the
> EFI_DRIVER_BINDING_PROTOCOL instance.
> + @param[in] ControllerHandle The handle of the controller to start. This
> handle
> + must support a protocol interface that supplies
> + an I/O abstraction to the driver.
> + @param[in] RemainingDevicePath A pointer to the remaining portion of a
> device path. This
> + parameter is ignored by device drivers, and is optional for
> bus
> + drivers. For a bus driver, if this parameter is NULL, then
> handles
> + for all the children of Controller are created by this driver.
> + If this parameter is not NULL and the first Device Path
> Node is
> + not the End of Device Path Node, then only the handle for
> the
> + child device specified by the first Device Path Node of
> + RemainingDevicePath is created by this driver.
> + If the first Device Path Node of RemainingDevicePath is
> + the End of Device Path Node, no child handle is created by
> this
> + driver.
> +
> + @retval EFI_SUCCESS The device was started.
> + @retval EFI_DEVICE_ERROR The device could not be started due to a
> device error.Currently not implemented.
> + @retval EFI_OUT_OF_RESOURCES The request could not be completed
> due to a lack of resources.
> + @retval Others The driver failded to start the device.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExDriverBindingStart (
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
> + IN EFI_HANDLE ControllerHandle,
> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
> + )
> +{
> + RESTEX_SERVICE *RestExSb;
> + EFI_STATUS Status;
> + UINT32 *Id;
> + VOID *Interface;
> +
> + Status = gBS->OpenProtocol (
> + ControllerHandle,
> + &gEfiCallerIdGuid,
> + (VOID **) &Id,
> + This->DriverBindingHandle,
> + ControllerHandle,
> + EFI_OPEN_PROTOCOL_GET_PROTOCOL
> + );
> + if (!EFI_ERROR (Status)) {
> + return EFI_ALREADY_STARTED;
> + }
> +
> + Status = RestExCreateService (ControllerHandle, This-
> >DriverBindingHandle, &RestExSb);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + ASSERT (RestExSb != NULL);
> +
> + //
> + // Create a Http child instance, but do not configure it.
> + // This will establish the parent-child relationship.
> + //
> + Status = NetLibCreateServiceChild (
> + ControllerHandle,
> + This->DriverBindingHandle,
> + &gEfiHttpServiceBindingProtocolGuid,
> + &RestExSb->HttpChildHandle
> + );
> + if (EFI_ERROR (Status)) {
> + goto ON_ERROR;
> + }
> +
> + Status = gBS->OpenProtocol (
> + RestExSb->HttpChildHandle,
> + &gEfiHttpProtocolGuid,
> + &Interface,
> + This->DriverBindingHandle,
> + ControllerHandle,
> + EFI_OPEN_PROTOCOL_BY_DRIVER
> + );
> + if (EFI_ERROR (Status)) {
> + goto ON_ERROR;
> + }
> +
> + //
> + // Install the RestEx ServiceBinding Protocol onto ControllerHandle.
> + //
> + Status = gBS->InstallMultipleProtocolInterfaces (
> + &ControllerHandle,
> + &gEfiRestExServiceBindingProtocolGuid,
> + &RestExSb->ServiceBinding,
> + NULL
> + );
> + if (EFI_ERROR (Status)) {
> + goto ON_ERROR;
> + }
> +
> + return EFI_SUCCESS;
> +
> +ON_ERROR:
> + RestExDestroyService (RestExSb);
> +
> + return Status;
> +}
> +
> +/**
> + Stops a device controller or a bus controller.
> +
> + The Stop() function is designed to be invoked from the EFI boot service
> DisconnectController().
> + As a result, much of the error checking on the parameters to Stop() has
> been moved
> + into this common boot service. It is legal to call Stop() from other locations,
> + but the following calling restrictions must be followed, or the system
> behavior will not be deterministic.
> + 1. ControllerHandle must be a valid EFI_HANDLE that was used on a
> previous call to this
> + same driver's Start() function.
> + 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a
> valid
> + EFI_HANDLE. In addition, all of these handles must have been created in
> this driver's
> + Start() function, and the Start() function must have called OpenProtocol()
> on
> + ControllerHandle with an Attribute of
> EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
> +
> + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL
> instance.
> + @param[in] ControllerHandle A handle to the device being stopped. The
> handle must
> + support a bus specific I/O protocol for the driver
> + to use to stop the device.
> + @param[in] NumberOfChildren The number of child device handles in
> ChildHandleBuffer.
> + @param[in] ChildHandleBuffer An array of child handles to be freed. May
> be NULL
> + if NumberOfChildren is 0.
> +
> + @retval EFI_SUCCESS The device was stopped.
> + @retval EFI_DEVICE_ERROR The device could not be stopped due to a
> device error.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExDriverBindingStop (
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
> + IN EFI_HANDLE ControllerHandle,
> + IN UINTN NumberOfChildren,
> + IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
> + )
> +{
> + EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
> + RESTEX_SERVICE *RestExSb;
> + EFI_HANDLE NicHandle;
> + EFI_STATUS Status;
> + LIST_ENTRY *List;
> + RESTEX_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;
> +
> + //
> + // RestEx driver opens HTTP child, So, Controller is a HTTP
> + // child handle. Locate the Nic handle first. Then get the
> + // RestEx private data back.
> + //
> + NicHandle = NetLibGetNicHandle (ControllerHandle,
> &gEfiHttpProtocolGuid);
> + if (NicHandle == NULL) {
> + return EFI_SUCCESS;
> + }
> +
> + Status = gBS->OpenProtocol (
> + NicHandle,
> + &gEfiRestExServiceBindingProtocolGuid,
> + (VOID **) &ServiceBinding,
> + This->DriverBindingHandle,
> + NicHandle,
> + EFI_OPEN_PROTOCOL_GET_PROTOCOL
> + );
> + if (EFI_ERROR (Status)) {
> + return EFI_DEVICE_ERROR;
> + }
> +
> + RestExSb = RESTEX_SERVICE_FROM_THIS (ServiceBinding);
> +
> + if (!IsListEmpty (&RestExSb->RestExChildrenList)) {
> + //
> + // Destroy the RestEx child instance in ChildHandleBuffer.
> + //
> + List = &RestExSb->RestExChildrenList;
> + Context.ServiceBinding = ServiceBinding;
> + Context.NumberOfChildren = NumberOfChildren;
> + Context.ChildHandleBuffer = ChildHandleBuffer;
> + Status = NetDestroyLinkList (
> + List,
> + RestExDestroyChildEntryInHandleBuffer,
> + &Context,
> + NULL
> + );
> + }
> +
> + if (NumberOfChildren == 0 && IsListEmpty (&RestExSb-
> >RestExChildrenList)) {
> + gBS->UninstallProtocolInterface (
> + NicHandle,
> + &gEfiRestExServiceBindingProtocolGuid,
> + ServiceBinding
> + );
> +
> + RestExDestroyService (RestExSb);
> +
> + if (gRedfishRestExControllerNameTable != NULL) {
> + FreeUnicodeStringTable (gRedfishRestExControllerNameTable);
> + gRedfishRestExControllerNameTable = NULL;
> + }
> +
> + Status = EFI_SUCCESS;
> + }
> +
> + return Status;
> +}
> +
> +/**
> + Creates a child handle and installs a protocol.
> +
> + The CreateChild() function installs a protocol on ChildHandle.
> + If ChildHandle is a pointer to NULL, then a new handle is created and
> returned in ChildHandle.
> + If ChildHandle is not a pointer to NULL, then the protocol installs on the
> existing ChildHandle.
> +
> + @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL
> instance.
> + @param[in] ChildHandle Pointer to the handle of the child to create. If it is
> NULL,
> + then a new handle is created. If it is a pointer to an existing
> UEFI handle,
> + then the protocol is added to the existing UEFI handle.
> +
> + @retval EFI_SUCCES The protocol was added to ChildHandle.
> + @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
> + @retval EFI_OUT_OF_RESOURCES There are not enough resources
> available to create
> + the child
> + @retval other The child handle was not created
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExServiceBindingCreateChild (
> + IN EFI_SERVICE_BINDING_PROTOCOL *This,
> + IN EFI_HANDLE *ChildHandle
> + )
> +{
> + RESTEX_SERVICE *RestExSb;
> + RESTEX_INSTANCE *Instance;
> + EFI_STATUS Status;
> + EFI_TPL OldTpl;
> + VOID *Http;
> +
> + if ((This == NULL) || (ChildHandle == NULL)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + RestExSb = RESTEX_SERVICE_FROM_THIS (This);
> +
> + Status = RestExCreateInstance (RestExSb, &Instance);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> + ASSERT (Instance != NULL);
> +
> + //
> + // Install the RestEx protocol onto ChildHandle
> + //
> + Status = gBS->InstallMultipleProtocolInterfaces (
> + ChildHandle,
> + &gEfiRestExProtocolGuid,
> + &Instance->RestEx,
> + NULL
> + );
> + if (EFI_ERROR (Status)) {
> + goto ON_ERROR;
> + }
> +
> + Instance->ChildHandle = *ChildHandle;
> +
> + //
> + // Open the Http protocol BY_CHILD.
> + //
> + Status = gBS->OpenProtocol (
> + RestExSb->HttpChildHandle,
> + &gEfiHttpProtocolGuid,
> + (VOID **) &Http,
> + gRedfishRestExDriverBinding.DriverBindingHandle,
> + Instance->ChildHandle,
> + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
> + );
> + if (EFI_ERROR (Status)) {
> + gBS->UninstallMultipleProtocolInterfaces (
> + Instance->ChildHandle,
> + &gEfiRestExProtocolGuid,
> + &Instance->RestEx,
> + NULL
> + );
> +
> + goto ON_ERROR;
> + }
> +
> + //
> + // Open the Http protocol by child.
> + //
> + Status = gBS->OpenProtocol (
> + Instance->HttpIo.Handle,
> + &gEfiHttpProtocolGuid,
> + (VOID **) &Http,
> + gRedfishRestExDriverBinding.DriverBindingHandle,
> + Instance->ChildHandle,
> + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
> + );
> + if (EFI_ERROR (Status)) {
> + //
> + // Close the Http protocol.
> + //
> + gBS->CloseProtocol (
> + RestExSb->HttpChildHandle,
> + &gEfiHttpProtocolGuid,
> + gRedfishRestExDriverBinding.DriverBindingHandle,
> + ChildHandle
> + );
> +
> + gBS->UninstallMultipleProtocolInterfaces (
> + Instance->ChildHandle,
> + &gEfiRestExProtocolGuid,
> + &Instance->RestEx,
> + NULL
> + );
> +
> + goto ON_ERROR;
> + }
> +
> + //
> + // Add it to the parent's child list.
> + //
> + OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
> +
> + InsertTailList (&RestExSb->RestExChildrenList, &Instance->Link);
> + RestExSb->RestExChildrenNum++;
> +
> + gBS->RestoreTPL (OldTpl);
> +
> + return EFI_SUCCESS;
> +
> +ON_ERROR:
> +
> + RestExDestroyInstance (Instance);
> + return Status;
> +}
> +
> +/**
> + Destroys a child handle with a protocol installed on it.
> +
> + The DestroyChild() function does the opposite of CreateChild(). It removes
> a protocol
> + that was installed by CreateChild() from ChildHandle. If the removed
> protocol is the
> + last protocol on ChildHandle, then ChildHandle is destroyed.
> +
> + @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL
> instance.
> + @param[in] ChildHandle Handle of the child to destroy
> +
> + @retval EFI_SUCCES The protocol was removed from ChildHandle.
> + @retval EFI_UNSUPPORTED ChildHandle does not support the protocol
> that is being removed.
> + @retval EFI_INVALID_PARAMETER Child handle is NULL.
> + @retval EFI_ACCESS_DENIED The protocol could not be removed from
> the ChildHandle
> + because its services are being used.
> + @retval other The child handle was not destroyed
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExServiceBindingDestroyChild (
> + IN EFI_SERVICE_BINDING_PROTOCOL *This,
> + IN EFI_HANDLE ChildHandle
> + )
> +{
> + RESTEX_SERVICE *RestExSb;
> + RESTEX_INSTANCE *Instance;
> +
> + EFI_REST_EX_PROTOCOL *RestEx;
> + EFI_STATUS Status;
> + EFI_TPL OldTpl;
> +
> + if ((This == NULL) || (ChildHandle == NULL)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + //
> + // Retrieve the private context data structures
> + //
> + Status = gBS->OpenProtocol (
> + ChildHandle,
> + &gEfiRestExProtocolGuid,
> + (VOID **) &RestEx,
> + NULL,
> + NULL,
> + EFI_OPEN_PROTOCOL_GET_PROTOCOL
> + );
> +
> + if (EFI_ERROR (Status)) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + Instance = RESTEX_INSTANCE_FROM_THIS (RestEx);
> + RestExSb = RESTEX_SERVICE_FROM_THIS (This);
> +
> + if (Instance->Service != RestExSb) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + if (Instance->InDestroy) {
> + return EFI_SUCCESS;
> + }
> +
> + OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
> +
> + Instance->InDestroy = TRUE;
> +
> + //
> + // Close the Http protocol.
> + //
> + gBS->CloseProtocol (
> + RestExSb->HttpChildHandle,
> + &gEfiHttpProtocolGuid,
> + gRedfishRestExDriverBinding.DriverBindingHandle,
> + ChildHandle
> + );
> +
> + gBS->CloseProtocol (
> + Instance->HttpIo.Handle,
> + &gEfiHttpProtocolGuid,
> + gRedfishRestExDriverBinding.DriverBindingHandle,
> + ChildHandle
> + );
> +
> +
> + gBS->RestoreTPL (OldTpl);
> +
> + //
> + // Uninstall the RestEx protocol first to enable a top down destruction.
> + //
> + Status = gBS->UninstallProtocolInterface (
> + ChildHandle,
> + &gEfiRestExProtocolGuid,
> + RestEx
> + );
> +
> + OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
> +
> + if (EFI_ERROR (Status)) {
> + Instance->InDestroy = FALSE;
> + gBS->RestoreTPL (OldTpl);
> + return Status;
> + }
> +
> + RemoveEntryList (&Instance->Link);
> + RestExSb->RestExChildrenNum--;
> +
> + gBS->RestoreTPL (OldTpl);
> +
> + RestExDestroyInstance (Instance);
> + return EFI_SUCCESS;
> +}
> +
> diff --git a/RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.h
> b/RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.h
> new file mode 100644
> index 0000000000..6743ced23c
> --- /dev/null
> +++ b/RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.h
> @@ -0,0 +1,650 @@
> +/** @file
> + RedfishRestExDxe support functions definitions.
> +
> + Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> + (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef EFI_REDFISH_RESTEX_DRIVER_H_
> +#define EFI_REDFISH_RESTEX_DRIVER_H_
> +
> +///
> +/// Libraries classes
> +///
> +#include <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/HttpIoLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/NetLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiDriverEntryPoint.h>
> +
> +///
> +/// UEFI Driver Model Protocols
> +///
> +#include <Protocol/DriverBinding.h>
> +#include <Protocol/RestEx.h>
> +#include <Protocol/ServiceBinding.h>
> +
> +///
> +/// Protocol instances
> +///
> +extern EFI_COMPONENT_NAME_PROTOCOL
> gRedfishRestExComponentName;
> +extern EFI_COMPONENT_NAME2_PROTOCOL
> gRedfishRestExComponentName2;
> +extern EFI_UNICODE_STRING_TABLE
> *gRedfishRestExControllerNameTable;
> +
> +extern EFI_DRIVER_BINDING_PROTOCOL gRedfishRestExDriverBinding;
> +extern EFI_SERVICE_BINDING_PROTOCOL mRedfishRestExServiceBinding;
> +extern EFI_REST_EX_PROTOCOL mRedfishRestExProtocol;
> +///
> +/// RestEx service block
> +///
> +typedef struct _RESTEX_SERVICE RESTEX_SERVICE;
> +
> +///
> +/// RestEx instance block
> +///
> +typedef struct _RESTEX_INSTANCE RESTEX_INSTANCE;
> +
> +///
> +/// Driver Version
> +///
> +#define REDFISH_RESTEX_DRIVER_VERSION 0x0100
> +
> +#define RESTEX_SERVICE_SIGNATURE SIGNATURE_32 ('R', 'E', 'S', 'S')
> +#define RESTEX_INSTANCE_SIGNATURE SIGNATURE_32 ('R', 'E', 'I', 'S')
> +
> +#define RESTEX_SERVICE_FROM_THIS(a) \
> + CR (a, RESTEX_SERVICE, ServiceBinding, RESTEX_SERVICE_SIGNATURE)
> +
> +#define RESTEX_INSTANCE_FROM_THIS(a) \
> + CR (a, RESTEX_INSTANCE, RestEx, RESTEX_INSTANCE_SIGNATURE)
> +
> +
> +#define RESTEX_STATE_UNCONFIGED 0
> +#define RESTEX_STATE_CONFIGED 1
> +
> +struct _RESTEX_SERVICE {
> + UINT32 Signature;
> + EFI_SERVICE_BINDING_PROTOCOL ServiceBinding;
> +
> + UINT16 RestExChildrenNum;
> + LIST_ENTRY RestExChildrenList;
> +
> + EFI_HANDLE ControllerHandle;
> + EFI_HANDLE ImageHandle;
> +
> + //
> + // Use to establish the parent-child relationship.
> + //
> + EFI_HANDLE HttpChildHandle;
> +
> + UINT32 Id;
> +
> + EFI_REST_EX_SERVICE_INFO RestExServiceInfo;
> +};
> +
> +#define RESTEX_INSTANCE_FLAGS_TLS_RETRY 0x00000001
> +#define RESTEX_INSTANCE_FLAGS_TCP_ERROR_RETRY 0x00000002
> +
> +struct _RESTEX_INSTANCE {
> + UINT32 Signature;
> + LIST_ENTRY Link;
> +
> + EFI_REST_EX_PROTOCOL RestEx;
> +
> + INTN State;
> + BOOLEAN InDestroy;
> +
> + RESTEX_SERVICE *Service;
> + EFI_HANDLE ChildHandle;
> +
> + EFI_REST_EX_CONFIG_DATA ConfigData;
> +
> + //
> + // HTTP_IO to access the HTTP service
> + //
> + HTTP_IO HttpIo;
> +
> + UINT32 Flags;
> +};
> +
> +typedef struct {
> + EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
> + UINTN NumberOfChildren;
> + EFI_HANDLE *ChildHandleBuffer;
> +} RESTEX_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT;
> +
> +/**
> + Provides a simple HTTP-like interface to send and receive resources from a
> REST service.
> +
> + The SendReceive() function sends an HTTP request to this REST service,
> and returns a
> + response when the data is retrieved from the service. RequestMessage
> contains the HTTP
> + request to the REST resource identified by RequestMessage.Request.Url.
> The
> + ResponseMessage is the returned HTTP response for that request,
> including any HTTP
> + status.
> +
> + @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a
> particular
> + REST service.
> + @param[in] RequestMessage Pointer to the HTTP request data for this
> resource
> + @param[out] ResponseMessage Pointer to the HTTP response data
> obtained for this requested.
> +
> + @retval EFI_SUCCESS operation succeeded.
> + @retval EFI_INVALID_PARAMETER This, RequestMessage, or
> ResponseMessage are NULL.
> + @retval EFI_DEVICE_ERROR An unexpected system or network error
> occurred.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExSendReceive (
> + IN EFI_REST_EX_PROTOCOL *This,
> + IN EFI_HTTP_MESSAGE *RequestMessage,
> + OUT EFI_HTTP_MESSAGE *ResponseMessage
> + );
> +
> +/**
> + Obtain the current time from this REST service instance.
> +
> + The GetServiceTime() function is an optional interface to obtain the
> current time from
> + this REST service instance. If this REST service does not support to retrieve
> the time,
> + this function returns EFI_UNSUPPORTED. This function must returns
> EFI_UNSUPPORTED if
> + EFI_REST_EX_SERVICE_TYPE returned in EFI_REST_EX_SERVICE_INFO from
> GetService() is
> + EFI_REST_EX_SERVICE_UNSPECIFIC.
> +
> + @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a
> particular
> + REST service.
> + @param[out] Time A pointer to storage to receive a snapshot of
> the current time of
> + the REST service.
> +
> + @retval EFI_SUCCESS operation succeeded.
> + @retval EFI_INVALID_PARAMETER This or Time are NULL.
> + @retval EFI_UNSUPPORTED The RESTful service does not support
> returning the time.
> + @retval EFI_DEVICE_ERROR An unexpected system or network error
> occurred.
> + @retval EFI_NOT_READY The configuration of this instance is not set
> yet. Configure() must
> + be executed and returns successfully prior to invoke this
> function.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExGetServiceTime (
> + IN EFI_REST_EX_PROTOCOL *This,
> + OUT EFI_TIME *Time
> + );
> +
> +/**
> + This function returns the information of REST service provided by this EFI
> REST EX driver instance.
> +
> + The information such as the type of REST service and the access mode of
> REST EX driver instance
> + (In-band or Out-of-band) are described in EFI_REST_EX_SERVICE_INFO
> structure. For the vendor-specific
> + REST service, vendor-specific REST service information is returned in
> VendorSpecifcData.
> + REST EX driver designer is well know what REST service this REST EX driver
> instance intends to
> + communicate with. The designer also well know this driver instance is used
> to talk to BMC through
> + specific platform mechanism or talk to REST server through UEFI HTTP
> protocol. REST EX driver is
> + responsible to fill up the correct information in
> EFI_REST_EX_SERVICE_INFO. EFI_REST_EX_SERVICE_INFO
> + is referred by EFI REST clients to pickup the proper EFI REST EX driver
> instance to get and set resource.
> + GetService() is a basic and mandatory function which must be able to use
> even Configure() is not invoked
> + in previously.
> +
> + @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a
> particular
> + REST service.
> + @param[out] RestExServiceInfo Pointer to receive a pointer to
> EFI_REST_EX_SERVICE_INFO structure. The
> + format of EFI_REST_EX_SERVICE_INFO is version
> controlled for the future
> + extension. The version of EFI_REST_EX_SERVICE_INFO
> structure is returned
> + in the header within this structure. EFI REST client refers to
> the correct
> + format of structure according to the version number. The
> pointer to
> + EFI_REST_EX_SERVICE_INFO is a memory block allocated
> by EFI REST EX driver
> + instance. That is caller's responsibility to free this memory
> when this
> + structure is no longer needed. Refer to Related Definitions
> below for the
> + definitions of EFI_REST_EX_SERVICE_INFO structure.
> +
> + @retval EFI_SUCCESS EFI_REST_EX_SERVICE_INFO is returned in
> RestExServiceInfo. This function
> + is not supported in this REST EX Protocol driver instance.
> + @retval EFI_UNSUPPORTED This function is not supported in this REST
> EX Protocol driver instance.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExGetService (
> + IN EFI_REST_EX_PROTOCOL *This,
> + OUT EFI_REST_EX_SERVICE_INFO **RestExServiceInfo
> + );
> +
> +/**
> + This function returns operational configuration of current EFI REST EX child
> instance.
> +
> + This function returns the current configuration of EFI REST EX child instance.
> The format of
> + operational configuration depends on the implementation of EFI REST EX
> driver instance. For
> + example, HTTP-aware EFI REST EX driver instance uses EFI HTTP protocol as
> the undying protocol
> + to communicate with REST service. In this case, the type of configuration is
> + EFI_REST_EX_CONFIG_TYPE_HTTP returned from GetService().
> EFI_HTTP_CONFIG_DATA is used as EFI REST
> + EX configuration format and returned to EFI REST client. User has to type
> cast RestExConfigData
> + to EFI_HTTP_CONFIG_DATA. For those non HTTP-aware REST EX driver
> instances, the type of configuration
> + is EFI_REST_EX_CONFIG_TYPE_UNSPECIFIC returned from GetService(). In
> this case, the format of
> + returning data could be non industrial. Instead, the format of configuration
> data is system/platform
> + specific definition such as BMC mechanism used in EFI REST EX driver
> instance. EFI REST client and
> + EFI REST EX driver instance have to refer to the specific system /platform
> spec which is out of UEFI scope.
> +
> + @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
> + @param[out] RestExConfigData Pointer to receive a pointer to
> EFI_REST_EX_CONFIG_DATA.
> + The memory allocated for configuration data should be
> freed
> + by caller. See Related Definitions for the details.
> +
> + @retval EFI_SUCCESS EFI_REST_EX_CONFIG_DATA is returned in
> successfully.
> + @retval EFI_UNSUPPORTED This function is not supported in this REST
> EX Protocol driver instance.
> + @retval EFI_NOT_READY The configuration of this instance is not set
> yet. Configure() must be
> + executed and returns successfully prior to invoke this
> function.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExGetModeData (
> + IN EFI_REST_EX_PROTOCOL *This,
> + OUT EFI_REST_EX_CONFIG_DATA *RestExConfigData
> + );
> +
> +/**
> + This function is used to configure EFI REST EX child instance.
> +
> + This function is used to configure the setting of underlying protocol of REST
> EX child
> + instance. The type of configuration is according to the implementation of
> EFI REST EX
> + driver instance. For example, HTTP-aware EFI REST EX driver instance uses
> EFI HTTP protocol
> + as the undying protocol to communicate with REST service. The type of
> configuration is
> + EFI_REST_EX_CONFIG_TYPE_HTTP and RestExConfigData is the same
> format with EFI_HTTP_CONFIG_DATA.
> + Akin to HTTP configuration, REST EX child instance can be configure to use
> different HTTP
> + local access point for the data transmission. Multiple REST clients may use
> different
> + configuration of HTTP to distinguish themselves, such as to use the
> different TCP port.
> + For those non HTTP-aware REST EX driver instance, the type of
> configuration is
> + EFI_REST_EX_CONFIG_TYPE_UNSPECIFIC. RestExConfigData refers to the
> non industrial standard.
> + Instead, the format of configuration data is system/platform specific
> definition such as BMC.
> + In this case, EFI REST client and EFI REST EX driver instance have to refer to
> the specific
> + system/platform spec which is out of the UEFI scope. Besides
> GetService()function, no other
> + EFI REST EX functions can be executed by this instance until Configure()is
> executed and returns
> + successfully. All other functions must returns EFI_NOT_READY if this
> instance is not configured
> + yet. Set RestExConfigData to NULL means to put EFI REST EX child instance
> into the unconfigured
> + state.
> +
> + @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
> + @param[in] RestExConfigData Pointer to EFI_REST_EX_CONFIG_DATA.
> See Related Definitions in
> + GetModeData() protocol interface.
> +
> + @retval EFI_SUCCESS EFI_REST_EX_CONFIG_DATA is set in
> successfully.
> + @retval EFI_DEVICE_ERROR Configuration for this REST EX child
> instance is failed with the given
> + EFI_REST_EX_CONFIG_DATA.
> + @retval EFI_UNSUPPORTED This function is not supported in this REST
> EX Protocol driver instance.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExConfigure (
> + IN EFI_REST_EX_PROTOCOL *This,
> + IN EFI_REST_EX_CONFIG_DATA RestExConfigData
> + );
> +
> +/**
> + This function sends REST request to REST service and signal caller's event
> asynchronously when
> + the final response is received by REST EX Protocol driver instance.
> +
> + The essential design of this function is to handle asynchronous
> send/receive implicitly according
> + to REST service asynchronous request mechanism. Caller will get the
> notification once the response
> + is returned from REST service.
> +
> + @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
> + @param[in] RequestMessage This is the HTTP request message sent
> to REST service. Set RequestMessage
> + to NULL to cancel the previous asynchronous request
> associated with the
> + corresponding RestExToken. See descriptions for the
> details.
> + @param[in] RestExToken REST EX token which REST EX Protocol
> instance uses to notify REST client
> + the status of response of asynchronous REST request. See
> related definition
> + of EFI_REST_EX_TOKEN.
> + @param[in] TimeOutInMilliSeconds The pointer to the timeout in
> milliseconds which REST EX Protocol driver
> + instance refers as the duration to drop asynchronous REST
> request. NULL
> + pointer means no timeout for this REST request. REST EX
> Protocol driver
> + signals caller's event with EFI_STATUS set to EFI_TIMEOUT
> in RestExToken
> + if REST EX Protocol can't get the response from REST
> service within
> + TimeOutInMilliSeconds.
> +
> + @retval EFI_SUCCESS Asynchronous REST request is established.
> + @retval EFI_UNSUPPORTED This REST EX Protocol driver instance
> doesn't support asynchronous request.
> + @retval EFI_TIMEOUT Asynchronous REST request is not
> established and timeout is expired.
> + @retval EFI_ABORT Previous asynchronous REST request has been
> canceled.
> + @retval EFI_DEVICE_ERROR Otherwise, returns EFI_DEVICE_ERROR
> for other errors according to HTTP Status Code.
> + @retval EFI_NOT_READY The configuration of this instance is not set
> yet. Configure() must be executed
> + and returns successfully prior to invoke this function.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExAyncSendReceive (
> + IN EFI_REST_EX_PROTOCOL *This,
> + IN EFI_HTTP_MESSAGE *RequestMessage OPTIONAL,
> + IN EFI_REST_EX_TOKEN *RestExToken,
> + IN UINTN *TimeOutInMilliSeconds OPTIONAL
> + );
> +
> +/**
> + This function sends REST request to a REST Event service and signals caller's
> event
> + token asynchronously when the URI resource change event is received by
> REST EX
> + Protocol driver instance.
> +
> + The essential design of this function is to monitor event implicitly according
> to
> + REST service event service mechanism. Caller will get the notification if
> certain
> + resource is changed.
> +
> + @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
> + @param[in] RequestMessage This is the HTTP request message sent
> to REST service. Set RequestMessage
> + to NULL to cancel the previous event service associated
> with the corresponding
> + RestExToken. See descriptions for the details.
> + @param[in] RestExToken REST EX token which REST EX Protocol
> driver instance uses to notify REST client
> + the URI resource which monitored by REST client has
> been changed. See the related
> + definition of EFI_REST_EX_TOKEN in
> EFI_REST_EX_PROTOCOL.AsyncSendReceive().
> +
> + @retval EFI_SUCCESS Asynchronous REST request is established.
> + @retval EFI_UNSUPPORTED This REST EX Protocol driver instance
> doesn't support asynchronous request.
> + @retval EFI_ABORT Previous asynchronous REST request has been
> canceled or event subscription has been
> + delete from service.
> + @retval EFI_DEVICE_ERROR Otherwise, returns EFI_DEVICE_ERROR
> for other errors according to HTTP Status Code.
> + @retval EFI_NOT_READY The configuration of this instance is not set
> yet. Configure() must be executed
> + and returns successfully prior to invoke this function.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExEventService (
> + IN EFI_REST_EX_PROTOCOL *This,
> + IN EFI_HTTP_MESSAGE *RequestMessage OPTIONAL,
> + IN EFI_REST_EX_TOKEN *RestExToken
> + );
> +/**
> + Create a new TLS session becuase the previous on is closed.
> + status.
> +
> + @param[in] Instance Pointer to EFI_REST_EX_PROTOCOL instance
> for a particular
> + REST service.
> + @retval EFI_SUCCESS operation succeeded.
> + @retval EFI Errors Other errors.
> +
> +**/
> +EFI_STATUS
> +ResetHttpTslSession (
> + IN RESTEX_INSTANCE *Instance
> +);
> +
> +
> +/**
> + Callback function which provided by user to remove one node in
> NetDestroyLinkList process.
> +
> + @param[in] Entry The entry to be removed.
> + @param[in] Context Pointer to the callback context corresponds to
> the Context in NetDestroyLinkList.
> +
> + @retval EFI_SUCCESS The entry has been removed successfully.
> + @retval Others Fail to remove the entry.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RestExDestroyChildEntryInHandleBuffer (
> + IN LIST_ENTRY *Entry,
> + IN VOID *Context
> + );
> +
> +/**
> + Destroy the RestEx instance and recycle the resources.
> +
> + @param[in] Instance The pointer to the RestEx instance.
> +
> +**/
> +VOID
> +RestExDestroyInstance (
> + IN RESTEX_INSTANCE *Instance
> + );
> +
> +/**
> + Create the RestEx instance and initialize it.
> +
> + @param[in] Service The pointer to the RestEx service.
> + @param[out] Instance The pointer to the RestEx instance.
> +
> + @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
> + @retval EFI_SUCCESS The RestEx instance is created.
> +
> +**/
> +EFI_STATUS
> +RestExCreateInstance (
> + IN RESTEX_SERVICE *Service,
> + OUT RESTEX_INSTANCE **Instance
> + );
> +
> +
> +/**
> + Release all the resource used the RestEx service binding instance.
> +
> + @param RestExSb The RestEx service binding instance.
> +
> +**/
> +VOID
> +RestExDestroyService (
> + IN RESTEX_SERVICE *RestExSb
> + );
> +
> +/**
> + Create then initialize a RestEx service binding instance.
> +
> + @param[in] Controller The controller to install the RestEx service
> + binding on.
> + @param[in] Image The driver binding image of the RestEx driver.
> + @param[out] Service The variable to receive the created service
> + binding instance.
> +
> + @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create
> the instance.
> + @retval EFI_SUCCESS The service instance is created for the
> controller.
> +
> +**/
> +EFI_STATUS
> +RestExCreateService (
> + IN EFI_HANDLE Controller,
> + IN EFI_HANDLE Image,
> + OUT RESTEX_SERVICE **Service
> + );
> +
> +/**
> + This is the declaration of an EFI image entry point. This entry point is
> + the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
> + both device drivers and bus drivers.
> +
> + @param[in] ImageHandle The firmware allocated handle for the UEFI
> image.
> + @param[in] SystemTable A pointer to the EFI System Table.
> +
> + @retval EFI_SUCCESS The operation completed successfully.
> + @retval Others An unexpected error occurred.
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExDriverEntryPoint (
> + IN EFI_HANDLE ImageHandle,
> + IN EFI_SYSTEM_TABLE *SystemTable
> + );
> +
> +/**
> + Tests to see if this driver supports a given controller. If a child device is
> provided,
> + it further tests to see if this driver supports creating a handle for the
> specified child device.
> +
> + This function checks to see if the driver specified by This supports the
> device specified by
> + ControllerHandle. Drivers will typically use the device path attached to
> + ControllerHandle and/or the services from the bus I/O abstraction
> attached to
> + ControllerHandle to determine if the driver supports ControllerHandle.
> This function
> + may be called many times during platform initialization. In order to reduce
> boot times, the tests
> + performed by this function must be very small, and take as little time as
> possible to execute. This
> + function must not change the state of any hardware devices, and this
> function must be aware that the
> + device specified by ControllerHandle may already be managed by the
> same driver or a
> + different driver. This function must match its calls to AllocatePages() with
> FreePages(),
> + AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
> + Because ControllerHandle may have been previously started by the same
> driver, if a protocol is
> + already in the opened state, then it must not be closed with
> CloseProtocol(). This is required
> + to guarantee the state of ControllerHandle is not modified by this function.
> +
> + @param[in] This A pointer to the
> EFI_DRIVER_BINDING_PROTOCOL instance.
> + @param[in] ControllerHandle The handle of the controller to test. This
> handle
> + must support a protocol interface that supplies
> + an I/O abstraction to the driver.
> + @param[in] RemainingDevicePath A pointer to the remaining portion of a
> device path. This
> + parameter is ignored by device drivers, and is optional for
> bus
> + drivers. For bus drivers, if this parameter is not NULL, then
> + the bus driver must determine if the bus controller
> specified
> + by ControllerHandle and the child controller specified
> + by RemainingDevicePath are both supported by this
> + bus driver.
> +
> + @retval EFI_SUCCESS The device specified by ControllerHandle and
> + RemainingDevicePath is supported by the driver specified
> by This.
> + @retval EFI_ALREADY_STARTED The device specified by
> ControllerHandle and
> + RemainingDevicePath is already being managed by the
> driver
> + specified by This.
> + @retval EFI_ACCESS_DENIED The device specified by ControllerHandle
> and
> + RemainingDevicePath is already being managed by a
> different
> + driver or an application that requires exclusive access.
> + Currently not implemented.
> + @retval EFI_UNSUPPORTED The device specified by ControllerHandle
> and
> + RemainingDevicePath is not supported by the driver
> specified by This.
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExDriverBindingSupported (
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
> + IN EFI_HANDLE ControllerHandle,
> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
> + );
> +
> +/**
> + Starts a device controller or a bus controller.
> +
> + The Start() function is designed to be invoked from the EFI boot service
> ConnectController().
> + As a result, much of the error checking on the parameters to Start() has
> been moved into this
> + common boot service. It is legal to call Start() from other locations,
> + but the following calling restrictions must be followed, or the system
> behavior will not be deterministic.
> + 1. ControllerHandle must be a valid EFI_HANDLE.
> + 2. If RemainingDevicePath is not NULL, then it must be a pointer to a
> naturally aligned
> + EFI_DEVICE_PATH_PROTOCOL.
> + 3. Prior to calling Start(), the Supported() function for the driver specified
> by This must
> + have been called with the same calling parameters, and Supported()
> must have returned EFI_SUCCESS.
> +
> + @param[in] This A pointer to the
> EFI_DRIVER_BINDING_PROTOCOL instance.
> + @param[in] ControllerHandle The handle of the controller to start. This
> handle
> + must support a protocol interface that supplies
> + an I/O abstraction to the driver.
> + @param[in] RemainingDevicePath A pointer to the remaining portion of a
> device path. This
> + parameter is ignored by device drivers, and is optional for
> bus
> + drivers. For a bus driver, if this parameter is NULL, then
> handles
> + for all the children of Controller are created by this driver.
> + If this parameter is not NULL and the first Device Path
> Node is
> + not the End of Device Path Node, then only the handle for
> the
> + child device specified by the first Device Path Node of
> + RemainingDevicePath is created by this driver.
> + If the first Device Path Node of RemainingDevicePath is
> + the End of Device Path Node, no child handle is created by
> this
> + driver.
> +
> + @retval EFI_SUCCESS The device was started.
> + @retval EFI_DEVICE_ERROR The device could not be started due to a
> device error.Currently not implemented.
> + @retval EFI_OUT_OF_RESOURCES The request could not be completed
> due to a lack of resources.
> + @retval Others The driver failded to start the device.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExDriverBindingStart (
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
> + IN EFI_HANDLE ControllerHandle,
> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
> + );
> +
> +/**
> + Stops a device controller or a bus controller.
> +
> + The Stop() function is designed to be invoked from the EFI boot service
> DisconnectController().
> + As a result, much of the error checking on the parameters to Stop() has
> been moved
> + into this common boot service. It is legal to call Stop() from other locations,
> + but the following calling restrictions must be followed, or the system
> behavior will not be deterministic.
> + 1. ControllerHandle must be a valid EFI_HANDLE that was used on a
> previous call to this
> + same driver's Start() function.
> + 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a
> valid
> + EFI_HANDLE. In addition, all of these handles must have been created in
> this driver's
> + Start() function, and the Start() function must have called OpenProtocol()
> on
> + ControllerHandle with an Attribute of
> EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
> +
> + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL
> instance.
> + @param[in] ControllerHandle A handle to the device being stopped. The
> handle must
> + support a bus specific I/O protocol for the driver
> + to use to stop the device.
> + @param[in] NumberOfChildren The number of child device handles in
> ChildHandleBuffer.
> + @param[in] ChildHandleBuffer An array of child handles to be freed. May
> be NULL
> + if NumberOfChildren is 0.
> +
> + @retval EFI_SUCCESS The device was stopped.
> + @retval EFI_DEVICE_ERROR The device could not be stopped due to a
> device error.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExDriverBindingStop (
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
> + IN EFI_HANDLE ControllerHandle,
> + IN UINTN NumberOfChildren,
> + IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
> + );
> +
> +/**
> + Creates a child handle and installs a protocol.
> +
> + The CreateChild() function installs a protocol on ChildHandle.
> + If ChildHandle is a pointer to NULL, then a new handle is created and
> returned in ChildHandle.
> + If ChildHandle is not a pointer to NULL, then the protocol installs on the
> existing ChildHandle.
> +
> + @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL
> instance.
> + @param[in] ChildHandle Pointer to the handle of the child to create. If it is
> NULL,
> + then a new handle is created. If it is a pointer to an existing
> UEFI handle,
> + then the protocol is added to the existing UEFI handle.
> +
> + @retval EFI_SUCCES The protocol was added to ChildHandle.
> + @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
> + @retval EFI_OUT_OF_RESOURCES There are not enough resources
> available to create
> + the child
> + @retval other The child handle was not created
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExServiceBindingCreateChild (
> + IN EFI_SERVICE_BINDING_PROTOCOL *This,
> + IN EFI_HANDLE *ChildHandle
> + );
> +
> +/**
> + Destroys a child handle with a protocol installed on it.
> +
> + The DestroyChild() function does the opposite of CreateChild(). It removes
> a protocol
> + that was installed by CreateChild() from ChildHandle. If the removed
> protocol is the
> + last protocol on ChildHandle, then ChildHandle is destroyed.
> +
> + @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL
> instance.
> + @param[in] ChildHandle Handle of the child to destroy
> +
> + @retval EFI_SUCCES The protocol was removed from ChildHandle.
> + @retval EFI_UNSUPPORTED ChildHandle does not support the protocol
> that is being removed.
> + @retval EFI_INVALID_PARAMETER Child handle is NULL.
> + @retval EFI_ACCESS_DENIED The protocol could not be removed from
> the ChildHandle
> + because its services are being used.
> + @retval other The child handle was not destroyed
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExServiceBindingDestroyChild (
> + IN EFI_SERVICE_BINDING_PROTOCOL *This,
> + IN EFI_HANDLE ChildHandle
> + );
> +#endif
> diff --git a/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf
> b/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf
> new file mode 100644
> index 0000000000..75437b086a
> --- /dev/null
> +++ b/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf
> @@ -0,0 +1,63 @@
> +## @file
> +# Implementation of Redfish EFI_REST_EX_PROTOCOL interfaces.
> +#
> +# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> +# (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> + INF_VERSION = 0x0001001b
> + BASE_NAME = RedfishRestExDxe
> + FILE_GUID = B64702DA-E6B5-43c8-8CE8-D253071E9D6C
> + MODULE_TYPE = UEFI_DRIVER
> + VERSION_STRING = 1.0
> + ENTRY_POINT = RedfishRestExDriverEntryPoint
> + UNLOAD_IMAGE = NetLibDefaultUnload
> + MODULE_UNI_FILE = RedfishRestExDxe.uni
> +
> +[Packages]
> + MdePkg/MdePkg.dec
> + MdeModulePkg/MdeModulePkg.dec
> + NetworkPkg/NetworkPkg.dec
> + RedfishPkg/RedfishPkg.dec
> +
> +[Sources]
> + ComponentName.c
> + RedfishRestExDriver.c
> + RedfishRestExDriver.h
> + RedfishRestExImpl.c
> + RedfishRestExProtocol.c
> + RedfishRestExInternal.h
> +
> +[LibraryClasses]
> + BaseLib
> + BaseMemoryLib
> + DebugLib
> + DevicePathLib
> + DpcLib
> + HttpLib
> + HttpIoLib
> + PrintLib
> + MemoryAllocationLib
> + NetLib
> + UefiLib
> + UefiBootServicesTableLib
> + UefiDriverEntryPoint
> + UefiRuntimeServicesTableLib
> +
> +[Protocols]
> + gEfiRestExServiceBindingProtocolGuid ## BY_START
> + gEfiRestExProtocolGuid ## BY_START
> + gEfiHttpServiceBindingProtocolGuid ## TO_START
> + gEfiHttpProtocolGuid ## TO_START
> + gEfiDevicePathProtocolGuid ## TO_START
> +
> +[Pcd]
> +
> gEfiRedfishPkgTokenSpaceGuid.PcdRedfishRestExServiceAccessModeInBan
> d ## CONSUMES
> +
> +[UserExtensions.TianoCore."ExtraFiles"]
> + RedfishRestExDxeExtra.uni
> +
> diff --git a/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.uni
> b/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.uni
> new file mode 100644
> index 0000000000..afa0c142a9
> --- /dev/null
> +++ b/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.uni
> @@ -0,0 +1,16 @@
> +// /** @file
> +// Redfish UEFI RESTEX DXE Driver.
> +//
> +// This driver provides Redfish UEFI RESTEX protocols.
> +//
> +// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> +// (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
> +//
> +// SPDX-License-Identifier: BSD-2-Clause-Patent
> +//
> +// **/
> +
> +#string STR_MODULE_ABSTRACT #language en-US "UEFI Redfish
> RESTEX service"
> +
> +#string STR_MODULE_DESCRIPTION #language en-US "This driver
> provides Redfish EFI RESTEX Protocol and Redfish EFI RESREX Service Binding
> Protocol."
> +
> diff --git a/RedfishPkg/RedfishRestExDxe/RedfishRestExDxeExtra.uni
> b/RedfishPkg/RedfishRestExDxe/RedfishRestExDxeExtra.uni
> new file mode 100644
> index 0000000000..a8ecf8aede
> --- /dev/null
> +++ b/RedfishPkg/RedfishRestExDxe/RedfishRestExDxeExtra.uni
> @@ -0,0 +1,15 @@
> +// /** @file
> +// RestExDxe Localized Strings and Content
> +//
> +// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> +// (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
> +//
> +// SPDX-License-Identifier: BSD-2-Clause-Patent
> +//
> +// **/
> +
> +#string STR_PROPERTIES_MODULE_NAME
> +#language en-US
> +"Redfish UEFI RESTEX DXE"
> +
> +
> diff --git a/RedfishPkg/RedfishRestExDxe/RedfishRestExImpl.c
> b/RedfishPkg/RedfishRestExDxe/RedfishRestExImpl.c
> new file mode 100644
> index 0000000000..006b64adc0
> --- /dev/null
> +++ b/RedfishPkg/RedfishRestExDxe/RedfishRestExImpl.c
> @@ -0,0 +1,157 @@
> +/** @file
> + RestExDxe support functions implementation.
> +
> + Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> + (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +#include <Uefi.h>
> +#include "RedfishRestExInternal.h"
> +
> +/**
> + Create a new TLS session becuase the previous on is closed.
> + status.
> +
> + @param[in] Instance Pointer to EFI_REST_EX_PROTOCOL instance
> for a particular
> + REST service.
> + @retval EFI_SUCCESS operation succeeded.
> + @retval EFI_ERROR Other errors.
> +
> +**/
> +EFI_STATUS
> +ResetHttpTslSession (
> + IN RESTEX_INSTANCE *Instance
> +)
> +{
> + EFI_STATUS Status;
> +
> + DEBUG ((DEBUG_INFO, "%a: TCP connection is finished. Could be TSL
> session closure, reset HTTP instance for the new TLS session.\n",
> __FUNCTION__));
> +
> + Status = Instance->HttpIo.Http->Configure (Instance->HttpIo.Http, NULL);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "%a: Error to reset HTTP instance.\n",
> __FUNCTION__));
> + return Status;
> + }
> + Status = Instance->HttpIo.Http->Configure(Instance->HttpIo.Http,
> &((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)-
> >HttpConfigData);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "%a: Error to re-initiate HTTP instance.\n",
> __FUNCTION__));
> + }
> + return Status;
> +}
> +/**
> + This function check
> +
> + @param[in] Instance Pointer to EFI_REST_EX_PROTOCOL instance
> for a particular
> + REST service.
> + @param[in] HttpIoReceiveStatus This is the status return from
> HttpIoRecvResponse
> +
> + @retval EFI_SUCCESS The payload receive from Redfish service in
> sucessfully.
> + @retval EFI_NOT_READY May need to resend the HTTP request.
> + @retval EFI_DEVICE_ERROR Something wrong and can't be resolved.
> + @retval Others Other errors as indicated.
> +
> +**/
> +EFI_STATUS
> +RedfishCheckHttpReceiveStatus (
> + IN RESTEX_INSTANCE *Instance,
> + IN EFI_STATUS HttpIoReceiveStatus
> + )
> +{
> + EFI_STATUS Status;
> + EFI_STATUS ReturnStatus;
> +
> + if (!EFI_ERROR (HttpIoReceiveStatus)){
> + ReturnStatus = EFI_SUCCESS;
> + } else if (EFI_ERROR (HttpIoReceiveStatus) && HttpIoReceiveStatus !=
> EFI_CONNECTION_FIN) {
> + if ((Instance->Flags & RESTEX_INSTANCE_FLAGS_TCP_ERROR_RETRY) ==
> 0) {
> + DEBUG ((DEBUG_ERROR, "%a: TCP error, reset HTTP session.\n",
> __FUNCTION__));
> + Instance->Flags |= RESTEX_INSTANCE_FLAGS_TCP_ERROR_RETRY;
> + gBS->Stall (500);
> + Status = ResetHttpTslSession (Instance);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "%a: Reset HTTP instance fail.\n",
> __FUNCTION__));
> + ReturnStatus = EFI_DEVICE_ERROR;
> + } else {
> + return EFI_NOT_READY;
> + }
> + } else {
> + ReturnStatus = EFI_DEVICE_ERROR;
> + }
> + } else {
> + if (HttpIoReceiveStatus == EFI_CONNECTION_FIN) {
> + if ((Instance->Flags & RESTEX_INSTANCE_FLAGS_TLS_RETRY) != 0) {
> + DEBUG ((DEBUG_ERROR, "%a: REST_EX Send and receive fail even
> with a new TLS session.\n", __FUNCTION__));
> + ReturnStatus = EFI_DEVICE_ERROR;
> + }
> + Instance->Flags |= RESTEX_INSTANCE_FLAGS_TLS_RETRY;
> + Status = ResetHttpTslSession (Instance);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "%a: Reset HTTP instance fail.\n",
> __FUNCTION__));
> + ReturnStatus = EFI_DEVICE_ERROR;
> + }
> + return EFI_NOT_READY;
> + }
> + }
> + //
> + // Clean TLS new session retry and error try flags.
> + //
> + Instance->Flags &= ~ (RESTEX_INSTANCE_FLAGS_TLS_RETRY |
> RESTEX_INSTANCE_FLAGS_TCP_ERROR_RETRY);
> + return ReturnStatus;
> +}
> +
> +/**
> + This function send the HTTP request without body to see
> + if the write to URL is permitted by Redfish service. This function
> + checks if the HTTP request has Content-length in HTTP header. If yes,
> + set HTTP body to NULL and then send to service. Check the HTTP status
> + for the firther actions.
> +
> + @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for
> a particular
> + REST service.
> + @param[in] RequestMessage Pointer to the HTTP request data for
> this resource
> + @param[in] PreservedRequestHeaders The pointer to save the request
> headers
> + @param[in] ItsWrite This is write method to URL.
> +
> + @retval EFI_INVALID_PARAMETER Improper given parameters.
> + @retval EFI_SUCCESS This HTTP request is free to send to Redfish
> service.
> + @retval EFI_OUT_OF_RESOURCES NOt enough memory to process.
> + @retval EFI_ACCESS_DENIED Not allowed to write to this URL.
> +
> + @retval Others Other errors as indicated.
> +
> +**/
> +EFI_STATUS
> +RedfishHttpAddExpectation (
> + IN EFI_REST_EX_PROTOCOL *This,
> + IN EFI_HTTP_MESSAGE *RequestMessage,
> + IN EFI_HTTP_HEADER **PreservedRequestHeaders,
> + IN BOOLEAN *ItsWrite
> + )
> +{
> + EFI_HTTP_HEADER *NewHeaders;
> +
> + if (This == NULL || RequestMessage == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + *ItsWrite = FALSE;
> + if (PreservedRequestHeaders != NULL) {
> + *PreservedRequestHeaders = RequestMessage->Headers;
> + }
> +
> + if ((RequestMessage->Data.Request->Method != HttpMethodPut) &&
> (RequestMessage->Data.Request->Method != HttpMethodPost) &&
> + (RequestMessage->Data.Request->Method != HttpMethodPatch)) {
> + return EFI_SUCCESS;
> + }
> + *ItsWrite = TRUE;
> +
> + NewHeaders = AllocateZeroPool((RequestMessage->HeaderCount + 1) *
> sizeof(EFI_HTTP_HEADER));
> + CopyMem ((VOID*)NewHeaders, (VOID *)RequestMessage->Headers,
> RequestMessage->HeaderCount * sizeof (EFI_HTTP_HEADER));
> + HttpSetFieldNameAndValue (NewHeaders + RequestMessage-
> >HeaderCount, HTTP_HEADER_EXPECT, HTTP_EXPECT_100_CONTINUE);
> + RequestMessage->HeaderCount ++;
> + RequestMessage->Headers = NewHeaders;
> + return EFI_SUCCESS;
> +}
> +
> diff --git a/RedfishPkg/RedfishRestExDxe/RedfishRestExInternal.h
> b/RedfishPkg/RedfishRestExDxe/RedfishRestExInternal.h
> new file mode 100644
> index 0000000000..a75985928c
> --- /dev/null
> +++ b/RedfishPkg/RedfishRestExDxe/RedfishRestExInternal.h
> @@ -0,0 +1,611 @@
> +/** @file
> + RedfishRestExDxe support functions definitions.
> +
> + Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> + (C) Copyright 2019-2020 Hewlett Packard Enterprise Development LP<BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef EFI_REDFISH_RESTEX_INTERNAL_H_
> +#define EFI_REDFISH_RESTEX_INTERNAL_H_
> +
> +///
> +/// Libraries classes
> +///
> +#include <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/HttpIoLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/NetLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiDriverEntryPoint.h>
> +
> +///
> +/// UEFI Driver Model Protocols
> +///
> +#include <Protocol/DriverBinding.h>
> +#include <Protocol/RestEx.h>
> +#include <Protocol/ServiceBinding.h>
> +
> +#include "RedfishRestExDriver.h"
> +
> +/**
> + This function check
> +
> + @param[in] Instance Pointer to EFI_REST_EX_PROTOCOL instance for
> a particular
> + REST service.
> + @param[in] HttpReceiveEfiStatus This is the status return from
> HttpIoRecvResponse
> +
> + @retval EFI_SUCCESS The payload receive from Redfish service in
> sucessfully.
> + @retval EFI_NOT_READY May need to resend the HTTP request.
> + @retval EFI_DEVICE_ERROR Something wrong and can't be resolved.
> + @retval Others Other errors as indicated.
> +
> +**/
> +EFI_STATUS
> +RedfishCheckHttpReceiveStatus (
> + IN RESTEX_INSTANCE *Instance,
> + IN EFI_STATUS HttpIoReceiveStatus
> + );
> +
> +/**
> + This function send the HTTP request without body to see
> + if the write to URL is permitted by Redfish service. This function
> + checks if the HTTP request has Content-length in HTTP header. If yes,
> + set HTTP body to NULL and then send to service. Check the HTTP status
> + for the firther actions.
> +
> + @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for
> a particular
> + REST service.
> + @param[in] RequestMessage Pointer to the HTTP request data for
> this resource
> + @param[in] PreservedRequestHeaders The pointer to save the request
> headers
> + @param[in] ItsWrite This is write method to URL.
> +
> + @retval EFI_INVALID_PARAMETER Improper given parameters.
> + @retval EFI_SUCCESS This HTTP request is free to send to Redfish
> service.
> + @retval EFI_OUT_OF_RESOURCES NOt enough memory to process.
> + @retval EFI_ACCESS_DENIED Not allowed to write to this URL.
> +
> + @retval Others Other errors as indicated.
> +
> +**/
> +EFI_STATUS
> +RedfishHttpAddExpectation (
> + IN EFI_REST_EX_PROTOCOL *This,
> + IN EFI_HTTP_MESSAGE *RequestMessage,
> + IN EFI_HTTP_HEADER **PreservedRequestHeaders,
> + IN BOOLEAN *ItsWrite
> + );
> +
> +/**
> + Provides a simple HTTP-like interface to send and receive resources from a
> REST service.
> +
> + The SendReceive() function sends an HTTP request to this REST service,
> and returns a
> + response when the data is retrieved from the service. RequestMessage
> contains the HTTP
> + request to the REST resource identified by RequestMessage.Request.Url.
> The
> + ResponseMessage is the returned HTTP response for that request,
> including any HTTP
> + status.
> +
> + @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a
> particular
> + REST service.
> + @param[in] RequestMessage Pointer to the HTTP request data for this
> resource
> + @param[out] ResponseMessage Pointer to the HTTP response data
> obtained for this requested.
> +
> + @retval EFI_SUCCESS operation succeeded.
> + @retval EFI_INVALID_PARAMETER This, RequestMessage, or
> ResponseMessage are NULL.
> + @retval EFI_DEVICE_ERROR An unexpected system or network error
> occurred.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExSendReceive (
> + IN EFI_REST_EX_PROTOCOL *This,
> + IN EFI_HTTP_MESSAGE *RequestMessage,
> + OUT EFI_HTTP_MESSAGE *ResponseMessage
> + );
> +
> +/**
> + Obtain the current time from this REST service instance.
> +
> + The GetServiceTime() function is an optional interface to obtain the
> current time from
> + this REST service instance. If this REST service does not support to retrieve
> the time,
> + this function returns EFI_UNSUPPORTED. This function must returns
> EFI_UNSUPPORTED if
> + EFI_REST_EX_SERVICE_TYPE returned in EFI_REST_EX_SERVICE_INFO from
> GetService() is
> + EFI_REST_EX_SERVICE_UNSPECIFIC.
> +
> + @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a
> particular
> + REST service.
> + @param[out] Time A pointer to storage to receive a snapshot of
> the current time of
> + the REST service.
> +
> + @retval EFI_SUCCESS operation succeeded.
> + @retval EFI_INVALID_PARAMETER This or Time are NULL.
> + @retval EFI_UNSUPPORTED The RESTful service does not support
> returning the time.
> + @retval EFI_DEVICE_ERROR An unexpected system or network error
> occurred.
> + @retval EFI_NOT_READY The configuration of this instance is not set
> yet. Configure() must
> + be executed and returns successfully prior to invoke this
> function.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExGetServiceTime (
> + IN EFI_REST_EX_PROTOCOL *This,
> + OUT EFI_TIME *Time
> + );
> +
> +/**
> + This function returns the information of REST service provided by this EFI
> REST EX driver instance.
> +
> + The information such as the type of REST service and the access mode of
> REST EX driver instance
> + (In-band or Out-of-band) are described in EFI_REST_EX_SERVICE_INFO
> structure. For the vendor-specific
> + REST service, vendor-specific REST service information is returned in
> VendorSpecifcData.
> + REST EX driver designer is well know what REST service this REST EX driver
> instance intends to
> + communicate with. The designer also well know this driver instance is used
> to talk to BMC through
> + specific platform mechanism or talk to REST server through UEFI HTTP
> protocol. REST EX driver is
> + responsible to fill up the correct information in
> EFI_REST_EX_SERVICE_INFO. EFI_REST_EX_SERVICE_INFO
> + is referred by EFI REST clients to pickup the proper EFI REST EX driver
> instance to get and set resource.
> + GetService() is a basic and mandatory function which must be able to use
> even Configure() is not invoked
> + in previously.
> +
> + @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a
> particular
> + REST service.
> + @param[out] RestExServiceInfo Pointer to receive a pointer to
> EFI_REST_EX_SERVICE_INFO structure. The
> + format of EFI_REST_EX_SERVICE_INFO is version
> controlled for the future
> + extension. The version of EFI_REST_EX_SERVICE_INFO
> structure is returned
> + in the header within this structure. EFI REST client refers to
> the correct
> + format of structure according to the version number. The
> pointer to
> + EFI_REST_EX_SERVICE_INFO is a memory block allocated
> by EFI REST EX driver
> + instance. That is caller's responsibility to free this memory
> when this
> + structure is no longer needed. Refer to Related Definitions
> below for the
> + definitions of EFI_REST_EX_SERVICE_INFO structure.
> +
> + @retval EFI_SUCCESS EFI_REST_EX_SERVICE_INFO is returned in
> RestExServiceInfo. This function
> + is not supported in this REST EX Protocol driver instance.
> + @retval EFI_UNSUPPORTED This function is not supported in this REST
> EX Protocol driver instance.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExGetService (
> + IN EFI_REST_EX_PROTOCOL *This,
> + OUT EFI_REST_EX_SERVICE_INFO **RestExServiceInfo
> + );
> +
> +/**
> + This function returns operational configuration of current EFI REST EX child
> instance.
> +
> + This function returns the current configuration of EFI REST EX child instance.
> The format of
> + operational configuration depends on the implementation of EFI REST EX
> driver instance. For
> + example, HTTP-aware EFI REST EX driver instance uses EFI HTTP protocol as
> the undying protocol
> + to communicate with REST service. In this case, the type of configuration is
> + EFI_REST_EX_CONFIG_TYPE_HTTP returned from GetService().
> EFI_HTTP_CONFIG_DATA is used as EFI REST
> + EX configuration format and returned to EFI REST client. User has to type
> cast RestExConfigData
> + to EFI_HTTP_CONFIG_DATA. For those non HTTP-aware REST EX driver
> instances, the type of configuration
> + is EFI_REST_EX_CONFIG_TYPE_UNSPECIFIC returned from GetService(). In
> this case, the format of
> + returning data could be non industrial. Instead, the format of configuration
> data is system/platform
> + specific definition such as BMC mechanism used in EFI REST EX driver
> instance. EFI REST client and
> + EFI REST EX driver instance have to refer to the specific system /platform
> spec which is out of UEFI scope.
> +
> + @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
> + @param[out] RestExConfigData Pointer to receive a pointer to
> EFI_REST_EX_CONFIG_DATA.
> + The memory allocated for configuration data should be
> freed
> + by caller. See Related Definitions for the details.
> +
> + @retval EFI_SUCCESS EFI_REST_EX_CONFIG_DATA is returned in
> successfully.
> + @retval EFI_UNSUPPORTED This function is not supported in this REST
> EX Protocol driver instance.
> + @retval EFI_NOT_READY The configuration of this instance is not set
> yet. Configure() must be
> + executed and returns successfully prior to invoke this
> function.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExGetModeData (
> + IN EFI_REST_EX_PROTOCOL *This,
> + OUT EFI_REST_EX_CONFIG_DATA *RestExConfigData
> + );
> +
> +/**
> + This function is used to configure EFI REST EX child instance.
> +
> + This function is used to configure the setting of underlying protocol of REST
> EX child
> + instance. The type of configuration is according to the implementation of
> EFI REST EX
> + driver instance. For example, HTTP-aware EFI REST EX driver instance uses
> EFI HTTP protocol
> + as the undying protocol to communicate with REST service. The type of
> configuration is
> + EFI_REST_EX_CONFIG_TYPE_HTTP and RestExConfigData is the same
> format with EFI_HTTP_CONFIG_DATA.
> + Akin to HTTP configuration, REST EX child instance can be configure to use
> different HTTP
> + local access point for the data transmission. Multiple REST clients may use
> different
> + configuration of HTTP to distinguish themselves, such as to use the
> different TCP port.
> + For those non HTTP-aware REST EX driver instance, the type of
> configuration is
> + EFI_REST_EX_CONFIG_TYPE_UNSPECIFIC. RestExConfigData refers to the
> non industrial standard.
> + Instead, the format of configuration data is system/platform specific
> definition such as BMC.
> + In this case, EFI REST client and EFI REST EX driver instance have to refer to
> the specific
> + system/platform spec which is out of the UEFI scope. Besides
> GetService()function, no other
> + EFI REST EX functions can be executed by this instance until Configure()is
> executed and returns
> + successfully. All other functions must returns EFI_NOT_READY if this
> instance is not configured
> + yet. Set RestExConfigData to NULL means to put EFI REST EX child instance
> into the unconfigured
> + state.
> +
> + @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
> + @param[in] RestExConfigData Pointer to EFI_REST_EX_CONFIG_DATA.
> See Related Definitions in
> + GetModeData() protocol interface.
> +
> + @retval EFI_SUCCESS EFI_REST_EX_CONFIG_DATA is set in
> successfully.
> + @retval EFI_DEVICE_ERROR Configuration for this REST EX child
> instance is failed with the given
> + EFI_REST_EX_CONFIG_DATA.
> + @retval EFI_UNSUPPORTED This function is not supported in this REST
> EX Protocol driver instance.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExConfigure (
> + IN EFI_REST_EX_PROTOCOL *This,
> + IN EFI_REST_EX_CONFIG_DATA RestExConfigData
> + );
> +
> +/**
> + This function sends REST request to REST service and signal caller's event
> asynchronously when
> + the final response is received by REST EX Protocol driver instance.
> +
> + The essential design of this function is to handle asynchronous
> send/receive implicitly according
> + to REST service asynchronous request mechanism. Caller will get the
> notification once the response
> + is returned from REST service.
> +
> + @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
> + @param[in] RequestMessage This is the HTTP request message sent
> to REST service. Set RequestMessage
> + to NULL to cancel the previous asynchronous request
> associated with the
> + corresponding RestExToken. See descriptions for the
> details.
> + @param[in] RestExToken REST EX token which REST EX Protocol
> instance uses to notify REST client
> + the status of response of asynchronous REST request. See
> related definition
> + of EFI_REST_EX_TOKEN.
> + @param[in] TimeOutInMilliSeconds The pointer to the timeout in
> milliseconds which REST EX Protocol driver
> + instance refers as the duration to drop asynchronous REST
> request. NULL
> + pointer means no timeout for this REST request. REST EX
> Protocol driver
> + signals caller's event with EFI_STATUS set to EFI_TIMEOUT
> in RestExToken
> + if REST EX Protocol can't get the response from REST
> service within
> + TimeOutInMilliSeconds.
> +
> + @retval EFI_SUCCESS Asynchronous REST request is established.
> + @retval EFI_UNSUPPORTED This REST EX Protocol driver instance
> doesn't support asynchronous request.
> + @retval EFI_TIMEOUT Asynchronous REST request is not
> established and timeout is expired.
> + @retval EFI_ABORT Previous asynchronous REST request has been
> canceled.
> + @retval EFI_DEVICE_ERROR Otherwise, returns EFI_DEVICE_ERROR
> for other errors according to HTTP Status Code.
> + @retval EFI_NOT_READY The configuration of this instance is not set
> yet. Configure() must be executed
> + and returns successfully prior to invoke this function.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExAyncSendReceive (
> + IN EFI_REST_EX_PROTOCOL *This,
> + IN EFI_HTTP_MESSAGE *RequestMessage OPTIONAL,
> + IN EFI_REST_EX_TOKEN *RestExToken,
> + IN UINTN *TimeOutInMilliSeconds OPTIONAL
> + );
> +
> +/**
> + This function sends REST request to a REST Event service and signals caller's
> event
> + token asynchronously when the URI resource change event is received by
> REST EX
> + Protocol driver instance.
> +
> + The essential design of this function is to monitor event implicitly according
> to
> + REST service event service mechanism. Caller will get the notification if
> certain
> + resource is changed.
> +
> + @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
> + @param[in] RequestMessage This is the HTTP request message sent
> to REST service. Set RequestMessage
> + to NULL to cancel the previous event service associated
> with the corresponding
> + RestExToken. See descriptions for the details.
> + @param[in] RestExToken REST EX token which REST EX Protocol
> driver instance uses to notify REST client
> + the URI resource which monitored by REST client has
> been changed. See the related
> + definition of EFI_REST_EX_TOKEN in
> EFI_REST_EX_PROTOCOL.AsyncSendReceive().
> +
> + @retval EFI_SUCCESS Asynchronous REST request is established.
> + @retval EFI_UNSUPPORTED This REST EX Protocol driver instance
> doesn't support asynchronous request.
> + @retval EFI_ABORT Previous asynchronous REST request has been
> canceled or event subscription has been
> + delete from service.
> + @retval EFI_DEVICE_ERROR Otherwise, returns EFI_DEVICE_ERROR
> for other errors according to HTTP Status Code.
> + @retval EFI_NOT_READY The configuration of this instance is not set
> yet. Configure() must be executed
> + and returns successfully prior to invoke this function.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExEventService (
> + IN EFI_REST_EX_PROTOCOL *This,
> + IN EFI_HTTP_MESSAGE *RequestMessage OPTIONAL,
> + IN EFI_REST_EX_TOKEN *RestExToken
> + );
> +/**
> + Create a new TLS session becuase the previous on is closed.
> + status.
> +
> + @param[in] Instance Pointer to EFI_REST_EX_PROTOCOL instance
> for a particular
> + REST service.
> + @retval EFI_SUCCESS operation succeeded.
> + @retval EFI Errors Other errors.
> +
> +**/
> +EFI_STATUS
> +ResetHttpTslSession (
> + IN RESTEX_INSTANCE *Instance
> +);
> +
> +
> +/**
> + Callback function which provided by user to remove one node in
> NetDestroyLinkList process.
> +
> + @param[in] Entry The entry to be removed.
> + @param[in] Context Pointer to the callback context corresponds to
> the Context in NetDestroyLinkList.
> +
> + @retval EFI_SUCCESS The entry has been removed successfully.
> + @retval Others Fail to remove the entry.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RestExDestroyChildEntryInHandleBuffer (
> + IN LIST_ENTRY *Entry,
> + IN VOID *Context
> + );
> +
> +/**
> + Destroy the RestEx instance and recycle the resources.
> +
> + @param[in] Instance The pointer to the RestEx instance.
> +
> +**/
> +VOID
> +RestExDestroyInstance (
> + IN RESTEX_INSTANCE *Instance
> + );
> +
> +/**
> + Create the RestEx instance and initialize it.
> +
> + @param[in] Service The pointer to the RestEx service.
> + @param[out] Instance The pointer to the RestEx instance.
> +
> + @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
> + @retval EFI_SUCCESS The RestEx instance is created.
> +
> +**/
> +EFI_STATUS
> +RestExCreateInstance (
> + IN RESTEX_SERVICE *Service,
> + OUT RESTEX_INSTANCE **Instance
> + );
> +
> +
> +/**
> + Release all the resource used the RestEx service binding instance.
> +
> + @param[in] RestExSb The RestEx service binding instance.
> +
> +**/
> +VOID
> +RestExDestroyService (
> + IN RESTEX_SERVICE *RestExSb
> + );
> +
> +/**
> + Create then initialize a RestEx service binding instance.
> +
> + @param[in] Controller The controller to install the RestEx service
> + binding on.
> + @param[in] Image The driver binding image of the RestEx driver.
> + @param[out] Service The variable to receive the created service
> + binding instance.
> +
> + @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create
> the instance.
> + @retval EFI_SUCCESS The service instance is created for the
> controller.
> +
> +**/
> +EFI_STATUS
> +RestExCreateService (
> + IN EFI_HANDLE Controller,
> + IN EFI_HANDLE Image,
> + OUT RESTEX_SERVICE **Service
> + );
> +
> +/**
> + This is the declaration of an EFI image entry point. This entry point is
> + the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
> + both device drivers and bus drivers.
> +
> + @param[in] ImageHandle The firmware allocated handle for the UEFI
> image.
> + @param[in] SystemTable A pointer to the EFI System Table.
> +
> + @retval EFI_SUCCESS The operation completed successfully.
> + @retval Others An unexpected error occurred.
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExDriverEntryPoint (
> + IN EFI_HANDLE ImageHandle,
> + IN EFI_SYSTEM_TABLE *SystemTable
> + );
> +
> +/**
> + Tests to see if this driver supports a given controller. If a child device is
> provided,
> + it further tests to see if this driver supports creating a handle for the
> specified child device.
> +
> + This function checks to see if the driver specified by This supports the
> device specified by
> + ControllerHandle. Drivers will typically use the device path attached to
> + ControllerHandle and/or the services from the bus I/O abstraction
> attached to
> + ControllerHandle to determine if the driver supports ControllerHandle.
> This function
> + may be called many times during platform initialization. In order to reduce
> boot times, the tests
> + performed by this function must be very small, and take as little time as
> possible to execute. This
> + function must not change the state of any hardware devices, and this
> function must be aware that the
> + device specified by ControllerHandle may already be managed by the
> same driver or a
> + different driver. This function must match its calls to AllocatePages() with
> FreePages(),
> + AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
> + Because ControllerHandle may have been previously started by the same
> driver, if a protocol is
> + already in the opened state, then it must not be closed with
> CloseProtocol(). This is required
> + to guarantee the state of ControllerHandle is not modified by this function.
> +
> + @param[in] This A pointer to the
> EFI_DRIVER_BINDING_PROTOCOL instance.
> + @param[in] ControllerHandle The handle of the controller to test. This
> handle
> + must support a protocol interface that supplies
> + an I/O abstraction to the driver.
> + @param[in] RemainingDevicePath A pointer to the remaining portion of a
> device path. This
> + parameter is ignored by device drivers, and is optional for
> bus
> + drivers. For bus drivers, if this parameter is not NULL, then
> + the bus driver must determine if the bus controller
> specified
> + by ControllerHandle and the child controller specified
> + by RemainingDevicePath are both supported by this
> + bus driver.
> +
> + @retval EFI_SUCCESS The device specified by ControllerHandle and
> + RemainingDevicePath is supported by the driver specified
> by This.
> + @retval EFI_ALREADY_STARTED The device specified by
> ControllerHandle and
> + RemainingDevicePath is already being managed by the
> driver
> + specified by This.
> + @retval EFI_ACCESS_DENIED The device specified by ControllerHandle
> and
> + RemainingDevicePath is already being managed by a
> different
> + driver or an application that requires exclusive access.
> + Currently not implemented.
> + @retval EFI_UNSUPPORTED The device specified by ControllerHandle
> and
> + RemainingDevicePath is not supported by the driver
> specified by This.
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExDriverBindingSupported (
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
> + IN EFI_HANDLE ControllerHandle,
> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
> + );
> +
> +/**
> + Starts a device controller or a bus controller.
> +
> + The Start() function is designed to be invoked from the EFI boot service
> ConnectController().
> + As a result, much of the error checking on the parameters to Start() has
> been moved into this
> + common boot service. It is legal to call Start() from other locations,
> + but the following calling restrictions must be followed, or the system
> behavior will not be deterministic.
> + 1. ControllerHandle must be a valid EFI_HANDLE.
> + 2. If RemainingDevicePath is not NULL, then it must be a pointer to a
> naturally aligned
> + EFI_DEVICE_PATH_PROTOCOL.
> + 3. Prior to calling Start(), the Supported() function for the driver specified
> by This must
> + have been called with the same calling parameters, and Supported()
> must have returned EFI_SUCCESS.
> +
> + @param[in] This A pointer to the
> EFI_DRIVER_BINDING_PROTOCOL instance.
> + @param[in] ControllerHandle The handle of the controller to start. This
> handle
> + must support a protocol interface that supplies
> + an I/O abstraction to the driver.
> + @param[in] RemainingDevicePath A pointer to the remaining portion of a
> device path. This
> + parameter is ignored by device drivers, and is optional for
> bus
> + drivers. For a bus driver, if this parameter is NULL, then
> handles
> + for all the children of Controller are created by this driver.
> + If this parameter is not NULL and the first Device Path
> Node is
> + not the End of Device Path Node, then only the handle for
> the
> + child device specified by the first Device Path Node of
> + RemainingDevicePath is created by this driver.
> + If the first Device Path Node of RemainingDevicePath is
> + the End of Device Path Node, no child handle is created by
> this
> + driver.
> +
> + @retval EFI_SUCCESS The device was started.
> + @retval EFI_DEVICE_ERROR The device could not be started due to a
> device error.Currently not implemented.
> + @retval EFI_OUT_OF_RESOURCES The request could not be completed
> due to a lack of resources.
> + @retval Others The driver failded to start the device.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExDriverBindingStart (
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
> + IN EFI_HANDLE ControllerHandle,
> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
> + );
> +
> +/**
> + Stops a device controller or a bus controller.
> +
> + The Stop() function is designed to be invoked from the EFI boot service
> DisconnectController().
> + As a result, much of the error checking on the parameters to Stop() has
> been moved
> + into this common boot service. It is legal to call Stop() from other locations,
> + but the following calling restrictions must be followed, or the system
> behavior will not be deterministic.
> + 1. ControllerHandle must be a valid EFI_HANDLE that was used on a
> previous call to this
> + same driver's Start() function.
> + 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a
> valid
> + EFI_HANDLE. In addition, all of these handles must have been created in
> this driver's
> + Start() function, and the Start() function must have called OpenProtocol()
> on
> + ControllerHandle with an Attribute of
> EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
> +
> + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL
> instance.
> + @param[in] ControllerHandle A handle to the device being stopped. The
> handle must
> + support a bus specific I/O protocol for the driver
> + to use to stop the device.
> + @param[in] NumberOfChildren The number of child device handles in
> ChildHandleBuffer.
> + @param[in] ChildHandleBuffer An array of child handles to be freed. May
> be NULL
> + if NumberOfChildren is 0.
> +
> + @retval EFI_SUCCESS The device was stopped.
> + @retval EFI_DEVICE_ERROR The device could not be stopped due to a
> device error.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExDriverBindingStop (
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
> + IN EFI_HANDLE ControllerHandle,
> + IN UINTN NumberOfChildren,
> + IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
> + );
> +
> +/**
> + Creates a child handle and installs a protocol.
> +
> + The CreateChild() function installs a protocol on ChildHandle.
> + If ChildHandle is a pointer to NULL, then a new handle is created and
> returned in ChildHandle.
> + If ChildHandle is not a pointer to NULL, then the protocol installs on the
> existing ChildHandle.
> +
> + @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL
> instance.
> + @param[in] ChildHandle Pointer to the handle of the child to create. If it is
> NULL,
> + then a new handle is created. If it is a pointer to an existing
> UEFI handle,
> + then the protocol is added to the existing UEFI handle.
> +
> + @retval EFI_SUCCES The protocol was added to ChildHandle.
> + @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
> + @retval EFI_OUT_OF_RESOURCES There are not enough resources
> available to create
> + the child
> + @retval other The child handle was not created
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExServiceBindingCreateChild (
> + IN EFI_SERVICE_BINDING_PROTOCOL *This,
> + IN EFI_HANDLE *ChildHandle
> + );
> +
> +/**
> + Destroys a child handle with a protocol installed on it.
> +
> + The DestroyChild() function does the opposite of CreateChild(). It removes
> a protocol
> + that was installed by CreateChild() from ChildHandle. If the removed
> protocol is the
> + last protocol on ChildHandle, then ChildHandle is destroyed.
> +
> + @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL
> instance.
> + @param[in] ChildHandle Handle of the child to destroy
> +
> + @retval EFI_SUCCES The protocol was removed from ChildHandle.
> + @retval EFI_UNSUPPORTED ChildHandle does not support the protocol
> that is being removed.
> + @retval EFI_INVALID_PARAMETER Child handle is NULL.
> + @retval EFI_ACCESS_DENIED The protocol could not be removed from
> the ChildHandle
> + because its services are being used.
> + @retval other The child handle was not destroyed
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExServiceBindingDestroyChild (
> + IN EFI_SERVICE_BINDING_PROTOCOL *This,
> + IN EFI_HANDLE ChildHandle
> + );
> +#endif
> diff --git a/RedfishPkg/RedfishRestExDxe/RedfishRestExProtocol.c
> b/RedfishPkg/RedfishRestExDxe/RedfishRestExProtocol.c
> new file mode 100644
> index 0000000000..65a5fe3713
> --- /dev/null
> +++ b/RedfishPkg/RedfishRestExDxe/RedfishRestExProtocol.c
> @@ -0,0 +1,735 @@
> +/** @file
> + Implementation of Redfish EFI_REST_EX_PROTOCOL interfaces.
> +
> + Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> + (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +#include <Uefi.h>
> +#include "RedfishRestExInternal.h"
> +
> +EFI_REST_EX_PROTOCOL mRedfishRestExProtocol = {
> + RedfishRestExSendReceive,
> + RedfishRestExGetServiceTime,
> + RedfishRestExGetService,
> + RedfishRestExGetModeData,
> + RedfishRestExConfigure,
> + RedfishRestExAyncSendReceive,
> + RedfishRestExEventService
> +};
> +
> +/**
> + Provides a simple HTTP-like interface to send and receive resources from a
> REST service.
> +
> + The SendReceive() function sends an HTTP request to this REST service,
> and returns a
> + response when the data is retrieved from the service. RequestMessage
> contains the HTTP
> + request to the REST resource identified by RequestMessage.Request.Url.
> The
> + ResponseMessage is the returned HTTP response for that request,
> including any HTTP
> + status.
> +
> + @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a
> particular
> + REST service.
> + @param[in] RequestMessage Pointer to the HTTP request data for this
> resource
> + @param[out] ResponseMessage Pointer to the HTTP response data
> obtained for this requested.
> +
> + @retval EFI_SUCCESS operation succeeded.
> + @retval EFI_INVALID_PARAMETER This, RequestMessage, or
> ResponseMessage are NULL.
> + @retval EFI_DEVICE_ERROR An unexpected system or network error
> occurred.
> + @retval EFI_ACCESS_DENIED HTTP method is not allowed on this URL.
> + @retval EFI_BAD_BUFFER_SIZE The payload is to large to be handled on
> server side.
> + @retval EFI_UNSUPPORTED Unsupported HTTP response.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExSendReceive (
> + IN EFI_REST_EX_PROTOCOL *This,
> + IN EFI_HTTP_MESSAGE *RequestMessage,
> + OUT EFI_HTTP_MESSAGE *ResponseMessage
> + )
> +{
> + EFI_STATUS Status;
> + RESTEX_INSTANCE *Instance;
> + HTTP_IO_RESPONSE_DATA *ResponseData;
> + UINTN TotalReceivedSize;
> + UINTN Index;
> + LIST_ENTRY *ChunkListLink;
> + HTTP_IO_CHUNKS *ThisChunk;
> + BOOLEAN CopyChunkData;
> + BOOLEAN MediaPresent;
> + EFI_HTTP_HEADER *PreservedRequestHeaders;
> + BOOLEAN ItsWrite;
> + BOOLEAN IsGetChunkedTransfer;
> + HTTP_IO_SEND_CHUNK_PROCESS SendChunkProcess;
> + HTTP_IO_SEND_NON_CHUNK_PROCESS SendNonChunkProcess;
> + EFI_HTTP_MESSAGE ChunkTransferRequestMessage;
> +
> + Status = EFI_SUCCESS;
> + ResponseData = NULL;
> + IsGetChunkedTransfer = FALSE;
> + SendChunkProcess = HttpIoSendChunkNone;
> + SendNonChunkProcess = HttpIoSendNonChunkNone;
> +
> + //
> + // Validate the parameters
> + //
> + if ((This == NULL) || (RequestMessage == NULL) || ResponseMessage ==
> NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + Instance = RESTEX_INSTANCE_FROM_THIS (This);
> +
> + //
> + // Check Media Status.
> + //
> + MediaPresent = TRUE;
> + NetLibDetectMedia (Instance->Service->ControllerHandle,
> &MediaPresent);
> + if (!MediaPresent) {
> + DEBUG ((DEBUG_INFO, "RedfishRestExSendReceive(): No
> MediaPresent.\n"));
> + return EFI_NO_MEDIA;
> + }
> +
> + DEBUG ((DEBUG_INFO, "\nRedfishRestExSendReceive():\n"));
> + DEBUG ((DEBUG_INFO, "*** Perform HTTP Request Method - %d, URL:
> %s\n", RequestMessage->Data.Request->Method, RequestMessage-
> >Data.Request->Url));
> +
> + //
> + // Add header "Expect" to server, only for URL write.
> + //
> + Status = RedfishHttpAddExpectation (This, RequestMessage,
> &PreservedRequestHeaders, &ItsWrite);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> + if (ItsWrite == TRUE) {
> + if (RequestMessage->BodyLength > HTTP_IO_MAX_SEND_PAYLOAD) {
> + //
> + // Send chunked transfer.
> + //
> + SendChunkProcess ++;
> + CopyMem ((VOID *)&ChunkTransferRequestMessage, (VOID
> *)RequestMessage, sizeof (EFI_HTTP_MESSAGE));
> + } else {
> + SendNonChunkProcess ++;
> + }
> + }
> +ReSendRequest:;
> + //
> + // Send out the request to REST service.
> + //
> + if (ItsWrite == TRUE) {
> + //
> + // This is write to URI
> + //
> + if (SendChunkProcess > HttpIoSendChunkNone) {
> + //
> + // This is chunk transfer for writing large payload.
> + // Send request header first and then handle the
> + // following request message body using chunk transfer.
> + //
> + do {
> + Status = HttpIoSendChunkedTransfer(
> + &(Instance->HttpIo),
> + &SendChunkProcess,
> + &ChunkTransferRequestMessage
> + );
> + if (EFI_ERROR (Status)) {
> + goto ON_EXIT;
> + }
> + } while (SendChunkProcess == HttpIoSendChunkContent ||
> SendChunkProcess == HttpIoSendChunkEndChunk);
> + } else {
> + //
> + // This is the non-chunk transfer, send request header first and then
> + // handle the following request message body using chunk transfer.
> + //
> + Status = HttpIoSendRequest(
> + &(Instance->HttpIo),
> + (SendNonChunkProcess == HttpIoSendNonChunkContent)? NULL:
> RequestMessage->Data.Request,
> + (SendNonChunkProcess == HttpIoSendNonChunkContent)? 0:
> RequestMessage->HeaderCount,
> + (SendNonChunkProcess == HttpIoSendNonChunkContent)? NULL:
> RequestMessage->Headers,
> + (SendNonChunkProcess ==
> HttpIoSendNonChunkHeaderZeroContent)? 0: RequestMessage-
> >BodyLength,
> + (SendNonChunkProcess ==
> HttpIoSendNonChunkHeaderZeroContent)? NULL: RequestMessage->Body
> + );
> + }
> + } else {
> + //
> + // This is read from URI.
> + //
> + Status = HttpIoSendRequest(
> + &(Instance->HttpIo),
> + RequestMessage->Data.Request,
> + RequestMessage->HeaderCount,
> + RequestMessage->Headers,
> + RequestMessage->BodyLength,
> + RequestMessage->Body
> + );
> + }
> + if (EFI_ERROR (Status)) {
> + goto ON_EXIT;
> + }
> +
> + //
> + // ResponseMessage->Data.Response is to indicate whether to receive
> the HTTP header or not.
> + // ResponseMessage->BodyLength/ResponseMessage->Body are to
> indicate whether to receive the response body or not.
> + // Clean the previous buffers and all of them will be allocated later
> according to the actual situation.
> + //
> + if (ResponseMessage->Data.Response != NULL) {
> + FreePool(ResponseMessage->Data.Response);
> + ResponseMessage->Data.Response = NULL;
> + }
> +
> + ResponseMessage->BodyLength = 0;
> + if (ResponseMessage->Body != NULL) {
> + FreePool(ResponseMessage->Body);
> + ResponseMessage->Body = NULL;
> + }
> +
> + //
> + // Use zero BodyLength to only receive the response headers.
> + //
> + ResponseData = AllocateZeroPool (sizeof(HTTP_IO_RESPONSE_DATA));
> + if (ResponseData == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + goto ON_EXIT;
> + }
> +
> + DEBUG ((DEBUG_INFO, "Receiving HTTP response and headers...\n"));
> + Status = RedfishCheckHttpReceiveStatus (
> + Instance,
> + HttpIoRecvResponse (
> + &(Instance->HttpIo),
> + TRUE,
> + ResponseData
> + )
> + );
> + if (Status == EFI_NOT_READY) {
> + goto ReSendRequest;
> + } else if (Status == EFI_DEVICE_ERROR) {
> + goto ON_EXIT;
> + }
> + //
> + // Restore the headers if it ever changed in RedfishHttpAddExpectation().
> + //
> + if (RequestMessage->Headers != PreservedRequestHeaders) {
> + FreePool (RequestMessage->Headers);
> + RequestMessage->Headers = PreservedRequestHeaders; // Restore
> headers before we adding "Expect".
> + RequestMessage->HeaderCount --; // Minus one header count
> for "Expect".
> + }
> +
> + DEBUG ((DEBUG_INFO, "HTTP Response StatusCode - %d:",
> ResponseData->Response.StatusCode));
> + if (ResponseData->Response.StatusCode == HTTP_STATUS_200_OK) {
> + DEBUG ((DEBUG_INFO, "HTTP_STATUS_200_OK\n"));
> +
> + if (SendChunkProcess == HttpIoSendChunkHeaderZeroContent) {
> + DEBUG ((DEBUG_INFO, "This is chunk transfer, start to send all chunks.",
> ResponseData->Response.StatusCode));
> + SendChunkProcess ++;
> + goto ReSendRequest;
> + }
> + } else if (ResponseData->Response.StatusCode ==
> HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE) {
> + DEBUG ((DEBUG_INFO,
> "HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE\n"));
> +
> + Status = EFI_BAD_BUFFER_SIZE;
> + goto ON_EXIT;
> + } else if (ResponseData->Response.StatusCode ==
> HTTP_STATUS_405_METHOD_NOT_ALLOWED){
> + DEBUG ((DEBUG_ERROR,
> "HTTP_STATUS_405_METHOD_NOT_ALLOWED\n"));
> +
> + Status = EFI_ACCESS_DENIED;
> + goto ON_EXIT;
> + } else if (ResponseData->Response.StatusCode ==
> HTTP_STATUS_400_BAD_REQUEST) {
> + DEBUG ((DEBUG_INFO, "HTTP_STATUS_400_BAD_REQUEST\n"));
> + if (SendChunkProcess == HttpIoSendChunkHeaderZeroContent) {
> + DEBUG ((DEBUG_INFO, "Bad request may caused by zero length chunk.
> Try to send all chunks...\n"));
> + SendChunkProcess ++;
> + goto ReSendRequest;
> + }
> + } else if (ResponseData->Response.StatusCode ==
> HTTP_STATUS_100_CONTINUE) {
> + DEBUG ((DEBUG_INFO, "HTTP_STATUS_100_CONTINUE\n"));
> + if (SendChunkProcess == HttpIoSendChunkHeaderZeroContent) {
> + //
> + // We get HTTP_STATUS_100_CONTINUE to send the body using chunk
> transfer.
> + //
> + DEBUG ((DEBUG_INFO, "HTTP_STATUS_100_CONTINUE for chunk
> transfer...\n"));
> + SendChunkProcess ++;
> + goto ReSendRequest;
> + }
> + if (SendNonChunkProcess == HttpIoSendNonChunkHeaderZeroContent)
> {
> + DEBUG ((DEBUG_INFO, "HTTP_STATUS_100_CONTINUE for non chunk
> transfer...\n"));
> + SendNonChunkProcess ++;
> + goto ReSendRequest;
> + }
> + //
> + // It's the REST protocol's responsibility to handle the interim HTTP
> response (e.g. 100 Continue Informational),
> + // and return the final response content to the caller.
> + //
> + if (ResponseData->Headers != NULL && ResponseData->HeaderCount !=
> 0) {
> + FreePool (ResponseData->Headers);
> + }
> + ZeroMem (ResponseData, sizeof(HTTP_IO_RESPONSE_DATA));
> + Status = HttpIoRecvResponse (
> + &(Instance->HttpIo),
> + TRUE,
> + ResponseData
> + );
> + if (EFI_ERROR (Status)) {
> + goto ON_EXIT;
> + }
> + } else {
> + DEBUG ((DEBUG_ERROR, "This HTTP Status is not handled!\n"));
> + Status = EFI_UNSUPPORTED;
> + goto ON_EXIT;
> + }
> +
> + //
> + // Ready to return the StatusCode, Header info and BodyLength.
> + //
> + ResponseMessage->Data.Response = AllocateZeroPool (sizeof
> (EFI_HTTP_RESPONSE_DATA));
> + if (ResponseMessage->Data.Response == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + goto ON_EXIT;
> + }
> +
> + ResponseMessage->Data.Response->StatusCode = ResponseData-
> >Response.StatusCode;
> + ResponseMessage->HeaderCount = ResponseData->HeaderCount;
> + ResponseMessage->Headers = ResponseData->Headers;
> +
> + //
> + // Get response message body.
> + //
> + if (ResponseMessage->HeaderCount > 0) {
> + Status = HttpIoGetContentLength (ResponseMessage->HeaderCount,
> ResponseMessage->Headers, &ResponseMessage->BodyLength);
> + if (EFI_ERROR (Status) && Status != EFI_NOT_FOUND) {
> + goto ON_EXIT;
> + }
> +
> + if (Status == EFI_NOT_FOUND) {
> + ASSERT (ResponseMessage->BodyLength == 0);
> + }
> +
> + if (ResponseMessage->BodyLength == 0) {
> + //
> + // Check if Chunked Transfer Coding.
> + //
> + Status = HttpIoGetChunkedTransferContent (
> + &(Instance->HttpIo),
> + ResponseMessage->HeaderCount,
> + ResponseMessage->Headers,
> + &ChunkListLink,
> + &ResponseMessage->BodyLength
> + );
> + if (EFI_ERROR (Status) && Status != EFI_NOT_FOUND) {
> + goto ON_EXIT;
> + }
> + if (Status == EFI_SUCCESS &&
> + ChunkListLink != NULL &&
> + !IsListEmpty(ChunkListLink) &&
> + ResponseMessage->BodyLength != 0) {
> + IsGetChunkedTransfer = TRUE;
> + //
> + // Copy data to Message body.
> + //
> + CopyChunkData = TRUE;
> + ResponseMessage->Body = AllocateZeroPool (ResponseMessage-
> >BodyLength);
> + if (ResponseMessage->Body == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + CopyChunkData = FALSE;
> + }
> + Index = 0;
> + while (!IsListEmpty(ChunkListLink)) {
> + ThisChunk = (HTTP_IO_CHUNKS *)GetFirstNode (ChunkListLink);
> + if (CopyChunkData) {
> + CopyMem(((UINT8 *)ResponseMessage->Body + Index), (UINT8
> *)ThisChunk->Data, ThisChunk->Length);
> + Index += ThisChunk->Length;
> + }
> + RemoveEntryList (&ThisChunk->NextChunk);
> + FreePool ((VOID *)ThisChunk->Data);
> + FreePool ((VOID *)ThisChunk);
> + };
> + FreePool ((VOID *)ChunkListLink);
> + }
> + }
> + Status = EFI_SUCCESS;
> + }
> +
> + //
> + // Ready to return the Body from REST service if have any.
> + //
> + if (ResponseMessage->BodyLength > 0 && !IsGetChunkedTransfer) {
> + ResponseData->HeaderCount = 0;
> + ResponseData->Headers = NULL;
> +
> + ResponseMessage->Body = AllocateZeroPool (ResponseMessage-
> >BodyLength);
> + if (ResponseMessage->Body == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + goto ON_EXIT;
> + }
> +
> + //
> + // Only receive the Body.
> + //
> + TotalReceivedSize = 0;
> + while (TotalReceivedSize < ResponseMessage->BodyLength) {
> + ResponseData->BodyLength = ResponseMessage->BodyLength -
> TotalReceivedSize;
> + ResponseData->Body = (CHAR8 *) ResponseMessage->Body +
> TotalReceivedSize;
> + Status = HttpIoRecvResponse (
> + &(Instance->HttpIo),
> + FALSE,
> + ResponseData
> + );
> + if (EFI_ERROR (Status)) {
> + goto ON_EXIT;
> + }
> +
> + TotalReceivedSize += ResponseData->BodyLength;
> + }
> + DEBUG ((DEBUG_INFO, "Total of lengh of Response :%d\n",
> TotalReceivedSize));
> + }
> + DEBUG ((DEBUG_INFO, "RedfishRestExSendReceive()- EFI_STATUS: %r\n",
> Status));
> +
> +ON_EXIT:
> +
> + if (ResponseData != NULL) {
> + FreePool (ResponseData);
> + }
> +
> + if (EFI_ERROR (Status)) {
> + if (ResponseMessage->Data.Response != NULL) {
> + FreePool (ResponseMessage->Data.Response);
> + ResponseMessage->Data.Response = NULL;
> + }
> +
> + if (ResponseMessage->Body != NULL) {
> + FreePool (ResponseMessage->Body);
> + ResponseMessage->Body = NULL;
> + }
> + }
> + return Status;
> +}
> +
> +/**
> + Obtain the current time from this REST service instance.
> +
> + The GetServiceTime() function is an optional interface to obtain the
> current time from
> + this REST service instance. If this REST service does not support to retrieve
> the time,
> + this function returns EFI_UNSUPPORTED. This function must returns
> EFI_UNSUPPORTED if
> + EFI_REST_EX_SERVICE_TYPE returned in EFI_REST_EX_SERVICE_INFO from
> GetService() is
> + EFI_REST_EX_SERVICE_UNSPECIFIC.
> +
> + @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a
> particular
> + REST service.
> + @param[out] Time A pointer to storage to receive a snapshot of
> the current time of
> + the REST service.
> +
> + @retval EFI_SUCCESS operation succeeded.
> + @retval EFI_INVALID_PARAMETER This or Time are NULL.
> + @retval EFI_UNSUPPORTED The RESTful service does not support
> returning the time.
> + @retval EFI_DEVICE_ERROR An unexpected system or network error
> occurred.
> + @retval EFI_NOT_READY The configuration of this instance is not set
> yet. Configure() must
> + be executed and returns successfully prior to invoke this
> function.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExGetServiceTime (
> + IN EFI_REST_EX_PROTOCOL *This,
> + OUT EFI_TIME *Time
> + )
> +{
> + return EFI_UNSUPPORTED;
> +}
> +
> +/**
> + This function returns the information of REST service provided by this EFI
> REST EX driver instance.
> +
> + The information such as the type of REST service and the access mode of
> REST EX driver instance
> + (In-band or Out-of-band) are described in EFI_REST_EX_SERVICE_INFO
> structure. For the vendor-specific
> + REST service, vendor-specific REST service information is returned in
> VendorSpecifcData.
> + REST EX driver designer is well know what REST service this REST EX driver
> instance intends to
> + communicate with. The designer also well know this driver instance is used
> to talk to BMC through
> + specific platform mechanism or talk to REST server through UEFI HTTP
> protocol. REST EX driver is
> + responsible to fill up the correct information in
> EFI_REST_EX_SERVICE_INFO. EFI_REST_EX_SERVICE_INFO
> + is referred by EFI REST clients to pickup the proper EFI REST EX driver
> instance to get and set resource.
> + GetService() is a basic and mandatory function which must be able to use
> even Configure() is not invoked
> + in previously.
> +
> + @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a
> particular
> + REST service.
> + @param[out] RestExServiceInfo Pointer to receive a pointer to
> EFI_REST_EX_SERVICE_INFO structure. The
> + format of EFI_REST_EX_SERVICE_INFO is version
> controlled for the future
> + extension. The version of EFI_REST_EX_SERVICE_INFO
> structure is returned
> + in the header within this structure. EFI REST client refers to
> the correct
> + format of structure according to the version number. The
> pointer to
> + EFI_REST_EX_SERVICE_INFO is a memory block allocated
> by EFI REST EX driver
> + instance. That is caller's responsibility to free this memory
> when this
> + structure is no longer needed. Refer to Related Definitions
> below for the
> + definitions of EFI_REST_EX_SERVICE_INFO structure.
> +
> + @retval EFI_SUCCESS EFI_REST_EX_SERVICE_INFO is returned in
> RestExServiceInfo. This function
> + is not supported in this REST EX Protocol driver instance.
> + @retval EFI_UNSUPPORTED This function is not supported in this REST
> EX Protocol driver instance.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExGetService (
> + IN EFI_REST_EX_PROTOCOL *This,
> + OUT EFI_REST_EX_SERVICE_INFO **RestExServiceInfo
> + )
> +{
> + EFI_TPL OldTpl;
> + RESTEX_INSTANCE *Instance;
> + EFI_REST_EX_SERVICE_INFO *ServiceInfo;
> +
> + ServiceInfo = NULL;
> +
> + if (This == NULL || RestExServiceInfo == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
> +
> + Instance = RESTEX_INSTANCE_FROM_THIS (This);
> +
> + ServiceInfo = AllocateZeroPool (sizeof (EFI_REST_EX_SERVICE_INFO));
> + if (ServiceInfo == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + CopyMem (ServiceInfo, &(Instance->Service->RestExServiceInfo), sizeof
> (EFI_REST_EX_SERVICE_INFO));
> +
> + *RestExServiceInfo = ServiceInfo;
> +
> + gBS->RestoreTPL (OldTpl);
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + This function returns operational configuration of current EFI REST EX child
> instance.
> +
> + This function returns the current configuration of EFI REST EX child instance.
> The format of
> + operational configuration depends on the implementation of EFI REST EX
> driver instance. For
> + example, HTTP-aware EFI REST EX driver instance uses EFI HTTP protocol as
> the undying protocol
> + to communicate with REST service. In this case, the type of configuration is
> + EFI_REST_EX_CONFIG_TYPE_HTTP returned from GetService().
> EFI_HTTP_CONFIG_DATA is used as EFI REST
> + EX configuration format and returned to EFI REST client. User has to type
> cast RestExConfigData
> + to EFI_HTTP_CONFIG_DATA. For those non HTTP-aware REST EX driver
> instances, the type of configuration
> + is EFI_REST_EX_CONFIG_TYPE_UNSPECIFIC returned from GetService(). In
> this case, the format of
> + returning data could be non industrial. Instead, the format of configuration
> data is system/platform
> + specific definition such as BMC mechanism used in EFI REST EX driver
> instance. EFI REST client and
> + EFI REST EX driver instance have to refer to the specific system /platform
> spec which is out of UEFI scope.
> +
> + @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
> + @param[out] RestExConfigData Pointer to receive a pointer to
> EFI_REST_EX_CONFIG_DATA.
> + The memory allocated for configuration data should be
> freed
> + by caller. See Related Definitions for the details.
> +
> + @retval EFI_SUCCESS EFI_REST_EX_CONFIG_DATA is returned in
> successfully.
> + @retval EFI_UNSUPPORTED This function is not supported in this REST
> EX Protocol driver instance.
> + @retval EFI_NOT_READY The configuration of this instance is not set
> yet. Configure() must be
> + executed and returns successfully prior to invoke this
> function.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExGetModeData (
> + IN EFI_REST_EX_PROTOCOL *This,
> + OUT EFI_REST_EX_CONFIG_DATA *RestExConfigData
> + )
> +{
> + return EFI_UNSUPPORTED;
> +}
> +
> +/**
> + This function is used to configure EFI REST EX child instance.
> +
> + This function is used to configure the setting of underlying protocol of REST
> EX child
> + instance. The type of configuration is according to the implementation of
> EFI REST EX
> + driver instance. For example, HTTP-aware EFI REST EX driver instance uses
> EFI HTTP protocol
> + as the undying protocol to communicate with REST service. The type of
> configuration is
> + EFI_REST_EX_CONFIG_TYPE_HTTP and RestExConfigData is the same
> format with EFI_HTTP_CONFIG_DATA.
> + Akin to HTTP configuration, REST EX child instance can be configure to use
> different HTTP
> + local access point for the data transmission. Multiple REST clients may use
> different
> + configuration of HTTP to distinguish themselves, such as to use the
> different TCP port.
> + For those non HTTP-aware REST EX driver instance, the type of
> configuration is
> + EFI_REST_EX_CONFIG_TYPE_UNSPECIFIC. RestExConfigData refers to the
> non industrial standard.
> + Instead, the format of configuration data is system/platform specific
> definition such as BMC.
> + In this case, EFI REST client and EFI REST EX driver instance have to refer to
> the specific
> + system/platform spec which is out of the UEFI scope. Besides
> GetService()function, no other
> + EFI REST EX functions can be executed by this instance until Configure()is
> executed and returns
> + successfully. All other functions must returns EFI_NOT_READY if this
> instance is not configured
> + yet. Set RestExConfigData to NULL means to put EFI REST EX child instance
> into the unconfigured
> + state.
> +
> + @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
> + @param[in] RestExConfigData Pointer to EFI_REST_EX_CONFIG_DATA.
> See Related Definitions in
> + GetModeData() protocol interface.
> +
> + @retval EFI_SUCCESS EFI_REST_EX_CONFIG_DATA is set in
> successfully.
> + @retval EFI_DEVICE_ERROR Configuration for this REST EX child
> instance is failed with the given
> + EFI_REST_EX_CONFIG_DATA.
> + @retval EFI_UNSUPPORTED This function is not supported in this REST
> EX Protocol driver instance.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExConfigure (
> + IN EFI_REST_EX_PROTOCOL *This,
> + IN EFI_REST_EX_CONFIG_DATA RestExConfigData
> + )
> +{
> + EFI_STATUS Status;
> + EFI_TPL OldTpl;
> + RESTEX_INSTANCE *Instance;
> +
> + EFI_HTTP_CONFIG_DATA *HttpConfigData;
> +
> + Status = EFI_SUCCESS;
> + HttpConfigData = NULL;
> +
> + if (This == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
> +
> + Instance = RESTEX_INSTANCE_FROM_THIS (This);
> +
> + if (RestExConfigData == NULL) {
> + //
> + // Set RestExConfigData to NULL means to put EFI REST EX child instance
> into the unconfigured state.
> + //
> + HttpIoDestroyIo (&(Instance->HttpIo));
> +
> + if (Instance->ConfigData != NULL) {
> + if (((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)-
> >HttpConfigData.AccessPoint.IPv4Node != NULL) {
> + FreePool(((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance-
> >ConfigData)->HttpConfigData.AccessPoint.IPv4Node);
> + }
> + FreePool(Instance->ConfigData);
> + Instance->ConfigData = NULL;
> + }
> +
> + Instance->State = RESTEX_STATE_UNCONFIGED;
> + } else {
> + HttpConfigData = &((EFI_REST_EX_HTTP_CONFIG_DATA
> *)RestExConfigData)->HttpConfigData;
> + Status = Instance->HttpIo.Http->Configure (Instance->HttpIo.Http,
> HttpConfigData);
> + if (EFI_ERROR (Status)) {
> + goto ON_EXIT;
> + }
> + Instance->HttpIo.Timeout = ((EFI_REST_EX_HTTP_CONFIG_DATA
> *)RestExConfigData)->SendReceiveTimeout;
> +
> + Instance->ConfigData = AllocateZeroPool (sizeof
> (EFI_REST_EX_HTTP_CONFIG_DATA));
> + if (Instance->ConfigData == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + goto ON_EXIT;
> + }
> + CopyMem (Instance->ConfigData, RestExConfigData, sizeof
> (EFI_REST_EX_HTTP_CONFIG_DATA));
> + if (HttpConfigData->LocalAddressIsIPv6 == TRUE) {
> + ((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)-
> >HttpConfigData.AccessPoint.IPv6Node = AllocateZeroPool (sizeof
> (EFI_HTTPv6_ACCESS_POINT));
> + if (((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)-
> >HttpConfigData.AccessPoint.IPv6Node == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + goto ON_EXIT;
> + }
> + CopyMem (
> + ((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)-
> >HttpConfigData.AccessPoint.IPv6Node,
> + HttpConfigData->AccessPoint.IPv6Node,
> + sizeof (EFI_HTTPv6_ACCESS_POINT)
> + );
> + } else {
> + ((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)-
> >HttpConfigData.AccessPoint.IPv4Node = AllocateZeroPool (sizeof
> (EFI_HTTPv4_ACCESS_POINT));
> + if (((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)-
> >HttpConfigData.AccessPoint.IPv4Node == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + goto ON_EXIT;
> + }
> + CopyMem (
> + ((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)-
> >HttpConfigData.AccessPoint.IPv4Node,
> + HttpConfigData->AccessPoint.IPv4Node,
> + sizeof (EFI_HTTPv4_ACCESS_POINT)
> + );
> + }
> + Instance->State = RESTEX_STATE_CONFIGED;
> + }
> +
> +ON_EXIT:
> + gBS->RestoreTPL (OldTpl);
> + return Status;
> +}
> +
> +/**
> + This function sends REST request to REST service and signal caller's event
> asynchronously when
> + the final response is received by REST EX Protocol driver instance.
> +
> + The essential design of this function is to handle asynchronous
> send/receive implicitly according
> + to REST service asynchronous request mechanism. Caller will get the
> notification once the response
> + is returned from REST service.
> +
> + @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
> + @param[in] RequestMessage This is the HTTP request message sent
> to REST service. Set RequestMessage
> + to NULL to cancel the previous asynchronous request
> associated with the
> + corresponding RestExToken. See descriptions for the
> details.
> + @param[in] RestExToken REST EX token which REST EX Protocol
> instance uses to notify REST client
> + the status of response of asynchronous REST request. See
> related definition
> + of EFI_REST_EX_TOKEN.
> + @param[in] TimeOutInMilliSeconds The pointer to the timeout in
> milliseconds which REST EX Protocol driver
> + instance refers as the duration to drop asynchronous REST
> request. NULL
> + pointer means no timeout for this REST request. REST EX
> Protocol driver
> + signals caller's event with EFI_STATUS set to EFI_TIMEOUT
> in RestExToken
> + if REST EX Protocol can't get the response from REST
> service within
> + TimeOutInMilliSeconds.
> +
> + @retval EFI_SUCCESS Asynchronous REST request is established.
> + @retval EFI_UNSUPPORTED This REST EX Protocol driver instance
> doesn't support asynchronous request.
> + @retval EFI_TIMEOUT Asynchronous REST request is not
> established and timeout is expired.
> + @retval EFI_ABORT Previous asynchronous REST request has been
> canceled.
> + @retval EFI_DEVICE_ERROR Otherwise, returns EFI_DEVICE_ERROR
> for other errors according to HTTP Status Code.
> + @retval EFI_NOT_READY The configuration of this instance is not set
> yet. Configure() must be executed
> + and returns successfully prior to invoke this function.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExAyncSendReceive (
> + IN EFI_REST_EX_PROTOCOL *This,
> + IN EFI_HTTP_MESSAGE *RequestMessage OPTIONAL,
> + IN EFI_REST_EX_TOKEN *RestExToken,
> + IN UINTN *TimeOutInMilliSeconds OPTIONAL
> + )
> +{
> + return EFI_UNSUPPORTED;
> +}
> +
> +/**
> + This function sends REST request to a REST Event service and signals caller's
> event
> + token asynchronously when the URI resource change event is received by
> REST EX
> + Protocol driver instance.
> +
> + The essential design of this function is to monitor event implicitly according
> to
> + REST service event service mechanism. Caller will get the notification if
> certain
> + resource is changed.
> +
> + @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
> + @param[in] RequestMessage This is the HTTP request message sent
> to REST service. Set RequestMessage
> + to NULL to cancel the previous event service associated
> with the corresponding
> + RestExToken. See descriptions for the details.
> + @param[in] RestExToken REST EX token which REST EX Protocol
> driver instance uses to notify REST client
> + the URI resource which monitored by REST client has
> been changed. See the related
> + definition of EFI_REST_EX_TOKEN in
> EFI_REST_EX_PROTOCOL.AsyncSendReceive().
> +
> + @retval EFI_SUCCESS Asynchronous REST request is established.
> + @retval EFI_UNSUPPORTED This REST EX Protocol driver instance
> doesn't support asynchronous request.
> + @retval EFI_ABORT Previous asynchronous REST request has been
> canceled or event subscription has been
> + delete from service.
> + @retval EFI_DEVICE_ERROR Otherwise, returns EFI_DEVICE_ERROR
> for other errors according to HTTP Status Code.
> + @retval EFI_NOT_READY The configuration of this instance is not set
> yet. Configure() must be executed
> + and returns successfully prior to invoke this function.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishRestExEventService (
> + IN EFI_REST_EX_PROTOCOL *This,
> + IN EFI_HTTP_MESSAGE *RequestMessage OPTIONAL,
> + IN EFI_REST_EX_TOKEN *RestExToken
> + )
> +{
> + return EFI_UNSUPPORTED;
> +}
> +
> --
> 2.17.1
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2020-12-10 3:08 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-12-07 6:54 [PATCH] RedfishPkg/RedfishRestExDxe: Implementation of EFI REST EX Protocol Abner Chang
2020-12-10 3:08 ` Nickle Wang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox