2021-03-24 08:35:54 +01:00
/** @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"
2021-12-05 23:54:11 +01:00
LIST_ENTRY mRedfishDiscoverList ;
LIST_ENTRY mRedfishInstanceList ;
EFI_SMBIOS_PROTOCOL * mSmbios = NULL ;
2021-03-24 08:35:54 +01:00
2021-12-05 23:54:11 +01:00
UINTN mNumNetworkInterface = 0 ;
UINTN mNumRestExInstance = 0 ;
LIST_ENTRY mEfiRedfishDiscoverNetworkInterface ;
LIST_ENTRY mEfiRedfishDiscoverRestExInstance ;
2021-03-24 08:35:54 +01:00
2021-12-05 23:54:11 +01:00
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 ;
2021-03-24 08:35:54 +01:00
2021-12-05 23:54:11 +01:00
EFI_HANDLE EfiRedfishDiscoverProtocolHandle = NULL ;
2021-03-24 08:35:54 +01:00
EFI_STATUS
EFIAPI
Tcp4GetSubnetInfo (
2021-12-05 23:54:11 +01:00
IN EFI_HANDLE ImageHandle ,
IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL * Instance
) ;
2021-03-24 08:35:54 +01:00
EFI_STATUS
EFIAPI
Tcp6GetSubnetInfo (
2021-12-05 23:54:11 +01:00
IN EFI_HANDLE ImageHandle ,
IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL * Instance
) ;
2021-03-24 08:35:54 +01:00
2021-12-05 23:54:11 +01:00
static REDFISH_DISCOVER_REQUIRED_PROTOCOL gRequiredProtocol [ ] = {
2021-03-24 08:35:54 +01:00
{
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 (
2021-12-05 23:54:11 +01:00
IN EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE * Instance ,
IN EFI_REDFISH_DISCOVERED_TOKEN * Token
2021-03-24 08:35:54 +01:00
)
{
2021-12-05 23:54:11 +01:00
EFI_STATUS Status ;
2021-03-24 08:35:54 +01:00
Status = RestExLibCreateChild (
2021-12-05 23:54:11 +01:00
Instance - > Owner ,
FixedPcdGetBool ( PcdRedfishDiscoverAccessModeInBand ) ? EfiRestExServiceInBandAccess : EfiRestExServiceOutOfBandAccess ,
EfiRestExConfigHttp ,
EfiRestExServiceRedfish ,
& Token - > DiscoverList . RedfishInstances - > Information . RedfishRestExHandle
) ;
2021-03-24 08:35:54 +01:00
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 (
2021-12-05 23:54:11 +01:00
IN EFI_HANDLE ImageHandle ,
IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL * TargetNetworkInterface ,
IN EFI_REDFISH_DISCOVER_FLAG DiscoverFlags
2021-03-24 08:35:54 +01:00
)
{
2021-12-05 23:54:11 +01:00
EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE * ThisInstance ;
2021-03-24 08:35:54 +01:00
if ( IsListEmpty ( & mRedfishDiscoverList ) ) {
return NULL ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
ThisInstance =
( EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE * ) GetFirstNode ( & mRedfishDiscoverList ) ;
while ( TRUE ) {
if ( ( ThisInstance - > Owner = = ImageHandle ) & &
2021-12-05 23:54:11 +01:00
( ThisInstance - > DiscoverFlags = = DiscoverFlags ) & &
( ThisInstance - > NetworkInterface = = TargetNetworkInterface ) )
{
2021-03-24 08:35:54 +01:00
return ThisInstance ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
if ( IsNodeAtEnd ( & mRedfishDiscoverList , & ThisInstance - > Entry ) ) {
break ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
ThisInstance =
( EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE * ) GetNextNode ( & mRedfishDiscoverList , & ThisInstance - > Entry ) ;
2021-12-05 23:54:11 +01:00
}
2021-03-24 08:35:54 +01:00
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 (
2021-12-05 23:54:11 +01:00
IN EFI_HANDLE ImageHandle ,
IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL * Instance
)
2021-03-24 08:35:54 +01:00
{
2021-12-05 23:54:11 +01:00
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 ;
2021-03-24 08:35:54 +01:00
if ( Instance = = NULL ) {
return EFI_INVALID_PARAMETER ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
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.
2021-12-05 23:54:11 +01:00
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 ) ;
2021-03-24 08:35:54 +01:00
if ( EFI_ERROR ( Status ) ) {
DEBUG ( ( DEBUG_ERROR , " %a: Can't get subnet information \n " , __FUNCTION__ ) ) ;
return Status ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
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 ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
IP4_COPY_ADDRESS ( & Instance - > SubnetMask , & IpModedata . ConfigData . SubnetMask ) ;
2021-12-05 23:54:11 +01:00
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 ] ;
2021-03-24 08:35:54 +01:00
//
// Calculate the subnet mask prefix.
//
GotPrefixLength = FALSE ;
2021-12-05 23:54:11 +01:00
PrefixLength = 0 ;
2021-03-24 08:35:54 +01:00
SubnetMaskIndex = 0 ;
while ( GotPrefixLength = = FALSE & & SubnetMaskIndex < 4 ) {
BitMask = 0x80 ;
while ( BitMask ! = 0 ) {
2021-12-05 23:54:11 +01:00
if ( ( Instance - > SubnetMask . v4 . Addr [ SubnetMaskIndex ] & BitMask ) ! = 0 ) {
PrefixLength + + ;
2021-03-24 08:35:54 +01:00
} else {
GotPrefixLength = TRUE ;
break ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
BitMask = BitMask > > 1 ;
2021-12-05 23:54:11 +01:00
}
SubnetMaskIndex + + ;
}
2021-03-24 08:35:54 +01:00
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 (
2021-12-05 23:54:11 +01:00
IN EFI_HANDLE ImageHandle ,
IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL * Instance
)
2021-03-24 08:35:54 +01:00
{
2021-12-05 23:54:11 +01:00
EFI_STATUS Status ;
EFI_TCP6_PROTOCOL * Tcp6 ;
EFI_IP6_MODE_DATA IpModedata ;
2021-03-24 08:35:54 +01:00
if ( Instance = = NULL ) {
return EFI_INVALID_PARAMETER ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
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 ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
if ( IpModedata . AddressCount = = 0 ) {
DEBUG ( ( DEBUG_INFO , " %a: No IPv6 address configured. \n " ) ) ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
if ( Instance - > SubnetAddrInfoIPv6 ! = NULL ) {
FreePool ( Instance - > SubnetAddrInfoIPv6 ) ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
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 ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
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
)
{
2021-12-05 23:54:11 +01:00
EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL * ThisNetworkInterface ;
2021-03-24 08:35:54 +01:00
ThisNetworkInterface = ( EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL * ) GetFirstNode ( & mEfiRedfishDiscoverNetworkInterface ) ;
while ( TRUE ) {
2021-12-05 23:54:11 +01:00
if ( CompareMem ( ( VOID * ) & ThisNetworkInterface - > MacAddress , & TargetNetworkInterface - > MacAddress , ThisNetworkInterface - > HwAddressSize ) = = 0 ) {
2021-03-24 08:35:54 +01:00
return ThisNetworkInterface ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
if ( IsNodeAtEnd ( & mEfiRedfishDiscoverNetworkInterface , & ThisNetworkInterface - > Entry ) ) {
return NULL ;
}
2021-12-05 23:54:11 +01:00
ThisNetworkInterface = ( EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL * ) GetNextNode ( & mEfiRedfishDiscoverNetworkInterface , & ThisNetworkInterface - > Entry ) ;
}
2021-03-24 08:35:54 +01:00
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 ,
2021-12-05 23:54:11 +01:00
IN EFI_REDFISH_DISCOVER_FLAG Flags
2021-03-24 08:35:54 +01:00
)
{
2021-12-05 23:54:11 +01:00
EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL * ThisNetworkInterface ;
2021-03-24 08:35:54 +01:00
2021-12-05 23:54:11 +01:00
if ( IsListEmpty ( & mEfiRedfishDiscoverNetworkInterface ) & & ( TargetNetworkInterface = = NULL ) ) {
2021-03-24 08:35:54 +01:00
return EFI_UNSUPPORTED ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
if ( TargetNetworkInterface = = NULL ) {
return EFI_SUCCESS ; // Return EFI_SUCCESS if no network interface is specified.
}
2021-12-05 23:54:11 +01:00
ThisNetworkInterface = ( EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL * ) GetFirstNode ( & mEfiRedfishDiscoverNetworkInterface ) ;
2021-03-24 08:35:54 +01:00
while ( TRUE ) {
2021-12-05 23:54:11 +01:00
if ( CompareMem ( ( VOID * ) & ThisNetworkInterface - > MacAddress , & TargetNetworkInterface - > MacAddress , ThisNetworkInterface - > HwAddressSize ) = = 0 ) {
2021-03-24 08:35:54 +01:00
break ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
if ( IsNodeAtEnd ( & mEfiRedfishDiscoverNetworkInterface , & ThisNetworkInterface - > Entry ) ) {
return EFI_UNSUPPORTED ;
}
2021-12-05 23:54:11 +01:00
ThisNetworkInterface = ( EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL * ) GetNextNode ( & mEfiRedfishDiscoverNetworkInterface , & ThisNetworkInterface - > Entry ) ;
}
2021-03-24 08:35:54 +01:00
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 ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
if ( ThisNetworkInterface - > NetworkInterfaceProtocolInfo . ProtocolControllerHandle = = NULL ) {
return EFI_UNSUPPORTED ; // The required protocol on this network interface is not found.
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
return EFI_SUCCESS ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
/**
This function returns number of network interface instance .
@ retval UINTN Number of network interface instances .
* */
UINTN
2021-12-05 23:54:11 +01:00
NumberOfNetworkInterface (
VOID
)
2021-03-24 08:35:54 +01:00
{
2021-12-05 23:54:11 +01:00
UINTN Num ;
EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL * ThisNetworkInterface ;
2021-03-24 08:35:54 +01:00
if ( IsListEmpty ( & mEfiRedfishDiscoverNetworkInterface ) ) {
return 0 ;
}
2021-12-05 23:54:11 +01:00
Num = 1 ;
2021-03-24 08:35:54 +01:00
ThisNetworkInterface = ( EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL * ) GetFirstNode ( & mEfiRedfishDiscoverNetworkInterface ) ;
while ( TRUE ) {
if ( IsNodeAtEnd ( & mEfiRedfishDiscoverNetworkInterface , & ThisNetworkInterface - > Entry ) ) {
break ;
}
2021-12-05 23:54:11 +01:00
ThisNetworkInterface = ( EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL * ) GetNextNode ( & mEfiRedfishDiscoverNetworkInterface , & ThisNetworkInterface - > Entry ) ;
Num + + ;
}
2021-03-24 08:35:54 +01:00
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 (
2021-12-05 23:54:11 +01:00
IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL * ThisNetworkInterface
)
2021-03-24 08:35:54 +01:00
{
if ( ThisNetworkInterface - > NetworkProtocolType = = ProtocolTypeTcp6 ) {
return TRUE ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
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
2021-12-05 23:54:11 +01:00
DiscoverRedfishHostInterface (
IN EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE * Instance
)
2021-03-24 08:35:54 +01:00
{
2021-12-05 23:54:11 +01:00
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 ;
2021-03-24 08:35:54 +01:00
DeviceDescriptor = NULL ;
if ( mSmbios = = NULL ) {
2021-12-05 23:54:11 +01:00
Status = gBS - > LocateProtocol ( & gEfiSmbiosProtocolGuid , NULL , ( VOID * * ) & mSmbios ) ;
2021-03-24 08:35:54 +01:00
if ( EFI_ERROR ( Status ) ) {
return Status ;
}
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
Status = RedfishGetHostInterfaceProtocolData ( mSmbios , & DeviceDescriptor , & Data ) ; // Search for SMBIOS type 42h
2021-12-05 23:54:11 +01:00
if ( ! EFI_ERROR ( Status ) & & ( Data ! = NULL ) & & ( DeviceDescriptor ! = NULL ) ) {
2021-03-24 08:35:54 +01:00
//
// 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 ) {
2021-12-05 23:54:11 +01:00
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 ) ;
2021-03-24 08:35:54 +01:00
} else {
return EFI_UNSUPPORTED ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
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 ) {
2021-12-05 23:54:11 +01:00
DEBUG ( ( DEBUG_ERROR , " %a:Send UPnP unicast SSDP to validate this Redfish Host Interface is not supported. \n " , __FUNCTION__ ) ) ;
2021-03-24 08:35:54 +01:00
Status = EFI_UNSUPPORTED ;
} else {
//
// Add this istance to list without detial information of Redfish
// service.
//
IsHttps = FALSE ;
if ( Data - > RedfishServiceIpPort = = 443 ) {
IsHttps = TRUE ;
}
2021-12-05 23:54:11 +01:00
StrSize = sizeof ( UuidStr ) ;
AsciiSPrint ( UuidStr , StrSize , " %g " , & Data - > ServiceUuid ) ;
2021-03-24 08:35:54 +01:00
//
// Generate Redfish service location string.
//
if ( Data - > RedfishServiceIpAddressFormat = = REDFISH_HOST_INTERFACE_HOST_IP_ADDRESS_FORMAT_IP6 ) {
2021-12-05 23:54:11 +01:00
NetLibIp6ToStr ( ( IPv6_ADDRESS * ) & Data - > RedfishServiceIpAddress , Ipv6Str , sizeof ( Ipv6Str ) ) ;
if ( ( Data - > RedfishServiceIpPort = = 0 ) | | ( IsHttps = = TRUE ) ) {
AsciiSPrintUnicodeFormat (
RedfishServiceLocateStr ,
sizeof ( RedfishServiceLocateStr ) ,
L " %s " ,
Ipv6Str
2021-03-24 08:35:54 +01:00
) ;
} else {
2021-12-05 23:54:11 +01:00
AsciiSPrintUnicodeFormat (
RedfishServiceLocateStr ,
sizeof ( RedfishServiceLocateStr ) ,
L " [%s]:%d " ,
Ipv6Str ,
Data - > RedfishServiceIpPort
2021-03-24 08:35:54 +01:00
) ;
}
} else {
2021-12-05 23:54:11 +01:00
if ( ( Data - > RedfishServiceIpPort = = 0 ) | | ( IsHttps = = TRUE ) ) {
AsciiSPrint (
2021-03-24 08:35:54 +01:00
RedfishServiceLocateStr ,
sizeof ( RedfishServiceLocateStr ) ,
" %d.%d.%d.%d " ,
2021-12-05 23:54:11 +01:00
Data - > RedfishServiceIpAddress [ 0 ] ,
Data - > RedfishServiceIpAddress [ 1 ] ,
Data - > RedfishServiceIpAddress [ 2 ] ,
Data - > RedfishServiceIpAddress [ 3 ]
2021-03-24 08:35:54 +01:00
) ;
} else {
2021-12-05 23:54:11 +01:00
AsciiSPrint (
2021-03-24 08:35:54 +01:00
RedfishServiceLocateStr ,
sizeof ( RedfishServiceLocateStr ) ,
" %d.%d.%d.%d:%d " ,
2021-12-05 23:54:11 +01:00
Data - > RedfishServiceIpAddress [ 0 ] ,
Data - > RedfishServiceIpAddress [ 1 ] ,
Data - > RedfishServiceIpAddress [ 2 ] ,
Data - > RedfishServiceIpAddress [ 3 ] ,
2021-03-24 08:35:54 +01:00
Data - > RedfishServiceIpPort
) ;
}
2021-12-05 23:54:11 +01:00
}
2021-03-24 08:35:54 +01:00
Status = AddAndSignalNewRedfishService (
2021-12-05 23:54:11 +01:00
Instance ,
NULL ,
RedfishServiceLocateStr ,
UuidStr ,
NULL ,
NULL ,
NULL ,
NULL ,
IsHttps
) ;
2021-03-24 08:35:54 +01:00
}
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
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 (
2021-12-05 23:54:11 +01:00
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
2021-03-24 08:35:54 +01:00
)
{
2021-12-05 23:54:11 +01:00
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 ;
2021-03-24 08:35:54 +01:00
RestExOpened = FALSE ;
DeleteRestEx = FALSE ;
2021-12-05 23:54:11 +01:00
DEBUG ( ( DEBUG_INFO , " %a:Add this instance to Redfish instance list. \n " , __FUNCTION__ ) ) ;
2021-03-24 08:35:54 +01:00
if ( Uuid ! = NULL ) {
2021-12-05 23:54:11 +01:00
Char16Uuid = ( CHAR16 * ) AllocateZeroPool ( AsciiStrSize ( ( const CHAR8 * ) Uuid ) * sizeof ( CHAR16 ) ) ;
AsciiStrToUnicodeStrS ( ( const CHAR8 * ) Uuid , Char16Uuid , AsciiStrSize ( ( const CHAR8 * ) Uuid ) * sizeof ( CHAR16 ) ) ;
2021-03-24 08:35:54 +01:00
}
2021-12-05 23:54:11 +01:00
DiscoveredList = NULL ;
DiscoveredInstance = NULL ;
2021-03-24 08:35:54 +01:00
RestExHttpConfigData = NULL ;
NetworkInterface = Instance - > NetworkInterface ;
if ( ! IsListEmpty ( & mRedfishInstanceList ) ) {
//
// Is this a duplicate redfish service.
//
DiscoveredList = ( EFI_REDFISH_DISCOVERED_INTERNAL_LIST * ) GetFirstNode ( & mRedfishInstanceList ) ;
2021-12-05 23:54:11 +01:00
NewFound = FALSE ;
2021-03-24 08:35:54 +01:00
do {
2021-12-05 23:54:11 +01:00
if ( ( Char16Uuid = = NULL ) | | ( DiscoveredList - > Instance - > Information . Uuid = = NULL ) ) {
2021-03-24 08:35:54 +01:00
//
// Check if this Redfish instance already found using IP addrress.
//
2021-12-05 23:54:11 +01:00
if ( ! CheckIsIpVersion6 ( NetworkInterface ) ) {
if ( CompareMem (
( VOID * ) & Instance - > TargetIpAddress . v4 ,
( VOID * ) & DiscoveredList - > Instance - > Information . RedfishHostIpAddress . v4 ,
sizeof ( EFI_IPv4_ADDRESS )
) = = 0 )
2021-03-24 08:35:54 +01:00
{
DiscoveredInstance = DiscoveredList - > Instance ;
2021-12-05 23:54:11 +01:00
if ( ( DiscoveredList - > Instance - > Information . Uuid = = NULL ) & &
( Char16Uuid ! = NULL ) )
{
InfoRefresh = TRUE ;
2021-03-24 08:35:54 +01:00
DiscoveredInstance = DiscoveredList - > Instance ;
2021-12-05 23:54:11 +01:00
DEBUG ( ( DEBUG_INFO , " *** This Redfish Service information refresh *** \n " ) ) ;
2021-03-24 08:35:54 +01:00
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
break ;
}
} else {
2021-12-05 23:54:11 +01:00
if ( CompareMem (
( VOID * ) & Instance - > TargetIpAddress . v6 ,
( VOID * ) & DiscoveredList - > Instance - > Information . RedfishHostIpAddress . v6 ,
sizeof ( EFI_IPv6_ADDRESS )
) = = 0 )
2021-03-24 08:35:54 +01:00
{
DiscoveredInstance = DiscoveredList - > Instance ;
break ;
}
}
} else {
//
// Check if this Redfish instance already found using UUID.
//
2021-12-05 23:54:11 +01:00
if ( StrCmp ( ( const CHAR16 * ) Char16Uuid , ( const CHAR16 * ) DiscoveredList - > Instance - > Information . Uuid ) = = 0 ) {
2021-03-24 08:35:54 +01:00
DiscoveredInstance = DiscoveredList - > Instance ;
break ;
}
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
if ( IsNodeAtEnd ( & mRedfishInstanceList , & DiscoveredList - > NextInstance ) ) {
NewFound = TRUE ;
break ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
DiscoveredList = ( EFI_REDFISH_DISCOVERED_INTERNAL_LIST * ) GetNextNode ( & mRedfishInstanceList , & DiscoveredList - > NextInstance ) ;
} while ( TRUE ) ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
if ( NewFound | | InfoRefresh ) {
if ( ! InfoRefresh ) {
2021-12-05 23:54:11 +01:00
DiscoveredList = ( EFI_REDFISH_DISCOVERED_INTERNAL_LIST * ) AllocateZeroPool ( sizeof ( EFI_REDFISH_DISCOVERED_INTERNAL_LIST ) ) ;
2021-03-24 08:35:54 +01:00
if ( DiscoveredList = = NULL ) {
return EFI_OUT_OF_RESOURCES ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
InitializeListHead ( & DiscoveredList - > NextInstance ) ;
2021-12-05 23:54:11 +01:00
DiscoveredInstance = ( EFI_REDFISH_DISCOVERED_INSTANCE * ) AllocateZeroPool ( sizeof ( EFI_REDFISH_DISCOVERED_INSTANCE ) ) ;
2021-03-24 08:35:54 +01:00
if ( DiscoveredInstance = = NULL ) {
FreePool ( ( VOID * ) DiscoveredList ) ;
return EFI_OUT_OF_RESOURCES ;
}
}
2021-12-05 23:54:11 +01:00
DEBUG ( ( DEBUG_INFO , " *** Redfish Service Information *** \n " ) ) ;
2021-03-24 08:35:54 +01:00
DiscoveredInstance - > Information . UseHttps = UseHttps ;
if ( RedfishVersion ! = NULL ) {
DiscoveredInstance - > Information . RedfishVersion = * RedfishVersion ;
2021-12-05 23:54:11 +01:00
DEBUG ( ( DEBUG_INFO , " Redfish service version: %d. \n " , DiscoveredInstance - > Information . RedfishVersion ) ) ;
2021-03-24 08:35:54 +01:00
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
if ( RedfishLocation ! = NULL ) {
2021-12-05 23:54:11 +01:00
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 ) ) ;
2021-03-24 08:35:54 +01:00
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
if ( Uuid ! = NULL ) {
2021-12-05 23:54:11 +01:00
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 ) ) ;
2021-03-24 08:35:54 +01:00
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
if ( Os ! = NULL ) {
2021-12-05 23:54:11 +01:00
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 ) ) ;
2021-03-24 08:35:54 +01:00
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
if ( OsVer ! = NULL ) {
2021-12-05 23:54:11 +01:00
DiscoveredInstance - > Information . OsVersion = ( CHAR16 * ) AllocatePool ( AsciiStrSize ( ( const CHAR8 * ) OsVer ) * sizeof ( CHAR16 ) ) ;
AsciiStrToUnicodeStrS ( ( const CHAR8 * ) OsVer , DiscoveredInstance - > Information . OsVersion , AsciiStrSize ( ( const CHAR8 * ) OsVer ) * sizeof ( CHAR16 ) ) ;
2021-03-24 08:35:54 +01:00
}
2021-12-05 23:54:11 +01:00
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 ) ) ;
2021-03-24 08:35:54 +01:00
}
if ( RedfishLocation = = NULL ) {
// This is the Redfish reported from SMBIOS 42h
// without validation.
2021-12-05 23:54:11 +01:00
IP4_COPY_ADDRESS ( ( VOID * ) & DiscoveredInstance - > Information . RedfishHostIpAddress . v4 , ( VOID * ) & Instance - > TargetIpAddress . v4 ) ;
2021-03-24 08:35:54 +01:00
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
if ( ! InfoRefresh ) {
DiscoveredList - > Instance = DiscoveredInstance ;
2021-12-05 23:54:11 +01:00
InsertTailList ( & mRedfishInstanceList , & DiscoveredList - > NextInstance ) ;
2021-03-24 08:35:54 +01:00
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
DiscoveredInstance - > Status = EFI_SUCCESS ;
} else {
if ( DiscoveredList ! = NULL ) {
2021-12-05 23:54:11 +01:00
DEBUG ( ( DEBUG_INFO , " *** This Redfish Service was already found *** \n " ) ) ;
2021-03-24 08:35:54 +01:00
if ( DiscoveredInstance - > Information . Uuid ! = NULL ) {
2021-12-05 23:54:11 +01:00
DEBUG ( ( DEBUG_INFO , " Service UUID: %s. \n " , DiscoveredInstance - > Information . Uuid ) ) ;
2021-03-24 08:35:54 +01:00
} else {
2021-12-05 23:54:11 +01:00
DEBUG ( ( DEBUG_INFO , " Service UUID: unknown. \n " ) ) ;
2021-03-24 08:35:54 +01:00
}
}
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
if ( Char16Uuid ! = NULL ) {
2021-12-05 23:54:11 +01:00
FreePool ( ( VOID * ) Char16Uuid ) ;
2021-03-24 08:35:54 +01:00
}
Status = EFI_SUCCESS ;
if ( NewFound | | InfoRefresh ) {
//
// Build up EFI_REDFISH_DISCOVERED_LIST in token.
//
Instance - > DiscoverToken - > DiscoverList . NumberOfServiceFound = 1 ;
2021-12-05 23:54:11 +01:00
Instance - > DiscoverToken - > DiscoverList . RedfishInstances = DiscoveredInstance ;
DiscoveredInstance - > Status = EFI_SUCCESS ;
2021-03-24 08:35:54 +01:00
if ( ! InfoRefresh ) {
Status = CreateRestExInstance ( Instance , Instance - > DiscoverToken ) ; // Create REST EX child.
if ( EFI_ERROR ( Status ) ) {
2021-12-05 23:54:11 +01:00
DEBUG ( ( DEBUG_ERROR , " %a:Can't create REST EX child instance. \n " , __FUNCTION__ ) ) ;
2021-03-24 08:35:54 +01:00
goto ON_EXIT ;
}
2021-12-05 23:54:11 +01:00
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
) ;
2021-03-24 08:35:54 +01:00
if ( EFI_ERROR ( Status ) ) {
DeleteRestEx = TRUE ;
goto ERROR_EXIT ;
}
2021-12-05 23:54:11 +01:00
RestExOpened = TRUE ;
2021-03-24 08:35:54 +01:00
RestExHttpConfigData = AllocateZeroPool ( sizeof ( EFI_REST_EX_HTTP_CONFIG_DATA ) ) ;
if ( RestExHttpConfigData = = NULL ) {
2021-12-05 23:54:11 +01:00
Status = EFI_OUT_OF_RESOURCES ;
2021-03-24 08:35:54 +01:00
DeleteRestEx = TRUE ;
goto EXIT_FREE_CONFIG_DATA ;
}
2021-12-05 23:54:11 +01:00
RestExHttpConfigData - > SendReceiveTimeout = 5000 ;
RestExHttpConfigData - > HttpConfigData . HttpVersion = HttpVersion11 ;
RestExHttpConfigData - > HttpConfigData . LocalAddressIsIPv6 = CheckIsIpVersion6 ( NetworkInterface ) ;
2021-03-24 08:35:54 +01:00
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 ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
RestExHttpConfigData - > HttpConfigData . AccessPoint . IPv4Node - > UseDefaultAddress = TRUE ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
Status = RestEx - > Configure (
2021-12-05 23:54:11 +01:00
RestEx ,
( EFI_REST_EX_CONFIG_DATA ) ( UINT8 * ) RestExHttpConfigData
) ;
2021-03-24 08:35:54 +01:00
if ( EFI_ERROR ( Status ) ) {
2021-12-05 23:54:11 +01:00
DEBUG ( ( DEBUG_ERROR , " %a:REST EX configured.. \n " , __FUNCTION__ ) ) ;
2021-03-24 08:35:54 +01:00
DeleteRestEx = TRUE ;
goto EXIT_FREE_ALL ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
//
// Signal client, close REST EX before signaling client.
//
if ( RestExOpened ) {
2021-12-05 23:54:11 +01:00
gBS - > CloseProtocol (
Instance - > DiscoverToken - > DiscoverList . RedfishInstances - > Information . RedfishRestExHandle ,
& gEfiRestExProtocolGuid ,
Instance - > NetworkInterface - > OpenDriverAgentHandle ,
Instance - > NetworkInterface - > OpenDriverControllerHandle
) ;
2021-03-24 08:35:54 +01:00
RestExOpened = FALSE ;
}
}
2021-12-05 23:54:11 +01:00
Status = gBS - > SignalEvent ( Instance - > DiscoverToken - > Event ) ;
2021-03-24 08:35:54 +01:00
if ( ! EFI_ERROR ( Status ) ) {
2021-12-05 23:54:11 +01:00
DEBUG ( ( DEBUG_ERROR , " %a:No event to signal! \n " , __FUNCTION__ ) ) ;
2021-03-24 08:35:54 +01:00
}
}
EXIT_FREE_ALL : ;
2021-12-05 23:54:11 +01:00
if ( ( RestExHttpConfigData ! = NULL ) & & ( RestExHttpConfigData - > HttpConfigData . AccessPoint . IPv4Node ! = NULL ) ) {
2021-03-24 08:35:54 +01:00
FreePool ( RestExHttpConfigData - > HttpConfigData . AccessPoint . IPv4Node ) ;
}
EXIT_FREE_CONFIG_DATA : ;
if ( RestExHttpConfigData ! = NULL ) {
2021-12-05 23:54:11 +01:00
FreePool ( ( VOID * ) RestExHttpConfigData ) ;
2021-03-24 08:35:54 +01:00
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
if ( RestExOpened ) {
2021-12-05 23:54:11 +01:00
gBS - > CloseProtocol (
2021-03-24 08:35:54 +01:00
Instance - > DiscoverToken - > DiscoverList . RedfishInstances - > Information . RedfishRestExHandle ,
& gEfiRestExProtocolGuid ,
Instance - > NetworkInterface - > OpenDriverAgentHandle ,
Instance - > NetworkInterface - > OpenDriverControllerHandle
2021-12-05 23:54:11 +01:00
) ;
2021-03-24 08:35:54 +01:00
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
ERROR_EXIT : ;
2021-12-05 23:54:11 +01:00
if ( DeleteRestEx & & RestExOpened ) {
gBS - > CloseProtocol (
2021-03-24 08:35:54 +01:00
Instance - > DiscoverToken - > DiscoverList . RedfishInstances - > Information . RedfishRestExHandle ,
& gEfiRestExProtocolGuid ,
Instance - > NetworkInterface - > OpenDriverAgentHandle ,
Instance - > NetworkInterface - > OpenDriverControllerHandle
2021-12-05 23:54:11 +01:00
) ;
}
2021-03-24 08:35:54 +01:00
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 (
2021-12-05 23:54:11 +01:00
IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL * Instance ,
IN EFI_HANDLE ImageHandle
2021-03-24 08:35:54 +01:00
)
{
2021-12-05 23:54:11 +01:00
EFI_STATUS Status ;
UINT32 ProtocolType ;
UINT32 IPv6InfoIndex ;
EFI_IP6_ADDRESS_INFO * ThisSubnetAddrInfoIPv6 ;
EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL * NewNetworkInterface ;
2021-03-24 08:35:54 +01:00
if ( Instance - > GotSubnetInfo ) {
return EFI_SUCCESS ;
}
ProtocolType = Instance - > NetworkProtocolType ;
2021-12-05 23:54:11 +01:00
if ( ( gRequiredProtocol [ ProtocolType ] . GetSubnetInfo ! = NULL ) & & ( Instance - > GotSubnetInfo = = FALSE ) ) {
Status = gRequiredProtocol [ ProtocolType ] . GetSubnetInfo (
ImageHandle ,
Instance
) ;
2021-03-24 08:35:54 +01:00
if ( EFI_ERROR ( Status ) ) {
2021-12-05 23:54:11 +01:00
DEBUG ( ( DEBUG_ERROR , " %a:Faile to get Subnet infomation. \n " , __FUNCTION__ ) ) ;
2021-03-24 08:35:54 +01:00
return Status ;
} else {
2021-12-05 23:54:11 +01:00
DEBUG ( ( DEBUG_INFO , " %a:MAC address: %s \n " , __FUNCTION__ , Instance - > StrMacAddr ) ) ;
2021-03-24 08:35:54 +01:00
if ( CheckIsIpVersion6 ( Instance ) ) {
if ( Instance - > SubnetAddrInfoIPv6Number = = 0 ) {
2021-12-05 23:54:11 +01:00
DEBUG ( ( DEBUG_ERROR , " %a: There is no Subnet infomation for IPv6 network interface. \n " , __FUNCTION__ ) ) ;
2021-03-24 08:35:54 +01:00
return EFI_NOT_FOUND ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
ThisSubnetAddrInfoIPv6 = Instance - > SubnetAddrInfoIPv6 ; // First IPv6 address information.
IP6_COPY_ADDRESS ( & Instance - > SubnetAddr . v6 , & ThisSubnetAddrInfoIPv6 - > Address ) ;
Instance - > SubnetPrefixLength = ThisSubnetAddrInfoIPv6 - > PrefixLength ;
2021-12-05 23:54:11 +01:00
DEBUG ( (
DEBUG_INFO ,
" IPv6 Subnet ID:%d, Prefix length: %d. \n " ,
ThisSubnetAddrInfoIPv6 - > Address . Addr [ 7 ] + ( UINT16 ) ThisSubnetAddrInfoIPv6 - > Address . Addr [ 6 ] * 256 ,
ThisSubnetAddrInfoIPv6 - > PrefixLength
)
) ;
2021-03-24 08:35:54 +01:00
//
// If this is IPv6, then we may have to propagate network interface for IPv6 network scopes
// according to the Ipv6 address information.
//
2021-12-05 23:54:11 +01:00
ThisSubnetAddrInfoIPv6 + + ;
2021-03-24 08:35:54 +01:00
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 ;
2021-12-05 23:54:11 +01:00
NewNetworkInterface - > GotSubnetInfo = TRUE ;
2021-03-24 08:35:54 +01:00
InsertTailList ( & mEfiRedfishDiscoverNetworkInterface , & NewNetworkInterface - > Entry ) ;
2021-12-05 23:54:11 +01:00
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
)
) ;
2021-03-24 08:35:54 +01:00
} else {
return EFI_OUT_OF_RESOURCES ;
}
}
} else {
2021-12-05 23:54:11 +01:00
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 ]
) ) ;
2021-03-24 08:35:54 +01:00
}
}
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
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 (
2021-12-05 23:54:11 +01:00
IN EFI_REDFISH_DISCOVER_PROTOCOL * This ,
IN EFI_HANDLE ImageHandle ,
OUT UINTN * NumberOfNetworkIntfs ,
OUT EFI_REDFISH_DISCOVER_NETWORK_INTERFACE * * NetworkIntfInstances
)
2021-03-24 08:35:54 +01:00
{
2021-12-05 23:54:11 +01:00
EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL * ThisNetworkInterfaceIntn ;
EFI_REDFISH_DISCOVER_NETWORK_INTERFACE * ThisNetworkInterface ;
2021-03-24 08:35:54 +01:00
2021-12-05 23:54:11 +01:00
if ( ( NetworkIntfInstances = = NULL ) | | ( NumberOfNetworkIntfs = = NULL ) | | ( ImageHandle = = NULL ) ) {
2021-03-24 08:35:54 +01:00
return EFI_INVALID_PARAMETER ;
}
* NumberOfNetworkIntfs = 0 ;
* NetworkIntfInstances = NULL ;
2021-12-05 23:54:11 +01:00
if ( IsListEmpty ( ( const LIST_ENTRY * ) & mEfiRedfishDiscoverNetworkInterface ) ) {
2021-03-24 08:35:54 +01:00
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 ;
}
2021-12-05 23:54:11 +01:00
* NetworkIntfInstances = ThisNetworkInterface ;
2021-03-24 08:35:54 +01:00
ThisNetworkInterfaceIntn = ( EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL * ) GetFirstNode ( & mEfiRedfishDiscoverNetworkInterface ) ;
while ( TRUE ) {
ThisNetworkInterface - > IsIpv6 = FALSE ;
if ( CheckIsIpVersion6 ( ThisNetworkInterfaceIntn ) ) {
ThisNetworkInterface - > IsIpv6 = TRUE ;
}
2021-12-05 23:54:11 +01:00
CopyMem ( ( VOID * ) & ThisNetworkInterface - > MacAddress , & ThisNetworkInterfaceIntn - > MacAddress , ThisNetworkInterfaceIntn - > HwAddressSize ) ;
NetworkInterfaceGetSubnetInfo ( ThisNetworkInterfaceIntn , ImageHandle ) ; // Get subnet info.
2021-03-24 08:35:54 +01:00
if ( ! ThisNetworkInterface - > IsIpv6 ) {
2021-12-05 23:54:11 +01:00
IP4_COPY_ADDRESS ( & ThisNetworkInterface - > SubnetId . v4 , & ThisNetworkInterfaceIntn - > SubnetAddr . v4 ) ; // IPv4 subnet information.
2021-03-24 08:35:54 +01:00
} else {
IP6_COPY_ADDRESS ( & ThisNetworkInterface - > SubnetId . v6 , & ThisNetworkInterfaceIntn - > SubnetAddr . v6 ) ; // IPv6 subnet information in IPv6 address information.
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
ThisNetworkInterface - > SubnetPrefixLength = ThisNetworkInterfaceIntn - > SubnetPrefixLength ;
2021-12-05 23:54:11 +01:00
ThisNetworkInterface - > VlanId = ThisNetworkInterfaceIntn - > VlanId ;
( * NumberOfNetworkIntfs ) + + ;
2021-03-24 08:35:54 +01:00
if ( IsNodeAtEnd ( & mEfiRedfishDiscoverNetworkInterface , & ThisNetworkInterfaceIntn - > Entry ) ) {
break ;
}
2021-12-05 23:54:11 +01:00
ThisNetworkInterfaceIntn = ( EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL * ) GetNextNode ( & mEfiRedfishDiscoverNetworkInterface , & ThisNetworkInterfaceIntn - > Entry ) ;
ThisNetworkInterface + + ;
}
2021-03-24 08:35:54 +01:00
return EFI_SUCCESS ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
/**
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 (
2021-12-05 23:54:11 +01:00
IN EFI_REDFISH_DISCOVER_PROTOCOL * This ,
IN EFI_HANDLE ImageHandle ,
2021-03-24 08:35:54 +01:00
IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE * TargetNetworkInterface ,
2021-12-05 23:54:11 +01:00
IN EFI_REDFISH_DISCOVER_FLAG Flags ,
IN EFI_REDFISH_DISCOVERED_TOKEN * Token
2021-03-24 08:35:54 +01:00
)
{
2021-12-05 23:54:11 +01:00
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 ;
2021-03-24 08:35:54 +01:00
2021-12-05 23:54:11 +01:00
DEBUG ( ( DEBUG_INFO , " %a:Entry. \n " , __FUNCTION__ ) ) ;
2021-03-24 08:35:54 +01:00
//
// Validate parameters.
//
2021-12-05 23:54:11 +01:00
if ( ( ImageHandle = = NULL ) | | ( Token = = NULL ) | | ( ( Flags & ~ EFI_REDFISH_DISCOVER_VALIDATION ) = = 0 ) ) {
DEBUG ( ( DEBUG_ERROR , " %a:Invalid parameters. \n " , __FUNCTION__ ) ) ;
2021-03-24 08:35:54 +01:00
return EFI_INVALID_PARAMETER ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
//
// Validate target network interface.
//
if ( EFI_ERROR ( ValidateTargetNetworkInterface ( TargetNetworkInterface , Flags ) ) ) {
2021-12-05 23:54:11 +01:00
return EFI_UNSUPPORTED ;
2021-03-24 08:35:54 +01:00
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
if ( TargetNetworkInterface ! = NULL ) {
TargetNetworkInterfaceInternal = GetTargetNetworkInterfaceInternal ( TargetNetworkInterface ) ;
2021-12-05 23:54:11 +01:00
NumNetworkInterfaces = 1 ;
2021-03-24 08:35:54 +01:00
} else {
TargetNetworkInterfaceInternal = ( EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL * ) GetFirstNode ( & mEfiRedfishDiscoverNetworkInterface ) ;
2021-12-05 23:54:11 +01:00
NumNetworkInterfaces = NumberOfNetworkInterface ( ) ;
2021-03-24 08:35:54 +01:00
if ( NumNetworkInterfaces = = 0 ) {
2021-12-05 23:54:11 +01:00
DEBUG ( ( DEBUG_ERROR , " %a:No network interface on platform. \n " , __FUNCTION__ ) ) ;
2021-03-24 08:35:54 +01:00
return EFI_UNSUPPORTED ;
}
}
2021-12-05 23:54:11 +01:00
for ( NetworkInterfacesIndex = 0 ; NetworkInterfacesIndex < NumNetworkInterfaces ; NetworkInterfacesIndex + + ) {
Status1 = EFI_SUCCESS ;
Status2 = EFI_SUCCESS ;
2021-03-24 08:35:54 +01:00
NewInstance = FALSE ;
2021-12-05 23:54:11 +01:00
Instance = GetInstanceByOwner ( ImageHandle , TargetNetworkInterfaceInternal , Flags & ~ EFI_REDFISH_DISCOVER_VALIDATION ) ; // Check if we can re-use previous instance.
2021-03-24 08:35:54 +01:00
if ( Instance = = NULL ) {
2021-12-05 23:54:11 +01:00
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 ) ) ;
2021-03-24 08:35:54 +01:00
if ( Instance = = NULL ) {
2021-12-05 23:54:11 +01:00
DEBUG ( ( DEBUG_ERROR , " %a:Memory allocation fail. \n " , __FUNCTION__ ) ) ;
2021-03-24 08:35:54 +01:00
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
InitializeListHead ( & Instance - > Entry ) ;
2021-12-05 23:54:11 +01:00
Instance - > Owner = ImageHandle ;
Instance - > DiscoverFlags = Flags & ~ EFI_REDFISH_DISCOVER_VALIDATION ;
2021-03-24 08:35:54 +01:00
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 ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
if ( TargetNetworkInterfaceInternal - > StrMacAddr ! = NULL ) {
2021-12-05 23:54:11 +01:00
DEBUG ( ( DEBUG_INFO , " %a:Acquire Redfish service on network interface MAC address:%s. \n " , __FUNCTION__ , TargetNetworkInterfaceInternal - > StrMacAddr ) ) ;
2021-03-24 08:35:54 +01:00
} else {
2021-12-05 23:54:11 +01:00
DEBUG ( ( DEBUG_INFO , " %a:WARNING: No MAC address on this network interface. \n " , __FUNCTION__ ) ) ;
2021-03-24 08:35:54 +01:00
}
Instance - > DiscoverToken = Token ; // Always use the latest Token passed by caller.
if ( ( Flags & EFI_REDFISH_DISCOVER_HOST_INTERFACE ) ! = 0 ) {
2021-12-05 23:54:11 +01:00
DEBUG ( ( DEBUG_INFO , " %a:Redfish HOST interface discovery. \n " , __FUNCTION__ ) ) ;
2021-03-24 08:35:54 +01:00
Instance - > HostIntfValidation = FALSE ;
if ( ( Flags & EFI_REDFISH_DISCOVER_VALIDATION ) ! = 0 ) {
Instance - > HostIntfValidation = TRUE ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
Status1 = DiscoverRedfishHostInterface ( Instance ) ; // Discover Redfish service through Redfish Host Interface.
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
if ( ( Flags & EFI_REDFISH_DISCOVER_SSDP ) ! = 0 ) {
2021-12-05 23:54:11 +01:00
DEBUG ( ( DEBUG_ERROR , " %a:Redfish service discovery through SSDP is not supported \n " , __FUNCTION__ ) ) ;
2021-03-24 08:35:54 +01:00
return EFI_UNSUPPORTED ;
} else {
if ( EFI_ERROR ( Status1 ) & & EFI_ERROR ( Status2 ) ) {
FreePool ( ( VOID * ) Instance ) ;
2021-12-05 23:54:11 +01:00
DEBUG ( ( DEBUG_ERROR , " %a:Something wrong on Redfish service discovery Status1=%x, Status2=%x. \n " , __FUNCTION__ , Status1 , Status2 ) ) ;
2021-03-24 08:35:54 +01:00
} else {
if ( NewInstance ) {
2021-12-05 23:54:11 +01:00
InsertTailList ( & mRedfishDiscoverList , & Instance - > Entry ) ;
2021-03-24 08:35:54 +01:00
}
}
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
if ( TargetNetworkInterface = = NULL ) {
//
// Discover Redfish services on all of network interfaces.
//
2021-12-05 23:54:11 +01:00
TargetNetworkInterfaceInternal = ( EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL * ) GetNextNode ( & mEfiRedfishDiscoverNetworkInterface , & TargetNetworkInterfaceInternal - > Entry ) ;
2021-03-24 08:35:54 +01:00
}
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
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 (
2021-12-05 23:54:11 +01:00
IN EFI_REDFISH_DISCOVER_PROTOCOL * This ,
2021-03-24 08:35:54 +01:00
IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE * TargetNetworkInterface OPTIONAL
2021-12-05 23:54:11 +01:00
)
2021-03-24 08:35:54 +01:00
{
// 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 (
2021-12-05 23:54:11 +01:00
IN EFI_REDFISH_DISCOVER_PROTOCOL * This ,
IN EFI_REDFISH_DISCOVERED_LIST * InstanceList
2021-03-24 08:35:54 +01:00
)
{
2021-12-05 23:54:11 +01:00
UINTN NumService ;
BOOLEAN AnyFailRelease ;
EFI_REDFISH_DISCOVERED_INSTANCE * ThisRedfishInstance ;
EFI_REDFISH_DISCOVERED_INTERNAL_LIST * DiscoveredRedfishInstance ;
2021-03-24 08:35:54 +01:00
if ( IsListEmpty ( & mRedfishInstanceList ) ) {
2021-12-05 23:54:11 +01:00
DEBUG ( ( DEBUG_ERROR , " %a:No any discovered Redfish service. \n " , __FUNCTION__ ) ) ;
2021-03-24 08:35:54 +01:00
return EFI_NOT_FOUND ;
}
2021-12-05 23:54:11 +01:00
AnyFailRelease = FALSE ;
2021-03-24 08:35:54 +01:00
ThisRedfishInstance = InstanceList - > RedfishInstances ;
2021-12-05 23:54:11 +01:00
for ( NumService = 0 ; NumService < InstanceList - > NumberOfServiceFound ; NumService + + ) {
DiscoveredRedfishInstance = ( EFI_REDFISH_DISCOVERED_INTERNAL_LIST * ) GetFirstNode ( & mRedfishInstanceList ) ;
2021-03-24 08:35:54 +01:00
do {
if ( DiscoveredRedfishInstance - > Instance = = ThisRedfishInstance ) {
RemoveEntryList ( & DiscoveredRedfishInstance - > NextInstance ) ;
if ( ThisRedfishInstance - > Information . Location ! = NULL ) {
FreePool ( ThisRedfishInstance - > Information . Location ) ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
if ( ThisRedfishInstance - > Information . Uuid ! = NULL ) {
FreePool ( ThisRedfishInstance - > Information . Uuid ) ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
if ( ThisRedfishInstance - > Information . Os ! = NULL ) {
FreePool ( ThisRedfishInstance - > Information . Os ) ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
if ( ThisRedfishInstance - > Information . OsVersion ! = NULL ) {
FreePool ( ThisRedfishInstance - > Information . OsVersion ) ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
if ( ThisRedfishInstance - > Information . Product ! = NULL ) {
FreePool ( ThisRedfishInstance - > Information . Product ) ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
if ( ThisRedfishInstance - > Information . ProductVer ! = NULL ) {
FreePool ( ThisRedfishInstance - > Information . ProductVer ) ;
}
2021-12-05 23:54:11 +01:00
FreePool ( ( VOID * ) ThisRedfishInstance ) ;
2021-03-24 08:35:54 +01:00
goto ReleaseNext ;
}
2021-12-05 23:54:11 +01:00
if ( IsNodeAtEnd ( & mRedfishInstanceList , & DiscoveredRedfishInstance - > NextInstance ) ) {
2021-03-24 08:35:54 +01:00
break ;
}
2021-12-05 23:54:11 +01:00
DiscoveredRedfishInstance = ( EFI_REDFISH_DISCOVERED_INTERNAL_LIST * ) GetNextNode ( & mRedfishInstanceList , & DiscoveredRedfishInstance - > NextInstance ) ;
2021-03-24 08:35:54 +01:00
} while ( TRUE ) ;
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
AnyFailRelease = TRUE ;
ReleaseNext : ;
//
// Release next discovered Redfish Service.
//
ThisRedfishInstance = ( EFI_REDFISH_DISCOVERED_INSTANCE * ) ( ( UINT8 * ) ThisRedfishInstance + sizeof ( EFI_REDFISH_DISCOVERED_INSTANCE ) ) ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
if ( AnyFailRelease ) {
return EFI_NOT_FOUND ;
} else {
return EFI_SUCCESS ;
}
}
2021-12-05 23:54:11 +01:00
EFI_REDFISH_DISCOVER_PROTOCOL mRedfishDiscover = {
2021-03-24 08:35:54 +01:00
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 (
2021-12-05 23:54:11 +01:00
IN EFI_HANDLE ControllerHandle ,
IN UINT32 NetworkProtocolType ,
OUT BOOLEAN * IsNewInstance ,
OUT EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL * * NetworkInterface
2021-03-24 08:35:54 +01:00
)
{
2021-12-05 23:54:11 +01:00
EFI_MAC_ADDRESS MacAddress ;
UINTN HwAddressSize ;
EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL * ThisNetworkInterface ;
EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL * NewNetworkInterface ;
2021-03-24 08:35:54 +01:00
NetLibGetMacAddress ( ControllerHandle , & MacAddress , & HwAddressSize ) ;
NewNetworkInterface = NULL ;
2021-12-05 23:54:11 +01:00
* IsNewInstance = TRUE ;
if ( ! IsListEmpty ( ( const LIST_ENTRY * ) & mEfiRedfishDiscoverNetworkInterface ) ) {
2021-03-24 08:35:54 +01:00
//
// 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 ) & &
2021-12-05 23:54:11 +01:00
( ThisNetworkInterface - > NetworkProtocolType = = NetworkProtocolType ) )
{
2021-03-24 08:35:54 +01:00
NewNetworkInterface = ThisNetworkInterface ;
2021-12-05 23:54:11 +01:00
* IsNewInstance = FALSE ;
2021-03-24 08:35:54 +01:00
break ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
if ( IsNodeAtEnd ( & mEfiRedfishDiscoverNetworkInterface , & ThisNetworkInterface - > Entry ) ) {
NewNetworkInterface = NULL ;
break ;
}
2021-12-05 23:54:11 +01:00
ThisNetworkInterface = ( EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL * ) GetNextNode ( & mEfiRedfishDiscoverNetworkInterface , & ThisNetworkInterface - > Entry ) ;
}
2021-03-24 08:35:54 +01:00
}
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
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 ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
NewNetworkInterface - > HwAddressSize = HwAddressSize ;
CopyMem ( & NewNetworkInterface - > MacAddress . Addr , & MacAddress . Addr , NewNetworkInterface - > HwAddressSize ) ;
NetLibGetMacString ( ControllerHandle , NULL , & NewNetworkInterface - > StrMacAddr ) ;
NewNetworkInterface - > VlanId = NetLibGetVlanId ( ControllerHandle ) ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
* 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 (
2021-12-05 23:54:11 +01:00
IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL * ThisNetworkInterface
2021-03-24 08:35:54 +01:00
)
{
2021-12-05 23:54:11 +01:00
EFI_STATUS Status ;
2021-03-24 08:35:54 +01:00
2021-12-05 23:54:11 +01:00
Status = gBS - > UninstallProtocolInterface (
2021-03-24 08:35:54 +01:00
ThisNetworkInterface - > OpenDriverControllerHandle ,
2021-12-05 23:54:11 +01:00
gRequiredProtocol [ ThisNetworkInterface - > NetworkProtocolType ] . DiscoveredProtocolGuid ,
2021-03-24 08:35:54 +01:00
& ThisNetworkInterface - > NetworkInterfaceProtocolInfo . ProtocolDiscoverId
) ;
RemoveEntryList ( & ThisNetworkInterface - > Entry ) ;
2021-12-05 23:54:11 +01:00
mNumNetworkInterface - - ;
2021-03-24 08:35:54 +01:00
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 ,
2021-12-05 23:54:11 +01:00
IN EFI_HANDLE ControllerHandle
2021-03-24 08:35:54 +01:00
)
{
2021-12-05 23:54:11 +01:00
UINT32 Id ;
UINTN Index ;
EFI_STATUS Status ;
2021-03-24 08:35:54 +01:00
2021-12-05 23:54:11 +01:00
for ( Index = 0 ; Index < ( sizeof ( gRequiredProtocol ) / sizeof ( REDFISH_DISCOVER_REQUIRED_PROTOCOL ) ) ; Index + + ) {
2021-03-24 08:35:54 +01:00
Status = gBS - > OpenProtocol (
2021-12-05 23:54:11 +01:00
ControllerHandle ,
gRequiredProtocol [ Index ] . RequiredServiceBindingProtocolGuid ,
NULL ,
This - > DriverBindingHandle ,
ControllerHandle ,
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
) ;
2021-03-24 08:35:54 +01:00
if ( ! EFI_ERROR ( Status ) ) {
Status = gBS - > OpenProtocol (
ControllerHandle ,
2021-12-05 23:54:11 +01:00
gRequiredProtocol [ Index ] . DiscoveredProtocolGuid ,
( VOID * * ) & Id ,
2021-03-24 08:35:54 +01:00
This - > DriverBindingHandle ,
ControllerHandle ,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
) ;
if ( EFI_ERROR ( Status ) ) {
2021-12-05 23:54:11 +01:00
DEBUG ( ( DEBUG_ERROR , " %a: %s is found on this controller handle. \n " , __FUNCTION__ , gRequiredProtocol [ Index ] . ProtocolName ) ) ;
2021-03-24 08:35:54 +01:00
return EFI_SUCCESS ;
}
}
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
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 ,
2021-12-05 23:54:11 +01:00
IN EFI_HANDLE ControllerHandle
2021-03-24 08:35:54 +01:00
)
{
2021-12-05 23:54:11 +01:00
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 ;
2021-03-24 08:35:54 +01:00
NewNetworkInterfaceInstalled = FALSE ;
2021-12-05 23:54:11 +01:00
Index = 0 ;
2021-03-24 08:35:54 +01:00
do {
2021-12-05 23:54:11 +01:00
Status = gBS - > OpenProtocol (
// Already in list?
2021-03-24 08:35:54 +01:00
ControllerHandle ,
2021-12-05 23:54:11 +01:00
gRequiredProtocol [ Index ] . DiscoveredProtocolGuid ,
( VOID * * ) & Id ,
2021-03-24 08:35:54 +01:00
This - > DriverBindingHandle ,
ControllerHandle ,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
) ;
if ( ! EFI_ERROR ( Status ) ) {
2021-12-05 23:54:11 +01:00
Index + + ;
if ( Index = = ( sizeof ( gRequiredProtocol ) / sizeof ( REDFISH_DISCOVER_REQUIRED_PROTOCOL ) ) ) {
2021-03-24 08:35:54 +01:00
break ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
continue ;
}
Status = gBS - > OpenProtocol (
ControllerHandle ,
2021-12-05 23:54:11 +01:00
gRequiredProtocol [ Index ] . RequiredServiceBindingProtocolGuid ,
2021-03-24 08:35:54 +01:00
& TempInterface ,
This - > DriverBindingHandle ,
ControllerHandle ,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
) ;
if ( EFI_ERROR ( Status ) ) {
2021-12-05 23:54:11 +01:00
Index + + ;
if ( Index = = ( sizeof ( gRequiredProtocol ) / sizeof ( REDFISH_DISCOVER_REQUIRED_PROTOCOL ) ) ) {
2021-03-24 08:35:54 +01:00
break ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
continue ;
}
2021-12-05 23:54:11 +01:00
if ( gRequiredProtocol [ Index ] . ProtocolType ! = ProtocolTypeRestEx ) {
2021-03-24 08:35:54 +01:00
OldTpl = gBS - > RaiseTPL ( EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL ) ;
2021-12-05 23:54:11 +01:00
Status = CreateRedfishDiscoverNetworkInterface ( ControllerHandle , gRequiredProtocol [ Index ] . ProtocolType , & IsNew , & NetworkInterface ) ;
2021-03-24 08:35:54 +01:00
if ( EFI_ERROR ( Status ) ) {
gBS - > RestoreTPL ( OldTpl ) ;
return Status ;
}
2021-12-05 23:54:11 +01:00
NetworkInterface - > NetworkProtocolType = gRequiredProtocol [ Index ] . ProtocolType ;
NetworkInterface - > OpenDriverAgentHandle = This - > DriverBindingHandle ;
NetworkInterface - > OpenDriverControllerHandle = ControllerHandle ;
2021-03-24 08:35:54 +01:00
NetworkInterface - > NetworkInterfaceProtocolInfo . ProtocolGuid = \
2021-12-05 23:54:11 +01:00
* gRequiredProtocol [ Index ] . RequiredProtocolGuid ;
2021-03-24 08:35:54 +01:00
NetworkInterface - > NetworkInterfaceProtocolInfo . ProtocolServiceGuid = \
2021-12-05 23:54:11 +01:00
* gRequiredProtocol [ Index ] . RequiredServiceBindingProtocolGuid ;
ProtocolDiscoverIdPtr = & NetworkInterface - > NetworkInterfaceProtocolInfo . ProtocolDiscoverId ;
OpenDriverAgentHandle = NetworkInterface - > OpenDriverAgentHandle ;
OpenDriverControllerHandle = NetworkInterface - > OpenDriverControllerHandle ;
2021-03-24 08:35:54 +01:00
HandleOfProtocolInterfacePtr = & NetworkInterface - > NetworkInterfaceProtocolInfo . ProtocolControllerHandle ;
2021-12-05 23:54:11 +01:00
Interface = & NetworkInterface - > NetworkInterfaceProtocolInfo . NetworkProtocolInterface ;
2021-03-24 08:35:54 +01:00
NewNetworkInterfaceInstalled = TRUE ;
if ( IsNew ) {
InsertTailList ( & mEfiRedfishDiscoverNetworkInterface , & NetworkInterface - > Entry ) ;
2021-12-05 23:54:11 +01:00
mNumNetworkInterface + + ;
2021-03-24 08:35:54 +01:00
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
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 ;
}
2021-12-05 23:54:11 +01:00
RestExInstance - > OpenDriverAgentHandle = This - > DriverBindingHandle ;
2021-03-24 08:35:54 +01:00
RestExInstance - > OpenDriverControllerHandle = ControllerHandle ;
2021-12-05 23:54:11 +01:00
RestExInstance - > RestExControllerHandle = ControllerHandle ;
2021-03-24 08:35:54 +01:00
InitializeListHead ( & RestExInstance - > Entry ) ;
InsertTailList ( & mEfiRedfishDiscoverRestExInstance , & RestExInstance - > Entry ) ;
2021-12-05 23:54:11 +01:00
mNumRestExInstance + + ;
ProtocolDiscoverIdPtr = & RestExInstance - > RestExId ;
OpenDriverAgentHandle = RestExInstance - > OpenDriverAgentHandle ;
OpenDriverControllerHandle = RestExInstance - > OpenDriverControllerHandle ;
2021-03-24 08:35:54 +01:00
HandleOfProtocolInterfacePtr = & RestExInstance - > RestExChildHandle ;
2021-12-05 23:54:11 +01:00
Interface = ( VOID * * ) & RestExInstance - > RestExProtocolInterface ;
2021-03-24 08:35:54 +01:00
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
Status = gBS - > InstallProtocolInterface (
& ControllerHandle ,
2021-12-05 23:54:11 +01:00
gRequiredProtocol [ Index ] . DiscoveredProtocolGuid ,
2021-03-24 08:35:54 +01:00
EFI_NATIVE_INTERFACE ,
ProtocolDiscoverIdPtr
) ;
if ( EFI_ERROR ( Status ) ) {
2021-12-05 23:54:11 +01:00
Index + + ;
if ( Index = = ( sizeof ( gRequiredProtocol ) / sizeof ( REDFISH_DISCOVER_REQUIRED_PROTOCOL ) ) ) {
2021-03-24 08:35:54 +01:00
break ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
continue ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
//
// Create service binding child and open it BY_DRIVER.
//
Status = NetLibCreateServiceChild (
2021-12-05 23:54:11 +01:00
ControllerHandle ,
This - > ImageHandle ,
gRequiredProtocol [ Index ] . RequiredServiceBindingProtocolGuid ,
HandleOfProtocolInterfacePtr
) ;
2021-03-24 08:35:54 +01:00
if ( ! EFI_ERROR ( Status ) ) {
Status = gBS - > OpenProtocol (
2021-12-05 23:54:11 +01:00
* HandleOfProtocolInterfacePtr ,
gRequiredProtocol [ Index ] . RequiredProtocolGuid ,
Interface ,
OpenDriverAgentHandle ,
OpenDriverControllerHandle ,
EFI_OPEN_PROTOCOL_BY_DRIVER
) ;
2021-03-24 08:35:54 +01:00
if ( ! EFI_ERROR ( Status ) ) {
2021-12-05 23:54:11 +01:00
if ( ( EfiRedfishDiscoverProtocolHandle = = NULL ) & &
( gRequiredProtocol [ Index ] . ProtocolType = = ProtocolTypeRestEx ) & &
2021-03-24 08:35:54 +01:00
! IsListEmpty ( & mEfiRedfishDiscoverNetworkInterface )
2021-12-05 23:54:11 +01:00
)
{
2021-03-24 08:35:54 +01:00
// 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
) ;
2021-12-05 23:54:11 +01:00
} else if ( ( EfiRedfishDiscoverProtocolHandle ! = NULL ) & & NewNetworkInterfaceInstalled ) {
Status = gBS - > ReinstallProtocolInterface (
EfiRedfishDiscoverProtocolHandle ,
& gEfiRedfishDiscoverProtocolGuid ,
( VOID * ) & mRedfishDiscover ,
( VOID * ) & mRedfishDiscover
) ;
NewNetworkInterfaceInstalled = FALSE ;
2021-03-24 08:35:54 +01:00
}
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
return Status ;
} else {
2021-12-05 23:54:11 +01:00
Index + + ;
if ( Index = = ( sizeof ( gRequiredProtocol ) / sizeof ( REDFISH_DISCOVER_REQUIRED_PROTOCOL ) ) ) {
2021-03-24 08:35:54 +01:00
break ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
continue ;
}
2021-12-05 23:54:11 +01:00
} while ( Index < ( sizeof ( gRequiredProtocol ) / sizeof ( REDFISH_DISCOVER_REQUIRED_PROTOCOL ) ) ) ;
2021-03-24 08:35:54 +01:00
return EFI_UNSUPPORTED ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
/**
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 (
2021-12-05 23:54:11 +01:00
IN EFI_DRIVER_BINDING_PROTOCOL * ThisBindingProtocol ,
IN EFI_HANDLE ControllerHandle ,
IN REDFISH_DISCOVER_REQUIRED_PROTOCOL * ThisRequiredProtocol ,
IN EFI_HANDLE DriverAgentHandle ,
IN EFI_HANDLE DriverControllerHandle
)
2021-03-24 08:35:54 +01:00
{
2021-12-05 23:54:11 +01:00
EFI_STATUS Status ;
2021-03-24 08:35:54 +01:00
Status = gBS - > CloseProtocol (
2021-12-05 23:54:11 +01:00
ControllerHandle ,
ThisRequiredProtocol - > RequiredProtocolGuid ,
DriverAgentHandle ,
DriverControllerHandle
) ;
2021-03-24 08:35:54 +01:00
if ( ! EFI_ERROR ( Status ) ) {
2021-12-05 23:54:11 +01:00
NetLibDestroyServiceChild (
2021-03-24 08:35:54 +01:00
ControllerHandle ,
ThisBindingProtocol - > ImageHandle ,
ThisRequiredProtocol - > RequiredServiceBindingProtocolGuid ,
ControllerHandle
) ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
return Status ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
/**
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 ,
2021-12-05 23:54:11 +01:00
IN EFI_HANDLE ControllerHandle
2021-03-24 08:35:54 +01:00
)
{
2021-12-05 23:54:11 +01:00
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 + + ) {
2021-03-24 08:35:54 +01:00
Status = gBS - > HandleProtocol (
2021-12-05 23:54:11 +01:00
ControllerHandle ,
gRequiredProtocol [ Index ] . RequiredProtocolGuid ,
( VOID * * ) & Interface
) ;
2021-03-24 08:35:54 +01:00
if ( ! EFI_ERROR ( Status ) ) {
2021-12-05 23:54:11 +01:00
if ( gRequiredProtocol [ Index ] . ProtocolType ! = ProtocolTypeRestEx ) {
2021-03-24 08:35:54 +01:00
if ( IsListEmpty ( & mEfiRedfishDiscoverNetworkInterface ) ) {
return EFI_NOT_FOUND ;
}
2021-12-05 23:54:11 +01:00
OldTpl = gBS - > RaiseTPL ( EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL ) ;
2021-03-24 08:35:54 +01:00
ThisNetworkInterface = ( EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL * ) GetFirstNode ( & mEfiRedfishDiscoverNetworkInterface ) ;
while ( TRUE ) {
if ( ThisNetworkInterface - > NetworkInterfaceProtocolInfo . ProtocolControllerHandle = = ControllerHandle ) {
2021-12-05 23:54:11 +01:00
Status = CloseProtocolService (
// Close protocol and destroy service.
2021-03-24 08:35:54 +01:00
ThisBindingProtocol ,
ControllerHandle ,
2021-12-05 23:54:11 +01:00
& gRequiredProtocol [ Index ] ,
2021-03-24 08:35:54 +01:00
ThisNetworkInterface - > OpenDriverAgentHandle ,
ThisNetworkInterface - > OpenDriverControllerHandle
) ;
if ( ! EFI_ERROR ( Status ) ) {
Status = DestroyRedfishNetwrokInterface ( ThisNetworkInterface ) ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
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 ) ) {
2021-12-05 23:54:11 +01:00
DEBUG ( ( DEBUG_ERROR , " %a: Reinstall gEfiRedfishDiscoverProtocolGuid fail. " , __FUNCTION__ ) ) ;
2021-03-24 08:35:54 +01:00
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
return Status ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
if ( IsNodeAtEnd ( & mEfiRedfishDiscoverNetworkInterface , & ThisNetworkInterface - > Entry ) ) {
break ;
}
2021-12-05 23:54:11 +01:00
ThisNetworkInterface = ( EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL * ) GetNextNode ( & mEfiRedfishDiscoverNetworkInterface , & ThisNetworkInterface - > Entry ) ;
}
2021-03-24 08:35:54 +01:00
gBS - > RestoreTPL ( OldTpl ) ;
} else {
if ( IsListEmpty ( & mEfiRedfishDiscoverRestExInstance ) ) {
return EFI_NOT_FOUND ;
}
2021-12-05 23:54:11 +01:00
OldTpl = gBS - > RaiseTPL ( EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL ) ;
2021-03-24 08:35:54 +01:00
RestExInstance = ( EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL * ) GetFirstNode ( & mEfiRedfishDiscoverRestExInstance ) ;
while ( TRUE ) {
if ( RestExInstance - > RestExChildHandle = = ControllerHandle ) {
2021-12-05 23:54:11 +01:00
Status = CloseProtocolService (
// Close REST_EX protocol.
2021-03-24 08:35:54 +01:00
ThisBindingProtocol ,
ControllerHandle ,
2021-12-05 23:54:11 +01:00
& gRequiredProtocol [ Index ] ,
2021-03-24 08:35:54 +01:00
RestExInstance - > OpenDriverAgentHandle ,
RestExInstance - > OpenDriverControllerHandle
) ;
RemoveEntryList ( & RestExInstance - > Entry ) ;
FreePool ( ( VOID * ) RestExInstance ) ;
2021-12-05 23:54:11 +01:00
mNumRestExInstance - - ;
2021-03-24 08:35:54 +01:00
gBS - > RestoreTPL ( OldTpl ) ;
return Status ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
if ( IsNodeAtEnd ( & mEfiRedfishDiscoverRestExInstance , & RestExInstance - > Entry ) ) {
break ;
}
2021-12-05 23:54:11 +01:00
RestExInstance = ( EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL * ) GetNextNode ( & mEfiRedfishDiscoverRestExInstance , & RestExInstance - > Entry ) ;
}
2021-03-24 08:35:54 +01:00
gBS - > RestoreTPL ( OldTpl ) ;
}
}
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
return EFI_NOT_FOUND ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
/**
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 ) ;
}
2021-12-05 23:54:11 +01:00
EFI_DRIVER_BINDING_PROTOCOL gRedfishDiscoverDriverBinding = {
2021-03-24 08:35:54 +01:00
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
)
{
2021-12-05 23:54:11 +01:00
EFI_STATUS Status ;
2021-03-24 08:35:54 +01:00
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 (
2021-12-05 23:54:11 +01:00
IN EFI_HANDLE ImageHandle
2021-03-24 08:35:54 +01:00
)
{
2021-12-05 23:54:11 +01:00
EFI_STATUS Status ;
EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL * ThisNetworkInterface ;
2021-03-24 08:35:54 +01:00
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 ) ;
2021-12-05 23:54:11 +01:00
}
2021-03-24 08:35:54 +01:00
// 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 ) ;
2021-12-05 23:54:11 +01:00
Status = gBS - > UninstallProtocolInterface (
2021-03-24 08:35:54 +01:00
EfiRedfishDiscoverProtocolHandle ,
& gEfiRedfishDiscoverProtocolGuid ,
( VOID * ) & mRedfishDiscover
) ;
}
2021-12-05 23:54:11 +01:00
2021-03-24 08:35:54 +01:00
return Status ;
}