* [PATCH] RedfishPkg/RedfishDiscoverDxe: EFI Redfish Discover Protocol
@ 2021-03-26 4:54 Abner Chang
2021-04-07 5:20 ` 回复: [edk2-devel] " gaoliming
2021-04-12 3:46 ` Nickle Wang
0 siblings, 2 replies; 4+ messages in thread
From: Abner Chang @ 2021-03-26 4:54 UTC (permalink / raw)
To: devel; +Cc: Nickle Wang, Jiaxin Wu, Siyuan Fu, Fan Wang, Jiewen Yao
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
^ permalink raw reply related [flat|nested] 4+ messages in thread
* 回复: [edk2-devel] [PATCH] RedfishPkg/RedfishDiscoverDxe: EFI Redfish Discover Protocol
2021-03-26 4:54 [PATCH] RedfishPkg/RedfishDiscoverDxe: EFI Redfish Discover Protocol Abner Chang
@ 2021-04-07 5:20 ` gaoliming
2021-04-07 6:26 ` Abner Chang
2021-04-12 3:46 ` Nickle Wang
1 sibling, 1 reply; 4+ messages in thread
From: gaoliming @ 2021-04-07 5:20 UTC (permalink / raw)
To: devel, abner.chang
Cc: 'Nickle Wang', 'Jiaxin Wu', 'Siyuan Fu',
'Fan Wang', 'Jiewen Yao'
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
>
>
>
>
>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [edk2-devel] [PATCH] RedfishPkg/RedfishDiscoverDxe: EFI Redfish Discover Protocol
2021-04-07 5:20 ` 回复: [edk2-devel] " gaoliming
@ 2021-04-07 6:26 ` Abner Chang
0 siblings, 0 replies; 4+ messages in thread
From: Abner Chang @ 2021-04-07 6:26 UTC (permalink / raw)
To: devel@edk2.groups.io, gaoliming@byosoft.com.cn
Cc: Wang, Nickle (HPS SW), 'Jiaxin Wu', 'Siyuan Fu',
'Fan Wang', 'Jiewen Yao'
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
> >
> >
> >
> >
> >
>
>
>
>
>
>
>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] RedfishPkg/RedfishDiscoverDxe: EFI Redfish Discover Protocol
2021-03-26 4:54 [PATCH] RedfishPkg/RedfishDiscoverDxe: EFI Redfish Discover Protocol Abner Chang
2021-04-07 5:20 ` 回复: [edk2-devel] " gaoliming
@ 2021-04-12 3:46 ` Nickle Wang
1 sibling, 0 replies; 4+ messages in thread
From: Nickle Wang @ 2021-04-12 3:46 UTC (permalink / raw)
To: Chang, Abner (HPS SW/FW Technologist), devel@edk2.groups.io
Cc: Jiaxin Wu, Siyuan Fu, Fan Wang, Jiewen Yao
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
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2021-04-12 3:46 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-03-26 4:54 [PATCH] RedfishPkg/RedfishDiscoverDxe: EFI Redfish Discover Protocol Abner Chang
2021-04-07 5:20 ` 回复: [edk2-devel] " gaoliming
2021-04-07 6:26 ` Abner Chang
2021-04-12 3:46 ` Nickle Wang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox