From nobody Fri Apr 19 21:03:55 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+73308+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+73308+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=hpe.com ARC-Seal: i=1; a=rsa-sha256; t=1616737529; cv=none; d=zohomail.com; s=zohoarc; b=S7A1Z1NwObXaENEGwAC3uZxvyyqUbk06D2sbeG7xlgwbG7TSWfEk+na7TVXrdOT5WJUi/s4YRnrUBMEew6md92eiQS8H9uz9yeqRz7cld9OprLNEj4yZ/TGY8Xb0xqb4HmQHACe5d466ULI6TIdy9ej8nMVLggNQfcQWdw/zflM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1616737529; h=Cc:Date:From:List-Subscribe:List-Id:List-Help:List-Unsubscribe:Message-ID:Reply-To:Sender:Subject:To; bh=TppkmC4fMkjD8T8d/R9T/MyM/vIHa6kVH6P9DFEMr6A=; b=AgLjZUfKKy87H2Lhe8g/7OLmLdtJKq0n0lHpuKXtZ+4/nsy018ETGe+ptAThssyMhghY8OaqgjzaJt3GIT4FABwS2KqYdprxrjbV2qVA1pWynmCwxY7LK+q9qxwKzBu0A2t/o5PDW5ypoJ58iHYgHdyS+MhrnLfhzu5z5SvbjVg= 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+73308+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 1616737529479627.8346248866118; Thu, 25 Mar 2021 22:45:29 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id lRyqYY1788612xauFApSzUeW; Thu, 25 Mar 2021 22:45:29 -0700 X-Received: from mx0a-002e3701.pphosted.com (mx0a-002e3701.pphosted.com [148.163.147.86]) by mx.groups.io with SMTP id smtpd.web10.8769.1616737523187449141 for ; Thu, 25 Mar 2021 22:45:23 -0700 X-Received: from pps.filterd (m0148663.ppops.net [127.0.0.1]) by mx0a-002e3701.pphosted.com (8.16.0.43/8.16.0.43) with SMTP id 12Q5ia2p030563; Fri, 26 Mar 2021 05:45:22 GMT X-Received: from g2t2353.austin.hpe.com (g2t2353.austin.hpe.com [15.233.44.26]) by mx0a-002e3701.pphosted.com with ESMTP id 37h13w32nw-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 26 Mar 2021 05:45:22 +0000 X-Received: from g2t2360.austin.hpecorp.net (g2t2360.austin.hpecorp.net [16.196.225.135]) by g2t2353.austin.hpe.com (Postfix) with ESMTP id 40F9065; Fri, 26 Mar 2021 05:45:21 +0000 (UTC) X-Received: from abner-virtual-machine.asiapacific.hpqcorp.net (abner-virtual-machine.asiapacific.hpqcorp.net [15.119.210.153]) by g2t2360.austin.hpecorp.net (Postfix) with ESMTP id 766C836; Fri, 26 Mar 2021 05:45:19 +0000 (UTC) From: "Abner Chang" To: devel@edk2.groups.io Cc: Nickle Wang , Jiaxin Wu , Siyuan Fu , Fan Wang , Jiewen Yao Subject: [edk2-devel] [PATCH] RedfishPkg/RedfishDiscoverDxe: EFI Redfish Discover Protocol Date: Fri, 26 Mar 2021 12:54:10 +0800 Message-Id: <20210326045410.21800-1-abner.chang@hpe.com> X-Proofpoint-ORIG-GUID: xCSsgxjotnPoBi5DI34MUQ7PSg34CoS8 X-Proofpoint-GUID: xCSsgxjotnPoBi5DI34MUQ7PSg34CoS8 X-HPE-SCL: -1 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: 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: Ktp2Ip2MH7ZZIUHWMnle9bqkx1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1616737529; bh=xJNB5ozLq4AJMDk6TORxEyXvuAEjRf3tZS9Miie0IPg=; h=Cc:Date:From:Reply-To:Subject:To; b=q3PKv27oCZDdC3UkuVUZbMESuhGKfy8Xa4gdN+1GIMX0tQ36Z7uWrPndbKEZQg71d0Y EtQUBkd8HQt8JB2TefRVzcVFHUcKK0/cl4oIw8Z4tpENz2f5a2TZ2VOL+YJoqD9uX8hoh 1/6eCTFiBVT8Kz3V45jpMH/hKtCvR7q2ytQ= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" EDK2 EFI Redfish Discover Protocol implementation. Refer to UEFI spec 2.9 section 31.1. Signed-off-by: Abner Chang Cc: Nickle Wang Cc: Jiaxin Wu Cc: Siyuan Fu Cc: Fan Wang Cc: Jiewen Yao Reviewed-by: Nickle Wang --- RedfishPkg/RedfishComponents.dsc.inc | 3 +- RedfishPkg/Redfish.fdf.inc | 3 +- .../RedfishDiscoverDxe/RedfishDiscoverDxe.inf | 55 + .../RedfishDiscoverInternal.h | 234 ++ RedfishPkg/RedfishDiscoverDxe/ComponentName.c | 218 ++ .../RedfishDiscoverDxe/RedfishDiscoverDxe.c | 1910 +++++++++++++++++ .../RedfishSmbiosHostInterface.c | 118 + 7 files changed, 2539 insertions(+), 2 deletions(-) create mode 100644 RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.inf create mode 100644 RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverInternal.h create mode 100644 RedfishPkg/RedfishDiscoverDxe/ComponentName.c create mode 100644 RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.c create mode 100644 RedfishPkg/RedfishDiscoverDxe/RedfishSmbiosHostInterfac= e.c diff --git a/RedfishPkg/RedfishComponents.dsc.inc b/RedfishPkg/RedfishCompo= nents.dsc.inc index 08f1d3bc32..6f3b055aba 100644 --- a/RedfishPkg/RedfishComponents.dsc.inc +++ b/RedfishPkg/RedfishComponents.dsc.inc @@ -6,7 +6,7 @@ # of EDKII Redfish drivers according to the value of flags described in # "RedfishDefines.dsc.inc". # -# (C) Copyright 2020 Hewlett Packard Enterprise Development LP
+# (C) Copyright 2021 Hewlett Packard Enterprise Development LP
# # SPDX-License-Identifier: BSD-2-Clause-Patent # @@ -17,4 +17,5 @@ RedfishPkg/RedfishHostInterfaceDxe/RedfishHostInterfaceDxe.inf RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf RedfishPkg/RedfishCredentialDxe/RedfishCredentialDxe.inf + RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.inf !endif diff --git a/RedfishPkg/Redfish.fdf.inc b/RedfishPkg/Redfish.fdf.inc index a64fd119a9..205c3101c0 100644 --- a/RedfishPkg/Redfish.fdf.inc +++ b/RedfishPkg/Redfish.fdf.inc @@ -5,7 +5,7 @@ # by using "!include RedfishPkg/RedfisLibs.fdf.inc" to specify the module = instances # to be built in the firmware volume. # -# (C) Copyright 2020 Hewlett Packard Enterprise Development LP
+# (C) Copyright 2021 Hewlett Packard Enterprise Development LP
# # SPDX-License-Identifier: BSD-2-Clause-Patent # @@ -15,4 +15,5 @@ INF RedfishPkg/RedfishHostInterfaceDxe/RedfishHostInterfaceDxe.inf INF RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf INF RedfishPkg/RedfishCredentialDxe/RedfishCredentialDxe.inf + INF RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.inf !endif diff --git a/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.inf b/Redfish= Pkg/RedfishDiscoverDxe/RedfishDiscoverDxe.inf new file mode 100644 index 0000000000..345bacf44d --- /dev/null +++ b/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.inf @@ -0,0 +1,55 @@ +## @file +# Implementation of EFI_REDFISH_DISCOVER_PROTOCOL interfaces. +# +# (C) Copyright 2021 Hewlett Packard Enterprise Development LP
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x0001001b + BASE_NAME =3D RedfishDiscoverDxe + FILE_GUID =3D 28A76FE5-43D7-48A3-9714-C1B7BDD6DFB6 + MODULE_TYPE =3D UEFI_DRIVER + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D RedfishDiscoverEntryPoint + UNLOAD_IMAGE =3D RedfishDiscoverUnload + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + NetworkPkg/NetworkPkg.dec + RedfishPkg/RedfishPkg.dec + +[Sources] + ComponentName.c + RedfishDiscoverDxe.c + RedfishSmbiosHostInterface.c + RedfishDiscoverInternal.h + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + MemoryAllocationLib + PrintLib + RestExLib + UefiLib + UefiBootServicesTableLib + UefiDriverEntryPoint + +[Protocols] + gEfiRestExServiceBindingProtocolGuid ## Consuming + gEfiRestExProtocolGuid ## Consuming + gEfiTcp4ServiceBindingProtocolGuid ## Consuming + gEfiTcp4ProtocolGuid ## Consuming + gEfiTcp6ServiceBindingProtocolGuid ## Consuming + gEfiTcp6ProtocolGuid ## Consuming + gEfiRedfishDiscoverProtocolGuid ## Prodcuing + gEfiSmbiosProtocolGuid ## Consuming + gEfiDriverBindingProtocolGuid ## Consuming + +[Pcd] + gEfiRedfishPkgTokenSpaceGuid.PcdRedfishDiscoverAccessModeInBand ## CONSU= MES + diff --git a/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverInternal.h b/Redf= ishPkg/RedfishDiscoverDxe/RedfishDiscoverInternal.h new file mode 100644 index 0000000000..cf69d9231a --- /dev/null +++ b/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverInternal.h @@ -0,0 +1,234 @@ +/** @file + This file defines the EFI Redfish Discover Protocol interface. + + (C) Copyright 2021 Hewlett Packard Enterprise Development LP
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef EFI_REDFISH_DISCOVER_INTERNAL_H_ +#define EFI_REDFISH_DISCOVER_INTERNAL_H_ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define REDFISH_DISCOVER_VERSION 0x00010000 +#define EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL TPL_NOTIFY + +// +//GUID definitions +// + +#define EFI_REDFISH_DISCOVER_TCP4_INSTANCE_GUID \ + { \ + 0xfbab97a4, 0x4c6a, 0xf8e8, { 0xf2, 0x25, 0x42, 0x8a, 0x80, 0x3f, 0xb6= , 0xaa } \ + } + +#define EFI_REDFISH_DISCOVER_TCP6_INSTANCE_GUID \ + { \ + 0xbe513b6d, 0x41c1, 0x96Ed, { 0x8d, 0xaf, 0x3e, 0x89, 0xc5, 0xf5, 0x02= , 0x25 } \ + } + +#define EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_GUID \ + { \ + 0xc44a6076, 0xd42a, 0x4d54, { 0x85, 0x6d, 0x98, 0x8a, 0x85, 0x8f, 0xa1= , 0x11 } \ + } + +extern EFI_COMPONENT_NAME_PROTOCOL gRedfishDiscoverComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gRedfishDiscoverComponentName2; +extern EFI_UNICODE_STRING_TABLE *gRedfishDiscoverControllerNameTable; + +// +// Enumeration of network protocols +// required for the Redfish service discovery. +// +typedef enum { + ProtocolTypeTcp4 =3D 0, ///< Network protocol TCPv4. + ProtocolTypeTcp6, ///< Network protocol TCCv6. + ProtocolTypeRestEx, ///< REST EX over network protocol. + MaxProtocolType +} NETWORK_INTERFACE_PROTOCOL_TYPE; + +// +// Network protocol information installed on +// the network interface. +// +typedef struct { + EFI_GUID ProtocolGuid; ///< Network protocol GUID. + EFI_GUID ProtocolServiceGuid; ///< Network protocol service GUID. + UINT32 ProtocolDiscoverId; ///< The identifier installed on n= etwork protocol handle. + EFI_HANDLE ProtocolControllerHandle; ///< The controller handle on netw= ork protocol. + VOID *NetworkProtocolInterface; ///< The protocol interface of net= work protocol. +} REDFISH_DISCOVER_NETWORK_INTERFACE_PROTOCOL; + +// +// Internal structure used to maintain network +// interface properties. +// +typedef struct { + LIST_ENTRY Entry; ///< Link list entry. + EFI_HANDLE OpenDriverAgentHandle; ///< The agent to open net= work protocol. + EFI_HANDLE OpenDriverControllerHandle; ///< The controller handle= to open network protocol. + UINTN HwAddressSize; ///< The size of network i= nterface hardware address. + EFI_MAC_ADDRESS MacAddress; ///< MAC address of networ= k interface. + CHAR16 *StrMacAddr; ///< String to MAC address= of network interface. + BOOLEAN GotSubnetInfo; ///< Indicates sub net inf= ormation is retrieved. + EFI_IP_ADDRESS SubnetAddr; ///< Subnet ID. + EFI_IP_ADDRESS SubnetMask; ///< Subnet mask (IPv4 onl= y) + UINT8 SubnetPrefixLength; ///< Subnet prefix. + UINT16 VlanId; ///< VLAN ID + UINT32 SubnetAddrInfoIPv6Number; ///< IPv6 address info num= ber. + EFI_IP6_ADDRESS_INFO *SubnetAddrInfoIPv6; ///< IPv6 address info. + // + // Network interface protocol and REST EX infor. + // + UINT32 NetworkProtocolType; ///< Network protocol type= . Refer to + ///< NETWORK_INTERFACE_PRO= TOCOL_TYPE. + REDFISH_DISCOVER_NETWORK_INTERFACE_PROTOCOL NetworkInterfaceProtocolInfo= ; ///< Network interface protocol information. + EFI_HANDLE RestExHandle; ///< REST EX handle associ= ated with this network interface. +} EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL; + +// +// Internal structure used to maintain REST EX properties. +// +typedef struct { + LIST_ENTRY Entry; ///< Link list entry. + EFI_HANDLE OpenDriverAgentHandle; ///< The agent to open= network protocol. + EFI_HANDLE OpenDriverControllerHandle; ///< The controller ha= ndle to open network protocol. + EFI_HANDLE RestExChildHandle; ///< The child handle = created throught REST EX Service Protocol. + EFI_HANDLE RestExControllerHandle; ///< The controller ha= ndle which provide REST EX protocol. + EFI_REST_EX_PROTOCOL *RestExProtocolInterface; ///< Pointer to EFI_RE= ST_EX_PROTOCOL. + UINT32 RestExId; ///< The identifier in= stalled on REST EX controller handle. +} EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL; + +/** + This function to get subnet information. + + @param[in] ImageHandle EFI handle with this image. + @param[in] Instance Instance of Network interface. + @retval EFI_STATUS Get subnet information successfully. + @retval Otherwise Fail to get subnet information. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_REDFISH_DISCOVER_GET_SUBNET_INFO)( + IN EFI_HANDLE ImageHandle, + IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *Instance +); + +// +// The require network protocol matrix. +// +typedef struct { + UINT32 ProtocolType; ///< Network proto= col type, + ///< Refer to NETW= ORK_INTERFACE_PROTOCOL_TYPE. + CHAR16 *ProtocolName; ///< Protocol name. + EFI_GUID *RequiredProtocolGuid; ///< Network proto= col interface GUID. + EFI_GUID *RequiredServiceBindingProtocolGuid; ///< Network proto= col service GUID. + EFI_GUID *DiscoveredProtocolGuid; ///< Protocol inte= rface GUID use to install identifier. + EFI_REDFISH_DISCOVER_GET_SUBNET_INFO GetSubnetInfo; ///< Function of g= etting subnet information. +} REDFISH_DISCOVER_REQUIRED_PROTOCOL; + +// +// Link list of Redfish discover instance. +// +typedef struct { + LIST_ENTRY NextInstance; ///< Next list. + EFI_REDFISH_DISCOVERED_INSTANCE *Instance; ///< Pointer to EF= I_REDFISH_DISCOVERED_INSTANCE. +} EFI_REDFISH_DISCOVERED_INTERNAL_LIST; + +// +// Internal structure of Redfish discover instance. +// +typedef struct { + LIST_ENTRY Entry; ///< Link list ent= ry. + EFI_HANDLE Owner; ///< The owner own= s this Redfish service discovery. + ///< It's the EFI = image handle of driver uses + ///< EFI Redfish D= iscover Protocol. + EFI_REDFISH_DISCOVER_FLAG DiscoverFlags; ///< EFI_REDFISH_D= ISCOVER_FLAG + EFI_REDFISH_DISCOVERED_TOKEN *DiscoverToken; ///< Token used to= signal when Redfish service is discovered. + EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *NetworkInterface; ///< = EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL + ///< = instance used to discover Redfish service. + // + // Below for Host insterface discovery. + // + BOOLEAN HostIntfValidation; ///< Indicates whe= ther to validate Redfish Host interface. + EFI_IP_ADDRESS TargetIpAddress; ///< Target IP add= ress reported in Redfish Host interface. +} EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE; + +/** + The function adds a new foudn Redfish service to internal list and + notify clinet. + + It simply frees the packet. + + @param[in] Instance EFI_REDFISH_DISCOVERED_INTERNAL_INSTAN= CE. + @param[in] RedfishVersion Redfish version. + @param[in] RedfishLocation Redfish location. + @param[in] Uuid Service UUID string. + @param[in] Os OS string. + @param[in] OsVer OS version string. + @param[in] Product Product string. + @param[in] ProductVer Product verison string. + @param[in] UseHttps Redfish service requires secured conne= ction. + @retval EFI_SUCCESS Redfish service is added to list succe= ssfully. + +**/ +EFI_STATUS +AddAndSignalNewRedfishService ( + IN EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *Instance, + IN UINTN *RedfishVersion OPTIONAL, + IN CHAR8 *RedfishLocation OPTIONAL, + IN CHAR8 *Uuid OPTIONAL, + IN CHAR8 *Os OPTIONAL, + IN CHAR8 *OsVer OPTIONAL, + IN CHAR8 *Product OPTIONAL, + IN CHAR8 *ProductVer OPTIONAL, + IN BOOLEAN UseHttps + ); + +/** + The function gets information reported in Redfish Host Interface. + + It simply frees the packet. + + @param[in] Smbios SMBIOS protocol. + @param[out] DeviceDescriptor Pointer to REDFISH_INTERFACE_DATA. + @param[out] ProtocolData Pointer to REDFISH_OVER_IP_PROTOCOL_DATA. + + @retval EFI_SUCCESS Get host interface succesfully. + @retval Otherwise Fail to tet host interface. + +**/ +EFI_STATUS +RedfishGetHostInterfaceProtocolData ( + IN EFI_SMBIOS_PROTOCOL *Smbios, + OUT REDFISH_INTERFACE_DATA **DeviceDescriptor, + OUT REDFISH_OVER_IP_PROTOCOL_DATA **ProtocolData + ); + +extern EFI_GUID gRedfishDiscoverTcp4Instance; +extern EFI_GUID gRedfishDiscoverTcp6Instance; +extern EFI_GUID gRedfishDiscoverRestEXInstance; +#endif diff --git a/RedfishPkg/RedfishDiscoverDxe/ComponentName.c b/RedfishPkg/Red= fishDiscoverDxe/ComponentName.c new file mode 100644 index 0000000000..adad2504bc --- /dev/null +++ b/RedfishPkg/RedfishDiscoverDxe/ComponentName.c @@ -0,0 +1,218 @@ +/** @file + Implementation of EFI_COMPONENT_NAME_PROTOCOL and EFI_COMPONENT_NAME2_PR= OTOCOL protocol. + for EFI Refish Discover Protocol + + (C) Copyright 2021 Hewlett Packard Enterprise Development LP
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "RedfishDiscoverInternal.h" + +// +// 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 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. This = Unicode string + is the name of the driver specified by This in th= e 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 +RedfishDiscoverComponentNameGetDriverName ( + 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_PROTOCO= L instance. + @param[in] ControllerHandle The handle of a controller that the driver = specified by + This is managing. This handle specifies th= e controller + whose name is to be returned. + @param[in] ChildHandle The handle of the child controller to retri= eve the name + of. This is an optional parameter that may= be NULL. It + will be NULL for device drivers. It will a= lso be NULL + for a bus drivers that wish to retrieve the= name of the + bus controller. It will not be NULL for a = bus driver + that wishes to retrieve the name of a child= controller. + @param[in] Language A pointer to a three character ISO 639-2 la= nguage + 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 SupportedLang= uages. The + number of languages supported by a driver i= s 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 specif= ied by + ControllerHandle and ChildHandle in the lan= guage 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 +RedfishDiscoverComponentNameGetControllerName ( + 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 gRedfishDiscoverComponentName =3D { + RedfishDiscoverComponentNameGetDriverName, + RedfishDiscoverComponentNameGetControllerName, + "eng" +}; + +/// +/// Component Name 2 Protocol instance +/// +GLOBAL_REMOVE_IF_UNREFERENCED +EFI_COMPONENT_NAME2_PROTOCOL gRedfishDiscoverComponentName2 =3D { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) RedfishDiscoverComponentNameGe= tDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) RedfishDiscoverComponentNameGe= tControllerName, + "en" +}; + +/// +/// Table of driver names +/// +GLOBAL_REMOVE_IF_UNREFERENCED +EFI_UNICODE_STRING_TABLE mRedfishDiscoverDriverNameTable[] =3D { + { "eng;en", (CHAR16 *)L"Redfish Discover UEFI Driver" }, + { NULL, NULL } +}; + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE *gRedfishDiscoverCo= ntrollerNameTable =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 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 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 +RedfishDiscoverComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mRedfishDiscoverDriverNameTable, + DriverName, + (BOOLEAN)(This =3D=3D &gRedfishDiscoverComponentName) + ); +} + +/** + 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_PROTOCO= L instance. + @param[in] ControllerHandle The handle of a controller that the driver = specified by + This is managing. This handle specifies th= e controller + whose name is to be returned. + @param[in] ChildHandle The handle of the child controller to retri= eve the name + of. This is an optional parameter that may= be NULL. It + will be NULL for device drivers. It will a= lso be NULL + for a bus drivers that wish to retrieve the= name of the + bus controller. It will not be NULL for a = bus driver + that wishes to retrieve the name of a child= controller. + @param[in] Language A pointer to a three character ISO 639-2 la= nguage + 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 SupportedLang= uages. The + number of languages supported by a driver i= s 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 specif= ied by + ControllerHandle and ChildHandle in the lan= guage 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 +RedfishDiscoverComponentNameGetControllerName ( + 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/RedfishDiscoverDxe/RedfishDiscoverDxe.c b/RedfishPk= g/RedfishDiscoverDxe/RedfishDiscoverDxe.c new file mode 100644 index 0000000000..80d70a4679 --- /dev/null +++ b/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.c @@ -0,0 +1,1910 @@ +/** @file + + The implementation of EFI Redfidh Discover Protocol. + + (C) Copyright 2021 Hewlett Packard Enterprise Development LP
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "RedfishDiscoverInternal.h" + +LIST_ENTRY mRedfishDiscoverList; +LIST_ENTRY mRedfishInstanceList; +EFI_SMBIOS_PROTOCOL *mSmbios =3D NULL; + +UINTN mNumNetworkInterface =3D 0; +UINTN mNumRestExInstance =3D 0; +LIST_ENTRY mEfiRedfishDiscoverNetworkInterface; +LIST_ENTRY mEfiRedfishDiscoverRestExInstance; + +EFI_GUID mRedfishDiscoverTcp4InstanceGuid =3D EFI_REDFISH_DISCOVER_TCP4_IN= STANCE_GUID; +EFI_GUID mRedfishDiscoverTcp6InstanceGuid =3D EFI_REDFISH_DISCOVER_TCP6_IN= STANCE_GUID; +EFI_GUID mRedfishDiscoverRestExInstanceGuid =3D EFI_REDFISH_DISCOVER_REST_= EX_INSTANCE_GUID; + +EFI_HANDLE EfiRedfishDiscoverProtocolHandle =3D NULL; + +EFI_STATUS +EFIAPI +Tcp4GetSubnetInfo ( + IN EFI_HANDLE ImageHandle, + IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *Instance +); + +EFI_STATUS +EFIAPI +Tcp6GetSubnetInfo ( + IN EFI_HANDLE ImageHandle, + IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *Instance +); + +static REDFISH_DISCOVER_REQUIRED_PROTOCOL gRequiredProtocol[] =3D { + { + ProtocolTypeTcp4, + L"TCP4 Service Binding Protocol", + &gEfiTcp4ProtocolGuid, + &gEfiTcp4ServiceBindingProtocolGuid, + &mRedfishDiscoverTcp4InstanceGuid, + Tcp4GetSubnetInfo + }, + { + ProtocolTypeTcp6, + L"TCP6 Service Binding Protocol", + &gEfiTcp6ProtocolGuid, + &gEfiTcp6ServiceBindingProtocolGuid, + &mRedfishDiscoverTcp6InstanceGuid, + Tcp6GetSubnetInfo + }, + { + ProtocolTypeRestEx, + L"REST EX Service Binding Protocol", + &gEfiRestExProtocolGuid, + &gEfiRestExServiceBindingProtocolGuid, + &mRedfishDiscoverRestExInstanceGuid, + NULL + } +}; + +/** + This function creates REST EX instance for the found Resfish service. + by known owner handle. + + @param[in] Instance EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE + @param[in] Token Client token. + + @retval NULL Instance not found. + @retval EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE The instance owned by t= his owner. + +**/ +EFI_STATUS +CreateRestExInstance ( + IN EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *Instance, + IN EFI_REDFISH_DISCOVERED_TOKEN *Token + ) +{ + EFI_STATUS Status; + + Status =3D RestExLibCreateChild ( + Instance->Owner, + FixedPcdGetBool (PcdRedfishDiscoverAccessModeInBand)? EfiRestE= xServiceInBandAccess: EfiRestExServiceOutOfBandAccess, + EfiRestExConfigHttp, + EfiRestExServiceRedfish, + &Token->DiscoverList.RedfishInstances->Information.RedfishRest= ExHandle + ); + return Status; +} + +/** + This function gets EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE + by known owner handle. + + @param[in] ImageHandle Image handle owns EFI_REDFISH_DISC= OVERED_INTERNAL_INSTANCE. + @param[in] TargetNetworkInterface Target network interface used by t= his EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE. + @param[in] DiscoverFlags EFI_REDFISH_DISCOVER_FLAG + + @retval NULL Instance not found. + @retval EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE The instance owned by t= his owner. + +**/ +EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE * +GetInstanceByOwner ( + IN EFI_HANDLE ImageHandle, + IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *TargetNetworkInterfa= ce, + IN EFI_REDFISH_DISCOVER_FLAG DiscoverFlags + ) +{ + EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *ThisInstance; + + if (IsListEmpty (&mRedfishDiscoverList)) { + return NULL; + } + ThisInstance =3D + (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *)GetFirstNode (&mRedfishDis= coverList); + while (TRUE) { + if ((ThisInstance->Owner =3D=3D ImageHandle) && + (ThisInstance->DiscoverFlags =3D=3D DiscoverFlags) && + (ThisInstance->NetworkInterface =3D=3D TargetNetworkInterface)) { + return ThisInstance; + } + if (IsNodeAtEnd (&mRedfishDiscoverList, &ThisInstance->Entry)) { + break; + } + ThisInstance =3D + (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *)GetNextNode (&mRedfishDi= scoverList, &ThisInstance->Entry); + }; + return NULL; +} + +/** + This function gets the subnet information of this TCP4 instance. + + @param[in] ImageHandle EFI handle with this image. + @param[in] Instance Instance of Network interface. + @retval EFI_STATUS Get subnet information successfully. + @retval Otherwise Fail to get subnet information. +**/ +EFI_STATUS +EFIAPI +Tcp4GetSubnetInfo ( + IN EFI_HANDLE ImageHandle, + IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *Instance +) +{ + EFI_STATUS Status; + EFI_TCP4_PROTOCOL *Tcp4; + EFI_TCP4_CONFIG_DATA Tcp4CfgData; + EFI_TCP4_OPTION Tcp4Option; + EFI_IP4_MODE_DATA IpModedata; + UINT8 SubnetMaskIndex; + UINT8 BitMask; + UINT8 PrefixLength; + BOOLEAN GotPrefixLength; + + if (Instance =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + Tcp4 =3D (EFI_TCP4_PROTOCOL *)Instance->NetworkInterfaceProtocolInfo.Net= workProtocolInterface; + + ZeroMem ((VOID *)&Tcp4CfgData, sizeof (EFI_TCP4_CONFIG_DATA)); + ZeroMem ((VOID *)&Tcp4Option, sizeof (EFI_TCP4_OPTION)); + // Give a local host IP address just for getting subnet information. + Tcp4CfgData.AccessPoint.UseDefaultAddress =3D TRUE; + Tcp4CfgData.AccessPoint.RemoteAddress.Addr [0] =3D 127; + Tcp4CfgData.AccessPoint.RemoteAddress.Addr [1] =3D 0; + Tcp4CfgData.AccessPoint.RemoteAddress.Addr [2] =3D 0; + Tcp4CfgData.AccessPoint.RemoteAddress.Addr [3] =3D 1; + Tcp4CfgData.AccessPoint.RemotePort =3D 80; + Tcp4CfgData.AccessPoint.ActiveFlag =3D TRUE; + + Tcp4CfgData.ControlOption =3D &Tcp4Option; + Tcp4Option.ReceiveBufferSize =3D 65535; + Tcp4Option.SendBufferSize =3D 65535; + Tcp4Option.MaxSynBackLog =3D 5; + Tcp4Option.ConnectionTimeout =3D 60; + Tcp4Option.DataRetries =3D 12; + Tcp4Option.FinTimeout =3D 2; + Tcp4Option.KeepAliveProbes =3D 6; + Tcp4Option.KeepAliveTime =3D 7200; + Tcp4Option.KeepAliveInterval =3D 30; + Tcp4Option.EnableNagle =3D TRUE; + Status =3D Tcp4->Configure (Tcp4, &Tcp4CfgData); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Can't get subnet information\n", __FUNCTION_= _)); + return Status; + } + Status =3D Tcp4->GetModeData (Tcp4, NULL, NULL, &IpModedata, NULL, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Can't get IP mode data information\n", __FUN= CTION__)); + return Status; + } + IP4_COPY_ADDRESS (&Instance->SubnetMask, &IpModedata.ConfigData.SubnetMa= sk); + Instance->SubnetAddr.v4.Addr [0] =3D IpModedata.ConfigData.StationAddres= s.Addr [0] & Instance->SubnetMask.v4.Addr [0]; + Instance->SubnetAddr.v4.Addr [1] =3D IpModedata.ConfigData.StationAddres= s.Addr [1] & Instance->SubnetMask.v4.Addr [1]; + Instance->SubnetAddr.v4.Addr [2] =3D IpModedata.ConfigData.StationAddres= s.Addr [2] & Instance->SubnetMask.v4.Addr [2]; + Instance->SubnetAddr.v4.Addr [3] =3D IpModedata.ConfigData.StationAddres= s.Addr [3] & Instance->SubnetMask.v4.Addr [3]; + // + // Calculate the subnet mask prefix. + // + GotPrefixLength =3D FALSE; + PrefixLength =3D 0; + SubnetMaskIndex =3D 0; + while (GotPrefixLength =3D=3D FALSE && SubnetMaskIndex < 4) { + BitMask =3D 0x80; + while (BitMask !=3D 0) { + if ((Instance->SubnetMask.v4.Addr [SubnetMaskIndex] & BitMask) !=3D = 0) { + PrefixLength ++; + } else { + GotPrefixLength =3D TRUE; + break; + } + BitMask =3D BitMask >> 1; + }; + SubnetMaskIndex ++; + }; + Instance->SubnetPrefixLength =3D PrefixLength; + return EFI_SUCCESS; +} + +/** + This function gets the subnet information of this TCP6 instance. + + @param[in] ImageHandle EFI handle with this image. + @param[in] Instance Instance of Network interface. + @retval EFI_STATUS Get subnet information successfully. + @retval Otherwise Fail to get subnet information. +**/ +EFI_STATUS +EFIAPI +Tcp6GetSubnetInfo ( + IN EFI_HANDLE ImageHandle, + IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *Instance +) +{ + EFI_STATUS Status; + EFI_TCP6_PROTOCOL *Tcp6; + EFI_IP6_MODE_DATA IpModedata; + + if (Instance =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + Tcp6 =3D (EFI_TCP6_PROTOCOL *)Instance->NetworkInterfaceProtocolInfo.Net= workProtocolInterface; + + Status =3D Tcp6->GetModeData (Tcp6, NULL, NULL, &IpModedata, NULL, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Can't get IP mode data information\n")); + return Status; + } + if (IpModedata.AddressCount =3D=3D 0) { + DEBUG ((DEBUG_INFO, "%a: No IPv6 address configured.\n")); + } + if (Instance->SubnetAddrInfoIPv6 !=3D NULL) { + FreePool (Instance->SubnetAddrInfoIPv6); + } + Instance->SubnetAddrInfoIPv6 =3D AllocateZeroPool (IpModedata.AddressCou= nt * sizeof (EFI_IP6_ADDRESS_INFO)); + if (Instance->SubnetAddrInfoIPv6 =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "%a: Failed to allocate memory fir IPv6 subnet ad= dress information\n")); + return EFI_OUT_OF_RESOURCES; + } + Instance->SubnetAddrInfoIPv6Number =3D IpModedata.AddressCount; + CopyMem ( + (VOID *)Instance->SubnetAddrInfoIPv6, + (VOID *)&IpModedata.AddressList, + IpModedata.AddressCount * sizeof (EFI_IP6_ADDRESS_INFO) + ); + FreePool (IpModedata.AddressList); + return EFI_SUCCESS; +} + +/** + This function searches EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL + instance with the given EFI_REDFISH_DISCOVER_NETWORK_INTERFACE. + + @param[in] TargetNetworkInterface EFI_REDFISH_DISCOVER_NETWORK_INTERFAC= E. + NULL for all EFI_REDFISH_DISCOVER_NET= WORK_INTERFACEs. + + @retval Non-NULL EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL is ret= urned. + @retval NULL Non of EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL= instance is returned. +**/ +EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL * +GetTargetNetworkInterfaceInternal ( + IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *TargetNetworkInterface + ) +{ + EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterface; + + ThisNetworkInterface =3D (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNA= L *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface); + while (TRUE) { + if (CompareMem((VOID *)&ThisNetworkInterface->MacAddress, &TargetNetwo= rkInterface->MacAddress, ThisNetworkInterface->HwAddressSize) =3D=3D 0) { + return ThisNetworkInterface; + } + if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInt= erface->Entry)) { + return NULL; + } + ThisNetworkInterface =3D (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTER= NAL *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterfa= ce->Entry); + }; + return NULL; +} + +/** + This function validate if target network interface is ready for discover= ing + Redfish service. + + @param[in] TargetNetworkInterface EFI_REDFISH_DISCOVER_NETWORK_INTERFAC= E. + NULL for all EFI_REDFISH_DISCOVER_NET= WORK_INTERFACEs. + @param[in] Flags EFI_REDFISH_DISCOVER_FLAG + + @retval EFI_SUCCESS Target network interface is ready to use. + @retval EFI_UNSUPPORTED Target network interface is not ready to use. +**/ +EFI_STATUS +ValidateTargetNetworkInterface ( + IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *TargetNetworkInterface, + IN EFI_REDFISH_DISCOVER_FLAG Flags + ) +{ + EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterface; + + if (IsListEmpty (&mEfiRedfishDiscoverNetworkInterface) && TargetNetworkI= nterface =3D=3D NULL) { + return EFI_UNSUPPORTED; + } + if (TargetNetworkInterface =3D=3D NULL) { + return EFI_SUCCESS; // Return EFI_SUCCESS if no network interface is s= pecified. + } + + ThisNetworkInterface =3D (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNA= L *)GetFirstNode(&mEfiRedfishDiscoverNetworkInterface); + while (TRUE) { + if (CompareMem((VOID *)&ThisNetworkInterface->MacAddress, &TargetNetwo= rkInterface->MacAddress, ThisNetworkInterface->HwAddressSize) =3D=3D 0) { + break; + } + if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInt= erface->Entry)) { + return EFI_UNSUPPORTED; + } + ThisNetworkInterface =3D (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTER= NAL *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterfa= ce->Entry); + }; + if ((Flags & EFI_REDFISH_DISCOVER_SSDP) !=3D 0) { + // Validate if UDP4/6 is supported on the given network interface. + // SSDP is not supported. + + return EFI_SUCCESS; + } + if (ThisNetworkInterface->NetworkInterfaceProtocolInfo.ProtocolControlle= rHandle =3D=3D NULL) { + return EFI_UNSUPPORTED; // The required protocol on this network inter= face is not found. + } + return EFI_SUCCESS; +} +/** + This function returns number of network interface instance. + + @retval UINTN Number of network interface instances. +**/ +UINTN +NumberOfNetworkInterface (VOID) +{ + UINTN Num; + EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterface; + + if (IsListEmpty (&mEfiRedfishDiscoverNetworkInterface)) { + return 0; + } + + Num =3D 1; + ThisNetworkInterface =3D (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNA= L *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface); + while (TRUE) { + if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInt= erface->Entry)) { + break; + } + ThisNetworkInterface =3D (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTER= NAL *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterfa= ce->Entry); + Num ++; + }; + return Num; +} + +/** + This function checks the IP version supported on this + netwoek interface. + + @param[in] ThisNetworkInterface EFI_REDFISH_DISCOVER_NETWORK_INTERF= ACE_INTERNAL + + @retval TRUE Is IPv6, otherwise IPv4. + +**/ +BOOLEAN +CheckIsIpVersion6 ( + IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterface +) +{ + if (ThisNetworkInterface->NetworkProtocolType =3D=3D ProtocolTypeTcp6) { + return TRUE; + } + return FALSE; +} + +/** + This function discover Redfish service through SMBIOS host interface. + + @param[in] Instance EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE + + @retval EFI_SUCCESS Redfish service is discovered through SMBIOS = Host interface. + @retval Others Fail to discover Redfish service throught SMB= IOS host interface + +**/ +EFI_STATUS +DiscoverRedfishHostInterface (IN EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE = *Instance) +{ + EFI_STATUS Status; + REDFISH_OVER_IP_PROTOCOL_DATA *Data; + REDFISH_INTERFACE_DATA *DeviceDescriptor; + CHAR8 UuidStr[sizeof"00000000-0000-0000-0000-000000000000" + 1]; + CHAR16 Ipv6Str [sizeof"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" + 1]; + CHAR8 RedfishServiceLocateStr [sizeof"ffff:ffff:ffff:ffff:ffff:ffff:ffff= :ffff" + 1]; + UINTN StrSize; + UINTN MacCompareStstus; + BOOLEAN IsHttps; + + Data =3D NULL; + DeviceDescriptor =3D NULL; + + if (mSmbios =3D=3D NULL) { + Status =3D gBS->LocateProtocol(&gEfiSmbiosProtocolGuid, NULL, (VOID **= )&mSmbios); + if (EFI_ERROR (Status)) { + return Status; + } + } + Status =3D RedfishGetHostInterfaceProtocolData (mSmbios, &DeviceDescript= or, &Data); // Search for SMBIOS type 42h + if (!EFI_ERROR (Status) && Data !=3D NULL && DeviceDescriptor !=3D NULL)= { + // + // Chceck if we can reach out Redfish service using this network inter= face. + // Check with MAC address using Device Descroptor Data Device Type 04 = and Type 05. + // Those two types of Redfish host interface device has MAC informatio= n. + // + if (DeviceDescriptor->DeviceType =3D=3D REDFISH_HOST_INTERFACE_DEVICE_= TYPE_PCI_PCIE_V2) { + MacCompareStstus =3D CompareMem(&Instance->NetworkInterface->MacAddr= ess, &DeviceDescriptor->DeviceDescriptor.PciPcieDeviceV2.MacAddress, 6); + } else if (DeviceDescriptor->DeviceType =3D=3D REDFISH_HOST_INTERFACE_= DEVICE_TYPE_USB_V2){ + MacCompareStstus =3D CompareMem(&Instance->NetworkInterface->MacAddr= ess, &DeviceDescriptor->DeviceDescriptor.UsbDeviceV2.MacAddress, 6); + } else { + return EFI_UNSUPPORTED; + } + if (MacCompareStstus !=3D 0) { + return EFI_UNSUPPORTED; + } + + if (Data->RedfishServiceIpAddressFormat =3D=3D 1) { + IP4_COPY_ADDRESS ((VOID *)&Instance->TargetIpAddress.v4, (VOID *)Dat= a->RedfishServiceIpAddress); + } else { + IP6_COPY_ADDRESS ((VOID *)&Instance->TargetIpAddress.v6, (VOID *)Dat= a->RedfishServiceIpAddress); + } + + if (Instance->HostIntfValidation) { + DEBUG ((DEBUG_ERROR,"%a:Send UPnP unicast SSDP to validate this Redf= ish Host Interface is not supported.\n", __FUNCTION__)); + Status =3D EFI_UNSUPPORTED; + } else { + // + // Add this istance to list without detial information of Redfish + // service. + // + IsHttps =3D FALSE; + if (Data->RedfishServiceIpPort =3D=3D 443) { + IsHttps =3D TRUE; + } + StrSize =3D sizeof(UuidStr); + AsciiSPrint(UuidStr, StrSize, "%g", &Data->ServiceUuid); + // + // Generate Redfish service location string. + // + if (Data->RedfishServiceIpAddressFormat =3D=3D REDFISH_HOST_INTERFAC= E_HOST_IP_ADDRESS_FORMAT_IP6) { + NetLibIp6ToStr((IPv6_ADDRESS *)&Data->RedfishServiceIpAddress, Ipv= 6Str, sizeof (Ipv6Str)); + if (Data->RedfishServiceIpPort =3D=3D 0 || IsHttps =3D=3D TRUE) { + AsciiSPrintUnicodeFormat ( + RedfishServiceLocateStr, + sizeof (RedfishServiceLocateStr), + L"%s", + Ipv6Str + ); + } else { + AsciiSPrintUnicodeFormat( + RedfishServiceLocateStr, + sizeof (RedfishServiceLocateStr), + L"[%s]:%d", + Ipv6Str, + Data->RedfishServiceIpPort + ); + } + } else { + if (Data->RedfishServiceIpPort =3D=3D 0 || IsHttps =3D=3D TRUE) { + AsciiSPrint( + RedfishServiceLocateStr, + sizeof (RedfishServiceLocateStr), + "%d.%d.%d.%d", + Data->RedfishServiceIpAddress [0], + Data->RedfishServiceIpAddress [1], + Data->RedfishServiceIpAddress [2], + Data->RedfishServiceIpAddress [3] + ); + } else { + AsciiSPrint( + RedfishServiceLocateStr, + sizeof (RedfishServiceLocateStr), + "%d.%d.%d.%d:%d", + Data->RedfishServiceIpAddress [0], + Data->RedfishServiceIpAddress [1], + Data->RedfishServiceIpAddress [2], + Data->RedfishServiceIpAddress [3], + Data->RedfishServiceIpPort + ); + } + } + Status =3D AddAndSignalNewRedfishService ( + Instance, + NULL, + RedfishServiceLocateStr, + UuidStr, + NULL, + NULL, + NULL, + NULL, + IsHttps + ); + } + } + return Status; +} + +/** + The function adds a new found Redfish service to internal list and + notify client. + + @param[in] Instance EFI_REDFISH_DISCOVERED_INTERNAL_INSTAN= CE. + @param[in] RedfishVersion Redfish version. + @param[in] RedfishLocation Redfish location. + @param[in] Uuid Service UUID string. + @param[in] Os OS string. + @param[in] OsVer OS version string. + @param[in] Product Product string. + @param[in] ProductVer Product verison string. + @param[in] UseHttps Redfish service requires secured conne= ction. + @retval EFI_SUCCESS Redfish service is added to list succe= ssfully. + +**/ +EFI_STATUS +AddAndSignalNewRedfishService ( + IN EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *Instance, + IN UINTN *RedfishVersion OPTIONAL, + IN CHAR8 *RedfishLocation OPTIONAL, + IN CHAR8 *Uuid OPTIONAL, + IN CHAR8 *Os OPTIONAL, + IN CHAR8 *OsVer OPTIONAL, + IN CHAR8 *Product OPTIONAL, + IN CHAR8 *ProductVer OPTIONAL, + IN BOOLEAN UseHttps + ) +{ + BOOLEAN NewFound; + BOOLEAN InfoRefresh; + BOOLEAN RestExOpened; + BOOLEAN DeleteRestEx; + EFI_STATUS Status; + EFI_REDFISH_DISCOVERED_INTERNAL_LIST *DiscoveredList; + EFI_REDFISH_DISCOVERED_INSTANCE *DiscoveredInstance; + CHAR16 *Char16Uuid; + EFI_REST_EX_PROTOCOL *RestEx; + EFI_REST_EX_HTTP_CONFIG_DATA *RestExHttpConfigData; + EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *NetworkInterface; + + NewFound =3D TRUE; + InfoRefresh =3D FALSE; + Char16Uuid =3D NULL; + RestExOpened =3D FALSE; + DeleteRestEx =3D FALSE; + + DEBUG ((DEBUG_INFO,"%a:Add this instance to Redfish instance list.\n", _= _FUNCTION__)); + + if (Uuid !=3D NULL) { + Char16Uuid =3D (CHAR16 *)AllocateZeroPool(AsciiStrSize((const CHAR8 *)= Uuid) * sizeof(CHAR16)); + AsciiStrToUnicodeStrS ((const CHAR8 *)Uuid, Char16Uuid, AsciiStrSize((= const CHAR8 *)Uuid) * sizeof(CHAR16)); + } + DiscoveredList =3D NULL; + DiscoveredInstance =3D NULL; + RestExHttpConfigData =3D NULL; + + NetworkInterface =3D Instance->NetworkInterface; + if (!IsListEmpty (&mRedfishInstanceList)) { + // + // Is this a duplicate redfish service. + // + DiscoveredList =3D (EFI_REDFISH_DISCOVERED_INTERNAL_LIST *)GetFirstNod= e (&mRedfishInstanceList); + NewFound =3D FALSE; + do { + if (Char16Uuid =3D=3D NULL || DiscoveredList->Instance->Information.= Uuid =3D=3D NULL) { + // + // Check if this Redfish instance already found using IP addrress. + // + if (!CheckIsIpVersion6(NetworkInterface)) { + if (CompareMem ((VOID *)&Instance->TargetIpAddress.v4, + (VOID *)&DiscoveredList->Instance->Information.Redfi= shHostIpAddress.v4, + sizeof (EFI_IPv4_ADDRESS) + ) =3D=3D 0) + { + DiscoveredInstance =3D DiscoveredList->Instance; + if (DiscoveredList->Instance->Information.Uuid =3D=3D NULL && + Char16Uuid !=3D NULL) { + InfoRefresh =3D TRUE; + DiscoveredInstance =3D DiscoveredList->Instance; + DEBUG((DEBUG_INFO,"*** This Redfish Service information refr= esh ***\n")); + } + break; + } + } else { + if (CompareMem ((VOID *)&Instance->TargetIpAddress.v6, + (VOID *)&DiscoveredList->Instance->Information.Redfi= shHostIpAddress.v6, + sizeof (EFI_IPv6_ADDRESS) + ) =3D=3D 0) + { + DiscoveredInstance =3D DiscoveredList->Instance; + break; + } + } + } else { + // + // Check if this Redfish instance already found using UUID. + // + if (StrCmp((const CHAR16 *)Char16Uuid, (const CHAR16 *)DiscoveredL= ist->Instance->Information.Uuid) =3D=3D 0) { + DiscoveredInstance =3D DiscoveredList->Instance; + break; + } + } + if (IsNodeAtEnd (&mRedfishInstanceList, &DiscoveredList->NextInstanc= e)) { + NewFound =3D TRUE; + break; + } + DiscoveredList =3D (EFI_REDFISH_DISCOVERED_INTERNAL_LIST *)GetNextNo= de (&mRedfishInstanceList, &DiscoveredList->NextInstance); + } while (TRUE); + } + if (NewFound || InfoRefresh) { + if (!InfoRefresh) { + DiscoveredList =3D (EFI_REDFISH_DISCOVERED_INTERNAL_LIST *)AllocateZ= eroPool(sizeof(EFI_REDFISH_DISCOVERED_INTERNAL_LIST)); + if (DiscoveredList =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + InitializeListHead (&DiscoveredList->NextInstance); + DiscoveredInstance =3D (EFI_REDFISH_DISCOVERED_INSTANCE *)AllocateZe= roPool(sizeof(EFI_REDFISH_DISCOVERED_INSTANCE)); + if (DiscoveredInstance =3D=3D NULL) { + FreePool ((VOID *)DiscoveredList); + return EFI_OUT_OF_RESOURCES; + } + } + DEBUG ((DEBUG_INFO,"*** Redfish Service Information ***\n")); + + DiscoveredInstance->Information.UseHttps =3D UseHttps; + if (RedfishVersion !=3D NULL) { + DiscoveredInstance->Information.RedfishVersion =3D *RedfishVersion; + DEBUG ((DEBUG_INFO,"Redfish service version: %d.\n", DiscoveredInsta= nce->Information.RedfishVersion)); + } + if (RedfishLocation !=3D NULL) { + DiscoveredInstance->Information.Location =3D (CHAR16 *)AllocatePool(= AsciiStrSize((const CHAR8 *)RedfishLocation) * sizeof(CHAR16)); + AsciiStrToUnicodeStrS ((const CHAR8 *)RedfishLocation, DiscoveredIns= tance->Information.Location, AsciiStrSize((const CHAR8 *)RedfishLocation) *= sizeof(CHAR16)); + DEBUG ((DEBUG_INFO,"Redfish service location: %s.\n", DiscoveredInst= ance->Information.Location)); + } + if (Uuid !=3D NULL) { + DiscoveredInstance->Information.Uuid =3D (CHAR16 *)AllocatePool(Asci= iStrSize((const CHAR8 *)Uuid) * sizeof(CHAR16)); + AsciiStrToUnicodeStrS ((const CHAR8 *)Uuid, DiscoveredInstance->Info= rmation.Uuid, AsciiStrSize((const CHAR8 *)Uuid) * sizeof(CHAR16)); + DEBUG ((DEBUG_INFO,"Service UUID: %s.\n", DiscoveredInstance->Inform= ation.Uuid)); + } + if (Os !=3D NULL) { + DiscoveredInstance->Information.Os =3D (CHAR16 *)AllocatePool(AsciiS= trSize((const CHAR8 *)Os) * sizeof(CHAR16)); + AsciiStrToUnicodeStrS ((const CHAR8 *)Os, DiscoveredInstance->Inform= ation.Os, AsciiStrSize((const CHAR8 *)Os) * sizeof(CHAR16)); + DEBUG ((DEBUG_INFO,"Redfish service OS: %s, Version:%s.\n", Discover= edInstance->Information.Os, DiscoveredInstance->Information.OsVersion)); + } + if (OsVer !=3D NULL) { + DiscoveredInstance->Information.OsVersion =3D (CHAR16 *)AllocatePool= (AsciiStrSize((const CHAR8 *)OsVer) * sizeof(CHAR16)); + AsciiStrToUnicodeStrS ((const CHAR8 *)OsVer, DiscoveredInstance->Inf= ormation.OsVersion, AsciiStrSize((const CHAR8 *)OsVer) * sizeof(CHAR16)); + } + if (Product !=3D NULL && ProductVer !=3D NULL) { + DiscoveredInstance->Information.Product =3D (CHAR16 *)AllocatePool(A= sciiStrSize((const CHAR8 *)Product) * sizeof(CHAR16)); + AsciiStrToUnicodeStrS ((const CHAR8 *)Product, DiscoveredInstance->I= nformation.Product, AsciiStrSize((const CHAR8 *)Product) * sizeof(CHAR16)); + DiscoveredInstance->Information.ProductVer =3D (CHAR16 *)AllocatePoo= l(AsciiStrSize((const CHAR8 *)ProductVer) * sizeof(CHAR16)); + AsciiStrToUnicodeStrS ((const CHAR8 *)ProductVer, DiscoveredInstance= ->Information.ProductVer, AsciiStrSize((const CHAR8 *)ProductVer) * sizeof(= CHAR16)); + DEBUG ((DEBUG_INFO,"Redfish service product: %s, Version:%s.\n", Dis= coveredInstance->Information.Product, DiscoveredInstance->Information.Produ= ctVer)); + } + + if (RedfishLocation =3D=3D NULL) { + // This is the Redfish reported from SMBIOS 42h + // without validation. + + IP4_COPY_ADDRESS((VOID *)&DiscoveredInstance->Information.RedfishHos= tIpAddress.v4, (VOID *)&Instance->TargetIpAddress.v4); + } + if (!InfoRefresh) { + DiscoveredList->Instance =3D DiscoveredInstance; + InsertTailList(&mRedfishInstanceList, &DiscoveredList->NextInstance); + } + DiscoveredInstance->Status =3D EFI_SUCCESS; + } else { + if (DiscoveredList !=3D NULL) { + DEBUG((DEBUG_INFO,"*** This Redfish Service was already found ***\n"= )); + if (DiscoveredInstance->Information.Uuid !=3D NULL) { + DEBUG((DEBUG_INFO,"Service UUID: %s.\n", DiscoveredInstance->Infor= mation.Uuid)); + } else { + DEBUG((DEBUG_INFO,"Service UUID: unknown.\n")); + } + } + } + if (Char16Uuid !=3D NULL) { + FreePool((VOID *)Char16Uuid); + } + + Status =3D EFI_SUCCESS; + if (NewFound || InfoRefresh) { + // + // Build up EFI_REDFISH_DISCOVERED_LIST in token. + // + Instance->DiscoverToken->DiscoverList.NumberOfServiceFound =3D 1; + Instance->DiscoverToken->DiscoverList.RedfishInstances =3D DiscoveredI= nstance; + DiscoveredInstance->Status =3D EFI_SUCCESS; + if (!InfoRefresh) { + Status =3D CreateRestExInstance (Instance, Instance->DiscoverToken);= // Create REST EX child. + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a:Can't create REST EX child instance.\n",_= _FUNCTION__)); + goto ON_EXIT; + } + Status =3D gBS->OpenProtocol ( // Configure local host information. + Instance->DiscoverToken->DiscoverList.RedfishInstances->= Information.RedfishRestExHandle, + &gEfiRestExProtocolGuid, + (VOID **)&RestEx, + Instance->NetworkInterface->OpenDriverAgentHandle, + Instance->NetworkInterface->OpenDriverControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + DeleteRestEx =3D TRUE; + goto ERROR_EXIT; + } + RestExOpened =3D TRUE; + RestExHttpConfigData =3D AllocateZeroPool (sizeof (EFI_REST_EX_HTTP_= CONFIG_DATA)); + if (RestExHttpConfigData =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + DeleteRestEx =3D TRUE; + goto EXIT_FREE_CONFIG_DATA; + } + RestExHttpConfigData->SendReceiveTimeout =3D 5000; + RestExHttpConfigData->HttpConfigData.HttpVersion =3D HttpVersion11; + RestExHttpConfigData->HttpConfigData.LocalAddressIsIPv6 =3D CheckIsI= pVersion6(NetworkInterface); + if (RestExHttpConfigData->HttpConfigData.LocalAddressIsIPv6) { + RestExHttpConfigData->HttpConfigData.AccessPoint.IPv6Node =3D Allo= cateZeroPool (sizeof (EFI_HTTPv6_ACCESS_POINT)); + if (RestExHttpConfigData->HttpConfigData.AccessPoint.IPv6Node =3D= =3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto EXIT_FREE_CONFIG_DATA; + } + } else { + RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node =3D Allo= cateZeroPool (sizeof (EFI_HTTPv4_ACCESS_POINT)); + if (RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node =3D= =3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto EXIT_FREE_CONFIG_DATA; + } + RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node->UseDefa= ultAddress =3D TRUE; + } + Status =3D RestEx->Configure ( + RestEx, + (EFI_REST_EX_CONFIG_DATA)(UINT8 *)RestExHttpConfigD= ata + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR,"%a:REST EX configured..\n", __FUNCTION__)); + DeleteRestEx =3D TRUE; + goto EXIT_FREE_ALL; + } + // + // Signal client, close REST EX before signaling client. + // + if (RestExOpened) { + gBS->CloseProtocol( + Instance->DiscoverToken->DiscoverList.RedfishInstances->Infor= mation.RedfishRestExHandle, + &gEfiRestExProtocolGuid, + Instance->NetworkInterface->OpenDriverAgentHandle, + Instance->NetworkInterface->OpenDriverControllerHandle + ); + RestExOpened =3D FALSE; + } + } + Status =3D gBS->SignalEvent(Instance->DiscoverToken->Event); + if (!EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR,"%a:No event to signal!\n", __FUNCTION__)); + } + } + +EXIT_FREE_ALL:; + if (RestExHttpConfigData !=3D NULL && RestExHttpConfigData->HttpConfigDa= ta.AccessPoint.IPv4Node !=3D NULL) { + FreePool (RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node); + } + +EXIT_FREE_CONFIG_DATA:; + if (RestExHttpConfigData !=3D NULL) { + FreePool((VOID *)RestExHttpConfigData); + } + if (RestExOpened) { + gBS->CloseProtocol( + Instance->DiscoverToken->DiscoverList.RedfishInstances->Informa= tion.RedfishRestExHandle, + &gEfiRestExProtocolGuid, + Instance->NetworkInterface->OpenDriverAgentHandle, + Instance->NetworkInterface->OpenDriverControllerHandle + ); + } +ERROR_EXIT:; + if (DeleteRestEx && RestExOpened) { + gBS->CloseProtocol( + Instance->DiscoverToken->DiscoverList.RedfishInstances->Informa= tion.RedfishRestExHandle, + &gEfiRestExProtocolGuid, + Instance->NetworkInterface->OpenDriverAgentHandle, + Instance->NetworkInterface->OpenDriverControllerHandle + ); + } +ON_EXIT:; + return Status; +} + +/** + This function gets the subnet information of this network interface inst= ance. + can discover Redfish service on it. + + @param[in] Instance EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERN= AL instance. + @param[in] ImageHandle EFI Image handle request the network interfac= e list. + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +NetworkInterfaceGetSubnetInfo ( + IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *Instance, + IN EFI_HANDLE ImageHandle + ) +{ + EFI_STATUS Status; + UINT32 ProtocolType; + UINT32 IPv6InfoIndex; + EFI_IP6_ADDRESS_INFO *ThisSubnetAddrInfoIPv6; + EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *NewNetworkInterface; + + if (Instance->GotSubnetInfo) { + return EFI_SUCCESS; + } + + ProtocolType =3D Instance->NetworkProtocolType; + if (gRequiredProtocol [ProtocolType].GetSubnetInfo !=3D NULL && Instance= ->GotSubnetInfo =3D=3D FALSE) { + Status =3D gRequiredProtocol [ProtocolType].GetSubnetInfo ( + ImageHandle, + Instance + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR,"%a:Faile to get Subnet infomation.\n", __FUNCTI= ON__)); + return Status; + } else { + DEBUG ((DEBUG_INFO,"%a:MAC address: %s\n", __FUNCTION__, Instance->S= trMacAddr)); + if (CheckIsIpVersion6 (Instance)) { + if (Instance->SubnetAddrInfoIPv6Number =3D=3D 0) { + DEBUG ((DEBUG_ERROR,"%a: There is no Subnet infomation for IPv6 = network interface.\n", __FUNCTION__)); + return EFI_NOT_FOUND; + } + ThisSubnetAddrInfoIPv6 =3D Instance->SubnetAddrInfoIPv6; // First = IPv6 address information. + IP6_COPY_ADDRESS (&Instance->SubnetAddr.v6, &ThisSubnetAddrInfoIPv= 6->Address); + Instance->SubnetPrefixLength =3D ThisSubnetAddrInfoIPv6->PrefixLen= gth; + DEBUG((DEBUG_INFO," IPv6 Subnet ID:%d, Prefix length: %d.\n", + ThisSubnetAddrInfoIPv6->Address.Addr [7] + (UINT16)ThisSubn= etAddrInfoIPv6->Address.Addr [6] * 256, + ThisSubnetAddrInfoIPv6->PrefixLength) + ); + // + // If this is IPv6, then we may have to propagate network interfac= e for IPv6 network scopes + // according to the Ipv6 address information. + // + ThisSubnetAddrInfoIPv6 ++; + for (IPv6InfoIndex =3D 0; IPv6InfoIndex < Instance->SubnetAddrInfo= IPv6Number - 1; IPv6InfoIndex++) { + // + // Build up addtional EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INT= ERNAL instances. + // + NewNetworkInterface =3D (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_= INTERNAL *)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE= _INTERNAL)); + if (NewNetworkInterface !=3D NULL) { + CopyMem ((VOID *)NewNetworkInterface, (VOID *)Instance, sizeof= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL)); // Clone information o= f first instance. + IP6_COPY_ADDRESS (&NewNetworkInterface->SubnetAddr.v6, &ThisSu= bnetAddrInfoIPv6->Address); + NewNetworkInterface->SubnetPrefixLength =3D ThisSubnetAddrInfo= IPv6->PrefixLength; + NewNetworkInterface->GotSubnetInfo =3D TRUE; + InsertTailList (&mEfiRedfishDiscoverNetworkInterface, &NewNetw= orkInterface->Entry); + ThisSubnetAddrInfoIPv6 ++; + mNumNetworkInterface ++; + DEBUG((DEBUG_INFO," IPv6 Subnet ID:%d, Prefix length: %d.\n", + ThisSubnetAddrInfoIPv6->Address.Addr [7] + (UINT16)This= SubnetAddrInfoIPv6->Address.Addr [6] * 256, + ThisSubnetAddrInfoIPv6->PrefixLength) + ); + } else { + return EFI_OUT_OF_RESOURCES; + } + } + } else { + DEBUG ((DEBUG_INFO," IPv4 Subnet:%d.%d.%d.%d Subnet mask: %d.%d.= %d.%d.\n", + Instance->SubnetAddr.v4.Addr [0], + Instance->SubnetAddr.v4.Addr [1], + Instance->SubnetAddr.v4.Addr [2], + Instance->SubnetAddr.v4.Addr [3], + Instance->SubnetMask.v4.Addr [0], + Instance->SubnetMask.v4.Addr [1], + Instance->SubnetMask.v4.Addr [2], + Instance->SubnetMask.v4.Addr [3] + )); + } + } + } + Instance->GotSubnetInfo =3D TRUE; // Only try to get Subnet Info once. + return EFI_SUCCESS; +} + +/** + This function gets the network interface list which Redfish discover pro= tocol + can discover Redfish service on it. + + @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instan= ce. + @param[in] ImageHandle EFI Image handle request the network= interface list, + @param[out] NumberOfNetworkIntfs Number of network interfaces can do = Redfish service discovery. + @param[out] NetworkIntfInstances Network interface instances. It's an= array of instance. The number of entries + in array is indicated by NumberOfNet= workIntfs. + Caller has to release the memory + allocated by Redfish discover protoc= ol. + + @retval EFI_SUCCESS The information of network interface is retur= ned in NumberOfNetworkIntfs and + NetworkIntfInstances. + @retval Others Fail to return the information of network int= erface. + +**/ +EFI_STATUS +EFIAPI +RedfishServiceGetNetworkInterface ( + IN EFI_REDFISH_DISCOVER_PROTOCOL *This, + IN EFI_HANDLE ImageHandle, + OUT UINTN *NumberOfNetworkIntfs, + OUT EFI_REDFISH_DISCOVER_NETWORK_INTERFACE **NetworkIntfInstances +) +{ + EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterfaceInt= n; + EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *ThisNetworkInterface; + + if (NetworkIntfInstances =3D=3D NULL || NumberOfNetworkIntfs =3D=3D NULL= || ImageHandle =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + *NumberOfNetworkIntfs =3D 0; + *NetworkIntfInstances =3D NULL; + + if (IsListEmpty ((const LIST_ENTRY*)&mEfiRedfishDiscoverNetworkInterface= )) { + return EFI_NOT_FOUND; + } + + ThisNetworkInterface =3D (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *)Alloc= ateZeroPool (sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE) * mNumNetworkI= nterface); + if (ThisNetworkInterface =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + *NetworkIntfInstances =3D ThisNetworkInterface; + ThisNetworkInterfaceIntn =3D (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INT= ERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface); + while (TRUE) { + ThisNetworkInterface->IsIpv6 =3D FALSE; + if (CheckIsIpVersion6 (ThisNetworkInterfaceIntn)) { + ThisNetworkInterface->IsIpv6 =3D TRUE; + } + CopyMem((VOID *)&ThisNetworkInterface->MacAddress, &ThisNetworkInterfa= ceIntn->MacAddress, ThisNetworkInterfaceIntn->HwAddressSize); + NetworkInterfaceGetSubnetInfo(ThisNetworkInterfaceIntn, ImageHandle); = // Get subnet info. + if (!ThisNetworkInterface->IsIpv6) { + IP4_COPY_ADDRESS(&ThisNetworkInterface->SubnetId.v4, &ThisNetworkInt= erfaceIntn->SubnetAddr.v4); // IPv4 subnet information. + } else { + IP6_COPY_ADDRESS (&ThisNetworkInterface->SubnetId.v6, &ThisNetworkIn= terfaceIntn->SubnetAddr.v6); // IPv6 subnet information in IPv6 address inf= ormation. + } + ThisNetworkInterface->SubnetPrefixLength =3D ThisNetworkInterfaceIntn-= >SubnetPrefixLength; + ThisNetworkInterface->VlanId =3D ThisNetworkInterfaceIntn->VlanId; + (*NumberOfNetworkIntfs) ++; + if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInt= erfaceIntn->Entry)) { + break; + } + ThisNetworkInterfaceIntn =3D (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_I= NTERNAL *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInt= erfaceIntn->Entry); + ThisNetworkInterface ++; + }; + return EFI_SUCCESS; +} +/** + This function acquires Redfish services by discovering static Redfish se= tting + according to Redfish Host Interface or through SSDP. Returns a list of E= FI + handles in EFI_REDFISH_DISCOVERED_LIST. Each of EFI handle has coorespon= ding + EFI REST EX instance installed on it. Each REST EX isntance is a child i= nstance which + created through EFI REST EX serivce protoocl for communicating with spec= ific + Redfish service. + + @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL inst= ance. + @param[in] ImageHandle EFI image owns these Redfish servi= ce instances. + @param[in] TargetNetworkInterface Target network interface to do the= discovery. + NULL means discover Redfish servic= e on all network interfaces on platform. + @param[in] Flags Redfish service discover flags. + @param[in] Token EFI_REDFISH_DISCOVERED_TOKEN insta= nce. + The memory of EFI_REDFISH_DISCOVER= ED_LIST and the strings in + EFI_REDFISH_DISCOVERED_INFORMATION= are all allocated by Acquire() + and must be freed when caller invo= ke Release(). + + @retval EFI_SUCCESS REST EX instance of discovered Redfish s= ervices are returned. + @retval EFI_INVALID_PARAMETERS ImageHandle =3D=3D NULL, Flags =3D=3D 0,= Token =3D=3D NULL, Token->Timeout > 5, + or Token->Event =3D=3D NULL. + @retval Others Fail acquire Redfish services. + +**/ +EFI_STATUS +EFIAPI +RedfishServiceAcquireService ( + IN EFI_REDFISH_DISCOVER_PROTOCOL *This, + IN EFI_HANDLE ImageHandle, + IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *TargetNetworkInterface, + IN EFI_REDFISH_DISCOVER_FLAG Flags, + IN EFI_REDFISH_DISCOVERED_TOKEN *Token + ) +{ + EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *Instance; + EFI_STATUS Status1; + EFI_STATUS Status2; + BOOLEAN NewInstance; + UINTN NumNetworkInterfaces; + UINTN NetworkInterfacesIndex; + EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *TargetNetworkInterfaceI= nternal; + + DEBUG ((DEBUG_INFO,"%a:Entry.\n", __FUNCTION__)); + + // + // Validate parameters. + // + if (ImageHandle =3D=3D NULL || Token =3D=3D NULL || ((Flags & ~EFI_REDFI= SH_DISCOVER_VALIDATION) =3D=3D 0)) { + DEBUG ((DEBUG_ERROR,"%a:Invalid parameters.\n", __FUNCTION__)); + return EFI_INVALID_PARAMETER; + } + // + // Validate target network interface. + // + if (EFI_ERROR (ValidateTargetNetworkInterface (TargetNetworkInterface, F= lags))) { + return EFI_UNSUPPORTED; + } + if (TargetNetworkInterface !=3D NULL) { + TargetNetworkInterfaceInternal =3D GetTargetNetworkInterfaceInternal (= TargetNetworkInterface); + NumNetworkInterfaces =3D 1; + } else { + TargetNetworkInterfaceInternal =3D (EFI_REDFISH_DISCOVER_NETWORK_INTER= FACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface); + NumNetworkInterfaces =3D NumberOfNetworkInterface (); + if (NumNetworkInterfaces =3D=3D 0) { + DEBUG ((DEBUG_ERROR,"%a:No network interface on platform.\n", __FUNC= TION__)); + return EFI_UNSUPPORTED; + } + } + for (NetworkInterfacesIndex =3D 0; NetworkInterfacesIndex < NumNetworkIn= terfaces; NetworkInterfacesIndex ++) { + Status1 =3D EFI_SUCCESS; + Status2 =3D EFI_SUCCESS; + NewInstance =3D FALSE; + Instance =3D GetInstanceByOwner (ImageHandle, TargetNetworkInterfaceIn= ternal, Flags & ~EFI_REDFISH_DISCOVER_VALIDATION); // Check if we can re-us= e previous instance. + if (Instance =3D=3D NULL) { + DEBUG ((DEBUG_INFO,"%a:Create new EFI_REDFISH_DISCOVERED_INTERNAL_IN= STANCE.\n", __FUNCTION__)); + Instance =3D (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *)AllocateZer= oPool(sizeof(EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE)); + if (Instance =3D=3D NULL) { + DEBUG ((DEBUG_ERROR,"%a:Memory allocation fail.\n", __FUNCTION__)); + } + InitializeListHead (&Instance->Entry); + Instance->Owner =3D ImageHandle; + Instance->DiscoverFlags =3D Flags & ~EFI_REDFISH_DISCOVER_VALIDATION; + Instance->NetworkInterface =3D TargetNetworkInterfaceInternal; + // + // Get subnet information in case subnet information is not set beca= use + // RedfishServiceGetNetworkInterfaces hasn't been called yet. + // + NetworkInterfaceGetSubnetInfo (TargetNetworkInterfaceInternal, Image= Handle); + NewInstance =3D TRUE; + } + if (TargetNetworkInterfaceInternal->StrMacAddr !=3D NULL) { + DEBUG((DEBUG_INFO,"%a:Acquire Redfish service on network interface M= AC address:%s.\n", __FUNCTION__, TargetNetworkInterfaceInternal->StrMacAddr= )); + } else { + DEBUG((DEBUG_INFO,"%a:WARNING: No MAC address on this network interf= ace.\n", __FUNCTION__)); + } + + Instance->DiscoverToken =3D Token; // Always use the latest Token pass= ed by caller. + if ((Flags & EFI_REDFISH_DISCOVER_HOST_INTERFACE) !=3D 0) { + DEBUG ((DEBUG_INFO,"%a:Redfish HOST interface discovery.\n", __FUNCT= ION__)); + Instance->HostIntfValidation =3D FALSE; + if ((Flags & EFI_REDFISH_DISCOVER_VALIDATION) !=3D 0) { + Instance->HostIntfValidation =3D TRUE; + } + Status1 =3D DiscoverRedfishHostInterface (Instance); // Discover Red= fish service through Redfish Host Interface. + } + if ((Flags & EFI_REDFISH_DISCOVER_SSDP) !=3D 0) { + DEBUG ((DEBUG_ERROR,"%a:Redfish service discovery through SSDP is no= t supported\n", __FUNCTION__)); + return EFI_UNSUPPORTED; + } else { + if (EFI_ERROR (Status1) && EFI_ERROR (Status2)) { + FreePool ((VOID *)Instance); + DEBUG ((DEBUG_ERROR,"%a:Something wrong on Redfish service discove= ry Status1=3D%x, Status2=3D%x.\n", __FUNCTION__, Status1, Status2)); + } else { + if (NewInstance) { + InsertTailList(&mRedfishDiscoverList, &Instance->Entry); + } + } + } + if (TargetNetworkInterface =3D=3D NULL) { + // + // Discover Redfish services on all of network interfaces. + // + TargetNetworkInterfaceInternal =3D (EFI_REDFISH_DISCOVER_NETWORK_INT= ERFACE_INTERNAL *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, &Target= NetworkInterfaceInternal->Entry); + } + } + return EFI_SUCCESS; +} + +/** + This function aborts Redfish service discovery on the given network inte= rface. + + @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL inst= ance. + @param[in] TargetNetworkInterface Target network interface to do the= discovery. + + @retval EFI_SUCCESS REST EX instance of discovered Redfish s= ervices are returned. + @retval Others Fail to abort Redfish service discovery. + +**/ +EFI_STATUS +EFIAPI +RedfishServiceAbortAcquire ( + IN EFI_REDFISH_DISCOVER_PROTOCOL *This, + IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *TargetNetworkInterface OPTIO= NAL +) +{ + // This function is used to abort Redfish service discovery through SSDP + // on the network interface. SSDP is optionally supprted by EFI_REDFISH_= DISCOVER_PROTOCOL, + // we dont have implementation for SSDP now. + + return EFI_UNSUPPORTED; +} + +/** + This function releases Redfish services found by RedfishServiceAcquire(). + + @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instance. + @param[in] InstanceList The Redfish service to release. + + @retval EFI_SUCCESS REST EX instances of discovered Redfish are r= eleased. + @retval Others Fail to remove the entry + +**/ +EFI_STATUS +EFIAPI +RedfishServiceReleaseService ( + IN EFI_REDFISH_DISCOVER_PROTOCOL *This, + IN EFI_REDFISH_DISCOVERED_LIST *InstanceList + ) +{ + UINTN NumService; + BOOLEAN AnyFailRelease; + EFI_REDFISH_DISCOVERED_INSTANCE *ThisRedfishInstance; + EFI_REDFISH_DISCOVERED_INTERNAL_LIST *DiscoveredRedfishInstance; + + if (IsListEmpty (&mRedfishInstanceList)) { + DEBUG ((DEBUG_ERROR,"%a:No any discovered Redfish service.\n", __FUNCT= ION__)); + return EFI_NOT_FOUND; + } + AnyFailRelease =3D FALSE; + ThisRedfishInstance =3D InstanceList->RedfishInstances; + for (NumService =3D 0; NumService < InstanceList->NumberOfServiceFound; = NumService ++) { + DiscoveredRedfishInstance =3D (EFI_REDFISH_DISCOVERED_INTERNAL_LIST *)= GetFirstNode(&mRedfishInstanceList); + do { + if (DiscoveredRedfishInstance->Instance =3D=3D ThisRedfishInstance) { + RemoveEntryList (&DiscoveredRedfishInstance->NextInstance); + if (ThisRedfishInstance->Information.Location !=3D NULL) { + FreePool (ThisRedfishInstance->Information.Location); + } + if (ThisRedfishInstance->Information.Uuid !=3D NULL) { + FreePool (ThisRedfishInstance->Information.Uuid); + } + if (ThisRedfishInstance->Information.Os !=3D NULL) { + FreePool (ThisRedfishInstance->Information.Os); + } + if (ThisRedfishInstance->Information.OsVersion !=3D NULL) { + FreePool (ThisRedfishInstance->Information.OsVersion); + } + if (ThisRedfishInstance->Information.Product !=3D NULL) { + FreePool (ThisRedfishInstance->Information.Product); + } + if (ThisRedfishInstance->Information.ProductVer !=3D NULL) { + FreePool (ThisRedfishInstance->Information.ProductVer); + } + FreePool((VOID *)ThisRedfishInstance); + goto ReleaseNext; + } + + if (IsNodeAtEnd(&mRedfishInstanceList, &DiscoveredRedfishInstance->N= extInstance)) { + break; + } + DiscoveredRedfishInstance =3D (EFI_REDFISH_DISCOVERED_INTERNAL_LIST = *)GetNextNode(&mRedfishInstanceList, &DiscoveredRedfishInstance->NextInstan= ce); + } while (TRUE); + AnyFailRelease =3D TRUE; +ReleaseNext:; + // + // Release next discovered Redfish Service. + // + ThisRedfishInstance =3D (EFI_REDFISH_DISCOVERED_INSTANCE *)((UINT8 *)T= hisRedfishInstance + sizeof (EFI_REDFISH_DISCOVERED_INSTANCE)); + } + if (AnyFailRelease) { + return EFI_NOT_FOUND; + } else { + return EFI_SUCCESS; + } +} + +EFI_REDFISH_DISCOVER_PROTOCOL mRedfishDiscover =3D { + RedfishServiceGetNetworkInterface, + RedfishServiceAcquireService, + RedfishServiceAbortAcquire, + RedfishServiceReleaseService +}; + +/** + This function create an EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL = for the + given network interface. + + + @param[in] ControllerHandle MAC address of this network interface. + @param[in] NetworkProtocolType Network protocol type. + @param[out] IsNewInstance BOOLEAN means new instance or not. + @param[out] NetworkInterface Pointer to to EFI_REDFISH_DISCOVER_NETWO= RK_INTERFACE_INTERNAL. + + @retval EFI_STATUS +**/ +EFI_STATUS +CreateRedfishDiscoverNetworkInterface ( + IN EFI_HANDLE ControllerHandle, + IN UINT32 NetworkProtocolType, + OUT BOOLEAN *IsNewInstance, + OUT EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL **NetworkInterface + ) +{ + EFI_MAC_ADDRESS MacAddress; + UINTN HwAddressSize; + EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterface; + EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *NewNetworkInterface; + + NetLibGetMacAddress (ControllerHandle, &MacAddress, &HwAddressSize); + NewNetworkInterface =3D NULL; + *IsNewInstance =3D TRUE; + if (!IsListEmpty ((const LIST_ENTRY*)&mEfiRedfishDiscoverNetworkInterfac= e)) { + // + // Check if this instance already exist. + // + ThisNetworkInterface =3D (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTER= NAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface); + if (ThisNetworkInterface !=3D NULL) { + while (TRUE) { + if ((CompareMem ((CONST VOID *)&ThisNetworkInterface->MacAddress.A= ddr, (CONST VOID *)&MacAddress.Addr, HwAddressSize) =3D=3D 0) && + (ThisNetworkInterface->NetworkProtocolType =3D=3D NetworkProt= ocolType)){ + NewNetworkInterface =3D ThisNetworkInterface; + *IsNewInstance =3D FALSE; + break; + } + if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetwor= kInterface->Entry)) { + NewNetworkInterface =3D NULL; + break; + } + ThisNetworkInterface =3D (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_I= NTERNAL *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInt= erface->Entry); + }; + } + } + if (NewNetworkInterface =3D=3D NULL) { + // + // Create a new instance. + // + NewNetworkInterface =3D (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERN= AL *)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTER= NAL)); + if (NewNetworkInterface =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + NewNetworkInterface->HwAddressSize =3D HwAddressSize; + CopyMem (&NewNetworkInterface->MacAddress.Addr, &MacAddress.Addr, NewN= etworkInterface->HwAddressSize); + NetLibGetMacString (ControllerHandle, NULL, &NewNetworkInterface->StrM= acAddr); + NewNetworkInterface->VlanId =3D NetLibGetVlanId (ControllerHandle); + } + *NetworkInterface =3D NewNetworkInterface; + return EFI_SUCCESS; +} + +/** + This function destory network interface + + + @param[in] ThisNetworkInterface EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_= INTERNAL instance. + + @retval EFI_STATUS +**/ +EFI_STATUS +DestroyRedfishNetwrokInterface ( + IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterface + ) +{ + EFI_STATUS Status; + + Status =3D gBS->UninstallProtocolInterface( + ThisNetworkInterface->OpenDriverControllerHandle, + gRequiredProtocol [ThisNetworkInterface->NetworkProtocol= Type].DiscoveredProtocolGuid, + &ThisNetworkInterface->NetworkInterfaceProtocolInfo.Prot= ocolDiscoverId + ); + RemoveEntryList (&ThisNetworkInterface->Entry); + mNumNetworkInterface --; + FreePool (ThisNetworkInterface); + return Status; +} + +/** + Tests to see if the required protocols are provided on the given + controller handle. + + @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. + @retval EFI_SUCCESS One of required protocol is found. + @retval EFI_UNSUPPORTED None of required protocol is found. +**/ +EFI_STATUS +TestForRequiredProtocols ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle + ) +{ + UINT32 Id; + UINTN Index; + EFI_STATUS Status; + + for (Index =3D 0; Index < (sizeof (gRequiredProtocol) / sizeof (REDFISH_= DISCOVER_REQUIRED_PROTOCOL)); Index ++) { + Status =3D gBS->OpenProtocol ( + ControllerHandle, + gRequiredProtocol [Index].RequiredServiceBindingProtocol= Guid, + NULL, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + Status =3D gBS->OpenProtocol ( + ControllerHandle, + gRequiredProtocol [Index].DiscoveredProtocolGuid, + (VOID **) &Id, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "%a: %s is found on this controller handle.\n"= , __FUNCTION__, gRequiredProtocol [Index].ProtocolName)); + return EFI_SUCCESS; + } + } + } + return EFI_UNSUPPORTED; +} + +/** + Build up network interface and create corresponding service through the = given + controller handle. + + @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. + @retval EFI_SUCCESS One of required protocol is found. + @retval EFI_UNSUPPORTED None of required protocol is found. + @retval EFI_UNSUPPORTED Failed to build up network interface. +**/ +EFI_STATUS +BuildupNetworkInterface ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle + ) +{ + UINT32 Id; + UINT32 Index; + EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *NetworkInterface; + BOOLEAN IsNew; + EFI_STATUS Status; + VOID *TempInterface; + VOID **Interface; + UINT32 *ProtocolDiscoverIdPtr; + EFI_HANDLE OpenDriverAgentHandle; + EFI_HANDLE OpenDriverControllerHandle; + EFI_HANDLE *HandleOfProtocolInterfacePtr; + EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL *RestExInstance; + EFI_TPL OldTpl; + BOOLEAN NewNetworkInterfaceInstalled; + + NewNetworkInterfaceInstalled =3D FALSE; + Index =3D 0; + do { + Status =3D gBS->OpenProtocol ( // Already in list? + ControllerHandle, + gRequiredProtocol [Index].DiscoveredProtocolGuid, + (VOID **) &Id, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + Index ++; + if (Index =3D=3D (sizeof(gRequiredProtocol) / sizeof(REDFISH_DISCOVE= R_REQUIRED_PROTOCOL))) { + break; + } + continue; + } + + Status =3D gBS->OpenProtocol ( + ControllerHandle, + gRequiredProtocol [Index].RequiredServiceBindingProtoc= olGuid, + &TempInterface, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + Index ++; + if (Index =3D=3D (sizeof(gRequiredProtocol) / sizeof(REDFISH_DISCOVE= R_REQUIRED_PROTOCOL))) { + break; + } + continue; + } + if (gRequiredProtocol [Index].ProtocolType !=3D ProtocolTypeRestEx) { + OldTpl =3D gBS->RaiseTPL (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL= ); + Status =3D CreateRedfishDiscoverNetworkInterface(ControllerHandle, g= RequiredProtocol [Index].ProtocolType, &IsNew, &NetworkInterface); + if (EFI_ERROR (Status)) { + gBS->RestoreTPL (OldTpl); + return Status; + } + NetworkInterface->NetworkProtocolType =3D gRequiredProtocol [Index].= ProtocolType; + NetworkInterface->OpenDriverAgentHandle =3D This->DriverBindingHandl= e; + NetworkInterface->OpenDriverControllerHandle =3D ControllerHandle; + NetworkInterface->NetworkInterfaceProtocolInfo.ProtocolGuid =3D \ + *gRequiredProtocol [Index].RequiredProtocolGuid; + NetworkInterface->NetworkInterfaceProtocolInfo.ProtocolServiceGuid = =3D \ + *gRequiredProtocol [Index].RequiredServiceBindingProtocolGuid; + ProtocolDiscoverIdPtr =3D &NetworkInterface->NetworkInterfaceProtoco= lInfo.ProtocolDiscoverId; + OpenDriverAgentHandle =3D NetworkInterface->OpenDriverAgentHandle; + OpenDriverControllerHandle =3D NetworkInterface->OpenDriverControlle= rHandle; + HandleOfProtocolInterfacePtr =3D &NetworkInterface->NetworkInterface= ProtocolInfo.ProtocolControllerHandle; + Interface =3D &NetworkInterface->NetworkInterfaceProtocolInfo.Networ= kProtocolInterface; + NewNetworkInterfaceInstalled =3D TRUE; + if (IsNew) { + InsertTailList (&mEfiRedfishDiscoverNetworkInterface, &NetworkInte= rface->Entry); + mNumNetworkInterface ++; + } + gBS->RestoreTPL (OldTpl); + } else { + // Record REST_EX instance. REST_EX is created when clinet asks for = Redfish service discovery. + // Redfish Service Discover protocol will match REST EX to the corre= sponding EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL + // when discovery. + + RestExInstance =3D (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL *= )AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL)); + if (RestExInstance =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + RestExInstance->OpenDriverAgentHandle =3D This->DriverBindingHandle; + RestExInstance->OpenDriverControllerHandle =3D ControllerHandle; + RestExInstance->RestExControllerHandle =3D ControllerHandle; + InitializeListHead (&RestExInstance->Entry); + InsertTailList (&mEfiRedfishDiscoverRestExInstance, &RestExInstance-= >Entry); + mNumRestExInstance ++; + ProtocolDiscoverIdPtr =3D &RestExInstance->RestExId; + OpenDriverAgentHandle =3D RestExInstance->OpenDriverAgentHandle; + OpenDriverControllerHandle =3D RestExInstance->OpenDriverControllerH= andle; + HandleOfProtocolInterfacePtr =3D &RestExInstance->RestExChildHandle; + Interface =3D (VOID **)&RestExInstance->RestExProtocolInterface; + } + Status =3D gBS->InstallProtocolInterface ( + &ControllerHandle, + gRequiredProtocol [Index].DiscoveredProtocolGuid, + EFI_NATIVE_INTERFACE, + ProtocolDiscoverIdPtr + ); + if (EFI_ERROR (Status)) { + Index ++; + if (Index =3D=3D (sizeof(gRequiredProtocol) / sizeof(REDFISH_DISCOVE= R_REQUIRED_PROTOCOL))) { + break; + } + continue; + } + // + // Create service binding child and open it BY_DRIVER. + // + Status =3D NetLibCreateServiceChild ( + ControllerHandle, + This->ImageHandle, + gRequiredProtocol [Index].RequiredServiceBindingProtocolGuid, + HandleOfProtocolInterfacePtr + ); + if (!EFI_ERROR (Status)) { + Status =3D gBS->OpenProtocol ( + *HandleOfProtocolInterfacePtr, + gRequiredProtocol [Index].RequiredProtocolGuid, + Interface, + OpenDriverAgentHandle, + OpenDriverControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (!EFI_ERROR (Status)) { + if (EfiRedfishDiscoverProtocolHandle =3D=3D NULL && + (gRequiredProtocol [Index].ProtocolType =3D=3D ProtocolTypeRes= tEx) && + !IsListEmpty (&mEfiRedfishDiscoverNetworkInterface) + ) { + // Install the fisrt Redfish Discover Protocol when EFI REST EX = protcol is discovered. + // This ensures EFI REST EX is ready while EFI_REDFISH_DISCOVER_= PROTOCOL consumer acquires + // Redfish serivce over network interface. + + Status =3D gBS->InstallProtocolInterface ( + &EfiRedfishDiscoverProtocolHandle, + &gEfiRedfishDiscoverProtocolGuid, + EFI_NATIVE_INTERFACE, + (VOID *)&mRedfishDiscover + ); + } else if (EfiRedfishDiscoverProtocolHandle !=3D NULL && NewNetwor= kInterfaceInstalled) { + Status =3D gBS->ReinstallProtocolInterface ( + EfiRedfishDiscoverProtocolHandle, + &gEfiRedfishDiscoverProtocolGuid, + (VOID *)&mRedfishDiscover, + (VOID *)&mRedfishDiscover + ); + NewNetworkInterfaceInstalled =3D FALSE; + } + } + return Status; + } else { + Index ++; + if (Index =3D=3D (sizeof(gRequiredProtocol) / sizeof(REDFISH_DISCOVE= R_REQUIRED_PROTOCOL))) { + break; + } + continue; + } + } while (Index < (sizeof(gRequiredProtocol) / sizeof(REDFISH_DISCOVER_RE= QUIRED_PROTOCOL))); + return EFI_UNSUPPORTED; +} +/** + Close the protocol opened for Redfish discovery. This function also dest= ories + the network services. + + @param[in] ThisBindingProtocol A pointer to the EFI_DRIVER_BINDING_= PROTOCOL instance. + @param[in] ControllerHandle The handle of the controller to test= . This handle + must support a protocol interface th= at supplies + an I/O abstraction to the driver. + @param[in] ThisRequiredProtocol Pointer to the instance of REDFISH_D= ISCOVER_REQUIRED_PROTOCOL. + @param[in] DriverAgentHandle Driver agent handle which used to ope= n protocol earlier. + @param[in] DriverControllerHandle Driver controller handle which used t= o open protocol earlier. + + @retval EFI_SUCCESS Prorocol is closed successfully. + @retval Others Prorocol is closed unsuccessfully. + +**/ +EFI_STATUS +CloseProtocolService ( + IN EFI_DRIVER_BINDING_PROTOCOL *ThisBindingProtocol, + IN EFI_HANDLE ControllerHandle, + IN REDFISH_DISCOVER_REQUIRED_PROTOCOL *ThisRequiredProtocol, + IN EFI_HANDLE DriverAgentHandle, + IN EFI_HANDLE DriverControllerHandle +) +{ + EFI_STATUS Status; + + Status =3D gBS->CloseProtocol ( + ControllerHandle, + ThisRequiredProtocol->RequiredProtocolGuid, + DriverAgentHandle, + DriverControllerHandle + ); + if (!EFI_ERROR (Status)) { + NetLibDestroyServiceChild( + ControllerHandle, + ThisBindingProtocol->ImageHandle, + ThisRequiredProtocol->RequiredServiceBindingProtocolGuid, + ControllerHandle + ); + } + return Status; +} +/** + Stop the services on network interface. + + @param[in] ThisBindingProtocol 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. + @retval EFI_SUCCESS One of required protocol is found. + @retval Others Faile to stop the services on network i= nterface. +**/ +EFI_STATUS +StopServiceOnNetworkInterface ( + IN EFI_DRIVER_BINDING_PROTOCOL *ThisBindingProtocol, + IN EFI_HANDLE ControllerHandle + ) +{ + UINT32 Index; + EFI_STATUS Status; + VOID *Interface; + EFI_TPL OldTpl; + EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterface; + EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL *RestExInstance; + + for (Index =3D 0; Index < (sizeof (gRequiredProtocol) / sizeof (REDFISH_= DISCOVER_REQUIRED_PROTOCOL)); Index ++) { + Status =3D gBS->HandleProtocol ( + ControllerHandle, + gRequiredProtocol [Index].RequiredProtocolGuid, + (VOID **)&Interface + ); + if (!EFI_ERROR (Status)) { + if (gRequiredProtocol [Index].ProtocolType !=3D ProtocolTypeRestEx) { + if (IsListEmpty (&mEfiRedfishDiscoverNetworkInterface)) { + return EFI_NOT_FOUND; + } + OldTpl =3D gBS->RaiseTPL (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_T= PL); + ThisNetworkInterface =3D (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_I= NTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface); + while (TRUE) { + if (ThisNetworkInterface->NetworkInterfaceProtocolInfo.ProtocolC= ontrollerHandle =3D=3D ControllerHandle) { + + Status =3D CloseProtocolService ( // Close protocol and destro= y service. + ThisBindingProtocol, + ControllerHandle, + &gRequiredProtocol [Index], + ThisNetworkInterface->OpenDriverAgentHandle, + ThisNetworkInterface->OpenDriverControllerHandle + ); + if (!EFI_ERROR (Status)) { + Status =3D DestroyRedfishNetwrokInterface (ThisNetworkInterf= ace); + } + gBS->RestoreTPL (OldTpl); + // Reinstall Redfish Discover protocol to notify network + // interface change. + + Status =3D gBS->ReinstallProtocolInterface ( + EfiRedfishDiscoverProtocolHandle, + &gEfiRedfishDiscoverProtocolGuid, + (VOID *)&mRedfishDiscover, + (VOID *)&mRedfishDiscover + ); + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "%a: Reinstall gEfiRedfishDiscoverProtoc= olGuid fail.", __FUNCTION__)); + } + return Status; + } + if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetw= orkInterface->Entry)) { + break; + } + ThisNetworkInterface =3D (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE= _INTERNAL *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkI= nterface->Entry); + }; + gBS->RestoreTPL (OldTpl); + } else { + if (IsListEmpty (&mEfiRedfishDiscoverRestExInstance)) { + return EFI_NOT_FOUND; + } + OldTpl =3D gBS->RaiseTPL (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_T= PL); + RestExInstance =3D (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL= *)GetFirstNode (&mEfiRedfishDiscoverRestExInstance); + while (TRUE) { + if (RestExInstance->RestExChildHandle =3D=3D ControllerHandle) { + Status =3D CloseProtocolService ( // Close REST_EX protocol. + ThisBindingProtocol, + ControllerHandle, + &gRequiredProtocol [Index], + RestExInstance->OpenDriverAgentHandle, + RestExInstance->OpenDriverControllerHandle + ); + RemoveEntryList (&RestExInstance->Entry); + FreePool ((VOID *)RestExInstance); + mNumRestExInstance --; + gBS->RestoreTPL (OldTpl); + return Status; + } + if (IsNodeAtEnd (&mEfiRedfishDiscoverRestExInstance, &RestExInst= ance->Entry)) { + break; + } + RestExInstance =3D (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERN= AL *)GetNextNode(&mEfiRedfishDiscoverRestExInstance, &RestExInstance->Entry= ); + }; + gBS->RestoreTPL (OldTpl); + } + } + } + return EFI_NOT_FOUND; +} +/** + 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 +RedfishDiscoverDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +{ + return TestForRequiredProtocols (This, ControllerHandle); +} + +/** + 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 +RedfishDiscoverDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +{ + return BuildupNetworkInterface (This, ControllerHandle); +} + +/** + 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 +RedfishDiscoverDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer OPTIONAL + ) +{ + return StopServiceOnNetworkInterface (This, ControllerHandle); +} + +EFI_DRIVER_BINDING_PROTOCOL gRedfishDiscoverDriverBinding =3D { + RedfishDiscoverDriverBindingSupported, + RedfishDiscoverDriverBindingStart, + RedfishDiscoverDriverBindingStop, + REDFISH_DISCOVER_VERSION, + NULL, + NULL +}; + +/** + This is the declaration of an EFI image entry point. + + @param ImageHandle The firmware allocated handle for the UEFI= image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The operation completed successfully. + @retval Others An unexpected error occurred. +**/ +EFI_STATUS +EFIAPI +RedfishDiscoverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status =3D EFI_SUCCESS; + InitializeListHead (&mRedfishDiscoverList); + InitializeListHead (&mRedfishInstanceList); + InitializeListHead (&mEfiRedfishDiscoverNetworkInterface); + InitializeListHead (&mEfiRedfishDiscoverRestExInstance); + // + // Install binding protoocl to obtain UDP and REST EX protocol. + // + Status =3D EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gRedfishDiscoverDriverBinding, + ImageHandle, + &gRedfishDiscoverComponentName, + &gRedfishDiscoverComponentName2 + ); + return Status; +} + +/** + This is the unload handle for Redfish discover module. + + Disconnect the driver specified by ImageHandle from all the devices in t= he handle database. + Uninstall all the protocols installed in the driver entry point. + + @param[in] ImageHandle The drivers' driver image. + + @retval EFI_SUCCESS The image is unloaded. + @retval Others Failed to unload the image. + +**/ +EFI_STATUS +EFIAPI +RedfishDiscoverUnload ( + IN EFI_HANDLE ImageHandle + ) +{ + EFI_STATUS Status; + EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterface; + + Status =3D EFI_SUCCESS; + // Destroy all network interfaces found by EFI Redfish Discover driver a= nd + // stop services created for Redfish Discover. + + while (!IsListEmpty (&mEfiRedfishDiscoverNetworkInterface)) { + ThisNetworkInterface =3D (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTER= NAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface); + StopServiceOnNetworkInterface (&gRedfishDiscoverDriverBinding, ThisNet= workInterface->NetworkInterfaceProtocolInfo.ProtocolControllerHandle); + }; + // Disconnect EFI Redfish discover driver controller to notify the + // clinet which uses .EFI Redfish discover protocol. + + if (EfiRedfishDiscoverProtocolHandle !=3D NULL) { + // + // Notify user EFI_REDFISH_DISCOVER_PROTOCOL is unloaded. + // + gBS->DisconnectController (EfiRedfishDiscoverProtocolHandle, NULL, NUL= L); + Status =3D gBS->UninstallProtocolInterface( + EfiRedfishDiscoverProtocolHandle, + &gEfiRedfishDiscoverProtocolGuid, + (VOID *)&mRedfishDiscover + ); + } + return Status; +} diff --git a/RedfishPkg/RedfishDiscoverDxe/RedfishSmbiosHostInterface.c b/R= edfishPkg/RedfishDiscoverDxe/RedfishSmbiosHostInterface.c new file mode 100644 index 0000000000..f3ad36ec3a --- /dev/null +++ b/RedfishPkg/RedfishDiscoverDxe/RedfishSmbiosHostInterface.c @@ -0,0 +1,118 @@ +/** @file + RedfishSmbiosHostInterface.c + + Discover Redfish SMBIOS Host Interface. + + (C) Copyright 2021 Hewlett Packard Enterprise Development LP
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "RedfishDiscoverInternal.h" + +SMBIOS_TABLE_TYPE42 *mType42Record; + +/** + The function gets information reported in Redfish Host Interface. + + It simply frees the packet. + + @param[in] Smbios SMBIOS protocol. + @param[out] DeviceDescriptor Pointer to REDFISH_INTERFACE_DATA. + @param[out] ProtocolData Pointer to REDFISH_OVER_IP_PROTOCOL_DATA. + + @retval EFI_SUCCESS Get host interface succesfully. + @retval Otherwise Fail to tet host interface. + +**/ +EFI_STATUS +RedfishGetHostInterfaceProtocolData ( + IN EFI_SMBIOS_PROTOCOL *Smbios, + OUT REDFISH_INTERFACE_DATA **DeviceDescriptor, + OUT REDFISH_OVER_IP_PROTOCOL_DATA **ProtocolData + ) +{ + EFI_STATUS Status; + EFI_SMBIOS_HANDLE SmbiosHandle; + EFI_SMBIOS_TABLE_HEADER *Record; + UINT16 Offset; + UINT8 *RecordTmp; + UINT8 ProtocolLength; + UINT8 SpecificDataLen; + + if ((Smbios =3D=3D NULL) || (ProtocolData =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + } + + SmbiosHandle =3D SMBIOS_HANDLE_PI_RESERVED; + Status =3D Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, NULL); + while (!EFI_ERROR (Status) && SmbiosHandle !=3D SMBIOS_HANDLE_PI_RESERVE= D) { + if (Record->Type =3D=3D SMBIOS_TYPE_MANAGEMENT_CONTROLLER_HOST_INTERFA= CE) { + // + // Check Interface Type, should be Network Host Interface =3D 40h + // + mType42Record =3D (SMBIOS_TABLE_TYPE42 *) Record; + if (mType42Record->InterfaceType =3D=3D MCHostInterfaceTypeNetworkHo= stInterface) { + ASSERT (Record->Length >=3D 9); + Offset =3D 5; + RecordTmp =3D (UINT8 *) Record + Offset; + // + // Get interface specific data length. + // + SpecificDataLen =3D *RecordTmp; + Offset +=3D 1; + RecordTmp =3D (UINT8 *) Record + Offset; + + // + // Check Device Type, only PCI/PCIe Network Interface v2 is suppor= ted now. + // + if (*RecordTmp =3D=3D REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE_= V2) { + ASSERT (SpecificDataLen =3D=3D sizeof (PCI_OR_PCIE_INTERFACE_DEV= ICE_DESCRIPTOR_V2) + 1); + *DeviceDescriptor =3D (REDFISH_INTERFACE_DATA *)RecordTmp; + Offset =3D Offset + SpecificDataLen; + RecordTmp =3D (UINT8 *) Record + Offset; + // + // Check Protocol count. if > 1, only use the first protocol. + // + ASSERT (*RecordTmp =3D=3D 1); + Offset +=3D 1; + RecordTmp =3D (UINT8 *) Record + Offset; + // + // Check protocol identifier. + // + if (*RecordTmp =3D=3D MCHostInterfaceProtocolTypeRedfishOverIP) { + Offset +=3D 1; + RecordTmp =3D (UINT8 *) Record + Offset; + ProtocolLength =3D *RecordTmp; + + Offset +=3D 1; + RecordTmp =3D (UINT8 *) Record + Offset; + + // + // This SMBIOS record is invalid, if the length of protocol sp= ecific data for + // Redfish Over IP protocol is wrong. + // + if ((*(RecordTmp + 90) + sizeof (REDFISH_OVER_IP_PROTOCOL_DATA= ) - 1) !=3D ProtocolLength) { + return EFI_SECURITY_VIOLATION; + } + + Offset +=3D ProtocolLength; + // + // This SMBIOS record is invalid, if the length is smaller tha= n the offset. + // + if (Offset > mType42Record->Hdr.Length) { + return EFI_SECURITY_VIOLATION; + } + *ProtocolData =3D (REDFISH_OVER_IP_PROTOCOL_DATA *)RecordTmp; + return EFI_SUCCESS; + } + } + } + } + Status =3D Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, NULL= ); + } + + *ProtocolData =3D NULL; + return EFI_NOT_FOUND; +} --=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 (#73308): https://edk2.groups.io/g/devel/message/73308 Mute This Topic: https://groups.io/mt/81621784/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-