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/RedfishSmbiosHostInterface.c
EDK2 EFI Redfish Discover Protocol implementation. Refer to UEFI spec 2.9
section 31.1.
Signed-off-by: Abner Chang <abner.chang@hpe.com>
Cc: Nickle Wang <nickle.wang@hpe.com>
Cc: Jiaxin Wu <jiaxin.wu@intel.com>
Cc: Siyuan Fu <siyuan.fu@intel.com>
Cc: Fan Wang <fan.wang@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
---
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/RedfishSmbiosHostInterface.c
diff --git a/RedfishPkg/RedfishComponents.dsc.inc b/RedfishPkg/RedfishComponents.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<BR>
+# (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
#
# 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<BR>
+# (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
#
# 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/RedfishPkg/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<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001b
+ BASE_NAME = RedfishDiscoverDxe
+ FILE_GUID = 28A76FE5-43D7-48A3-9714-C1B7BDD6DFB6
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = RedfishDiscoverEntryPoint
+ UNLOAD_IMAGE = 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 ## CONSUMES
+
diff --git a/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverInternal.h b/RedfishPkg/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<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef EFI_REDFISH_DISCOVER_INTERNAL_H_
+#define EFI_REDFISH_DISCOVER_INTERNAL_H_
+
+#include <Uefi.h>
+
+#include <Protocol/ComponentName.h>
+#include <Protocol/ComponentName2.h>
+#include <Protocol/DriverBinding.h>
+#include <Protocol/RedfishDiscover.h>
+#include <Protocol/Smbios.h>
+#include <Protocol/Tcp4.h>
+#include <Protocol/Tcp6.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/NetLib.h>
+#include <Library/PrintLib.h>
+#include <Library/RestExLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+
+#include <IndustryStandard/RedfishHostInterface.h>
+
+#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 = 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 network protocol handle.
+ EFI_HANDLE ProtocolControllerHandle; ///< The controller handle on network protocol.
+ VOID *NetworkProtocolInterface; ///< The protocol interface of network 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 network protocol.
+ EFI_HANDLE OpenDriverControllerHandle; ///< The controller handle to open network protocol.
+ UINTN HwAddressSize; ///< The size of network interface hardware address.
+ EFI_MAC_ADDRESS MacAddress; ///< MAC address of network interface.
+ CHAR16 *StrMacAddr; ///< String to MAC address of network interface.
+ BOOLEAN GotSubnetInfo; ///< Indicates sub net information is retrieved.
+ EFI_IP_ADDRESS SubnetAddr; ///< Subnet ID.
+ EFI_IP_ADDRESS SubnetMask; ///< Subnet mask (IPv4 only)
+ UINT8 SubnetPrefixLength; ///< Subnet prefix.
+ UINT16 VlanId; ///< VLAN ID
+ UINT32 SubnetAddrInfoIPv6Number; ///< IPv6 address info number.
+ EFI_IP6_ADDRESS_INFO *SubnetAddrInfoIPv6; ///< IPv6 address info.
+ //
+ // Network interface protocol and REST EX infor.
+ //
+ UINT32 NetworkProtocolType; ///< Network protocol type. Refer to
+ ///< NETWORK_INTERFACE_PROTOCOL_TYPE.
+ REDFISH_DISCOVER_NETWORK_INTERFACE_PROTOCOL NetworkInterfaceProtocolInfo; ///< Network interface protocol information.
+ EFI_HANDLE RestExHandle; ///< REST EX handle associated 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 handle to open network protocol.
+ EFI_HANDLE RestExChildHandle; ///< The child handle created throught REST EX Service Protocol.
+ EFI_HANDLE RestExControllerHandle; ///< The controller handle which provide REST EX protocol.
+ EFI_REST_EX_PROTOCOL *RestExProtocolInterface; ///< Pointer to EFI_REST_EX_PROTOCOL.
+ UINT32 RestExId; ///< The identifier installed 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 protocol type,
+ ///< Refer to NETWORK_INTERFACE_PROTOCOL_TYPE.
+ CHAR16 *ProtocolName; ///< Protocol name.
+ EFI_GUID *RequiredProtocolGuid; ///< Network protocol interface GUID.
+ EFI_GUID *RequiredServiceBindingProtocolGuid; ///< Network protocol service GUID.
+ EFI_GUID *DiscoveredProtocolGuid; ///< Protocol interface GUID use to install identifier.
+ EFI_REDFISH_DISCOVER_GET_SUBNET_INFO GetSubnetInfo; ///< Function of getting 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 EFI_REDFISH_DISCOVERED_INSTANCE.
+} EFI_REDFISH_DISCOVERED_INTERNAL_LIST;
+
+//
+// Internal structure of Redfish discover instance.
+//
+typedef struct {
+ LIST_ENTRY Entry; ///< Link list entry.
+ EFI_HANDLE Owner; ///< The owner owns this Redfish service discovery.
+ ///< It's the EFI image handle of driver uses
+ ///< EFI Redfish Discover Protocol.
+ EFI_REDFISH_DISCOVER_FLAG DiscoverFlags; ///< EFI_REDFISH_DISCOVER_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 whether to validate Redfish Host interface.
+ EFI_IP_ADDRESS TargetIpAddress; ///< Target IP address 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_INSTANCE.
+ @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 connection.
+ @retval EFI_SUCCESS Redfish service is added to list successfully.
+
+**/
+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/RedfishDiscoverDxe/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_PROTOCOL protocol.
+ for EFI Refish Discover Protocol
+
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ 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 Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] Language A pointer to a three-character ISO 639-2 language identifier.
+ This is the language of the driver name that that the caller
+ is requesting, and it must match one of the languages specified
+ in SupportedLanguages. The number of languages supported by a
+ driver is up to the driver writer.
+ @param[out] DriverName A pointer to the Unicode string to return. This Unicode string
+ is the name of the driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by This
+ and the language specified by Language was returned
+ in DriverName.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the
+ language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+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 controller
+ that is being managed by an EFI Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of a controller that the driver specified by
+ This is managing. This handle specifies the controller
+ whose name is to be returned.
+ @param[in] ChildHandle The handle of the child controller to retrieve the name
+ of. This is an optional parameter that may be NULL. It
+ will be NULL for device drivers. It will also be NULL
+ for a bus drivers that wish to retrieve the name of the
+ bus controller. It will not be NULL for a bus driver
+ that wishes to retrieve the name of a child controller.
+ @param[in] Language A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the controller name
+ that the caller is requesting, and it must match one
+ of the languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up to the
+ driver writer.
+ @param[out] ControllerName A pointer to the Unicode string to return. This Unicode
+ string is the name of the controller specified by
+ ControllerHandle and ChildHandle in the language specified
+ by Language, from the point of view of the driver specified
+ by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user-readable name in the
+ language specified by Language for the driver
+ specified by This was returned in DriverName.
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently managing
+ the controller specified by ControllerHandle and
+ ChildHandle.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the
+ language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+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 = {
+ RedfishDiscoverComponentNameGetDriverName,
+ RedfishDiscoverComponentNameGetControllerName,
+ "eng"
+};
+
+///
+/// Component Name 2 Protocol instance
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_COMPONENT_NAME2_PROTOCOL gRedfishDiscoverComponentName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) RedfishDiscoverComponentNameGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) RedfishDiscoverComponentNameGetControllerName,
+ "en"
+};
+
+///
+/// Table of driver names
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_UNICODE_STRING_TABLE mRedfishDiscoverDriverNameTable[] = {
+ { "eng;en", (CHAR16 *)L"Redfish Discover UEFI Driver" },
+ { NULL, NULL }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE *gRedfishDiscoverControllerNameTable = NULL;
+
+/**
+ Retrieves a Unicode string that is the user-readable name of the EFI Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] Language A pointer to a three-character ISO 639-2 language identifier.
+ This is the language of the driver name that that the caller
+ is requesting, and it must match one of the languages specified
+ in SupportedLanguages. The number of languages supported by a
+ driver is up to the driver writer.
+ @param[out] DriverName A pointer to the Unicode string to return. This Unicode string
+ is the name of the driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by This
+ and the language specified by Language was returned
+ in DriverName.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the
+ language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishDiscoverComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mRedfishDiscoverDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This == &gRedfishDiscoverComponentName)
+ );
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by an EFI Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of a controller that the driver specified by
+ This is managing. This handle specifies the controller
+ whose name is to be returned.
+ @param[in] ChildHandle The handle of the child controller to retrieve the name
+ of. This is an optional parameter that may be NULL. It
+ will be NULL for device drivers. It will also be NULL
+ for a bus drivers that wish to retrieve the name of the
+ bus controller. It will not be NULL for a bus driver
+ that wishes to retrieve the name of a child controller.
+ @param[in] Language A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the controller name
+ that the caller is requesting, and it must match one
+ of the languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up to the
+ driver writer.
+ @param[out] ControllerName A pointer to the Unicode string to return. This Unicode
+ string is the name of the controller specified by
+ ControllerHandle and ChildHandle in the language specified
+ by Language, from the point of view of the driver specified
+ by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user-readable name in the
+ language specified by Language for the driver
+ specified by This was returned in DriverName.
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently managing
+ the controller specified by ControllerHandle and
+ ChildHandle.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the
+ language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+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/RedfishPkg/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<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "RedfishDiscoverInternal.h"
+
+LIST_ENTRY mRedfishDiscoverList;
+LIST_ENTRY mRedfishInstanceList;
+EFI_SMBIOS_PROTOCOL *mSmbios = NULL;
+
+UINTN mNumNetworkInterface = 0;
+UINTN mNumRestExInstance = 0;
+LIST_ENTRY mEfiRedfishDiscoverNetworkInterface;
+LIST_ENTRY mEfiRedfishDiscoverRestExInstance;
+
+EFI_GUID mRedfishDiscoverTcp4InstanceGuid = EFI_REDFISH_DISCOVER_TCP4_INSTANCE_GUID;
+EFI_GUID mRedfishDiscoverTcp6InstanceGuid = EFI_REDFISH_DISCOVER_TCP6_INSTANCE_GUID;
+EFI_GUID mRedfishDiscoverRestExInstanceGuid = EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_GUID;
+
+EFI_HANDLE EfiRedfishDiscoverProtocolHandle = 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[] = {
+ {
+ 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 this owner.
+
+**/
+EFI_STATUS
+CreateRestExInstance (
+ IN EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *Instance,
+ IN EFI_REDFISH_DISCOVERED_TOKEN *Token
+ )
+{
+ EFI_STATUS Status;
+
+ Status = RestExLibCreateChild (
+ Instance->Owner,
+ FixedPcdGetBool (PcdRedfishDiscoverAccessModeInBand)? EfiRestExServiceInBandAccess: EfiRestExServiceOutOfBandAccess,
+ EfiRestExConfigHttp,
+ EfiRestExServiceRedfish,
+ &Token->DiscoverList.RedfishInstances->Information.RedfishRestExHandle
+ );
+ return Status;
+}
+
+/**
+ This function gets EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
+ by known owner handle.
+
+ @param[in] ImageHandle Image handle owns EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE.
+ @param[in] TargetNetworkInterface Target network interface used by this 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 this owner.
+
+**/
+EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *
+GetInstanceByOwner (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *TargetNetworkInterface,
+ IN EFI_REDFISH_DISCOVER_FLAG DiscoverFlags
+ )
+{
+ EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *ThisInstance;
+
+ if (IsListEmpty (&mRedfishDiscoverList)) {
+ return NULL;
+ }
+ ThisInstance =
+ (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *)GetFirstNode (&mRedfishDiscoverList);
+ while (TRUE) {
+ if ((ThisInstance->Owner == ImageHandle) &&
+ (ThisInstance->DiscoverFlags == DiscoverFlags) &&
+ (ThisInstance->NetworkInterface == TargetNetworkInterface)) {
+ return ThisInstance;
+ }
+ if (IsNodeAtEnd (&mRedfishDiscoverList, &ThisInstance->Entry)) {
+ break;
+ }
+ ThisInstance =
+ (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *)GetNextNode (&mRedfishDiscoverList, &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 == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ Tcp4 = (EFI_TCP4_PROTOCOL *)Instance->NetworkInterfaceProtocolInfo.NetworkProtocolInterface;
+
+ 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 = TRUE;
+ Tcp4CfgData.AccessPoint.RemoteAddress.Addr [0] = 127;
+ Tcp4CfgData.AccessPoint.RemoteAddress.Addr [1] = 0;
+ Tcp4CfgData.AccessPoint.RemoteAddress.Addr [2] = 0;
+ Tcp4CfgData.AccessPoint.RemoteAddress.Addr [3] = 1;
+ Tcp4CfgData.AccessPoint.RemotePort = 80;
+ Tcp4CfgData.AccessPoint.ActiveFlag = TRUE;
+
+ Tcp4CfgData.ControlOption = &Tcp4Option;
+ Tcp4Option.ReceiveBufferSize = 65535;
+ Tcp4Option.SendBufferSize = 65535;
+ Tcp4Option.MaxSynBackLog = 5;
+ Tcp4Option.ConnectionTimeout = 60;
+ Tcp4Option.DataRetries = 12;
+ Tcp4Option.FinTimeout = 2;
+ Tcp4Option.KeepAliveProbes = 6;
+ Tcp4Option.KeepAliveTime = 7200;
+ Tcp4Option.KeepAliveInterval = 30;
+ Tcp4Option.EnableNagle = TRUE;
+ Status = Tcp4->Configure (Tcp4, &Tcp4CfgData);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Can't get subnet information\n", __FUNCTION__));
+ return Status;
+ }
+ Status = Tcp4->GetModeData (Tcp4, NULL, NULL, &IpModedata, NULL, NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Can't get IP mode data information\n", __FUNCTION__));
+ return Status;
+ }
+ IP4_COPY_ADDRESS (&Instance->SubnetMask, &IpModedata.ConfigData.SubnetMask);
+ Instance->SubnetAddr.v4.Addr [0] = IpModedata.ConfigData.StationAddress.Addr [0] & Instance->SubnetMask.v4.Addr [0];
+ Instance->SubnetAddr.v4.Addr [1] = IpModedata.ConfigData.StationAddress.Addr [1] & Instance->SubnetMask.v4.Addr [1];
+ Instance->SubnetAddr.v4.Addr [2] = IpModedata.ConfigData.StationAddress.Addr [2] & Instance->SubnetMask.v4.Addr [2];
+ Instance->SubnetAddr.v4.Addr [3] = IpModedata.ConfigData.StationAddress.Addr [3] & Instance->SubnetMask.v4.Addr [3];
+ //
+ // Calculate the subnet mask prefix.
+ //
+ GotPrefixLength = FALSE;
+ PrefixLength = 0;
+ SubnetMaskIndex = 0;
+ while (GotPrefixLength == FALSE && SubnetMaskIndex < 4) {
+ BitMask = 0x80;
+ while (BitMask != 0) {
+ if ((Instance->SubnetMask.v4.Addr [SubnetMaskIndex] & BitMask) != 0) {
+ PrefixLength ++;
+ } else {
+ GotPrefixLength = TRUE;
+ break;
+ }
+ BitMask = BitMask >> 1;
+ };
+ SubnetMaskIndex ++;
+ };
+ Instance->SubnetPrefixLength = 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 == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ Tcp6 = (EFI_TCP6_PROTOCOL *)Instance->NetworkInterfaceProtocolInfo.NetworkProtocolInterface;
+
+ Status = 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 == 0) {
+ DEBUG ((DEBUG_INFO, "%a: No IPv6 address configured.\n"));
+ }
+ if (Instance->SubnetAddrInfoIPv6 != NULL) {
+ FreePool (Instance->SubnetAddrInfoIPv6);
+ }
+ Instance->SubnetAddrInfoIPv6 = AllocateZeroPool (IpModedata.AddressCount * sizeof (EFI_IP6_ADDRESS_INFO));
+ if (Instance->SubnetAddrInfoIPv6 == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: Failed to allocate memory fir IPv6 subnet address information\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Instance->SubnetAddrInfoIPv6Number = 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_INTERFACE.
+ NULL for all EFI_REDFISH_DISCOVER_NETWORK_INTERFACEs.
+
+ @retval Non-NULL EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL is returned.
+ @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 = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface);
+ while (TRUE) {
+ if (CompareMem((VOID *)&ThisNetworkInterface->MacAddress, &TargetNetworkInterface->MacAddress, ThisNetworkInterface->HwAddressSize) == 0) {
+ return ThisNetworkInterface;
+ }
+ if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry)) {
+ return NULL;
+ }
+ ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry);
+ };
+ return NULL;
+}
+
+/**
+ This function validate if target network interface is ready for discovering
+ Redfish service.
+
+ @param[in] TargetNetworkInterface EFI_REDFISH_DISCOVER_NETWORK_INTERFACE.
+ NULL for all EFI_REDFISH_DISCOVER_NETWORK_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) && TargetNetworkInterface == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+ if (TargetNetworkInterface == NULL) {
+ return EFI_SUCCESS; // Return EFI_SUCCESS if no network interface is specified.
+ }
+
+ ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode(&mEfiRedfishDiscoverNetworkInterface);
+ while (TRUE) {
+ if (CompareMem((VOID *)&ThisNetworkInterface->MacAddress, &TargetNetworkInterface->MacAddress, ThisNetworkInterface->HwAddressSize) == 0) {
+ break;
+ }
+ if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry)) {
+ return EFI_UNSUPPORTED;
+ }
+ ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry);
+ };
+ if ((Flags & EFI_REDFISH_DISCOVER_SSDP) != 0) {
+ // Validate if UDP4/6 is supported on the given network interface.
+ // SSDP is not supported.
+
+ return EFI_SUCCESS;
+ }
+ if (ThisNetworkInterface->NetworkInterfaceProtocolInfo.ProtocolControllerHandle == NULL) {
+ return EFI_UNSUPPORTED; // The required protocol on this network interface 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 = 1;
+ ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface);
+ while (TRUE) {
+ if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry)) {
+ break;
+ }
+ ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry);
+ Num ++;
+ };
+ return Num;
+}
+
+/**
+ This function checks the IP version supported on this
+ netwoek interface.
+
+ @param[in] ThisNetworkInterface EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
+
+ @retval TRUE Is IPv6, otherwise IPv4.
+
+**/
+BOOLEAN
+CheckIsIpVersion6 (
+ IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterface
+)
+{
+ if (ThisNetworkInterface->NetworkProtocolType == 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 SMBIOS 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 = NULL;
+ DeviceDescriptor = NULL;
+
+ if (mSmbios == NULL) {
+ Status = gBS->LocateProtocol(&gEfiSmbiosProtocolGuid, NULL, (VOID **)&mSmbios);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ Status = RedfishGetHostInterfaceProtocolData (mSmbios, &DeviceDescriptor, &Data); // Search for SMBIOS type 42h
+ if (!EFI_ERROR (Status) && Data != NULL && DeviceDescriptor != NULL) {
+ //
+ // Chceck if we can reach out Redfish service using this network interface.
+ // Check with MAC address using Device Descroptor Data Device Type 04 and Type 05.
+ // Those two types of Redfish host interface device has MAC information.
+ //
+ if (DeviceDescriptor->DeviceType == REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE_V2) {
+ MacCompareStstus = CompareMem(&Instance->NetworkInterface->MacAddress, &DeviceDescriptor->DeviceDescriptor.PciPcieDeviceV2.MacAddress, 6);
+ } else if (DeviceDescriptor->DeviceType == REDFISH_HOST_INTERFACE_DEVICE_TYPE_USB_V2){
+ MacCompareStstus = CompareMem(&Instance->NetworkInterface->MacAddress, &DeviceDescriptor->DeviceDescriptor.UsbDeviceV2.MacAddress, 6);
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+ if (MacCompareStstus != 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (Data->RedfishServiceIpAddressFormat == 1) {
+ IP4_COPY_ADDRESS ((VOID *)&Instance->TargetIpAddress.v4, (VOID *)Data->RedfishServiceIpAddress);
+ } else {
+ IP6_COPY_ADDRESS ((VOID *)&Instance->TargetIpAddress.v6, (VOID *)Data->RedfishServiceIpAddress);
+ }
+
+ if (Instance->HostIntfValidation) {
+ DEBUG ((DEBUG_ERROR,"%a:Send UPnP unicast SSDP to validate this Redfish Host Interface is not supported.\n", __FUNCTION__));
+ Status = EFI_UNSUPPORTED;
+ } else {
+ //
+ // Add this istance to list without detial information of Redfish
+ // service.
+ //
+ IsHttps = FALSE;
+ if (Data->RedfishServiceIpPort == 443) {
+ IsHttps = TRUE;
+ }
+ StrSize = sizeof(UuidStr);
+ AsciiSPrint(UuidStr, StrSize, "%g", &Data->ServiceUuid);
+ //
+ // Generate Redfish service location string.
+ //
+ if (Data->RedfishServiceIpAddressFormat == REDFISH_HOST_INTERFACE_HOST_IP_ADDRESS_FORMAT_IP6) {
+ NetLibIp6ToStr((IPv6_ADDRESS *)&Data->RedfishServiceIpAddress, Ipv6Str, sizeof (Ipv6Str));
+ if (Data->RedfishServiceIpPort == 0 || IsHttps == TRUE) {
+ AsciiSPrintUnicodeFormat (
+ RedfishServiceLocateStr,
+ sizeof (RedfishServiceLocateStr),
+ L"%s",
+ Ipv6Str
+ );
+ } else {
+ AsciiSPrintUnicodeFormat(
+ RedfishServiceLocateStr,
+ sizeof (RedfishServiceLocateStr),
+ L"[%s]:%d",
+ Ipv6Str,
+ Data->RedfishServiceIpPort
+ );
+ }
+ } else {
+ if (Data->RedfishServiceIpPort == 0 || IsHttps == 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 = 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_INSTANCE.
+ @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 connection.
+ @retval EFI_SUCCESS Redfish service is added to list successfully.
+
+**/
+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 = TRUE;
+ InfoRefresh = FALSE;
+ Char16Uuid = NULL;
+ RestExOpened = FALSE;
+ DeleteRestEx = FALSE;
+
+ DEBUG ((DEBUG_INFO,"%a:Add this instance to Redfish instance list.\n", __FUNCTION__));
+
+ if (Uuid != NULL) {
+ Char16Uuid = (CHAR16 *)AllocateZeroPool(AsciiStrSize((const CHAR8 *)Uuid) * sizeof(CHAR16));
+ AsciiStrToUnicodeStrS ((const CHAR8 *)Uuid, Char16Uuid, AsciiStrSize((const CHAR8 *)Uuid) * sizeof(CHAR16));
+ }
+ DiscoveredList = NULL;
+ DiscoveredInstance = NULL;
+ RestExHttpConfigData = NULL;
+
+ NetworkInterface = Instance->NetworkInterface;
+ if (!IsListEmpty (&mRedfishInstanceList)) {
+ //
+ // Is this a duplicate redfish service.
+ //
+ DiscoveredList = (EFI_REDFISH_DISCOVERED_INTERNAL_LIST *)GetFirstNode (&mRedfishInstanceList);
+ NewFound = FALSE;
+ do {
+ if (Char16Uuid == NULL || DiscoveredList->Instance->Information.Uuid == NULL) {
+ //
+ // Check if this Redfish instance already found using IP addrress.
+ //
+ if (!CheckIsIpVersion6(NetworkInterface)) {
+ if (CompareMem ((VOID *)&Instance->TargetIpAddress.v4,
+ (VOID *)&DiscoveredList->Instance->Information.RedfishHostIpAddress.v4,
+ sizeof (EFI_IPv4_ADDRESS)
+ ) == 0)
+ {
+ DiscoveredInstance = DiscoveredList->Instance;
+ if (DiscoveredList->Instance->Information.Uuid == NULL &&
+ Char16Uuid != NULL) {
+ InfoRefresh = TRUE;
+ DiscoveredInstance = DiscoveredList->Instance;
+ DEBUG((DEBUG_INFO,"*** This Redfish Service information refresh ***\n"));
+ }
+ break;
+ }
+ } else {
+ if (CompareMem ((VOID *)&Instance->TargetIpAddress.v6,
+ (VOID *)&DiscoveredList->Instance->Information.RedfishHostIpAddress.v6,
+ sizeof (EFI_IPv6_ADDRESS)
+ ) == 0)
+ {
+ DiscoveredInstance = DiscoveredList->Instance;
+ break;
+ }
+ }
+ } else {
+ //
+ // Check if this Redfish instance already found using UUID.
+ //
+ if (StrCmp((const CHAR16 *)Char16Uuid, (const CHAR16 *)DiscoveredList->Instance->Information.Uuid) == 0) {
+ DiscoveredInstance = DiscoveredList->Instance;
+ break;
+ }
+ }
+ if (IsNodeAtEnd (&mRedfishInstanceList, &DiscoveredList->NextInstance)) {
+ NewFound = TRUE;
+ break;
+ }
+ DiscoveredList = (EFI_REDFISH_DISCOVERED_INTERNAL_LIST *)GetNextNode (&mRedfishInstanceList, &DiscoveredList->NextInstance);
+ } while (TRUE);
+ }
+ if (NewFound || InfoRefresh) {
+ if (!InfoRefresh) {
+ DiscoveredList = (EFI_REDFISH_DISCOVERED_INTERNAL_LIST *)AllocateZeroPool(sizeof(EFI_REDFISH_DISCOVERED_INTERNAL_LIST));
+ if (DiscoveredList == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ InitializeListHead (&DiscoveredList->NextInstance);
+ DiscoveredInstance = (EFI_REDFISH_DISCOVERED_INSTANCE *)AllocateZeroPool(sizeof(EFI_REDFISH_DISCOVERED_INSTANCE));
+ if (DiscoveredInstance == NULL) {
+ FreePool ((VOID *)DiscoveredList);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+ DEBUG ((DEBUG_INFO,"*** Redfish Service Information ***\n"));
+
+ DiscoveredInstance->Information.UseHttps = UseHttps;
+ if (RedfishVersion != NULL) {
+ DiscoveredInstance->Information.RedfishVersion = *RedfishVersion;
+ DEBUG ((DEBUG_INFO,"Redfish service version: %d.\n", DiscoveredInstance->Information.RedfishVersion));
+ }
+ if (RedfishLocation != NULL) {
+ DiscoveredInstance->Information.Location = (CHAR16 *)AllocatePool(AsciiStrSize((const CHAR8 *)RedfishLocation) * sizeof(CHAR16));
+ AsciiStrToUnicodeStrS ((const CHAR8 *)RedfishLocation, DiscoveredInstance->Information.Location, AsciiStrSize((const CHAR8 *)RedfishLocation) * sizeof(CHAR16));
+ DEBUG ((DEBUG_INFO,"Redfish service location: %s.\n", DiscoveredInstance->Information.Location));
+ }
+ if (Uuid != NULL) {
+ DiscoveredInstance->Information.Uuid = (CHAR16 *)AllocatePool(AsciiStrSize((const CHAR8 *)Uuid) * sizeof(CHAR16));
+ AsciiStrToUnicodeStrS ((const CHAR8 *)Uuid, DiscoveredInstance->Information.Uuid, AsciiStrSize((const CHAR8 *)Uuid) * sizeof(CHAR16));
+ DEBUG ((DEBUG_INFO,"Service UUID: %s.\n", DiscoveredInstance->Information.Uuid));
+ }
+ if (Os != NULL) {
+ DiscoveredInstance->Information.Os = (CHAR16 *)AllocatePool(AsciiStrSize((const CHAR8 *)Os) * sizeof(CHAR16));
+ AsciiStrToUnicodeStrS ((const CHAR8 *)Os, DiscoveredInstance->Information.Os, AsciiStrSize((const CHAR8 *)Os) * sizeof(CHAR16));
+ DEBUG ((DEBUG_INFO,"Redfish service OS: %s, Version:%s.\n", DiscoveredInstance->Information.Os, DiscoveredInstance->Information.OsVersion));
+ }
+ if (OsVer != NULL) {
+ DiscoveredInstance->Information.OsVersion = (CHAR16 *)AllocatePool(AsciiStrSize((const CHAR8 *)OsVer) * sizeof(CHAR16));
+ AsciiStrToUnicodeStrS ((const CHAR8 *)OsVer, DiscoveredInstance->Information.OsVersion, AsciiStrSize((const CHAR8 *)OsVer) * sizeof(CHAR16));
+ }
+ if (Product != NULL && ProductVer != NULL) {
+ DiscoveredInstance->Information.Product = (CHAR16 *)AllocatePool(AsciiStrSize((const CHAR8 *)Product) * sizeof(CHAR16));
+ AsciiStrToUnicodeStrS ((const CHAR8 *)Product, DiscoveredInstance->Information.Product, AsciiStrSize((const CHAR8 *)Product) * sizeof(CHAR16));
+ DiscoveredInstance->Information.ProductVer = (CHAR16 *)AllocatePool(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", DiscoveredInstance->Information.Product, DiscoveredInstance->Information.ProductVer));
+ }
+
+ if (RedfishLocation == NULL) {
+ // This is the Redfish reported from SMBIOS 42h
+ // without validation.
+
+ IP4_COPY_ADDRESS((VOID *)&DiscoveredInstance->Information.RedfishHostIpAddress.v4, (VOID *)&Instance->TargetIpAddress.v4);
+ }
+ if (!InfoRefresh) {
+ DiscoveredList->Instance = DiscoveredInstance;
+ InsertTailList(&mRedfishInstanceList, &DiscoveredList->NextInstance);
+ }
+ DiscoveredInstance->Status = EFI_SUCCESS;
+ } else {
+ if (DiscoveredList != NULL) {
+ DEBUG((DEBUG_INFO,"*** This Redfish Service was already found ***\n"));
+ if (DiscoveredInstance->Information.Uuid != NULL) {
+ DEBUG((DEBUG_INFO,"Service UUID: %s.\n", DiscoveredInstance->Information.Uuid));
+ } else {
+ DEBUG((DEBUG_INFO,"Service UUID: unknown.\n"));
+ }
+ }
+ }
+ if (Char16Uuid != NULL) {
+ FreePool((VOID *)Char16Uuid);
+ }
+
+ Status = EFI_SUCCESS;
+ if (NewFound || InfoRefresh) {
+ //
+ // Build up EFI_REDFISH_DISCOVERED_LIST in token.
+ //
+ Instance->DiscoverToken->DiscoverList.NumberOfServiceFound = 1;
+ Instance->DiscoverToken->DiscoverList.RedfishInstances = DiscoveredInstance;
+ DiscoveredInstance->Status = EFI_SUCCESS;
+ if (!InfoRefresh) {
+ Status = 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 = 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 = TRUE;
+ goto ERROR_EXIT;
+ }
+ RestExOpened = TRUE;
+ RestExHttpConfigData = AllocateZeroPool (sizeof (EFI_REST_EX_HTTP_CONFIG_DATA));
+ if (RestExHttpConfigData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ DeleteRestEx = TRUE;
+ goto EXIT_FREE_CONFIG_DATA;
+ }
+ RestExHttpConfigData->SendReceiveTimeout = 5000;
+ RestExHttpConfigData->HttpConfigData.HttpVersion = HttpVersion11;
+ RestExHttpConfigData->HttpConfigData.LocalAddressIsIPv6 = CheckIsIpVersion6(NetworkInterface);
+ if (RestExHttpConfigData->HttpConfigData.LocalAddressIsIPv6) {
+ RestExHttpConfigData->HttpConfigData.AccessPoint.IPv6Node = AllocateZeroPool (sizeof (EFI_HTTPv6_ACCESS_POINT));
+ if (RestExHttpConfigData->HttpConfigData.AccessPoint.IPv6Node == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto EXIT_FREE_CONFIG_DATA;
+ }
+ } else {
+ RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node = AllocateZeroPool (sizeof (EFI_HTTPv4_ACCESS_POINT));
+ if (RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto EXIT_FREE_CONFIG_DATA;
+ }
+ RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node->UseDefaultAddress = TRUE;
+ }
+ Status = RestEx->Configure (
+ RestEx,
+ (EFI_REST_EX_CONFIG_DATA)(UINT8 *)RestExHttpConfigData
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR,"%a:REST EX configured..\n", __FUNCTION__));
+ DeleteRestEx = TRUE;
+ goto EXIT_FREE_ALL;
+ }
+ //
+ // Signal client, close REST EX before signaling client.
+ //
+ if (RestExOpened) {
+ gBS->CloseProtocol(
+ Instance->DiscoverToken->DiscoverList.RedfishInstances->Information.RedfishRestExHandle,
+ &gEfiRestExProtocolGuid,
+ Instance->NetworkInterface->OpenDriverAgentHandle,
+ Instance->NetworkInterface->OpenDriverControllerHandle
+ );
+ RestExOpened = FALSE;
+ }
+ }
+ Status = gBS->SignalEvent(Instance->DiscoverToken->Event);
+ if (!EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR,"%a:No event to signal!\n", __FUNCTION__));
+ }
+ }
+
+EXIT_FREE_ALL:;
+ if (RestExHttpConfigData != NULL && RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node != NULL) {
+ FreePool (RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node);
+ }
+
+EXIT_FREE_CONFIG_DATA:;
+ if (RestExHttpConfigData != NULL) {
+ FreePool((VOID *)RestExHttpConfigData);
+ }
+ if (RestExOpened) {
+ gBS->CloseProtocol(
+ Instance->DiscoverToken->DiscoverList.RedfishInstances->Information.RedfishRestExHandle,
+ &gEfiRestExProtocolGuid,
+ Instance->NetworkInterface->OpenDriverAgentHandle,
+ Instance->NetworkInterface->OpenDriverControllerHandle
+ );
+ }
+ERROR_EXIT:;
+ if (DeleteRestEx && RestExOpened) {
+ gBS->CloseProtocol(
+ Instance->DiscoverToken->DiscoverList.RedfishInstances->Information.RedfishRestExHandle,
+ &gEfiRestExProtocolGuid,
+ Instance->NetworkInterface->OpenDriverAgentHandle,
+ Instance->NetworkInterface->OpenDriverControllerHandle
+ );
+ }
+ON_EXIT:;
+ return Status;
+}
+
+/**
+ This function gets the subnet information of this network interface instance.
+ can discover Redfish service on it.
+
+ @param[in] Instance EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL instance.
+ @param[in] ImageHandle EFI Image handle request the network interface 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 = Instance->NetworkProtocolType;
+ if (gRequiredProtocol [ProtocolType].GetSubnetInfo != NULL && Instance->GotSubnetInfo == FALSE) {
+ Status = gRequiredProtocol [ProtocolType].GetSubnetInfo (
+ ImageHandle,
+ Instance
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR,"%a:Faile to get Subnet infomation.\n", __FUNCTION__));
+ return Status;
+ } else {
+ DEBUG ((DEBUG_INFO,"%a:MAC address: %s\n", __FUNCTION__, Instance->StrMacAddr));
+ if (CheckIsIpVersion6 (Instance)) {
+ if (Instance->SubnetAddrInfoIPv6Number == 0) {
+ DEBUG ((DEBUG_ERROR,"%a: There is no Subnet infomation for IPv6 network interface.\n", __FUNCTION__));
+ return EFI_NOT_FOUND;
+ }
+ ThisSubnetAddrInfoIPv6 = Instance->SubnetAddrInfoIPv6; // First IPv6 address information.
+ IP6_COPY_ADDRESS (&Instance->SubnetAddr.v6, &ThisSubnetAddrInfoIPv6->Address);
+ Instance->SubnetPrefixLength = ThisSubnetAddrInfoIPv6->PrefixLength;
+ DEBUG((DEBUG_INFO," IPv6 Subnet ID:%d, Prefix length: %d.\n",
+ ThisSubnetAddrInfoIPv6->Address.Addr [7] + (UINT16)ThisSubnetAddrInfoIPv6->Address.Addr [6] * 256,
+ ThisSubnetAddrInfoIPv6->PrefixLength)
+ );
+ //
+ // If this is IPv6, then we may have to propagate network interface for IPv6 network scopes
+ // according to the Ipv6 address information.
+ //
+ ThisSubnetAddrInfoIPv6 ++;
+ for (IPv6InfoIndex = 0; IPv6InfoIndex < Instance->SubnetAddrInfoIPv6Number - 1; IPv6InfoIndex++) {
+ //
+ // Build up addtional EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL instances.
+ //
+ NewNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL));
+ if (NewNetworkInterface != NULL) {
+ CopyMem ((VOID *)NewNetworkInterface, (VOID *)Instance, sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL)); // Clone information of first instance.
+ IP6_COPY_ADDRESS (&NewNetworkInterface->SubnetAddr.v6, &ThisSubnetAddrInfoIPv6->Address);
+ NewNetworkInterface->SubnetPrefixLength = ThisSubnetAddrInfoIPv6->PrefixLength;
+ NewNetworkInterface->GotSubnetInfo = TRUE;
+ InsertTailList (&mEfiRedfishDiscoverNetworkInterface, &NewNetworkInterface->Entry);
+ ThisSubnetAddrInfoIPv6 ++;
+ mNumNetworkInterface ++;
+ DEBUG((DEBUG_INFO," IPv6 Subnet ID:%d, Prefix length: %d.\n",
+ ThisSubnetAddrInfoIPv6->Address.Addr [7] + (UINT16)ThisSubnetAddrInfoIPv6->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 = TRUE; // Only try to get Subnet Info once.
+ return EFI_SUCCESS;
+}
+
+/**
+ This function gets the network interface list which Redfish discover protocol
+ can discover Redfish service on it.
+
+ @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instance.
+ @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 NumberOfNetworkIntfs.
+ Caller has to release the memory
+ allocated by Redfish discover protocol.
+
+ @retval EFI_SUCCESS The information of network interface is returned in NumberOfNetworkIntfs and
+ NetworkIntfInstances.
+ @retval Others Fail to return the information of network interface.
+
+**/
+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 *ThisNetworkInterfaceIntn;
+ EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *ThisNetworkInterface;
+
+ if (NetworkIntfInstances == NULL || NumberOfNetworkIntfs == NULL || ImageHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *NumberOfNetworkIntfs = 0;
+ *NetworkIntfInstances = NULL;
+
+ if (IsListEmpty ((const LIST_ENTRY*)&mEfiRedfishDiscoverNetworkInterface)) {
+ return EFI_NOT_FOUND;
+ }
+
+ ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE) * mNumNetworkInterface);
+ if (ThisNetworkInterface == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ *NetworkIntfInstances = ThisNetworkInterface;
+ ThisNetworkInterfaceIntn = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface);
+ while (TRUE) {
+ ThisNetworkInterface->IsIpv6 = FALSE;
+ if (CheckIsIpVersion6 (ThisNetworkInterfaceIntn)) {
+ ThisNetworkInterface->IsIpv6 = TRUE;
+ }
+ CopyMem((VOID *)&ThisNetworkInterface->MacAddress, &ThisNetworkInterfaceIntn->MacAddress, ThisNetworkInterfaceIntn->HwAddressSize);
+ NetworkInterfaceGetSubnetInfo(ThisNetworkInterfaceIntn, ImageHandle); // Get subnet info.
+ if (!ThisNetworkInterface->IsIpv6) {
+ IP4_COPY_ADDRESS(&ThisNetworkInterface->SubnetId.v4, &ThisNetworkInterfaceIntn->SubnetAddr.v4); // IPv4 subnet information.
+ } else {
+ IP6_COPY_ADDRESS (&ThisNetworkInterface->SubnetId.v6, &ThisNetworkInterfaceIntn->SubnetAddr.v6); // IPv6 subnet information in IPv6 address information.
+ }
+ ThisNetworkInterface->SubnetPrefixLength = ThisNetworkInterfaceIntn->SubnetPrefixLength;
+ ThisNetworkInterface->VlanId = ThisNetworkInterfaceIntn->VlanId;
+ (*NumberOfNetworkIntfs) ++;
+ if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterfaceIntn->Entry)) {
+ break;
+ }
+ ThisNetworkInterfaceIntn = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterfaceIntn->Entry);
+ ThisNetworkInterface ++;
+ };
+ return EFI_SUCCESS;
+}
+/**
+ This function acquires Redfish services by discovering static Redfish setting
+ according to Redfish Host Interface or through SSDP. Returns a list of EFI
+ handles in EFI_REDFISH_DISCOVERED_LIST. Each of EFI handle has cooresponding
+ EFI REST EX instance installed on it. Each REST EX isntance is a child instance which
+ created through EFI REST EX serivce protoocl for communicating with specific
+ Redfish service.
+
+ @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instance.
+ @param[in] ImageHandle EFI image owns these Redfish service instances.
+ @param[in] TargetNetworkInterface Target network interface to do the discovery.
+ NULL means discover Redfish service on all network interfaces on platform.
+ @param[in] Flags Redfish service discover flags.
+ @param[in] Token EFI_REDFISH_DISCOVERED_TOKEN instance.
+ The memory of EFI_REDFISH_DISCOVERED_LIST and the strings in
+ EFI_REDFISH_DISCOVERED_INFORMATION are all allocated by Acquire()
+ and must be freed when caller invoke Release().
+
+ @retval EFI_SUCCESS REST EX instance of discovered Redfish services are returned.
+ @retval EFI_INVALID_PARAMETERS ImageHandle == NULL, Flags == 0, Token == NULL, Token->Timeout > 5,
+ or Token->Event == 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 *TargetNetworkInterfaceInternal;
+
+ DEBUG ((DEBUG_INFO,"%a:Entry.\n", __FUNCTION__));
+
+ //
+ // Validate parameters.
+ //
+ if (ImageHandle == NULL || Token == NULL || ((Flags & ~EFI_REDFISH_DISCOVER_VALIDATION) == 0)) {
+ DEBUG ((DEBUG_ERROR,"%a:Invalid parameters.\n", __FUNCTION__));
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Validate target network interface.
+ //
+ if (EFI_ERROR (ValidateTargetNetworkInterface (TargetNetworkInterface, Flags))) {
+ return EFI_UNSUPPORTED;
+ }
+ if (TargetNetworkInterface != NULL) {
+ TargetNetworkInterfaceInternal = GetTargetNetworkInterfaceInternal (TargetNetworkInterface);
+ NumNetworkInterfaces = 1;
+ } else {
+ TargetNetworkInterfaceInternal = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface);
+ NumNetworkInterfaces = NumberOfNetworkInterface ();
+ if (NumNetworkInterfaces == 0) {
+ DEBUG ((DEBUG_ERROR,"%a:No network interface on platform.\n", __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ }
+ }
+ for (NetworkInterfacesIndex = 0; NetworkInterfacesIndex < NumNetworkInterfaces; NetworkInterfacesIndex ++) {
+ Status1 = EFI_SUCCESS;
+ Status2 = EFI_SUCCESS;
+ NewInstance = FALSE;
+ Instance = GetInstanceByOwner (ImageHandle, TargetNetworkInterfaceInternal, Flags & ~EFI_REDFISH_DISCOVER_VALIDATION); // Check if we can re-use previous instance.
+ if (Instance == NULL) {
+ DEBUG ((DEBUG_INFO,"%a:Create new EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE.\n", __FUNCTION__));
+ Instance = (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *)AllocateZeroPool(sizeof(EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE));
+ if (Instance == NULL) {
+ DEBUG ((DEBUG_ERROR,"%a:Memory allocation fail.\n", __FUNCTION__));
+ }
+ InitializeListHead (&Instance->Entry);
+ Instance->Owner = ImageHandle;
+ Instance->DiscoverFlags = Flags & ~EFI_REDFISH_DISCOVER_VALIDATION;
+ Instance->NetworkInterface = TargetNetworkInterfaceInternal;
+ //
+ // Get subnet information in case subnet information is not set because
+ // RedfishServiceGetNetworkInterfaces hasn't been called yet.
+ //
+ NetworkInterfaceGetSubnetInfo (TargetNetworkInterfaceInternal, ImageHandle);
+ NewInstance = TRUE;
+ }
+ if (TargetNetworkInterfaceInternal->StrMacAddr != NULL) {
+ DEBUG((DEBUG_INFO,"%a:Acquire Redfish service on network interface MAC address:%s.\n", __FUNCTION__, TargetNetworkInterfaceInternal->StrMacAddr));
+ } else {
+ DEBUG((DEBUG_INFO,"%a:WARNING: No MAC address on this network interface.\n", __FUNCTION__));
+ }
+
+ Instance->DiscoverToken = Token; // Always use the latest Token passed by caller.
+ if ((Flags & EFI_REDFISH_DISCOVER_HOST_INTERFACE) != 0) {
+ DEBUG ((DEBUG_INFO,"%a:Redfish HOST interface discovery.\n", __FUNCTION__));
+ Instance->HostIntfValidation = FALSE;
+ if ((Flags & EFI_REDFISH_DISCOVER_VALIDATION) != 0) {
+ Instance->HostIntfValidation = TRUE;
+ }
+ Status1 = DiscoverRedfishHostInterface (Instance); // Discover Redfish service through Redfish Host Interface.
+ }
+ if ((Flags & EFI_REDFISH_DISCOVER_SSDP) != 0) {
+ DEBUG ((DEBUG_ERROR,"%a:Redfish service discovery through SSDP is not 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 discovery Status1=%x, Status2=%x.\n", __FUNCTION__, Status1, Status2));
+ } else {
+ if (NewInstance) {
+ InsertTailList(&mRedfishDiscoverList, &Instance->Entry);
+ }
+ }
+ }
+ if (TargetNetworkInterface == NULL) {
+ //
+ // Discover Redfish services on all of network interfaces.
+ //
+ TargetNetworkInterfaceInternal = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, &TargetNetworkInterfaceInternal->Entry);
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ This function aborts Redfish service discovery on the given network interface.
+
+ @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instance.
+ @param[in] TargetNetworkInterface Target network interface to do the discovery.
+
+ @retval EFI_SUCCESS REST EX instance of discovered Redfish services 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 OPTIONAL
+)
+{
+ // 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 released.
+ @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", __FUNCTION__));
+ return EFI_NOT_FOUND;
+ }
+ AnyFailRelease = FALSE;
+ ThisRedfishInstance = InstanceList->RedfishInstances;
+ for (NumService = 0; NumService < InstanceList->NumberOfServiceFound; NumService ++) {
+ DiscoveredRedfishInstance = (EFI_REDFISH_DISCOVERED_INTERNAL_LIST *)GetFirstNode(&mRedfishInstanceList);
+ do {
+ if (DiscoveredRedfishInstance->Instance == ThisRedfishInstance) {
+ RemoveEntryList (&DiscoveredRedfishInstance->NextInstance);
+ if (ThisRedfishInstance->Information.Location != NULL) {
+ FreePool (ThisRedfishInstance->Information.Location);
+ }
+ if (ThisRedfishInstance->Information.Uuid != NULL) {
+ FreePool (ThisRedfishInstance->Information.Uuid);
+ }
+ if (ThisRedfishInstance->Information.Os != NULL) {
+ FreePool (ThisRedfishInstance->Information.Os);
+ }
+ if (ThisRedfishInstance->Information.OsVersion != NULL) {
+ FreePool (ThisRedfishInstance->Information.OsVersion);
+ }
+ if (ThisRedfishInstance->Information.Product != NULL) {
+ FreePool (ThisRedfishInstance->Information.Product);
+ }
+ if (ThisRedfishInstance->Information.ProductVer != NULL) {
+ FreePool (ThisRedfishInstance->Information.ProductVer);
+ }
+ FreePool((VOID *)ThisRedfishInstance);
+ goto ReleaseNext;
+ }
+
+ if (IsNodeAtEnd(&mRedfishInstanceList, &DiscoveredRedfishInstance->NextInstance)) {
+ break;
+ }
+ DiscoveredRedfishInstance = (EFI_REDFISH_DISCOVERED_INTERNAL_LIST *)GetNextNode(&mRedfishInstanceList, &DiscoveredRedfishInstance->NextInstance);
+ } while (TRUE);
+ AnyFailRelease = TRUE;
+ReleaseNext:;
+ //
+ // Release next discovered Redfish Service.
+ //
+ ThisRedfishInstance = (EFI_REDFISH_DISCOVERED_INSTANCE *)((UINT8 *)ThisRedfishInstance + sizeof (EFI_REDFISH_DISCOVERED_INSTANCE));
+ }
+ if (AnyFailRelease) {
+ return EFI_NOT_FOUND;
+ } else {
+ return EFI_SUCCESS;
+ }
+}
+
+EFI_REDFISH_DISCOVER_PROTOCOL mRedfishDiscover = {
+ 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_NETWORK_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 = NULL;
+ *IsNewInstance = TRUE;
+ if (!IsListEmpty ((const LIST_ENTRY*)&mEfiRedfishDiscoverNetworkInterface)) {
+ //
+ // Check if this instance already exist.
+ //
+ ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface);
+ if (ThisNetworkInterface != NULL) {
+ while (TRUE) {
+ if ((CompareMem ((CONST VOID *)&ThisNetworkInterface->MacAddress.Addr, (CONST VOID *)&MacAddress.Addr, HwAddressSize) == 0) &&
+ (ThisNetworkInterface->NetworkProtocolType == NetworkProtocolType)){
+ NewNetworkInterface = ThisNetworkInterface;
+ *IsNewInstance = FALSE;
+ break;
+ }
+ if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry)) {
+ NewNetworkInterface = NULL;
+ break;
+ }
+ ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry);
+ };
+ }
+ }
+ if (NewNetworkInterface == NULL) {
+ //
+ // Create a new instance.
+ //
+ NewNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL));
+ if (NewNetworkInterface == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ NewNetworkInterface->HwAddressSize = HwAddressSize;
+ CopyMem (&NewNetworkInterface->MacAddress.Addr, &MacAddress.Addr, NewNetworkInterface->HwAddressSize);
+ NetLibGetMacString (ControllerHandle, NULL, &NewNetworkInterface->StrMacAddr);
+ NewNetworkInterface->VlanId = NetLibGetVlanId (ControllerHandle);
+ }
+ *NetworkInterface = 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 = gBS->UninstallProtocolInterface(
+ ThisNetworkInterface->OpenDriverControllerHandle,
+ gRequiredProtocol [ThisNetworkInterface->NetworkProtocolType].DiscoveredProtocolGuid,
+ &ThisNetworkInterface->NetworkInterfaceProtocolInfo.ProtocolDiscoverId
+ );
+ 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_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @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 = 0; Index < (sizeof (gRequiredProtocol) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL)); Index ++) {
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ gRequiredProtocol [Index].RequiredServiceBindingProtocolGuid,
+ NULL,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = 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_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @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 = FALSE;
+ Index = 0;
+ do {
+ Status = 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 == (sizeof(gRequiredProtocol) / sizeof(REDFISH_DISCOVER_REQUIRED_PROTOCOL))) {
+ break;
+ }
+ continue;
+ }
+
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ gRequiredProtocol [Index].RequiredServiceBindingProtocolGuid,
+ &TempInterface,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ Index ++;
+ if (Index == (sizeof(gRequiredProtocol) / sizeof(REDFISH_DISCOVER_REQUIRED_PROTOCOL))) {
+ break;
+ }
+ continue;
+ }
+ if (gRequiredProtocol [Index].ProtocolType != ProtocolTypeRestEx) {
+ OldTpl = gBS->RaiseTPL (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL);
+ Status = CreateRedfishDiscoverNetworkInterface(ControllerHandle, gRequiredProtocol [Index].ProtocolType, &IsNew, &NetworkInterface);
+ if (EFI_ERROR (Status)) {
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+ }
+ NetworkInterface->NetworkProtocolType = gRequiredProtocol [Index].ProtocolType;
+ NetworkInterface->OpenDriverAgentHandle = This->DriverBindingHandle;
+ NetworkInterface->OpenDriverControllerHandle = ControllerHandle;
+ NetworkInterface->NetworkInterfaceProtocolInfo.ProtocolGuid = \
+ *gRequiredProtocol [Index].RequiredProtocolGuid;
+ NetworkInterface->NetworkInterfaceProtocolInfo.ProtocolServiceGuid = \
+ *gRequiredProtocol [Index].RequiredServiceBindingProtocolGuid;
+ ProtocolDiscoverIdPtr = &NetworkInterface->NetworkInterfaceProtocolInfo.ProtocolDiscoverId;
+ OpenDriverAgentHandle = NetworkInterface->OpenDriverAgentHandle;
+ OpenDriverControllerHandle = NetworkInterface->OpenDriverControllerHandle;
+ HandleOfProtocolInterfacePtr = &NetworkInterface->NetworkInterfaceProtocolInfo.ProtocolControllerHandle;
+ Interface = &NetworkInterface->NetworkInterfaceProtocolInfo.NetworkProtocolInterface;
+ NewNetworkInterfaceInstalled = TRUE;
+ if (IsNew) {
+ InsertTailList (&mEfiRedfishDiscoverNetworkInterface, &NetworkInterface->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 corresponding EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
+ // when discovery.
+
+ RestExInstance = (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL *)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL));
+ if (RestExInstance == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ RestExInstance->OpenDriverAgentHandle = This->DriverBindingHandle;
+ RestExInstance->OpenDriverControllerHandle = ControllerHandle;
+ RestExInstance->RestExControllerHandle = ControllerHandle;
+ InitializeListHead (&RestExInstance->Entry);
+ InsertTailList (&mEfiRedfishDiscoverRestExInstance, &RestExInstance->Entry);
+ mNumRestExInstance ++;
+ ProtocolDiscoverIdPtr = &RestExInstance->RestExId;
+ OpenDriverAgentHandle = RestExInstance->OpenDriverAgentHandle;
+ OpenDriverControllerHandle = RestExInstance->OpenDriverControllerHandle;
+ HandleOfProtocolInterfacePtr = &RestExInstance->RestExChildHandle;
+ Interface = (VOID **)&RestExInstance->RestExProtocolInterface;
+ }
+ Status = gBS->InstallProtocolInterface (
+ &ControllerHandle,
+ gRequiredProtocol [Index].DiscoveredProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ ProtocolDiscoverIdPtr
+ );
+ if (EFI_ERROR (Status)) {
+ Index ++;
+ if (Index == (sizeof(gRequiredProtocol) / sizeof(REDFISH_DISCOVER_REQUIRED_PROTOCOL))) {
+ break;
+ }
+ continue;
+ }
+ //
+ // Create service binding child and open it BY_DRIVER.
+ //
+ Status = NetLibCreateServiceChild (
+ ControllerHandle,
+ This->ImageHandle,
+ gRequiredProtocol [Index].RequiredServiceBindingProtocolGuid,
+ HandleOfProtocolInterfacePtr
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->OpenProtocol (
+ *HandleOfProtocolInterfacePtr,
+ gRequiredProtocol [Index].RequiredProtocolGuid,
+ Interface,
+ OpenDriverAgentHandle,
+ OpenDriverControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (!EFI_ERROR (Status)) {
+ if (EfiRedfishDiscoverProtocolHandle == NULL &&
+ (gRequiredProtocol [Index].ProtocolType == ProtocolTypeRestEx) &&
+ !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 = gBS->InstallProtocolInterface (
+ &EfiRedfishDiscoverProtocolHandle,
+ &gEfiRedfishDiscoverProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ (VOID *)&mRedfishDiscover
+ );
+ } else if (EfiRedfishDiscoverProtocolHandle != NULL && NewNetworkInterfaceInstalled) {
+ Status = gBS->ReinstallProtocolInterface (
+ EfiRedfishDiscoverProtocolHandle,
+ &gEfiRedfishDiscoverProtocolGuid,
+ (VOID *)&mRedfishDiscover,
+ (VOID *)&mRedfishDiscover
+ );
+ NewNetworkInterfaceInstalled = FALSE;
+ }
+ }
+ return Status;
+ } else {
+ Index ++;
+ if (Index == (sizeof(gRequiredProtocol) / sizeof(REDFISH_DISCOVER_REQUIRED_PROTOCOL))) {
+ break;
+ }
+ continue;
+ }
+ } while (Index < (sizeof(gRequiredProtocol) / sizeof(REDFISH_DISCOVER_REQUIRED_PROTOCOL)));
+ return EFI_UNSUPPORTED;
+}
+/**
+ Close the protocol opened for Redfish discovery. This function also destories
+ 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 that supplies
+ an I/O abstraction to the driver.
+ @param[in] ThisRequiredProtocol Pointer to the instance of REDFISH_DISCOVER_REQUIRED_PROTOCOL.
+ @param[in] DriverAgentHandle Driver agent handle which used to open protocol earlier.
+ @param[in] DriverControllerHandle Driver controller handle which used to 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 = 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_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @retval EFI_SUCCESS One of required protocol is found.
+ @retval Others Faile to stop the services on network interface.
+**/
+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 = 0; Index < (sizeof (gRequiredProtocol) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL)); Index ++) {
+ Status = gBS->HandleProtocol (
+ ControllerHandle,
+ gRequiredProtocol [Index].RequiredProtocolGuid,
+ (VOID **)&Interface
+ );
+ if (!EFI_ERROR (Status)) {
+ if (gRequiredProtocol [Index].ProtocolType != ProtocolTypeRestEx) {
+ if (IsListEmpty (&mEfiRedfishDiscoverNetworkInterface)) {
+ return EFI_NOT_FOUND;
+ }
+ OldTpl = gBS->RaiseTPL (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL);
+ ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface);
+ while (TRUE) {
+ if (ThisNetworkInterface->NetworkInterfaceProtocolInfo.ProtocolControllerHandle == ControllerHandle) {
+
+ Status = CloseProtocolService ( // Close protocol and destroy service.
+ ThisBindingProtocol,
+ ControllerHandle,
+ &gRequiredProtocol [Index],
+ ThisNetworkInterface->OpenDriverAgentHandle,
+ ThisNetworkInterface->OpenDriverControllerHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = DestroyRedfishNetwrokInterface (ThisNetworkInterface);
+ }
+ gBS->RestoreTPL (OldTpl);
+ // Reinstall Redfish Discover protocol to notify network
+ // interface change.
+
+ Status = gBS->ReinstallProtocolInterface (
+ EfiRedfishDiscoverProtocolHandle,
+ &gEfiRedfishDiscoverProtocolGuid,
+ (VOID *)&mRedfishDiscover,
+ (VOID *)&mRedfishDiscover
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((DEBUG_ERROR, "%a: Reinstall gEfiRedfishDiscoverProtocolGuid fail.", __FUNCTION__));
+ }
+ return Status;
+ }
+ if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry)) {
+ break;
+ }
+ ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry);
+ };
+ gBS->RestoreTPL (OldTpl);
+ } else {
+ if (IsListEmpty (&mEfiRedfishDiscoverRestExInstance)) {
+ return EFI_NOT_FOUND;
+ }
+ OldTpl = gBS->RaiseTPL (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL);
+ RestExInstance = (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverRestExInstance);
+ while (TRUE) {
+ if (RestExInstance->RestExChildHandle == ControllerHandle) {
+ Status = 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, &RestExInstance->Entry)) {
+ break;
+ }
+ RestExInstance = (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL *)GetNextNode(&mEfiRedfishDiscoverRestExInstance, &RestExInstance->Entry);
+ };
+ gBS->RestoreTPL (OldTpl);
+ }
+ }
+ }
+ return EFI_NOT_FOUND;
+}
+/**
+ Tests to see if this driver supports a given controller. If a child device is provided,
+ it further tests to see if this driver supports creating a handle for the specified child device.
+
+ This function checks to see if the driver specified by This supports the device specified by
+ ControllerHandle. Drivers will typically use the device path attached to
+ ControllerHandle and/or the services from the bus I/O abstraction attached to
+ ControllerHandle to determine if the driver supports ControllerHandle. This function
+ may be called many times during platform initialization. In order to reduce boot times, the tests
+ performed by this function must be very small, and take as little time as possible to execute. This
+ function must not change the state of any hardware devices, and this function must be aware that the
+ device specified by ControllerHandle may already be managed by the same driver or a
+ different driver. This function must match its calls to AllocatePages() with FreePages(),
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+ Because ControllerHandle may have been previously started by the same driver, if a protocol is
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required
+ to guarantee the state of ControllerHandle is not modified by this function.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For bus drivers, if this parameter is not NULL, then
+ the bus driver must determine if the bus controller specified
+ by ControllerHandle and the child controller specified
+ by RemainingDevicePath are both supported by this
+ bus driver.
+
+ @retval EFI_SUCCESS The device specified by ControllerHandle and
+ RemainingDevicePath is supported by the driver specified by This.
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by the driver
+ specified by This.
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by a different
+ driver or an application that requires exclusive access.
+ Currently not implemented.
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
+ RemainingDevicePath is not supported by the driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+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 behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE.
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+ EFI_DEVICE_PATH_PROTOCOL.
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to start. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For a bus driver, if this parameter is NULL, then handles
+ for all the children of Controller are created by this driver.
+ If this parameter is not NULL and the first Device Path Node is
+ not the End of Device Path Node, then only the handle for the
+ child device specified by the first Device Path Node of
+ RemainingDevicePath is created by this driver.
+ If the first Device Path Node of RemainingDevicePath is
+ the End of Device Path Node, no child handle is created by this
+ driver.
+
+ @retval EFI_SUCCESS The device was started.
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval Others The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+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 locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+ same driver's Start() function.
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+ Start() function, and the Start() function must have called OpenProtocol() on
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must
+ support a bus specific I/O protocol for the driver
+ to use to stop the device.
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
+ if NumberOfChildren is 0.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+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 = {
+ 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 = EFI_SUCCESS;
+ InitializeListHead (&mRedfishDiscoverList);
+ InitializeListHead (&mRedfishInstanceList);
+ InitializeListHead (&mEfiRedfishDiscoverNetworkInterface);
+ InitializeListHead (&mEfiRedfishDiscoverRestExInstance);
+ //
+ // Install binding protoocl to obtain UDP and REST EX protocol.
+ //
+ Status = 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 the 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 = EFI_SUCCESS;
+ // Destroy all network interfaces found by EFI Redfish Discover driver and
+ // stop services created for Redfish Discover.
+
+ while (!IsListEmpty (&mEfiRedfishDiscoverNetworkInterface)) {
+ ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface);
+ StopServiceOnNetworkInterface (&gRedfishDiscoverDriverBinding, ThisNetworkInterface->NetworkInterfaceProtocolInfo.ProtocolControllerHandle);
+ };
+ // Disconnect EFI Redfish discover driver controller to notify the
+ // clinet which uses .EFI Redfish discover protocol.
+
+ if (EfiRedfishDiscoverProtocolHandle != NULL) {
+ //
+ // Notify user EFI_REDFISH_DISCOVER_PROTOCOL is unloaded.
+ //
+ gBS->DisconnectController (EfiRedfishDiscoverProtocolHandle, NULL, NULL);
+ Status = gBS->UninstallProtocolInterface(
+ EfiRedfishDiscoverProtocolHandle,
+ &gEfiRedfishDiscoverProtocolGuid,
+ (VOID *)&mRedfishDiscover
+ );
+ }
+ return Status;
+}
diff --git a/RedfishPkg/RedfishDiscoverDxe/RedfishSmbiosHostInterface.c b/RedfishPkg/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<BR>
+
+ 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 == NULL) || (ProtocolData == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ Status = Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, NULL);
+ while (!EFI_ERROR (Status) && SmbiosHandle != SMBIOS_HANDLE_PI_RESERVED) {
+ if (Record->Type == SMBIOS_TYPE_MANAGEMENT_CONTROLLER_HOST_INTERFACE) {
+ //
+ // Check Interface Type, should be Network Host Interface = 40h
+ //
+ mType42Record = (SMBIOS_TABLE_TYPE42 *) Record;
+ if (mType42Record->InterfaceType == MCHostInterfaceTypeNetworkHostInterface) {
+ ASSERT (Record->Length >= 9);
+ Offset = 5;
+ RecordTmp = (UINT8 *) Record + Offset;
+ //
+ // Get interface specific data length.
+ //
+ SpecificDataLen = *RecordTmp;
+ Offset += 1;
+ RecordTmp = (UINT8 *) Record + Offset;
+
+ //
+ // Check Device Type, only PCI/PCIe Network Interface v2 is supported now.
+ //
+ if (*RecordTmp == REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE_V2) {
+ ASSERT (SpecificDataLen == sizeof (PCI_OR_PCIE_INTERFACE_DEVICE_DESCRIPTOR_V2) + 1);
+ *DeviceDescriptor = (REDFISH_INTERFACE_DATA *)RecordTmp;
+ Offset = Offset + SpecificDataLen;
+ RecordTmp = (UINT8 *) Record + Offset;
+ //
+ // Check Protocol count. if > 1, only use the first protocol.
+ //
+ ASSERT (*RecordTmp == 1);
+ Offset += 1;
+ RecordTmp = (UINT8 *) Record + Offset;
+ //
+ // Check protocol identifier.
+ //
+ if (*RecordTmp == MCHostInterfaceProtocolTypeRedfishOverIP) {
+ Offset += 1;
+ RecordTmp = (UINT8 *) Record + Offset;
+ ProtocolLength = *RecordTmp;
+
+ Offset += 1;
+ RecordTmp = (UINT8 *) Record + Offset;
+
+ //
+ // This SMBIOS record is invalid, if the length of protocol specific data for
+ // Redfish Over IP protocol is wrong.
+ //
+ if ((*(RecordTmp + 90) + sizeof (REDFISH_OVER_IP_PROTOCOL_DATA) - 1) != ProtocolLength) {
+ return EFI_SECURITY_VIOLATION;
+ }
+
+ Offset += ProtocolLength;
+ //
+ // This SMBIOS record is invalid, if the length is smaller than the offset.
+ //
+ if (Offset > mType42Record->Hdr.Length) {
+ return EFI_SECURITY_VIOLATION;
+ }
+ *ProtocolData = (REDFISH_OVER_IP_PROTOCOL_DATA *)RecordTmp;
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ }
+ Status = Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, NULL);
+ }
+
+ *ProtocolData = NULL;
+ return EFI_NOT_FOUND;
+}
--
2.17.1
-=-=-=-=-=-=-=-=-=-=-=-
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]
-=-=-=-=-=-=-=-=-=-=-=-
Abner: This is new feature. Can you submit one BZ for it? Thanks Liming > -----邮件原件----- > 发件人: devel@edk2.groups.io <devel@edk2.groups.io> 代表 Abner Chang > 发送时间: 2021年3月26日 12:54 > 收件人: devel@edk2.groups.io > 抄送: Nickle Wang <nickle.wang@hpe.com>; Jiaxin Wu > <jiaxin.wu@intel.com>; Siyuan Fu <siyuan.fu@intel.com>; Fan Wang > <fan.wang@intel.com>; Jiewen Yao <jiewen.yao@intel.com> > 主题: [edk2-devel] [PATCH] RedfishPkg/RedfishDiscoverDxe: EFI Redfish > Discover Protocol > > EDK2 EFI Redfish Discover Protocol implementation. Refer to UEFI spec 2.9 > section 31.1. > > Signed-off-by: Abner Chang <abner.chang@hpe.com> > Cc: Nickle Wang <nickle.wang@hpe.com> > Cc: Jiaxin Wu <jiaxin.wu@intel.com> > Cc: Siyuan Fu <siyuan.fu@intel.com> > Cc: Fan Wang <fan.wang@intel.com> > Cc: Jiewen Yao <jiewen.yao@intel.com> > --- > 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/RedfishSmbiosHostInterface.c > > diff --git a/RedfishPkg/RedfishComponents.dsc.inc > b/RedfishPkg/RedfishComponents.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<BR> > +# (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR> > # > # 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<BR> > +# (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR> > # > # 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/RedfishPkg/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<BR> > +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > +## > + > +[Defines] > + INF_VERSION = 0x0001001b > + BASE_NAME = RedfishDiscoverDxe > + FILE_GUID = > 28A76FE5-43D7-48A3-9714-C1B7BDD6DFB6 > + MODULE_TYPE = UEFI_DRIVER > + VERSION_STRING = 1.0 > + ENTRY_POINT = RedfishDiscoverEntryPoint > + UNLOAD_IMAGE = 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 ## > CONSUMES > + > diff --git a/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverInternal.h > b/RedfishPkg/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<BR> > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef EFI_REDFISH_DISCOVER_INTERNAL_H_ > +#define EFI_REDFISH_DISCOVER_INTERNAL_H_ > + > +#include <Uefi.h> > + > +#include <Protocol/ComponentName.h> > +#include <Protocol/ComponentName2.h> > +#include <Protocol/DriverBinding.h> > +#include <Protocol/RedfishDiscover.h> > +#include <Protocol/Smbios.h> > +#include <Protocol/Tcp4.h> > +#include <Protocol/Tcp6.h> > + > +#include <Library/BaseLib.h> > +#include <Library/BaseMemoryLib.h> > +#include <Library/DebugLib.h> > +#include <Library/MemoryAllocationLib.h> > +#include <Library/NetLib.h> > +#include <Library/PrintLib.h> > +#include <Library/RestExLib.h> > +#include <Library/UefiLib.h> > +#include <Library/UefiBootServicesTableLib.h> > +#include <Library/UefiDriverEntryPoint.h> > + > +#include <IndustryStandard/RedfishHostInterface.h> > + > +#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 = 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 > network protocol handle. > + EFI_HANDLE ProtocolControllerHandle; ///< The controller handle on > network protocol. > + VOID *NetworkProtocolInterface; ///< The protocol interface of > network 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 network protocol. > + EFI_HANDLE OpenDriverControllerHandle; ///< The controller > handle to open network protocol. > + UINTN HwAddressSize; ///< The size of > network interface hardware address. > + EFI_MAC_ADDRESS MacAddress; ///< MAC > address of network interface. > + CHAR16 *StrMacAddr; ///< String to > MAC address of network interface. > + BOOLEAN GotSubnetInfo; ///< Indicates sub > net information is retrieved. > + EFI_IP_ADDRESS SubnetAddr; ///< Subnet ID. > + EFI_IP_ADDRESS SubnetMask; ///< Subnet mask > (IPv4 only) > + UINT8 SubnetPrefixLength; ///< Subnet prefix. > + UINT16 VlanId; ///< VLAN ID > + UINT32 SubnetAddrInfoIPv6Number; ///< IPv6 address > info number. > + EFI_IP6_ADDRESS_INFO *SubnetAddrInfoIPv6; ///< IPv6 address > info. > + // > + // Network interface protocol and REST EX infor. > + // > + UINT32 NetworkProtocolType; ///< Network > protocol type. Refer to > + ///< > NETWORK_INTERFACE_PROTOCOL_TYPE. > + REDFISH_DISCOVER_NETWORK_INTERFACE_PROTOCOL > NetworkInterfaceProtocolInfo; ///< Network interface protocol information. > + EFI_HANDLE RestExHandle; ///< REST EX > handle associated 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 handle to open network protocol. > + EFI_HANDLE RestExChildHandle; ///< The child > handle created throught REST EX Service Protocol. > + EFI_HANDLE RestExControllerHandle; ///< The > controller handle which provide REST EX protocol. > + EFI_REST_EX_PROTOCOL *RestExProtocolInterface; ///< Pointer to > EFI_REST_EX_PROTOCOL. > + UINT32 RestExId; ///< The > identifier installed 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 protocol type, > + ///< > Refer to NETWORK_INTERFACE_PROTOCOL_TYPE. > + CHAR16 *ProtocolName; ///< > Protocol name. > + EFI_GUID *RequiredProtocolGuid; ///< > Network protocol interface GUID. > + EFI_GUID *RequiredServiceBindingProtocolGuid; ///< Network > protocol service GUID. > + EFI_GUID *DiscoveredProtocolGuid; ///< > Protocol interface GUID use to install identifier. > + EFI_REDFISH_DISCOVER_GET_SUBNET_INFO GetSubnetInfo; ///< > Function of getting 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 EFI_REDFISH_DISCOVERED_INSTANCE. > +} EFI_REDFISH_DISCOVERED_INTERNAL_LIST; > + > +// > +// Internal structure of Redfish discover instance. > +// > +typedef struct { > + LIST_ENTRY Entry; ///< > Link list entry. > + EFI_HANDLE Owner; ///< > The owner owns this Redfish service discovery. > + ///< > It's the EFI image handle of driver uses > + ///< > EFI Redfish Discover Protocol. > + EFI_REDFISH_DISCOVER_FLAG DiscoverFlags; ///< > EFI_REDFISH_DISCOVER_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 whether to validate Redfish Host interface. > + EFI_IP_ADDRESS TargetIpAddress; ///< > Target IP address 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_INSTANCE. > + @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 > connection. > + @retval EFI_SUCCESS Redfish service is added to list > successfully. > + > +**/ > +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/RedfishDiscoverDxe/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_PROTOCOL protocol. > + for EFI Refish Discover Protocol > + > + (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR> > + > + 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 > Driver. > + > + @param[in] This A pointer to the > EFI_COMPONENT_NAME_PROTOCOL instance. > + @param[in] Language A pointer to a three-character ISO 639-2 > language identifier. > + This is the language of the driver name that > that the caller > + is requesting, and it must match one of the > languages specified > + in SupportedLanguages. The number of > languages supported by a > + driver is up to the driver writer. > + @param[out] DriverName A pointer to the Unicode string to return. > This Unicode string > + is the name of the driver specified by This in > the language > + specified by Language. > + > + @retval EFI_SUCCESS The Unicode string for the Driver > specified by This > + and the language specified by > Language was returned > + in DriverName. > + @retval EFI_INVALID_PARAMETER Language is NULL. > + @retval EFI_INVALID_PARAMETER DriverName is NULL. > + @retval EFI_UNSUPPORTED The driver specified by This does not > support the > + language specified by Language. > + > +**/ > +EFI_STATUS > +EFIAPI > +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 controller > + that is being managed by an EFI Driver. > + > + @param[in] This A pointer to the > EFI_COMPONENT_NAME_PROTOCOL instance. > + @param[in] ControllerHandle The handle of a controller that the driver > specified by > + This is managing. This handle > specifies the controller > + whose name is to be returned. > + @param[in] ChildHandle The handle of the child controller to > retrieve the name > + of. This is an optional parameter > that may be NULL. It > + will be NULL for device drivers. It > will also be NULL > + for a bus drivers that wish to retrieve > the name of the > + bus controller. It will not be NULL > for a bus driver > + that wishes to retrieve the name of a > child controller. > + @param[in] Language A pointer to a three character ISO > 639-2 language > + identifier. This is the language of the > controller name > + that the caller is requesting, and it > must match one > + of the languages specified in > SupportedLanguages. The > + number of languages supported by a > driver is up to the > + driver writer. > + @param[out] ControllerName A pointer to the Unicode string to > return. This Unicode > + string is the name of the controller > specified by > + ControllerHandle and ChildHandle in > the language specified > + by Language, from the point of view > of the driver specified > + by This. > + > + @retval EFI_SUCCESS The Unicode string for the > user-readable name in the > + language specified by Language for > the driver > + specified by This was returned in > DriverName. > + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. > + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a > valid EFI_HANDLE. > + @retval EFI_INVALID_PARAMETER Language is NULL. > + @retval EFI_INVALID_PARAMETER ControllerName is NULL. > + @retval EFI_UNSUPPORTED The driver specified by This is not > currently managing > + the controller specified by > ControllerHandle and > + ChildHandle. > + @retval EFI_UNSUPPORTED The driver specified by This does not > support the > + language specified by Language. > + > +**/ > +EFI_STATUS > +EFIAPI > +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 > = { > + RedfishDiscoverComponentNameGetDriverName, > + RedfishDiscoverComponentNameGetControllerName, > + "eng" > +}; > + > +/// > +/// Component Name 2 Protocol instance > +/// > +GLOBAL_REMOVE_IF_UNREFERENCED > +EFI_COMPONENT_NAME2_PROTOCOL > gRedfishDiscoverComponentName2 = { > + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) > RedfishDiscoverComponentNameGetDriverName, > + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) > RedfishDiscoverComponentNameGetControllerName, > + "en" > +}; > + > +/// > +/// Table of driver names > +/// > +GLOBAL_REMOVE_IF_UNREFERENCED > +EFI_UNICODE_STRING_TABLE mRedfishDiscoverDriverNameTable[] = { > + { "eng;en", (CHAR16 *)L"Redfish Discover UEFI Driver" }, > + { NULL, NULL } > +}; > + > +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE > *gRedfishDiscoverControllerNameTable = NULL; > + > +/** > + Retrieves a Unicode string that is the user-readable name of the EFI > Driver. > + > + @param[in] This A pointer to the > EFI_COMPONENT_NAME_PROTOCOL instance. > + @param[in] Language A pointer to a three-character ISO 639-2 > language identifier. > + This is the language of the driver name that > that the caller > + is requesting, and it must match one of the > languages specified > + in SupportedLanguages. The number of > languages supported by a > + driver is up to the driver writer. > + @param[out] DriverName A pointer to the Unicode string to return. > This Unicode string > + is the name of the driver specified by This in > the language > + specified by Language. > + > + @retval EFI_SUCCESS The Unicode string for the Driver > specified by This > + and the language specified by > Language was returned > + in DriverName. > + @retval EFI_INVALID_PARAMETER Language is NULL. > + @retval EFI_INVALID_PARAMETER DriverName is NULL. > + @retval EFI_UNSUPPORTED The driver specified by This does not > support the > + language specified by Language. > + > +**/ > +EFI_STATUS > +EFIAPI > +RedfishDiscoverComponentNameGetDriverName ( > + IN EFI_COMPONENT_NAME_PROTOCOL *This, > + IN CHAR8 *Language, > + OUT CHAR16 **DriverName > + ) > +{ > + return LookupUnicodeString2 ( > + Language, > + This->SupportedLanguages, > + mRedfishDiscoverDriverNameTable, > + DriverName, > + (BOOLEAN)(This == &gRedfishDiscoverComponentName) > + ); > +} > + > +/** > + Retrieves a Unicode string that is the user readable name of the controller > + that is being managed by an EFI Driver. > + > + @param[in] This A pointer to the > EFI_COMPONENT_NAME_PROTOCOL instance. > + @param[in] ControllerHandle The handle of a controller that the driver > specified by > + This is managing. This handle > specifies the controller > + whose name is to be returned. > + @param[in] ChildHandle The handle of the child controller to > retrieve the name > + of. This is an optional parameter > that may be NULL. It > + will be NULL for device drivers. It > will also be NULL > + for a bus drivers that wish to retrieve > the name of the > + bus controller. It will not be NULL > for a bus driver > + that wishes to retrieve the name of a > child controller. > + @param[in] Language A pointer to a three character ISO > 639-2 language > + identifier. This is the language of the > controller name > + that the caller is requesting, and it > must match one > + of the languages specified in > SupportedLanguages. The > + number of languages supported by a > driver is up to the > + driver writer. > + @param[out] ControllerName A pointer to the Unicode string to > return. This Unicode > + string is the name of the controller > specified by > + ControllerHandle and ChildHandle in > the language specified > + by Language, from the point of view > of the driver specified > + by This. > + > + @retval EFI_SUCCESS The Unicode string for the > user-readable name in the > + language specified by Language for > the driver > + specified by This was returned in > DriverName. > + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. > + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a > valid EFI_HANDLE. > + @retval EFI_INVALID_PARAMETER Language is NULL. > + @retval EFI_INVALID_PARAMETER ControllerName is NULL. > + @retval EFI_UNSUPPORTED The driver specified by This is not > currently managing > + the controller specified by > ControllerHandle and > + ChildHandle. > + @retval EFI_UNSUPPORTED The driver specified by This does not > support the > + language specified by Language. > + > +**/ > +EFI_STATUS > +EFIAPI > +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/RedfishPkg/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<BR> > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include "RedfishDiscoverInternal.h" > + > +LIST_ENTRY mRedfishDiscoverList; > +LIST_ENTRY mRedfishInstanceList; > +EFI_SMBIOS_PROTOCOL *mSmbios = NULL; > + > +UINTN mNumNetworkInterface = 0; > +UINTN mNumRestExInstance = 0; > +LIST_ENTRY mEfiRedfishDiscoverNetworkInterface; > +LIST_ENTRY mEfiRedfishDiscoverRestExInstance; > + > +EFI_GUID mRedfishDiscoverTcp4InstanceGuid = > EFI_REDFISH_DISCOVER_TCP4_INSTANCE_GUID; > +EFI_GUID mRedfishDiscoverTcp6InstanceGuid = > EFI_REDFISH_DISCOVER_TCP6_INSTANCE_GUID; > +EFI_GUID mRedfishDiscoverRestExInstanceGuid = > EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_GUID; > + > +EFI_HANDLE EfiRedfishDiscoverProtocolHandle = 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[] = { > + { > + 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 this owner. > + > +**/ > +EFI_STATUS > +CreateRestExInstance ( > + IN EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *Instance, > + IN EFI_REDFISH_DISCOVERED_TOKEN *Token > + ) > +{ > + EFI_STATUS Status; > + > + Status = RestExLibCreateChild ( > + Instance->Owner, > + FixedPcdGetBool (PcdRedfishDiscoverAccessModeInBand)? > EfiRestExServiceInBandAccess: EfiRestExServiceOutOfBandAccess, > + EfiRestExConfigHttp, > + EfiRestExServiceRedfish, > + > &Token->DiscoverList.RedfishInstances->Information.RedfishRestExHandle > + ); > + return Status; > +} > + > +/** > + This function gets EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE > + by known owner handle. > + > + @param[in] ImageHandle Image handle owns > EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE. > + @param[in] TargetNetworkInterface Target network interface used > by this 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 this owner. > + > +**/ > +EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE * > +GetInstanceByOwner ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL > *TargetNetworkInterface, > + IN EFI_REDFISH_DISCOVER_FLAG DiscoverFlags > + ) > +{ > + EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *ThisInstance; > + > + if (IsListEmpty (&mRedfishDiscoverList)) { > + return NULL; > + } > + ThisInstance = > + (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *)GetFirstNode > (&mRedfishDiscoverList); > + while (TRUE) { > + if ((ThisInstance->Owner == ImageHandle) && > + (ThisInstance->DiscoverFlags == DiscoverFlags) && > + (ThisInstance->NetworkInterface == TargetNetworkInterface)) { > + return ThisInstance; > + } > + if (IsNodeAtEnd (&mRedfishDiscoverList, &ThisInstance->Entry)) { > + break; > + } > + ThisInstance = > + (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *)GetNextNode > (&mRedfishDiscoverList, &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 == NULL) { > + return EFI_INVALID_PARAMETER; > + } > + Tcp4 = (EFI_TCP4_PROTOCOL > *)Instance->NetworkInterfaceProtocolInfo.NetworkProtocolInterface; > + > + 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 = TRUE; > + Tcp4CfgData.AccessPoint.RemoteAddress.Addr [0] = 127; > + Tcp4CfgData.AccessPoint.RemoteAddress.Addr [1] = 0; > + Tcp4CfgData.AccessPoint.RemoteAddress.Addr [2] = 0; > + Tcp4CfgData.AccessPoint.RemoteAddress.Addr [3] = 1; > + Tcp4CfgData.AccessPoint.RemotePort = 80; > + Tcp4CfgData.AccessPoint.ActiveFlag = TRUE; > + > + Tcp4CfgData.ControlOption = &Tcp4Option; > + Tcp4Option.ReceiveBufferSize = 65535; > + Tcp4Option.SendBufferSize = 65535; > + Tcp4Option.MaxSynBackLog = 5; > + Tcp4Option.ConnectionTimeout = 60; > + Tcp4Option.DataRetries = 12; > + Tcp4Option.FinTimeout = 2; > + Tcp4Option.KeepAliveProbes = 6; > + Tcp4Option.KeepAliveTime = 7200; > + Tcp4Option.KeepAliveInterval = 30; > + Tcp4Option.EnableNagle = TRUE; > + Status = Tcp4->Configure (Tcp4, &Tcp4CfgData); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: Can't get subnet information\n", > __FUNCTION__)); > + return Status; > + } > + Status = Tcp4->GetModeData (Tcp4, NULL, NULL, &IpModedata, NULL, > NULL); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: Can't get IP mode data information\n", > __FUNCTION__)); > + return Status; > + } > + IP4_COPY_ADDRESS (&Instance->SubnetMask, > &IpModedata.ConfigData.SubnetMask); > + Instance->SubnetAddr.v4.Addr [0] = > IpModedata.ConfigData.StationAddress.Addr [0] & > Instance->SubnetMask.v4.Addr [0]; > + Instance->SubnetAddr.v4.Addr [1] = > IpModedata.ConfigData.StationAddress.Addr [1] & > Instance->SubnetMask.v4.Addr [1]; > + Instance->SubnetAddr.v4.Addr [2] = > IpModedata.ConfigData.StationAddress.Addr [2] & > Instance->SubnetMask.v4.Addr [2]; > + Instance->SubnetAddr.v4.Addr [3] = > IpModedata.ConfigData.StationAddress.Addr [3] & > Instance->SubnetMask.v4.Addr [3]; > + // > + // Calculate the subnet mask prefix. > + // > + GotPrefixLength = FALSE; > + PrefixLength = 0; > + SubnetMaskIndex = 0; > + while (GotPrefixLength == FALSE && SubnetMaskIndex < 4) { > + BitMask = 0x80; > + while (BitMask != 0) { > + if ((Instance->SubnetMask.v4.Addr [SubnetMaskIndex] & BitMask) != > 0) { > + PrefixLength ++; > + } else { > + GotPrefixLength = TRUE; > + break; > + } > + BitMask = BitMask >> 1; > + }; > + SubnetMaskIndex ++; > + }; > + Instance->SubnetPrefixLength = 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 == NULL) { > + return EFI_INVALID_PARAMETER; > + } > + Tcp6 = (EFI_TCP6_PROTOCOL > *)Instance->NetworkInterfaceProtocolInfo.NetworkProtocolInterface; > + > + Status = 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 == 0) { > + DEBUG ((DEBUG_INFO, "%a: No IPv6 address configured.\n")); > + } > + if (Instance->SubnetAddrInfoIPv6 != NULL) { > + FreePool (Instance->SubnetAddrInfoIPv6); > + } > + Instance->SubnetAddrInfoIPv6 = AllocateZeroPool > (IpModedata.AddressCount * sizeof (EFI_IP6_ADDRESS_INFO)); > + if (Instance->SubnetAddrInfoIPv6 == NULL) { > + DEBUG ((DEBUG_ERROR, "%a: Failed to allocate memory fir IPv6 > subnet address information\n")); > + return EFI_OUT_OF_RESOURCES; > + } > + Instance->SubnetAddrInfoIPv6Number = 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_INTERFACE. > + NULL for all > EFI_REDFISH_DISCOVER_NETWORK_INTERFACEs. > + > + @retval Non-NULL > EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL is returned. > + @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 = > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode > (&mEfiRedfishDiscoverNetworkInterface); > + while (TRUE) { > + if (CompareMem((VOID *)&ThisNetworkInterface->MacAddress, > &TargetNetworkInterface->MacAddress, > ThisNetworkInterface->HwAddressSize) == 0) { > + return ThisNetworkInterface; > + } > + if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, > &ThisNetworkInterface->Entry)) { > + return NULL; > + } > + ThisNetworkInterface = > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL > *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, > &ThisNetworkInterface->Entry); > + }; > + return NULL; > +} > + > +/** > + This function validate if target network interface is ready for discovering > + Redfish service. > + > + @param[in] TargetNetworkInterface > EFI_REDFISH_DISCOVER_NETWORK_INTERFACE. > + NULL for all > EFI_REDFISH_DISCOVER_NETWORK_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) && > TargetNetworkInterface == NULL) { > + return EFI_UNSUPPORTED; > + } > + if (TargetNetworkInterface == NULL) { > + return EFI_SUCCESS; // Return EFI_SUCCESS if no network interface is > specified. > + } > + > + ThisNetworkInterface = > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL > *)GetFirstNode(&mEfiRedfishDiscoverNetworkInterface); > + while (TRUE) { > + if (CompareMem((VOID *)&ThisNetworkInterface->MacAddress, > &TargetNetworkInterface->MacAddress, > ThisNetworkInterface->HwAddressSize) == 0) { > + break; > + } > + if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, > &ThisNetworkInterface->Entry)) { > + return EFI_UNSUPPORTED; > + } > + ThisNetworkInterface = > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL > *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, > &ThisNetworkInterface->Entry); > + }; > + if ((Flags & EFI_REDFISH_DISCOVER_SSDP) != 0) { > + // Validate if UDP4/6 is supported on the given network interface. > + // SSDP is not supported. > + > + return EFI_SUCCESS; > + } > + if > (ThisNetworkInterface->NetworkInterfaceProtocolInfo.ProtocolControllerHan > dle == NULL) { > + return EFI_UNSUPPORTED; // The required protocol on this network > interface 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 = 1; > + ThisNetworkInterface = > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode > (&mEfiRedfishDiscoverNetworkInterface); > + while (TRUE) { > + if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, > &ThisNetworkInterface->Entry)) { > + break; > + } > + ThisNetworkInterface = > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL > *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, > &ThisNetworkInterface->Entry); > + Num ++; > + }; > + return Num; > +} > + > +/** > + This function checks the IP version supported on this > + netwoek interface. > + > + @param[in] ThisNetworkInterface > EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL > + > + @retval TRUE Is IPv6, otherwise IPv4. > + > +**/ > +BOOLEAN > +CheckIsIpVersion6 ( > + IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL > *ThisNetworkInterface > +) > +{ > + if (ThisNetworkInterface->NetworkProtocolType == 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 > SMBIOS 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 = NULL; > + DeviceDescriptor = NULL; > + > + if (mSmbios == NULL) { > + Status = gBS->LocateProtocol(&gEfiSmbiosProtocolGuid, NULL, (VOID > **)&mSmbios); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + } > + Status = RedfishGetHostInterfaceProtocolData (mSmbios, > &DeviceDescriptor, &Data); // Search for SMBIOS type 42h > + if (!EFI_ERROR (Status) && Data != NULL && DeviceDescriptor != NULL) { > + // > + // Chceck if we can reach out Redfish service using this network > interface. > + // Check with MAC address using Device Descroptor Data Device Type > 04 and Type 05. > + // Those two types of Redfish host interface device has MAC > information. > + // > + if (DeviceDescriptor->DeviceType == > REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE_V2) { > + MacCompareStstus = > CompareMem(&Instance->NetworkInterface->MacAddress, > &DeviceDescriptor->DeviceDescriptor.PciPcieDeviceV2.MacAddress, 6); > + } else if (DeviceDescriptor->DeviceType == > REDFISH_HOST_INTERFACE_DEVICE_TYPE_USB_V2){ > + MacCompareStstus = > CompareMem(&Instance->NetworkInterface->MacAddress, > &DeviceDescriptor->DeviceDescriptor.UsbDeviceV2.MacAddress, 6); > + } else { > + return EFI_UNSUPPORTED; > + } > + if (MacCompareStstus != 0) { > + return EFI_UNSUPPORTED; > + } > + > + if (Data->RedfishServiceIpAddressFormat == 1) { > + IP4_COPY_ADDRESS ((VOID *)&Instance->TargetIpAddress.v4, (VOID > *)Data->RedfishServiceIpAddress); > + } else { > + IP6_COPY_ADDRESS ((VOID *)&Instance->TargetIpAddress.v6, (VOID > *)Data->RedfishServiceIpAddress); > + } > + > + if (Instance->HostIntfValidation) { > + DEBUG ((DEBUG_ERROR,"%a:Send UPnP unicast SSDP to validate > this Redfish Host Interface is not supported.\n", __FUNCTION__)); > + Status = EFI_UNSUPPORTED; > + } else { > + // > + // Add this istance to list without detial information of Redfish > + // service. > + // > + IsHttps = FALSE; > + if (Data->RedfishServiceIpPort == 443) { > + IsHttps = TRUE; > + } > + StrSize = sizeof(UuidStr); > + AsciiSPrint(UuidStr, StrSize, "%g", &Data->ServiceUuid); > + // > + // Generate Redfish service location string. > + // > + if (Data->RedfishServiceIpAddressFormat == > REDFISH_HOST_INTERFACE_HOST_IP_ADDRESS_FORMAT_IP6) { > + NetLibIp6ToStr((IPv6_ADDRESS *)&Data->RedfishServiceIpAddress, > Ipv6Str, sizeof (Ipv6Str)); > + if (Data->RedfishServiceIpPort == 0 || IsHttps == TRUE) { > + AsciiSPrintUnicodeFormat ( > + RedfishServiceLocateStr, > + sizeof (RedfishServiceLocateStr), > + L"%s", > + Ipv6Str > + ); > + } else { > + AsciiSPrintUnicodeFormat( > + RedfishServiceLocateStr, > + sizeof (RedfishServiceLocateStr), > + L"[%s]:%d", > + Ipv6Str, > + Data->RedfishServiceIpPort > + ); > + } > + } else { > + if (Data->RedfishServiceIpPort == 0 || IsHttps == 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 = 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_INSTANCE. > + @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 > connection. > + @retval EFI_SUCCESS Redfish service is added to list > successfully. > + > +**/ > +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 = TRUE; > + InfoRefresh = FALSE; > + Char16Uuid = NULL; > + RestExOpened = FALSE; > + DeleteRestEx = FALSE; > + > + DEBUG ((DEBUG_INFO,"%a:Add this instance to Redfish instance list.\n", > __FUNCTION__)); > + > + if (Uuid != NULL) { > + Char16Uuid = (CHAR16 *)AllocateZeroPool(AsciiStrSize((const CHAR8 > *)Uuid) * sizeof(CHAR16)); > + AsciiStrToUnicodeStrS ((const CHAR8 *)Uuid, Char16Uuid, > AsciiStrSize((const CHAR8 *)Uuid) * sizeof(CHAR16)); > + } > + DiscoveredList = NULL; > + DiscoveredInstance = NULL; > + RestExHttpConfigData = NULL; > + > + NetworkInterface = Instance->NetworkInterface; > + if (!IsListEmpty (&mRedfishInstanceList)) { > + // > + // Is this a duplicate redfish service. > + // > + DiscoveredList = (EFI_REDFISH_DISCOVERED_INTERNAL_LIST > *)GetFirstNode (&mRedfishInstanceList); > + NewFound = FALSE; > + do { > + if (Char16Uuid == NULL || > DiscoveredList->Instance->Information.Uuid == NULL) { > + // > + // Check if this Redfish instance already found using IP addrress. > + // > + if (!CheckIsIpVersion6(NetworkInterface)) { > + if (CompareMem ((VOID *)&Instance->TargetIpAddress.v4, > + (VOID > *)&DiscoveredList->Instance->Information.RedfishHostIpAddress.v4, > + sizeof (EFI_IPv4_ADDRESS) > + ) == 0) > + { > + DiscoveredInstance = DiscoveredList->Instance; > + if (DiscoveredList->Instance->Information.Uuid == NULL && > + Char16Uuid != NULL) { > + InfoRefresh = TRUE; > + DiscoveredInstance = DiscoveredList->Instance; > + DEBUG((DEBUG_INFO,"*** This Redfish Service > information refresh ***\n")); > + } > + break; > + } > + } else { > + if (CompareMem ((VOID *)&Instance->TargetIpAddress.v6, > + (VOID > *)&DiscoveredList->Instance->Information.RedfishHostIpAddress.v6, > + sizeof (EFI_IPv6_ADDRESS) > + ) == 0) > + { > + DiscoveredInstance = DiscoveredList->Instance; > + break; > + } > + } > + } else { > + // > + // Check if this Redfish instance already found using UUID. > + // > + if (StrCmp((const CHAR16 *)Char16Uuid, (const CHAR16 > *)DiscoveredList->Instance->Information.Uuid) == 0) { > + DiscoveredInstance = DiscoveredList->Instance; > + break; > + } > + } > + if (IsNodeAtEnd (&mRedfishInstanceList, > &DiscoveredList->NextInstance)) { > + NewFound = TRUE; > + break; > + } > + DiscoveredList = (EFI_REDFISH_DISCOVERED_INTERNAL_LIST > *)GetNextNode (&mRedfishInstanceList, &DiscoveredList->NextInstance); > + } while (TRUE); > + } > + if (NewFound || InfoRefresh) { > + if (!InfoRefresh) { > + DiscoveredList = (EFI_REDFISH_DISCOVERED_INTERNAL_LIST > *)AllocateZeroPool(sizeof(EFI_REDFISH_DISCOVERED_INTERNAL_LIST)); > + if (DiscoveredList == NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + InitializeListHead (&DiscoveredList->NextInstance); > + DiscoveredInstance = (EFI_REDFISH_DISCOVERED_INSTANCE > *)AllocateZeroPool(sizeof(EFI_REDFISH_DISCOVERED_INSTANCE)); > + if (DiscoveredInstance == NULL) { > + FreePool ((VOID *)DiscoveredList); > + return EFI_OUT_OF_RESOURCES; > + } > + } > + DEBUG ((DEBUG_INFO,"*** Redfish Service Information ***\n")); > + > + DiscoveredInstance->Information.UseHttps = UseHttps; > + if (RedfishVersion != NULL) { > + DiscoveredInstance->Information.RedfishVersion = *RedfishVersion; > + DEBUG ((DEBUG_INFO,"Redfish service version: %d.\n", > DiscoveredInstance->Information.RedfishVersion)); > + } > + if (RedfishLocation != NULL) { > + DiscoveredInstance->Information.Location = (CHAR16 > *)AllocatePool(AsciiStrSize((const CHAR8 *)RedfishLocation) * > sizeof(CHAR16)); > + AsciiStrToUnicodeStrS ((const CHAR8 *)RedfishLocation, > DiscoveredInstance->Information.Location, AsciiStrSize((const CHAR8 > *)RedfishLocation) * sizeof(CHAR16)); > + DEBUG ((DEBUG_INFO,"Redfish service location: %s.\n", > DiscoveredInstance->Information.Location)); > + } > + if (Uuid != NULL) { > + DiscoveredInstance->Information.Uuid = (CHAR16 > *)AllocatePool(AsciiStrSize((const CHAR8 *)Uuid) * sizeof(CHAR16)); > + AsciiStrToUnicodeStrS ((const CHAR8 *)Uuid, > DiscoveredInstance->Information.Uuid, AsciiStrSize((const CHAR8 *)Uuid) * > sizeof(CHAR16)); > + DEBUG ((DEBUG_INFO,"Service UUID: %s.\n", > DiscoveredInstance->Information.Uuid)); > + } > + if (Os != NULL) { > + DiscoveredInstance->Information.Os = (CHAR16 > *)AllocatePool(AsciiStrSize((const CHAR8 *)Os) * sizeof(CHAR16)); > + AsciiStrToUnicodeStrS ((const CHAR8 *)Os, > DiscoveredInstance->Information.Os, AsciiStrSize((const CHAR8 *)Os) * > sizeof(CHAR16)); > + DEBUG ((DEBUG_INFO,"Redfish service OS: %s, Version:%s.\n", > DiscoveredInstance->Information.Os, > DiscoveredInstance->Information.OsVersion)); > + } > + if (OsVer != NULL) { > + DiscoveredInstance->Information.OsVersion = (CHAR16 > *)AllocatePool(AsciiStrSize((const CHAR8 *)OsVer) * sizeof(CHAR16)); > + AsciiStrToUnicodeStrS ((const CHAR8 *)OsVer, > DiscoveredInstance->Information.OsVersion, AsciiStrSize((const CHAR8 > *)OsVer) * sizeof(CHAR16)); > + } > + if (Product != NULL && ProductVer != NULL) { > + DiscoveredInstance->Information.Product = (CHAR16 > *)AllocatePool(AsciiStrSize((const CHAR8 *)Product) * sizeof(CHAR16)); > + AsciiStrToUnicodeStrS ((const CHAR8 *)Product, > DiscoveredInstance->Information.Product, AsciiStrSize((const CHAR8 > *)Product) * sizeof(CHAR16)); > + DiscoveredInstance->Information.ProductVer = (CHAR16 > *)AllocatePool(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", > DiscoveredInstance->Information.Product, > DiscoveredInstance->Information.ProductVer)); > + } > + > + if (RedfishLocation == NULL) { > + // This is the Redfish reported from SMBIOS 42h > + // without validation. > + > + IP4_COPY_ADDRESS((VOID > *)&DiscoveredInstance->Information.RedfishHostIpAddress.v4, (VOID > *)&Instance->TargetIpAddress.v4); > + } > + if (!InfoRefresh) { > + DiscoveredList->Instance = DiscoveredInstance; > + InsertTailList(&mRedfishInstanceList, > &DiscoveredList->NextInstance); > + } > + DiscoveredInstance->Status = EFI_SUCCESS; > + } else { > + if (DiscoveredList != NULL) { > + DEBUG((DEBUG_INFO,"*** This Redfish Service was already found > ***\n")); > + if (DiscoveredInstance->Information.Uuid != NULL) { > + DEBUG((DEBUG_INFO,"Service UUID: %s.\n", > DiscoveredInstance->Information.Uuid)); > + } else { > + DEBUG((DEBUG_INFO,"Service UUID: unknown.\n")); > + } > + } > + } > + if (Char16Uuid != NULL) { > + FreePool((VOID *)Char16Uuid); > + } > + > + Status = EFI_SUCCESS; > + if (NewFound || InfoRefresh) { > + // > + // Build up EFI_REDFISH_DISCOVERED_LIST in token. > + // > + Instance->DiscoverToken->DiscoverList.NumberOfServiceFound = 1; > + Instance->DiscoverToken->DiscoverList.RedfishInstances = > DiscoveredInstance; > + DiscoveredInstance->Status = EFI_SUCCESS; > + if (!InfoRefresh) { > + Status = 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 = gBS->OpenProtocol ( // Configure local host information. > + > Instance->DiscoverToken->DiscoverList.RedfishInstances->Information.Redfis > hRestExHandle, > + &gEfiRestExProtocolGuid, > + (VOID **)&RestEx, > + > Instance->NetworkInterface->OpenDriverAgentHandle, > + > Instance->NetworkInterface->OpenDriverControllerHandle, > + EFI_OPEN_PROTOCOL_BY_DRIVER > + ); > + if (EFI_ERROR (Status)) { > + DeleteRestEx = TRUE; > + goto ERROR_EXIT; > + } > + RestExOpened = TRUE; > + RestExHttpConfigData = AllocateZeroPool (sizeof > (EFI_REST_EX_HTTP_CONFIG_DATA)); > + if (RestExHttpConfigData == NULL) { > + Status = EFI_OUT_OF_RESOURCES; > + DeleteRestEx = TRUE; > + goto EXIT_FREE_CONFIG_DATA; > + } > + RestExHttpConfigData->SendReceiveTimeout = 5000; > + RestExHttpConfigData->HttpConfigData.HttpVersion = > HttpVersion11; > + RestExHttpConfigData->HttpConfigData.LocalAddressIsIPv6 = > CheckIsIpVersion6(NetworkInterface); > + if (RestExHttpConfigData->HttpConfigData.LocalAddressIsIPv6) { > + RestExHttpConfigData->HttpConfigData.AccessPoint.IPv6Node = > AllocateZeroPool (sizeof (EFI_HTTPv6_ACCESS_POINT)); > + if (RestExHttpConfigData->HttpConfigData.AccessPoint.IPv6Node > == NULL) { > + Status = EFI_OUT_OF_RESOURCES; > + goto EXIT_FREE_CONFIG_DATA; > + } > + } else { > + RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node = > AllocateZeroPool (sizeof (EFI_HTTPv4_ACCESS_POINT)); > + if (RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node > == NULL) { > + Status = EFI_OUT_OF_RESOURCES; > + goto EXIT_FREE_CONFIG_DATA; > + } > + > RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node->UseDefaultA > ddress = TRUE; > + } > + Status = RestEx->Configure ( > + RestEx, > + (EFI_REST_EX_CONFIG_DATA)(UINT8 > *)RestExHttpConfigData > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR,"%a:REST EX configured..\n", > __FUNCTION__)); > + DeleteRestEx = TRUE; > + goto EXIT_FREE_ALL; > + } > + // > + // Signal client, close REST EX before signaling client. > + // > + if (RestExOpened) { > + gBS->CloseProtocol( > + > Instance->DiscoverToken->DiscoverList.RedfishInstances->Information.Redfis > hRestExHandle, > + &gEfiRestExProtocolGuid, > + Instance->NetworkInterface->OpenDriverAgentHandle, > + Instance->NetworkInterface->OpenDriverControllerHandle > + ); > + RestExOpened = FALSE; > + } > + } > + Status = gBS->SignalEvent(Instance->DiscoverToken->Event); > + if (!EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR,"%a:No event to signal!\n", > __FUNCTION__)); > + } > + } > + > +EXIT_FREE_ALL:; > + if (RestExHttpConfigData != NULL && > RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node != NULL) { > + FreePool > (RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node); > + } > + > +EXIT_FREE_CONFIG_DATA:; > + if (RestExHttpConfigData != NULL) { > + FreePool((VOID *)RestExHttpConfigData); > + } > + if (RestExOpened) { > + gBS->CloseProtocol( > + > Instance->DiscoverToken->DiscoverList.RedfishInstances->Information.Redfis > hRestExHandle, > + &gEfiRestExProtocolGuid, > + Instance->NetworkInterface->OpenDriverAgentHandle, > + Instance->NetworkInterface->OpenDriverControllerHandle > + ); > + } > +ERROR_EXIT:; > + if (DeleteRestEx && RestExOpened) { > + gBS->CloseProtocol( > + > Instance->DiscoverToken->DiscoverList.RedfishInstances->Information.Redfis > hRestExHandle, > + &gEfiRestExProtocolGuid, > + Instance->NetworkInterface->OpenDriverAgentHandle, > + Instance->NetworkInterface->OpenDriverControllerHandle > + ); > + } > +ON_EXIT:; > + return Status; > +} > + > +/** > + This function gets the subnet information of this network interface > instance. > + can discover Redfish service on it. > + > + @param[in] Instance > EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL instance. > + @param[in] ImageHandle EFI Image handle request the network > interface 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 = Instance->NetworkProtocolType; > + if (gRequiredProtocol [ProtocolType].GetSubnetInfo != NULL && > Instance->GotSubnetInfo == FALSE) { > + Status = gRequiredProtocol [ProtocolType].GetSubnetInfo ( > + ImageHandle, > + Instance > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR,"%a:Faile to get Subnet infomation.\n", > __FUNCTION__)); > + return Status; > + } else { > + DEBUG ((DEBUG_INFO,"%a:MAC address: %s\n", __FUNCTION__, > Instance->StrMacAddr)); > + if (CheckIsIpVersion6 (Instance)) { > + if (Instance->SubnetAddrInfoIPv6Number == 0) { > + DEBUG ((DEBUG_ERROR,"%a: There is no Subnet infomation for > IPv6 network interface.\n", __FUNCTION__)); > + return EFI_NOT_FOUND; > + } > + ThisSubnetAddrInfoIPv6 = Instance->SubnetAddrInfoIPv6; // First > IPv6 address information. > + IP6_COPY_ADDRESS (&Instance->SubnetAddr.v6, > &ThisSubnetAddrInfoIPv6->Address); > + Instance->SubnetPrefixLength = > ThisSubnetAddrInfoIPv6->PrefixLength; > + DEBUG((DEBUG_INFO," IPv6 Subnet ID:%d, Prefix > length: %d.\n", > + ThisSubnetAddrInfoIPv6->Address.Addr [7] + > (UINT16)ThisSubnetAddrInfoIPv6->Address.Addr [6] * 256, > + ThisSubnetAddrInfoIPv6->PrefixLength) > + ); > + // > + // If this is IPv6, then we may have to propagate network interface > for IPv6 network scopes > + // according to the Ipv6 address information. > + // > + ThisSubnetAddrInfoIPv6 ++; > + for (IPv6InfoIndex = 0; IPv6InfoIndex < > Instance->SubnetAddrInfoIPv6Number - 1; IPv6InfoIndex++) { > + // > + // Build up addtional > EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL instances. > + // > + NewNetworkInterface = > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL > *)AllocateZeroPool (sizeof > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL)); > + if (NewNetworkInterface != NULL) { > + CopyMem ((VOID *)NewNetworkInterface, (VOID *)Instance, > sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL)); // > Clone information of first instance. > + IP6_COPY_ADDRESS > (&NewNetworkInterface->SubnetAddr.v6, > &ThisSubnetAddrInfoIPv6->Address); > + NewNetworkInterface->SubnetPrefixLength = > ThisSubnetAddrInfoIPv6->PrefixLength; > + NewNetworkInterface->GotSubnetInfo = TRUE; > + InsertTailList (&mEfiRedfishDiscoverNetworkInterface, > &NewNetworkInterface->Entry); > + ThisSubnetAddrInfoIPv6 ++; > + mNumNetworkInterface ++; > + DEBUG((DEBUG_INFO," IPv6 Subnet ID:%d, Prefix > length: %d.\n", > + ThisSubnetAddrInfoIPv6->Address.Addr [7] + > (UINT16)ThisSubnetAddrInfoIPv6->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 = TRUE; // Only try to get Subnet Info once. > + return EFI_SUCCESS; > +} > + > +/** > + This function gets the network interface list which Redfish discover > protocol > + can discover Redfish service on it. > + > + @param[in] This > EFI_REDFISH_DISCOVER_PROTOCOL instance. > + @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 > NumberOfNetworkIntfs. > + Caller has to release the > memory > + allocated by Redfish discover > protocol. > + > + @retval EFI_SUCCESS The information of network interface is > returned in NumberOfNetworkIntfs and > + NetworkIntfInstances. > + @retval Others Fail to return the information of network > interface. > + > +**/ > +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 > *ThisNetworkInterfaceIntn; > + EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *ThisNetworkInterface; > + > + if (NetworkIntfInstances == NULL || NumberOfNetworkIntfs == NULL || > ImageHandle == NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + *NumberOfNetworkIntfs = 0; > + *NetworkIntfInstances = NULL; > + > + if (IsListEmpty ((const > LIST_ENTRY*)&mEfiRedfishDiscoverNetworkInterface)) { > + return EFI_NOT_FOUND; > + } > + > + ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE > *)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE) > * mNumNetworkInterface); > + if (ThisNetworkInterface == NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + *NetworkIntfInstances = ThisNetworkInterface; > + ThisNetworkInterfaceIntn = > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode > (&mEfiRedfishDiscoverNetworkInterface); > + while (TRUE) { > + ThisNetworkInterface->IsIpv6 = FALSE; > + if (CheckIsIpVersion6 (ThisNetworkInterfaceIntn)) { > + ThisNetworkInterface->IsIpv6 = TRUE; > + } > + CopyMem((VOID *)&ThisNetworkInterface->MacAddress, > &ThisNetworkInterfaceIntn->MacAddress, > ThisNetworkInterfaceIntn->HwAddressSize); > + NetworkInterfaceGetSubnetInfo(ThisNetworkInterfaceIntn, > ImageHandle); // Get subnet info. > + if (!ThisNetworkInterface->IsIpv6) { > + IP4_COPY_ADDRESS(&ThisNetworkInterface->SubnetId.v4, > &ThisNetworkInterfaceIntn->SubnetAddr.v4); // IPv4 subnet information. > + } else { > + IP6_COPY_ADDRESS (&ThisNetworkInterface->SubnetId.v6, > &ThisNetworkInterfaceIntn->SubnetAddr.v6); // IPv6 subnet information in > IPv6 address information. > + } > + ThisNetworkInterface->SubnetPrefixLength = > ThisNetworkInterfaceIntn->SubnetPrefixLength; > + ThisNetworkInterface->VlanId = ThisNetworkInterfaceIntn->VlanId; > + (*NumberOfNetworkIntfs) ++; > + if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, > &ThisNetworkInterfaceIntn->Entry)) { > + break; > + } > + ThisNetworkInterfaceIntn = > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL > *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, > &ThisNetworkInterfaceIntn->Entry); > + ThisNetworkInterface ++; > + }; > + return EFI_SUCCESS; > +} > +/** > + This function acquires Redfish services by discovering static Redfish setting > + according to Redfish Host Interface or through SSDP. Returns a list of EFI > + handles in EFI_REDFISH_DISCOVERED_LIST. Each of EFI handle has > cooresponding > + EFI REST EX instance installed on it. Each REST EX isntance is a child > instance which > + created through EFI REST EX serivce protoocl for communicating with > specific > + Redfish service. > + > + @param[in] This > EFI_REDFISH_DISCOVER_PROTOCOL instance. > + @param[in] ImageHandle EFI image owns these > Redfish service instances. > + @param[in] TargetNetworkInterface Target network interface to > do the discovery. > + NULL means discover > Redfish service on all network interfaces on platform. > + @param[in] Flags Redfish service discover > flags. > + @param[in] Token > EFI_REDFISH_DISCOVERED_TOKEN instance. > + The memory of > EFI_REDFISH_DISCOVERED_LIST and the strings in > + > EFI_REDFISH_DISCOVERED_INFORMATION are all allocated by Acquire() > + and must be freed when > caller invoke Release(). > + > + @retval EFI_SUCCESS REST EX instance of discovered > Redfish services are returned. > + @retval EFI_INVALID_PARAMETERS ImageHandle == NULL, Flags == 0, > Token == NULL, Token->Timeout > 5, > + or Token->Event == 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 > *TargetNetworkInterfaceInternal; > + > + DEBUG ((DEBUG_INFO,"%a:Entry.\n", __FUNCTION__)); > + > + // > + // Validate parameters. > + // > + if (ImageHandle == NULL || Token == NULL || ((Flags & > ~EFI_REDFISH_DISCOVER_VALIDATION) == 0)) { > + DEBUG ((DEBUG_ERROR,"%a:Invalid parameters.\n", > __FUNCTION__)); > + return EFI_INVALID_PARAMETER; > + } > + // > + // Validate target network interface. > + // > + if (EFI_ERROR (ValidateTargetNetworkInterface (TargetNetworkInterface, > Flags))) { > + return EFI_UNSUPPORTED; > + } > + if (TargetNetworkInterface != NULL) { > + TargetNetworkInterfaceInternal = GetTargetNetworkInterfaceInternal > (TargetNetworkInterface); > + NumNetworkInterfaces = 1; > + } else { > + TargetNetworkInterfaceInternal = > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode > (&mEfiRedfishDiscoverNetworkInterface); > + NumNetworkInterfaces = NumberOfNetworkInterface (); > + if (NumNetworkInterfaces == 0) { > + DEBUG ((DEBUG_ERROR,"%a:No network interface on platform.\n", > __FUNCTION__)); > + return EFI_UNSUPPORTED; > + } > + } > + for (NetworkInterfacesIndex = 0; NetworkInterfacesIndex < > NumNetworkInterfaces; NetworkInterfacesIndex ++) { > + Status1 = EFI_SUCCESS; > + Status2 = EFI_SUCCESS; > + NewInstance = FALSE; > + Instance = GetInstanceByOwner (ImageHandle, > TargetNetworkInterfaceInternal, Flags & > ~EFI_REDFISH_DISCOVER_VALIDATION); // Check if we can re-use previous > instance. > + if (Instance == NULL) { > + DEBUG ((DEBUG_INFO,"%a:Create new > EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE.\n", __FUNCTION__)); > + Instance = (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE > *)AllocateZeroPool(sizeof(EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE)) > ; > + if (Instance == NULL) { > + DEBUG ((DEBUG_ERROR,"%a:Memory allocation fail.\n", > __FUNCTION__)); > + } > + InitializeListHead (&Instance->Entry); > + Instance->Owner = ImageHandle; > + Instance->DiscoverFlags = Flags & > ~EFI_REDFISH_DISCOVER_VALIDATION; > + Instance->NetworkInterface = TargetNetworkInterfaceInternal; > + // > + // Get subnet information in case subnet information is not set > because > + // RedfishServiceGetNetworkInterfaces hasn't been called yet. > + // > + NetworkInterfaceGetSubnetInfo (TargetNetworkInterfaceInternal, > ImageHandle); > + NewInstance = TRUE; > + } > + if (TargetNetworkInterfaceInternal->StrMacAddr != NULL) { > + DEBUG((DEBUG_INFO,"%a:Acquire Redfish service on network > interface MAC address:%s.\n", __FUNCTION__, > TargetNetworkInterfaceInternal->StrMacAddr)); > + } else { > + DEBUG((DEBUG_INFO,"%a:WARNING: No MAC address on this > network interface.\n", __FUNCTION__)); > + } > + > + Instance->DiscoverToken = Token; // Always use the latest Token > passed by caller. > + if ((Flags & EFI_REDFISH_DISCOVER_HOST_INTERFACE) != 0) { > + DEBUG ((DEBUG_INFO,"%a:Redfish HOST interface discovery.\n", > __FUNCTION__)); > + Instance->HostIntfValidation = FALSE; > + if ((Flags & EFI_REDFISH_DISCOVER_VALIDATION) != 0) { > + Instance->HostIntfValidation = TRUE; > + } > + Status1 = DiscoverRedfishHostInterface (Instance); // Discover > Redfish service through Redfish Host Interface. > + } > + if ((Flags & EFI_REDFISH_DISCOVER_SSDP) != 0) { > + DEBUG ((DEBUG_ERROR,"%a:Redfish service discovery through SSDP > is not 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 > discovery Status1=%x, Status2=%x.\n", __FUNCTION__, Status1, Status2)); > + } else { > + if (NewInstance) { > + InsertTailList(&mRedfishDiscoverList, &Instance->Entry); > + } > + } > + } > + if (TargetNetworkInterface == NULL) { > + // > + // Discover Redfish services on all of network interfaces. > + // > + TargetNetworkInterfaceInternal = > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL > *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, > &TargetNetworkInterfaceInternal->Entry); > + } > + } > + return EFI_SUCCESS; > +} > + > +/** > + This function aborts Redfish service discovery on the given network > interface. > + > + @param[in] This > EFI_REDFISH_DISCOVER_PROTOCOL instance. > + @param[in] TargetNetworkInterface Target network interface to > do the discovery. > + > + @retval EFI_SUCCESS REST EX instance of discovered > Redfish services 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 OPTIONAL > +) > +{ > + // 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 released. > + @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", > __FUNCTION__)); > + return EFI_NOT_FOUND; > + } > + AnyFailRelease = FALSE; > + ThisRedfishInstance = InstanceList->RedfishInstances; > + for (NumService = 0; NumService < InstanceList->NumberOfServiceFound; > NumService ++) { > + DiscoveredRedfishInstance = > (EFI_REDFISH_DISCOVERED_INTERNAL_LIST > *)GetFirstNode(&mRedfishInstanceList); > + do { > + if (DiscoveredRedfishInstance->Instance == ThisRedfishInstance) { > + RemoveEntryList (&DiscoveredRedfishInstance->NextInstance); > + if (ThisRedfishInstance->Information.Location != NULL) { > + FreePool (ThisRedfishInstance->Information.Location); > + } > + if (ThisRedfishInstance->Information.Uuid != NULL) { > + FreePool (ThisRedfishInstance->Information.Uuid); > + } > + if (ThisRedfishInstance->Information.Os != NULL) { > + FreePool (ThisRedfishInstance->Information.Os); > + } > + if (ThisRedfishInstance->Information.OsVersion != NULL) { > + FreePool (ThisRedfishInstance->Information.OsVersion); > + } > + if (ThisRedfishInstance->Information.Product != NULL) { > + FreePool (ThisRedfishInstance->Information.Product); > + } > + if (ThisRedfishInstance->Information.ProductVer != NULL) { > + FreePool (ThisRedfishInstance->Information.ProductVer); > + } > + FreePool((VOID *)ThisRedfishInstance); > + goto ReleaseNext; > + } > + > + if (IsNodeAtEnd(&mRedfishInstanceList, > &DiscoveredRedfishInstance->NextInstance)) { > + break; > + } > + DiscoveredRedfishInstance = > (EFI_REDFISH_DISCOVERED_INTERNAL_LIST > *)GetNextNode(&mRedfishInstanceList, > &DiscoveredRedfishInstance->NextInstance); > + } while (TRUE); > + AnyFailRelease = TRUE; > +ReleaseNext:; > + // > + // Release next discovered Redfish Service. > + // > + ThisRedfishInstance = (EFI_REDFISH_DISCOVERED_INSTANCE > *)((UINT8 *)ThisRedfishInstance + sizeof > (EFI_REDFISH_DISCOVERED_INSTANCE)); > + } > + if (AnyFailRelease) { > + return EFI_NOT_FOUND; > + } else { > + return EFI_SUCCESS; > + } > +} > + > +EFI_REDFISH_DISCOVER_PROTOCOL mRedfishDiscover = { > + 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_NETWORK_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 = NULL; > + *IsNewInstance = TRUE; > + if (!IsListEmpty ((const > LIST_ENTRY*)&mEfiRedfishDiscoverNetworkInterface)) { > + // > + // Check if this instance already exist. > + // > + ThisNetworkInterface = > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode > (&mEfiRedfishDiscoverNetworkInterface); > + if (ThisNetworkInterface != NULL) { > + while (TRUE) { > + if ((CompareMem ((CONST VOID > *)&ThisNetworkInterface->MacAddress.Addr, (CONST VOID > *)&MacAddress.Addr, HwAddressSize) == 0) && > + (ThisNetworkInterface->NetworkProtocolType == > NetworkProtocolType)){ > + NewNetworkInterface = ThisNetworkInterface; > + *IsNewInstance = FALSE; > + break; > + } > + if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, > &ThisNetworkInterface->Entry)) { > + NewNetworkInterface = NULL; > + break; > + } > + ThisNetworkInterface = > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL > *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, > &ThisNetworkInterface->Entry); > + }; > + } > + } > + if (NewNetworkInterface == NULL) { > + // > + // Create a new instance. > + // > + NewNetworkInterface = > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL > *)AllocateZeroPool (sizeof > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL)); > + if (NewNetworkInterface == NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + NewNetworkInterface->HwAddressSize = HwAddressSize; > + CopyMem (&NewNetworkInterface->MacAddress.Addr, > &MacAddress.Addr, NewNetworkInterface->HwAddressSize); > + NetLibGetMacString (ControllerHandle, NULL, > &NewNetworkInterface->StrMacAddr); > + NewNetworkInterface->VlanId = NetLibGetVlanId (ControllerHandle); > + } > + *NetworkInterface = 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 = gBS->UninstallProtocolInterface( > + ThisNetworkInterface->OpenDriverControllerHandle, > + gRequiredProtocol > [ThisNetworkInterface->NetworkProtocolType].DiscoveredProtocolGuid, > + > &ThisNetworkInterface->NetworkInterfaceProtocolInfo.ProtocolDiscoverId > + ); > + 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_PROTOCOL instance. > + @param[in] ControllerHandle The handle of the controller to test. > This handle > + must support a protocol > interface that supplies > + an I/O abstraction to the driver. > + @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 = 0; Index < (sizeof (gRequiredProtocol) / sizeof > (REDFISH_DISCOVER_REQUIRED_PROTOCOL)); Index ++) { > + Status = gBS->OpenProtocol ( > + ControllerHandle, > + gRequiredProtocol > [Index].RequiredServiceBindingProtocolGuid, > + NULL, > + This->DriverBindingHandle, > + ControllerHandle, > + EFI_OPEN_PROTOCOL_TEST_PROTOCOL > + ); > + if (!EFI_ERROR (Status)) { > + Status = 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_PROTOCOL instance. > + @param[in] ControllerHandle The handle of the controller to test. > This handle > + must support a protocol > interface that supplies > + an I/O abstraction to the driver. > + @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 = FALSE; > + Index = 0; > + do { > + Status = 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 == (sizeof(gRequiredProtocol) / > sizeof(REDFISH_DISCOVER_REQUIRED_PROTOCOL))) { > + break; > + } > + continue; > + } > + > + Status = gBS->OpenProtocol ( > + ControllerHandle, > + gRequiredProtocol > [Index].RequiredServiceBindingProtocolGuid, > + &TempInterface, > + This->DriverBindingHandle, > + ControllerHandle, > + EFI_OPEN_PROTOCOL_GET_PROTOCOL > + ); > + if (EFI_ERROR (Status)) { > + Index ++; > + if (Index == (sizeof(gRequiredProtocol) / > sizeof(REDFISH_DISCOVER_REQUIRED_PROTOCOL))) { > + break; > + } > + continue; > + } > + if (gRequiredProtocol [Index].ProtocolType != ProtocolTypeRestEx) { > + OldTpl = gBS->RaiseTPL > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL); > + Status = CreateRedfishDiscoverNetworkInterface(ControllerHandle, > gRequiredProtocol [Index].ProtocolType, &IsNew, &NetworkInterface); > + if (EFI_ERROR (Status)) { > + gBS->RestoreTPL (OldTpl); > + return Status; > + } > + NetworkInterface->NetworkProtocolType = gRequiredProtocol > [Index].ProtocolType; > + NetworkInterface->OpenDriverAgentHandle = > This->DriverBindingHandle; > + NetworkInterface->OpenDriverControllerHandle = ControllerHandle; > + NetworkInterface->NetworkInterfaceProtocolInfo.ProtocolGuid = \ > + *gRequiredProtocol [Index].RequiredProtocolGuid; > + > NetworkInterface->NetworkInterfaceProtocolInfo.ProtocolServiceGuid = \ > + *gRequiredProtocol [Index].RequiredServiceBindingProtocolGuid; > + ProtocolDiscoverIdPtr = > &NetworkInterface->NetworkInterfaceProtocolInfo.ProtocolDiscoverId; > + OpenDriverAgentHandle = > NetworkInterface->OpenDriverAgentHandle; > + OpenDriverControllerHandle = > NetworkInterface->OpenDriverControllerHandle; > + HandleOfProtocolInterfacePtr = > &NetworkInterface->NetworkInterfaceProtocolInfo.ProtocolControllerHandle > ; > + Interface = > &NetworkInterface->NetworkInterfaceProtocolInfo.NetworkProtocolInterfac > e; > + NewNetworkInterfaceInstalled = TRUE; > + if (IsNew) { > + InsertTailList (&mEfiRedfishDiscoverNetworkInterface, > &NetworkInterface->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 > corresponding EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL > + // when discovery. > + > + RestExInstance = > (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL *)AllocateZeroPool > (sizeof (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL)); > + if (RestExInstance == NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + RestExInstance->OpenDriverAgentHandle = > This->DriverBindingHandle; > + RestExInstance->OpenDriverControllerHandle = ControllerHandle; > + RestExInstance->RestExControllerHandle = ControllerHandle; > + InitializeListHead (&RestExInstance->Entry); > + InsertTailList (&mEfiRedfishDiscoverRestExInstance, > &RestExInstance->Entry); > + mNumRestExInstance ++; > + ProtocolDiscoverIdPtr = &RestExInstance->RestExId; > + OpenDriverAgentHandle = > RestExInstance->OpenDriverAgentHandle; > + OpenDriverControllerHandle = > RestExInstance->OpenDriverControllerHandle; > + HandleOfProtocolInterfacePtr = > &RestExInstance->RestExChildHandle; > + Interface = (VOID **)&RestExInstance->RestExProtocolInterface; > + } > + Status = gBS->InstallProtocolInterface ( > + &ControllerHandle, > + gRequiredProtocol [Index].DiscoveredProtocolGuid, > + EFI_NATIVE_INTERFACE, > + ProtocolDiscoverIdPtr > + ); > + if (EFI_ERROR (Status)) { > + Index ++; > + if (Index == (sizeof(gRequiredProtocol) / > sizeof(REDFISH_DISCOVER_REQUIRED_PROTOCOL))) { > + break; > + } > + continue; > + } > + // > + // Create service binding child and open it BY_DRIVER. > + // > + Status = NetLibCreateServiceChild ( > + ControllerHandle, > + This->ImageHandle, > + gRequiredProtocol > [Index].RequiredServiceBindingProtocolGuid, > + HandleOfProtocolInterfacePtr > + ); > + if (!EFI_ERROR (Status)) { > + Status = gBS->OpenProtocol ( > + *HandleOfProtocolInterfacePtr, > + gRequiredProtocol [Index].RequiredProtocolGuid, > + Interface, > + OpenDriverAgentHandle, > + OpenDriverControllerHandle, > + EFI_OPEN_PROTOCOL_BY_DRIVER > + ); > + if (!EFI_ERROR (Status)) { > + if (EfiRedfishDiscoverProtocolHandle == NULL && > + (gRequiredProtocol [Index].ProtocolType == > ProtocolTypeRestEx) && > + !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 = gBS->InstallProtocolInterface ( > + &EfiRedfishDiscoverProtocolHandle, > + &gEfiRedfishDiscoverProtocolGuid, > + EFI_NATIVE_INTERFACE, > + (VOID *)&mRedfishDiscover > + ); > + } else if (EfiRedfishDiscoverProtocolHandle != NULL && > NewNetworkInterfaceInstalled) { > + Status = gBS->ReinstallProtocolInterface ( > + EfiRedfishDiscoverProtocolHandle, > + &gEfiRedfishDiscoverProtocolGuid, > + (VOID *)&mRedfishDiscover, > + (VOID *)&mRedfishDiscover > + ); > + NewNetworkInterfaceInstalled = FALSE; > + } > + } > + return Status; > + } else { > + Index ++; > + if (Index == (sizeof(gRequiredProtocol) / > sizeof(REDFISH_DISCOVER_REQUIRED_PROTOCOL))) { > + break; > + } > + continue; > + } > + } while (Index < (sizeof(gRequiredProtocol) / > sizeof(REDFISH_DISCOVER_REQUIRED_PROTOCOL))); > + return EFI_UNSUPPORTED; > +} > +/** > + Close the protocol opened for Redfish discovery. This function also > destories > + 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 that supplies > + an I/O abstraction to the > driver. > + @param[in] ThisRequiredProtocol Pointer to the instance of > REDFISH_DISCOVER_REQUIRED_PROTOCOL. > + @param[in] DriverAgentHandle Driver agent handle which used > to open protocol earlier. > + @param[in] DriverControllerHandle Driver controller handle which used > to 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 = 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_PROTOCOL instance. > + @param[in] ControllerHandle The handle of the controller to test. > This handle > + must support a protocol > interface that supplies > + an I/O abstraction to the driver. > + @retval EFI_SUCCESS One of required protocol is found. > + @retval Others Faile to stop the services on > network interface. > +**/ > +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 = 0; Index < (sizeof (gRequiredProtocol) / sizeof > (REDFISH_DISCOVER_REQUIRED_PROTOCOL)); Index ++) { > + Status = gBS->HandleProtocol ( > + ControllerHandle, > + gRequiredProtocol [Index].RequiredProtocolGuid, > + (VOID **)&Interface > + ); > + if (!EFI_ERROR (Status)) { > + if (gRequiredProtocol [Index].ProtocolType != ProtocolTypeRestEx) { > + if (IsListEmpty (&mEfiRedfishDiscoverNetworkInterface)) { > + return EFI_NOT_FOUND; > + } > + OldTpl = gBS->RaiseTPL > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL); > + ThisNetworkInterface = > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode > (&mEfiRedfishDiscoverNetworkInterface); > + while (TRUE) { > + if > (ThisNetworkInterface->NetworkInterfaceProtocolInfo.ProtocolControllerHan > dle == ControllerHandle) { > + > + Status = CloseProtocolService ( // Close protocol and destroy > service. > + ThisBindingProtocol, > + ControllerHandle, > + &gRequiredProtocol [Index], > + > ThisNetworkInterface->OpenDriverAgentHandle, > + > ThisNetworkInterface->OpenDriverControllerHandle > + ); > + if (!EFI_ERROR (Status)) { > + Status = DestroyRedfishNetwrokInterface > (ThisNetworkInterface); > + } > + gBS->RestoreTPL (OldTpl); > + // Reinstall Redfish Discover protocol to notify network > + // interface change. > + > + Status = gBS->ReinstallProtocolInterface ( > + EfiRedfishDiscoverProtocolHandle, > + &gEfiRedfishDiscoverProtocolGuid, > + (VOID *)&mRedfishDiscover, > + (VOID *)&mRedfishDiscover > + ); > + if (EFI_ERROR (Status)) { > + DEBUG((DEBUG_ERROR, "%a: Reinstall > gEfiRedfishDiscoverProtocolGuid fail.", __FUNCTION__)); > + } > + return Status; > + } > + if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, > &ThisNetworkInterface->Entry)) { > + break; > + } > + ThisNetworkInterface = > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL > *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, > &ThisNetworkInterface->Entry); > + }; > + gBS->RestoreTPL (OldTpl); > + } else { > + if (IsListEmpty (&mEfiRedfishDiscoverRestExInstance)) { > + return EFI_NOT_FOUND; > + } > + OldTpl = gBS->RaiseTPL > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL); > + RestExInstance = > (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL *)GetFirstNode > (&mEfiRedfishDiscoverRestExInstance); > + while (TRUE) { > + if (RestExInstance->RestExChildHandle == ControllerHandle) { > + Status = 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, > &RestExInstance->Entry)) { > + break; > + } > + RestExInstance = > (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL > *)GetNextNode(&mEfiRedfishDiscoverRestExInstance, > &RestExInstance->Entry); > + }; > + gBS->RestoreTPL (OldTpl); > + } > + } > + } > + return EFI_NOT_FOUND; > +} > +/** > + Tests to see if this driver supports a given controller. If a child device is > provided, > + it further tests to see if this driver supports creating a handle for the > specified child device. > + > + This function checks to see if the driver specified by This supports the > device specified by > + ControllerHandle. Drivers will typically use the device path attached to > + ControllerHandle and/or the services from the bus I/O abstraction > attached to > + ControllerHandle to determine if the driver supports ControllerHandle. > This function > + may be called many times during platform initialization. In order to reduce > boot times, the tests > + performed by this function must be very small, and take as little time as > possible to execute. This > + function must not change the state of any hardware devices, and this > function must be aware that the > + device specified by ControllerHandle may already be managed by the > same driver or a > + different driver. This function must match its calls to AllocatePages() with > FreePages(), > + AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol(). > + Because ControllerHandle may have been previously started by the same > driver, if a protocol is > + already in the opened state, then it must not be closed with > CloseProtocol(). This is required > + to guarantee the state of ControllerHandle is not modified by this > function. > + > + @param[in] This A pointer to the > EFI_DRIVER_BINDING_PROTOCOL instance. > + @param[in] ControllerHandle The handle of the controller to test. > This handle > + must support a protocol > interface that supplies > + an I/O abstraction to the driver. > + @param[in] RemainingDevicePath A pointer to the remaining portion > of a device path. This > + parameter is ignored by device > drivers, and is optional for bus > + drivers. For bus drivers, if this > parameter is not NULL, then > + the bus driver must determine if > the bus controller specified > + by ControllerHandle and the > child controller specified > + by RemainingDevicePath are > both supported by this > + bus driver. > + > + @retval EFI_SUCCESS The device specified by > ControllerHandle and > + RemainingDevicePath is > supported by the driver specified by This. > + @retval EFI_ALREADY_STARTED The device specified by > ControllerHandle and > + RemainingDevicePath is already > being managed by the driver > + specified by This. > + @retval EFI_ACCESS_DENIED The device specified by > ControllerHandle and > + RemainingDevicePath is already > being managed by a different > + driver or an application that > requires exclusive access. > + Currently not implemented. > + @retval EFI_UNSUPPORTED The device specified by > ControllerHandle and > + RemainingDevicePath is not > supported by the driver specified by This. > +**/ > +EFI_STATUS > +EFIAPI > +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 > behavior will not be deterministic. > + 1. ControllerHandle must be a valid EFI_HANDLE. > + 2. If RemainingDevicePath is not NULL, then it must be a pointer to a > naturally aligned > + EFI_DEVICE_PATH_PROTOCOL. > + 3. Prior to calling Start(), the Supported() function for the driver specified > by This must > + have been called with the same calling parameters, and Supported() > must have returned EFI_SUCCESS. > + > + @param[in] This A pointer to the > EFI_DRIVER_BINDING_PROTOCOL instance. > + @param[in] ControllerHandle The handle of the controller to start. > This handle > + must support a protocol > interface that supplies > + an I/O abstraction to the driver. > + @param[in] RemainingDevicePath A pointer to the remaining portion > of a device path. This > + parameter is ignored by device > drivers, and is optional for bus > + drivers. For a bus driver, if this > parameter is NULL, then handles > + for all the children of Controller > are created by this driver. > + If this parameter is not NULL > and the first Device Path Node is > + not the End of Device Path Node, > then only the handle for the > + child device specified by the first > Device Path Node of > + RemainingDevicePath is created > by this driver. > + If the first Device Path Node of > RemainingDevicePath is > + the End of Device Path Node, no > child handle is created by this > + driver. > + > + @retval EFI_SUCCESS The device was started. > + @retval EFI_DEVICE_ERROR The device could not be started > due to a device error.Currently not implemented. > + @retval EFI_OUT_OF_RESOURCES The request could not be > completed due to a lack of resources. > + @retval Others The driver failded to start the > device. > + > +**/ > +EFI_STATUS > +EFIAPI > +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 locations, > + but the following calling restrictions must be followed, or the system > behavior will not be deterministic. > + 1. ControllerHandle must be a valid EFI_HANDLE that was used on a > previous call to this > + same driver's Start() function. > + 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a > valid > + EFI_HANDLE. In addition, all of these handles must have been created > in this driver's > + Start() function, and the Start() function must have called > OpenProtocol() on > + ControllerHandle with an Attribute of > EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. > + > + @param[in] This A pointer to the > EFI_DRIVER_BINDING_PROTOCOL instance. > + @param[in] ControllerHandle A handle to the device being stopped. > The handle must > + support a bus specific I/O protocol > for the driver > + to use to stop the device. > + @param[in] NumberOfChildren The number of child device handles in > ChildHandleBuffer. > + @param[in] ChildHandleBuffer An array of child handles to be freed. > May be NULL > + if NumberOfChildren is 0. > + > + @retval EFI_SUCCESS The device was stopped. > + @retval EFI_DEVICE_ERROR The device could not be stopped due > to a device error. > + > +**/ > +EFI_STATUS > +EFIAPI > +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 = { > + 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 = EFI_SUCCESS; > + InitializeListHead (&mRedfishDiscoverList); > + InitializeListHead (&mRedfishInstanceList); > + InitializeListHead (&mEfiRedfishDiscoverNetworkInterface); > + InitializeListHead (&mEfiRedfishDiscoverRestExInstance); > + // > + // Install binding protoocl to obtain UDP and REST EX protocol. > + // > + Status = 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 the > 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 = EFI_SUCCESS; > + // Destroy all network interfaces found by EFI Redfish Discover driver and > + // stop services created for Redfish Discover. > + > + while (!IsListEmpty (&mEfiRedfishDiscoverNetworkInterface)) { > + ThisNetworkInterface = > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode > (&mEfiRedfishDiscoverNetworkInterface); > + StopServiceOnNetworkInterface (&gRedfishDiscoverDriverBinding, > ThisNetworkInterface->NetworkInterfaceProtocolInfo.ProtocolControllerHan > dle); > + }; > + // Disconnect EFI Redfish discover driver controller to notify the > + // clinet which uses .EFI Redfish discover protocol. > + > + if (EfiRedfishDiscoverProtocolHandle != NULL) { > + // > + // Notify user EFI_REDFISH_DISCOVER_PROTOCOL is unloaded. > + // > + gBS->DisconnectController (EfiRedfishDiscoverProtocolHandle, NULL, > NULL); > + Status = gBS->UninstallProtocolInterface( > + EfiRedfishDiscoverProtocolHandle, > + &gEfiRedfishDiscoverProtocolGuid, > + (VOID *)&mRedfishDiscover > + ); > + } > + return Status; > +} > diff --git a/RedfishPkg/RedfishDiscoverDxe/RedfishSmbiosHostInterface.c > b/RedfishPkg/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<BR> > + > + 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 == NULL) || (ProtocolData == NULL)) { > + return EFI_INVALID_PARAMETER; > + } > + > + SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; > + Status = Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, > NULL); > + while (!EFI_ERROR (Status) && SmbiosHandle != > SMBIOS_HANDLE_PI_RESERVED) { > + if (Record->Type == > SMBIOS_TYPE_MANAGEMENT_CONTROLLER_HOST_INTERFACE) { > + // > + // Check Interface Type, should be Network Host Interface = 40h > + // > + mType42Record = (SMBIOS_TABLE_TYPE42 *) Record; > + if (mType42Record->InterfaceType == > MCHostInterfaceTypeNetworkHostInterface) { > + ASSERT (Record->Length >= 9); > + Offset = 5; > + RecordTmp = (UINT8 *) Record + Offset; > + // > + // Get interface specific data length. > + // > + SpecificDataLen = *RecordTmp; > + Offset += 1; > + RecordTmp = (UINT8 *) Record + Offset; > + > + // > + // Check Device Type, only PCI/PCIe Network Interface v2 is > supported now. > + // > + if (*RecordTmp == > REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE_V2) { > + ASSERT (SpecificDataLen == sizeof > (PCI_OR_PCIE_INTERFACE_DEVICE_DESCRIPTOR_V2) + 1); > + *DeviceDescriptor = (REDFISH_INTERFACE_DATA *)RecordTmp; > + Offset = Offset + SpecificDataLen; > + RecordTmp = (UINT8 *) Record + Offset; > + // > + // Check Protocol count. if > 1, only use the first protocol. > + // > + ASSERT (*RecordTmp == 1); > + Offset += 1; > + RecordTmp = (UINT8 *) Record + Offset; > + // > + // Check protocol identifier. > + // > + if (*RecordTmp == MCHostInterfaceProtocolTypeRedfishOverIP) > { > + Offset += 1; > + RecordTmp = (UINT8 *) Record + Offset; > + ProtocolLength = *RecordTmp; > + > + Offset += 1; > + RecordTmp = (UINT8 *) Record + Offset; > + > + // > + // This SMBIOS record is invalid, if the length of protocol > specific data for > + // Redfish Over IP protocol is wrong. > + // > + if ((*(RecordTmp + 90) + sizeof > (REDFISH_OVER_IP_PROTOCOL_DATA) - 1) != ProtocolLength) { > + return EFI_SECURITY_VIOLATION; > + } > + > + Offset += ProtocolLength; > + // > + // This SMBIOS record is invalid, if the length is smaller than > the offset. > + // > + if (Offset > mType42Record->Hdr.Length) { > + return EFI_SECURITY_VIOLATION; > + } > + *ProtocolData = (REDFISH_OVER_IP_PROTOCOL_DATA > *)RecordTmp; > + return EFI_SUCCESS; > + } > + } > + } > + } > + Status = Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, > NULL); > + } > + > + *ProtocolData = NULL; > + return EFI_NOT_FOUND; > +} > -- > 2.17.1 > > > > > -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#73762): https://edk2.groups.io/g/devel/message/73762 Mute This Topic: https://groups.io/mt/81909222/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=-=-=-=-=-=-=-=-=-=-=-
BZ was created for this. https://bugzilla.tianocore.org/show_bug.cgi?id=2906 I will update the commit message with the feedback from reviewer if any. Thanks > -----Original Message----- > From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of > gaoliming > Sent: Wednesday, April 7, 2021 1:20 PM > To: devel@edk2.groups.io; Chang, Abner (HPS SW/FW Technologist) > <abner.chang@hpe.com> > Cc: Wang, Nickle (HPS SW) <nickle.wang@hpe.com>; 'Jiaxin Wu' > <jiaxin.wu@intel.com>; 'Siyuan Fu' <siyuan.fu@intel.com>; 'Fan Wang' > <fan.wang@intel.com>; 'Jiewen Yao' <jiewen.yao@intel.com> > Subject: 回复: [edk2-devel] [PATCH] RedfishPkg/RedfishDiscoverDxe: EFI > Redfish Discover Protocol > > Abner: > This is new feature. Can you submit one BZ for it? > > Thanks > Liming > > -----邮件原件----- > > 发件人: devel@edk2.groups.io <devel@edk2.groups.io> 代表 Abner > Chang > > 发送时间: 2021年3月26日 12:54 > > 收件人: devel@edk2.groups.io > > 抄送: Nickle Wang <nickle.wang@hpe.com>; Jiaxin Wu > > <jiaxin.wu@intel.com>; Siyuan Fu <siyuan.fu@intel.com>; Fan Wang > > <fan.wang@intel.com>; Jiewen Yao <jiewen.yao@intel.com> > > 主题: [edk2-devel] [PATCH] RedfishPkg/RedfishDiscoverDxe: EFI Redfish > > Discover Protocol > > > > EDK2 EFI Redfish Discover Protocol implementation. Refer to UEFI spec 2.9 > > section 31.1. > > > > Signed-off-by: Abner Chang <abner.chang@hpe.com> > > Cc: Nickle Wang <nickle.wang@hpe.com> > > Cc: Jiaxin Wu <jiaxin.wu@intel.com> > > Cc: Siyuan Fu <siyuan.fu@intel.com> > > Cc: Fan Wang <fan.wang@intel.com> > > Cc: Jiewen Yao <jiewen.yao@intel.com> > > --- > > 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/RedfishSmbiosHostInterface.c > > > > diff --git a/RedfishPkg/RedfishComponents.dsc.inc > > b/RedfishPkg/RedfishComponents.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<BR> > > +# (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR> > > # > > # 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<BR> > > +# (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR> > > # > > # 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/RedfishPkg/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<BR> > > +# > > +# SPDX-License-Identifier: BSD-2-Clause-Patent > > +# > > +## > > + > > +[Defines] > > + INF_VERSION = 0x0001001b > > + BASE_NAME = RedfishDiscoverDxe > > + FILE_GUID = > > 28A76FE5-43D7-48A3-9714-C1B7BDD6DFB6 > > + MODULE_TYPE = UEFI_DRIVER > > + VERSION_STRING = 1.0 > > + ENTRY_POINT = RedfishDiscoverEntryPoint > > + UNLOAD_IMAGE = 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 > ## > > CONSUMES > > + > > diff --git a/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverInternal.h > > b/RedfishPkg/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<BR> > > + > > + SPDX-License-Identifier: BSD-2-Clause-Patent > > + > > +**/ > > + > > +#ifndef EFI_REDFISH_DISCOVER_INTERNAL_H_ > > +#define EFI_REDFISH_DISCOVER_INTERNAL_H_ > > + > > +#include <Uefi.h> > > + > > +#include <Protocol/ComponentName.h> > > +#include <Protocol/ComponentName2.h> > > +#include <Protocol/DriverBinding.h> > > +#include <Protocol/RedfishDiscover.h> > > +#include <Protocol/Smbios.h> > > +#include <Protocol/Tcp4.h> > > +#include <Protocol/Tcp6.h> > > + > > +#include <Library/BaseLib.h> > > +#include <Library/BaseMemoryLib.h> > > +#include <Library/DebugLib.h> > > +#include <Library/MemoryAllocationLib.h> > > +#include <Library/NetLib.h> > > +#include <Library/PrintLib.h> > > +#include <Library/RestExLib.h> > > +#include <Library/UefiLib.h> > > +#include <Library/UefiBootServicesTableLib.h> > > +#include <Library/UefiDriverEntryPoint.h> > > + > > +#include <IndustryStandard/RedfishHostInterface.h> > > + > > +#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 = 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 > > network protocol handle. > > + EFI_HANDLE ProtocolControllerHandle; ///< The controller handle on > > network protocol. > > + VOID *NetworkProtocolInterface; ///< The protocol interface of > > network 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 network protocol. > > + EFI_HANDLE OpenDriverControllerHandle; ///< The controller > > handle to open network protocol. > > + UINTN HwAddressSize; ///< The size of > > network interface hardware address. > > + EFI_MAC_ADDRESS MacAddress; ///< MAC > > address of network interface. > > + CHAR16 *StrMacAddr; ///< String to > > MAC address of network interface. > > + BOOLEAN GotSubnetInfo; ///< Indicates sub > > net information is retrieved. > > + EFI_IP_ADDRESS SubnetAddr; ///< Subnet ID. > > + EFI_IP_ADDRESS SubnetMask; ///< Subnet mask > > (IPv4 only) > > + UINT8 SubnetPrefixLength; ///< Subnet prefix. > > + UINT16 VlanId; ///< VLAN ID > > + UINT32 SubnetAddrInfoIPv6Number; ///< IPv6 address > > info number. > > + EFI_IP6_ADDRESS_INFO *SubnetAddrInfoIPv6; ///< IPv6 address > > info. > > + // > > + // Network interface protocol and REST EX infor. > > + // > > + UINT32 NetworkProtocolType; ///< Network > > protocol type. Refer to > > + ///< > > NETWORK_INTERFACE_PROTOCOL_TYPE. > > + REDFISH_DISCOVER_NETWORK_INTERFACE_PROTOCOL > > NetworkInterfaceProtocolInfo; ///< Network interface protocol > information. > > + EFI_HANDLE RestExHandle; ///< REST EX > > handle associated 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 handle to open network protocol. > > + EFI_HANDLE RestExChildHandle; ///< The child > > handle created throught REST EX Service Protocol. > > + EFI_HANDLE RestExControllerHandle; ///< The > > controller handle which provide REST EX protocol. > > + EFI_REST_EX_PROTOCOL *RestExProtocolInterface; ///< Pointer to > > EFI_REST_EX_PROTOCOL. > > + UINT32 RestExId; ///< The > > identifier installed 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 protocol type, > > + ///< > > Refer to NETWORK_INTERFACE_PROTOCOL_TYPE. > > + CHAR16 *ProtocolName; ///< > > Protocol name. > > + EFI_GUID *RequiredProtocolGuid; ///< > > Network protocol interface GUID. > > + EFI_GUID *RequiredServiceBindingProtocolGuid; ///< Network > > protocol service GUID. > > + EFI_GUID *DiscoveredProtocolGuid; ///< > > Protocol interface GUID use to install identifier. > > + EFI_REDFISH_DISCOVER_GET_SUBNET_INFO GetSubnetInfo; ///< > > Function of getting 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 EFI_REDFISH_DISCOVERED_INSTANCE. > > +} EFI_REDFISH_DISCOVERED_INTERNAL_LIST; > > + > > +// > > +// Internal structure of Redfish discover instance. > > +// > > +typedef struct { > > + LIST_ENTRY Entry; ///< > > Link list entry. > > + EFI_HANDLE Owner; ///< > > The owner owns this Redfish service discovery. > > + ///< > > It's the EFI image handle of driver uses > > + ///< > > EFI Redfish Discover Protocol. > > + EFI_REDFISH_DISCOVER_FLAG DiscoverFlags; ///< > > EFI_REDFISH_DISCOVER_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 whether to validate Redfish Host interface. > > + EFI_IP_ADDRESS TargetIpAddress; ///< > > Target IP address 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_INSTANCE. > > + @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 > > connection. > > + @retval EFI_SUCCESS Redfish service is added to list > > successfully. > > + > > +**/ > > +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/RedfishDiscoverDxe/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_PROTOCOL protocol. > > + for EFI Refish Discover Protocol > > + > > + (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR> > > + > > + 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 > > Driver. > > + > > + @param[in] This A pointer to the > > EFI_COMPONENT_NAME_PROTOCOL instance. > > + @param[in] Language A pointer to a three-character ISO 639-2 > > language identifier. > > + This is the language of the driver name that > > that the caller > > + is requesting, and it must match one of the > > languages specified > > + in SupportedLanguages. The number of > > languages supported by a > > + driver is up to the driver writer. > > + @param[out] DriverName A pointer to the Unicode string to return. > > This Unicode string > > + is the name of the driver specified by This in > > the language > > + specified by Language. > > + > > + @retval EFI_SUCCESS The Unicode string for the Driver > > specified by This > > + and the language specified by > > Language was returned > > + in DriverName. > > + @retval EFI_INVALID_PARAMETER Language is NULL. > > + @retval EFI_INVALID_PARAMETER DriverName is NULL. > > + @retval EFI_UNSUPPORTED The driver specified by This does not > > support the > > + language specified by Language. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +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 > controller > > + that is being managed by an EFI Driver. > > + > > + @param[in] This A pointer to the > > EFI_COMPONENT_NAME_PROTOCOL instance. > > + @param[in] ControllerHandle The handle of a controller that the driver > > specified by > > + This is managing. This handle > > specifies the controller > > + whose name is to be returned. > > + @param[in] ChildHandle The handle of the child controller to > > retrieve the name > > + of. This is an optional parameter > > that may be NULL. It > > + will be NULL for device drivers. It > > will also be NULL > > + for a bus drivers that wish to retrieve > > the name of the > > + bus controller. It will not be NULL > > for a bus driver > > + that wishes to retrieve the name of a > > child controller. > > + @param[in] Language A pointer to a three character ISO > > 639-2 language > > + identifier. This is the language of the > > controller name > > + that the caller is requesting, and it > > must match one > > + of the languages specified in > > SupportedLanguages. The > > + number of languages supported by a > > driver is up to the > > + driver writer. > > + @param[out] ControllerName A pointer to the Unicode string to > > return. This Unicode > > + string is the name of the controller > > specified by > > + ControllerHandle and ChildHandle in > > the language specified > > + by Language, from the point of view > > of the driver specified > > + by This. > > + > > + @retval EFI_SUCCESS The Unicode string for the > > user-readable name in the > > + language specified by Language for > > the driver > > + specified by This was returned in > > DriverName. > > + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. > > + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a > > valid EFI_HANDLE. > > + @retval EFI_INVALID_PARAMETER Language is NULL. > > + @retval EFI_INVALID_PARAMETER ControllerName is NULL. > > + @retval EFI_UNSUPPORTED The driver specified by This is not > > currently managing > > + the controller specified by > > ControllerHandle and > > + ChildHandle. > > + @retval EFI_UNSUPPORTED The driver specified by This does not > > support the > > + language specified by Language. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +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 > > = { > > + RedfishDiscoverComponentNameGetDriverName, > > + RedfishDiscoverComponentNameGetControllerName, > > + "eng" > > +}; > > + > > +/// > > +/// Component Name 2 Protocol instance > > +/// > > +GLOBAL_REMOVE_IF_UNREFERENCED > > +EFI_COMPONENT_NAME2_PROTOCOL > > gRedfishDiscoverComponentName2 = { > > + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) > > RedfishDiscoverComponentNameGetDriverName, > > + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) > > RedfishDiscoverComponentNameGetControllerName, > > + "en" > > +}; > > + > > +/// > > +/// Table of driver names > > +/// > > +GLOBAL_REMOVE_IF_UNREFERENCED > > +EFI_UNICODE_STRING_TABLE mRedfishDiscoverDriverNameTable[] = { > > + { "eng;en", (CHAR16 *)L"Redfish Discover UEFI Driver" }, > > + { NULL, NULL } > > +}; > > + > > +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE > > *gRedfishDiscoverControllerNameTable = NULL; > > + > > +/** > > + Retrieves a Unicode string that is the user-readable name of the EFI > > Driver. > > + > > + @param[in] This A pointer to the > > EFI_COMPONENT_NAME_PROTOCOL instance. > > + @param[in] Language A pointer to a three-character ISO 639-2 > > language identifier. > > + This is the language of the driver name that > > that the caller > > + is requesting, and it must match one of the > > languages specified > > + in SupportedLanguages. The number of > > languages supported by a > > + driver is up to the driver writer. > > + @param[out] DriverName A pointer to the Unicode string to return. > > This Unicode string > > + is the name of the driver specified by This in > > the language > > + specified by Language. > > + > > + @retval EFI_SUCCESS The Unicode string for the Driver > > specified by This > > + and the language specified by > > Language was returned > > + in DriverName. > > + @retval EFI_INVALID_PARAMETER Language is NULL. > > + @retval EFI_INVALID_PARAMETER DriverName is NULL. > > + @retval EFI_UNSUPPORTED The driver specified by This does not > > support the > > + language specified by Language. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +RedfishDiscoverComponentNameGetDriverName ( > > + IN EFI_COMPONENT_NAME_PROTOCOL *This, > > + IN CHAR8 *Language, > > + OUT CHAR16 **DriverName > > + ) > > +{ > > + return LookupUnicodeString2 ( > > + Language, > > + This->SupportedLanguages, > > + mRedfishDiscoverDriverNameTable, > > + DriverName, > > + (BOOLEAN)(This == &gRedfishDiscoverComponentName) > > + ); > > +} > > + > > +/** > > + Retrieves a Unicode string that is the user readable name of the > controller > > + that is being managed by an EFI Driver. > > + > > + @param[in] This A pointer to the > > EFI_COMPONENT_NAME_PROTOCOL instance. > > + @param[in] ControllerHandle The handle of a controller that the driver > > specified by > > + This is managing. This handle > > specifies the controller > > + whose name is to be returned. > > + @param[in] ChildHandle The handle of the child controller to > > retrieve the name > > + of. This is an optional parameter > > that may be NULL. It > > + will be NULL for device drivers. It > > will also be NULL > > + for a bus drivers that wish to retrieve > > the name of the > > + bus controller. It will not be NULL > > for a bus driver > > + that wishes to retrieve the name of a > > child controller. > > + @param[in] Language A pointer to a three character ISO > > 639-2 language > > + identifier. This is the language of the > > controller name > > + that the caller is requesting, and it > > must match one > > + of the languages specified in > > SupportedLanguages. The > > + number of languages supported by a > > driver is up to the > > + driver writer. > > + @param[out] ControllerName A pointer to the Unicode string to > > return. This Unicode > > + string is the name of the controller > > specified by > > + ControllerHandle and ChildHandle in > > the language specified > > + by Language, from the point of view > > of the driver specified > > + by This. > > + > > + @retval EFI_SUCCESS The Unicode string for the > > user-readable name in the > > + language specified by Language for > > the driver > > + specified by This was returned in > > DriverName. > > + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. > > + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a > > valid EFI_HANDLE. > > + @retval EFI_INVALID_PARAMETER Language is NULL. > > + @retval EFI_INVALID_PARAMETER ControllerName is NULL. > > + @retval EFI_UNSUPPORTED The driver specified by This is not > > currently managing > > + the controller specified by > > ControllerHandle and > > + ChildHandle. > > + @retval EFI_UNSUPPORTED The driver specified by This does not > > support the > > + language specified by Language. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +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/RedfishPkg/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<BR> > > + > > + SPDX-License-Identifier: BSD-2-Clause-Patent > > + > > +**/ > > + > > +#include "RedfishDiscoverInternal.h" > > + > > +LIST_ENTRY mRedfishDiscoverList; > > +LIST_ENTRY mRedfishInstanceList; > > +EFI_SMBIOS_PROTOCOL *mSmbios = NULL; > > + > > +UINTN mNumNetworkInterface = 0; > > +UINTN mNumRestExInstance = 0; > > +LIST_ENTRY mEfiRedfishDiscoverNetworkInterface; > > +LIST_ENTRY mEfiRedfishDiscoverRestExInstance; > > + > > +EFI_GUID mRedfishDiscoverTcp4InstanceGuid = > > EFI_REDFISH_DISCOVER_TCP4_INSTANCE_GUID; > > +EFI_GUID mRedfishDiscoverTcp6InstanceGuid = > > EFI_REDFISH_DISCOVER_TCP6_INSTANCE_GUID; > > +EFI_GUID mRedfishDiscoverRestExInstanceGuid = > > EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_GUID; > > + > > +EFI_HANDLE EfiRedfishDiscoverProtocolHandle = 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[] = { > > + { > > + 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 this owner. > > + > > +**/ > > +EFI_STATUS > > +CreateRestExInstance ( > > + IN EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *Instance, > > + IN EFI_REDFISH_DISCOVERED_TOKEN *Token > > + ) > > +{ > > + EFI_STATUS Status; > > + > > + Status = RestExLibCreateChild ( > > + Instance->Owner, > > + FixedPcdGetBool (PcdRedfishDiscoverAccessModeInBand)? > > EfiRestExServiceInBandAccess: EfiRestExServiceOutOfBandAccess, > > + EfiRestExConfigHttp, > > + EfiRestExServiceRedfish, > > + > > &Token->DiscoverList.RedfishInstances- > >Information.RedfishRestExHandle > > + ); > > + return Status; > > +} > > + > > +/** > > + This function gets EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE > > + by known owner handle. > > + > > + @param[in] ImageHandle Image handle owns > > EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE. > > + @param[in] TargetNetworkInterface Target network interface used > > by this 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 this owner. > > + > > +**/ > > +EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE * > > +GetInstanceByOwner ( > > + IN EFI_HANDLE ImageHandle, > > + IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL > > *TargetNetworkInterface, > > + IN EFI_REDFISH_DISCOVER_FLAG DiscoverFlags > > + ) > > +{ > > + EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *ThisInstance; > > + > > + if (IsListEmpty (&mRedfishDiscoverList)) { > > + return NULL; > > + } > > + ThisInstance = > > + (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *)GetFirstNode > > (&mRedfishDiscoverList); > > + while (TRUE) { > > + if ((ThisInstance->Owner == ImageHandle) && > > + (ThisInstance->DiscoverFlags == DiscoverFlags) && > > + (ThisInstance->NetworkInterface == TargetNetworkInterface)) { > > + return ThisInstance; > > + } > > + if (IsNodeAtEnd (&mRedfishDiscoverList, &ThisInstance->Entry)) { > > + break; > > + } > > + ThisInstance = > > + (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *)GetNextNode > > (&mRedfishDiscoverList, &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 == NULL) { > > + return EFI_INVALID_PARAMETER; > > + } > > + Tcp4 = (EFI_TCP4_PROTOCOL > > *)Instance->NetworkInterfaceProtocolInfo.NetworkProtocolInterface; > > + > > + 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 = TRUE; > > + Tcp4CfgData.AccessPoint.RemoteAddress.Addr [0] = 127; > > + Tcp4CfgData.AccessPoint.RemoteAddress.Addr [1] = 0; > > + Tcp4CfgData.AccessPoint.RemoteAddress.Addr [2] = 0; > > + Tcp4CfgData.AccessPoint.RemoteAddress.Addr [3] = 1; > > + Tcp4CfgData.AccessPoint.RemotePort = 80; > > + Tcp4CfgData.AccessPoint.ActiveFlag = TRUE; > > + > > + Tcp4CfgData.ControlOption = &Tcp4Option; > > + Tcp4Option.ReceiveBufferSize = 65535; > > + Tcp4Option.SendBufferSize = 65535; > > + Tcp4Option.MaxSynBackLog = 5; > > + Tcp4Option.ConnectionTimeout = 60; > > + Tcp4Option.DataRetries = 12; > > + Tcp4Option.FinTimeout = 2; > > + Tcp4Option.KeepAliveProbes = 6; > > + Tcp4Option.KeepAliveTime = 7200; > > + Tcp4Option.KeepAliveInterval = 30; > > + Tcp4Option.EnableNagle = TRUE; > > + Status = Tcp4->Configure (Tcp4, &Tcp4CfgData); > > + if (EFI_ERROR (Status)) { > > + DEBUG ((DEBUG_ERROR, "%a: Can't get subnet information\n", > > __FUNCTION__)); > > + return Status; > > + } > > + Status = Tcp4->GetModeData (Tcp4, NULL, NULL, &IpModedata, NULL, > > NULL); > > + if (EFI_ERROR (Status)) { > > + DEBUG ((DEBUG_ERROR, "%a: Can't get IP mode data information\n", > > __FUNCTION__)); > > + return Status; > > + } > > + IP4_COPY_ADDRESS (&Instance->SubnetMask, > > &IpModedata.ConfigData.SubnetMask); > > + Instance->SubnetAddr.v4.Addr [0] = > > IpModedata.ConfigData.StationAddress.Addr [0] & > > Instance->SubnetMask.v4.Addr [0]; > > + Instance->SubnetAddr.v4.Addr [1] = > > IpModedata.ConfigData.StationAddress.Addr [1] & > > Instance->SubnetMask.v4.Addr [1]; > > + Instance->SubnetAddr.v4.Addr [2] = > > IpModedata.ConfigData.StationAddress.Addr [2] & > > Instance->SubnetMask.v4.Addr [2]; > > + Instance->SubnetAddr.v4.Addr [3] = > > IpModedata.ConfigData.StationAddress.Addr [3] & > > Instance->SubnetMask.v4.Addr [3]; > > + // > > + // Calculate the subnet mask prefix. > > + // > > + GotPrefixLength = FALSE; > > + PrefixLength = 0; > > + SubnetMaskIndex = 0; > > + while (GotPrefixLength == FALSE && SubnetMaskIndex < 4) { > > + BitMask = 0x80; > > + while (BitMask != 0) { > > + if ((Instance->SubnetMask.v4.Addr [SubnetMaskIndex] & BitMask) != > > 0) { > > + PrefixLength ++; > > + } else { > > + GotPrefixLength = TRUE; > > + break; > > + } > > + BitMask = BitMask >> 1; > > + }; > > + SubnetMaskIndex ++; > > + }; > > + Instance->SubnetPrefixLength = 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 == NULL) { > > + return EFI_INVALID_PARAMETER; > > + } > > + Tcp6 = (EFI_TCP6_PROTOCOL > > *)Instance->NetworkInterfaceProtocolInfo.NetworkProtocolInterface; > > + > > + Status = 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 == 0) { > > + DEBUG ((DEBUG_INFO, "%a: No IPv6 address configured.\n")); > > + } > > + if (Instance->SubnetAddrInfoIPv6 != NULL) { > > + FreePool (Instance->SubnetAddrInfoIPv6); > > + } > > + Instance->SubnetAddrInfoIPv6 = AllocateZeroPool > > (IpModedata.AddressCount * sizeof (EFI_IP6_ADDRESS_INFO)); > > + if (Instance->SubnetAddrInfoIPv6 == NULL) { > > + DEBUG ((DEBUG_ERROR, "%a: Failed to allocate memory fir IPv6 > > subnet address information\n")); > > + return EFI_OUT_OF_RESOURCES; > > + } > > + Instance->SubnetAddrInfoIPv6Number = 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_INTERFACE. > > + NULL for all > > EFI_REDFISH_DISCOVER_NETWORK_INTERFACEs. > > + > > + @retval Non-NULL > > EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL is returned. > > + @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 = > > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL > *)GetFirstNode > > (&mEfiRedfishDiscoverNetworkInterface); > > + while (TRUE) { > > + if (CompareMem((VOID *)&ThisNetworkInterface->MacAddress, > > &TargetNetworkInterface->MacAddress, > > ThisNetworkInterface->HwAddressSize) == 0) { > > + return ThisNetworkInterface; > > + } > > + if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, > > &ThisNetworkInterface->Entry)) { > > + return NULL; > > + } > > + ThisNetworkInterface = > > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL > > *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, > > &ThisNetworkInterface->Entry); > > + }; > > + return NULL; > > +} > > + > > +/** > > + This function validate if target network interface is ready for > discovering > > + Redfish service. > > + > > + @param[in] TargetNetworkInterface > > EFI_REDFISH_DISCOVER_NETWORK_INTERFACE. > > + NULL for all > > EFI_REDFISH_DISCOVER_NETWORK_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) && > > TargetNetworkInterface == NULL) { > > + return EFI_UNSUPPORTED; > > + } > > + if (TargetNetworkInterface == NULL) { > > + return EFI_SUCCESS; // Return EFI_SUCCESS if no network interface is > > specified. > > + } > > + > > + ThisNetworkInterface = > > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL > > *)GetFirstNode(&mEfiRedfishDiscoverNetworkInterface); > > + while (TRUE) { > > + if (CompareMem((VOID *)&ThisNetworkInterface->MacAddress, > > &TargetNetworkInterface->MacAddress, > > ThisNetworkInterface->HwAddressSize) == 0) { > > + break; > > + } > > + if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, > > &ThisNetworkInterface->Entry)) { > > + return EFI_UNSUPPORTED; > > + } > > + ThisNetworkInterface = > > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL > > *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, > > &ThisNetworkInterface->Entry); > > + }; > > + if ((Flags & EFI_REDFISH_DISCOVER_SSDP) != 0) { > > + // Validate if UDP4/6 is supported on the given network interface. > > + // SSDP is not supported. > > + > > + return EFI_SUCCESS; > > + } > > + if > > (ThisNetworkInterface- > >NetworkInterfaceProtocolInfo.ProtocolControllerHan > > dle == NULL) { > > + return EFI_UNSUPPORTED; // The required protocol on this network > > interface 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 = 1; > > + ThisNetworkInterface = > > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL > *)GetFirstNode > > (&mEfiRedfishDiscoverNetworkInterface); > > + while (TRUE) { > > + if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, > > &ThisNetworkInterface->Entry)) { > > + break; > > + } > > + ThisNetworkInterface = > > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL > > *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, > > &ThisNetworkInterface->Entry); > > + Num ++; > > + }; > > + return Num; > > +} > > + > > +/** > > + This function checks the IP version supported on this > > + netwoek interface. > > + > > + @param[in] ThisNetworkInterface > > EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL > > + > > + @retval TRUE Is IPv6, otherwise IPv4. > > + > > +**/ > > +BOOLEAN > > +CheckIsIpVersion6 ( > > + IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL > > *ThisNetworkInterface > > +) > > +{ > > + if (ThisNetworkInterface->NetworkProtocolType == 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 > > SMBIOS 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 = NULL; > > + DeviceDescriptor = NULL; > > + > > + if (mSmbios == NULL) { > > + Status = gBS->LocateProtocol(&gEfiSmbiosProtocolGuid, NULL, (VOID > > **)&mSmbios); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + } > > + Status = RedfishGetHostInterfaceProtocolData (mSmbios, > > &DeviceDescriptor, &Data); // Search for SMBIOS type 42h > > + if (!EFI_ERROR (Status) && Data != NULL && DeviceDescriptor != NULL) { > > + // > > + // Chceck if we can reach out Redfish service using this network > > interface. > > + // Check with MAC address using Device Descroptor Data Device Type > > 04 and Type 05. > > + // Those two types of Redfish host interface device has MAC > > information. > > + // > > + if (DeviceDescriptor->DeviceType == > > REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE_V2) { > > + MacCompareStstus = > > CompareMem(&Instance->NetworkInterface->MacAddress, > > &DeviceDescriptor->DeviceDescriptor.PciPcieDeviceV2.MacAddress, 6); > > + } else if (DeviceDescriptor->DeviceType == > > REDFISH_HOST_INTERFACE_DEVICE_TYPE_USB_V2){ > > + MacCompareStstus = > > CompareMem(&Instance->NetworkInterface->MacAddress, > > &DeviceDescriptor->DeviceDescriptor.UsbDeviceV2.MacAddress, 6); > > + } else { > > + return EFI_UNSUPPORTED; > > + } > > + if (MacCompareStstus != 0) { > > + return EFI_UNSUPPORTED; > > + } > > + > > + if (Data->RedfishServiceIpAddressFormat == 1) { > > + IP4_COPY_ADDRESS ((VOID *)&Instance->TargetIpAddress.v4, (VOID > > *)Data->RedfishServiceIpAddress); > > + } else { > > + IP6_COPY_ADDRESS ((VOID *)&Instance->TargetIpAddress.v6, (VOID > > *)Data->RedfishServiceIpAddress); > > + } > > + > > + if (Instance->HostIntfValidation) { > > + DEBUG ((DEBUG_ERROR,"%a:Send UPnP unicast SSDP to validate > > this Redfish Host Interface is not supported.\n", __FUNCTION__)); > > + Status = EFI_UNSUPPORTED; > > + } else { > > + // > > + // Add this istance to list without detial information of Redfish > > + // service. > > + // > > + IsHttps = FALSE; > > + if (Data->RedfishServiceIpPort == 443) { > > + IsHttps = TRUE; > > + } > > + StrSize = sizeof(UuidStr); > > + AsciiSPrint(UuidStr, StrSize, "%g", &Data->ServiceUuid); > > + // > > + // Generate Redfish service location string. > > + // > > + if (Data->RedfishServiceIpAddressFormat == > > REDFISH_HOST_INTERFACE_HOST_IP_ADDRESS_FORMAT_IP6) { > > + NetLibIp6ToStr((IPv6_ADDRESS *)&Data->RedfishServiceIpAddress, > > Ipv6Str, sizeof (Ipv6Str)); > > + if (Data->RedfishServiceIpPort == 0 || IsHttps == TRUE) { > > + AsciiSPrintUnicodeFormat ( > > + RedfishServiceLocateStr, > > + sizeof (RedfishServiceLocateStr), > > + L"%s", > > + Ipv6Str > > + ); > > + } else { > > + AsciiSPrintUnicodeFormat( > > + RedfishServiceLocateStr, > > + sizeof (RedfishServiceLocateStr), > > + L"[%s]:%d", > > + Ipv6Str, > > + Data->RedfishServiceIpPort > > + ); > > + } > > + } else { > > + if (Data->RedfishServiceIpPort == 0 || IsHttps == 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 = 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_INSTANCE. > > + @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 > > connection. > > + @retval EFI_SUCCESS Redfish service is added to list > > successfully. > > + > > +**/ > > +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 = TRUE; > > + InfoRefresh = FALSE; > > + Char16Uuid = NULL; > > + RestExOpened = FALSE; > > + DeleteRestEx = FALSE; > > + > > + DEBUG ((DEBUG_INFO,"%a:Add this instance to Redfish instance list.\n", > > __FUNCTION__)); > > + > > + if (Uuid != NULL) { > > + Char16Uuid = (CHAR16 *)AllocateZeroPool(AsciiStrSize((const CHAR8 > > *)Uuid) * sizeof(CHAR16)); > > + AsciiStrToUnicodeStrS ((const CHAR8 *)Uuid, Char16Uuid, > > AsciiStrSize((const CHAR8 *)Uuid) * sizeof(CHAR16)); > > + } > > + DiscoveredList = NULL; > > + DiscoveredInstance = NULL; > > + RestExHttpConfigData = NULL; > > + > > + NetworkInterface = Instance->NetworkInterface; > > + if (!IsListEmpty (&mRedfishInstanceList)) { > > + // > > + // Is this a duplicate redfish service. > > + // > > + DiscoveredList = (EFI_REDFISH_DISCOVERED_INTERNAL_LIST > > *)GetFirstNode (&mRedfishInstanceList); > > + NewFound = FALSE; > > + do { > > + if (Char16Uuid == NULL || > > DiscoveredList->Instance->Information.Uuid == NULL) { > > + // > > + // Check if this Redfish instance already found using IP > addrress. > > + // > > + if (!CheckIsIpVersion6(NetworkInterface)) { > > + if (CompareMem ((VOID *)&Instance->TargetIpAddress.v4, > > + (VOID > > *)&DiscoveredList->Instance->Information.RedfishHostIpAddress.v4, > > + sizeof (EFI_IPv4_ADDRESS) > > + ) == 0) > > + { > > + DiscoveredInstance = DiscoveredList->Instance; > > + if (DiscoveredList->Instance->Information.Uuid == NULL && > > + Char16Uuid != NULL) { > > + InfoRefresh = TRUE; > > + DiscoveredInstance = DiscoveredList->Instance; > > + DEBUG((DEBUG_INFO,"*** This Redfish Service > > information refresh ***\n")); > > + } > > + break; > > + } > > + } else { > > + if (CompareMem ((VOID *)&Instance->TargetIpAddress.v6, > > + (VOID > > *)&DiscoveredList->Instance->Information.RedfishHostIpAddress.v6, > > + sizeof (EFI_IPv6_ADDRESS) > > + ) == 0) > > + { > > + DiscoveredInstance = DiscoveredList->Instance; > > + break; > > + } > > + } > > + } else { > > + // > > + // Check if this Redfish instance already found using UUID. > > + // > > + if (StrCmp((const CHAR16 *)Char16Uuid, (const CHAR16 > > *)DiscoveredList->Instance->Information.Uuid) == 0) { > > + DiscoveredInstance = DiscoveredList->Instance; > > + break; > > + } > > + } > > + if (IsNodeAtEnd (&mRedfishInstanceList, > > &DiscoveredList->NextInstance)) { > > + NewFound = TRUE; > > + break; > > + } > > + DiscoveredList = (EFI_REDFISH_DISCOVERED_INTERNAL_LIST > > *)GetNextNode (&mRedfishInstanceList, &DiscoveredList->NextInstance); > > + } while (TRUE); > > + } > > + if (NewFound || InfoRefresh) { > > + if (!InfoRefresh) { > > + DiscoveredList = (EFI_REDFISH_DISCOVERED_INTERNAL_LIST > > *)AllocateZeroPool(sizeof(EFI_REDFISH_DISCOVERED_INTERNAL_LIST)); > > + if (DiscoveredList == NULL) { > > + return EFI_OUT_OF_RESOURCES; > > + } > > + InitializeListHead (&DiscoveredList->NextInstance); > > + DiscoveredInstance = (EFI_REDFISH_DISCOVERED_INSTANCE > > *)AllocateZeroPool(sizeof(EFI_REDFISH_DISCOVERED_INSTANCE)); > > + if (DiscoveredInstance == NULL) { > > + FreePool ((VOID *)DiscoveredList); > > + return EFI_OUT_OF_RESOURCES; > > + } > > + } > > + DEBUG ((DEBUG_INFO,"*** Redfish Service Information ***\n")); > > + > > + DiscoveredInstance->Information.UseHttps = UseHttps; > > + if (RedfishVersion != NULL) { > > + DiscoveredInstance->Information.RedfishVersion = *RedfishVersion; > > + DEBUG ((DEBUG_INFO,"Redfish service version: %d.\n", > > DiscoveredInstance->Information.RedfishVersion)); > > + } > > + if (RedfishLocation != NULL) { > > + DiscoveredInstance->Information.Location = (CHAR16 > > *)AllocatePool(AsciiStrSize((const CHAR8 *)RedfishLocation) * > > sizeof(CHAR16)); > > + AsciiStrToUnicodeStrS ((const CHAR8 *)RedfishLocation, > > DiscoveredInstance->Information.Location, AsciiStrSize((const CHAR8 > > *)RedfishLocation) * sizeof(CHAR16)); > > + DEBUG ((DEBUG_INFO,"Redfish service location: %s.\n", > > DiscoveredInstance->Information.Location)); > > + } > > + if (Uuid != NULL) { > > + DiscoveredInstance->Information.Uuid = (CHAR16 > > *)AllocatePool(AsciiStrSize((const CHAR8 *)Uuid) * sizeof(CHAR16)); > > + AsciiStrToUnicodeStrS ((const CHAR8 *)Uuid, > > DiscoveredInstance->Information.Uuid, AsciiStrSize((const CHAR8 *)Uuid) > * > > sizeof(CHAR16)); > > + DEBUG ((DEBUG_INFO,"Service UUID: %s.\n", > > DiscoveredInstance->Information.Uuid)); > > + } > > + if (Os != NULL) { > > + DiscoveredInstance->Information.Os = (CHAR16 > > *)AllocatePool(AsciiStrSize((const CHAR8 *)Os) * sizeof(CHAR16)); > > + AsciiStrToUnicodeStrS ((const CHAR8 *)Os, > > DiscoveredInstance->Information.Os, AsciiStrSize((const CHAR8 *)Os) * > > sizeof(CHAR16)); > > + DEBUG ((DEBUG_INFO,"Redfish service OS: %s, Version:%s.\n", > > DiscoveredInstance->Information.Os, > > DiscoveredInstance->Information.OsVersion)); > > + } > > + if (OsVer != NULL) { > > + DiscoveredInstance->Information.OsVersion = (CHAR16 > > *)AllocatePool(AsciiStrSize((const CHAR8 *)OsVer) * sizeof(CHAR16)); > > + AsciiStrToUnicodeStrS ((const CHAR8 *)OsVer, > > DiscoveredInstance->Information.OsVersion, AsciiStrSize((const CHAR8 > > *)OsVer) * sizeof(CHAR16)); > > + } > > + if (Product != NULL && ProductVer != NULL) { > > + DiscoveredInstance->Information.Product = (CHAR16 > > *)AllocatePool(AsciiStrSize((const CHAR8 *)Product) * sizeof(CHAR16)); > > + AsciiStrToUnicodeStrS ((const CHAR8 *)Product, > > DiscoveredInstance->Information.Product, AsciiStrSize((const CHAR8 > > *)Product) * sizeof(CHAR16)); > > + DiscoveredInstance->Information.ProductVer = (CHAR16 > > *)AllocatePool(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", > > DiscoveredInstance->Information.Product, > > DiscoveredInstance->Information.ProductVer)); > > + } > > + > > + if (RedfishLocation == NULL) { > > + // This is the Redfish reported from SMBIOS 42h > > + // without validation. > > + > > + IP4_COPY_ADDRESS((VOID > > *)&DiscoveredInstance->Information.RedfishHostIpAddress.v4, (VOID > > *)&Instance->TargetIpAddress.v4); > > + } > > + if (!InfoRefresh) { > > + DiscoveredList->Instance = DiscoveredInstance; > > + InsertTailList(&mRedfishInstanceList, > > &DiscoveredList->NextInstance); > > + } > > + DiscoveredInstance->Status = EFI_SUCCESS; > > + } else { > > + if (DiscoveredList != NULL) { > > + DEBUG((DEBUG_INFO,"*** This Redfish Service was already found > > ***\n")); > > + if (DiscoveredInstance->Information.Uuid != NULL) { > > + DEBUG((DEBUG_INFO,"Service UUID: %s.\n", > > DiscoveredInstance->Information.Uuid)); > > + } else { > > + DEBUG((DEBUG_INFO,"Service UUID: unknown.\n")); > > + } > > + } > > + } > > + if (Char16Uuid != NULL) { > > + FreePool((VOID *)Char16Uuid); > > + } > > + > > + Status = EFI_SUCCESS; > > + if (NewFound || InfoRefresh) { > > + // > > + // Build up EFI_REDFISH_DISCOVERED_LIST in token. > > + // > > + Instance->DiscoverToken->DiscoverList.NumberOfServiceFound = 1; > > + Instance->DiscoverToken->DiscoverList.RedfishInstances = > > DiscoveredInstance; > > + DiscoveredInstance->Status = EFI_SUCCESS; > > + if (!InfoRefresh) { > > + Status = 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 = gBS->OpenProtocol ( // Configure local host information. > > + > > Instance->DiscoverToken->DiscoverList.RedfishInstances- > >Information.Redfis > > hRestExHandle, > > + &gEfiRestExProtocolGuid, > > + (VOID **)&RestEx, > > + > > Instance->NetworkInterface->OpenDriverAgentHandle, > > + > > Instance->NetworkInterface->OpenDriverControllerHandle, > > + EFI_OPEN_PROTOCOL_BY_DRIVER > > + ); > > + if (EFI_ERROR (Status)) { > > + DeleteRestEx = TRUE; > > + goto ERROR_EXIT; > > + } > > + RestExOpened = TRUE; > > + RestExHttpConfigData = AllocateZeroPool (sizeof > > (EFI_REST_EX_HTTP_CONFIG_DATA)); > > + if (RestExHttpConfigData == NULL) { > > + Status = EFI_OUT_OF_RESOURCES; > > + DeleteRestEx = TRUE; > > + goto EXIT_FREE_CONFIG_DATA; > > + } > > + RestExHttpConfigData->SendReceiveTimeout = 5000; > > + RestExHttpConfigData->HttpConfigData.HttpVersion = > > HttpVersion11; > > + RestExHttpConfigData->HttpConfigData.LocalAddressIsIPv6 = > > CheckIsIpVersion6(NetworkInterface); > > + if (RestExHttpConfigData->HttpConfigData.LocalAddressIsIPv6) { > > + RestExHttpConfigData->HttpConfigData.AccessPoint.IPv6Node = > > AllocateZeroPool (sizeof (EFI_HTTPv6_ACCESS_POINT)); > > + if (RestExHttpConfigData->HttpConfigData.AccessPoint.IPv6Node > > == NULL) { > > + Status = EFI_OUT_OF_RESOURCES; > > + goto EXIT_FREE_CONFIG_DATA; > > + } > > + } else { > > + RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node = > > AllocateZeroPool (sizeof (EFI_HTTPv4_ACCESS_POINT)); > > + if (RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node > > == NULL) { > > + Status = EFI_OUT_OF_RESOURCES; > > + goto EXIT_FREE_CONFIG_DATA; > > + } > > + > > RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node- > >UseDefaultA > > ddress = TRUE; > > + } > > + Status = RestEx->Configure ( > > + RestEx, > > + (EFI_REST_EX_CONFIG_DATA)(UINT8 > > *)RestExHttpConfigData > > + ); > > + if (EFI_ERROR (Status)) { > > + DEBUG ((DEBUG_ERROR,"%a:REST EX configured..\n", > > __FUNCTION__)); > > + DeleteRestEx = TRUE; > > + goto EXIT_FREE_ALL; > > + } > > + // > > + // Signal client, close REST EX before signaling client. > > + // > > + if (RestExOpened) { > > + gBS->CloseProtocol( > > + > > Instance->DiscoverToken->DiscoverList.RedfishInstances- > >Information.Redfis > > hRestExHandle, > > + &gEfiRestExProtocolGuid, > > + Instance->NetworkInterface->OpenDriverAgentHandle, > > + Instance->NetworkInterface->OpenDriverControllerHandle > > + ); > > + RestExOpened = FALSE; > > + } > > + } > > + Status = gBS->SignalEvent(Instance->DiscoverToken->Event); > > + if (!EFI_ERROR (Status)) { > > + DEBUG ((DEBUG_ERROR,"%a:No event to signal!\n", > > __FUNCTION__)); > > + } > > + } > > + > > +EXIT_FREE_ALL:; > > + if (RestExHttpConfigData != NULL && > > RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node != NULL) { > > + FreePool > > (RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node); > > + } > > + > > +EXIT_FREE_CONFIG_DATA:; > > + if (RestExHttpConfigData != NULL) { > > + FreePool((VOID *)RestExHttpConfigData); > > + } > > + if (RestExOpened) { > > + gBS->CloseProtocol( > > + > > Instance->DiscoverToken->DiscoverList.RedfishInstances- > >Information.Redfis > > hRestExHandle, > > + &gEfiRestExProtocolGuid, > > + Instance->NetworkInterface->OpenDriverAgentHandle, > > + Instance->NetworkInterface->OpenDriverControllerHandle > > + ); > > + } > > +ERROR_EXIT:; > > + if (DeleteRestEx && RestExOpened) { > > + gBS->CloseProtocol( > > + > > Instance->DiscoverToken->DiscoverList.RedfishInstances- > >Information.Redfis > > hRestExHandle, > > + &gEfiRestExProtocolGuid, > > + Instance->NetworkInterface->OpenDriverAgentHandle, > > + Instance->NetworkInterface->OpenDriverControllerHandle > > + ); > > + } > > +ON_EXIT:; > > + return Status; > > +} > > + > > +/** > > + This function gets the subnet information of this network interface > > instance. > > + can discover Redfish service on it. > > + > > + @param[in] Instance > > EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL instance. > > + @param[in] ImageHandle EFI Image handle request the network > > interface 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 = Instance->NetworkProtocolType; > > + if (gRequiredProtocol [ProtocolType].GetSubnetInfo != NULL && > > Instance->GotSubnetInfo == FALSE) { > > + Status = gRequiredProtocol [ProtocolType].GetSubnetInfo ( > > + ImageHandle, > > + Instance > > + ); > > + if (EFI_ERROR (Status)) { > > + DEBUG ((DEBUG_ERROR,"%a:Faile to get Subnet infomation.\n", > > __FUNCTION__)); > > + return Status; > > + } else { > > + DEBUG ((DEBUG_INFO,"%a:MAC address: %s\n", __FUNCTION__, > > Instance->StrMacAddr)); > > + if (CheckIsIpVersion6 (Instance)) { > > + if (Instance->SubnetAddrInfoIPv6Number == 0) { > > + DEBUG ((DEBUG_ERROR,"%a: There is no Subnet infomation for > > IPv6 network interface.\n", __FUNCTION__)); > > + return EFI_NOT_FOUND; > > + } > > + ThisSubnetAddrInfoIPv6 = Instance->SubnetAddrInfoIPv6; // First > > IPv6 address information. > > + IP6_COPY_ADDRESS (&Instance->SubnetAddr.v6, > > &ThisSubnetAddrInfoIPv6->Address); > > + Instance->SubnetPrefixLength = > > ThisSubnetAddrInfoIPv6->PrefixLength; > > + DEBUG((DEBUG_INFO," IPv6 Subnet ID:%d, Prefix > > length: %d.\n", > > + ThisSubnetAddrInfoIPv6->Address.Addr [7] + > > (UINT16)ThisSubnetAddrInfoIPv6->Address.Addr [6] * 256, > > + ThisSubnetAddrInfoIPv6->PrefixLength) > > + ); > > + // > > + // If this is IPv6, then we may have to propagate network > interface > > for IPv6 network scopes > > + // according to the Ipv6 address information. > > + // > > + ThisSubnetAddrInfoIPv6 ++; > > + for (IPv6InfoIndex = 0; IPv6InfoIndex < > > Instance->SubnetAddrInfoIPv6Number - 1; IPv6InfoIndex++) { > > + // > > + // Build up addtional > > EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL instances. > > + // > > + NewNetworkInterface = > > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL > > *)AllocateZeroPool (sizeof > > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL)); > > + if (NewNetworkInterface != NULL) { > > + CopyMem ((VOID *)NewNetworkInterface, (VOID *)Instance, > > sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL)); // > > Clone information of first instance. > > + IP6_COPY_ADDRESS > > (&NewNetworkInterface->SubnetAddr.v6, > > &ThisSubnetAddrInfoIPv6->Address); > > + NewNetworkInterface->SubnetPrefixLength = > > ThisSubnetAddrInfoIPv6->PrefixLength; > > + NewNetworkInterface->GotSubnetInfo = TRUE; > > + InsertTailList (&mEfiRedfishDiscoverNetworkInterface, > > &NewNetworkInterface->Entry); > > + ThisSubnetAddrInfoIPv6 ++; > > + mNumNetworkInterface ++; > > + DEBUG((DEBUG_INFO," IPv6 Subnet ID:%d, Prefix > > length: %d.\n", > > + ThisSubnetAddrInfoIPv6->Address.Addr [7] + > > (UINT16)ThisSubnetAddrInfoIPv6->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 = TRUE; // Only try to get Subnet Info once. > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + This function gets the network interface list which Redfish discover > > protocol > > + can discover Redfish service on it. > > + > > + @param[in] This > > EFI_REDFISH_DISCOVER_PROTOCOL instance. > > + @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 > > NumberOfNetworkIntfs. > > + Caller has to release the > > memory > > + allocated by Redfish discover > > protocol. > > + > > + @retval EFI_SUCCESS The information of network interface is > > returned in NumberOfNetworkIntfs and > > + NetworkIntfInstances. > > + @retval Others Fail to return the information of network > > interface. > > + > > +**/ > > +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 > > *ThisNetworkInterfaceIntn; > > + EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *ThisNetworkInterface; > > + > > + if (NetworkIntfInstances == NULL || NumberOfNetworkIntfs == NULL || > > ImageHandle == NULL) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + *NumberOfNetworkIntfs = 0; > > + *NetworkIntfInstances = NULL; > > + > > + if (IsListEmpty ((const > > LIST_ENTRY*)&mEfiRedfishDiscoverNetworkInterface)) { > > + return EFI_NOT_FOUND; > > + } > > + > > + ThisNetworkInterface = > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE > > *)AllocateZeroPool (sizeof > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE) > > * mNumNetworkInterface); > > + if (ThisNetworkInterface == NULL) { > > + return EFI_OUT_OF_RESOURCES; > > + } > > + *NetworkIntfInstances = ThisNetworkInterface; > > + ThisNetworkInterfaceIntn = > > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL > *)GetFirstNode > > (&mEfiRedfishDiscoverNetworkInterface); > > + while (TRUE) { > > + ThisNetworkInterface->IsIpv6 = FALSE; > > + if (CheckIsIpVersion6 (ThisNetworkInterfaceIntn)) { > > + ThisNetworkInterface->IsIpv6 = TRUE; > > + } > > + CopyMem((VOID *)&ThisNetworkInterface->MacAddress, > > &ThisNetworkInterfaceIntn->MacAddress, > > ThisNetworkInterfaceIntn->HwAddressSize); > > + NetworkInterfaceGetSubnetInfo(ThisNetworkInterfaceIntn, > > ImageHandle); // Get subnet info. > > + if (!ThisNetworkInterface->IsIpv6) { > > + IP4_COPY_ADDRESS(&ThisNetworkInterface->SubnetId.v4, > > &ThisNetworkInterfaceIntn->SubnetAddr.v4); // IPv4 subnet information. > > + } else { > > + IP6_COPY_ADDRESS (&ThisNetworkInterface->SubnetId.v6, > > &ThisNetworkInterfaceIntn->SubnetAddr.v6); // IPv6 subnet information > in > > IPv6 address information. > > + } > > + ThisNetworkInterface->SubnetPrefixLength = > > ThisNetworkInterfaceIntn->SubnetPrefixLength; > > + ThisNetworkInterface->VlanId = ThisNetworkInterfaceIntn->VlanId; > > + (*NumberOfNetworkIntfs) ++; > > + if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, > > &ThisNetworkInterfaceIntn->Entry)) { > > + break; > > + } > > + ThisNetworkInterfaceIntn = > > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL > > *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, > > &ThisNetworkInterfaceIntn->Entry); > > + ThisNetworkInterface ++; > > + }; > > + return EFI_SUCCESS; > > +} > > +/** > > + This function acquires Redfish services by discovering static Redfish > setting > > + according to Redfish Host Interface or through SSDP. Returns a list of > EFI > > + handles in EFI_REDFISH_DISCOVERED_LIST. Each of EFI handle has > > cooresponding > > + EFI REST EX instance installed on it. Each REST EX isntance is a child > > instance which > > + created through EFI REST EX serivce protoocl for communicating with > > specific > > + Redfish service. > > + > > + @param[in] This > > EFI_REDFISH_DISCOVER_PROTOCOL instance. > > + @param[in] ImageHandle EFI image owns these > > Redfish service instances. > > + @param[in] TargetNetworkInterface Target network interface to > > do the discovery. > > + NULL means discover > > Redfish service on all network interfaces on platform. > > + @param[in] Flags Redfish service discover > > flags. > > + @param[in] Token > > EFI_REDFISH_DISCOVERED_TOKEN instance. > > + The memory of > > EFI_REDFISH_DISCOVERED_LIST and the strings in > > + > > EFI_REDFISH_DISCOVERED_INFORMATION are all allocated by Acquire() > > + and must be freed when > > caller invoke Release(). > > + > > + @retval EFI_SUCCESS REST EX instance of discovered > > Redfish services are returned. > > + @retval EFI_INVALID_PARAMETERS ImageHandle == NULL, Flags == 0, > > Token == NULL, Token->Timeout > 5, > > + or Token->Event == 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 > > *TargetNetworkInterfaceInternal; > > + > > + DEBUG ((DEBUG_INFO,"%a:Entry.\n", __FUNCTION__)); > > + > > + // > > + // Validate parameters. > > + // > > + if (ImageHandle == NULL || Token == NULL || ((Flags & > > ~EFI_REDFISH_DISCOVER_VALIDATION) == 0)) { > > + DEBUG ((DEBUG_ERROR,"%a:Invalid parameters.\n", > > __FUNCTION__)); > > + return EFI_INVALID_PARAMETER; > > + } > > + // > > + // Validate target network interface. > > + // > > + if (EFI_ERROR (ValidateTargetNetworkInterface > (TargetNetworkInterface, > > Flags))) { > > + return EFI_UNSUPPORTED; > > + } > > + if (TargetNetworkInterface != NULL) { > > + TargetNetworkInterfaceInternal = GetTargetNetworkInterfaceInternal > > (TargetNetworkInterface); > > + NumNetworkInterfaces = 1; > > + } else { > > + TargetNetworkInterfaceInternal = > > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL > *)GetFirstNode > > (&mEfiRedfishDiscoverNetworkInterface); > > + NumNetworkInterfaces = NumberOfNetworkInterface (); > > + if (NumNetworkInterfaces == 0) { > > + DEBUG ((DEBUG_ERROR,"%a:No network interface on platform.\n", > > __FUNCTION__)); > > + return EFI_UNSUPPORTED; > > + } > > + } > > + for (NetworkInterfacesIndex = 0; NetworkInterfacesIndex < > > NumNetworkInterfaces; NetworkInterfacesIndex ++) { > > + Status1 = EFI_SUCCESS; > > + Status2 = EFI_SUCCESS; > > + NewInstance = FALSE; > > + Instance = GetInstanceByOwner (ImageHandle, > > TargetNetworkInterfaceInternal, Flags & > > ~EFI_REDFISH_DISCOVER_VALIDATION); // Check if we can re-use > previous > > instance. > > + if (Instance == NULL) { > > + DEBUG ((DEBUG_INFO,"%a:Create new > > EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE.\n", __FUNCTION__)); > > + Instance = (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE > > > *)AllocateZeroPool(sizeof(EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE)) > > ; > > + if (Instance == NULL) { > > + DEBUG ((DEBUG_ERROR,"%a:Memory allocation fail.\n", > > __FUNCTION__)); > > + } > > + InitializeListHead (&Instance->Entry); > > + Instance->Owner = ImageHandle; > > + Instance->DiscoverFlags = Flags & > > ~EFI_REDFISH_DISCOVER_VALIDATION; > > + Instance->NetworkInterface = TargetNetworkInterfaceInternal; > > + // > > + // Get subnet information in case subnet information is not set > > because > > + // RedfishServiceGetNetworkInterfaces hasn't been called yet. > > + // > > + NetworkInterfaceGetSubnetInfo (TargetNetworkInterfaceInternal, > > ImageHandle); > > + NewInstance = TRUE; > > + } > > + if (TargetNetworkInterfaceInternal->StrMacAddr != NULL) { > > + DEBUG((DEBUG_INFO,"%a:Acquire Redfish service on network > > interface MAC address:%s.\n", __FUNCTION__, > > TargetNetworkInterfaceInternal->StrMacAddr)); > > + } else { > > + DEBUG((DEBUG_INFO,"%a:WARNING: No MAC address on this > > network interface.\n", __FUNCTION__)); > > + } > > + > > + Instance->DiscoverToken = Token; // Always use the latest Token > > passed by caller. > > + if ((Flags & EFI_REDFISH_DISCOVER_HOST_INTERFACE) != 0) { > > + DEBUG ((DEBUG_INFO,"%a:Redfish HOST interface discovery.\n", > > __FUNCTION__)); > > + Instance->HostIntfValidation = FALSE; > > + if ((Flags & EFI_REDFISH_DISCOVER_VALIDATION) != 0) { > > + Instance->HostIntfValidation = TRUE; > > + } > > + Status1 = DiscoverRedfishHostInterface (Instance); // Discover > > Redfish service through Redfish Host Interface. > > + } > > + if ((Flags & EFI_REDFISH_DISCOVER_SSDP) != 0) { > > + DEBUG ((DEBUG_ERROR,"%a:Redfish service discovery through SSDP > > is not 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 > > discovery Status1=%x, Status2=%x.\n", __FUNCTION__, Status1, Status2)); > > + } else { > > + if (NewInstance) { > > + InsertTailList(&mRedfishDiscoverList, &Instance->Entry); > > + } > > + } > > + } > > + if (TargetNetworkInterface == NULL) { > > + // > > + // Discover Redfish services on all of network interfaces. > > + // > > + TargetNetworkInterfaceInternal = > > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL > > *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, > > &TargetNetworkInterfaceInternal->Entry); > > + } > > + } > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + This function aborts Redfish service discovery on the given network > > interface. > > + > > + @param[in] This > > EFI_REDFISH_DISCOVER_PROTOCOL instance. > > + @param[in] TargetNetworkInterface Target network interface to > > do the discovery. > > + > > + @retval EFI_SUCCESS REST EX instance of discovered > > Redfish services 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 OPTIONAL > > +) > > +{ > > + // 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 released. > > + @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", > > __FUNCTION__)); > > + return EFI_NOT_FOUND; > > + } > > + AnyFailRelease = FALSE; > > + ThisRedfishInstance = InstanceList->RedfishInstances; > > + for (NumService = 0; NumService < InstanceList- > >NumberOfServiceFound; > > NumService ++) { > > + DiscoveredRedfishInstance = > > (EFI_REDFISH_DISCOVERED_INTERNAL_LIST > > *)GetFirstNode(&mRedfishInstanceList); > > + do { > > + if (DiscoveredRedfishInstance->Instance == ThisRedfishInstance) { > > + RemoveEntryList (&DiscoveredRedfishInstance->NextInstance); > > + if (ThisRedfishInstance->Information.Location != NULL) { > > + FreePool (ThisRedfishInstance->Information.Location); > > + } > > + if (ThisRedfishInstance->Information.Uuid != NULL) { > > + FreePool (ThisRedfishInstance->Information.Uuid); > > + } > > + if (ThisRedfishInstance->Information.Os != NULL) { > > + FreePool (ThisRedfishInstance->Information.Os); > > + } > > + if (ThisRedfishInstance->Information.OsVersion != NULL) { > > + FreePool (ThisRedfishInstance->Information.OsVersion); > > + } > > + if (ThisRedfishInstance->Information.Product != NULL) { > > + FreePool (ThisRedfishInstance->Information.Product); > > + } > > + if (ThisRedfishInstance->Information.ProductVer != NULL) { > > + FreePool (ThisRedfishInstance->Information.ProductVer); > > + } > > + FreePool((VOID *)ThisRedfishInstance); > > + goto ReleaseNext; > > + } > > + > > + if (IsNodeAtEnd(&mRedfishInstanceList, > > &DiscoveredRedfishInstance->NextInstance)) { > > + break; > > + } > > + DiscoveredRedfishInstance = > > (EFI_REDFISH_DISCOVERED_INTERNAL_LIST > > *)GetNextNode(&mRedfishInstanceList, > > &DiscoveredRedfishInstance->NextInstance); > > + } while (TRUE); > > + AnyFailRelease = TRUE; > > +ReleaseNext:; > > + // > > + // Release next discovered Redfish Service. > > + // > > + ThisRedfishInstance = (EFI_REDFISH_DISCOVERED_INSTANCE > > *)((UINT8 *)ThisRedfishInstance + sizeof > > (EFI_REDFISH_DISCOVERED_INSTANCE)); > > + } > > + if (AnyFailRelease) { > > + return EFI_NOT_FOUND; > > + } else { > > + return EFI_SUCCESS; > > + } > > +} > > + > > +EFI_REDFISH_DISCOVER_PROTOCOL mRedfishDiscover = { > > + 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_NETWORK_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 = NULL; > > + *IsNewInstance = TRUE; > > + if (!IsListEmpty ((const > > LIST_ENTRY*)&mEfiRedfishDiscoverNetworkInterface)) { > > + // > > + // Check if this instance already exist. > > + // > > + ThisNetworkInterface = > > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL > *)GetFirstNode > > (&mEfiRedfishDiscoverNetworkInterface); > > + if (ThisNetworkInterface != NULL) { > > + while (TRUE) { > > + if ((CompareMem ((CONST VOID > > *)&ThisNetworkInterface->MacAddress.Addr, (CONST VOID > > *)&MacAddress.Addr, HwAddressSize) == 0) && > > + (ThisNetworkInterface->NetworkProtocolType == > > NetworkProtocolType)){ > > + NewNetworkInterface = ThisNetworkInterface; > > + *IsNewInstance = FALSE; > > + break; > > + } > > + if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, > > &ThisNetworkInterface->Entry)) { > > + NewNetworkInterface = NULL; > > + break; > > + } > > + ThisNetworkInterface = > > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL > > *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, > > &ThisNetworkInterface->Entry); > > + }; > > + } > > + } > > + if (NewNetworkInterface == NULL) { > > + // > > + // Create a new instance. > > + // > > + NewNetworkInterface = > > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL > > *)AllocateZeroPool (sizeof > > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL)); > > + if (NewNetworkInterface == NULL) { > > + return EFI_OUT_OF_RESOURCES; > > + } > > + NewNetworkInterface->HwAddressSize = HwAddressSize; > > + CopyMem (&NewNetworkInterface->MacAddress.Addr, > > &MacAddress.Addr, NewNetworkInterface->HwAddressSize); > > + NetLibGetMacString (ControllerHandle, NULL, > > &NewNetworkInterface->StrMacAddr); > > + NewNetworkInterface->VlanId = NetLibGetVlanId (ControllerHandle); > > + } > > + *NetworkInterface = 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 = gBS->UninstallProtocolInterface( > > + ThisNetworkInterface->OpenDriverControllerHandle, > > + gRequiredProtocol > > [ThisNetworkInterface->NetworkProtocolType].DiscoveredProtocolGuid, > > + > > &ThisNetworkInterface- > >NetworkInterfaceProtocolInfo.ProtocolDiscoverId > > + ); > > + 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_PROTOCOL instance. > > + @param[in] ControllerHandle The handle of the controller to test. > > This handle > > + must support a protocol > > interface that supplies > > + an I/O abstraction to the driver. > > + @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 = 0; Index < (sizeof (gRequiredProtocol) / sizeof > > (REDFISH_DISCOVER_REQUIRED_PROTOCOL)); Index ++) { > > + Status = gBS->OpenProtocol ( > > + ControllerHandle, > > + gRequiredProtocol > > [Index].RequiredServiceBindingProtocolGuid, > > + NULL, > > + This->DriverBindingHandle, > > + ControllerHandle, > > + EFI_OPEN_PROTOCOL_TEST_PROTOCOL > > + ); > > + if (!EFI_ERROR (Status)) { > > + Status = 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_PROTOCOL instance. > > + @param[in] ControllerHandle The handle of the controller to test. > > This handle > > + must support a protocol > > interface that supplies > > + an I/O abstraction to the driver. > > + @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 = FALSE; > > + Index = 0; > > + do { > > + Status = 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 == (sizeof(gRequiredProtocol) / > > sizeof(REDFISH_DISCOVER_REQUIRED_PROTOCOL))) { > > + break; > > + } > > + continue; > > + } > > + > > + Status = gBS->OpenProtocol ( > > + ControllerHandle, > > + gRequiredProtocol > > [Index].RequiredServiceBindingProtocolGuid, > > + &TempInterface, > > + This->DriverBindingHandle, > > + ControllerHandle, > > + EFI_OPEN_PROTOCOL_GET_PROTOCOL > > + ); > > + if (EFI_ERROR (Status)) { > > + Index ++; > > + if (Index == (sizeof(gRequiredProtocol) / > > sizeof(REDFISH_DISCOVER_REQUIRED_PROTOCOL))) { > > + break; > > + } > > + continue; > > + } > > + if (gRequiredProtocol [Index].ProtocolType != ProtocolTypeRestEx) { > > + OldTpl = gBS->RaiseTPL > > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL); > > + Status = CreateRedfishDiscoverNetworkInterface(ControllerHandle, > > gRequiredProtocol [Index].ProtocolType, &IsNew, &NetworkInterface); > > + if (EFI_ERROR (Status)) { > > + gBS->RestoreTPL (OldTpl); > > + return Status; > > + } > > + NetworkInterface->NetworkProtocolType = gRequiredProtocol > > [Index].ProtocolType; > > + NetworkInterface->OpenDriverAgentHandle = > > This->DriverBindingHandle; > > + NetworkInterface->OpenDriverControllerHandle = ControllerHandle; > > + NetworkInterface->NetworkInterfaceProtocolInfo.ProtocolGuid = \ > > + *gRequiredProtocol [Index].RequiredProtocolGuid; > > + > > NetworkInterface->NetworkInterfaceProtocolInfo.ProtocolServiceGuid = \ > > + *gRequiredProtocol [Index].RequiredServiceBindingProtocolGuid; > > + ProtocolDiscoverIdPtr = > > &NetworkInterface->NetworkInterfaceProtocolInfo.ProtocolDiscoverId; > > + OpenDriverAgentHandle = > > NetworkInterface->OpenDriverAgentHandle; > > + OpenDriverControllerHandle = > > NetworkInterface->OpenDriverControllerHandle; > > + HandleOfProtocolInterfacePtr = > > &NetworkInterface- > >NetworkInterfaceProtocolInfo.ProtocolControllerHandle > > ; > > + Interface = > > &NetworkInterface- > >NetworkInterfaceProtocolInfo.NetworkProtocolInterfac > > e; > > + NewNetworkInterfaceInstalled = TRUE; > > + if (IsNew) { > > + InsertTailList (&mEfiRedfishDiscoverNetworkInterface, > > &NetworkInterface->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 > > corresponding EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL > > + // when discovery. > > + > > + RestExInstance = > > (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL > *)AllocateZeroPool > > (sizeof (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL)); > > + if (RestExInstance == NULL) { > > + return EFI_OUT_OF_RESOURCES; > > + } > > + RestExInstance->OpenDriverAgentHandle = > > This->DriverBindingHandle; > > + RestExInstance->OpenDriverControllerHandle = ControllerHandle; > > + RestExInstance->RestExControllerHandle = ControllerHandle; > > + InitializeListHead (&RestExInstance->Entry); > > + InsertTailList (&mEfiRedfishDiscoverRestExInstance, > > &RestExInstance->Entry); > > + mNumRestExInstance ++; > > + ProtocolDiscoverIdPtr = &RestExInstance->RestExId; > > + OpenDriverAgentHandle = > > RestExInstance->OpenDriverAgentHandle; > > + OpenDriverControllerHandle = > > RestExInstance->OpenDriverControllerHandle; > > + HandleOfProtocolInterfacePtr = > > &RestExInstance->RestExChildHandle; > > + Interface = (VOID **)&RestExInstance->RestExProtocolInterface; > > + } > > + Status = gBS->InstallProtocolInterface ( > > + &ControllerHandle, > > + gRequiredProtocol [Index].DiscoveredProtocolGuid, > > + EFI_NATIVE_INTERFACE, > > + ProtocolDiscoverIdPtr > > + ); > > + if (EFI_ERROR (Status)) { > > + Index ++; > > + if (Index == (sizeof(gRequiredProtocol) / > > sizeof(REDFISH_DISCOVER_REQUIRED_PROTOCOL))) { > > + break; > > + } > > + continue; > > + } > > + // > > + // Create service binding child and open it BY_DRIVER. > > + // > > + Status = NetLibCreateServiceChild ( > > + ControllerHandle, > > + This->ImageHandle, > > + gRequiredProtocol > > [Index].RequiredServiceBindingProtocolGuid, > > + HandleOfProtocolInterfacePtr > > + ); > > + if (!EFI_ERROR (Status)) { > > + Status = gBS->OpenProtocol ( > > + *HandleOfProtocolInterfacePtr, > > + gRequiredProtocol [Index].RequiredProtocolGuid, > > + Interface, > > + OpenDriverAgentHandle, > > + OpenDriverControllerHandle, > > + EFI_OPEN_PROTOCOL_BY_DRIVER > > + ); > > + if (!EFI_ERROR (Status)) { > > + if (EfiRedfishDiscoverProtocolHandle == NULL && > > + (gRequiredProtocol [Index].ProtocolType == > > ProtocolTypeRestEx) && > > + !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 = gBS->InstallProtocolInterface ( > > + &EfiRedfishDiscoverProtocolHandle, > > + &gEfiRedfishDiscoverProtocolGuid, > > + EFI_NATIVE_INTERFACE, > > + (VOID *)&mRedfishDiscover > > + ); > > + } else if (EfiRedfishDiscoverProtocolHandle != NULL && > > NewNetworkInterfaceInstalled) { > > + Status = gBS->ReinstallProtocolInterface ( > > + EfiRedfishDiscoverProtocolHandle, > > + &gEfiRedfishDiscoverProtocolGuid, > > + (VOID *)&mRedfishDiscover, > > + (VOID *)&mRedfishDiscover > > + ); > > + NewNetworkInterfaceInstalled = FALSE; > > + } > > + } > > + return Status; > > + } else { > > + Index ++; > > + if (Index == (sizeof(gRequiredProtocol) / > > sizeof(REDFISH_DISCOVER_REQUIRED_PROTOCOL))) { > > + break; > > + } > > + continue; > > + } > > + } while (Index < (sizeof(gRequiredProtocol) / > > sizeof(REDFISH_DISCOVER_REQUIRED_PROTOCOL))); > > + return EFI_UNSUPPORTED; > > +} > > +/** > > + Close the protocol opened for Redfish discovery. This function also > > destories > > + 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 that supplies > > + an I/O abstraction to the > > driver. > > + @param[in] ThisRequiredProtocol Pointer to the instance of > > REDFISH_DISCOVER_REQUIRED_PROTOCOL. > > + @param[in] DriverAgentHandle Driver agent handle which used > > to open protocol earlier. > > + @param[in] DriverControllerHandle Driver controller handle which used > > to 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 = 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_PROTOCOL instance. > > + @param[in] ControllerHandle The handle of the controller to test. > > This handle > > + must support a protocol > > interface that supplies > > + an I/O abstraction to the driver. > > + @retval EFI_SUCCESS One of required protocol is found. > > + @retval Others Faile to stop the services on > > network interface. > > +**/ > > +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 = 0; Index < (sizeof (gRequiredProtocol) / sizeof > > (REDFISH_DISCOVER_REQUIRED_PROTOCOL)); Index ++) { > > + Status = gBS->HandleProtocol ( > > + ControllerHandle, > > + gRequiredProtocol [Index].RequiredProtocolGuid, > > + (VOID **)&Interface > > + ); > > + if (!EFI_ERROR (Status)) { > > + if (gRequiredProtocol [Index].ProtocolType != ProtocolTypeRestEx) { > > + if (IsListEmpty (&mEfiRedfishDiscoverNetworkInterface)) { > > + return EFI_NOT_FOUND; > > + } > > + OldTpl = gBS->RaiseTPL > > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL); > > + ThisNetworkInterface = > > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL > *)GetFirstNode > > (&mEfiRedfishDiscoverNetworkInterface); > > + while (TRUE) { > > + if > > (ThisNetworkInterface- > >NetworkInterfaceProtocolInfo.ProtocolControllerHan > > dle == ControllerHandle) { > > + > > + Status = CloseProtocolService ( // Close protocol and destroy > > service. > > + ThisBindingProtocol, > > + ControllerHandle, > > + &gRequiredProtocol [Index], > > + > > ThisNetworkInterface->OpenDriverAgentHandle, > > + > > ThisNetworkInterface->OpenDriverControllerHandle > > + ); > > + if (!EFI_ERROR (Status)) { > > + Status = DestroyRedfishNetwrokInterface > > (ThisNetworkInterface); > > + } > > + gBS->RestoreTPL (OldTpl); > > + // Reinstall Redfish Discover protocol to notify network > > + // interface change. > > + > > + Status = gBS->ReinstallProtocolInterface ( > > + EfiRedfishDiscoverProtocolHandle, > > + &gEfiRedfishDiscoverProtocolGuid, > > + (VOID *)&mRedfishDiscover, > > + (VOID *)&mRedfishDiscover > > + ); > > + if (EFI_ERROR (Status)) { > > + DEBUG((DEBUG_ERROR, "%a: Reinstall > > gEfiRedfishDiscoverProtocolGuid fail.", __FUNCTION__)); > > + } > > + return Status; > > + } > > + if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, > > &ThisNetworkInterface->Entry)) { > > + break; > > + } > > + ThisNetworkInterface = > > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL > > *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, > > &ThisNetworkInterface->Entry); > > + }; > > + gBS->RestoreTPL (OldTpl); > > + } else { > > + if (IsListEmpty (&mEfiRedfishDiscoverRestExInstance)) { > > + return EFI_NOT_FOUND; > > + } > > + OldTpl = gBS->RaiseTPL > > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL); > > + RestExInstance = > > (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL *)GetFirstNode > > (&mEfiRedfishDiscoverRestExInstance); > > + while (TRUE) { > > + if (RestExInstance->RestExChildHandle == ControllerHandle) { > > + Status = 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, > > &RestExInstance->Entry)) { > > + break; > > + } > > + RestExInstance = > > (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL > > *)GetNextNode(&mEfiRedfishDiscoverRestExInstance, > > &RestExInstance->Entry); > > + }; > > + gBS->RestoreTPL (OldTpl); > > + } > > + } > > + } > > + return EFI_NOT_FOUND; > > +} > > +/** > > + Tests to see if this driver supports a given controller. If a child > device is > > provided, > > + it further tests to see if this driver supports creating a handle for > the > > specified child device. > > + > > + This function checks to see if the driver specified by This supports > the > > device specified by > > + ControllerHandle. Drivers will typically use the device path attached > to > > + ControllerHandle and/or the services from the bus I/O abstraction > > attached to > > + ControllerHandle to determine if the driver supports ControllerHandle. > > This function > > + may be called many times during platform initialization. In order to > reduce > > boot times, the tests > > + performed by this function must be very small, and take as little time > as > > possible to execute. This > > + function must not change the state of any hardware devices, and this > > function must be aware that the > > + device specified by ControllerHandle may already be managed by the > > same driver or a > > + different driver. This function must match its calls to AllocatePages() > with > > FreePages(), > > + AllocatePool() with FreePool(), and OpenProtocol() with > CloseProtocol(). > > + Because ControllerHandle may have been previously started by the > same > > driver, if a protocol is > > + already in the opened state, then it must not be closed with > > CloseProtocol(). This is required > > + to guarantee the state of ControllerHandle is not modified by this > > function. > > + > > + @param[in] This A pointer to the > > EFI_DRIVER_BINDING_PROTOCOL instance. > > + @param[in] ControllerHandle The handle of the controller to test. > > This handle > > + must support a protocol > > interface that supplies > > + an I/O abstraction to the driver. > > + @param[in] RemainingDevicePath A pointer to the remaining portion > > of a device path. This > > + parameter is ignored by device > > drivers, and is optional for bus > > + drivers. For bus drivers, if this > > parameter is not NULL, then > > + the bus driver must determine if > > the bus controller specified > > + by ControllerHandle and the > > child controller specified > > + by RemainingDevicePath are > > both supported by this > > + bus driver. > > + > > + @retval EFI_SUCCESS The device specified by > > ControllerHandle and > > + RemainingDevicePath is > > supported by the driver specified by This. > > + @retval EFI_ALREADY_STARTED The device specified by > > ControllerHandle and > > + RemainingDevicePath is already > > being managed by the driver > > + specified by This. > > + @retval EFI_ACCESS_DENIED The device specified by > > ControllerHandle and > > + RemainingDevicePath is already > > being managed by a different > > + driver or an application that > > requires exclusive access. > > + Currently not implemented. > > + @retval EFI_UNSUPPORTED The device specified by > > ControllerHandle and > > + RemainingDevicePath is not > > supported by the driver specified by This. > > +**/ > > +EFI_STATUS > > +EFIAPI > > +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 > > behavior will not be deterministic. > > + 1. ControllerHandle must be a valid EFI_HANDLE. > > + 2. If RemainingDevicePath is not NULL, then it must be a pointer to a > > naturally aligned > > + EFI_DEVICE_PATH_PROTOCOL. > > + 3. Prior to calling Start(), the Supported() function for the driver > specified > > by This must > > + have been called with the same calling parameters, and Supported() > > must have returned EFI_SUCCESS. > > + > > + @param[in] This A pointer to the > > EFI_DRIVER_BINDING_PROTOCOL instance. > > + @param[in] ControllerHandle The handle of the controller to start. > > This handle > > + must support a protocol > > interface that supplies > > + an I/O abstraction to the driver. > > + @param[in] RemainingDevicePath A pointer to the remaining portion > > of a device path. This > > + parameter is ignored by device > > drivers, and is optional for bus > > + drivers. For a bus driver, if this > > parameter is NULL, then handles > > + for all the children of Controller > > are created by this driver. > > + If this parameter is not NULL > > and the first Device Path Node is > > + not the End of Device Path Node, > > then only the handle for the > > + child device specified by the first > > Device Path Node of > > + RemainingDevicePath is created > > by this driver. > > + If the first Device Path Node of > > RemainingDevicePath is > > + the End of Device Path Node, no > > child handle is created by this > > + driver. > > + > > + @retval EFI_SUCCESS The device was started. > > + @retval EFI_DEVICE_ERROR The device could not be started > > due to a device error.Currently not implemented. > > + @retval EFI_OUT_OF_RESOURCES The request could not be > > completed due to a lack of resources. > > + @retval Others The driver failded to start the > > device. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +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 > locations, > > + but the following calling restrictions must be followed, or the system > > behavior will not be deterministic. > > + 1. ControllerHandle must be a valid EFI_HANDLE that was used on a > > previous call to this > > + same driver's Start() function. > > + 2. The first NumberOfChildren handles of ChildHandleBuffer must all be > a > > valid > > + EFI_HANDLE. In addition, all of these handles must have been created > > in this driver's > > + Start() function, and the Start() function must have called > > OpenProtocol() on > > + ControllerHandle with an Attribute of > > EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. > > + > > + @param[in] This A pointer to the > > EFI_DRIVER_BINDING_PROTOCOL instance. > > + @param[in] ControllerHandle A handle to the device being stopped. > > The handle must > > + support a bus specific I/O protocol > > for the driver > > + to use to stop the device. > > + @param[in] NumberOfChildren The number of child device handles in > > ChildHandleBuffer. > > + @param[in] ChildHandleBuffer An array of child handles to be freed. > > May be NULL > > + if NumberOfChildren is 0. > > + > > + @retval EFI_SUCCESS The device was stopped. > > + @retval EFI_DEVICE_ERROR The device could not be stopped due > > to a device error. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +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 = { > > + 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 = EFI_SUCCESS; > > + InitializeListHead (&mRedfishDiscoverList); > > + InitializeListHead (&mRedfishInstanceList); > > + InitializeListHead (&mEfiRedfishDiscoverNetworkInterface); > > + InitializeListHead (&mEfiRedfishDiscoverRestExInstance); > > + // > > + // Install binding protoocl to obtain UDP and REST EX protocol. > > + // > > + Status = 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 > the > > 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 = EFI_SUCCESS; > > + // Destroy all network interfaces found by EFI Redfish Discover driver > and > > + // stop services created for Redfish Discover. > > + > > + while (!IsListEmpty (&mEfiRedfishDiscoverNetworkInterface)) { > > + ThisNetworkInterface = > > (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL > *)GetFirstNode > > (&mEfiRedfishDiscoverNetworkInterface); > > + StopServiceOnNetworkInterface (&gRedfishDiscoverDriverBinding, > > ThisNetworkInterface- > >NetworkInterfaceProtocolInfo.ProtocolControllerHan > > dle); > > + }; > > + // Disconnect EFI Redfish discover driver controller to notify the > > + // clinet which uses .EFI Redfish discover protocol. > > + > > + if (EfiRedfishDiscoverProtocolHandle != NULL) { > > + // > > + // Notify user EFI_REDFISH_DISCOVER_PROTOCOL is unloaded. > > + // > > + gBS->DisconnectController (EfiRedfishDiscoverProtocolHandle, NULL, > > NULL); > > + Status = gBS->UninstallProtocolInterface( > > + EfiRedfishDiscoverProtocolHandle, > > + &gEfiRedfishDiscoverProtocolGuid, > > + (VOID *)&mRedfishDiscover > > + ); > > + } > > + return Status; > > +} > > diff --git a/RedfishPkg/RedfishDiscoverDxe/RedfishSmbiosHostInterface.c > > b/RedfishPkg/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<BR> > > + > > + 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 == NULL) || (ProtocolData == NULL)) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; > > + Status = Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, > > NULL); > > + while (!EFI_ERROR (Status) && SmbiosHandle != > > SMBIOS_HANDLE_PI_RESERVED) { > > + if (Record->Type == > > SMBIOS_TYPE_MANAGEMENT_CONTROLLER_HOST_INTERFACE) { > > + // > > + // Check Interface Type, should be Network Host Interface = 40h > > + // > > + mType42Record = (SMBIOS_TABLE_TYPE42 *) Record; > > + if (mType42Record->InterfaceType == > > MCHostInterfaceTypeNetworkHostInterface) { > > + ASSERT (Record->Length >= 9); > > + Offset = 5; > > + RecordTmp = (UINT8 *) Record + Offset; > > + // > > + // Get interface specific data length. > > + // > > + SpecificDataLen = *RecordTmp; > > + Offset += 1; > > + RecordTmp = (UINT8 *) Record + Offset; > > + > > + // > > + // Check Device Type, only PCI/PCIe Network Interface v2 is > > supported now. > > + // > > + if (*RecordTmp == > > REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE_V2) { > > + ASSERT (SpecificDataLen == sizeof > > (PCI_OR_PCIE_INTERFACE_DEVICE_DESCRIPTOR_V2) + 1); > > + *DeviceDescriptor = (REDFISH_INTERFACE_DATA *)RecordTmp; > > + Offset = Offset + SpecificDataLen; > > + RecordTmp = (UINT8 *) Record + Offset; > > + // > > + // Check Protocol count. if > 1, only use the first protocol. > > + // > > + ASSERT (*RecordTmp == 1); > > + Offset += 1; > > + RecordTmp = (UINT8 *) Record + Offset; > > + // > > + // Check protocol identifier. > > + // > > + if (*RecordTmp == MCHostInterfaceProtocolTypeRedfishOverIP) > > { > > + Offset += 1; > > + RecordTmp = (UINT8 *) Record + Offset; > > + ProtocolLength = *RecordTmp; > > + > > + Offset += 1; > > + RecordTmp = (UINT8 *) Record + Offset; > > + > > + // > > + // This SMBIOS record is invalid, if the length of protocol > > specific data for > > + // Redfish Over IP protocol is wrong. > > + // > > + if ((*(RecordTmp + 90) + sizeof > > (REDFISH_OVER_IP_PROTOCOL_DATA) - 1) != ProtocolLength) { > > + return EFI_SECURITY_VIOLATION; > > + } > > + > > + Offset += ProtocolLength; > > + // > > + // This SMBIOS record is invalid, if the length is smaller > than > > the offset. > > + // > > + if (Offset > mType42Record->Hdr.Length) { > > + return EFI_SECURITY_VIOLATION; > > + } > > + *ProtocolData = (REDFISH_OVER_IP_PROTOCOL_DATA > > *)RecordTmp; > > + return EFI_SUCCESS; > > + } > > + } > > + } > > + } > > + Status = Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, > > NULL); > > + } > > + > > + *ProtocolData = NULL; > > + return EFI_NOT_FOUND; > > +} > > -- > > 2.17.1 > > > > > > > > > > > > > > > > > -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#73764): https://edk2.groups.io/g/devel/message/73764 Mute This Topic: https://groups.io/mt/81909823/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=-=-=-=-=-=-=-=-=-=-=-
Reviewed-by: Nickle Wang <nickle.wang@hpe.com> Thanks, Nickle -----Original Message----- From: Chang, Abner (HPS SW/FW Technologist) <abner.chang@hpe.com> Sent: Friday, March 26, 2021 12:54 PM To: devel@edk2.groups.io Cc: Wang, Nickle (HPS SW) <nickle.wang@hpe.com>; Jiaxin Wu <jiaxin.wu@intel.com>; Siyuan Fu <siyuan.fu@intel.com>; Fan Wang <fan.wang@intel.com>; Jiewen Yao <jiewen.yao@intel.com> Subject: [PATCH] RedfishPkg/RedfishDiscoverDxe: EFI Redfish Discover Protocol EDK2 EFI Redfish Discover Protocol implementation. Refer to UEFI spec 2.9 section 31.1. Signed-off-by: Abner Chang <abner.chang@hpe.com> Cc: Nickle Wang <nickle.wang@hpe.com> Cc: Jiaxin Wu <jiaxin.wu@intel.com> Cc: Siyuan Fu <siyuan.fu@intel.com> Cc: Fan Wang <fan.wang@intel.com> Cc: Jiewen Yao <jiewen.yao@intel.com> --- 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/RedfishSmbiosHostInterface.c diff --git a/RedfishPkg/RedfishComponents.dsc.inc b/RedfishPkg/RedfishComponents.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<BR> +# (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR> # # 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<BR> +# (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR> # # 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/RedfishPkg/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<BR> +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x0001001b + BASE_NAME = RedfishDiscoverDxe + FILE_GUID = 28A76FE5-43D7-48A3-9714-C1B7BDD6DFB6 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = RedfishDiscoverEntryPoint + UNLOAD_IMAGE = 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 ## CONSUMES + diff --git a/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverInternal.h b/RedfishPkg/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<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef EFI_REDFISH_DISCOVER_INTERNAL_H_ +#define EFI_REDFISH_DISCOVER_INTERNAL_H_ + +#include <Uefi.h> + +#include <Protocol/ComponentName.h> +#include <Protocol/ComponentName2.h> +#include <Protocol/DriverBinding.h> +#include <Protocol/RedfishDiscover.h> +#include <Protocol/Smbios.h> +#include <Protocol/Tcp4.h> +#include <Protocol/Tcp6.h> + +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/DebugLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/NetLib.h> +#include <Library/PrintLib.h> +#include <Library/RestExLib.h> +#include <Library/UefiLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiDriverEntryPoint.h> + +#include <IndustryStandard/RedfishHostInterface.h> + +#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 = 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 network protocol handle. + EFI_HANDLE ProtocolControllerHandle; ///< The controller handle on network protocol. + VOID *NetworkProtocolInterface; ///< The protocol interface of network 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 network protocol. + EFI_HANDLE OpenDriverControllerHandle; ///< The controller handle to open network protocol. + UINTN HwAddressSize; ///< The size of network interface hardware address. + EFI_MAC_ADDRESS MacAddress; ///< MAC address of network interface. + CHAR16 *StrMacAddr; ///< String to MAC address of network interface. + BOOLEAN GotSubnetInfo; ///< Indicates sub net information is retrieved. + EFI_IP_ADDRESS SubnetAddr; ///< Subnet ID. + EFI_IP_ADDRESS SubnetMask; ///< Subnet mask (IPv4 only) + UINT8 SubnetPrefixLength; ///< Subnet prefix. + UINT16 VlanId; ///< VLAN ID + UINT32 SubnetAddrInfoIPv6Number; ///< IPv6 address info number. + EFI_IP6_ADDRESS_INFO *SubnetAddrInfoIPv6; ///< IPv6 address info. + // + // Network interface protocol and REST EX infor. + // + UINT32 NetworkProtocolType; ///< Network protocol type. Refer to + ///< NETWORK_INTERFACE_PROTOCOL_TYPE. + REDFISH_DISCOVER_NETWORK_INTERFACE_PROTOCOL NetworkInterfaceProtocolInfo; ///< Network interface protocol information. + EFI_HANDLE RestExHandle; ///< REST EX handle associated 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 handle to open network protocol. + EFI_HANDLE RestExChildHandle; ///< The child handle created throught REST EX Service Protocol. + EFI_HANDLE RestExControllerHandle; ///< The controller handle which provide REST EX protocol. + EFI_REST_EX_PROTOCOL *RestExProtocolInterface; ///< Pointer to EFI_REST_EX_PROTOCOL. + UINT32 RestExId; ///< The identifier installed 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 protocol type, + ///< Refer to NETWORK_INTERFACE_PROTOCOL_TYPE. + CHAR16 *ProtocolName; ///< Protocol name. + EFI_GUID *RequiredProtocolGuid; ///< Network protocol interface GUID. + EFI_GUID *RequiredServiceBindingProtocolGuid; ///< Network protocol service GUID. + EFI_GUID *DiscoveredProtocolGuid; ///< Protocol interface GUID use to install identifier. + EFI_REDFISH_DISCOVER_GET_SUBNET_INFO GetSubnetInfo; ///< Function of getting 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 EFI_REDFISH_DISCOVERED_INSTANCE. +} EFI_REDFISH_DISCOVERED_INTERNAL_LIST; + +// +// Internal structure of Redfish discover instance. +// +typedef struct { + LIST_ENTRY Entry; ///< Link list entry. + EFI_HANDLE Owner; ///< The owner owns this Redfish service discovery. + ///< It's the EFI image handle of driver uses + ///< EFI Redfish Discover Protocol. + EFI_REDFISH_DISCOVER_FLAG DiscoverFlags; ///< EFI_REDFISH_DISCOVER_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 whether to validate Redfish Host interface. + EFI_IP_ADDRESS TargetIpAddress; ///< Target IP address 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_INSTANCE. + @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 connection. + @retval EFI_SUCCESS Redfish service is added to list successfully. + +**/ +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/RedfishDiscoverDxe/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_PROTOCOL protocol. + for EFI Refish Discover Protocol + + (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR> + + 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 Driver. + + @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + @param[in] Language A pointer to a three-character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + @param[out] DriverName A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER DriverName is NULL. + @retval EFI_UNSUPPORTED The driver specified by This does not support the + language specified by Language. + +**/ +EFI_STATUS +EFIAPI +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 controller + that is being managed by an EFI Driver. + + @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + @param[in] ControllerHandle The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + @param[in] ChildHandle The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + @param[in] Language A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + @param[out] ControllerName A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language specified + by Language, from the point of view of the driver specified + by This. + + @retval EFI_SUCCESS The Unicode string for the user-readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + @retval EFI_UNSUPPORTED The driver specified by This is not currently managing + the controller specified by ControllerHandle and + ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not support the + language specified by Language. + +**/ +EFI_STATUS +EFIAPI +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 = { + RedfishDiscoverComponentNameGetDriverName, + RedfishDiscoverComponentNameGetControllerName, + "eng" +}; + +/// +/// Component Name 2 Protocol instance +/// +GLOBAL_REMOVE_IF_UNREFERENCED +EFI_COMPONENT_NAME2_PROTOCOL gRedfishDiscoverComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) RedfishDiscoverComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) RedfishDiscoverComponentNameGetControllerName, + "en" +}; + +/// +/// Table of driver names +/// +GLOBAL_REMOVE_IF_UNREFERENCED +EFI_UNICODE_STRING_TABLE mRedfishDiscoverDriverNameTable[] = { + { "eng;en", (CHAR16 *)L"Redfish Discover UEFI Driver" }, + { NULL, NULL } +}; + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE *gRedfishDiscoverControllerNameTable = NULL; + +/** + Retrieves a Unicode string that is the user-readable name of the EFI Driver. + + @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + @param[in] Language A pointer to a three-character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + @param[out] DriverName A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER DriverName is NULL. + @retval EFI_UNSUPPORTED The driver specified by This does not support the + language specified by Language. + +**/ +EFI_STATUS +EFIAPI +RedfishDiscoverComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mRedfishDiscoverDriverNameTable, + DriverName, + (BOOLEAN)(This == &gRedfishDiscoverComponentName) + ); +} + +/** + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + @param[in] ControllerHandle The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + @param[in] ChildHandle The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + @param[in] Language A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + @param[out] ControllerName A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language specified + by Language, from the point of view of the driver specified + by This. + + @retval EFI_SUCCESS The Unicode string for the user-readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + @retval EFI_UNSUPPORTED The driver specified by This is not currently managing + the controller specified by ControllerHandle and + ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not support the + language specified by Language. + +**/ +EFI_STATUS +EFIAPI +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/RedfishPkg/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<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "RedfishDiscoverInternal.h" + +LIST_ENTRY mRedfishDiscoverList; +LIST_ENTRY mRedfishInstanceList; +EFI_SMBIOS_PROTOCOL *mSmbios = NULL; + +UINTN mNumNetworkInterface = 0; +UINTN mNumRestExInstance = 0; +LIST_ENTRY mEfiRedfishDiscoverNetworkInterface; +LIST_ENTRY mEfiRedfishDiscoverRestExInstance; + +EFI_GUID mRedfishDiscoverTcp4InstanceGuid = EFI_REDFISH_DISCOVER_TCP4_INSTANCE_GUID; +EFI_GUID mRedfishDiscoverTcp6InstanceGuid = EFI_REDFISH_DISCOVER_TCP6_INSTANCE_GUID; +EFI_GUID mRedfishDiscoverRestExInstanceGuid = EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_GUID; + +EFI_HANDLE EfiRedfishDiscoverProtocolHandle = 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[] = { + { + 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 this owner. + +**/ +EFI_STATUS +CreateRestExInstance ( + IN EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *Instance, + IN EFI_REDFISH_DISCOVERED_TOKEN *Token + ) +{ + EFI_STATUS Status; + + Status = RestExLibCreateChild ( + Instance->Owner, + FixedPcdGetBool (PcdRedfishDiscoverAccessModeInBand)? EfiRestExServiceInBandAccess: EfiRestExServiceOutOfBandAccess, + EfiRestExConfigHttp, + EfiRestExServiceRedfish, + &Token->DiscoverList.RedfishInstances->Information.RedfishRestExHandle + ); + return Status; +} + +/** + This function gets EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE + by known owner handle. + + @param[in] ImageHandle Image handle owns EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE. + @param[in] TargetNetworkInterface Target network interface used by this 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 this owner. + +**/ +EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE * +GetInstanceByOwner ( + IN EFI_HANDLE ImageHandle, + IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *TargetNetworkInterface, + IN EFI_REDFISH_DISCOVER_FLAG DiscoverFlags + ) +{ + EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *ThisInstance; + + if (IsListEmpty (&mRedfishDiscoverList)) { + return NULL; + } + ThisInstance = + (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *)GetFirstNode (&mRedfishDiscoverList); + while (TRUE) { + if ((ThisInstance->Owner == ImageHandle) && + (ThisInstance->DiscoverFlags == DiscoverFlags) && + (ThisInstance->NetworkInterface == TargetNetworkInterface)) { + return ThisInstance; + } + if (IsNodeAtEnd (&mRedfishDiscoverList, &ThisInstance->Entry)) { + break; + } + ThisInstance = + (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *)GetNextNode (&mRedfishDiscoverList, &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 == NULL) { + return EFI_INVALID_PARAMETER; + } + Tcp4 = (EFI_TCP4_PROTOCOL *)Instance->NetworkInterfaceProtocolInfo.NetworkProtocolInterface; + + 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 = TRUE; + Tcp4CfgData.AccessPoint.RemoteAddress.Addr [0] = 127; + Tcp4CfgData.AccessPoint.RemoteAddress.Addr [1] = 0; + Tcp4CfgData.AccessPoint.RemoteAddress.Addr [2] = 0; + Tcp4CfgData.AccessPoint.RemoteAddress.Addr [3] = 1; + Tcp4CfgData.AccessPoint.RemotePort = 80; + Tcp4CfgData.AccessPoint.ActiveFlag = TRUE; + + Tcp4CfgData.ControlOption = &Tcp4Option; + Tcp4Option.ReceiveBufferSize = 65535; + Tcp4Option.SendBufferSize = 65535; + Tcp4Option.MaxSynBackLog = 5; + Tcp4Option.ConnectionTimeout = 60; + Tcp4Option.DataRetries = 12; + Tcp4Option.FinTimeout = 2; + Tcp4Option.KeepAliveProbes = 6; + Tcp4Option.KeepAliveTime = 7200; + Tcp4Option.KeepAliveInterval = 30; + Tcp4Option.EnableNagle = TRUE; + Status = Tcp4->Configure (Tcp4, &Tcp4CfgData); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Can't get subnet information\n", __FUNCTION__)); + return Status; + } + Status = Tcp4->GetModeData (Tcp4, NULL, NULL, &IpModedata, NULL, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Can't get IP mode data information\n", __FUNCTION__)); + return Status; + } + IP4_COPY_ADDRESS (&Instance->SubnetMask, &IpModedata.ConfigData.SubnetMask); + Instance->SubnetAddr.v4.Addr [0] = IpModedata.ConfigData.StationAddress.Addr [0] & Instance->SubnetMask.v4.Addr [0]; + Instance->SubnetAddr.v4.Addr [1] = IpModedata.ConfigData.StationAddress.Addr [1] & Instance->SubnetMask.v4.Addr [1]; + Instance->SubnetAddr.v4.Addr [2] = IpModedata.ConfigData.StationAddress.Addr [2] & Instance->SubnetMask.v4.Addr [2]; + Instance->SubnetAddr.v4.Addr [3] = IpModedata.ConfigData.StationAddress.Addr [3] & Instance->SubnetMask.v4.Addr [3]; + // + // Calculate the subnet mask prefix. + // + GotPrefixLength = FALSE; + PrefixLength = 0; + SubnetMaskIndex = 0; + while (GotPrefixLength == FALSE && SubnetMaskIndex < 4) { + BitMask = 0x80; + while (BitMask != 0) { + if ((Instance->SubnetMask.v4.Addr [SubnetMaskIndex] & BitMask) != 0) { + PrefixLength ++; + } else { + GotPrefixLength = TRUE; + break; + } + BitMask = BitMask >> 1; + }; + SubnetMaskIndex ++; + }; + Instance->SubnetPrefixLength = 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 == NULL) { + return EFI_INVALID_PARAMETER; + } + Tcp6 = (EFI_TCP6_PROTOCOL *)Instance->NetworkInterfaceProtocolInfo.NetworkProtocolInterface; + + Status = 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 == 0) { + DEBUG ((DEBUG_INFO, "%a: No IPv6 address configured.\n")); + } + if (Instance->SubnetAddrInfoIPv6 != NULL) { + FreePool (Instance->SubnetAddrInfoIPv6); + } + Instance->SubnetAddrInfoIPv6 = AllocateZeroPool (IpModedata.AddressCount * sizeof (EFI_IP6_ADDRESS_INFO)); + if (Instance->SubnetAddrInfoIPv6 == NULL) { + DEBUG ((DEBUG_ERROR, "%a: Failed to allocate memory fir IPv6 subnet address information\n")); + return EFI_OUT_OF_RESOURCES; + } + Instance->SubnetAddrInfoIPv6Number = 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_INTERFACE. + NULL for all EFI_REDFISH_DISCOVER_NETWORK_INTERFACEs. + + @retval Non-NULL EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL is returned. + @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 = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface); + while (TRUE) { + if (CompareMem((VOID *)&ThisNetworkInterface->MacAddress, &TargetNetworkInterface->MacAddress, ThisNetworkInterface->HwAddressSize) == 0) { + return ThisNetworkInterface; + } + if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry)) { + return NULL; + } + ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry); + }; + return NULL; +} + +/** + This function validate if target network interface is ready for discovering + Redfish service. + + @param[in] TargetNetworkInterface EFI_REDFISH_DISCOVER_NETWORK_INTERFACE. + NULL for all EFI_REDFISH_DISCOVER_NETWORK_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) && TargetNetworkInterface == NULL) { + return EFI_UNSUPPORTED; + } + if (TargetNetworkInterface == NULL) { + return EFI_SUCCESS; // Return EFI_SUCCESS if no network interface is specified. + } + + ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode(&mEfiRedfishDiscoverNetworkInterface); + while (TRUE) { + if (CompareMem((VOID *)&ThisNetworkInterface->MacAddress, &TargetNetworkInterface->MacAddress, ThisNetworkInterface->HwAddressSize) == 0) { + break; + } + if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry)) { + return EFI_UNSUPPORTED; + } + ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry); + }; + if ((Flags & EFI_REDFISH_DISCOVER_SSDP) != 0) { + // Validate if UDP4/6 is supported on the given network interface. + // SSDP is not supported. + + return EFI_SUCCESS; + } + if (ThisNetworkInterface->NetworkInterfaceProtocolInfo.ProtocolControllerHandle == NULL) { + return EFI_UNSUPPORTED; // The required protocol on this network interface 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 = 1; + ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface); + while (TRUE) { + if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry)) { + break; + } + ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry); + Num ++; + }; + return Num; +} + +/** + This function checks the IP version supported on this + netwoek interface. + + @param[in] ThisNetworkInterface EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL + + @retval TRUE Is IPv6, otherwise IPv4. + +**/ +BOOLEAN +CheckIsIpVersion6 ( + IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterface +) +{ + if (ThisNetworkInterface->NetworkProtocolType == 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 SMBIOS 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 = NULL; + DeviceDescriptor = NULL; + + if (mSmbios == NULL) { + Status = gBS->LocateProtocol(&gEfiSmbiosProtocolGuid, NULL, (VOID **)&mSmbios); + if (EFI_ERROR (Status)) { + return Status; + } + } + Status = RedfishGetHostInterfaceProtocolData (mSmbios, &DeviceDescriptor, &Data); // Search for SMBIOS type 42h + if (!EFI_ERROR (Status) && Data != NULL && DeviceDescriptor != NULL) { + // + // Chceck if we can reach out Redfish service using this network interface. + // Check with MAC address using Device Descroptor Data Device Type 04 and Type 05. + // Those two types of Redfish host interface device has MAC information. + // + if (DeviceDescriptor->DeviceType == REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE_V2) { + MacCompareStstus = CompareMem(&Instance->NetworkInterface->MacAddress, &DeviceDescriptor->DeviceDescriptor.PciPcieDeviceV2.MacAddress, 6); + } else if (DeviceDescriptor->DeviceType == REDFISH_HOST_INTERFACE_DEVICE_TYPE_USB_V2){ + MacCompareStstus = CompareMem(&Instance->NetworkInterface->MacAddress, &DeviceDescriptor->DeviceDescriptor.UsbDeviceV2.MacAddress, 6); + } else { + return EFI_UNSUPPORTED; + } + if (MacCompareStstus != 0) { + return EFI_UNSUPPORTED; + } + + if (Data->RedfishServiceIpAddressFormat == 1) { + IP4_COPY_ADDRESS ((VOID *)&Instance->TargetIpAddress.v4, (VOID *)Data->RedfishServiceIpAddress); + } else { + IP6_COPY_ADDRESS ((VOID *)&Instance->TargetIpAddress.v6, (VOID *)Data->RedfishServiceIpAddress); + } + + if (Instance->HostIntfValidation) { + DEBUG ((DEBUG_ERROR,"%a:Send UPnP unicast SSDP to validate this Redfish Host Interface is not supported.\n", __FUNCTION__)); + Status = EFI_UNSUPPORTED; + } else { + // + // Add this istance to list without detial information of Redfish + // service. + // + IsHttps = FALSE; + if (Data->RedfishServiceIpPort == 443) { + IsHttps = TRUE; + } + StrSize = sizeof(UuidStr); + AsciiSPrint(UuidStr, StrSize, "%g", &Data->ServiceUuid); + // + // Generate Redfish service location string. + // + if (Data->RedfishServiceIpAddressFormat == REDFISH_HOST_INTERFACE_HOST_IP_ADDRESS_FORMAT_IP6) { + NetLibIp6ToStr((IPv6_ADDRESS *)&Data->RedfishServiceIpAddress, Ipv6Str, sizeof (Ipv6Str)); + if (Data->RedfishServiceIpPort == 0 || IsHttps == TRUE) { + AsciiSPrintUnicodeFormat ( + RedfishServiceLocateStr, + sizeof (RedfishServiceLocateStr), + L"%s", + Ipv6Str + ); + } else { + AsciiSPrintUnicodeFormat( + RedfishServiceLocateStr, + sizeof (RedfishServiceLocateStr), + L"[%s]:%d", + Ipv6Str, + Data->RedfishServiceIpPort + ); + } + } else { + if (Data->RedfishServiceIpPort == 0 || IsHttps == 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 = 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_INSTANCE. + @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 connection. + @retval EFI_SUCCESS Redfish service is added to list successfully. + +**/ +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 = TRUE; + InfoRefresh = FALSE; + Char16Uuid = NULL; + RestExOpened = FALSE; + DeleteRestEx = FALSE; + + DEBUG ((DEBUG_INFO,"%a:Add this instance to Redfish instance list.\n", __FUNCTION__)); + + if (Uuid != NULL) { + Char16Uuid = (CHAR16 *)AllocateZeroPool(AsciiStrSize((const CHAR8 *)Uuid) * sizeof(CHAR16)); + AsciiStrToUnicodeStrS ((const CHAR8 *)Uuid, Char16Uuid, AsciiStrSize((const CHAR8 *)Uuid) * sizeof(CHAR16)); + } + DiscoveredList = NULL; + DiscoveredInstance = NULL; + RestExHttpConfigData = NULL; + + NetworkInterface = Instance->NetworkInterface; + if (!IsListEmpty (&mRedfishInstanceList)) { + // + // Is this a duplicate redfish service. + // + DiscoveredList = (EFI_REDFISH_DISCOVERED_INTERNAL_LIST *)GetFirstNode (&mRedfishInstanceList); + NewFound = FALSE; + do { + if (Char16Uuid == NULL || DiscoveredList->Instance->Information.Uuid == NULL) { + // + // Check if this Redfish instance already found using IP addrress. + // + if (!CheckIsIpVersion6(NetworkInterface)) { + if (CompareMem ((VOID *)&Instance->TargetIpAddress.v4, + (VOID *)&DiscoveredList->Instance->Information.RedfishHostIpAddress.v4, + sizeof (EFI_IPv4_ADDRESS) + ) == 0) + { + DiscoveredInstance = DiscoveredList->Instance; + if (DiscoveredList->Instance->Information.Uuid == NULL && + Char16Uuid != NULL) { + InfoRefresh = TRUE; + DiscoveredInstance = DiscoveredList->Instance; + DEBUG((DEBUG_INFO,"*** This Redfish Service information refresh ***\n")); + } + break; + } + } else { + if (CompareMem ((VOID *)&Instance->TargetIpAddress.v6, + (VOID *)&DiscoveredList->Instance->Information.RedfishHostIpAddress.v6, + sizeof (EFI_IPv6_ADDRESS) + ) == 0) + { + DiscoveredInstance = DiscoveredList->Instance; + break; + } + } + } else { + // + // Check if this Redfish instance already found using UUID. + // + if (StrCmp((const CHAR16 *)Char16Uuid, (const CHAR16 *)DiscoveredList->Instance->Information.Uuid) == 0) { + DiscoveredInstance = DiscoveredList->Instance; + break; + } + } + if (IsNodeAtEnd (&mRedfishInstanceList, &DiscoveredList->NextInstance)) { + NewFound = TRUE; + break; + } + DiscoveredList = (EFI_REDFISH_DISCOVERED_INTERNAL_LIST *)GetNextNode (&mRedfishInstanceList, &DiscoveredList->NextInstance); + } while (TRUE); + } + if (NewFound || InfoRefresh) { + if (!InfoRefresh) { + DiscoveredList = (EFI_REDFISH_DISCOVERED_INTERNAL_LIST *)AllocateZeroPool(sizeof(EFI_REDFISH_DISCOVERED_INTERNAL_LIST)); + if (DiscoveredList == NULL) { + return EFI_OUT_OF_RESOURCES; + } + InitializeListHead (&DiscoveredList->NextInstance); + DiscoveredInstance = (EFI_REDFISH_DISCOVERED_INSTANCE *)AllocateZeroPool(sizeof(EFI_REDFISH_DISCOVERED_INSTANCE)); + if (DiscoveredInstance == NULL) { + FreePool ((VOID *)DiscoveredList); + return EFI_OUT_OF_RESOURCES; + } + } + DEBUG ((DEBUG_INFO,"*** Redfish Service Information ***\n")); + + DiscoveredInstance->Information.UseHttps = UseHttps; + if (RedfishVersion != NULL) { + DiscoveredInstance->Information.RedfishVersion = *RedfishVersion; + DEBUG ((DEBUG_INFO,"Redfish service version: %d.\n", DiscoveredInstance->Information.RedfishVersion)); + } + if (RedfishLocation != NULL) { + DiscoveredInstance->Information.Location = (CHAR16 *)AllocatePool(AsciiStrSize((const CHAR8 *)RedfishLocation) * sizeof(CHAR16)); + AsciiStrToUnicodeStrS ((const CHAR8 *)RedfishLocation, DiscoveredInstance->Information.Location, AsciiStrSize((const CHAR8 *)RedfishLocation) * sizeof(CHAR16)); + DEBUG ((DEBUG_INFO,"Redfish service location: %s.\n", DiscoveredInstance->Information.Location)); + } + if (Uuid != NULL) { + DiscoveredInstance->Information.Uuid = (CHAR16 *)AllocatePool(AsciiStrSize((const CHAR8 *)Uuid) * sizeof(CHAR16)); + AsciiStrToUnicodeStrS ((const CHAR8 *)Uuid, DiscoveredInstance->Information.Uuid, AsciiStrSize((const CHAR8 *)Uuid) * sizeof(CHAR16)); + DEBUG ((DEBUG_INFO,"Service UUID: %s.\n", DiscoveredInstance->Information.Uuid)); + } + if (Os != NULL) { + DiscoveredInstance->Information.Os = (CHAR16 *)AllocatePool(AsciiStrSize((const CHAR8 *)Os) * sizeof(CHAR16)); + AsciiStrToUnicodeStrS ((const CHAR8 *)Os, DiscoveredInstance->Information.Os, AsciiStrSize((const CHAR8 *)Os) * sizeof(CHAR16)); + DEBUG ((DEBUG_INFO,"Redfish service OS: %s, Version:%s.\n", DiscoveredInstance->Information.Os, DiscoveredInstance->Information.OsVersion)); + } + if (OsVer != NULL) { + DiscoveredInstance->Information.OsVersion = (CHAR16 *)AllocatePool(AsciiStrSize((const CHAR8 *)OsVer) * sizeof(CHAR16)); + AsciiStrToUnicodeStrS ((const CHAR8 *)OsVer, DiscoveredInstance->Information.OsVersion, AsciiStrSize((const CHAR8 *)OsVer) * sizeof(CHAR16)); + } + if (Product != NULL && ProductVer != NULL) { + DiscoveredInstance->Information.Product = (CHAR16 *)AllocatePool(AsciiStrSize((const CHAR8 *)Product) * sizeof(CHAR16)); + AsciiStrToUnicodeStrS ((const CHAR8 *)Product, DiscoveredInstance->Information.Product, AsciiStrSize((const CHAR8 *)Product) * sizeof(CHAR16)); + DiscoveredInstance->Information.ProductVer = (CHAR16 *)AllocatePool(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", DiscoveredInstance->Information.Product, DiscoveredInstance->Information.ProductVer)); + } + + if (RedfishLocation == NULL) { + // This is the Redfish reported from SMBIOS 42h + // without validation. + + IP4_COPY_ADDRESS((VOID *)&DiscoveredInstance->Information.RedfishHostIpAddress.v4, (VOID *)&Instance->TargetIpAddress.v4); + } + if (!InfoRefresh) { + DiscoveredList->Instance = DiscoveredInstance; + InsertTailList(&mRedfishInstanceList, &DiscoveredList->NextInstance); + } + DiscoveredInstance->Status = EFI_SUCCESS; + } else { + if (DiscoveredList != NULL) { + DEBUG((DEBUG_INFO,"*** This Redfish Service was already found ***\n")); + if (DiscoveredInstance->Information.Uuid != NULL) { + DEBUG((DEBUG_INFO,"Service UUID: %s.\n", DiscoveredInstance->Information.Uuid)); + } else { + DEBUG((DEBUG_INFO,"Service UUID: unknown.\n")); + } + } + } + if (Char16Uuid != NULL) { + FreePool((VOID *)Char16Uuid); + } + + Status = EFI_SUCCESS; + if (NewFound || InfoRefresh) { + // + // Build up EFI_REDFISH_DISCOVERED_LIST in token. + // + Instance->DiscoverToken->DiscoverList.NumberOfServiceFound = 1; + Instance->DiscoverToken->DiscoverList.RedfishInstances = DiscoveredInstance; + DiscoveredInstance->Status = EFI_SUCCESS; + if (!InfoRefresh) { + Status = 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 = 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 = TRUE; + goto ERROR_EXIT; + } + RestExOpened = TRUE; + RestExHttpConfigData = AllocateZeroPool (sizeof (EFI_REST_EX_HTTP_CONFIG_DATA)); + if (RestExHttpConfigData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + DeleteRestEx = TRUE; + goto EXIT_FREE_CONFIG_DATA; + } + RestExHttpConfigData->SendReceiveTimeout = 5000; + RestExHttpConfigData->HttpConfigData.HttpVersion = HttpVersion11; + RestExHttpConfigData->HttpConfigData.LocalAddressIsIPv6 = CheckIsIpVersion6(NetworkInterface); + if (RestExHttpConfigData->HttpConfigData.LocalAddressIsIPv6) { + RestExHttpConfigData->HttpConfigData.AccessPoint.IPv6Node = AllocateZeroPool (sizeof (EFI_HTTPv6_ACCESS_POINT)); + if (RestExHttpConfigData->HttpConfigData.AccessPoint.IPv6Node == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto EXIT_FREE_CONFIG_DATA; + } + } else { + RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node = AllocateZeroPool (sizeof (EFI_HTTPv4_ACCESS_POINT)); + if (RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto EXIT_FREE_CONFIG_DATA; + } + RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node->UseDefaultAddress = TRUE; + } + Status = RestEx->Configure ( + RestEx, + (EFI_REST_EX_CONFIG_DATA)(UINT8 *)RestExHttpConfigData + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR,"%a:REST EX configured..\n", __FUNCTION__)); + DeleteRestEx = TRUE; + goto EXIT_FREE_ALL; + } + // + // Signal client, close REST EX before signaling client. + // + if (RestExOpened) { + gBS->CloseProtocol( + Instance->DiscoverToken->DiscoverList.RedfishInstances->Information.RedfishRestExHandle, + &gEfiRestExProtocolGuid, + Instance->NetworkInterface->OpenDriverAgentHandle, + Instance->NetworkInterface->OpenDriverControllerHandle + ); + RestExOpened = FALSE; + } + } + Status = gBS->SignalEvent(Instance->DiscoverToken->Event); + if (!EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR,"%a:No event to signal!\n", __FUNCTION__)); + } + } + +EXIT_FREE_ALL:; + if (RestExHttpConfigData != NULL && RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node != NULL) { + FreePool (RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node); + } + +EXIT_FREE_CONFIG_DATA:; + if (RestExHttpConfigData != NULL) { + FreePool((VOID *)RestExHttpConfigData); + } + if (RestExOpened) { + gBS->CloseProtocol( + Instance->DiscoverToken->DiscoverList.RedfishInstances->Information.RedfishRestExHandle, + &gEfiRestExProtocolGuid, + Instance->NetworkInterface->OpenDriverAgentHandle, + Instance->NetworkInterface->OpenDriverControllerHandle + ); + } +ERROR_EXIT:; + if (DeleteRestEx && RestExOpened) { + gBS->CloseProtocol( + Instance->DiscoverToken->DiscoverList.RedfishInstances->Information.RedfishRestExHandle, + &gEfiRestExProtocolGuid, + Instance->NetworkInterface->OpenDriverAgentHandle, + Instance->NetworkInterface->OpenDriverControllerHandle + ); + } +ON_EXIT:; + return Status; +} + +/** + This function gets the subnet information of this network interface instance. + can discover Redfish service on it. + + @param[in] Instance EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL instance. + @param[in] ImageHandle EFI Image handle request the network interface 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 = Instance->NetworkProtocolType; + if (gRequiredProtocol [ProtocolType].GetSubnetInfo != NULL && Instance->GotSubnetInfo == FALSE) { + Status = gRequiredProtocol [ProtocolType].GetSubnetInfo ( + ImageHandle, + Instance + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR,"%a:Faile to get Subnet infomation.\n", __FUNCTION__)); + return Status; + } else { + DEBUG ((DEBUG_INFO,"%a:MAC address: %s\n", __FUNCTION__, Instance->StrMacAddr)); + if (CheckIsIpVersion6 (Instance)) { + if (Instance->SubnetAddrInfoIPv6Number == 0) { + DEBUG ((DEBUG_ERROR,"%a: There is no Subnet infomation for IPv6 network interface.\n", __FUNCTION__)); + return EFI_NOT_FOUND; + } + ThisSubnetAddrInfoIPv6 = Instance->SubnetAddrInfoIPv6; // First IPv6 address information. + IP6_COPY_ADDRESS (&Instance->SubnetAddr.v6, &ThisSubnetAddrInfoIPv6->Address); + Instance->SubnetPrefixLength = ThisSubnetAddrInfoIPv6->PrefixLength; + DEBUG((DEBUG_INFO," IPv6 Subnet ID:%d, Prefix length: %d.\n", + ThisSubnetAddrInfoIPv6->Address.Addr [7] + (UINT16)ThisSubnetAddrInfoIPv6->Address.Addr [6] * 256, + ThisSubnetAddrInfoIPv6->PrefixLength) + ); + // + // If this is IPv6, then we may have to propagate network interface for IPv6 network scopes + // according to the Ipv6 address information. + // + ThisSubnetAddrInfoIPv6 ++; + for (IPv6InfoIndex = 0; IPv6InfoIndex < Instance->SubnetAddrInfoIPv6Number - 1; IPv6InfoIndex++) { + // + // Build up addtional EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL instances. + // + NewNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL)); + if (NewNetworkInterface != NULL) { + CopyMem ((VOID *)NewNetworkInterface, (VOID *)Instance, sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL)); // Clone information of first instance. + IP6_COPY_ADDRESS (&NewNetworkInterface->SubnetAddr.v6, &ThisSubnetAddrInfoIPv6->Address); + NewNetworkInterface->SubnetPrefixLength = ThisSubnetAddrInfoIPv6->PrefixLength; + NewNetworkInterface->GotSubnetInfo = TRUE; + InsertTailList (&mEfiRedfishDiscoverNetworkInterface, &NewNetworkInterface->Entry); + ThisSubnetAddrInfoIPv6 ++; + mNumNetworkInterface ++; + DEBUG((DEBUG_INFO," IPv6 Subnet ID:%d, Prefix length: %d.\n", + ThisSubnetAddrInfoIPv6->Address.Addr [7] + (UINT16)ThisSubnetAddrInfoIPv6->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 = TRUE; // Only try to get Subnet Info once. + return EFI_SUCCESS; +} + +/** + This function gets the network interface list which Redfish discover protocol + can discover Redfish service on it. + + @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instance. + @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 NumberOfNetworkIntfs. + Caller has to release the memory + allocated by Redfish discover protocol. + + @retval EFI_SUCCESS The information of network interface is returned in NumberOfNetworkIntfs and + NetworkIntfInstances. + @retval Others Fail to return the information of network interface. + +**/ +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 *ThisNetworkInterfaceIntn; + EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *ThisNetworkInterface; + + if (NetworkIntfInstances == NULL || NumberOfNetworkIntfs == NULL || ImageHandle == NULL) { + return EFI_INVALID_PARAMETER; + } + + *NumberOfNetworkIntfs = 0; + *NetworkIntfInstances = NULL; + + if (IsListEmpty ((const LIST_ENTRY*)&mEfiRedfishDiscoverNetworkInterface)) { + return EFI_NOT_FOUND; + } + + ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE) * mNumNetworkInterface); + if (ThisNetworkInterface == NULL) { + return EFI_OUT_OF_RESOURCES; + } + *NetworkIntfInstances = ThisNetworkInterface; + ThisNetworkInterfaceIntn = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface); + while (TRUE) { + ThisNetworkInterface->IsIpv6 = FALSE; + if (CheckIsIpVersion6 (ThisNetworkInterfaceIntn)) { + ThisNetworkInterface->IsIpv6 = TRUE; + } + CopyMem((VOID *)&ThisNetworkInterface->MacAddress, &ThisNetworkInterfaceIntn->MacAddress, ThisNetworkInterfaceIntn->HwAddressSize); + NetworkInterfaceGetSubnetInfo(ThisNetworkInterfaceIntn, ImageHandle); // Get subnet info. + if (!ThisNetworkInterface->IsIpv6) { + IP4_COPY_ADDRESS(&ThisNetworkInterface->SubnetId.v4, &ThisNetworkInterfaceIntn->SubnetAddr.v4); // IPv4 subnet information. + } else { + IP6_COPY_ADDRESS (&ThisNetworkInterface->SubnetId.v6, &ThisNetworkInterfaceIntn->SubnetAddr.v6); // IPv6 subnet information in IPv6 address information. + } + ThisNetworkInterface->SubnetPrefixLength = ThisNetworkInterfaceIntn->SubnetPrefixLength; + ThisNetworkInterface->VlanId = ThisNetworkInterfaceIntn->VlanId; + (*NumberOfNetworkIntfs) ++; + if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterfaceIntn->Entry)) { + break; + } + ThisNetworkInterfaceIntn = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterfaceIntn->Entry); + ThisNetworkInterface ++; + }; + return EFI_SUCCESS; +} +/** + This function acquires Redfish services by discovering static Redfish setting + according to Redfish Host Interface or through SSDP. Returns a list of EFI + handles in EFI_REDFISH_DISCOVERED_LIST. Each of EFI handle has cooresponding + EFI REST EX instance installed on it. Each REST EX isntance is a child instance which + created through EFI REST EX serivce protoocl for communicating with specific + Redfish service. + + @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instance. + @param[in] ImageHandle EFI image owns these Redfish service instances. + @param[in] TargetNetworkInterface Target network interface to do the discovery. + NULL means discover Redfish service on all network interfaces on platform. + @param[in] Flags Redfish service discover flags. + @param[in] Token EFI_REDFISH_DISCOVERED_TOKEN instance. + The memory of EFI_REDFISH_DISCOVERED_LIST and the strings in + EFI_REDFISH_DISCOVERED_INFORMATION are all allocated by Acquire() + and must be freed when caller invoke Release(). + + @retval EFI_SUCCESS REST EX instance of discovered Redfish services are returned. + @retval EFI_INVALID_PARAMETERS ImageHandle == NULL, Flags == 0, Token == NULL, Token->Timeout > 5, + or Token->Event == 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 *TargetNetworkInterfaceInternal; + + DEBUG ((DEBUG_INFO,"%a:Entry.\n", __FUNCTION__)); + + // + // Validate parameters. + // + if (ImageHandle == NULL || Token == NULL || ((Flags & ~EFI_REDFISH_DISCOVER_VALIDATION) == 0)) { + DEBUG ((DEBUG_ERROR,"%a:Invalid parameters.\n", __FUNCTION__)); + return EFI_INVALID_PARAMETER; + } + // + // Validate target network interface. + // + if (EFI_ERROR (ValidateTargetNetworkInterface (TargetNetworkInterface, Flags))) { + return EFI_UNSUPPORTED; + } + if (TargetNetworkInterface != NULL) { + TargetNetworkInterfaceInternal = GetTargetNetworkInterfaceInternal (TargetNetworkInterface); + NumNetworkInterfaces = 1; + } else { + TargetNetworkInterfaceInternal = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface); + NumNetworkInterfaces = NumberOfNetworkInterface (); + if (NumNetworkInterfaces == 0) { + DEBUG ((DEBUG_ERROR,"%a:No network interface on platform.\n", __FUNCTION__)); + return EFI_UNSUPPORTED; + } + } + for (NetworkInterfacesIndex = 0; NetworkInterfacesIndex < NumNetworkInterfaces; NetworkInterfacesIndex ++) { + Status1 = EFI_SUCCESS; + Status2 = EFI_SUCCESS; + NewInstance = FALSE; + Instance = GetInstanceByOwner (ImageHandle, TargetNetworkInterfaceInternal, Flags & ~EFI_REDFISH_DISCOVER_VALIDATION); // Check if we can re-use previous instance. + if (Instance == NULL) { + DEBUG ((DEBUG_INFO,"%a:Create new EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE.\n", __FUNCTION__)); + Instance = (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *)AllocateZeroPool(sizeof(EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE)); + if (Instance == NULL) { + DEBUG ((DEBUG_ERROR,"%a:Memory allocation fail.\n", __FUNCTION__)); + } + InitializeListHead (&Instance->Entry); + Instance->Owner = ImageHandle; + Instance->DiscoverFlags = Flags & ~EFI_REDFISH_DISCOVER_VALIDATION; + Instance->NetworkInterface = TargetNetworkInterfaceInternal; + // + // Get subnet information in case subnet information is not set because + // RedfishServiceGetNetworkInterfaces hasn't been called yet. + // + NetworkInterfaceGetSubnetInfo (TargetNetworkInterfaceInternal, ImageHandle); + NewInstance = TRUE; + } + if (TargetNetworkInterfaceInternal->StrMacAddr != NULL) { + DEBUG((DEBUG_INFO,"%a:Acquire Redfish service on network interface MAC address:%s.\n", __FUNCTION__, TargetNetworkInterfaceInternal->StrMacAddr)); + } else { + DEBUG((DEBUG_INFO,"%a:WARNING: No MAC address on this network interface.\n", __FUNCTION__)); + } + + Instance->DiscoverToken = Token; // Always use the latest Token passed by caller. + if ((Flags & EFI_REDFISH_DISCOVER_HOST_INTERFACE) != 0) { + DEBUG ((DEBUG_INFO,"%a:Redfish HOST interface discovery.\n", __FUNCTION__)); + Instance->HostIntfValidation = FALSE; + if ((Flags & EFI_REDFISH_DISCOVER_VALIDATION) != 0) { + Instance->HostIntfValidation = TRUE; + } + Status1 = DiscoverRedfishHostInterface (Instance); // Discover Redfish service through Redfish Host Interface. + } + if ((Flags & EFI_REDFISH_DISCOVER_SSDP) != 0) { + DEBUG ((DEBUG_ERROR,"%a:Redfish service discovery through SSDP is not 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 discovery Status1=%x, Status2=%x.\n", __FUNCTION__, Status1, Status2)); + } else { + if (NewInstance) { + InsertTailList(&mRedfishDiscoverList, &Instance->Entry); + } + } + } + if (TargetNetworkInterface == NULL) { + // + // Discover Redfish services on all of network interfaces. + // + TargetNetworkInterfaceInternal = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, &TargetNetworkInterfaceInternal->Entry); + } + } + return EFI_SUCCESS; +} + +/** + This function aborts Redfish service discovery on the given network interface. + + @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instance. + @param[in] TargetNetworkInterface Target network interface to do the discovery. + + @retval EFI_SUCCESS REST EX instance of discovered Redfish services 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 OPTIONAL +) +{ + // 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 released. + @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", __FUNCTION__)); + return EFI_NOT_FOUND; + } + AnyFailRelease = FALSE; + ThisRedfishInstance = InstanceList->RedfishInstances; + for (NumService = 0; NumService < InstanceList->NumberOfServiceFound; NumService ++) { + DiscoveredRedfishInstance = (EFI_REDFISH_DISCOVERED_INTERNAL_LIST *)GetFirstNode(&mRedfishInstanceList); + do { + if (DiscoveredRedfishInstance->Instance == ThisRedfishInstance) { + RemoveEntryList (&DiscoveredRedfishInstance->NextInstance); + if (ThisRedfishInstance->Information.Location != NULL) { + FreePool (ThisRedfishInstance->Information.Location); + } + if (ThisRedfishInstance->Information.Uuid != NULL) { + FreePool (ThisRedfishInstance->Information.Uuid); + } + if (ThisRedfishInstance->Information.Os != NULL) { + FreePool (ThisRedfishInstance->Information.Os); + } + if (ThisRedfishInstance->Information.OsVersion != NULL) { + FreePool (ThisRedfishInstance->Information.OsVersion); + } + if (ThisRedfishInstance->Information.Product != NULL) { + FreePool (ThisRedfishInstance->Information.Product); + } + if (ThisRedfishInstance->Information.ProductVer != NULL) { + FreePool (ThisRedfishInstance->Information.ProductVer); + } + FreePool((VOID *)ThisRedfishInstance); + goto ReleaseNext; + } + + if (IsNodeAtEnd(&mRedfishInstanceList, &DiscoveredRedfishInstance->NextInstance)) { + break; + } + DiscoveredRedfishInstance = (EFI_REDFISH_DISCOVERED_INTERNAL_LIST *)GetNextNode(&mRedfishInstanceList, &DiscoveredRedfishInstance->NextInstance); + } while (TRUE); + AnyFailRelease = TRUE; +ReleaseNext:; + // + // Release next discovered Redfish Service. + // + ThisRedfishInstance = (EFI_REDFISH_DISCOVERED_INSTANCE *)((UINT8 *)ThisRedfishInstance + sizeof (EFI_REDFISH_DISCOVERED_INSTANCE)); + } + if (AnyFailRelease) { + return EFI_NOT_FOUND; + } else { + return EFI_SUCCESS; + } +} + +EFI_REDFISH_DISCOVER_PROTOCOL mRedfishDiscover = { + 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_NETWORK_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 = NULL; + *IsNewInstance = TRUE; + if (!IsListEmpty ((const LIST_ENTRY*)&mEfiRedfishDiscoverNetworkInterface)) { + // + // Check if this instance already exist. + // + ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface); + if (ThisNetworkInterface != NULL) { + while (TRUE) { + if ((CompareMem ((CONST VOID *)&ThisNetworkInterface->MacAddress.Addr, (CONST VOID *)&MacAddress.Addr, HwAddressSize) == 0) && + (ThisNetworkInterface->NetworkProtocolType == NetworkProtocolType)){ + NewNetworkInterface = ThisNetworkInterface; + *IsNewInstance = FALSE; + break; + } + if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry)) { + NewNetworkInterface = NULL; + break; + } + ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry); + }; + } + } + if (NewNetworkInterface == NULL) { + // + // Create a new instance. + // + NewNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL)); + if (NewNetworkInterface == NULL) { + return EFI_OUT_OF_RESOURCES; + } + NewNetworkInterface->HwAddressSize = HwAddressSize; + CopyMem (&NewNetworkInterface->MacAddress.Addr, &MacAddress.Addr, NewNetworkInterface->HwAddressSize); + NetLibGetMacString (ControllerHandle, NULL, &NewNetworkInterface->StrMacAddr); + NewNetworkInterface->VlanId = NetLibGetVlanId (ControllerHandle); + } + *NetworkInterface = 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 = gBS->UninstallProtocolInterface( + ThisNetworkInterface->OpenDriverControllerHandle, + gRequiredProtocol [ThisNetworkInterface->NetworkProtocolType].DiscoveredProtocolGuid, + &ThisNetworkInterface->NetworkInterfaceProtocolInfo.ProtocolDiscoverId + ); + 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_PROTOCOL instance. + @param[in] ControllerHandle The handle of the controller to test. This handle + must support a protocol interface that supplies + an I/O abstraction to the driver. + @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 = 0; Index < (sizeof (gRequiredProtocol) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL)); Index ++) { + Status = gBS->OpenProtocol ( + ControllerHandle, + gRequiredProtocol [Index].RequiredServiceBindingProtocolGuid, + NULL, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + Status = 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_PROTOCOL instance. + @param[in] ControllerHandle The handle of the controller to test. This handle + must support a protocol interface that supplies + an I/O abstraction to the driver. + @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 = FALSE; + Index = 0; + do { + Status = 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 == (sizeof(gRequiredProtocol) / sizeof(REDFISH_DISCOVER_REQUIRED_PROTOCOL))) { + break; + } + continue; + } + + Status = gBS->OpenProtocol ( + ControllerHandle, + gRequiredProtocol [Index].RequiredServiceBindingProtocolGuid, + &TempInterface, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + Index ++; + if (Index == (sizeof(gRequiredProtocol) / sizeof(REDFISH_DISCOVER_REQUIRED_PROTOCOL))) { + break; + } + continue; + } + if (gRequiredProtocol [Index].ProtocolType != ProtocolTypeRestEx) { + OldTpl = gBS->RaiseTPL (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL); + Status = CreateRedfishDiscoverNetworkInterface(ControllerHandle, gRequiredProtocol [Index].ProtocolType, &IsNew, &NetworkInterface); + if (EFI_ERROR (Status)) { + gBS->RestoreTPL (OldTpl); + return Status; + } + NetworkInterface->NetworkProtocolType = gRequiredProtocol [Index].ProtocolType; + NetworkInterface->OpenDriverAgentHandle = This->DriverBindingHandle; + NetworkInterface->OpenDriverControllerHandle = ControllerHandle; + NetworkInterface->NetworkInterfaceProtocolInfo.ProtocolGuid = \ + *gRequiredProtocol [Index].RequiredProtocolGuid; + NetworkInterface->NetworkInterfaceProtocolInfo.ProtocolServiceGuid = \ + *gRequiredProtocol [Index].RequiredServiceBindingProtocolGuid; + ProtocolDiscoverIdPtr = &NetworkInterface->NetworkInterfaceProtocolInfo.ProtocolDiscoverId; + OpenDriverAgentHandle = NetworkInterface->OpenDriverAgentHandle; + OpenDriverControllerHandle = NetworkInterface->OpenDriverControllerHandle; + HandleOfProtocolInterfacePtr = &NetworkInterface->NetworkInterfaceProtocolInfo.ProtocolControllerHandle; + Interface = &NetworkInterface->NetworkInterfaceProtocolInfo.NetworkProtocolInterface; + NewNetworkInterfaceInstalled = TRUE; + if (IsNew) { + InsertTailList (&mEfiRedfishDiscoverNetworkInterface, &NetworkInterface->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 corresponding EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL + // when discovery. + + RestExInstance = (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL *)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL)); + if (RestExInstance == NULL) { + return EFI_OUT_OF_RESOURCES; + } + RestExInstance->OpenDriverAgentHandle = This->DriverBindingHandle; + RestExInstance->OpenDriverControllerHandle = ControllerHandle; + RestExInstance->RestExControllerHandle = ControllerHandle; + InitializeListHead (&RestExInstance->Entry); + InsertTailList (&mEfiRedfishDiscoverRestExInstance, &RestExInstance->Entry); + mNumRestExInstance ++; + ProtocolDiscoverIdPtr = &RestExInstance->RestExId; + OpenDriverAgentHandle = RestExInstance->OpenDriverAgentHandle; + OpenDriverControllerHandle = RestExInstance->OpenDriverControllerHandle; + HandleOfProtocolInterfacePtr = &RestExInstance->RestExChildHandle; + Interface = (VOID **)&RestExInstance->RestExProtocolInterface; + } + Status = gBS->InstallProtocolInterface ( + &ControllerHandle, + gRequiredProtocol [Index].DiscoveredProtocolGuid, + EFI_NATIVE_INTERFACE, + ProtocolDiscoverIdPtr + ); + if (EFI_ERROR (Status)) { + Index ++; + if (Index == (sizeof(gRequiredProtocol) / sizeof(REDFISH_DISCOVER_REQUIRED_PROTOCOL))) { + break; + } + continue; + } + // + // Create service binding child and open it BY_DRIVER. + // + Status = NetLibCreateServiceChild ( + ControllerHandle, + This->ImageHandle, + gRequiredProtocol [Index].RequiredServiceBindingProtocolGuid, + HandleOfProtocolInterfacePtr + ); + if (!EFI_ERROR (Status)) { + Status = gBS->OpenProtocol ( + *HandleOfProtocolInterfacePtr, + gRequiredProtocol [Index].RequiredProtocolGuid, + Interface, + OpenDriverAgentHandle, + OpenDriverControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (!EFI_ERROR (Status)) { + if (EfiRedfishDiscoverProtocolHandle == NULL && + (gRequiredProtocol [Index].ProtocolType == ProtocolTypeRestEx) && + !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 = gBS->InstallProtocolInterface ( + &EfiRedfishDiscoverProtocolHandle, + &gEfiRedfishDiscoverProtocolGuid, + EFI_NATIVE_INTERFACE, + (VOID *)&mRedfishDiscover + ); + } else if (EfiRedfishDiscoverProtocolHandle != NULL && NewNetworkInterfaceInstalled) { + Status = gBS->ReinstallProtocolInterface ( + EfiRedfishDiscoverProtocolHandle, + &gEfiRedfishDiscoverProtocolGuid, + (VOID *)&mRedfishDiscover, + (VOID *)&mRedfishDiscover + ); + NewNetworkInterfaceInstalled = FALSE; + } + } + return Status; + } else { + Index ++; + if (Index == (sizeof(gRequiredProtocol) / sizeof(REDFISH_DISCOVER_REQUIRED_PROTOCOL))) { + break; + } + continue; + } + } while (Index < (sizeof(gRequiredProtocol) / sizeof(REDFISH_DISCOVER_REQUIRED_PROTOCOL))); + return EFI_UNSUPPORTED; +} +/** + Close the protocol opened for Redfish discovery. This function also destories + 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 that supplies + an I/O abstraction to the driver. + @param[in] ThisRequiredProtocol Pointer to the instance of REDFISH_DISCOVER_REQUIRED_PROTOCOL. + @param[in] DriverAgentHandle Driver agent handle which used to open protocol earlier. + @param[in] DriverControllerHandle Driver controller handle which used to 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 = 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_PROTOCOL instance. + @param[in] ControllerHandle The handle of the controller to test. This handle + must support a protocol interface that supplies + an I/O abstraction to the driver. + @retval EFI_SUCCESS One of required protocol is found. + @retval Others Faile to stop the services on network interface. +**/ +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 = 0; Index < (sizeof (gRequiredProtocol) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL)); Index ++) { + Status = gBS->HandleProtocol ( + ControllerHandle, + gRequiredProtocol [Index].RequiredProtocolGuid, + (VOID **)&Interface + ); + if (!EFI_ERROR (Status)) { + if (gRequiredProtocol [Index].ProtocolType != ProtocolTypeRestEx) { + if (IsListEmpty (&mEfiRedfishDiscoverNetworkInterface)) { + return EFI_NOT_FOUND; + } + OldTpl = gBS->RaiseTPL (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL); + ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface); + while (TRUE) { + if (ThisNetworkInterface->NetworkInterfaceProtocolInfo.ProtocolControllerHandle == ControllerHandle) { + + Status = CloseProtocolService ( // Close protocol and destroy service. + ThisBindingProtocol, + ControllerHandle, + &gRequiredProtocol [Index], + ThisNetworkInterface->OpenDriverAgentHandle, + ThisNetworkInterface->OpenDriverControllerHandle + ); + if (!EFI_ERROR (Status)) { + Status = DestroyRedfishNetwrokInterface (ThisNetworkInterface); + } + gBS->RestoreTPL (OldTpl); + // Reinstall Redfish Discover protocol to notify network + // interface change. + + Status = gBS->ReinstallProtocolInterface ( + EfiRedfishDiscoverProtocolHandle, + &gEfiRedfishDiscoverProtocolGuid, + (VOID *)&mRedfishDiscover, + (VOID *)&mRedfishDiscover + ); + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "%a: Reinstall gEfiRedfishDiscoverProtocolGuid fail.", __FUNCTION__)); + } + return Status; + } + if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry)) { + break; + } + ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry); + }; + gBS->RestoreTPL (OldTpl); + } else { + if (IsListEmpty (&mEfiRedfishDiscoverRestExInstance)) { + return EFI_NOT_FOUND; + } + OldTpl = gBS->RaiseTPL (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL); + RestExInstance = (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverRestExInstance); + while (TRUE) { + if (RestExInstance->RestExChildHandle == ControllerHandle) { + Status = 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, &RestExInstance->Entry)) { + break; + } + RestExInstance = (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL *)GetNextNode(&mEfiRedfishDiscoverRestExInstance, &RestExInstance->Entry); + }; + gBS->RestoreTPL (OldTpl); + } + } + } + return EFI_NOT_FOUND; +} +/** + Tests to see if this driver supports a given controller. If a child device is provided, + it further tests to see if this driver supports creating a handle for the specified child device. + + This function checks to see if the driver specified by This supports the device specified by + ControllerHandle. Drivers will typically use the device path attached to + ControllerHandle and/or the services from the bus I/O abstraction attached to + ControllerHandle to determine if the driver supports ControllerHandle. This function + may be called many times during platform initialization. In order to reduce boot times, the tests + performed by this function must be very small, and take as little time as possible to execute. This + function must not change the state of any hardware devices, and this function must be aware that the + device specified by ControllerHandle may already be managed by the same driver or a + different driver. This function must match its calls to AllocatePages() with FreePages(), + AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol(). + Because ControllerHandle may have been previously started by the same driver, if a protocol is + already in the opened state, then it must not be closed with CloseProtocol(). This is required + to guarantee the state of ControllerHandle is not modified by this function. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] ControllerHandle The handle of the controller to test. This handle + must support a protocol interface that supplies + an I/O abstraction to the driver. + @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This + parameter is ignored by device drivers, and is optional for bus + drivers. For bus drivers, if this parameter is not NULL, then + the bus driver must determine if the bus controller specified + by ControllerHandle and the child controller specified + by RemainingDevicePath are both supported by this + bus driver. + + @retval EFI_SUCCESS The device specified by ControllerHandle and + RemainingDevicePath is supported by the driver specified by This. + @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and + RemainingDevicePath is already being managed by the driver + specified by This. + @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and + RemainingDevicePath is already being managed by a different + driver or an application that requires exclusive access. + Currently not implemented. + @retval EFI_UNSUPPORTED The device specified by ControllerHandle and + RemainingDevicePath is not supported by the driver specified by This. +**/ +EFI_STATUS +EFIAPI +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 behavior will not be deterministic. + 1. ControllerHandle must be a valid EFI_HANDLE. + 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned + EFI_DEVICE_PATH_PROTOCOL. + 3. Prior to calling Start(), the Supported() function for the driver specified by This must + have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] ControllerHandle The handle of the controller to start. This handle + must support a protocol interface that supplies + an I/O abstraction to the driver. + @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This + parameter is ignored by device drivers, and is optional for bus + drivers. For a bus driver, if this parameter is NULL, then handles + for all the children of Controller are created by this driver. + If this parameter is not NULL and the first Device Path Node is + not the End of Device Path Node, then only the handle for the + child device specified by the first Device Path Node of + RemainingDevicePath is created by this driver. + If the first Device Path Node of RemainingDevicePath is + the End of Device Path Node, no child handle is created by this + driver. + + @retval EFI_SUCCESS The device was started. + @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval Others The driver failded to start the device. + +**/ +EFI_STATUS +EFIAPI +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 locations, + but the following calling restrictions must be followed, or the system behavior will not be deterministic. + 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this + same driver's Start() function. + 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid + EFI_HANDLE. In addition, all of these handles must have been created in this driver's + Start() function, and the Start() function must have called OpenProtocol() on + ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] ControllerHandle A handle to the device being stopped. The handle must + support a bus specific I/O protocol for the driver + to use to stop the device. + @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer. + @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL + if NumberOfChildren is 0. + + @retval EFI_SUCCESS The device was stopped. + @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. + +**/ +EFI_STATUS +EFIAPI +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 = { + 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 = EFI_SUCCESS; + InitializeListHead (&mRedfishDiscoverList); + InitializeListHead (&mRedfishInstanceList); + InitializeListHead (&mEfiRedfishDiscoverNetworkInterface); + InitializeListHead (&mEfiRedfishDiscoverRestExInstance); + // + // Install binding protoocl to obtain UDP and REST EX protocol. + // + Status = 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 the 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 = EFI_SUCCESS; + // Destroy all network interfaces found by EFI Redfish Discover driver and + // stop services created for Redfish Discover. + + while (!IsListEmpty (&mEfiRedfishDiscoverNetworkInterface)) { + ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface); + StopServiceOnNetworkInterface (&gRedfishDiscoverDriverBinding, ThisNetworkInterface->NetworkInterfaceProtocolInfo.ProtocolControllerHandle); + }; + // Disconnect EFI Redfish discover driver controller to notify the + // clinet which uses .EFI Redfish discover protocol. + + if (EfiRedfishDiscoverProtocolHandle != NULL) { + // + // Notify user EFI_REDFISH_DISCOVER_PROTOCOL is unloaded. + // + gBS->DisconnectController (EfiRedfishDiscoverProtocolHandle, NULL, NULL); + Status = gBS->UninstallProtocolInterface( + EfiRedfishDiscoverProtocolHandle, + &gEfiRedfishDiscoverProtocolGuid, + (VOID *)&mRedfishDiscover + ); + } + return Status; +} diff --git a/RedfishPkg/RedfishDiscoverDxe/RedfishSmbiosHostInterface.c b/RedfishPkg/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<BR> + + 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 == NULL) || (ProtocolData == NULL)) { + return EFI_INVALID_PARAMETER; + } + + SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; + Status = Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, NULL); + while (!EFI_ERROR (Status) && SmbiosHandle != SMBIOS_HANDLE_PI_RESERVED) { + if (Record->Type == SMBIOS_TYPE_MANAGEMENT_CONTROLLER_HOST_INTERFACE) { + // + // Check Interface Type, should be Network Host Interface = 40h + // + mType42Record = (SMBIOS_TABLE_TYPE42 *) Record; + if (mType42Record->InterfaceType == MCHostInterfaceTypeNetworkHostInterface) { + ASSERT (Record->Length >= 9); + Offset = 5; + RecordTmp = (UINT8 *) Record + Offset; + // + // Get interface specific data length. + // + SpecificDataLen = *RecordTmp; + Offset += 1; + RecordTmp = (UINT8 *) Record + Offset; + + // + // Check Device Type, only PCI/PCIe Network Interface v2 is supported now. + // + if (*RecordTmp == REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE_V2) { + ASSERT (SpecificDataLen == sizeof (PCI_OR_PCIE_INTERFACE_DEVICE_DESCRIPTOR_V2) + 1); + *DeviceDescriptor = (REDFISH_INTERFACE_DATA *)RecordTmp; + Offset = Offset + SpecificDataLen; + RecordTmp = (UINT8 *) Record + Offset; + // + // Check Protocol count. if > 1, only use the first protocol. + // + ASSERT (*RecordTmp == 1); + Offset += 1; + RecordTmp = (UINT8 *) Record + Offset; + // + // Check protocol identifier. + // + if (*RecordTmp == MCHostInterfaceProtocolTypeRedfishOverIP) { + Offset += 1; + RecordTmp = (UINT8 *) Record + Offset; + ProtocolLength = *RecordTmp; + + Offset += 1; + RecordTmp = (UINT8 *) Record + Offset; + + // + // This SMBIOS record is invalid, if the length of protocol specific data for + // Redfish Over IP protocol is wrong. + // + if ((*(RecordTmp + 90) + sizeof (REDFISH_OVER_IP_PROTOCOL_DATA) - 1) != ProtocolLength) { + return EFI_SECURITY_VIOLATION; + } + + Offset += ProtocolLength; + // + // This SMBIOS record is invalid, if the length is smaller than the offset. + // + if (Offset > mType42Record->Hdr.Length) { + return EFI_SECURITY_VIOLATION; + } + *ProtocolData = (REDFISH_OVER_IP_PROTOCOL_DATA *)RecordTmp; + return EFI_SUCCESS; + } + } + } + } + Status = Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, NULL); + } + + *ProtocolData = NULL; + return EFI_NOT_FOUND; +} -- 2.17.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#73933): https://edk2.groups.io/g/devel/message/73933 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] -=-=-=-=-=-=-=-=-=-=-=-
© 2016 - 2024 Red Hat, Inc.