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
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/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."
+
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
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#68377): https://edk2.groups.io/g/devel/message/68377
Mute This Topic: https://groups.io/mt/78773779/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
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 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#68628): https://edk2.groups.io/g/devel/message/68628 Mute This Topic: https://groups.io/mt/78773779/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=-=-=-=-=-=-=-=-=-=-=-
© 2016 - 2024 Red Hat, Inc.