]> git.proxmox.com Git - mirror_edk2.git/commitdiff
RedfishPkg/RedfishRestExDxe: Implementation of EFI REST EX Protocol
authorAbner Chang <abner.chang@hpe.com>
Fri, 16 Oct 2020 08:24:04 +0000 (16:24 +0800)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Thu, 10 Dec 2020 06:04:49 +0000 (06:04 +0000)
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>
Reviewed-by: Nickle Wang <nickle.wang@hpe.com>
12 files changed:
RedfishPkg/Redfish.fdf.inc
RedfishPkg/RedfishComponents.dsc.inc
RedfishPkg/RedfishPkg.dsc
RedfishPkg/RedfishRestExDxe/ComponentName.c [new file with mode: 0644]
RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.c [new file with mode: 0644]
RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.h [new file with mode: 0644]
RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf [new file with mode: 0644]
RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.uni [new file with mode: 0644]
RedfishPkg/RedfishRestExDxe/RedfishRestExDxeExtra.uni [new file with mode: 0644]
RedfishPkg/RedfishRestExDxe/RedfishRestExImpl.c [new file with mode: 0644]
RedfishPkg/RedfishRestExDxe/RedfishRestExInternal.h [new file with mode: 0644]
RedfishPkg/RedfishRestExDxe/RedfishRestExProtocol.c [new file with mode: 0644]

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