From nobody Sat May 4 07:03:42 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+68377+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+68377+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=hpe.com ARC-Seal: i=1; a=rsa-sha256; t=1607326849; cv=none; d=zohomail.com; s=zohoarc; b=WI/EPWag09fRL9OvU9vkoy/BROUKyFhmcXyOC3YPxg1RPNqR5LFRBoRLRj2+qa9GsdSyrqtQBHOTHJUwgN10KVrh4B6lpznSD+oQLxj93HgygyOqnkO7sutZclP6x+x/7cwjjNye0tXQ6m8d/m6sZAcGK+nLrq5K5o7gBUJ0yww= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1607326849; h=Cc:Date:From:List-Id:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Sender:Subject:To; bh=iu35+DIe7DAeCHFIqWJ/6BuhFqf9HELF9SmtNxeuu5I=; b=jrTQHat6w4c0UdZzluF4mcHr3qnvIA/yIVsNA/ruq4Jm2Jqz6EcF2LhKaf94tzB+Zf5/VCIQN9OjBpRn/Ofijt3bZ/eIyZCjMrGVt3mV5eOT2Z+mirnISJje5fBOe8OaelLSeLS/QX1HQNqFCER3VZFDfrunTqU/lKJBCk75tyQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+68377+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) header.from= Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1607326849650202.29587698653472; Sun, 6 Dec 2020 23:40:49 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id g5RRYY1788612xfNeaLHYIf4; Sun, 06 Dec 2020 23:40:49 -0800 X-Received: from mx0b-002e3701.pphosted.com (mx0b-002e3701.pphosted.com [148.163.143.35]) by mx.groups.io with SMTP id smtpd.web12.3220.1607326845170426003 for ; Sun, 06 Dec 2020 23:40:45 -0800 X-Received: from pps.filterd (m0150244.ppops.net [127.0.0.1]) by mx0b-002e3701.pphosted.com (8.16.0.43/8.16.0.43) with SMTP id 0B77d94s008632; Mon, 7 Dec 2020 07:40:44 GMT X-Received: from g9t5008.houston.hpe.com (g9t5008.houston.hpe.com [15.241.48.72]) by mx0b-002e3701.pphosted.com with ESMTP id 3587jfrn7s-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 07 Dec 2020 07:40:43 +0000 X-Received: from g9t2301.houston.hpecorp.net (g9t2301.houston.hpecorp.net [16.220.97.129]) by g9t5008.houston.hpe.com (Postfix) with ESMTP id BCF434F; Mon, 7 Dec 2020 07:40:42 +0000 (UTC) X-Received: from abner-virtual-machine.asiapacific.hpqcorp.net (abner-virtual-machine.asiapacific.hpqcorp.net [15.119.210.153]) by g9t2301.houston.hpecorp.net (Postfix) with ESMTP id B58D44A; Mon, 7 Dec 2020 07:40:40 +0000 (UTC) From: "Abner Chang" To: devel@edk2.groups.io Cc: Jiaxin Wu , Siyuan Fu , Fan Wang , Jiewen Yao , Nickle Wang , Peter O'Hanley Subject: [edk2-devel] [PATCH] RedfishPkg/RedfishRestExDxe: Implementation of EFI REST EX Protocol Date: Mon, 7 Dec 2020 14:54:04 +0800 Message-Id: <20201207065404.31257-1-abner.chang@hpe.com> X-Proofpoint-UnRewURL: 0 URL was un-rewritten MIME-Version: 1.0 X-HPE-SCL: -1 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,abner.chang@hpe.com X-Gm-Message-State: XIA6pxfe8ju35tBCayZ0okl1x1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1607326849; bh=XYMF7viGE5iHhK6LIi6vo2RpVr5nhGVVJ2iXnJERjgM=; h=Cc:Date:From:Reply-To:Subject:To; b=TJ/cl6KWcAzkD1kYOFoe19r7Wt4T4einTJbUXHL1e5pxPxRNvgeD6CXwYljPoM2hIwn Z9sdrsyuoeofTjifQpRld6FMj7FBaXoGrRH9xYzPAmPqHf/NfJiFVZT1VJ4O/yhrS03AI +JYoT+v35P9RtO7tVb3hKS81P38de9RIU9o= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" BZ#: 2908 https://bugzilla.tianocore.org/show_bug.cgi?id=3D2908 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 Signed-off-by: Siyuan Fu Signed-off-by: Fan Wang Signed-off-by: Ting Ye Signed-off-by: Abner Chang Cc: Jiaxin Wu Cc: Siyuan Fu Cc: Fan Wang Cc: Jiewen Yao Cc: Nickle Wang Cc: Peter O'Hanley Reviewed-by: Nickle Wang --- RedfishPkg/Redfish.fdf.inc | 1 + RedfishPkg/RedfishComponents.dsc.inc | 1 + RedfishPkg/RedfishPkg.dsc | 4 + RedfishPkg/RedfishRestExDxe/ComponentName.c | 222 +++++ .../RedfishRestExDxe/RedfishRestExDriver.c | 831 ++++++++++++++++++ .../RedfishRestExDxe/RedfishRestExDriver.h | 650 ++++++++++++++ .../RedfishRestExDxe/RedfishRestExDxe.inf | 63 ++ .../RedfishRestExDxe/RedfishRestExDxe.uni | 16 + .../RedfishRestExDxeExtra.uni | 15 + .../RedfishRestExDxe/RedfishRestExImpl.c | 157 ++++ .../RedfishRestExDxe/RedfishRestExInternal.h | 611 +++++++++++++ .../RedfishRestExDxe/RedfishRestExProtocol.c | 735 ++++++++++++++++ 12 files changed, 3306 insertions(+) create mode 100644 RedfishPkg/RedfishRestExDxe/ComponentName.c create mode 100644 RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.c create mode 100644 RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.h create mode 100644 RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf create mode 100644 RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.uni create mode 100644 RedfishPkg/RedfishRestExDxe/RedfishRestExDxeExtra.uni create mode 100644 RedfishPkg/RedfishRestExDxe/RedfishRestExImpl.c create mode 100644 RedfishPkg/RedfishRestExDxe/RedfishRestExInternal.h create mode 100644 RedfishPkg/RedfishRestExDxe/RedfishRestExProtocol.c diff --git a/RedfishPkg/Redfish.fdf.inc b/RedfishPkg/Redfish.fdf.inc index 19de479a80..429156aa78 100644 --- a/RedfishPkg/Redfish.fdf.inc +++ b/RedfishPkg/Redfish.fdf.inc @@ -13,4 +13,5 @@ !if $(REDFISH_ENABLE) =3D=3D TRUE INF RedfishPkg/RestJsonStructureDxe/RestJsonStructureDxe.inf INF RedfishPkg/RedfishHostInterfaceDxe/RedfishHostInterfaceDxe.inf + INF RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf !endif diff --git a/RedfishPkg/RedfishComponents.dsc.inc b/RedfishPkg/RedfishCompo= nents.dsc.inc index ac1b57ed8f..3b9429db09 100644 --- a/RedfishPkg/RedfishComponents.dsc.inc +++ b/RedfishPkg/RedfishComponents.dsc.inc @@ -15,4 +15,5 @@ !if $(REDFISH_ENABLE) =3D=3D TRUE RedfishPkg/RestJsonStructureDxe/RestJsonStructureDxe.inf RedfishPkg/RedfishHostInterfaceDxe/RedfishHostInterfaceDxe.inf + RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf !endif diff --git a/RedfishPkg/RedfishPkg.dsc b/RedfishPkg/RedfishPkg.dsc index 94e7127bc6..c05e81af7b 100644 --- a/RedfishPkg/RedfishPkg.dsc +++ b/RedfishPkg/RedfishPkg.dsc @@ -32,6 +32,10 @@ DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseD= ebugPrintErrorLevelLib.inf PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf RedfishPlatformHostInterfaceLib|RedfishPkg/Library/PlatformHostInterface= LibNull/PlatformHostInterfaceLibNull.inf + HttpLib|NetworkPkg/Library/DxeHttpLib/DxeHttpLib.inf + HttpIoLib|NetworkPkg/Library/DxeHttpIoLib/DxeHttpIoLib.inf + NetLib|NetworkPkg/Library/DxeNetLib/DxeNetLib.inf + DpcLib|NetworkPkg/Library/DxeDpcLib/DxeDpcLib.inf =20 [LibraryClasses.ARM, LibraryClasses.AARCH64] # diff --git a/RedfishPkg/RedfishRestExDxe/ComponentName.c b/RedfishPkg/Redfi= shRestExDxe/ComponentName.c new file mode 100644 index 0000000000..3674178412 --- /dev/null +++ b/RedfishPkg/RedfishRestExDxe/ComponentName.c @@ -0,0 +1,222 @@ +/** @file + Implementation of EFI_COMPONENT_NAME_PROTOCOL and EFI_COMPONENT_NAME2_PR= OTOCOL + protocol. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include + +#include + +#include +#include + +// +// EFI Component Name Functions +// +/** + Retrieves a Unicode string that is the user-readable name of the EFI Dri= ver. + + @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL ins= tance. + @param[in] Language A pointer to a three-character ISO 639-2 languag= e identifier. + This is the language of the driver name that tha= t the caller + is requesting, and it must match one of the lang= uages specified + in SupportedLanguages. The number of languages = supported by a + driver is up to the driver writer. + @param[out] DriverName A pointer to the Unicode string to return. This= Unicode string + is the name of the driver specified by This in t= he language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by = This + and the language specified by Language was retu= rned + in DriverName. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER DriverName is NULL. + @retval EFI_UNSUPPORTED The driver specified by This does not supp= ort the + language specified by Language. + +**/ +EFI_STATUS +EFIAPI +RedfishRestExComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +/** + Retrieves a Unicode string that is the user readable name of the control= ler + that is being managed by an EFI Driver. + + @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOC= OL instance. + @param[in] ControllerHandle The handle of a controller that the driver= specified by + This is managing. This handle specifies t= he controller + whose name is to be returned. + @param[in] ChildHandle The handle of the child controller to retr= ieve the name + of. This is an optional parameter that may= be NULL. It + will be NULL for device drivers. It will = also be NULL + for a bus drivers that wish to retrieve th= e name of the + bus controller. It will not be NULL for a= bus driver + that wishes to retrieve the name of a chil= d controller. + @param[in] Language A pointer to a three character ISO 639-2 l= anguage + identifier. This is the language of the co= ntroller name + that the caller is requesting, and it must= match one + of the languages specified in SupportedLan= guages. The + number of languages supported by a driver = is up to the + driver writer. + @param[out] ControllerName A pointer to the Unicode string to return.= This Unicode + string is the name of the controller speci= fied by + ControllerHandle and ChildHandle in the la= nguage specified + by Language, from the point of view of the= driver specified + by This. + + @retval EFI_SUCCESS The Unicode string for the user-readable n= ame in the + language specified by Language for the dri= ver + specified by This was returned in DriverNa= me. + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a va= lid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + @retval EFI_UNSUPPORTED The driver specified by This is not curren= tly managing + the controller specified by ControllerHand= le and + ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not supp= ort the + language specified by Language. + +**/ +EFI_STATUS +EFIAPI +RedfishRestExComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +/// +/// Component Name Protocol instance +/// +GLOBAL_REMOVE_IF_UNREFERENCED +EFI_COMPONENT_NAME_PROTOCOL gRedfishRestExComponentName =3D { + RedfishRestExComponentNameGetDriverName, + RedfishRestExComponentNameGetControllerName, + "eng" +}; + +/// +/// Component Name 2 Protocol instance +/// +GLOBAL_REMOVE_IF_UNREFERENCED +EFI_COMPONENT_NAME2_PROTOCOL gRedfishRestExComponentName2 =3D { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) RedfishRestExComponentNameGetD= riverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) RedfishRestExComponentNameGetC= ontrollerName, + "en" +}; + +/// +/// Table of driver names +/// +GLOBAL_REMOVE_IF_UNREFERENCED +EFI_UNICODE_STRING_TABLE mRedfishRestExDriverNameTable[] =3D { + { "eng;en", (CHAR16 *)L"Redfish RestEx Network Service Driver" }, + { NULL, NULL } +}; + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE *gRedfishRestExCont= rollerNameTable =3D NULL; + +/** + Retrieves a Unicode string that is the user-readable name of the EFI Dri= ver. + + @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL inst= ance. + @param[in] Language A pointer to a three-character ISO 639-2 language= identifier. + This is the language of the driver name that that= the caller + is requesting, and it must match one of the langu= ages specified + in SupportedLanguages. The number of languages s= upported by a + driver is up to the driver writer. + @param[out] DriverName A pointer to the Unicode string to return. Thi= s Unicode string + is the name of the driver specified by This in = the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specifie= d by This + and the language specified by Language was= returned + in DriverName. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER DriverName is NULL. + @retval EFI_UNSUPPORTED The driver specified by This does not supp= ort the + language specified by Language. + +**/ +EFI_STATUS +EFIAPI +RedfishRestExComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mRedfishRestExDriverNameTable, + DriverName, + (BOOLEAN)(This =3D=3D &gRedfishRestExComponentName) + ); +} + +/** + Retrieves a Unicode string that is the user readable name of the control= ler + that is being managed by an EFI Driver. + + @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTO= COL instance. + @param[in] ControllerHandle The handle of a controller that the drive= r specified by + This is managing. This handle specifies = the controller + whose name is to be returned. + @param[in] ChildHandle The handle of the child controller to ret= rieve the name + of. This is an optional parameter that m= ay be NULL. It + will be NULL for device drivers. It will= also be NULL + for a bus drivers that wish to retrieve t= he name of the + bus controller. It will not be NULL for = a bus driver + that wishes to retrieve the name of a chi= ld controller. + @param[in] Language A pointer to a three character ISO 639-2 langua= ge + identifier. This is the language of the contro= ller name + that the caller is requesting, and it must matc= h one + of the languages specified in SupportedLanguage= s. The + number of languages supported by a driver is up= to the + driver writer. + @param[out] ControllerName A pointer to the Unicode string to return= . This Unicode + string is the name of the controller spe= cified by + ControllerHandle and ChildHandle in the = language specified + by Language, from the point of view of t= he driver specified + by This. + + @retval EFI_SUCCESS The Unicode string for the user-readable n= ame in the + language specified by Language for the dri= ver + specified by This was returned in DriverNa= me. + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a va= lid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + @retval EFI_UNSUPPORTED The driver specified by This is not curren= tly managing + the controller specified by ControllerHand= le and + ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not supp= ort the + language specified by Language. + +**/ +EFI_STATUS +EFIAPI +RedfishRestExComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + return EFI_UNSUPPORTED; +} diff --git a/RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.c b/RedfishPkg= /RedfishRestExDxe/RedfishRestExDriver.c new file mode 100644 index 0000000000..87327a8549 --- /dev/null +++ b/RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.c @@ -0,0 +1,831 @@ +/** @file + The driver binding and service binding protocol for Redfish RestExDxe dr= iver. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include "RedfishRestExDriver.h" + +EFI_DRIVER_BINDING_PROTOCOL gRedfishRestExDriverBinding =3D { + RedfishRestExDriverBindingSupported, + RedfishRestExDriverBindingStart, + RedfishRestExDriverBindingStop, + REDFISH_RESTEX_DRIVER_VERSION, + NULL, + NULL +}; + +EFI_SERVICE_BINDING_PROTOCOL mRedfishRestExServiceBinding =3D { + RedfishRestExServiceBindingCreateChild, + RedfishRestExServiceBindingDestroyChild +}; + +/** + Callback function which provided by user to remove one node in NetDestro= yLinkList process. + + @param[in] Entry The entry to be removed. + @param[in] Context Pointer to the callback context correspond= s to the Context in NetDestroyLinkList. + + @retval EFI_SUCCESS The entry has been removed successfully. + @retval Others Fail to remove the entry. + +**/ +EFI_STATUS +EFIAPI +RestExDestroyChildEntryInHandleBuffer ( + IN LIST_ENTRY *Entry, + IN VOID *Context + ) +{ + RESTEX_INSTANCE *Instance; + EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding; + UINTN NumberOfChildren; + EFI_HANDLE *ChildHandleBuffer; + + if (Entry =3D=3D NULL || Context =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + Instance =3D NET_LIST_USER_STRUCT_S (Entry, RESTEX_INSTANCE, Link, RESTE= X_INSTANCE_SIGNATURE); + ServiceBinding =3D ((RESTEX_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Co= ntext)->ServiceBinding; + NumberOfChildren =3D ((RESTEX_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Co= ntext)->NumberOfChildren; + ChildHandleBuffer =3D ((RESTEX_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Co= ntext)->ChildHandleBuffer; + + if (!NetIsInHandleBuffer (Instance->ChildHandle, NumberOfChildren, Child= HandleBuffer)) { + return EFI_SUCCESS; + } + + return ServiceBinding->DestroyChild (ServiceBinding, Instance->ChildHand= le); +} + +/** + Destroy the RestEx instance and recycle the resources. + + @param[in] Instance The pointer to the RestEx instance. + +**/ +VOID +RestExDestroyInstance ( + IN RESTEX_INSTANCE *Instance + ) +{ + HttpIoDestroyIo (&(Instance->HttpIo)); + + FreePool (Instance); +} + +/** + Create the RestEx instance and initialize it. + + @param[in] Service The pointer to the RestEx service. + @param[out] Instance The pointer to the RestEx instance. + + @retval EFI_OUT_OF_RESOURCES Failed to allocate resources. + @retval EFI_SUCCESS The RestEx instance is created. + +**/ +EFI_STATUS +RestExCreateInstance ( + IN RESTEX_SERVICE *Service, + OUT RESTEX_INSTANCE **Instance + ) +{ + RESTEX_INSTANCE *RestExIns; + EFI_STATUS Status; + + *Instance =3D NULL; + Status =3D EFI_SUCCESS; + + RestExIns =3D AllocateZeroPool (sizeof (RESTEX_INSTANCE)); + if (RestExIns =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + RestExIns->Signature =3D RESTEX_INSTANCE_SIGNATURE; + InitializeListHead (&RestExIns->Link); + RestExIns->InDestroy =3D FALSE; + RestExIns->Service =3D Service; + + CopyMem (&RestExIns->RestEx, &mRedfishRestExProtocol, sizeof (RestExIns-= >RestEx)); + + // + // Create a HTTP_IO to access the HTTP service. + // + Status =3D HttpIoCreateIo ( + RestExIns->Service->ImageHandle, + RestExIns->Service->ControllerHandle, + IP_VERSION_4, + NULL, + NULL, + NULL, + &(RestExIns->HttpIo) + ); + if (EFI_ERROR (Status)) { + FreePool (RestExIns); + return Status; + } + + *Instance =3D RestExIns; + + return EFI_SUCCESS; +} + +/** + Release all the resource used the RestEx service binding instance. + + @param[in] RestExSb The RestEx service binding instance. + +**/ +VOID +RestExDestroyService ( + IN RESTEX_SERVICE *RestExSb + ) +{ + if (RestExSb->HttpChildHandle !=3D NULL) { + gBS->CloseProtocol ( + RestExSb->HttpChildHandle, + &gEfiHttpProtocolGuid, + RestExSb->ImageHandle, + RestExSb->ControllerHandle + ); + + NetLibDestroyServiceChild ( + RestExSb->ControllerHandle, + RestExSb->ImageHandle, + &gEfiHttpServiceBindingProtocolGuid, + RestExSb->HttpChildHandle + ); + + RestExSb->HttpChildHandle =3D NULL; + } + + gBS->UninstallProtocolInterface ( + RestExSb->ControllerHandle, + &gEfiCallerIdGuid, + &RestExSb->Id + ); + + FreePool (RestExSb); +} + +/** + Check the NIC controller handle represents an in-band or out-of-band Red= fish host + interface device. If not in-band, treat it as out-of-band interface devi= ce. + + @param[in] Controller The NIC controller handle needs to be chec= ked. + + @return EFI_REST_EX_SERVICE_ACCESS_MODE of the device. + +**/ +EFI_REST_EX_SERVICE_ACCESS_MODE +RestExServiceAccessMode ( + IN EFI_HANDLE Controller + ) +{ + // + // This is EFI REST EX driver instance to connect + // to Redfish service using HTTP in out of band. + // + if (FixedPcdGetBool (PcdRedfishRestExServiceAccessModeInBand)) { + return EfiRestExServiceInBandAccess; + } else { + return EfiRestExServiceOutOfBandAccess; + } +} + +/** + Create then initialize a RestEx service binding instance. + + @param[in] Controller The controller to install the RestEx servi= ce + binding on. + @param[in] Image The driver binding image of the RestEx dri= ver. + @param[out] Service The variable to receive the created service + binding instance. + + @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the = instance. + @retval EFI_SUCCESS The service instance is created for the co= ntroller. + +**/ +EFI_STATUS +RestExCreateService ( + IN EFI_HANDLE Controller, + IN EFI_HANDLE Image, + OUT RESTEX_SERVICE **Service + ) +{ + EFI_STATUS Status; + RESTEX_SERVICE *RestExSb; + + Status =3D EFI_SUCCESS; + RestExSb =3D NULL; + + *Service =3D NULL; + + RestExSb =3D AllocateZeroPool (sizeof (RESTEX_SERVICE)); + if (RestExSb =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + RestExSb->Signature =3D RESTEX_SERVICE_SIGNATURE; + + RestExSb->ServiceBinding =3D mRedfishRestExServiceBinding; + + RestExSb->RestExChildrenNum =3D 0; + InitializeListHead (&RestExSb->RestExChildrenList); + + RestExSb->ControllerHandle =3D Controller; + RestExSb->ImageHandle =3D Image; + + RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.EfiRestExServiceInfo= Header.Length =3D sizeof (EFI_REST_EX_SERVICE_INFO); + RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.EfiRestExServiceInfo= Header.RestServiceInfoVer.Major =3D 1; + RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.EfiRestExServiceInfo= Header.RestServiceInfoVer.Minor =3D 0; + RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.RestServiceType =3D = EfiRestExServiceRedfish; + RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.RestServiceAccessMod= e =3D RestExServiceAccessMode (Controller); + RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.RestExConfigType =3D= EfiRestExConfigHttp; + RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.RestExConfigDataLeng= th =3D sizeof (EFI_REST_EX_HTTP_CONFIG_DATA); + + Status =3D gBS->InstallProtocolInterface ( + &Controller, + &gEfiCallerIdGuid, + EFI_NATIVE_INTERFACE, + &RestExSb->Id + ); + if (EFI_ERROR (Status)) { + FreePool (RestExSb); + RestExSb =3D NULL; + } + + *Service =3D RestExSb; + return Status; +} + +/** + This is the declaration of an EFI image entry point. This entry point is + the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers includ= ing + both device drivers and bus drivers. + + @param[in] ImageHandle The firmware allocated handle for the UEFI = image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The operation completed successfully. + @retval Others An unexpected error occurred. +**/ +EFI_STATUS +EFIAPI +RedfishRestExDriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status =3D EFI_SUCCESS; + + // + // Install the RestEx Driver Binding Protocol. + // + Status =3D EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gRedfishRestExDriverBinding, + ImageHandle, + &gRedfishRestExComponentName, + &gRedfishRestExComponentName2 + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return Status; +} + +/** + Tests to see if this driver supports a given controller. If a child devi= ce is provided, + it further tests to see if this driver supports creating a handle for th= e specified child device. + + This function checks to see if the driver specified by This supports the= device specified by + ControllerHandle. Drivers will typically use the device path attached to + ControllerHandle and/or the services from the bus I/O abstraction attach= ed to + ControllerHandle to determine if the driver supports ControllerHandle. T= his function + may be called many times during platform initialization. In order to red= uce boot times, the tests + performed by this function must be very small, and take as little time a= s possible to execute. This + function must not change the state of any hardware devices, and this fun= ction must be aware that the + device specified by ControllerHandle may already be managed by the same = driver or a + different driver. This function must match its calls to AllocatePages() = with FreePages(), + AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol(). + Because ControllerHandle may have been previously started by the same dr= iver, if a protocol is + already in the opened state, then it must not be closed with CloseProtoc= ol(). This is required + to guarantee the state of ControllerHandle is not modified by this funct= ion. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PRO= TOCOL instance. + @param[in] ControllerHandle The handle of the controller to test. T= his handle + must support a protocol interface that = supplies + an I/O abstraction to the driver. + @param[in] RemainingDevicePath A pointer to the remaining portion of a= device path. This + parameter is ignored by device drivers,= and is optional for bus + drivers. For bus drivers, if this param= eter is not NULL, then + the bus driver must determine if the bu= s controller specified + by ControllerHandle and the child contr= oller specified + by RemainingDevicePath are both support= ed by this + bus driver. + + @retval EFI_SUCCESS The device specified by ControllerHandl= e and + RemainingDevicePath is supported by the= driver specified by This. + @retval EFI_ALREADY_STARTED The device specified by ControllerHandl= e and + RemainingDevicePath is already being ma= naged by the driver + specified by This. + @retval EFI_ACCESS_DENIED The device specified by ControllerHandl= e and + RemainingDevicePath is already being ma= naged by a different + driver or an application that requires = exclusive access. + Currently not implemented. + @retval EFI_UNSUPPORTED The device specified by ControllerHandl= e and + RemainingDevicePath is not supported by= the driver specified by This. +**/ +EFI_STATUS +EFIAPI +RedfishRestExDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +{ + + // + // Test for the HttpServiceBinding Protocol. + // + return gBS->OpenProtocol ( + ControllerHandle, + &gEfiHttpServiceBindingProtocolGuid, + NULL, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + +} + +/** + Starts a device controller or a bus controller. + + The Start() function is designed to be invoked from the EFI boot service= ConnectController(). + As a result, much of the error checking on the parameters to Start() has= been moved into this + common boot service. It is legal to call Start() from other locations, + but the following calling restrictions must be followed, or the system b= ehavior will not be deterministic. + 1. ControllerHandle must be a valid EFI_HANDLE. + 2. If RemainingDevicePath is not NULL, then it must be a pointer to a na= turally aligned + EFI_DEVICE_PATH_PROTOCOL. + 3. Prior to calling Start(), the Supported() function for the driver spe= cified by This must + have been called with the same calling parameters, and Supported() mu= st have returned EFI_SUCCESS. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PRO= TOCOL instance. + @param[in] ControllerHandle The handle of the controller to start. = This handle + must support a protocol interface that = supplies + an I/O abstraction to the driver. + @param[in] RemainingDevicePath A pointer to the remaining portion of a= device path. This + parameter is ignored by device drivers,= and is optional for bus + drivers. For a bus driver, if this para= meter is NULL, then handles + for all the children of Controller are = created by this driver. + If this parameter is not NULL and the f= irst Device Path Node is + not the End of Device Path Node, then o= nly the handle for the + child device specified by the first Dev= ice Path Node of + RemainingDevicePath is created by this = driver. + If the first Device Path Node of Remain= ingDevicePath is + the End of Device Path Node, no child h= andle is created by this + driver. + + @retval EFI_SUCCESS The device was started. + @retval EFI_DEVICE_ERROR The device could not be started due to = a device error.Currently not implemented. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due = to a lack of resources. + @retval Others The driver failded to start the device. + +**/ +EFI_STATUS +EFIAPI +RedfishRestExDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +{ + RESTEX_SERVICE *RestExSb; + EFI_STATUS Status; + UINT32 *Id; + VOID *Interface; + + Status =3D gBS->OpenProtocol ( + ControllerHandle, + &gEfiCallerIdGuid, + (VOID **) &Id, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + return EFI_ALREADY_STARTED; + } + + Status =3D RestExCreateService (ControllerHandle, This->DriverBindingHan= dle, &RestExSb); + if (EFI_ERROR (Status)) { + return Status; + } + + ASSERT (RestExSb !=3D NULL); + + // + // Create a Http child instance, but do not configure it. + // This will establish the parent-child relationship. + // + Status =3D NetLibCreateServiceChild ( + ControllerHandle, + This->DriverBindingHandle, + &gEfiHttpServiceBindingProtocolGuid, + &RestExSb->HttpChildHandle + ); + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + + Status =3D gBS->OpenProtocol ( + RestExSb->HttpChildHandle, + &gEfiHttpProtocolGuid, + &Interface, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + + // + // Install the RestEx ServiceBinding Protocol onto ControllerHandle. + // + Status =3D gBS->InstallMultipleProtocolInterfaces ( + &ControllerHandle, + &gEfiRestExServiceBindingProtocolGuid, + &RestExSb->ServiceBinding, + NULL + ); + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + + return EFI_SUCCESS; + +ON_ERROR: + RestExDestroyService (RestExSb); + + return Status; +} + +/** + Stops a device controller or a bus controller. + + The Stop() function is designed to be invoked from the EFI boot service = DisconnectController(). + As a result, much of the error checking on the parameters to Stop() has = been moved + into this common boot service. It is legal to call Stop() from other loc= ations, + but the following calling restrictions must be followed, or the system b= ehavior will not be deterministic. + 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previo= us call to this + same driver's Start() function. + 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a= valid + EFI_HANDLE. In addition, all of these handles must have been created = in this driver's + Start() function, and the Start() function must have called OpenProto= col() on + ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONT= ROLLER. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOC= OL instance. + @param[in] ControllerHandle A handle to the device being stopped. The = handle must + support a bus specific I/O protocol for th= e driver + to use to stop the device. + @param[in] NumberOfChildren The number of child device handles in Chil= dHandleBuffer. + @param[in] ChildHandleBuffer An array of child handles to be freed. May= be NULL + if NumberOfChildren is 0. + + @retval EFI_SUCCESS The device was stopped. + @retval EFI_DEVICE_ERROR The device could not be stopped due to a d= evice error. + +**/ +EFI_STATUS +EFIAPI +RedfishRestExDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer OPTIONAL + ) +{ + EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding; + RESTEX_SERVICE *RestExSb; + EFI_HANDLE NicHandle; + EFI_STATUS Status; + LIST_ENTRY *List; + RESTEX_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context; + + // + // RestEx driver opens HTTP child, So, Controller is a HTTP + // child handle. Locate the Nic handle first. Then get the + // RestEx private data back. + // + NicHandle =3D NetLibGetNicHandle (ControllerHandle, &gEfiHttpProtocolGui= d); + if (NicHandle =3D=3D NULL) { + return EFI_SUCCESS; + } + + Status =3D gBS->OpenProtocol ( + NicHandle, + &gEfiRestExServiceBindingProtocolGuid, + (VOID **) &ServiceBinding, + This->DriverBindingHandle, + NicHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + RestExSb =3D RESTEX_SERVICE_FROM_THIS (ServiceBinding); + + if (!IsListEmpty (&RestExSb->RestExChildrenList)) { + // + // Destroy the RestEx child instance in ChildHandleBuffer. + // + List =3D &RestExSb->RestExChildrenList; + Context.ServiceBinding =3D ServiceBinding; + Context.NumberOfChildren =3D NumberOfChildren; + Context.ChildHandleBuffer =3D ChildHandleBuffer; + Status =3D NetDestroyLinkList ( + List, + RestExDestroyChildEntryInHandleBuffer, + &Context, + NULL + ); + } + + if (NumberOfChildren =3D=3D 0 && IsListEmpty (&RestExSb->RestExChildrenL= ist)) { + gBS->UninstallProtocolInterface ( + NicHandle, + &gEfiRestExServiceBindingProtocolGuid, + ServiceBinding + ); + + RestExDestroyService (RestExSb); + + if (gRedfishRestExControllerNameTable !=3D NULL) { + FreeUnicodeStringTable (gRedfishRestExControllerNameTable); + gRedfishRestExControllerNameTable =3D NULL; + } + + Status =3D EFI_SUCCESS; + } + + return Status; +} + +/** + Creates a child handle and installs a protocol. + + The CreateChild() function installs a protocol on ChildHandle. + If ChildHandle is a pointer to NULL, then a new handle is created and re= turned in ChildHandle. + If ChildHandle is not a pointer to NULL, then the protocol installs on t= he existing ChildHandle. + + @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL insta= nce. + @param[in] ChildHandle Pointer to the handle of the child to create. If = it is NULL, + then a new handle is created. If it is a pointer = to an existing UEFI handle, + then the protocol is added to the existing UEFI h= andle. + + @retval EFI_SUCCES The protocol was added to ChildHandle. + @retval EFI_INVALID_PARAMETER ChildHandle is NULL. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available t= o create + the child + @retval other The child handle was not created + +**/ +EFI_STATUS +EFIAPI +RedfishRestExServiceBindingCreateChild ( + IN EFI_SERVICE_BINDING_PROTOCOL *This, + IN EFI_HANDLE *ChildHandle + ) +{ + RESTEX_SERVICE *RestExSb; + RESTEX_INSTANCE *Instance; + EFI_STATUS Status; + EFI_TPL OldTpl; + VOID *Http; + + if ((This =3D=3D NULL) || (ChildHandle =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + } + + RestExSb =3D RESTEX_SERVICE_FROM_THIS (This); + + Status =3D RestExCreateInstance (RestExSb, &Instance); + if (EFI_ERROR (Status)) { + return Status; + } + ASSERT (Instance !=3D NULL); + + // + // Install the RestEx protocol onto ChildHandle + // + Status =3D gBS->InstallMultipleProtocolInterfaces ( + ChildHandle, + &gEfiRestExProtocolGuid, + &Instance->RestEx, + NULL + ); + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + + Instance->ChildHandle =3D *ChildHandle; + + // + // Open the Http protocol BY_CHILD. + // + Status =3D gBS->OpenProtocol ( + RestExSb->HttpChildHandle, + &gEfiHttpProtocolGuid, + (VOID **) &Http, + gRedfishRestExDriverBinding.DriverBindingHandle, + Instance->ChildHandle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + if (EFI_ERROR (Status)) { + gBS->UninstallMultipleProtocolInterfaces ( + Instance->ChildHandle, + &gEfiRestExProtocolGuid, + &Instance->RestEx, + NULL + ); + + goto ON_ERROR; + } + + // + // Open the Http protocol by child. + // + Status =3D gBS->OpenProtocol ( + Instance->HttpIo.Handle, + &gEfiHttpProtocolGuid, + (VOID **) &Http, + gRedfishRestExDriverBinding.DriverBindingHandle, + Instance->ChildHandle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + if (EFI_ERROR (Status)) { + // + // Close the Http protocol. + // + gBS->CloseProtocol ( + RestExSb->HttpChildHandle, + &gEfiHttpProtocolGuid, + gRedfishRestExDriverBinding.DriverBindingHandle, + ChildHandle + ); + + gBS->UninstallMultipleProtocolInterfaces ( + Instance->ChildHandle, + &gEfiRestExProtocolGuid, + &Instance->RestEx, + NULL + ); + + goto ON_ERROR; + } + + // + // Add it to the parent's child list. + // + OldTpl =3D gBS->RaiseTPL (TPL_CALLBACK); + + InsertTailList (&RestExSb->RestExChildrenList, &Instance->Link); + RestExSb->RestExChildrenNum++; + + gBS->RestoreTPL (OldTpl); + + return EFI_SUCCESS; + +ON_ERROR: + + RestExDestroyInstance (Instance); + return Status; +} + +/** + Destroys a child handle with a protocol installed on it. + + The DestroyChild() function does the opposite of CreateChild(). It remov= es a protocol + that was installed by CreateChild() from ChildHandle. If the removed pro= tocol is the + last protocol on ChildHandle, then ChildHandle is destroyed. + + @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL insta= nce. + @param[in] ChildHandle Handle of the child to destroy + + @retval EFI_SUCCES The protocol was removed from ChildHandle. + @retval EFI_UNSUPPORTED ChildHandle does not support the protocol = that is being removed. + @retval EFI_INVALID_PARAMETER Child handle is NULL. + @retval EFI_ACCESS_DENIED The protocol could not be removed from the= ChildHandle + because its services are being used. + @retval other The child handle was not destroyed + +**/ +EFI_STATUS +EFIAPI +RedfishRestExServiceBindingDestroyChild ( + IN EFI_SERVICE_BINDING_PROTOCOL *This, + IN EFI_HANDLE ChildHandle + ) +{ + RESTEX_SERVICE *RestExSb; + RESTEX_INSTANCE *Instance; + + EFI_REST_EX_PROTOCOL *RestEx; + EFI_STATUS Status; + EFI_TPL OldTpl; + + if ((This =3D=3D NULL) || (ChildHandle =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Retrieve the private context data structures + // + Status =3D gBS->OpenProtocol ( + ChildHandle, + &gEfiRestExProtocolGuid, + (VOID **) &RestEx, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Instance =3D RESTEX_INSTANCE_FROM_THIS (RestEx); + RestExSb =3D RESTEX_SERVICE_FROM_THIS (This); + + if (Instance->Service !=3D RestExSb) { + return EFI_INVALID_PARAMETER; + } + + if (Instance->InDestroy) { + return EFI_SUCCESS; + } + + OldTpl =3D gBS->RaiseTPL (TPL_CALLBACK); + + Instance->InDestroy =3D TRUE; + + // + // Close the Http protocol. + // + gBS->CloseProtocol ( + RestExSb->HttpChildHandle, + &gEfiHttpProtocolGuid, + gRedfishRestExDriverBinding.DriverBindingHandle, + ChildHandle + ); + + gBS->CloseProtocol ( + Instance->HttpIo.Handle, + &gEfiHttpProtocolGuid, + gRedfishRestExDriverBinding.DriverBindingHandle, + ChildHandle + ); + + + gBS->RestoreTPL (OldTpl); + + // + // Uninstall the RestEx protocol first to enable a top down destruction. + // + Status =3D gBS->UninstallProtocolInterface ( + ChildHandle, + &gEfiRestExProtocolGuid, + RestEx + ); + + OldTpl =3D gBS->RaiseTPL (TPL_CALLBACK); + + if (EFI_ERROR (Status)) { + Instance->InDestroy =3D FALSE; + gBS->RestoreTPL (OldTpl); + return Status; + } + + RemoveEntryList (&Instance->Link); + RestExSb->RestExChildrenNum--; + + gBS->RestoreTPL (OldTpl); + + RestExDestroyInstance (Instance); + return EFI_SUCCESS; +} + diff --git a/RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.h b/RedfishPkg= /RedfishRestExDxe/RedfishRestExDriver.h new file mode 100644 index 0000000000..6743ced23c --- /dev/null +++ b/RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.h @@ -0,0 +1,650 @@ +/** @file + RedfishRestExDxe support functions definitions. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef EFI_REDFISH_RESTEX_DRIVER_H_ +#define EFI_REDFISH_RESTEX_DRIVER_H_ + +/// +/// Libraries classes +/// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/// +/// UEFI Driver Model Protocols +/// +#include +#include +#include + +/// +/// Protocol instances +/// +extern EFI_COMPONENT_NAME_PROTOCOL gRedfishRestExComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gRedfishRestExComponentName2; +extern EFI_UNICODE_STRING_TABLE *gRedfishRestExControllerNameTable; + +extern EFI_DRIVER_BINDING_PROTOCOL gRedfishRestExDriverBinding; +extern EFI_SERVICE_BINDING_PROTOCOL mRedfishRestExServiceBinding; +extern EFI_REST_EX_PROTOCOL mRedfishRestExProtocol; +/// +/// RestEx service block +/// +typedef struct _RESTEX_SERVICE RESTEX_SERVICE; + +/// +/// RestEx instance block +/// +typedef struct _RESTEX_INSTANCE RESTEX_INSTANCE; + +/// +/// Driver Version +/// +#define REDFISH_RESTEX_DRIVER_VERSION 0x0100 + +#define RESTEX_SERVICE_SIGNATURE SIGNATURE_32 ('R', 'E', 'S', 'S') +#define RESTEX_INSTANCE_SIGNATURE SIGNATURE_32 ('R', 'E', 'I', 'S') + +#define RESTEX_SERVICE_FROM_THIS(a) \ + CR (a, RESTEX_SERVICE, ServiceBinding, RESTEX_SERVICE_SIGNATURE) + +#define RESTEX_INSTANCE_FROM_THIS(a) \ + CR (a, RESTEX_INSTANCE, RestEx, RESTEX_INSTANCE_SIGNATURE) + + +#define RESTEX_STATE_UNCONFIGED 0 +#define RESTEX_STATE_CONFIGED 1 + +struct _RESTEX_SERVICE { + UINT32 Signature; + EFI_SERVICE_BINDING_PROTOCOL ServiceBinding; + + UINT16 RestExChildrenNum; + LIST_ENTRY RestExChildrenList; + + EFI_HANDLE ControllerHandle; + EFI_HANDLE ImageHandle; + + // + // Use to establish the parent-child relationship. + // + EFI_HANDLE HttpChildHandle; + + UINT32 Id; + + EFI_REST_EX_SERVICE_INFO RestExServiceInfo; +}; + +#define RESTEX_INSTANCE_FLAGS_TLS_RETRY 0x00000001 +#define RESTEX_INSTANCE_FLAGS_TCP_ERROR_RETRY 0x00000002 + +struct _RESTEX_INSTANCE { + UINT32 Signature; + LIST_ENTRY Link; + + EFI_REST_EX_PROTOCOL RestEx; + + INTN State; + BOOLEAN InDestroy; + + RESTEX_SERVICE *Service; + EFI_HANDLE ChildHandle; + + EFI_REST_EX_CONFIG_DATA ConfigData; + + // + // HTTP_IO to access the HTTP service + // + HTTP_IO HttpIo; + + UINT32 Flags; +}; + +typedef struct { + EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding; + UINTN NumberOfChildren; + EFI_HANDLE *ChildHandleBuffer; +} RESTEX_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT; + +/** + Provides a simple HTTP-like interface to send and receive resources from= a REST service. + + The SendReceive() function sends an HTTP request to this REST service, a= nd returns a + response when the data is retrieved from the service. RequestMessage con= tains the HTTP + request to the REST resource identified by RequestMessage.Request.Url. T= he + ResponseMessage is the returned HTTP response for that request, includin= g any HTTP + status. + + @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance= for a particular + REST service. + @param[in] RequestMessage Pointer to the HTTP request data for thi= s resource + @param[out] ResponseMessage Pointer to the HTTP response data obtain= ed for this requested. + + @retval EFI_SUCCESS operation succeeded. + @retval EFI_INVALID_PARAMETER This, RequestMessage, or ResponseMessage= are NULL. + @retval EFI_DEVICE_ERROR An unexpected system or network error oc= curred. + +**/ +EFI_STATUS +EFIAPI +RedfishRestExSendReceive ( + IN EFI_REST_EX_PROTOCOL *This, + IN EFI_HTTP_MESSAGE *RequestMessage, + OUT EFI_HTTP_MESSAGE *ResponseMessage + ); + +/** + Obtain the current time from this REST service instance. + + The GetServiceTime() function is an optional interface to obtain the cur= rent time from + this REST service instance. If this REST service does not support to ret= rieve the time, + this function returns EFI_UNSUPPORTED. This function must returns EFI_UN= SUPPORTED if + EFI_REST_EX_SERVICE_TYPE returned in EFI_REST_EX_SERVICE_INFO from GetSe= rvice() is + EFI_REST_EX_SERVICE_UNSPECIFIC. + + @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance= for a particular + REST service. + @param[out] Time A pointer to storage to receive a snapsh= ot of the current time of + the REST service. + + @retval EFI_SUCCESS operation succeeded. + @retval EFI_INVALID_PARAMETER This or Time are NULL. + @retval EFI_UNSUPPORTED The RESTful service does not support ret= urning the time. + @retval EFI_DEVICE_ERROR An unexpected system or network error oc= curred. + @retval EFI_NOT_READY The configuration of this instance is no= t set yet. Configure() must + be executed and returns successfully pri= or to invoke this function. + +**/ +EFI_STATUS +EFIAPI +RedfishRestExGetServiceTime ( + IN EFI_REST_EX_PROTOCOL *This, + OUT EFI_TIME *Time + ); + +/** + This function returns the information of REST service provided by this E= FI REST EX driver instance. + + The information such as the type of REST service and the access mode of = REST EX driver instance + (In-band or Out-of-band) are described in EFI_REST_EX_SERVICE_INFO struc= ture. For the vendor-specific + REST service, vendor-specific REST service information is returned in Ve= ndorSpecifcData. + REST EX driver designer is well know what REST service this REST EX driv= er instance intends to + communicate with. The designer also well know this driver instance is us= ed to talk to BMC through + specific platform mechanism or talk to REST server through UEFI HTTP pro= tocol. REST EX driver is + responsible to fill up the correct information in EFI_REST_EX_SERVICE_IN= FO. EFI_REST_EX_SERVICE_INFO + is referred by EFI REST clients to pickup the proper EFI REST EX driver = instance to get and set resource. + GetService() is a basic and mandatory function which must be able to use= even Configure() is not invoked + in previously. + + @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance= for a particular + REST service. + @param[out] RestExServiceInfo Pointer to receive a pointer to EFI_REST= _EX_SERVICE_INFO structure. The + format of EFI_REST_EX_SERVICE_INFO is ve= rsion controlled for the future + extension. The version of EFI_REST_EX_SE= RVICE_INFO structure is returned + in the header within this structure. EFI= REST client refers to the correct + format of structure according to the ver= sion number. The pointer to + EFI_REST_EX_SERVICE_INFO is a memory blo= ck allocated by EFI REST EX driver + instance. That is caller's responsibilit= y to free this memory when this + structure is no longer needed. Refer to = Related Definitions below for the + definitions of EFI_REST_EX_SERVICE_INFO = structure. + + @retval EFI_SUCCESS EFI_REST_EX_SERVICE_INFO is returned in = RestExServiceInfo. This function + is not supported in this REST EX Protoco= l driver instance. + @retval EFI_UNSUPPORTED This function is not supported in this R= EST EX Protocol driver instance. + +**/ +EFI_STATUS +EFIAPI +RedfishRestExGetService ( + IN EFI_REST_EX_PROTOCOL *This, + OUT EFI_REST_EX_SERVICE_INFO **RestExServiceInfo + ); + +/** + This function returns operational configuration of current EFI REST EX c= hild instance. + + This function returns the current configuration of EFI REST EX child ins= tance. The format of + operational configuration depends on the implementation of EFI REST EX d= river instance. For + example, HTTP-aware EFI REST EX driver instance uses EFI HTTP protocol a= s the undying protocol + to communicate with REST service. In this case, the type of configuratio= n is + EFI_REST_EX_CONFIG_TYPE_HTTP returned from GetService(). EFI_HTTP_CONFIG= _DATA is used as EFI REST + EX configuration format and returned to EFI REST client. User has to typ= e cast RestExConfigData + to EFI_HTTP_CONFIG_DATA. For those non HTTP-aware REST EX driver instanc= es, the type of configuration + is EFI_REST_EX_CONFIG_TYPE_UNSPECIFIC returned from GetService(). In thi= s case, the format of + returning data could be non industrial. Instead, the format of configura= tion data is system/platform + specific definition such as BMC mechanism used in EFI REST EX driver ins= tance. EFI REST client and + EFI REST EX driver instance have to refer to the specific system /platfo= rm spec which is out of UEFI scope. + + @param[in] This This is the EFI_REST_EX_PROTOCOL instanc= e. + @param[out] RestExConfigData Pointer to receive a pointer to EFI_REST= _EX_CONFIG_DATA. + The memory allocated for configuration d= ata should be freed + by caller. See Related Definitions for t= he details. + + @retval EFI_SUCCESS EFI_REST_EX_CONFIG_DATA is returned in s= uccessfully. + @retval EFI_UNSUPPORTED This function is not supported in this R= EST EX Protocol driver instance. + @retval EFI_NOT_READY The configuration of this instance is no= t set yet. Configure() must be + executed and returns successfully prior = to invoke this function. + +**/ +EFI_STATUS +EFIAPI +RedfishRestExGetModeData ( + IN EFI_REST_EX_PROTOCOL *This, + OUT EFI_REST_EX_CONFIG_DATA *RestExConfigData + ); + +/** + This function is used to configure EFI REST EX child instance. + + This function is used to configure the setting of underlying protocol of= REST EX child + instance. The type of configuration is according to the implementation o= f EFI REST EX + driver instance. For example, HTTP-aware EFI REST EX driver instance use= s EFI HTTP protocol + as the undying protocol to communicate with REST service. The type of co= nfiguration is + EFI_REST_EX_CONFIG_TYPE_HTTP and RestExConfigData is the same format wit= h EFI_HTTP_CONFIG_DATA. + Akin to HTTP configuration, REST EX child instance can be configure to u= se different HTTP + local access point for the data transmission. Multiple REST clients may = use different + configuration of HTTP to distinguish themselves, such as to use the diff= erent TCP port. + For those non HTTP-aware REST EX driver instance, the type of configurat= ion is + EFI_REST_EX_CONFIG_TYPE_UNSPECIFIC. RestExConfigData refers to the non i= ndustrial standard. + Instead, the format of configuration data is system/platform specific de= finition such as BMC. + In this case, EFI REST client and EFI REST EX driver instance have to re= fer to the specific + system/platform spec which is out of the UEFI scope. Besides GetService(= )function, no other + EFI REST EX functions can be executed by this instance until Configure()= is executed and returns + successfully. All other functions must returns EFI_NOT_READY if this ins= tance is not configured + yet. Set RestExConfigData to NULL means to put EFI REST EX child instanc= e into the unconfigured + state. + + @param[in] This This is the EFI_REST_EX_PROTOCOL instanc= e. + @param[in] RestExConfigData Pointer to EFI_REST_EX_CONFIG_DATA. See = Related Definitions in + GetModeData() protocol interface. + + @retval EFI_SUCCESS EFI_REST_EX_CONFIG_DATA is set in succes= sfully. + @retval EFI_DEVICE_ERROR Configuration for this REST EX child ins= tance is failed with the given + EFI_REST_EX_CONFIG_DATA. + @retval EFI_UNSUPPORTED This function is not supported in this R= EST EX Protocol driver instance. + +**/ +EFI_STATUS +EFIAPI +RedfishRestExConfigure ( + IN EFI_REST_EX_PROTOCOL *This, + IN EFI_REST_EX_CONFIG_DATA RestExConfigData + ); + +/** + This function sends REST request to REST service and signal caller's eve= nt asynchronously when + the final response is received by REST EX Protocol driver instance. + + The essential design of this function is to handle asynchronous send/rec= eive implicitly according + to REST service asynchronous request mechanism. Caller will get the noti= fication once the response + is returned from REST service. + + @param[in] This This is the EFI_REST_EX_PROTOCOL insta= nce. + @param[in] RequestMessage This is the HTTP request message sent = to REST service. Set RequestMessage + to NULL to cancel the previous asynchr= onous request associated with the + corresponding RestExToken. See descrip= tions for the details. + @param[in] RestExToken REST EX token which REST EX Protocol i= nstance uses to notify REST client + the status of response of asynchronous= REST request. See related definition + of EFI_REST_EX_TOKEN. + @param[in] TimeOutInMilliSeconds The pointer to the timeout in millisec= onds which REST EX Protocol driver + instance refers as the duration to dro= p asynchronous REST request. NULL + pointer means no timeout for this REST= request. REST EX Protocol driver + signals caller's event with EFI_STATUS= set to EFI_TIMEOUT in RestExToken + if REST EX Protocol can't get the resp= onse from REST service within + TimeOutInMilliSeconds. + + @retval EFI_SUCCESS Asynchronous REST request is establish= ed. + @retval EFI_UNSUPPORTED This REST EX Protocol driver instance = doesn't support asynchronous request. + @retval EFI_TIMEOUT Asynchronous REST request is not estab= lished and timeout is expired. + @retval EFI_ABORT Previous asynchronous REST request has= been canceled. + @retval EFI_DEVICE_ERROR Otherwise, returns EFI_DEVICE_ERROR fo= r other errors according to HTTP Status Code. + @retval EFI_NOT_READY The configuration of this instance is = not set yet. Configure() must be executed + and returns successfully prior to invo= ke this function. + +**/ +EFI_STATUS +EFIAPI +RedfishRestExAyncSendReceive ( + IN EFI_REST_EX_PROTOCOL *This, + IN EFI_HTTP_MESSAGE *RequestMessage OPTIONAL, + IN EFI_REST_EX_TOKEN *RestExToken, + IN UINTN *TimeOutInMilliSeconds OPTIONAL + ); + +/** + This function sends REST request to a REST Event service and signals cal= ler's event + token asynchronously when the URI resource change event is received by R= EST EX + Protocol driver instance. + + The essential design of this function is to monitor event implicitly acc= ording to + REST service event service mechanism. Caller will get the notification i= f certain + resource is changed. + + @param[in] This This is the EFI_REST_EX_PROTOCOL insta= nce. + @param[in] RequestMessage This is the HTTP request message sent = to REST service. Set RequestMessage + to NULL to cancel the previous event s= ervice associated with the corresponding + RestExToken. See descriptions for the = details. + @param[in] RestExToken REST EX token which REST EX Protocol d= river instance uses to notify REST client + the URI resource which monitored by RE= ST client has been changed. See the related + definition of EFI_REST_EX_TOKEN in EFI= _REST_EX_PROTOCOL.AsyncSendReceive(). + + @retval EFI_SUCCESS Asynchronous REST request is establish= ed. + @retval EFI_UNSUPPORTED This REST EX Protocol driver instance = doesn't support asynchronous request. + @retval EFI_ABORT Previous asynchronous REST request has= been canceled or event subscription has been + delete from service. + @retval EFI_DEVICE_ERROR Otherwise, returns EFI_DEVICE_ERROR fo= r other errors according to HTTP Status Code. + @retval EFI_NOT_READY The configuration of this instance is = not set yet. Configure() must be executed + and returns successfully prior to invo= ke this function. + +**/ +EFI_STATUS +EFIAPI +RedfishRestExEventService ( + IN EFI_REST_EX_PROTOCOL *This, + IN EFI_HTTP_MESSAGE *RequestMessage OPTIONAL, + IN EFI_REST_EX_TOKEN *RestExToken + ); +/** + Create a new TLS session becuase the previous on is closed. + status. + + @param[in] Instance Pointer to EFI_REST_EX_PROTOCOL instance= for a particular + REST service. + @retval EFI_SUCCESS operation succeeded. + @retval EFI Errors Other errors. + +**/ +EFI_STATUS +ResetHttpTslSession ( + IN RESTEX_INSTANCE *Instance +); + + +/** + Callback function which provided by user to remove one node in NetDestro= yLinkList process. + + @param[in] Entry The entry to be removed. + @param[in] Context Pointer to the callback context correspond= s to the Context in NetDestroyLinkList. + + @retval EFI_SUCCESS The entry has been removed successfully. + @retval Others Fail to remove the entry. + +**/ +EFI_STATUS +EFIAPI +RestExDestroyChildEntryInHandleBuffer ( + IN LIST_ENTRY *Entry, + IN VOID *Context + ); + +/** + Destroy the RestEx instance and recycle the resources. + + @param[in] Instance The pointer to the RestEx instance. + +**/ +VOID +RestExDestroyInstance ( + IN RESTEX_INSTANCE *Instance + ); + +/** + Create the RestEx instance and initialize it. + + @param[in] Service The pointer to the RestEx service. + @param[out] Instance The pointer to the RestEx instance. + + @retval EFI_OUT_OF_RESOURCES Failed to allocate resources. + @retval EFI_SUCCESS The RestEx instance is created. + +**/ +EFI_STATUS +RestExCreateInstance ( + IN RESTEX_SERVICE *Service, + OUT RESTEX_INSTANCE **Instance + ); + + +/** + Release all the resource used the RestEx service binding instance. + + @param RestExSb The RestEx service binding instance. + +**/ +VOID +RestExDestroyService ( + IN RESTEX_SERVICE *RestExSb + ); + +/** + Create then initialize a RestEx service binding instance. + + @param[in] Controller The controller to install the RestEx servi= ce + binding on. + @param[in] Image The driver binding image of the RestEx dri= ver. + @param[out] Service The variable to receive the created service + binding instance. + + @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the= instance. + @retval EFI_SUCCESS The service instance is created for the c= ontroller. + +**/ +EFI_STATUS +RestExCreateService ( + IN EFI_HANDLE Controller, + IN EFI_HANDLE Image, + OUT RESTEX_SERVICE **Service + ); + +/** + This is the declaration of an EFI image entry point. This entry point is + the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers includ= ing + both device drivers and bus drivers. + + @param[in] ImageHandle The firmware allocated handle for the UEFI = image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The operation completed successfully. + @retval Others An unexpected error occurred. +**/ +EFI_STATUS +EFIAPI +RedfishRestExDriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Tests to see if this driver supports a given controller. If a child devi= ce is provided, + it further tests to see if this driver supports creating a handle for th= e specified child device. + + This function checks to see if the driver specified by This supports the= device specified by + ControllerHandle. Drivers will typically use the device path attached to + ControllerHandle and/or the services from the bus I/O abstraction attach= ed to + ControllerHandle to determine if the driver supports ControllerHandle. T= his function + may be called many times during platform initialization. In order to red= uce boot times, the tests + performed by this function must be very small, and take as little time a= s possible to execute. This + function must not change the state of any hardware devices, and this fun= ction must be aware that the + device specified by ControllerHandle may already be managed by the same = driver or a + different driver. This function must match its calls to AllocatePages() = with FreePages(), + AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol(). + Because ControllerHandle may have been previously started by the same dr= iver, if a protocol is + already in the opened state, then it must not be closed with CloseProtoc= ol(). This is required + to guarantee the state of ControllerHandle is not modified by this funct= ion. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PRO= TOCOL instance. + @param[in] ControllerHandle The handle of the controller to test. T= his handle + must support a protocol interface that = supplies + an I/O abstraction to the driver. + @param[in] RemainingDevicePath A pointer to the remaining portion of a= device path. This + parameter is ignored by device drivers,= and is optional for bus + drivers. For bus drivers, if this param= eter is not NULL, then + the bus driver must determine if the bu= s controller specified + by ControllerHandle and the child contr= oller specified + by RemainingDevicePath are both support= ed by this + bus driver. + + @retval EFI_SUCCESS The device specified by ControllerHandl= e and + RemainingDevicePath is supported by the= driver specified by This. + @retval EFI_ALREADY_STARTED The device specified by ControllerHandl= e and + RemainingDevicePath is already being ma= naged by the driver + specified by This. + @retval EFI_ACCESS_DENIED The device specified by ControllerHandl= e and + RemainingDevicePath is already being ma= naged by a different + driver or an application that requires = exclusive access. + Currently not implemented. + @retval EFI_UNSUPPORTED The device specified by ControllerHandl= e and + RemainingDevicePath is not supported by= the driver specified by This. +**/ +EFI_STATUS +EFIAPI +RedfishRestExDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ); + +/** + Starts a device controller or a bus controller. + + The Start() function is designed to be invoked from the EFI boot service= ConnectController(). + As a result, much of the error checking on the parameters to Start() has= been moved into this + common boot service. It is legal to call Start() from other locations, + but the following calling restrictions must be followed, or the system b= ehavior will not be deterministic. + 1. ControllerHandle must be a valid EFI_HANDLE. + 2. If RemainingDevicePath is not NULL, then it must be a pointer to a na= turally aligned + EFI_DEVICE_PATH_PROTOCOL. + 3. Prior to calling Start(), the Supported() function for the driver spe= cified by This must + have been called with the same calling parameters, and Supported() mu= st have returned EFI_SUCCESS. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PRO= TOCOL instance. + @param[in] ControllerHandle The handle of the controller to start. = This handle + must support a protocol interface that = supplies + an I/O abstraction to the driver. + @param[in] RemainingDevicePath A pointer to the remaining portion of a= device path. This + parameter is ignored by device drivers,= and is optional for bus + drivers. For a bus driver, if this para= meter is NULL, then handles + for all the children of Controller are = created by this driver. + If this parameter is not NULL and the f= irst Device Path Node is + not the End of Device Path Node, then o= nly the handle for the + child device specified by the first Dev= ice Path Node of + RemainingDevicePath is created by this = driver. + If the first Device Path Node of Remain= ingDevicePath is + the End of Device Path Node, no child h= andle is created by this + driver. + + @retval EFI_SUCCESS The device was started. + @retval EFI_DEVICE_ERROR The device could not be started due to = a device error.Currently not implemented. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due = to a lack of resources. + @retval Others The driver failded to start the device. + +**/ +EFI_STATUS +EFIAPI +RedfishRestExDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ); + +/** + Stops a device controller or a bus controller. + + The Stop() function is designed to be invoked from the EFI boot service = DisconnectController(). + As a result, much of the error checking on the parameters to Stop() has = been moved + into this common boot service. It is legal to call Stop() from other loc= ations, + but the following calling restrictions must be followed, or the system b= ehavior will not be deterministic. + 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previo= us call to this + same driver's Start() function. + 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a= valid + EFI_HANDLE. In addition, all of these handles must have been created = in this driver's + Start() function, and the Start() function must have called OpenProto= col() on + ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONT= ROLLER. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOC= OL instance. + @param[in] ControllerHandle A handle to the device being stopped. The = handle must + support a bus specific I/O protocol for th= e driver + to use to stop the device. + @param[in] NumberOfChildren The number of child device handles in Chil= dHandleBuffer. + @param[in] ChildHandleBuffer An array of child handles to be freed. May= be NULL + if NumberOfChildren is 0. + + @retval EFI_SUCCESS The device was stopped. + @retval EFI_DEVICE_ERROR The device could not be stopped due to a d= evice error. + +**/ +EFI_STATUS +EFIAPI +RedfishRestExDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer OPTIONAL + ); + +/** + Creates a child handle and installs a protocol. + + The CreateChild() function installs a protocol on ChildHandle. + If ChildHandle is a pointer to NULL, then a new handle is created and re= turned in ChildHandle. + If ChildHandle is not a pointer to NULL, then the protocol installs on t= he existing ChildHandle. + + @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL insta= nce. + @param[in] ChildHandle Pointer to the handle of the child to create. If = it is NULL, + then a new handle is created. If it is a pointer = to an existing UEFI handle, + then the protocol is added to the existing UEFI h= andle. + + @retval EFI_SUCCES The protocol was added to ChildHandle. + @retval EFI_INVALID_PARAMETER ChildHandle is NULL. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available t= o create + the child + @retval other The child handle was not created + +**/ +EFI_STATUS +EFIAPI +RedfishRestExServiceBindingCreateChild ( + IN EFI_SERVICE_BINDING_PROTOCOL *This, + IN EFI_HANDLE *ChildHandle + ); + +/** + Destroys a child handle with a protocol installed on it. + + The DestroyChild() function does the opposite of CreateChild(). It remov= es a protocol + that was installed by CreateChild() from ChildHandle. If the removed pro= tocol is the + last protocol on ChildHandle, then ChildHandle is destroyed. + + @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL insta= nce. + @param[in] ChildHandle Handle of the child to destroy + + @retval EFI_SUCCES The protocol was removed from ChildHandle. + @retval EFI_UNSUPPORTED ChildHandle does not support the protocol = that is being removed. + @retval EFI_INVALID_PARAMETER Child handle is NULL. + @retval EFI_ACCESS_DENIED The protocol could not be removed from the= ChildHandle + because its services are being used. + @retval other The child handle was not destroyed + +**/ +EFI_STATUS +EFIAPI +RedfishRestExServiceBindingDestroyChild ( + IN EFI_SERVICE_BINDING_PROTOCOL *This, + IN EFI_HANDLE ChildHandle + ); +#endif diff --git a/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf b/RedfishPkg/= RedfishRestExDxe/RedfishRestExDxe.inf new file mode 100644 index 0000000000..75437b086a --- /dev/null +++ b/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf @@ -0,0 +1,63 @@ +## @file +# Implementation of Redfish EFI_REST_EX_PROTOCOL interfaces. +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# (C) Copyright 2020 Hewlett Packard Enterprise Development LP
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x0001001b + BASE_NAME =3D RedfishRestExDxe + FILE_GUID =3D B64702DA-E6B5-43c8-8CE8-D253071E9D6C + MODULE_TYPE =3D UEFI_DRIVER + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D RedfishRestExDriverEntryPoint + UNLOAD_IMAGE =3D NetLibDefaultUnload + MODULE_UNI_FILE =3D RedfishRestExDxe.uni + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + NetworkPkg/NetworkPkg.dec + RedfishPkg/RedfishPkg.dec + +[Sources] + ComponentName.c + RedfishRestExDriver.c + RedfishRestExDriver.h + RedfishRestExImpl.c + RedfishRestExProtocol.c + RedfishRestExInternal.h + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + DevicePathLib + DpcLib + HttpLib + HttpIoLib + PrintLib + MemoryAllocationLib + NetLib + UefiLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UefiRuntimeServicesTableLib + +[Protocols] + gEfiRestExServiceBindingProtocolGuid ## BY_START + gEfiRestExProtocolGuid ## BY_START + gEfiHttpServiceBindingProtocolGuid ## TO_START + gEfiHttpProtocolGuid ## TO_START + gEfiDevicePathProtocolGuid ## TO_START + +[Pcd] + gEfiRedfishPkgTokenSpaceGuid.PcdRedfishRestExServiceAccessModeInBand #= # CONSUMES + +[UserExtensions.TianoCore."ExtraFiles"] + RedfishRestExDxeExtra.uni + diff --git a/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.uni b/RedfishPkg/= RedfishRestExDxe/RedfishRestExDxe.uni new file mode 100644 index 0000000000..afa0c142a9 --- /dev/null +++ b/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.uni @@ -0,0 +1,16 @@ +// /** @file +// Redfish UEFI RESTEX DXE Driver. +// +// This driver provides Redfish UEFI RESTEX protocols. +// +// Copyright (c) 2019, Intel Corporation. All rights reserved.
+// (C) Copyright 2020 Hewlett Packard Enterprise Development LP
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + +#string STR_MODULE_ABSTRACT #language en-US "UEFI Redfish REST= EX service" + +#string STR_MODULE_DESCRIPTION #language en-US "This driver provi= des Redfish EFI RESTEX Protocol and Redfish EFI RESREX Service Binding Prot= ocol." + diff --git a/RedfishPkg/RedfishRestExDxe/RedfishRestExDxeExtra.uni b/Redfis= hPkg/RedfishRestExDxe/RedfishRestExDxeExtra.uni new file mode 100644 index 0000000000..a8ecf8aede --- /dev/null +++ b/RedfishPkg/RedfishRestExDxe/RedfishRestExDxeExtra.uni @@ -0,0 +1,15 @@ +// /** @file +// RestExDxe Localized Strings and Content +// +// Copyright (c) 2019, Intel Corporation. All rights reserved.
+// (C) Copyright 2020 Hewlett Packard Enterprise Development LP
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + +#string STR_PROPERTIES_MODULE_NAME +#language en-US +"Redfish UEFI RESTEX DXE" + + diff --git a/RedfishPkg/RedfishRestExDxe/RedfishRestExImpl.c b/RedfishPkg/R= edfishRestExDxe/RedfishRestExImpl.c new file mode 100644 index 0000000000..006b64adc0 --- /dev/null +++ b/RedfishPkg/RedfishRestExDxe/RedfishRestExImpl.c @@ -0,0 +1,157 @@ +/** @file + RestExDxe support functions implementation. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include +#include "RedfishRestExInternal.h" + +/** + Create a new TLS session becuase the previous on is closed. + status. + + @param[in] Instance Pointer to EFI_REST_EX_PROTOCOL instance= for a particular + REST service. + @retval EFI_SUCCESS operation succeeded. + @retval EFI_ERROR Other errors. + +**/ +EFI_STATUS +ResetHttpTslSession ( + IN RESTEX_INSTANCE *Instance +) +{ + EFI_STATUS Status; + + DEBUG ((DEBUG_INFO, "%a: TCP connection is finished. Could be TSL sessio= n closure, reset HTTP instance for the new TLS session.\n", __FUNCTION__)); + + Status =3D Instance->HttpIo.Http->Configure (Instance->HttpIo.Http, NULL= ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Error to reset HTTP instance.\n", __FUNCTION= __)); + return Status; + } + Status =3D Instance->HttpIo.Http->Configure(Instance->HttpIo.Http, &((EF= I_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConfigData); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Error to re-initiate HTTP instance.\n", __FU= NCTION__)); + } + return Status; +} +/** + This function check + + @param[in] Instance Pointer to EFI_REST_EX_PROTOCOL instanc= e for a particular + REST service. + @param[in] HttpIoReceiveStatus This is the status return from HttpIoRe= cvResponse + + @retval EFI_SUCCESS The payload receive from Redfish service i= n sucessfully. + @retval EFI_NOT_READY May need to resend the HTTP request. + @retval EFI_DEVICE_ERROR Something wrong and can't be resolved. + @retval Others Other errors as indicated. + +**/ +EFI_STATUS +RedfishCheckHttpReceiveStatus ( + IN RESTEX_INSTANCE *Instance, + IN EFI_STATUS HttpIoReceiveStatus + ) +{ + EFI_STATUS Status; + EFI_STATUS ReturnStatus; + + if (!EFI_ERROR (HttpIoReceiveStatus)){ + ReturnStatus =3D EFI_SUCCESS; + } else if (EFI_ERROR (HttpIoReceiveStatus) && HttpIoReceiveStatus !=3D E= FI_CONNECTION_FIN) { + if ((Instance->Flags & RESTEX_INSTANCE_FLAGS_TCP_ERROR_RETRY) =3D=3D 0= ) { + DEBUG ((DEBUG_ERROR, "%a: TCP error, reset HTTP session.\n", __FUNCT= ION__)); + Instance->Flags |=3D RESTEX_INSTANCE_FLAGS_TCP_ERROR_RETRY; + gBS->Stall (500); + Status =3D ResetHttpTslSession (Instance); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Reset HTTP instance fail.\n", __FUNCTION= __)); + ReturnStatus =3D EFI_DEVICE_ERROR; + } else { + return EFI_NOT_READY; + } + } else { + ReturnStatus =3D EFI_DEVICE_ERROR; + } + } else { + if (HttpIoReceiveStatus =3D=3D EFI_CONNECTION_FIN) { + if ((Instance->Flags & RESTEX_INSTANCE_FLAGS_TLS_RETRY) !=3D 0) { + DEBUG ((DEBUG_ERROR, "%a: REST_EX Send and receive fail even wit= h a new TLS session.\n", __FUNCTION__)); + ReturnStatus =3D EFI_DEVICE_ERROR; + } + Instance->Flags |=3D RESTEX_INSTANCE_FLAGS_TLS_RETRY; + Status =3D ResetHttpTslSession (Instance); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Reset HTTP instance fail.\n", __FUNCTI= ON__)); + ReturnStatus =3D EFI_DEVICE_ERROR; + } + return EFI_NOT_READY; + } + } + // + // Clean TLS new session retry and error try flags. + // + Instance->Flags &=3D ~ (RESTEX_INSTANCE_FLAGS_TLS_RETRY | RESTEX_INSTANC= E_FLAGS_TCP_ERROR_RETRY); + return ReturnStatus; +} + +/** + This function send the HTTP request without body to see + if the write to URL is permitted by Redfish service. This function + checks if the HTTP request has Content-length in HTTP header. If yes, + set HTTP body to NULL and then send to service. Check the HTTP status + for the firther actions. + + @param[in] This Pointer to EFI_REST_EX_PROTOCOL inst= ance for a particular + REST service. + @param[in] RequestMessage Pointer to the HTTP request data for= this resource + @param[in] PreservedRequestHeaders The pointer to save the request head= ers + @param[in] ItsWrite This is write method to URL. + + @retval EFI_INVALID_PARAMETER Improper given parameters. + @retval EFI_SUCCESS This HTTP request is free to send to Redf= ish service. + @retval EFI_OUT_OF_RESOURCES NOt enough memory to process. + @retval EFI_ACCESS_DENIED Not allowed to write to this URL. + + @retval Others Other errors as indicated. + +**/ +EFI_STATUS +RedfishHttpAddExpectation ( + IN EFI_REST_EX_PROTOCOL *This, + IN EFI_HTTP_MESSAGE *RequestMessage, + IN EFI_HTTP_HEADER **PreservedRequestHeaders, + IN BOOLEAN *ItsWrite + ) +{ + EFI_HTTP_HEADER *NewHeaders; + + if (This =3D=3D NULL || RequestMessage =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + *ItsWrite =3D FALSE; + if (PreservedRequestHeaders !=3D NULL) { + *PreservedRequestHeaders =3D RequestMessage->Headers; + } + + if ((RequestMessage->Data.Request->Method !=3D HttpMethodPut) && (Reques= tMessage->Data.Request->Method !=3D HttpMethodPost) && + (RequestMessage->Data.Request->Method !=3D HttpMethodPatch)) { + return EFI_SUCCESS; + } + *ItsWrite =3D TRUE; + + NewHeaders =3D AllocateZeroPool((RequestMessage->HeaderCount + 1) * size= of(EFI_HTTP_HEADER)); + CopyMem ((VOID*)NewHeaders, (VOID *)RequestMessage->Headers, RequestMess= age->HeaderCount * sizeof (EFI_HTTP_HEADER)); + HttpSetFieldNameAndValue (NewHeaders + RequestMessage->HeaderCount, HTTP= _HEADER_EXPECT, HTTP_EXPECT_100_CONTINUE); + RequestMessage->HeaderCount ++; + RequestMessage->Headers =3D NewHeaders; + return EFI_SUCCESS; +} + diff --git a/RedfishPkg/RedfishRestExDxe/RedfishRestExInternal.h b/RedfishP= kg/RedfishRestExDxe/RedfishRestExInternal.h new file mode 100644 index 0000000000..a75985928c --- /dev/null +++ b/RedfishPkg/RedfishRestExDxe/RedfishRestExInternal.h @@ -0,0 +1,611 @@ +/** @file + RedfishRestExDxe support functions definitions. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ (C) Copyright 2019-2020 Hewlett Packard Enterprise Development LP
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef EFI_REDFISH_RESTEX_INTERNAL_H_ +#define EFI_REDFISH_RESTEX_INTERNAL_H_ + +/// +/// Libraries classes +/// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/// +/// UEFI Driver Model Protocols +/// +#include +#include +#include + +#include "RedfishRestExDriver.h" + +/** + This function check + + @param[in] Instance Pointer to EFI_REST_EX_PROTOCOL instance f= or a particular + REST service. + @param[in] HttpReceiveEfiStatus This is the status return from HttpIoR= ecvResponse + + @retval EFI_SUCCESS The payload receive from Redfish service i= n sucessfully. + @retval EFI_NOT_READY May need to resend the HTTP request. + @retval EFI_DEVICE_ERROR Something wrong and can't be resolved. + @retval Others Other errors as indicated. + +**/ +EFI_STATUS +RedfishCheckHttpReceiveStatus ( + IN RESTEX_INSTANCE *Instance, + IN EFI_STATUS HttpIoReceiveStatus + ); + +/** + This function send the HTTP request without body to see + if the write to URL is permitted by Redfish service. This function + checks if the HTTP request has Content-length in HTTP header. If yes, + set HTTP body to NULL and then send to service. Check the HTTP status + for the firther actions. + + @param[in] This Pointer to EFI_REST_EX_PROTOCOL inst= ance for a particular + REST service. + @param[in] RequestMessage Pointer to the HTTP request data for= this resource + @param[in] PreservedRequestHeaders The pointer to save the request head= ers + @param[in] ItsWrite This is write method to URL. + + @retval EFI_INVALID_PARAMETER Improper given parameters. + @retval EFI_SUCCESS This HTTP request is free to send to Redf= ish service. + @retval EFI_OUT_OF_RESOURCES NOt enough memory to process. + @retval EFI_ACCESS_DENIED Not allowed to write to this URL. + + @retval Others Other errors as indicated. + +**/ +EFI_STATUS +RedfishHttpAddExpectation ( + IN EFI_REST_EX_PROTOCOL *This, + IN EFI_HTTP_MESSAGE *RequestMessage, + IN EFI_HTTP_HEADER **PreservedRequestHeaders, + IN BOOLEAN *ItsWrite + ); + +/** + Provides a simple HTTP-like interface to send and receive resources from= a REST service. + + The SendReceive() function sends an HTTP request to this REST service, a= nd returns a + response when the data is retrieved from the service. RequestMessage con= tains the HTTP + request to the REST resource identified by RequestMessage.Request.Url. T= he + ResponseMessage is the returned HTTP response for that request, includin= g any HTTP + status. + + @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance= for a particular + REST service. + @param[in] RequestMessage Pointer to the HTTP request data for thi= s resource + @param[out] ResponseMessage Pointer to the HTTP response data obtain= ed for this requested. + + @retval EFI_SUCCESS operation succeeded. + @retval EFI_INVALID_PARAMETER This, RequestMessage, or ResponseMessage= are NULL. + @retval EFI_DEVICE_ERROR An unexpected system or network error oc= curred. + +**/ +EFI_STATUS +EFIAPI +RedfishRestExSendReceive ( + IN EFI_REST_EX_PROTOCOL *This, + IN EFI_HTTP_MESSAGE *RequestMessage, + OUT EFI_HTTP_MESSAGE *ResponseMessage + ); + +/** + Obtain the current time from this REST service instance. + + The GetServiceTime() function is an optional interface to obtain the cur= rent time from + this REST service instance. If this REST service does not support to ret= rieve the time, + this function returns EFI_UNSUPPORTED. This function must returns EFI_UN= SUPPORTED if + EFI_REST_EX_SERVICE_TYPE returned in EFI_REST_EX_SERVICE_INFO from GetSe= rvice() is + EFI_REST_EX_SERVICE_UNSPECIFIC. + + @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance= for a particular + REST service. + @param[out] Time A pointer to storage to receive a snapsh= ot of the current time of + the REST service. + + @retval EFI_SUCCESS operation succeeded. + @retval EFI_INVALID_PARAMETER This or Time are NULL. + @retval EFI_UNSUPPORTED The RESTful service does not support ret= urning the time. + @retval EFI_DEVICE_ERROR An unexpected system or network error oc= curred. + @retval EFI_NOT_READY The configuration of this instance is no= t set yet. Configure() must + be executed and returns successfully pri= or to invoke this function. + +**/ +EFI_STATUS +EFIAPI +RedfishRestExGetServiceTime ( + IN EFI_REST_EX_PROTOCOL *This, + OUT EFI_TIME *Time + ); + +/** + This function returns the information of REST service provided by this E= FI REST EX driver instance. + + The information such as the type of REST service and the access mode of = REST EX driver instance + (In-band or Out-of-band) are described in EFI_REST_EX_SERVICE_INFO struc= ture. For the vendor-specific + REST service, vendor-specific REST service information is returned in Ve= ndorSpecifcData. + REST EX driver designer is well know what REST service this REST EX driv= er instance intends to + communicate with. The designer also well know this driver instance is us= ed to talk to BMC through + specific platform mechanism or talk to REST server through UEFI HTTP pro= tocol. REST EX driver is + responsible to fill up the correct information in EFI_REST_EX_SERVICE_IN= FO. EFI_REST_EX_SERVICE_INFO + is referred by EFI REST clients to pickup the proper EFI REST EX driver = instance to get and set resource. + GetService() is a basic and mandatory function which must be able to use= even Configure() is not invoked + in previously. + + @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance= for a particular + REST service. + @param[out] RestExServiceInfo Pointer to receive a pointer to EFI_REST= _EX_SERVICE_INFO structure. The + format of EFI_REST_EX_SERVICE_INFO is ve= rsion controlled for the future + extension. The version of EFI_REST_EX_SE= RVICE_INFO structure is returned + in the header within this structure. EFI= REST client refers to the correct + format of structure according to the ver= sion number. The pointer to + EFI_REST_EX_SERVICE_INFO is a memory blo= ck allocated by EFI REST EX driver + instance. That is caller's responsibilit= y to free this memory when this + structure is no longer needed. Refer to = Related Definitions below for the + definitions of EFI_REST_EX_SERVICE_INFO = structure. + + @retval EFI_SUCCESS EFI_REST_EX_SERVICE_INFO is returned in = RestExServiceInfo. This function + is not supported in this REST EX Protoco= l driver instance. + @retval EFI_UNSUPPORTED This function is not supported in this R= EST EX Protocol driver instance. + +**/ +EFI_STATUS +EFIAPI +RedfishRestExGetService ( + IN EFI_REST_EX_PROTOCOL *This, + OUT EFI_REST_EX_SERVICE_INFO **RestExServiceInfo + ); + +/** + This function returns operational configuration of current EFI REST EX c= hild instance. + + This function returns the current configuration of EFI REST EX child ins= tance. The format of + operational configuration depends on the implementation of EFI REST EX d= river instance. For + example, HTTP-aware EFI REST EX driver instance uses EFI HTTP protocol a= s the undying protocol + to communicate with REST service. In this case, the type of configuratio= n is + EFI_REST_EX_CONFIG_TYPE_HTTP returned from GetService(). EFI_HTTP_CONFIG= _DATA is used as EFI REST + EX configuration format and returned to EFI REST client. User has to typ= e cast RestExConfigData + to EFI_HTTP_CONFIG_DATA. For those non HTTP-aware REST EX driver instanc= es, the type of configuration + is EFI_REST_EX_CONFIG_TYPE_UNSPECIFIC returned from GetService(). In thi= s case, the format of + returning data could be non industrial. Instead, the format of configura= tion data is system/platform + specific definition such as BMC mechanism used in EFI REST EX driver ins= tance. EFI REST client and + EFI REST EX driver instance have to refer to the specific system /platfo= rm spec which is out of UEFI scope. + + @param[in] This This is the EFI_REST_EX_PROTOCOL instanc= e. + @param[out] RestExConfigData Pointer to receive a pointer to EFI_REST= _EX_CONFIG_DATA. + The memory allocated for configuration d= ata should be freed + by caller. See Related Definitions for t= he details. + + @retval EFI_SUCCESS EFI_REST_EX_CONFIG_DATA is returned in s= uccessfully. + @retval EFI_UNSUPPORTED This function is not supported in this R= EST EX Protocol driver instance. + @retval EFI_NOT_READY The configuration of this instance is no= t set yet. Configure() must be + executed and returns successfully prior = to invoke this function. + +**/ +EFI_STATUS +EFIAPI +RedfishRestExGetModeData ( + IN EFI_REST_EX_PROTOCOL *This, + OUT EFI_REST_EX_CONFIG_DATA *RestExConfigData + ); + +/** + This function is used to configure EFI REST EX child instance. + + This function is used to configure the setting of underlying protocol of= REST EX child + instance. The type of configuration is according to the implementation o= f EFI REST EX + driver instance. For example, HTTP-aware EFI REST EX driver instance use= s EFI HTTP protocol + as the undying protocol to communicate with REST service. The type of co= nfiguration is + EFI_REST_EX_CONFIG_TYPE_HTTP and RestExConfigData is the same format wit= h EFI_HTTP_CONFIG_DATA. + Akin to HTTP configuration, REST EX child instance can be configure to u= se different HTTP + local access point for the data transmission. Multiple REST clients may = use different + configuration of HTTP to distinguish themselves, such as to use the diff= erent TCP port. + For those non HTTP-aware REST EX driver instance, the type of configurat= ion is + EFI_REST_EX_CONFIG_TYPE_UNSPECIFIC. RestExConfigData refers to the non i= ndustrial standard. + Instead, the format of configuration data is system/platform specific de= finition such as BMC. + In this case, EFI REST client and EFI REST EX driver instance have to re= fer to the specific + system/platform spec which is out of the UEFI scope. Besides GetService(= )function, no other + EFI REST EX functions can be executed by this instance until Configure()= is executed and returns + successfully. All other functions must returns EFI_NOT_READY if this ins= tance is not configured + yet. Set RestExConfigData to NULL means to put EFI REST EX child instanc= e into the unconfigured + state. + + @param[in] This This is the EFI_REST_EX_PROTOCOL instanc= e. + @param[in] RestExConfigData Pointer to EFI_REST_EX_CONFIG_DATA. See = Related Definitions in + GetModeData() protocol interface. + + @retval EFI_SUCCESS EFI_REST_EX_CONFIG_DATA is set in succes= sfully. + @retval EFI_DEVICE_ERROR Configuration for this REST EX child ins= tance is failed with the given + EFI_REST_EX_CONFIG_DATA. + @retval EFI_UNSUPPORTED This function is not supported in this R= EST EX Protocol driver instance. + +**/ +EFI_STATUS +EFIAPI +RedfishRestExConfigure ( + IN EFI_REST_EX_PROTOCOL *This, + IN EFI_REST_EX_CONFIG_DATA RestExConfigData + ); + +/** + This function sends REST request to REST service and signal caller's eve= nt asynchronously when + the final response is received by REST EX Protocol driver instance. + + The essential design of this function is to handle asynchronous send/rec= eive implicitly according + to REST service asynchronous request mechanism. Caller will get the noti= fication once the response + is returned from REST service. + + @param[in] This This is the EFI_REST_EX_PROTOCOL insta= nce. + @param[in] RequestMessage This is the HTTP request message sent = to REST service. Set RequestMessage + to NULL to cancel the previous asynchr= onous request associated with the + corresponding RestExToken. See descrip= tions for the details. + @param[in] RestExToken REST EX token which REST EX Protocol i= nstance uses to notify REST client + the status of response of asynchronous= REST request. See related definition + of EFI_REST_EX_TOKEN. + @param[in] TimeOutInMilliSeconds The pointer to the timeout in millisec= onds which REST EX Protocol driver + instance refers as the duration to dro= p asynchronous REST request. NULL + pointer means no timeout for this REST= request. REST EX Protocol driver + signals caller's event with EFI_STATUS= set to EFI_TIMEOUT in RestExToken + if REST EX Protocol can't get the resp= onse from REST service within + TimeOutInMilliSeconds. + + @retval EFI_SUCCESS Asynchronous REST request is establish= ed. + @retval EFI_UNSUPPORTED This REST EX Protocol driver instance = doesn't support asynchronous request. + @retval EFI_TIMEOUT Asynchronous REST request is not estab= lished and timeout is expired. + @retval EFI_ABORT Previous asynchronous REST request has= been canceled. + @retval EFI_DEVICE_ERROR Otherwise, returns EFI_DEVICE_ERROR fo= r other errors according to HTTP Status Code. + @retval EFI_NOT_READY The configuration of this instance is = not set yet. Configure() must be executed + and returns successfully prior to invo= ke this function. + +**/ +EFI_STATUS +EFIAPI +RedfishRestExAyncSendReceive ( + IN EFI_REST_EX_PROTOCOL *This, + IN EFI_HTTP_MESSAGE *RequestMessage OPTIONAL, + IN EFI_REST_EX_TOKEN *RestExToken, + IN UINTN *TimeOutInMilliSeconds OPTIONAL + ); + +/** + This function sends REST request to a REST Event service and signals cal= ler's event + token asynchronously when the URI resource change event is received by R= EST EX + Protocol driver instance. + + The essential design of this function is to monitor event implicitly acc= ording to + REST service event service mechanism. Caller will get the notification i= f certain + resource is changed. + + @param[in] This This is the EFI_REST_EX_PROTOCOL insta= nce. + @param[in] RequestMessage This is the HTTP request message sent = to REST service. Set RequestMessage + to NULL to cancel the previous event s= ervice associated with the corresponding + RestExToken. See descriptions for the = details. + @param[in] RestExToken REST EX token which REST EX Protocol d= river instance uses to notify REST client + the URI resource which monitored by RE= ST client has been changed. See the related + definition of EFI_REST_EX_TOKEN in EFI= _REST_EX_PROTOCOL.AsyncSendReceive(). + + @retval EFI_SUCCESS Asynchronous REST request is establish= ed. + @retval EFI_UNSUPPORTED This REST EX Protocol driver instance = doesn't support asynchronous request. + @retval EFI_ABORT Previous asynchronous REST request has= been canceled or event subscription has been + delete from service. + @retval EFI_DEVICE_ERROR Otherwise, returns EFI_DEVICE_ERROR fo= r other errors according to HTTP Status Code. + @retval EFI_NOT_READY The configuration of this instance is = not set yet. Configure() must be executed + and returns successfully prior to invo= ke this function. + +**/ +EFI_STATUS +EFIAPI +RedfishRestExEventService ( + IN EFI_REST_EX_PROTOCOL *This, + IN EFI_HTTP_MESSAGE *RequestMessage OPTIONAL, + IN EFI_REST_EX_TOKEN *RestExToken + ); +/** + Create a new TLS session becuase the previous on is closed. + status. + + @param[in] Instance Pointer to EFI_REST_EX_PROTOCOL instance= for a particular + REST service. + @retval EFI_SUCCESS operation succeeded. + @retval EFI Errors Other errors. + +**/ +EFI_STATUS +ResetHttpTslSession ( + IN RESTEX_INSTANCE *Instance +); + + +/** + Callback function which provided by user to remove one node in NetDestro= yLinkList process. + + @param[in] Entry The entry to be removed. + @param[in] Context Pointer to the callback context correspond= s to the Context in NetDestroyLinkList. + + @retval EFI_SUCCESS The entry has been removed successfully. + @retval Others Fail to remove the entry. + +**/ +EFI_STATUS +EFIAPI +RestExDestroyChildEntryInHandleBuffer ( + IN LIST_ENTRY *Entry, + IN VOID *Context + ); + +/** + Destroy the RestEx instance and recycle the resources. + + @param[in] Instance The pointer to the RestEx instance. + +**/ +VOID +RestExDestroyInstance ( + IN RESTEX_INSTANCE *Instance + ); + +/** + Create the RestEx instance and initialize it. + + @param[in] Service The pointer to the RestEx service. + @param[out] Instance The pointer to the RestEx instance. + + @retval EFI_OUT_OF_RESOURCES Failed to allocate resources. + @retval EFI_SUCCESS The RestEx instance is created. + +**/ +EFI_STATUS +RestExCreateInstance ( + IN RESTEX_SERVICE *Service, + OUT RESTEX_INSTANCE **Instance + ); + + +/** + Release all the resource used the RestEx service binding instance. + + @param[in] RestExSb The RestEx service binding instance. + +**/ +VOID +RestExDestroyService ( + IN RESTEX_SERVICE *RestExSb + ); + +/** + Create then initialize a RestEx service binding instance. + + @param[in] Controller The controller to install the RestEx servi= ce + binding on. + @param[in] Image The driver binding image of the RestEx dri= ver. + @param[out] Service The variable to receive the created service + binding instance. + + @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the= instance. + @retval EFI_SUCCESS The service instance is created for the c= ontroller. + +**/ +EFI_STATUS +RestExCreateService ( + IN EFI_HANDLE Controller, + IN EFI_HANDLE Image, + OUT RESTEX_SERVICE **Service + ); + +/** + This is the declaration of an EFI image entry point. This entry point is + the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers includ= ing + both device drivers and bus drivers. + + @param[in] ImageHandle The firmware allocated handle for the UEFI = image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The operation completed successfully. + @retval Others An unexpected error occurred. +**/ +EFI_STATUS +EFIAPI +RedfishRestExDriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Tests to see if this driver supports a given controller. If a child devi= ce is provided, + it further tests to see if this driver supports creating a handle for th= e specified child device. + + This function checks to see if the driver specified by This supports the= device specified by + ControllerHandle. Drivers will typically use the device path attached to + ControllerHandle and/or the services from the bus I/O abstraction attach= ed to + ControllerHandle to determine if the driver supports ControllerHandle. T= his function + may be called many times during platform initialization. In order to red= uce boot times, the tests + performed by this function must be very small, and take as little time a= s possible to execute. This + function must not change the state of any hardware devices, and this fun= ction must be aware that the + device specified by ControllerHandle may already be managed by the same = driver or a + different driver. This function must match its calls to AllocatePages() = with FreePages(), + AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol(). + Because ControllerHandle may have been previously started by the same dr= iver, if a protocol is + already in the opened state, then it must not be closed with CloseProtoc= ol(). This is required + to guarantee the state of ControllerHandle is not modified by this funct= ion. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PRO= TOCOL instance. + @param[in] ControllerHandle The handle of the controller to test. T= his handle + must support a protocol interface that = supplies + an I/O abstraction to the driver. + @param[in] RemainingDevicePath A pointer to the remaining portion of a= device path. This + parameter is ignored by device drivers,= and is optional for bus + drivers. For bus drivers, if this param= eter is not NULL, then + the bus driver must determine if the bu= s controller specified + by ControllerHandle and the child contr= oller specified + by RemainingDevicePath are both support= ed by this + bus driver. + + @retval EFI_SUCCESS The device specified by ControllerHandl= e and + RemainingDevicePath is supported by the= driver specified by This. + @retval EFI_ALREADY_STARTED The device specified by ControllerHandl= e and + RemainingDevicePath is already being ma= naged by the driver + specified by This. + @retval EFI_ACCESS_DENIED The device specified by ControllerHandl= e and + RemainingDevicePath is already being ma= naged by a different + driver or an application that requires = exclusive access. + Currently not implemented. + @retval EFI_UNSUPPORTED The device specified by ControllerHandl= e and + RemainingDevicePath is not supported by= the driver specified by This. +**/ +EFI_STATUS +EFIAPI +RedfishRestExDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ); + +/** + Starts a device controller or a bus controller. + + The Start() function is designed to be invoked from the EFI boot service= ConnectController(). + As a result, much of the error checking on the parameters to Start() has= been moved into this + common boot service. It is legal to call Start() from other locations, + but the following calling restrictions must be followed, or the system b= ehavior will not be deterministic. + 1. ControllerHandle must be a valid EFI_HANDLE. + 2. If RemainingDevicePath is not NULL, then it must be a pointer to a na= turally aligned + EFI_DEVICE_PATH_PROTOCOL. + 3. Prior to calling Start(), the Supported() function for the driver spe= cified by This must + have been called with the same calling parameters, and Supported() mu= st have returned EFI_SUCCESS. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PRO= TOCOL instance. + @param[in] ControllerHandle The handle of the controller to start. = This handle + must support a protocol interface that = supplies + an I/O abstraction to the driver. + @param[in] RemainingDevicePath A pointer to the remaining portion of a= device path. This + parameter is ignored by device drivers,= and is optional for bus + drivers. For a bus driver, if this para= meter is NULL, then handles + for all the children of Controller are = created by this driver. + If this parameter is not NULL and the f= irst Device Path Node is + not the End of Device Path Node, then o= nly the handle for the + child device specified by the first Dev= ice Path Node of + RemainingDevicePath is created by this = driver. + If the first Device Path Node of Remain= ingDevicePath is + the End of Device Path Node, no child h= andle is created by this + driver. + + @retval EFI_SUCCESS The device was started. + @retval EFI_DEVICE_ERROR The device could not be started due to = a device error.Currently not implemented. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due = to a lack of resources. + @retval Others The driver failded to start the device. + +**/ +EFI_STATUS +EFIAPI +RedfishRestExDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ); + +/** + Stops a device controller or a bus controller. + + The Stop() function is designed to be invoked from the EFI boot service = DisconnectController(). + As a result, much of the error checking on the parameters to Stop() has = been moved + into this common boot service. It is legal to call Stop() from other loc= ations, + but the following calling restrictions must be followed, or the system b= ehavior will not be deterministic. + 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previo= us call to this + same driver's Start() function. + 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a= valid + EFI_HANDLE. In addition, all of these handles must have been created = in this driver's + Start() function, and the Start() function must have called OpenProto= col() on + ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONT= ROLLER. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOC= OL instance. + @param[in] ControllerHandle A handle to the device being stopped. The = handle must + support a bus specific I/O protocol for th= e driver + to use to stop the device. + @param[in] NumberOfChildren The number of child device handles in Chil= dHandleBuffer. + @param[in] ChildHandleBuffer An array of child handles to be freed. May= be NULL + if NumberOfChildren is 0. + + @retval EFI_SUCCESS The device was stopped. + @retval EFI_DEVICE_ERROR The device could not be stopped due to a d= evice error. + +**/ +EFI_STATUS +EFIAPI +RedfishRestExDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer OPTIONAL + ); + +/** + Creates a child handle and installs a protocol. + + The CreateChild() function installs a protocol on ChildHandle. + If ChildHandle is a pointer to NULL, then a new handle is created and re= turned in ChildHandle. + If ChildHandle is not a pointer to NULL, then the protocol installs on t= he existing ChildHandle. + + @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL insta= nce. + @param[in] ChildHandle Pointer to the handle of the child to create. If = it is NULL, + then a new handle is created. If it is a pointer = to an existing UEFI handle, + then the protocol is added to the existing UEFI h= andle. + + @retval EFI_SUCCES The protocol was added to ChildHandle. + @retval EFI_INVALID_PARAMETER ChildHandle is NULL. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available t= o create + the child + @retval other The child handle was not created + +**/ +EFI_STATUS +EFIAPI +RedfishRestExServiceBindingCreateChild ( + IN EFI_SERVICE_BINDING_PROTOCOL *This, + IN EFI_HANDLE *ChildHandle + ); + +/** + Destroys a child handle with a protocol installed on it. + + The DestroyChild() function does the opposite of CreateChild(). It remov= es a protocol + that was installed by CreateChild() from ChildHandle. If the removed pro= tocol is the + last protocol on ChildHandle, then ChildHandle is destroyed. + + @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL insta= nce. + @param[in] ChildHandle Handle of the child to destroy + + @retval EFI_SUCCES The protocol was removed from ChildHandle. + @retval EFI_UNSUPPORTED ChildHandle does not support the protocol = that is being removed. + @retval EFI_INVALID_PARAMETER Child handle is NULL. + @retval EFI_ACCESS_DENIED The protocol could not be removed from the= ChildHandle + because its services are being used. + @retval other The child handle was not destroyed + +**/ +EFI_STATUS +EFIAPI +RedfishRestExServiceBindingDestroyChild ( + IN EFI_SERVICE_BINDING_PROTOCOL *This, + IN EFI_HANDLE ChildHandle + ); +#endif diff --git a/RedfishPkg/RedfishRestExDxe/RedfishRestExProtocol.c b/RedfishP= kg/RedfishRestExDxe/RedfishRestExProtocol.c new file mode 100644 index 0000000000..65a5fe3713 --- /dev/null +++ b/RedfishPkg/RedfishRestExDxe/RedfishRestExProtocol.c @@ -0,0 +1,735 @@ +/** @file + Implementation of Redfish EFI_REST_EX_PROTOCOL interfaces. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include +#include "RedfishRestExInternal.h" + +EFI_REST_EX_PROTOCOL mRedfishRestExProtocol =3D { + RedfishRestExSendReceive, + RedfishRestExGetServiceTime, + RedfishRestExGetService, + RedfishRestExGetModeData, + RedfishRestExConfigure, + RedfishRestExAyncSendReceive, + RedfishRestExEventService +}; + +/** + Provides a simple HTTP-like interface to send and receive resources from= a REST service. + + The SendReceive() function sends an HTTP request to this REST service, a= nd returns a + response when the data is retrieved from the service. RequestMessage con= tains the HTTP + request to the REST resource identified by RequestMessage.Request.Url. T= he + ResponseMessage is the returned HTTP response for that request, includin= g any HTTP + status. + + @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance= for a particular + REST service. + @param[in] RequestMessage Pointer to the HTTP request data for thi= s resource + @param[out] ResponseMessage Pointer to the HTTP response data obtain= ed for this requested. + + @retval EFI_SUCCESS operation succeeded. + @retval EFI_INVALID_PARAMETER This, RequestMessage, or ResponseMessage= are NULL. + @retval EFI_DEVICE_ERROR An unexpected system or network error oc= curred. + @retval EFI_ACCESS_DENIED HTTP method is not allowed on this URL. + @retval EFI_BAD_BUFFER_SIZE The payload is to large to be handled on= server side. + @retval EFI_UNSUPPORTED Unsupported HTTP response. + +**/ +EFI_STATUS +EFIAPI +RedfishRestExSendReceive ( + IN EFI_REST_EX_PROTOCOL *This, + IN EFI_HTTP_MESSAGE *RequestMessage, + OUT EFI_HTTP_MESSAGE *ResponseMessage + ) +{ + EFI_STATUS Status; + RESTEX_INSTANCE *Instance; + HTTP_IO_RESPONSE_DATA *ResponseData; + UINTN TotalReceivedSize; + UINTN Index; + LIST_ENTRY *ChunkListLink; + HTTP_IO_CHUNKS *ThisChunk; + BOOLEAN CopyChunkData; + BOOLEAN MediaPresent; + EFI_HTTP_HEADER *PreservedRequestHeaders; + BOOLEAN ItsWrite; + BOOLEAN IsGetChunkedTransfer; + HTTP_IO_SEND_CHUNK_PROCESS SendChunkProcess; + HTTP_IO_SEND_NON_CHUNK_PROCESS SendNonChunkProcess; + EFI_HTTP_MESSAGE ChunkTransferRequestMessage; + + Status =3D EFI_SUCCESS; + ResponseData =3D NULL; + IsGetChunkedTransfer =3D FALSE; + SendChunkProcess =3D HttpIoSendChunkNone; + SendNonChunkProcess =3D HttpIoSendNonChunkNone; + + // + // Validate the parameters + // + if ((This =3D=3D NULL) || (RequestMessage =3D=3D NULL) || ResponseMessag= e =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + Instance =3D RESTEX_INSTANCE_FROM_THIS (This); + + // + // Check Media Status. + // + MediaPresent =3D TRUE; + NetLibDetectMedia (Instance->Service->ControllerHandle, &MediaPresent); + if (!MediaPresent) { + DEBUG ((DEBUG_INFO, "RedfishRestExSendReceive(): No MediaPresent.\n")); + return EFI_NO_MEDIA; + } + + DEBUG ((DEBUG_INFO, "\nRedfishRestExSendReceive():\n")); + DEBUG ((DEBUG_INFO, "*** Perform HTTP Request Method - %d, URL: %s\n", R= equestMessage->Data.Request->Method, RequestMessage->Data.Request->Url)); + + // + // Add header "Expect" to server, only for URL write. + // + Status =3D RedfishHttpAddExpectation (This, RequestMessage, &PreservedRe= questHeaders, &ItsWrite); + if (EFI_ERROR (Status)) { + return Status; + } + if (ItsWrite =3D=3D TRUE) { + if (RequestMessage->BodyLength > HTTP_IO_MAX_SEND_PAYLOAD) { + // + // Send chunked transfer. + // + SendChunkProcess ++; + CopyMem ((VOID *)&ChunkTransferRequestMessage, (VOID *)RequestMessag= e, sizeof (EFI_HTTP_MESSAGE)); + } else { + SendNonChunkProcess ++; + } + } +ReSendRequest:; + // + // Send out the request to REST service. + // + if (ItsWrite =3D=3D TRUE) { + // + // This is write to URI + // + if (SendChunkProcess > HttpIoSendChunkNone) { + // + // This is chunk transfer for writing large payload. + // Send request header first and then handle the + // following request message body using chunk transfer. + // + do { + Status =3D HttpIoSendChunkedTransfer( + &(Instance->HttpIo), + &SendChunkProcess, + &ChunkTransferRequestMessage + ); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + } while (SendChunkProcess =3D=3D HttpIoSendChunkContent || SendChunk= Process =3D=3D HttpIoSendChunkEndChunk); + } else { + // + // This is the non-chunk transfer, send request header first and then + // handle the following request message body using chunk transfer. + // + Status =3D HttpIoSendRequest( + &(Instance->HttpIo), + (SendNonChunkProcess =3D=3D HttpIoSendNonChunkContent)? N= ULL: RequestMessage->Data.Request, + (SendNonChunkProcess =3D=3D HttpIoSendNonChunkContent)? 0= : RequestMessage->HeaderCount, + (SendNonChunkProcess =3D=3D HttpIoSendNonChunkContent)? N= ULL: RequestMessage->Headers, + (SendNonChunkProcess =3D=3D HttpIoSendNonChunkHeaderZeroC= ontent)? 0: RequestMessage->BodyLength, + (SendNonChunkProcess =3D=3D HttpIoSendNonChunkHeaderZeroC= ontent)? NULL: RequestMessage->Body + ); + } + } else { + // + // This is read from URI. + // + Status =3D HttpIoSendRequest( + &(Instance->HttpIo), + RequestMessage->Data.Request, + RequestMessage->HeaderCount, + RequestMessage->Headers, + RequestMessage->BodyLength, + RequestMessage->Body + ); + } + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + // + // ResponseMessage->Data.Response is to indicate whether to receive the = HTTP header or not. + // ResponseMessage->BodyLength/ResponseMessage->Body are to indicate whe= ther to receive the response body or not. + // Clean the previous buffers and all of them will be allocated later ac= cording to the actual situation. + // + if (ResponseMessage->Data.Response !=3D NULL) { + FreePool(ResponseMessage->Data.Response); + ResponseMessage->Data.Response =3D NULL; + } + + ResponseMessage->BodyLength =3D 0; + if (ResponseMessage->Body !=3D NULL) { + FreePool(ResponseMessage->Body); + ResponseMessage->Body =3D NULL; + } + + // + // Use zero BodyLength to only receive the response headers. + // + ResponseData =3D AllocateZeroPool (sizeof(HTTP_IO_RESPONSE_DATA)); + if (ResponseData =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + DEBUG ((DEBUG_INFO, "Receiving HTTP response and headers...\n")); + Status =3D RedfishCheckHttpReceiveStatus ( + Instance, + HttpIoRecvResponse ( + &(Instance->HttpIo), + TRUE, + ResponseData + ) + ); + if (Status =3D=3D EFI_NOT_READY) { + goto ReSendRequest; + } else if (Status =3D=3D EFI_DEVICE_ERROR) { + goto ON_EXIT; + } + // + // Restore the headers if it ever changed in RedfishHttpAddExpectation(). + // + if (RequestMessage->Headers !=3D PreservedRequestHeaders) { + FreePool (RequestMessage->Headers); + RequestMessage->Headers =3D PreservedRequestHeaders; // Restore header= s before we adding "Expect". + RequestMessage->HeaderCount --; // Minus one header= count for "Expect". + } + + DEBUG ((DEBUG_INFO, "HTTP Response StatusCode - %d:", ResponseData->Resp= onse.StatusCode)); + if (ResponseData->Response.StatusCode =3D=3D HTTP_STATUS_200_OK) { + DEBUG ((DEBUG_INFO, "HTTP_STATUS_200_OK\n")); + + if (SendChunkProcess =3D=3D HttpIoSendChunkHeaderZeroContent) { + DEBUG ((DEBUG_INFO, "This is chunk transfer, start to send all chunk= s.", ResponseData->Response.StatusCode)); + SendChunkProcess ++; + goto ReSendRequest; + } + } else if (ResponseData->Response.StatusCode =3D=3D HTTP_STATUS_413_REQU= EST_ENTITY_TOO_LARGE) { + DEBUG ((DEBUG_INFO, "HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE\n")); + + Status =3D EFI_BAD_BUFFER_SIZE; + goto ON_EXIT; + } else if (ResponseData->Response.StatusCode =3D=3D HTTP_STATUS_405_METH= OD_NOT_ALLOWED){ + DEBUG ((DEBUG_ERROR, "HTTP_STATUS_405_METHOD_NOT_ALLOWED\n")); + + Status =3D EFI_ACCESS_DENIED; + goto ON_EXIT; + } else if (ResponseData->Response.StatusCode =3D=3D HTTP_STATUS_400_BAD_= REQUEST) { + DEBUG ((DEBUG_INFO, "HTTP_STATUS_400_BAD_REQUEST\n")); + if (SendChunkProcess =3D=3D HttpIoSendChunkHeaderZeroContent) { + DEBUG ((DEBUG_INFO, "Bad request may caused by zero length chunk. Tr= y to send all chunks...\n")); + SendChunkProcess ++; + goto ReSendRequest; + } + } else if (ResponseData->Response.StatusCode =3D=3D HTTP_STATUS_100_CONT= INUE) { + DEBUG ((DEBUG_INFO, "HTTP_STATUS_100_CONTINUE\n")); + if (SendChunkProcess =3D=3D HttpIoSendChunkHeaderZeroContent) { + // + // We get HTTP_STATUS_100_CONTINUE to send the body using chunk tran= sfer. + // + DEBUG ((DEBUG_INFO, "HTTP_STATUS_100_CONTINUE for chunk transfer...\= n")); + SendChunkProcess ++; + goto ReSendRequest; + } + if (SendNonChunkProcess =3D=3D HttpIoSendNonChunkHeaderZeroContent) { + DEBUG ((DEBUG_INFO, "HTTP_STATUS_100_CONTINUE for non chunk transfer= ...\n")); + SendNonChunkProcess ++; + goto ReSendRequest; + } + // + // It's the REST protocol's responsibility to handle the interim HTTP = response (e.g. 100 Continue Informational), + // and return the final response content to the caller. + // + if (ResponseData->Headers !=3D NULL && ResponseData->HeaderCount !=3D = 0) { + FreePool (ResponseData->Headers); + } + ZeroMem (ResponseData, sizeof(HTTP_IO_RESPONSE_DATA)); + Status =3D HttpIoRecvResponse ( + &(Instance->HttpIo), + TRUE, + ResponseData + ); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + } else { + DEBUG ((DEBUG_ERROR, "This HTTP Status is not handled!\n")); + Status =3D EFI_UNSUPPORTED; + goto ON_EXIT; + } + + // + // Ready to return the StatusCode, Header info and BodyLength. + // + ResponseMessage->Data.Response =3D AllocateZeroPool (sizeof (EFI_HTTP_RE= SPONSE_DATA)); + if (ResponseMessage->Data.Response =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + ResponseMessage->Data.Response->StatusCode =3D ResponseData->Response.St= atusCode; + ResponseMessage->HeaderCount =3D ResponseData->HeaderCount; + ResponseMessage->Headers =3D ResponseData->Headers; + + // + // Get response message body. + // + if (ResponseMessage->HeaderCount > 0) { + Status =3D HttpIoGetContentLength (ResponseMessage->HeaderCount, Respo= nseMessage->Headers, &ResponseMessage->BodyLength); + if (EFI_ERROR (Status) && Status !=3D EFI_NOT_FOUND) { + goto ON_EXIT; + } + + if (Status =3D=3D EFI_NOT_FOUND) { + ASSERT (ResponseMessage->BodyLength =3D=3D 0); + } + + if (ResponseMessage->BodyLength =3D=3D 0) { + // + // Check if Chunked Transfer Coding. + // + Status =3D HttpIoGetChunkedTransferContent ( + &(Instance->HttpIo), + ResponseMessage->HeaderCount, + ResponseMessage->Headers, + &ChunkListLink, + &ResponseMessage->BodyLength + ); + if (EFI_ERROR (Status) && Status !=3D EFI_NOT_FOUND) { + goto ON_EXIT; + } + if (Status =3D=3D EFI_SUCCESS && + ChunkListLink !=3D NULL && + !IsListEmpty(ChunkListLink) && + ResponseMessage->BodyLength !=3D 0) { + IsGetChunkedTransfer =3D TRUE; + // + // Copy data to Message body. + // + CopyChunkData =3D TRUE; + ResponseMessage->Body =3D AllocateZeroPool (ResponseMessage->BodyL= ength); + if (ResponseMessage->Body =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + CopyChunkData =3D FALSE; + } + Index =3D 0; + while (!IsListEmpty(ChunkListLink)) { + ThisChunk =3D (HTTP_IO_CHUNKS *)GetFirstNode (ChunkListLink); + if (CopyChunkData) { + CopyMem(((UINT8 *)ResponseMessage->Body + Index), (UINT8 *)Thi= sChunk->Data, ThisChunk->Length); + Index +=3D ThisChunk->Length; + } + RemoveEntryList (&ThisChunk->NextChunk); + FreePool ((VOID *)ThisChunk->Data); + FreePool ((VOID *)ThisChunk); + }; + FreePool ((VOID *)ChunkListLink); + } + } + Status =3D EFI_SUCCESS; + } + + // + // Ready to return the Body from REST service if have any. + // + if (ResponseMessage->BodyLength > 0 && !IsGetChunkedTransfer) { + ResponseData->HeaderCount =3D 0; + ResponseData->Headers =3D NULL; + + ResponseMessage->Body =3D AllocateZeroPool (ResponseMessage->BodyLengt= h); + if (ResponseMessage->Body =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + // + // Only receive the Body. + // + TotalReceivedSize =3D 0; + while (TotalReceivedSize < ResponseMessage->BodyLength) { + ResponseData->BodyLength =3D ResponseMessage->BodyLength - TotalRece= ivedSize; + ResponseData->Body =3D (CHAR8 *) ResponseMessage->Body + TotalReceiv= edSize; + Status =3D HttpIoRecvResponse ( + &(Instance->HttpIo), + FALSE, + ResponseData + ); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + TotalReceivedSize +=3D ResponseData->BodyLength; + } + DEBUG ((DEBUG_INFO, "Total of lengh of Response :%d\n", TotalReceivedS= ize)); + } + DEBUG ((DEBUG_INFO, "RedfishRestExSendReceive()- EFI_STATUS: %r\n", Stat= us)); + +ON_EXIT: + + if (ResponseData !=3D NULL) { + FreePool (ResponseData); + } + + if (EFI_ERROR (Status)) { + if (ResponseMessage->Data.Response !=3D NULL) { + FreePool (ResponseMessage->Data.Response); + ResponseMessage->Data.Response =3D NULL; + } + + if (ResponseMessage->Body !=3D NULL) { + FreePool (ResponseMessage->Body); + ResponseMessage->Body =3D NULL; + } + } + return Status; +} + +/** + Obtain the current time from this REST service instance. + + The GetServiceTime() function is an optional interface to obtain the cur= rent time from + this REST service instance. If this REST service does not support to ret= rieve the time, + this function returns EFI_UNSUPPORTED. This function must returns EFI_UN= SUPPORTED if + EFI_REST_EX_SERVICE_TYPE returned in EFI_REST_EX_SERVICE_INFO from GetSe= rvice() is + EFI_REST_EX_SERVICE_UNSPECIFIC. + + @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance= for a particular + REST service. + @param[out] Time A pointer to storage to receive a snapsh= ot of the current time of + the REST service. + + @retval EFI_SUCCESS operation succeeded. + @retval EFI_INVALID_PARAMETER This or Time are NULL. + @retval EFI_UNSUPPORTED The RESTful service does not support ret= urning the time. + @retval EFI_DEVICE_ERROR An unexpected system or network error oc= curred. + @retval EFI_NOT_READY The configuration of this instance is no= t set yet. Configure() must + be executed and returns successfully pri= or to invoke this function. + +**/ +EFI_STATUS +EFIAPI +RedfishRestExGetServiceTime ( + IN EFI_REST_EX_PROTOCOL *This, + OUT EFI_TIME *Time + ) +{ + return EFI_UNSUPPORTED; +} + +/** + This function returns the information of REST service provided by this E= FI REST EX driver instance. + + The information such as the type of REST service and the access mode of = REST EX driver instance + (In-band or Out-of-band) are described in EFI_REST_EX_SERVICE_INFO struc= ture. For the vendor-specific + REST service, vendor-specific REST service information is returned in Ve= ndorSpecifcData. + REST EX driver designer is well know what REST service this REST EX driv= er instance intends to + communicate with. The designer also well know this driver instance is us= ed to talk to BMC through + specific platform mechanism or talk to REST server through UEFI HTTP pro= tocol. REST EX driver is + responsible to fill up the correct information in EFI_REST_EX_SERVICE_IN= FO. EFI_REST_EX_SERVICE_INFO + is referred by EFI REST clients to pickup the proper EFI REST EX driver = instance to get and set resource. + GetService() is a basic and mandatory function which must be able to use= even Configure() is not invoked + in previously. + + @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance= for a particular + REST service. + @param[out] RestExServiceInfo Pointer to receive a pointer to EFI_REST= _EX_SERVICE_INFO structure. The + format of EFI_REST_EX_SERVICE_INFO is ve= rsion controlled for the future + extension. The version of EFI_REST_EX_SE= RVICE_INFO structure is returned + in the header within this structure. EFI= REST client refers to the correct + format of structure according to the ver= sion number. The pointer to + EFI_REST_EX_SERVICE_INFO is a memory blo= ck allocated by EFI REST EX driver + instance. That is caller's responsibilit= y to free this memory when this + structure is no longer needed. Refer to = Related Definitions below for the + definitions of EFI_REST_EX_SERVICE_INFO = structure. + + @retval EFI_SUCCESS EFI_REST_EX_SERVICE_INFO is returned in = RestExServiceInfo. This function + is not supported in this REST EX Protoco= l driver instance. + @retval EFI_UNSUPPORTED This function is not supported in this R= EST EX Protocol driver instance. + +**/ +EFI_STATUS +EFIAPI +RedfishRestExGetService ( + IN EFI_REST_EX_PROTOCOL *This, + OUT EFI_REST_EX_SERVICE_INFO **RestExServiceInfo + ) +{ + EFI_TPL OldTpl; + RESTEX_INSTANCE *Instance; + EFI_REST_EX_SERVICE_INFO *ServiceInfo; + + ServiceInfo =3D NULL; + + if (This =3D=3D NULL || RestExServiceInfo =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + OldTpl =3D gBS->RaiseTPL (TPL_CALLBACK); + + Instance =3D RESTEX_INSTANCE_FROM_THIS (This); + + ServiceInfo =3D AllocateZeroPool (sizeof (EFI_REST_EX_SERVICE_INFO)); + if (ServiceInfo =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + CopyMem (ServiceInfo, &(Instance->Service->RestExServiceInfo), sizeof (E= FI_REST_EX_SERVICE_INFO)); + + *RestExServiceInfo =3D ServiceInfo; + + gBS->RestoreTPL (OldTpl); + + return EFI_SUCCESS; +} + +/** + This function returns operational configuration of current EFI REST EX c= hild instance. + + This function returns the current configuration of EFI REST EX child ins= tance. The format of + operational configuration depends on the implementation of EFI REST EX d= river instance. For + example, HTTP-aware EFI REST EX driver instance uses EFI HTTP protocol a= s the undying protocol + to communicate with REST service. In this case, the type of configuratio= n is + EFI_REST_EX_CONFIG_TYPE_HTTP returned from GetService(). EFI_HTTP_CONFIG= _DATA is used as EFI REST + EX configuration format and returned to EFI REST client. User has to typ= e cast RestExConfigData + to EFI_HTTP_CONFIG_DATA. For those non HTTP-aware REST EX driver instanc= es, the type of configuration + is EFI_REST_EX_CONFIG_TYPE_UNSPECIFIC returned from GetService(). In thi= s case, the format of + returning data could be non industrial. Instead, the format of configura= tion data is system/platform + specific definition such as BMC mechanism used in EFI REST EX driver ins= tance. EFI REST client and + EFI REST EX driver instance have to refer to the specific system /platfo= rm spec which is out of UEFI scope. + + @param[in] This This is the EFI_REST_EX_PROTOCOL instanc= e. + @param[out] RestExConfigData Pointer to receive a pointer to EFI_REST= _EX_CONFIG_DATA. + The memory allocated for configuration d= ata should be freed + by caller. See Related Definitions for t= he details. + + @retval EFI_SUCCESS EFI_REST_EX_CONFIG_DATA is returned in s= uccessfully. + @retval EFI_UNSUPPORTED This function is not supported in this R= EST EX Protocol driver instance. + @retval EFI_NOT_READY The configuration of this instance is no= t set yet. Configure() must be + executed and returns successfully prior = to invoke this function. + +**/ +EFI_STATUS +EFIAPI +RedfishRestExGetModeData ( + IN EFI_REST_EX_PROTOCOL *This, + OUT EFI_REST_EX_CONFIG_DATA *RestExConfigData + ) +{ + return EFI_UNSUPPORTED; +} + +/** + This function is used to configure EFI REST EX child instance. + + This function is used to configure the setting of underlying protocol of= REST EX child + instance. The type of configuration is according to the implementation o= f EFI REST EX + driver instance. For example, HTTP-aware EFI REST EX driver instance use= s EFI HTTP protocol + as the undying protocol to communicate with REST service. The type of co= nfiguration is + EFI_REST_EX_CONFIG_TYPE_HTTP and RestExConfigData is the same format wit= h EFI_HTTP_CONFIG_DATA. + Akin to HTTP configuration, REST EX child instance can be configure to u= se different HTTP + local access point for the data transmission. Multiple REST clients may = use different + configuration of HTTP to distinguish themselves, such as to use the diff= erent TCP port. + For those non HTTP-aware REST EX driver instance, the type of configurat= ion is + EFI_REST_EX_CONFIG_TYPE_UNSPECIFIC. RestExConfigData refers to the non i= ndustrial standard. + Instead, the format of configuration data is system/platform specific de= finition such as BMC. + In this case, EFI REST client and EFI REST EX driver instance have to re= fer to the specific + system/platform spec which is out of the UEFI scope. Besides GetService(= )function, no other + EFI REST EX functions can be executed by this instance until Configure()= is executed and returns + successfully. All other functions must returns EFI_NOT_READY if this ins= tance is not configured + yet. Set RestExConfigData to NULL means to put EFI REST EX child instanc= e into the unconfigured + state. + + @param[in] This This is the EFI_REST_EX_PROTOCOL instanc= e. + @param[in] RestExConfigData Pointer to EFI_REST_EX_CONFIG_DATA. See = Related Definitions in + GetModeData() protocol interface. + + @retval EFI_SUCCESS EFI_REST_EX_CONFIG_DATA is set in succes= sfully. + @retval EFI_DEVICE_ERROR Configuration for this REST EX child ins= tance is failed with the given + EFI_REST_EX_CONFIG_DATA. + @retval EFI_UNSUPPORTED This function is not supported in this R= EST EX Protocol driver instance. + +**/ +EFI_STATUS +EFIAPI +RedfishRestExConfigure ( + IN EFI_REST_EX_PROTOCOL *This, + IN EFI_REST_EX_CONFIG_DATA RestExConfigData + ) +{ + EFI_STATUS Status; + EFI_TPL OldTpl; + RESTEX_INSTANCE *Instance; + + EFI_HTTP_CONFIG_DATA *HttpConfigData; + + Status =3D EFI_SUCCESS; + HttpConfigData =3D NULL; + + if (This =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + OldTpl =3D gBS->RaiseTPL (TPL_CALLBACK); + + Instance =3D RESTEX_INSTANCE_FROM_THIS (This); + + if (RestExConfigData =3D=3D NULL) { + // + // Set RestExConfigData to NULL means to put EFI REST EX child instanc= e into the unconfigured state. + // + HttpIoDestroyIo (&(Instance->HttpIo)); + + if (Instance->ConfigData !=3D NULL) { + if (((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConf= igData.AccessPoint.IPv4Node !=3D NULL) { + FreePool(((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->H= ttpConfigData.AccessPoint.IPv4Node); + } + FreePool(Instance->ConfigData); + Instance->ConfigData =3D NULL; + } + + Instance->State =3D RESTEX_STATE_UNCONFIGED; + } else { + HttpConfigData =3D &((EFI_REST_EX_HTTP_CONFIG_DATA *)RestExConfigData)= ->HttpConfigData; + Status =3D Instance->HttpIo.Http->Configure (Instance->HttpIo.Http, Ht= tpConfigData); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + Instance->HttpIo.Timeout =3D ((EFI_REST_EX_HTTP_CONFIG_DATA *)RestExCo= nfigData)->SendReceiveTimeout; + + Instance->ConfigData =3D AllocateZeroPool (sizeof (EFI_REST_EX_HTTP_CO= NFIG_DATA)); + if (Instance->ConfigData =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + CopyMem (Instance->ConfigData, RestExConfigData, sizeof (EFI_REST_EX_H= TTP_CONFIG_DATA)); + if (HttpConfigData->LocalAddressIsIPv6 =3D=3D TRUE) { + ((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConfigDa= ta.AccessPoint.IPv6Node =3D AllocateZeroPool (sizeof (EFI_HTTPv6_ACCESS_POI= NT)); + if (((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConf= igData.AccessPoint.IPv6Node =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + CopyMem ( + ((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConfig= Data.AccessPoint.IPv6Node, + HttpConfigData->AccessPoint.IPv6Node, + sizeof (EFI_HTTPv6_ACCESS_POINT) + ); + } else { + ((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConfigDa= ta.AccessPoint.IPv4Node =3D AllocateZeroPool (sizeof (EFI_HTTPv4_ACCESS_POI= NT)); + if (((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConf= igData.AccessPoint.IPv4Node =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + CopyMem ( + ((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConfig= Data.AccessPoint.IPv4Node, + HttpConfigData->AccessPoint.IPv4Node, + sizeof (EFI_HTTPv4_ACCESS_POINT) + ); + } + Instance->State =3D RESTEX_STATE_CONFIGED; + } + +ON_EXIT: + gBS->RestoreTPL (OldTpl); + return Status; +} + +/** + This function sends REST request to REST service and signal caller's eve= nt asynchronously when + the final response is received by REST EX Protocol driver instance. + + The essential design of this function is to handle asynchronous send/rec= eive implicitly according + to REST service asynchronous request mechanism. Caller will get the noti= fication once the response + is returned from REST service. + + @param[in] This This is the EFI_REST_EX_PROTOCOL insta= nce. + @param[in] RequestMessage This is the HTTP request message sent = to REST service. Set RequestMessage + to NULL to cancel the previous asynchr= onous request associated with the + corresponding RestExToken. See descrip= tions for the details. + @param[in] RestExToken REST EX token which REST EX Protocol i= nstance uses to notify REST client + the status of response of asynchronous= REST request. See related definition + of EFI_REST_EX_TOKEN. + @param[in] TimeOutInMilliSeconds The pointer to the timeout in millisec= onds which REST EX Protocol driver + instance refers as the duration to dro= p asynchronous REST request. NULL + pointer means no timeout for this REST= request. REST EX Protocol driver + signals caller's event with EFI_STATUS= set to EFI_TIMEOUT in RestExToken + if REST EX Protocol can't get the resp= onse from REST service within + TimeOutInMilliSeconds. + + @retval EFI_SUCCESS Asynchronous REST request is establish= ed. + @retval EFI_UNSUPPORTED This REST EX Protocol driver instance = doesn't support asynchronous request. + @retval EFI_TIMEOUT Asynchronous REST request is not estab= lished and timeout is expired. + @retval EFI_ABORT Previous asynchronous REST request has= been canceled. + @retval EFI_DEVICE_ERROR Otherwise, returns EFI_DEVICE_ERROR fo= r other errors according to HTTP Status Code. + @retval EFI_NOT_READY The configuration of this instance is = not set yet. Configure() must be executed + and returns successfully prior to invo= ke this function. + +**/ +EFI_STATUS +EFIAPI +RedfishRestExAyncSendReceive ( + IN EFI_REST_EX_PROTOCOL *This, + IN EFI_HTTP_MESSAGE *RequestMessage OPTIONAL, + IN EFI_REST_EX_TOKEN *RestExToken, + IN UINTN *TimeOutInMilliSeconds OPTIONAL + ) +{ + return EFI_UNSUPPORTED; +} + +/** + This function sends REST request to a REST Event service and signals cal= ler's event + token asynchronously when the URI resource change event is received by R= EST EX + Protocol driver instance. + + The essential design of this function is to monitor event implicitly acc= ording to + REST service event service mechanism. Caller will get the notification i= f certain + resource is changed. + + @param[in] This This is the EFI_REST_EX_PROTOCOL insta= nce. + @param[in] RequestMessage This is the HTTP request message sent = to REST service. Set RequestMessage + to NULL to cancel the previous event s= ervice associated with the corresponding + RestExToken. See descriptions for the = details. + @param[in] RestExToken REST EX token which REST EX Protocol d= river instance uses to notify REST client + the URI resource which monitored by RE= ST client has been changed. See the related + definition of EFI_REST_EX_TOKEN in EFI= _REST_EX_PROTOCOL.AsyncSendReceive(). + + @retval EFI_SUCCESS Asynchronous REST request is establish= ed. + @retval EFI_UNSUPPORTED This REST EX Protocol driver instance = doesn't support asynchronous request. + @retval EFI_ABORT Previous asynchronous REST request has= been canceled or event subscription has been + delete from service. + @retval EFI_DEVICE_ERROR Otherwise, returns EFI_DEVICE_ERROR fo= r other errors according to HTTP Status Code. + @retval EFI_NOT_READY The configuration of this instance is = not set yet. Configure() must be executed + and returns successfully prior to invo= ke this function. + +**/ +EFI_STATUS +EFIAPI +RedfishRestExEventService ( + IN EFI_REST_EX_PROTOCOL *This, + IN EFI_HTTP_MESSAGE *RequestMessage OPTIONAL, + IN EFI_REST_EX_TOKEN *RestExToken + ) +{ + return EFI_UNSUPPORTED; +} + --=20 2.17.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#68377): https://edk2.groups.io/g/devel/message/68377 Mute This Topic: https://groups.io/mt/78773779/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-