3 The implementation of EFI Redfidh Discover Protocol.
5 (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include "RedfishDiscoverInternal.h"
13 LIST_ENTRY mRedfishDiscoverList
;
14 LIST_ENTRY mRedfishInstanceList
;
15 EFI_SMBIOS_PROTOCOL
*mSmbios
= NULL
;
17 UINTN mNumNetworkInterface
= 0;
18 UINTN mNumRestExInstance
= 0;
19 LIST_ENTRY mEfiRedfishDiscoverNetworkInterface
;
20 LIST_ENTRY mEfiRedfishDiscoverRestExInstance
;
22 EFI_GUID mRedfishDiscoverTcp4InstanceGuid
= EFI_REDFISH_DISCOVER_TCP4_INSTANCE_GUID
;
23 EFI_GUID mRedfishDiscoverTcp6InstanceGuid
= EFI_REDFISH_DISCOVER_TCP6_INSTANCE_GUID
;
24 EFI_GUID mRedfishDiscoverRestExInstanceGuid
= EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_GUID
;
26 EFI_HANDLE EfiRedfishDiscoverProtocolHandle
= NULL
;
31 IN EFI_HANDLE ImageHandle
,
32 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*Instance
38 IN EFI_HANDLE ImageHandle
,
39 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*Instance
42 static REDFISH_DISCOVER_REQUIRED_PROTOCOL gRequiredProtocol
[] = {
45 L
"TCP4 Service Binding Protocol",
46 &gEfiTcp4ProtocolGuid
,
47 &gEfiTcp4ServiceBindingProtocolGuid
,
48 &mRedfishDiscoverTcp4InstanceGuid
,
53 L
"TCP6 Service Binding Protocol",
54 &gEfiTcp6ProtocolGuid
,
55 &gEfiTcp6ServiceBindingProtocolGuid
,
56 &mRedfishDiscoverTcp6InstanceGuid
,
61 L
"REST EX Service Binding Protocol",
62 &gEfiRestExProtocolGuid
,
63 &gEfiRestExServiceBindingProtocolGuid
,
64 &mRedfishDiscoverRestExInstanceGuid
,
70 This function creates REST EX instance for the found Resfish service.
71 by known owner handle.
73 @param[in] Instance EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
74 @param[in] Token Client token.
76 @retval NULL Instance not found.
77 @retval EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE The instance owned by this owner.
81 CreateRestExInstance (
82 IN EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
*Instance
,
83 IN EFI_REDFISH_DISCOVERED_TOKEN
*Token
88 Status
= RestExLibCreateChild (
90 FixedPcdGetBool (PcdRedfishDiscoverAccessModeInBand
) ? EfiRestExServiceInBandAccess
: EfiRestExServiceOutOfBandAccess
,
92 EfiRestExServiceRedfish
,
93 &Token
->DiscoverList
.RedfishInstances
->Information
.RedfishRestExHandle
99 This function gets EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
100 by known owner handle.
102 @param[in] ImageHandle Image handle owns EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE.
103 @param[in] TargetNetworkInterface Target network interface used by this EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE.
104 @param[in] DiscoverFlags EFI_REDFISH_DISCOVER_FLAG
106 @retval NULL Instance not found.
107 @retval EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE The instance owned by this owner.
110 EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
*
112 IN EFI_HANDLE ImageHandle
,
113 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*TargetNetworkInterface
,
114 IN EFI_REDFISH_DISCOVER_FLAG DiscoverFlags
117 EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
*ThisInstance
;
119 if (IsListEmpty (&mRedfishDiscoverList
)) {
124 (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
*)GetFirstNode (&mRedfishDiscoverList
);
126 if ((ThisInstance
->Owner
== ImageHandle
) &&
127 (ThisInstance
->DiscoverFlags
== DiscoverFlags
) &&
128 (ThisInstance
->NetworkInterface
== TargetNetworkInterface
))
133 if (IsNodeAtEnd (&mRedfishDiscoverList
, &ThisInstance
->Entry
)) {
138 (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
*)GetNextNode (&mRedfishDiscoverList
, &ThisInstance
->Entry
);
145 This function gets the subnet information of this TCP4 instance.
147 @param[in] ImageHandle EFI handle with this image.
148 @param[in] Instance Instance of Network interface.
149 @retval EFI_STATUS Get subnet information successfully.
150 @retval Otherwise Fail to get subnet information.
155 IN EFI_HANDLE ImageHandle
,
156 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*Instance
160 EFI_TCP4_PROTOCOL
*Tcp4
;
161 EFI_TCP4_CONFIG_DATA Tcp4CfgData
;
162 EFI_TCP4_OPTION Tcp4Option
;
163 EFI_IP4_MODE_DATA IpModedata
;
164 UINT8 SubnetMaskIndex
;
167 BOOLEAN GotPrefixLength
;
169 if (Instance
== NULL
) {
170 return EFI_INVALID_PARAMETER
;
173 Tcp4
= (EFI_TCP4_PROTOCOL
*)Instance
->NetworkInterfaceProtocolInfo
.NetworkProtocolInterface
;
175 ZeroMem ((VOID
*)&Tcp4CfgData
, sizeof (EFI_TCP4_CONFIG_DATA
));
176 ZeroMem ((VOID
*)&Tcp4Option
, sizeof (EFI_TCP4_OPTION
));
177 // Give a local host IP address just for getting subnet information.
178 Tcp4CfgData
.AccessPoint
.UseDefaultAddress
= TRUE
;
179 Tcp4CfgData
.AccessPoint
.RemoteAddress
.Addr
[0] = 127;
180 Tcp4CfgData
.AccessPoint
.RemoteAddress
.Addr
[1] = 0;
181 Tcp4CfgData
.AccessPoint
.RemoteAddress
.Addr
[2] = 0;
182 Tcp4CfgData
.AccessPoint
.RemoteAddress
.Addr
[3] = 1;
183 Tcp4CfgData
.AccessPoint
.RemotePort
= 80;
184 Tcp4CfgData
.AccessPoint
.ActiveFlag
= TRUE
;
186 Tcp4CfgData
.ControlOption
= &Tcp4Option
;
187 Tcp4Option
.ReceiveBufferSize
= 65535;
188 Tcp4Option
.SendBufferSize
= 65535;
189 Tcp4Option
.MaxSynBackLog
= 5;
190 Tcp4Option
.ConnectionTimeout
= 60;
191 Tcp4Option
.DataRetries
= 12;
192 Tcp4Option
.FinTimeout
= 2;
193 Tcp4Option
.KeepAliveProbes
= 6;
194 Tcp4Option
.KeepAliveTime
= 7200;
195 Tcp4Option
.KeepAliveInterval
= 30;
196 Tcp4Option
.EnableNagle
= TRUE
;
197 Status
= Tcp4
->Configure (Tcp4
, &Tcp4CfgData
);
198 if (EFI_ERROR (Status
)) {
199 DEBUG ((DEBUG_ERROR
, "%a: Can't get subnet information\n", __FUNCTION__
));
203 Status
= Tcp4
->GetModeData (Tcp4
, NULL
, NULL
, &IpModedata
, NULL
, NULL
);
204 if (EFI_ERROR (Status
)) {
205 DEBUG ((DEBUG_ERROR
, "%a: Can't get IP mode data information\n", __FUNCTION__
));
209 IP4_COPY_ADDRESS (&Instance
->SubnetMask
, &IpModedata
.ConfigData
.SubnetMask
);
210 Instance
->SubnetAddr
.v4
.Addr
[0] = IpModedata
.ConfigData
.StationAddress
.Addr
[0] & Instance
->SubnetMask
.v4
.Addr
[0];
211 Instance
->SubnetAddr
.v4
.Addr
[1] = IpModedata
.ConfigData
.StationAddress
.Addr
[1] & Instance
->SubnetMask
.v4
.Addr
[1];
212 Instance
->SubnetAddr
.v4
.Addr
[2] = IpModedata
.ConfigData
.StationAddress
.Addr
[2] & Instance
->SubnetMask
.v4
.Addr
[2];
213 Instance
->SubnetAddr
.v4
.Addr
[3] = IpModedata
.ConfigData
.StationAddress
.Addr
[3] & Instance
->SubnetMask
.v4
.Addr
[3];
215 // Calculate the subnet mask prefix.
217 GotPrefixLength
= FALSE
;
220 while (GotPrefixLength
== FALSE
&& SubnetMaskIndex
< 4) {
222 while (BitMask
!= 0) {
223 if ((Instance
->SubnetMask
.v4
.Addr
[SubnetMaskIndex
] & BitMask
) != 0) {
226 GotPrefixLength
= TRUE
;
230 BitMask
= BitMask
>> 1;
236 Instance
->SubnetPrefixLength
= PrefixLength
;
241 This function gets the subnet information of this TCP6 instance.
243 @param[in] ImageHandle EFI handle with this image.
244 @param[in] Instance Instance of Network interface.
245 @retval EFI_STATUS Get subnet information successfully.
246 @retval Otherwise Fail to get subnet information.
251 IN EFI_HANDLE ImageHandle
,
252 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*Instance
256 EFI_TCP6_PROTOCOL
*Tcp6
;
257 EFI_IP6_MODE_DATA IpModedata
;
259 if (Instance
== NULL
) {
260 return EFI_INVALID_PARAMETER
;
263 Tcp6
= (EFI_TCP6_PROTOCOL
*)Instance
->NetworkInterfaceProtocolInfo
.NetworkProtocolInterface
;
265 Status
= Tcp6
->GetModeData (Tcp6
, NULL
, NULL
, &IpModedata
, NULL
, NULL
);
266 if (EFI_ERROR (Status
)) {
267 DEBUG ((DEBUG_ERROR
, "%a: Can't get IP mode data information\n"));
271 if (IpModedata
.AddressCount
== 0) {
272 DEBUG ((DEBUG_INFO
, "%a: No IPv6 address configured.\n"));
275 if (Instance
->SubnetAddrInfoIPv6
!= NULL
) {
276 FreePool (Instance
->SubnetAddrInfoIPv6
);
279 Instance
->SubnetAddrInfoIPv6
= AllocateZeroPool (IpModedata
.AddressCount
* sizeof (EFI_IP6_ADDRESS_INFO
));
280 if (Instance
->SubnetAddrInfoIPv6
== NULL
) {
281 DEBUG ((DEBUG_ERROR
, "%a: Failed to allocate memory fir IPv6 subnet address information\n"));
282 return EFI_OUT_OF_RESOURCES
;
285 Instance
->SubnetAddrInfoIPv6Number
= IpModedata
.AddressCount
;
287 (VOID
*)Instance
->SubnetAddrInfoIPv6
,
288 (VOID
*)&IpModedata
.AddressList
,
289 IpModedata
.AddressCount
* sizeof (EFI_IP6_ADDRESS_INFO
)
291 FreePool (IpModedata
.AddressList
);
296 This function searches EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
297 instance with the given EFI_REDFISH_DISCOVER_NETWORK_INTERFACE.
299 @param[in] TargetNetworkInterface EFI_REDFISH_DISCOVER_NETWORK_INTERFACE.
300 NULL for all EFI_REDFISH_DISCOVER_NETWORK_INTERFACEs.
302 @retval Non-NULL EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL is returned.
303 @retval NULL Non of EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL instance is returned.
305 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*
306 GetTargetNetworkInterfaceInternal (
307 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE
*TargetNetworkInterface
310 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*ThisNetworkInterface
;
312 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface
);
314 if (CompareMem ((VOID
*)&ThisNetworkInterface
->MacAddress
, &TargetNetworkInterface
->MacAddress
, ThisNetworkInterface
->HwAddressSize
) == 0) {
315 return ThisNetworkInterface
;
318 if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterface
->Entry
)) {
322 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetNextNode (&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterface
->Entry
);
329 This function validate if target network interface is ready for discovering
332 @param[in] TargetNetworkInterface EFI_REDFISH_DISCOVER_NETWORK_INTERFACE.
333 NULL for all EFI_REDFISH_DISCOVER_NETWORK_INTERFACEs.
334 @param[in] Flags EFI_REDFISH_DISCOVER_FLAG
336 @retval EFI_SUCCESS Target network interface is ready to use.
337 @retval EFI_UNSUPPORTED Target network interface is not ready to use.
340 ValidateTargetNetworkInterface (
341 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE
*TargetNetworkInterface
,
342 IN EFI_REDFISH_DISCOVER_FLAG Flags
345 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*ThisNetworkInterface
;
347 if (IsListEmpty (&mEfiRedfishDiscoverNetworkInterface
) && (TargetNetworkInterface
== NULL
)) {
348 return EFI_UNSUPPORTED
;
351 if (TargetNetworkInterface
== NULL
) {
352 return EFI_SUCCESS
; // Return EFI_SUCCESS if no network interface is specified.
355 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface
);
357 if (CompareMem ((VOID
*)&ThisNetworkInterface
->MacAddress
, &TargetNetworkInterface
->MacAddress
, ThisNetworkInterface
->HwAddressSize
) == 0) {
361 if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterface
->Entry
)) {
362 return EFI_UNSUPPORTED
;
365 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetNextNode (&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterface
->Entry
);
368 if ((Flags
& EFI_REDFISH_DISCOVER_SSDP
) != 0) {
369 // Validate if UDP4/6 is supported on the given network interface.
370 // SSDP is not supported.
375 if (ThisNetworkInterface
->NetworkInterfaceProtocolInfo
.ProtocolControllerHandle
== NULL
) {
376 return EFI_UNSUPPORTED
; // The required protocol on this network interface is not found.
383 This function returns number of network interface instance.
385 @retval UINTN Number of network interface instances.
388 NumberOfNetworkInterface (
393 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*ThisNetworkInterface
;
395 if (IsListEmpty (&mEfiRedfishDiscoverNetworkInterface
)) {
400 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface
);
402 if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterface
->Entry
)) {
406 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetNextNode (&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterface
->Entry
);
414 This function checks the IP version supported on this
417 @param[in] ThisNetworkInterface EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
419 @retval TRUE Is IPv6, otherwise IPv4.
424 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*ThisNetworkInterface
427 if (ThisNetworkInterface
->NetworkProtocolType
== ProtocolTypeTcp6
) {
435 This function discover Redfish service through SMBIOS host interface.
437 @param[in] Instance EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
439 @retval EFI_SUCCESS Redfish service is discovered through SMBIOS Host interface.
440 @retval Others Fail to discover Redfish service throught SMBIOS host interface
444 DiscoverRedfishHostInterface (
445 IN EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
*Instance
449 REDFISH_OVER_IP_PROTOCOL_DATA
*Data
;
450 REDFISH_INTERFACE_DATA
*DeviceDescriptor
;
451 CHAR8 UuidStr
[sizeof "00000000-0000-0000-0000-000000000000" + 1];
452 CHAR16 Ipv6Str
[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" + 1];
453 CHAR8 RedfishServiceLocateStr
[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" + 1];
455 UINTN MacCompareStstus
;
459 DeviceDescriptor
= NULL
;
461 if (mSmbios
== NULL
) {
462 Status
= gBS
->LocateProtocol (&gEfiSmbiosProtocolGuid
, NULL
, (VOID
**)&mSmbios
);
463 if (EFI_ERROR (Status
)) {
468 Status
= RedfishGetHostInterfaceProtocolData (mSmbios
, &DeviceDescriptor
, &Data
); // Search for SMBIOS type 42h
469 if (!EFI_ERROR (Status
) && (Data
!= NULL
) && (DeviceDescriptor
!= NULL
)) {
471 // Chceck if we can reach out Redfish service using this network interface.
472 // Check with MAC address using Device Descroptor Data Device Type 04 and Type 05.
473 // Those two types of Redfish host interface device has MAC information.
475 if (DeviceDescriptor
->DeviceType
== REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE_V2
) {
476 MacCompareStstus
= CompareMem (&Instance
->NetworkInterface
->MacAddress
, &DeviceDescriptor
->DeviceDescriptor
.PciPcieDeviceV2
.MacAddress
, 6);
477 } else if (DeviceDescriptor
->DeviceType
== REDFISH_HOST_INTERFACE_DEVICE_TYPE_USB_V2
) {
478 MacCompareStstus
= CompareMem (&Instance
->NetworkInterface
->MacAddress
, &DeviceDescriptor
->DeviceDescriptor
.UsbDeviceV2
.MacAddress
, 6);
480 return EFI_UNSUPPORTED
;
483 if (MacCompareStstus
!= 0) {
484 return EFI_UNSUPPORTED
;
487 if (Data
->RedfishServiceIpAddressFormat
== 1) {
488 IP4_COPY_ADDRESS ((VOID
*)&Instance
->TargetIpAddress
.v4
, (VOID
*)Data
->RedfishServiceIpAddress
);
490 IP6_COPY_ADDRESS ((VOID
*)&Instance
->TargetIpAddress
.v6
, (VOID
*)Data
->RedfishServiceIpAddress
);
493 if (Instance
->HostIntfValidation
) {
494 DEBUG ((DEBUG_ERROR
, "%a:Send UPnP unicast SSDP to validate this Redfish Host Interface is not supported.\n", __FUNCTION__
));
495 Status
= EFI_UNSUPPORTED
;
498 // Add this istance to list without detial information of Redfish
502 if (Data
->RedfishServiceIpPort
== 443) {
506 StrSize
= sizeof (UuidStr
);
507 AsciiSPrint (UuidStr
, StrSize
, "%g", &Data
->ServiceUuid
);
509 // Generate Redfish service location string.
511 if (Data
->RedfishServiceIpAddressFormat
== REDFISH_HOST_INTERFACE_HOST_IP_ADDRESS_FORMAT_IP6
) {
512 NetLibIp6ToStr ((IPv6_ADDRESS
*)&Data
->RedfishServiceIpAddress
, Ipv6Str
, sizeof (Ipv6Str
));
513 if ((Data
->RedfishServiceIpPort
== 0) || (IsHttps
== TRUE
)) {
514 AsciiSPrintUnicodeFormat (
515 RedfishServiceLocateStr
,
516 sizeof (RedfishServiceLocateStr
),
521 AsciiSPrintUnicodeFormat (
522 RedfishServiceLocateStr
,
523 sizeof (RedfishServiceLocateStr
),
526 Data
->RedfishServiceIpPort
530 if ((Data
->RedfishServiceIpPort
== 0) || (IsHttps
== TRUE
)) {
532 RedfishServiceLocateStr
,
533 sizeof (RedfishServiceLocateStr
),
535 Data
->RedfishServiceIpAddress
[0],
536 Data
->RedfishServiceIpAddress
[1],
537 Data
->RedfishServiceIpAddress
[2],
538 Data
->RedfishServiceIpAddress
[3]
542 RedfishServiceLocateStr
,
543 sizeof (RedfishServiceLocateStr
),
545 Data
->RedfishServiceIpAddress
[0],
546 Data
->RedfishServiceIpAddress
[1],
547 Data
->RedfishServiceIpAddress
[2],
548 Data
->RedfishServiceIpAddress
[3],
549 Data
->RedfishServiceIpPort
554 Status
= AddAndSignalNewRedfishService (
557 RedfishServiceLocateStr
,
572 The function adds a new found Redfish service to internal list and
575 @param[in] Instance EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE.
576 @param[in] RedfishVersion Redfish version.
577 @param[in] RedfishLocation Redfish location.
578 @param[in] Uuid Service UUID string.
579 @param[in] Os OS string.
580 @param[in] OsVer OS version string.
581 @param[in] Product Product string.
582 @param[in] ProductVer Product verison string.
583 @param[in] UseHttps Redfish service requires secured connection.
584 @retval EFI_SUCCESS Redfish service is added to list successfully.
588 AddAndSignalNewRedfishService (
589 IN EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
*Instance
,
590 IN UINTN
*RedfishVersion OPTIONAL
,
591 IN CHAR8
*RedfishLocation OPTIONAL
,
592 IN CHAR8
*Uuid OPTIONAL
,
593 IN CHAR8
*Os OPTIONAL
,
594 IN CHAR8
*OsVer OPTIONAL
,
595 IN CHAR8
*Product OPTIONAL
,
596 IN CHAR8
*ProductVer OPTIONAL
,
602 BOOLEAN RestExOpened
;
603 BOOLEAN DeleteRestEx
;
605 EFI_REDFISH_DISCOVERED_INTERNAL_LIST
*DiscoveredList
;
606 EFI_REDFISH_DISCOVERED_INSTANCE
*DiscoveredInstance
;
608 EFI_REST_EX_PROTOCOL
*RestEx
;
609 EFI_REST_EX_HTTP_CONFIG_DATA
*RestExHttpConfigData
;
610 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*NetworkInterface
;
615 RestExOpened
= FALSE
;
616 DeleteRestEx
= FALSE
;
618 DEBUG ((DEBUG_INFO
, "%a:Add this instance to Redfish instance list.\n", __FUNCTION__
));
621 Char16Uuid
= (CHAR16
*)AllocateZeroPool (AsciiStrSize ((const CHAR8
*)Uuid
) * sizeof (CHAR16
));
622 AsciiStrToUnicodeStrS ((const CHAR8
*)Uuid
, Char16Uuid
, AsciiStrSize ((const CHAR8
*)Uuid
) * sizeof (CHAR16
));
625 DiscoveredList
= NULL
;
626 DiscoveredInstance
= NULL
;
627 RestExHttpConfigData
= NULL
;
629 NetworkInterface
= Instance
->NetworkInterface
;
630 if (!IsListEmpty (&mRedfishInstanceList
)) {
632 // Is this a duplicate redfish service.
634 DiscoveredList
= (EFI_REDFISH_DISCOVERED_INTERNAL_LIST
*)GetFirstNode (&mRedfishInstanceList
);
637 if ((Char16Uuid
== NULL
) || (DiscoveredList
->Instance
->Information
.Uuid
== NULL
)) {
639 // Check if this Redfish instance already found using IP addrress.
641 if (!CheckIsIpVersion6 (NetworkInterface
)) {
643 (VOID
*)&Instance
->TargetIpAddress
.v4
,
644 (VOID
*)&DiscoveredList
->Instance
->Information
.RedfishHostIpAddress
.v4
,
645 sizeof (EFI_IPv4_ADDRESS
)
648 DiscoveredInstance
= DiscoveredList
->Instance
;
649 if ((DiscoveredList
->Instance
->Information
.Uuid
== NULL
) &&
650 (Char16Uuid
!= NULL
))
653 DiscoveredInstance
= DiscoveredList
->Instance
;
654 DEBUG ((DEBUG_INFO
, "*** This Redfish Service information refresh ***\n"));
661 (VOID
*)&Instance
->TargetIpAddress
.v6
,
662 (VOID
*)&DiscoveredList
->Instance
->Information
.RedfishHostIpAddress
.v6
,
663 sizeof (EFI_IPv6_ADDRESS
)
666 DiscoveredInstance
= DiscoveredList
->Instance
;
672 // Check if this Redfish instance already found using UUID.
674 if (StrCmp ((const CHAR16
*)Char16Uuid
, (const CHAR16
*)DiscoveredList
->Instance
->Information
.Uuid
) == 0) {
675 DiscoveredInstance
= DiscoveredList
->Instance
;
680 if (IsNodeAtEnd (&mRedfishInstanceList
, &DiscoveredList
->NextInstance
)) {
685 DiscoveredList
= (EFI_REDFISH_DISCOVERED_INTERNAL_LIST
*)GetNextNode (&mRedfishInstanceList
, &DiscoveredList
->NextInstance
);
689 if (NewFound
|| InfoRefresh
) {
691 DiscoveredList
= (EFI_REDFISH_DISCOVERED_INTERNAL_LIST
*)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVERED_INTERNAL_LIST
));
692 if (DiscoveredList
== NULL
) {
693 return EFI_OUT_OF_RESOURCES
;
696 InitializeListHead (&DiscoveredList
->NextInstance
);
697 DiscoveredInstance
= (EFI_REDFISH_DISCOVERED_INSTANCE
*)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVERED_INSTANCE
));
698 if (DiscoveredInstance
== NULL
) {
699 FreePool ((VOID
*)DiscoveredList
);
700 return EFI_OUT_OF_RESOURCES
;
704 DEBUG ((DEBUG_INFO
, "*** Redfish Service Information ***\n"));
706 DiscoveredInstance
->Information
.UseHttps
= UseHttps
;
707 if (RedfishVersion
!= NULL
) {
708 DiscoveredInstance
->Information
.RedfishVersion
= *RedfishVersion
;
709 DEBUG ((DEBUG_INFO
, "Redfish service version: %d.\n", DiscoveredInstance
->Information
.RedfishVersion
));
712 if (RedfishLocation
!= NULL
) {
713 DiscoveredInstance
->Information
.Location
= (CHAR16
*)AllocatePool (AsciiStrSize ((const CHAR8
*)RedfishLocation
) * sizeof (CHAR16
));
714 AsciiStrToUnicodeStrS ((const CHAR8
*)RedfishLocation
, DiscoveredInstance
->Information
.Location
, AsciiStrSize ((const CHAR8
*)RedfishLocation
) * sizeof (CHAR16
));
715 DEBUG ((DEBUG_INFO
, "Redfish service location: %s.\n", DiscoveredInstance
->Information
.Location
));
719 DiscoveredInstance
->Information
.Uuid
= (CHAR16
*)AllocatePool (AsciiStrSize ((const CHAR8
*)Uuid
) * sizeof (CHAR16
));
720 AsciiStrToUnicodeStrS ((const CHAR8
*)Uuid
, DiscoveredInstance
->Information
.Uuid
, AsciiStrSize ((const CHAR8
*)Uuid
) * sizeof (CHAR16
));
721 DEBUG ((DEBUG_INFO
, "Service UUID: %s.\n", DiscoveredInstance
->Information
.Uuid
));
725 DiscoveredInstance
->Information
.Os
= (CHAR16
*)AllocatePool (AsciiStrSize ((const CHAR8
*)Os
) * sizeof (CHAR16
));
726 AsciiStrToUnicodeStrS ((const CHAR8
*)Os
, DiscoveredInstance
->Information
.Os
, AsciiStrSize ((const CHAR8
*)Os
) * sizeof (CHAR16
));
727 DEBUG ((DEBUG_INFO
, "Redfish service OS: %s, Version:%s.\n", DiscoveredInstance
->Information
.Os
, DiscoveredInstance
->Information
.OsVersion
));
731 DiscoveredInstance
->Information
.OsVersion
= (CHAR16
*)AllocatePool (AsciiStrSize ((const CHAR8
*)OsVer
) * sizeof (CHAR16
));
732 AsciiStrToUnicodeStrS ((const CHAR8
*)OsVer
, DiscoveredInstance
->Information
.OsVersion
, AsciiStrSize ((const CHAR8
*)OsVer
) * sizeof (CHAR16
));
735 if ((Product
!= NULL
) && (ProductVer
!= NULL
)) {
736 DiscoveredInstance
->Information
.Product
= (CHAR16
*)AllocatePool (AsciiStrSize ((const CHAR8
*)Product
) * sizeof (CHAR16
));
737 AsciiStrToUnicodeStrS ((const CHAR8
*)Product
, DiscoveredInstance
->Information
.Product
, AsciiStrSize ((const CHAR8
*)Product
) * sizeof (CHAR16
));
738 DiscoveredInstance
->Information
.ProductVer
= (CHAR16
*)AllocatePool (AsciiStrSize ((const CHAR8
*)ProductVer
) * sizeof (CHAR16
));
739 AsciiStrToUnicodeStrS ((const CHAR8
*)ProductVer
, DiscoveredInstance
->Information
.ProductVer
, AsciiStrSize ((const CHAR8
*)ProductVer
) * sizeof (CHAR16
));
740 DEBUG ((DEBUG_INFO
, "Redfish service product: %s, Version:%s.\n", DiscoveredInstance
->Information
.Product
, DiscoveredInstance
->Information
.ProductVer
));
743 if (RedfishLocation
== NULL
) {
744 // This is the Redfish reported from SMBIOS 42h
745 // without validation.
747 IP4_COPY_ADDRESS ((VOID
*)&DiscoveredInstance
->Information
.RedfishHostIpAddress
.v4
, (VOID
*)&Instance
->TargetIpAddress
.v4
);
751 DiscoveredList
->Instance
= DiscoveredInstance
;
752 InsertTailList (&mRedfishInstanceList
, &DiscoveredList
->NextInstance
);
755 DiscoveredInstance
->Status
= EFI_SUCCESS
;
757 if (DiscoveredList
!= NULL
) {
758 DEBUG ((DEBUG_INFO
, "*** This Redfish Service was already found ***\n"));
759 if (DiscoveredInstance
->Information
.Uuid
!= NULL
) {
760 DEBUG ((DEBUG_INFO
, "Service UUID: %s.\n", DiscoveredInstance
->Information
.Uuid
));
762 DEBUG ((DEBUG_INFO
, "Service UUID: unknown.\n"));
767 if (Char16Uuid
!= NULL
) {
768 FreePool ((VOID
*)Char16Uuid
);
771 Status
= EFI_SUCCESS
;
772 if (NewFound
|| InfoRefresh
) {
774 // Build up EFI_REDFISH_DISCOVERED_LIST in token.
776 Instance
->DiscoverToken
->DiscoverList
.NumberOfServiceFound
= 1;
777 Instance
->DiscoverToken
->DiscoverList
.RedfishInstances
= DiscoveredInstance
;
778 DiscoveredInstance
->Status
= EFI_SUCCESS
;
780 Status
= CreateRestExInstance (Instance
, Instance
->DiscoverToken
); // Create REST EX child.
781 if (EFI_ERROR (Status
)) {
782 DEBUG ((DEBUG_ERROR
, "%a:Can't create REST EX child instance.\n", __FUNCTION__
));
786 Status
= gBS
->OpenProtocol (
787 // Configure local host information.
788 Instance
->DiscoverToken
->DiscoverList
.RedfishInstances
->Information
.RedfishRestExHandle
,
789 &gEfiRestExProtocolGuid
,
791 Instance
->NetworkInterface
->OpenDriverAgentHandle
,
792 Instance
->NetworkInterface
->OpenDriverControllerHandle
,
793 EFI_OPEN_PROTOCOL_BY_DRIVER
795 if (EFI_ERROR (Status
)) {
801 RestExHttpConfigData
= AllocateZeroPool (sizeof (EFI_REST_EX_HTTP_CONFIG_DATA
));
802 if (RestExHttpConfigData
== NULL
) {
803 Status
= EFI_OUT_OF_RESOURCES
;
805 goto EXIT_FREE_CONFIG_DATA
;
808 RestExHttpConfigData
->SendReceiveTimeout
= 5000;
809 RestExHttpConfigData
->HttpConfigData
.HttpVersion
= HttpVersion11
;
810 RestExHttpConfigData
->HttpConfigData
.LocalAddressIsIPv6
= CheckIsIpVersion6 (NetworkInterface
);
811 if (RestExHttpConfigData
->HttpConfigData
.LocalAddressIsIPv6
) {
812 RestExHttpConfigData
->HttpConfigData
.AccessPoint
.IPv6Node
= AllocateZeroPool (sizeof (EFI_HTTPv6_ACCESS_POINT
));
813 if (RestExHttpConfigData
->HttpConfigData
.AccessPoint
.IPv6Node
== NULL
) {
814 Status
= EFI_OUT_OF_RESOURCES
;
815 goto EXIT_FREE_CONFIG_DATA
;
818 RestExHttpConfigData
->HttpConfigData
.AccessPoint
.IPv4Node
= AllocateZeroPool (sizeof (EFI_HTTPv4_ACCESS_POINT
));
819 if (RestExHttpConfigData
->HttpConfigData
.AccessPoint
.IPv4Node
== NULL
) {
820 Status
= EFI_OUT_OF_RESOURCES
;
821 goto EXIT_FREE_CONFIG_DATA
;
824 RestExHttpConfigData
->HttpConfigData
.AccessPoint
.IPv4Node
->UseDefaultAddress
= TRUE
;
827 Status
= RestEx
->Configure (
829 (EFI_REST_EX_CONFIG_DATA
)(UINT8
*)RestExHttpConfigData
831 if (EFI_ERROR (Status
)) {
832 DEBUG ((DEBUG_ERROR
, "%a:REST EX configured..\n", __FUNCTION__
));
838 // Signal client, close REST EX before signaling client.
842 Instance
->DiscoverToken
->DiscoverList
.RedfishInstances
->Information
.RedfishRestExHandle
,
843 &gEfiRestExProtocolGuid
,
844 Instance
->NetworkInterface
->OpenDriverAgentHandle
,
845 Instance
->NetworkInterface
->OpenDriverControllerHandle
847 RestExOpened
= FALSE
;
851 Status
= gBS
->SignalEvent (Instance
->DiscoverToken
->Event
);
852 if (!EFI_ERROR (Status
)) {
853 DEBUG ((DEBUG_ERROR
, "%a:No event to signal!\n", __FUNCTION__
));
858 if ((RestExHttpConfigData
!= NULL
) && (RestExHttpConfigData
->HttpConfigData
.AccessPoint
.IPv4Node
!= NULL
)) {
859 FreePool (RestExHttpConfigData
->HttpConfigData
.AccessPoint
.IPv4Node
);
862 EXIT_FREE_CONFIG_DATA
:;
863 if (RestExHttpConfigData
!= NULL
) {
864 FreePool ((VOID
*)RestExHttpConfigData
);
869 Instance
->DiscoverToken
->DiscoverList
.RedfishInstances
->Information
.RedfishRestExHandle
,
870 &gEfiRestExProtocolGuid
,
871 Instance
->NetworkInterface
->OpenDriverAgentHandle
,
872 Instance
->NetworkInterface
->OpenDriverControllerHandle
877 if (DeleteRestEx
&& RestExOpened
) {
879 Instance
->DiscoverToken
->DiscoverList
.RedfishInstances
->Information
.RedfishRestExHandle
,
880 &gEfiRestExProtocolGuid
,
881 Instance
->NetworkInterface
->OpenDriverAgentHandle
,
882 Instance
->NetworkInterface
->OpenDriverControllerHandle
891 This function gets the subnet information of this network interface instance.
892 can discover Redfish service on it.
894 @param[in] Instance EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL instance.
895 @param[in] ImageHandle EFI Image handle request the network interface list.
901 NetworkInterfaceGetSubnetInfo (
902 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*Instance
,
903 IN EFI_HANDLE ImageHandle
908 UINT32 IPv6InfoIndex
;
909 EFI_IP6_ADDRESS_INFO
*ThisSubnetAddrInfoIPv6
;
910 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*NewNetworkInterface
;
912 if (Instance
->GotSubnetInfo
) {
916 ProtocolType
= Instance
->NetworkProtocolType
;
917 if ((gRequiredProtocol
[ProtocolType
].GetSubnetInfo
!= NULL
) && (Instance
->GotSubnetInfo
== FALSE
)) {
918 Status
= gRequiredProtocol
[ProtocolType
].GetSubnetInfo (
922 if (EFI_ERROR (Status
)) {
923 DEBUG ((DEBUG_ERROR
, "%a:Faile to get Subnet infomation.\n", __FUNCTION__
));
926 DEBUG ((DEBUG_INFO
, "%a:MAC address: %s\n", __FUNCTION__
, Instance
->StrMacAddr
));
927 if (CheckIsIpVersion6 (Instance
)) {
928 if (Instance
->SubnetAddrInfoIPv6Number
== 0) {
929 DEBUG ((DEBUG_ERROR
, "%a: There is no Subnet infomation for IPv6 network interface.\n", __FUNCTION__
));
930 return EFI_NOT_FOUND
;
933 ThisSubnetAddrInfoIPv6
= Instance
->SubnetAddrInfoIPv6
; // First IPv6 address information.
934 IP6_COPY_ADDRESS (&Instance
->SubnetAddr
.v6
, &ThisSubnetAddrInfoIPv6
->Address
);
935 Instance
->SubnetPrefixLength
= ThisSubnetAddrInfoIPv6
->PrefixLength
;
938 " IPv6 Subnet ID:%d, Prefix length: %d.\n",
939 ThisSubnetAddrInfoIPv6
->Address
.Addr
[7] + (UINT16
)ThisSubnetAddrInfoIPv6
->Address
.Addr
[6] * 256,
940 ThisSubnetAddrInfoIPv6
->PrefixLength
944 // If this is IPv6, then we may have to propagate network interface for IPv6 network scopes
945 // according to the Ipv6 address information.
947 ThisSubnetAddrInfoIPv6
++;
948 for (IPv6InfoIndex
= 0; IPv6InfoIndex
< Instance
->SubnetAddrInfoIPv6Number
- 1; IPv6InfoIndex
++) {
950 // Build up addtional EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL instances.
952 NewNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
));
953 if (NewNetworkInterface
!= NULL
) {
954 CopyMem ((VOID
*)NewNetworkInterface
, (VOID
*)Instance
, sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
)); // Clone information of first instance.
955 IP6_COPY_ADDRESS (&NewNetworkInterface
->SubnetAddr
.v6
, &ThisSubnetAddrInfoIPv6
->Address
);
956 NewNetworkInterface
->SubnetPrefixLength
= ThisSubnetAddrInfoIPv6
->PrefixLength
;
957 NewNetworkInterface
->GotSubnetInfo
= TRUE
;
958 InsertTailList (&mEfiRedfishDiscoverNetworkInterface
, &NewNetworkInterface
->Entry
);
959 ThisSubnetAddrInfoIPv6
++;
960 mNumNetworkInterface
++;
963 " IPv6 Subnet ID:%d, Prefix length: %d.\n",
964 ThisSubnetAddrInfoIPv6
->Address
.Addr
[7] + (UINT16
)ThisSubnetAddrInfoIPv6
->Address
.Addr
[6] * 256,
965 ThisSubnetAddrInfoIPv6
->PrefixLength
969 return EFI_OUT_OF_RESOURCES
;
975 " IPv4 Subnet:%d.%d.%d.%d Subnet mask: %d.%d.%d.%d.\n",
976 Instance
->SubnetAddr
.v4
.Addr
[0],
977 Instance
->SubnetAddr
.v4
.Addr
[1],
978 Instance
->SubnetAddr
.v4
.Addr
[2],
979 Instance
->SubnetAddr
.v4
.Addr
[3],
980 Instance
->SubnetMask
.v4
.Addr
[0],
981 Instance
->SubnetMask
.v4
.Addr
[1],
982 Instance
->SubnetMask
.v4
.Addr
[2],
983 Instance
->SubnetMask
.v4
.Addr
[3]
989 Instance
->GotSubnetInfo
= TRUE
; // Only try to get Subnet Info once.
994 This function gets the network interface list which Redfish discover protocol
995 can discover Redfish service on it.
997 @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instance.
998 @param[in] ImageHandle EFI Image handle request the network interface list,
999 @param[out] NumberOfNetworkIntfs Number of network interfaces can do Redfish service discovery.
1000 @param[out] NetworkIntfInstances Network interface instances. It's an array of instance. The number of entries
1001 in array is indicated by NumberOfNetworkIntfs.
1002 Caller has to release the memory
1003 allocated by Redfish discover protocol.
1005 @retval EFI_SUCCESS The information of network interface is returned in NumberOfNetworkIntfs and
1006 NetworkIntfInstances.
1007 @retval Others Fail to return the information of network interface.
1012 RedfishServiceGetNetworkInterface (
1013 IN EFI_REDFISH_DISCOVER_PROTOCOL
*This
,
1014 IN EFI_HANDLE ImageHandle
,
1015 OUT UINTN
*NumberOfNetworkIntfs
,
1016 OUT EFI_REDFISH_DISCOVER_NETWORK_INTERFACE
**NetworkIntfInstances
1019 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*ThisNetworkInterfaceIntn
;
1020 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE
*ThisNetworkInterface
;
1022 if ((NetworkIntfInstances
== NULL
) || (NumberOfNetworkIntfs
== NULL
) || (ImageHandle
== NULL
)) {
1023 return EFI_INVALID_PARAMETER
;
1026 *NumberOfNetworkIntfs
= 0;
1027 *NetworkIntfInstances
= NULL
;
1029 if (IsListEmpty ((const LIST_ENTRY
*)&mEfiRedfishDiscoverNetworkInterface
)) {
1030 return EFI_NOT_FOUND
;
1033 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE
*)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE
) * mNumNetworkInterface
);
1034 if (ThisNetworkInterface
== NULL
) {
1035 return EFI_OUT_OF_RESOURCES
;
1038 *NetworkIntfInstances
= ThisNetworkInterface
;
1039 ThisNetworkInterfaceIntn
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface
);
1041 ThisNetworkInterface
->IsIpv6
= FALSE
;
1042 if (CheckIsIpVersion6 (ThisNetworkInterfaceIntn
)) {
1043 ThisNetworkInterface
->IsIpv6
= TRUE
;
1046 CopyMem ((VOID
*)&ThisNetworkInterface
->MacAddress
, &ThisNetworkInterfaceIntn
->MacAddress
, ThisNetworkInterfaceIntn
->HwAddressSize
);
1047 NetworkInterfaceGetSubnetInfo (ThisNetworkInterfaceIntn
, ImageHandle
); // Get subnet info.
1048 if (!ThisNetworkInterface
->IsIpv6
) {
1049 IP4_COPY_ADDRESS (&ThisNetworkInterface
->SubnetId
.v4
, &ThisNetworkInterfaceIntn
->SubnetAddr
.v4
); // IPv4 subnet information.
1051 IP6_COPY_ADDRESS (&ThisNetworkInterface
->SubnetId
.v6
, &ThisNetworkInterfaceIntn
->SubnetAddr
.v6
); // IPv6 subnet information in IPv6 address information.
1054 ThisNetworkInterface
->SubnetPrefixLength
= ThisNetworkInterfaceIntn
->SubnetPrefixLength
;
1055 ThisNetworkInterface
->VlanId
= ThisNetworkInterfaceIntn
->VlanId
;
1056 (*NumberOfNetworkIntfs
)++;
1057 if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterfaceIntn
->Entry
)) {
1061 ThisNetworkInterfaceIntn
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetNextNode (&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterfaceIntn
->Entry
);
1062 ThisNetworkInterface
++;
1069 This function acquires Redfish services by discovering static Redfish setting
1070 according to Redfish Host Interface or through SSDP. Returns a list of EFI
1071 handles in EFI_REDFISH_DISCOVERED_LIST. Each of EFI handle has cooresponding
1072 EFI REST EX instance installed on it. Each REST EX isntance is a child instance which
1073 created through EFI REST EX serivce protoocl for communicating with specific
1076 @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instance.
1077 @param[in] ImageHandle EFI image owns these Redfish service instances.
1078 @param[in] TargetNetworkInterface Target network interface to do the discovery.
1079 NULL means discover Redfish service on all network interfaces on platform.
1080 @param[in] Flags Redfish service discover flags.
1081 @param[in] Token EFI_REDFISH_DISCOVERED_TOKEN instance.
1082 The memory of EFI_REDFISH_DISCOVERED_LIST and the strings in
1083 EFI_REDFISH_DISCOVERED_INFORMATION are all allocated by Acquire()
1084 and must be freed when caller invoke Release().
1086 @retval EFI_SUCCESS REST EX instance of discovered Redfish services are returned.
1087 @retval EFI_INVALID_PARAMETERS ImageHandle == NULL, Flags == 0, Token == NULL, Token->Timeout > 5,
1088 or Token->Event == NULL.
1089 @retval Others Fail acquire Redfish services.
1094 RedfishServiceAcquireService (
1095 IN EFI_REDFISH_DISCOVER_PROTOCOL
*This
,
1096 IN EFI_HANDLE ImageHandle
,
1097 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE
*TargetNetworkInterface
,
1098 IN EFI_REDFISH_DISCOVER_FLAG Flags
,
1099 IN EFI_REDFISH_DISCOVERED_TOKEN
*Token
1102 EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
*Instance
;
1105 BOOLEAN NewInstance
;
1106 UINTN NumNetworkInterfaces
;
1107 UINTN NetworkInterfacesIndex
;
1108 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*TargetNetworkInterfaceInternal
;
1110 DEBUG ((DEBUG_INFO
, "%a:Entry.\n", __FUNCTION__
));
1113 // Validate parameters.
1115 if ((ImageHandle
== NULL
) || (Token
== NULL
) || ((Flags
& ~EFI_REDFISH_DISCOVER_VALIDATION
) == 0)) {
1116 DEBUG ((DEBUG_ERROR
, "%a:Invalid parameters.\n", __FUNCTION__
));
1117 return EFI_INVALID_PARAMETER
;
1121 // Validate target network interface.
1123 if (EFI_ERROR (ValidateTargetNetworkInterface (TargetNetworkInterface
, Flags
))) {
1124 return EFI_UNSUPPORTED
;
1127 if (TargetNetworkInterface
!= NULL
) {
1128 TargetNetworkInterfaceInternal
= GetTargetNetworkInterfaceInternal (TargetNetworkInterface
);
1129 NumNetworkInterfaces
= 1;
1131 TargetNetworkInterfaceInternal
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface
);
1132 NumNetworkInterfaces
= NumberOfNetworkInterface ();
1133 if (NumNetworkInterfaces
== 0) {
1134 DEBUG ((DEBUG_ERROR
, "%a:No network interface on platform.\n", __FUNCTION__
));
1135 return EFI_UNSUPPORTED
;
1139 for (NetworkInterfacesIndex
= 0; NetworkInterfacesIndex
< NumNetworkInterfaces
; NetworkInterfacesIndex
++) {
1140 Status1
= EFI_SUCCESS
;
1141 Status2
= EFI_SUCCESS
;
1142 NewInstance
= FALSE
;
1143 Instance
= GetInstanceByOwner (ImageHandle
, TargetNetworkInterfaceInternal
, Flags
& ~EFI_REDFISH_DISCOVER_VALIDATION
); // Check if we can re-use previous instance.
1144 if (Instance
== NULL
) {
1145 DEBUG ((DEBUG_INFO
, "%a:Create new EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE.\n", __FUNCTION__
));
1146 Instance
= (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
*)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
));
1147 if (Instance
== NULL
) {
1148 DEBUG ((DEBUG_ERROR
, "%a:Memory allocation fail.\n", __FUNCTION__
));
1151 InitializeListHead (&Instance
->Entry
);
1152 Instance
->Owner
= ImageHandle
;
1153 Instance
->DiscoverFlags
= Flags
& ~EFI_REDFISH_DISCOVER_VALIDATION
;
1154 Instance
->NetworkInterface
= TargetNetworkInterfaceInternal
;
1156 // Get subnet information in case subnet information is not set because
1157 // RedfishServiceGetNetworkInterfaces hasn't been called yet.
1159 NetworkInterfaceGetSubnetInfo (TargetNetworkInterfaceInternal
, ImageHandle
);
1163 if (TargetNetworkInterfaceInternal
->StrMacAddr
!= NULL
) {
1164 DEBUG ((DEBUG_INFO
, "%a:Acquire Redfish service on network interface MAC address:%s.\n", __FUNCTION__
, TargetNetworkInterfaceInternal
->StrMacAddr
));
1166 DEBUG ((DEBUG_INFO
, "%a:WARNING: No MAC address on this network interface.\n", __FUNCTION__
));
1169 Instance
->DiscoverToken
= Token
; // Always use the latest Token passed by caller.
1170 if ((Flags
& EFI_REDFISH_DISCOVER_HOST_INTERFACE
) != 0) {
1171 DEBUG ((DEBUG_INFO
, "%a:Redfish HOST interface discovery.\n", __FUNCTION__
));
1172 Instance
->HostIntfValidation
= FALSE
;
1173 if ((Flags
& EFI_REDFISH_DISCOVER_VALIDATION
) != 0) {
1174 Instance
->HostIntfValidation
= TRUE
;
1177 Status1
= DiscoverRedfishHostInterface (Instance
); // Discover Redfish service through Redfish Host Interface.
1180 if ((Flags
& EFI_REDFISH_DISCOVER_SSDP
) != 0) {
1181 DEBUG ((DEBUG_ERROR
, "%a:Redfish service discovery through SSDP is not supported\n", __FUNCTION__
));
1182 return EFI_UNSUPPORTED
;
1184 if (EFI_ERROR (Status1
) && EFI_ERROR (Status2
)) {
1185 FreePool ((VOID
*)Instance
);
1186 DEBUG ((DEBUG_ERROR
, "%a:Something wrong on Redfish service discovery Status1=%x, Status2=%x.\n", __FUNCTION__
, Status1
, Status2
));
1189 InsertTailList (&mRedfishDiscoverList
, &Instance
->Entry
);
1194 if (TargetNetworkInterface
== NULL
) {
1196 // Discover Redfish services on all of network interfaces.
1198 TargetNetworkInterfaceInternal
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetNextNode (&mEfiRedfishDiscoverNetworkInterface
, &TargetNetworkInterfaceInternal
->Entry
);
1206 This function aborts Redfish service discovery on the given network interface.
1208 @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instance.
1209 @param[in] TargetNetworkInterface Target network interface to do the discovery.
1211 @retval EFI_SUCCESS REST EX instance of discovered Redfish services are returned.
1212 @retval Others Fail to abort Redfish service discovery.
1217 RedfishServiceAbortAcquire (
1218 IN EFI_REDFISH_DISCOVER_PROTOCOL
*This
,
1219 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE
*TargetNetworkInterface OPTIONAL
1222 // This function is used to abort Redfish service discovery through SSDP
1223 // on the network interface. SSDP is optionally supprted by EFI_REDFISH_DISCOVER_PROTOCOL,
1224 // we dont have implementation for SSDP now.
1226 return EFI_UNSUPPORTED
;
1230 This function releases Redfish services found by RedfishServiceAcquire().
1232 @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instance.
1233 @param[in] InstanceList The Redfish service to release.
1235 @retval EFI_SUCCESS REST EX instances of discovered Redfish are released.
1236 @retval Others Fail to remove the entry
1241 RedfishServiceReleaseService (
1242 IN EFI_REDFISH_DISCOVER_PROTOCOL
*This
,
1243 IN EFI_REDFISH_DISCOVERED_LIST
*InstanceList
1247 BOOLEAN AnyFailRelease
;
1248 EFI_REDFISH_DISCOVERED_INSTANCE
*ThisRedfishInstance
;
1249 EFI_REDFISH_DISCOVERED_INTERNAL_LIST
*DiscoveredRedfishInstance
;
1251 if (IsListEmpty (&mRedfishInstanceList
)) {
1252 DEBUG ((DEBUG_ERROR
, "%a:No any discovered Redfish service.\n", __FUNCTION__
));
1253 return EFI_NOT_FOUND
;
1256 AnyFailRelease
= FALSE
;
1257 ThisRedfishInstance
= InstanceList
->RedfishInstances
;
1258 for (NumService
= 0; NumService
< InstanceList
->NumberOfServiceFound
; NumService
++) {
1259 DiscoveredRedfishInstance
= (EFI_REDFISH_DISCOVERED_INTERNAL_LIST
*)GetFirstNode (&mRedfishInstanceList
);
1261 if (DiscoveredRedfishInstance
->Instance
== ThisRedfishInstance
) {
1262 RemoveEntryList (&DiscoveredRedfishInstance
->NextInstance
);
1263 if (ThisRedfishInstance
->Information
.Location
!= NULL
) {
1264 FreePool (ThisRedfishInstance
->Information
.Location
);
1267 if (ThisRedfishInstance
->Information
.Uuid
!= NULL
) {
1268 FreePool (ThisRedfishInstance
->Information
.Uuid
);
1271 if (ThisRedfishInstance
->Information
.Os
!= NULL
) {
1272 FreePool (ThisRedfishInstance
->Information
.Os
);
1275 if (ThisRedfishInstance
->Information
.OsVersion
!= NULL
) {
1276 FreePool (ThisRedfishInstance
->Information
.OsVersion
);
1279 if (ThisRedfishInstance
->Information
.Product
!= NULL
) {
1280 FreePool (ThisRedfishInstance
->Information
.Product
);
1283 if (ThisRedfishInstance
->Information
.ProductVer
!= NULL
) {
1284 FreePool (ThisRedfishInstance
->Information
.ProductVer
);
1287 FreePool ((VOID
*)ThisRedfishInstance
);
1291 if (IsNodeAtEnd (&mRedfishInstanceList
, &DiscoveredRedfishInstance
->NextInstance
)) {
1295 DiscoveredRedfishInstance
= (EFI_REDFISH_DISCOVERED_INTERNAL_LIST
*)GetNextNode (&mRedfishInstanceList
, &DiscoveredRedfishInstance
->NextInstance
);
1298 AnyFailRelease
= TRUE
;
1301 // Release next discovered Redfish Service.
1303 ThisRedfishInstance
= (EFI_REDFISH_DISCOVERED_INSTANCE
*)((UINT8
*)ThisRedfishInstance
+ sizeof (EFI_REDFISH_DISCOVERED_INSTANCE
));
1306 if (AnyFailRelease
) {
1307 return EFI_NOT_FOUND
;
1313 EFI_REDFISH_DISCOVER_PROTOCOL mRedfishDiscover
= {
1314 RedfishServiceGetNetworkInterface
,
1315 RedfishServiceAcquireService
,
1316 RedfishServiceAbortAcquire
,
1317 RedfishServiceReleaseService
1321 This function create an EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL for the
1322 given network interface.
1325 @param[in] ControllerHandle MAC address of this network interface.
1326 @param[in] NetworkProtocolType Network protocol type.
1327 @param[out] IsNewInstance BOOLEAN means new instance or not.
1328 @param[out] NetworkInterface Pointer to to EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL.
1333 CreateRedfishDiscoverNetworkInterface (
1334 IN EFI_HANDLE ControllerHandle
,
1335 IN UINT32 NetworkProtocolType
,
1336 OUT BOOLEAN
*IsNewInstance
,
1337 OUT EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
**NetworkInterface
1340 EFI_MAC_ADDRESS MacAddress
;
1341 UINTN HwAddressSize
;
1342 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*ThisNetworkInterface
;
1343 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*NewNetworkInterface
;
1345 NetLibGetMacAddress (ControllerHandle
, &MacAddress
, &HwAddressSize
);
1346 NewNetworkInterface
= NULL
;
1347 *IsNewInstance
= TRUE
;
1348 if (!IsListEmpty ((const LIST_ENTRY
*)&mEfiRedfishDiscoverNetworkInterface
)) {
1350 // Check if this instance already exist.
1352 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface
);
1353 if (ThisNetworkInterface
!= NULL
) {
1355 if ((CompareMem ((CONST VOID
*)&ThisNetworkInterface
->MacAddress
.Addr
, (CONST VOID
*)&MacAddress
.Addr
, HwAddressSize
) == 0) &&
1356 (ThisNetworkInterface
->NetworkProtocolType
== NetworkProtocolType
))
1358 NewNetworkInterface
= ThisNetworkInterface
;
1359 *IsNewInstance
= FALSE
;
1363 if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterface
->Entry
)) {
1364 NewNetworkInterface
= NULL
;
1368 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetNextNode (&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterface
->Entry
);
1373 if (NewNetworkInterface
== NULL
) {
1375 // Create a new instance.
1377 NewNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
));
1378 if (NewNetworkInterface
== NULL
) {
1379 return EFI_OUT_OF_RESOURCES
;
1382 NewNetworkInterface
->HwAddressSize
= HwAddressSize
;
1383 CopyMem (&NewNetworkInterface
->MacAddress
.Addr
, &MacAddress
.Addr
, NewNetworkInterface
->HwAddressSize
);
1384 NetLibGetMacString (ControllerHandle
, NULL
, &NewNetworkInterface
->StrMacAddr
);
1385 NewNetworkInterface
->VlanId
= NetLibGetVlanId (ControllerHandle
);
1388 *NetworkInterface
= NewNetworkInterface
;
1393 This function destory network interface
1396 @param[in] ThisNetworkInterface EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL instance.
1401 DestroyRedfishNetwrokInterface (
1402 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*ThisNetworkInterface
1407 Status
= gBS
->UninstallProtocolInterface (
1408 ThisNetworkInterface
->OpenDriverControllerHandle
,
1409 gRequiredProtocol
[ThisNetworkInterface
->NetworkProtocolType
].DiscoveredProtocolGuid
,
1410 &ThisNetworkInterface
->NetworkInterfaceProtocolInfo
.ProtocolDiscoverId
1412 RemoveEntryList (&ThisNetworkInterface
->Entry
);
1413 mNumNetworkInterface
--;
1414 FreePool (ThisNetworkInterface
);
1419 Tests to see if the required protocols are provided on the given
1422 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1423 @param[in] ControllerHandle The handle of the controller to test. This handle
1424 must support a protocol interface that supplies
1425 an I/O abstraction to the driver.
1426 @retval EFI_SUCCESS One of required protocol is found.
1427 @retval EFI_UNSUPPORTED None of required protocol is found.
1430 TestForRequiredProtocols (
1431 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1432 IN EFI_HANDLE ControllerHandle
1439 for (Index
= 0; Index
< (sizeof (gRequiredProtocol
) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL
)); Index
++) {
1440 Status
= gBS
->OpenProtocol (
1442 gRequiredProtocol
[Index
].RequiredServiceBindingProtocolGuid
,
1444 This
->DriverBindingHandle
,
1446 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
1448 if (!EFI_ERROR (Status
)) {
1449 Status
= gBS
->OpenProtocol (
1451 gRequiredProtocol
[Index
].DiscoveredProtocolGuid
,
1453 This
->DriverBindingHandle
,
1455 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1457 if (EFI_ERROR (Status
)) {
1458 DEBUG ((DEBUG_ERROR
, "%a: %s is found on this controller handle.\n", __FUNCTION__
, gRequiredProtocol
[Index
].ProtocolName
));
1464 return EFI_UNSUPPORTED
;
1468 Build up network interface and create corresponding service through the given
1471 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1472 @param[in] ControllerHandle The handle of the controller to test. This handle
1473 must support a protocol interface that supplies
1474 an I/O abstraction to the driver.
1475 @retval EFI_SUCCESS One of required protocol is found.
1476 @retval EFI_UNSUPPORTED None of required protocol is found.
1477 @retval EFI_UNSUPPORTED Failed to build up network interface.
1480 BuildupNetworkInterface (
1481 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1482 IN EFI_HANDLE ControllerHandle
1487 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*NetworkInterface
;
1490 VOID
*TempInterface
;
1492 UINT32
*ProtocolDiscoverIdPtr
;
1493 EFI_HANDLE OpenDriverAgentHandle
;
1494 EFI_HANDLE OpenDriverControllerHandle
;
1495 EFI_HANDLE
*HandleOfProtocolInterfacePtr
;
1496 EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL
*RestExInstance
;
1498 BOOLEAN NewNetworkInterfaceInstalled
;
1500 NewNetworkInterfaceInstalled
= FALSE
;
1503 Status
= gBS
->OpenProtocol (
1506 gRequiredProtocol
[Index
].DiscoveredProtocolGuid
,
1508 This
->DriverBindingHandle
,
1510 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1512 if (!EFI_ERROR (Status
)) {
1514 if (Index
== (sizeof (gRequiredProtocol
) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL
))) {
1521 Status
= gBS
->OpenProtocol (
1523 gRequiredProtocol
[Index
].RequiredServiceBindingProtocolGuid
,
1525 This
->DriverBindingHandle
,
1527 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1529 if (EFI_ERROR (Status
)) {
1531 if (Index
== (sizeof (gRequiredProtocol
) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL
))) {
1538 if (gRequiredProtocol
[Index
].ProtocolType
!= ProtocolTypeRestEx
) {
1539 OldTpl
= gBS
->RaiseTPL (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL
);
1540 Status
= CreateRedfishDiscoverNetworkInterface (ControllerHandle
, gRequiredProtocol
[Index
].ProtocolType
, &IsNew
, &NetworkInterface
);
1541 if (EFI_ERROR (Status
)) {
1542 gBS
->RestoreTPL (OldTpl
);
1546 NetworkInterface
->NetworkProtocolType
= gRequiredProtocol
[Index
].ProtocolType
;
1547 NetworkInterface
->OpenDriverAgentHandle
= This
->DriverBindingHandle
;
1548 NetworkInterface
->OpenDriverControllerHandle
= ControllerHandle
;
1549 NetworkInterface
->NetworkInterfaceProtocolInfo
.ProtocolGuid
= \
1550 *gRequiredProtocol
[Index
].RequiredProtocolGuid
;
1551 NetworkInterface
->NetworkInterfaceProtocolInfo
.ProtocolServiceGuid
= \
1552 *gRequiredProtocol
[Index
].RequiredServiceBindingProtocolGuid
;
1553 ProtocolDiscoverIdPtr
= &NetworkInterface
->NetworkInterfaceProtocolInfo
.ProtocolDiscoverId
;
1554 OpenDriverAgentHandle
= NetworkInterface
->OpenDriverAgentHandle
;
1555 OpenDriverControllerHandle
= NetworkInterface
->OpenDriverControllerHandle
;
1556 HandleOfProtocolInterfacePtr
= &NetworkInterface
->NetworkInterfaceProtocolInfo
.ProtocolControllerHandle
;
1557 Interface
= &NetworkInterface
->NetworkInterfaceProtocolInfo
.NetworkProtocolInterface
;
1558 NewNetworkInterfaceInstalled
= TRUE
;
1560 InsertTailList (&mEfiRedfishDiscoverNetworkInterface
, &NetworkInterface
->Entry
);
1561 mNumNetworkInterface
++;
1564 gBS
->RestoreTPL (OldTpl
);
1566 // Record REST_EX instance. REST_EX is created when clinet asks for Redfish service discovery.
1567 // Redfish Service Discover protocol will match REST EX to the corresponding EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
1570 RestExInstance
= (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL
*)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL
));
1571 if (RestExInstance
== NULL
) {
1572 return EFI_OUT_OF_RESOURCES
;
1575 RestExInstance
->OpenDriverAgentHandle
= This
->DriverBindingHandle
;
1576 RestExInstance
->OpenDriverControllerHandle
= ControllerHandle
;
1577 RestExInstance
->RestExControllerHandle
= ControllerHandle
;
1578 InitializeListHead (&RestExInstance
->Entry
);
1579 InsertTailList (&mEfiRedfishDiscoverRestExInstance
, &RestExInstance
->Entry
);
1580 mNumRestExInstance
++;
1581 ProtocolDiscoverIdPtr
= &RestExInstance
->RestExId
;
1582 OpenDriverAgentHandle
= RestExInstance
->OpenDriverAgentHandle
;
1583 OpenDriverControllerHandle
= RestExInstance
->OpenDriverControllerHandle
;
1584 HandleOfProtocolInterfacePtr
= &RestExInstance
->RestExChildHandle
;
1585 Interface
= (VOID
**)&RestExInstance
->RestExProtocolInterface
;
1588 Status
= gBS
->InstallProtocolInterface (
1590 gRequiredProtocol
[Index
].DiscoveredProtocolGuid
,
1591 EFI_NATIVE_INTERFACE
,
1592 ProtocolDiscoverIdPtr
1594 if (EFI_ERROR (Status
)) {
1596 if (Index
== (sizeof (gRequiredProtocol
) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL
))) {
1604 // Create service binding child and open it BY_DRIVER.
1606 Status
= NetLibCreateServiceChild (
1609 gRequiredProtocol
[Index
].RequiredServiceBindingProtocolGuid
,
1610 HandleOfProtocolInterfacePtr
1612 if (!EFI_ERROR (Status
)) {
1613 Status
= gBS
->OpenProtocol (
1614 *HandleOfProtocolInterfacePtr
,
1615 gRequiredProtocol
[Index
].RequiredProtocolGuid
,
1617 OpenDriverAgentHandle
,
1618 OpenDriverControllerHandle
,
1619 EFI_OPEN_PROTOCOL_BY_DRIVER
1621 if (!EFI_ERROR (Status
)) {
1622 if ((EfiRedfishDiscoverProtocolHandle
== NULL
) &&
1623 (gRequiredProtocol
[Index
].ProtocolType
== ProtocolTypeRestEx
) &&
1624 !IsListEmpty (&mEfiRedfishDiscoverNetworkInterface
)
1627 // Install the fisrt Redfish Discover Protocol when EFI REST EX protcol is discovered.
1628 // This ensures EFI REST EX is ready while EFI_REDFISH_DISCOVER_PROTOCOL consumer acquires
1629 // Redfish serivce over network interface.
1631 Status
= gBS
->InstallProtocolInterface (
1632 &EfiRedfishDiscoverProtocolHandle
,
1633 &gEfiRedfishDiscoverProtocolGuid
,
1634 EFI_NATIVE_INTERFACE
,
1635 (VOID
*)&mRedfishDiscover
1637 } else if ((EfiRedfishDiscoverProtocolHandle
!= NULL
) && NewNetworkInterfaceInstalled
) {
1638 Status
= gBS
->ReinstallProtocolInterface (
1639 EfiRedfishDiscoverProtocolHandle
,
1640 &gEfiRedfishDiscoverProtocolGuid
,
1641 (VOID
*)&mRedfishDiscover
,
1642 (VOID
*)&mRedfishDiscover
1644 NewNetworkInterfaceInstalled
= FALSE
;
1651 if (Index
== (sizeof (gRequiredProtocol
) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL
))) {
1657 } while (Index
< (sizeof (gRequiredProtocol
) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL
)));
1659 return EFI_UNSUPPORTED
;
1663 Close the protocol opened for Redfish discovery. This function also destories
1664 the network services.
1666 @param[in] ThisBindingProtocol A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1667 @param[in] ControllerHandle The handle of the controller to test. This handle
1668 must support a protocol interface that supplies
1669 an I/O abstraction to the driver.
1670 @param[in] ThisRequiredProtocol Pointer to the instance of REDFISH_DISCOVER_REQUIRED_PROTOCOL.
1671 @param[in] DriverAgentHandle Driver agent handle which used to open protocol earlier.
1672 @param[in] DriverControllerHandle Driver controller handle which used to open protocol earlier.
1674 @retval EFI_SUCCESS Prorocol is closed successfully.
1675 @retval Others Prorocol is closed unsuccessfully.
1679 CloseProtocolService (
1680 IN EFI_DRIVER_BINDING_PROTOCOL
*ThisBindingProtocol
,
1681 IN EFI_HANDLE ControllerHandle
,
1682 IN REDFISH_DISCOVER_REQUIRED_PROTOCOL
*ThisRequiredProtocol
,
1683 IN EFI_HANDLE DriverAgentHandle
,
1684 IN EFI_HANDLE DriverControllerHandle
1689 Status
= gBS
->CloseProtocol (
1691 ThisRequiredProtocol
->RequiredProtocolGuid
,
1693 DriverControllerHandle
1695 if (!EFI_ERROR (Status
)) {
1696 NetLibDestroyServiceChild (
1698 ThisBindingProtocol
->ImageHandle
,
1699 ThisRequiredProtocol
->RequiredServiceBindingProtocolGuid
,
1708 Stop the services on network interface.
1710 @param[in] ThisBindingProtocol A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1711 @param[in] ControllerHandle The handle of the controller to test. This handle
1712 must support a protocol interface that supplies
1713 an I/O abstraction to the driver.
1714 @retval EFI_SUCCESS One of required protocol is found.
1715 @retval Others Faile to stop the services on network interface.
1718 StopServiceOnNetworkInterface (
1719 IN EFI_DRIVER_BINDING_PROTOCOL
*ThisBindingProtocol
,
1720 IN EFI_HANDLE ControllerHandle
1727 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*ThisNetworkInterface
;
1728 EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL
*RestExInstance
;
1730 for (Index
= 0; Index
< (sizeof (gRequiredProtocol
) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL
)); Index
++) {
1731 Status
= gBS
->HandleProtocol (
1733 gRequiredProtocol
[Index
].RequiredProtocolGuid
,
1736 if (!EFI_ERROR (Status
)) {
1737 if (gRequiredProtocol
[Index
].ProtocolType
!= ProtocolTypeRestEx
) {
1738 if (IsListEmpty (&mEfiRedfishDiscoverNetworkInterface
)) {
1739 return EFI_NOT_FOUND
;
1742 OldTpl
= gBS
->RaiseTPL (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL
);
1743 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface
);
1745 if (ThisNetworkInterface
->NetworkInterfaceProtocolInfo
.ProtocolControllerHandle
== ControllerHandle
) {
1746 Status
= CloseProtocolService (
1747 // Close protocol and destroy service.
1748 ThisBindingProtocol
,
1750 &gRequiredProtocol
[Index
],
1751 ThisNetworkInterface
->OpenDriverAgentHandle
,
1752 ThisNetworkInterface
->OpenDriverControllerHandle
1754 if (!EFI_ERROR (Status
)) {
1755 Status
= DestroyRedfishNetwrokInterface (ThisNetworkInterface
);
1758 gBS
->RestoreTPL (OldTpl
);
1759 // Reinstall Redfish Discover protocol to notify network
1760 // interface change.
1762 Status
= gBS
->ReinstallProtocolInterface (
1763 EfiRedfishDiscoverProtocolHandle
,
1764 &gEfiRedfishDiscoverProtocolGuid
,
1765 (VOID
*)&mRedfishDiscover
,
1766 (VOID
*)&mRedfishDiscover
1768 if (EFI_ERROR (Status
)) {
1769 DEBUG ((DEBUG_ERROR
, "%a: Reinstall gEfiRedfishDiscoverProtocolGuid fail.", __FUNCTION__
));
1775 if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterface
->Entry
)) {
1779 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetNextNode (&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterface
->Entry
);
1782 gBS
->RestoreTPL (OldTpl
);
1784 if (IsListEmpty (&mEfiRedfishDiscoverRestExInstance
)) {
1785 return EFI_NOT_FOUND
;
1788 OldTpl
= gBS
->RaiseTPL (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL
);
1789 RestExInstance
= (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL
*)GetFirstNode (&mEfiRedfishDiscoverRestExInstance
);
1791 if (RestExInstance
->RestExChildHandle
== ControllerHandle
) {
1792 Status
= CloseProtocolService (
1793 // Close REST_EX protocol.
1794 ThisBindingProtocol
,
1796 &gRequiredProtocol
[Index
],
1797 RestExInstance
->OpenDriverAgentHandle
,
1798 RestExInstance
->OpenDriverControllerHandle
1800 RemoveEntryList (&RestExInstance
->Entry
);
1801 FreePool ((VOID
*)RestExInstance
);
1802 mNumRestExInstance
--;
1803 gBS
->RestoreTPL (OldTpl
);
1807 if (IsNodeAtEnd (&mEfiRedfishDiscoverRestExInstance
, &RestExInstance
->Entry
)) {
1811 RestExInstance
= (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL
*)GetNextNode (&mEfiRedfishDiscoverRestExInstance
, &RestExInstance
->Entry
);
1814 gBS
->RestoreTPL (OldTpl
);
1819 return EFI_NOT_FOUND
;
1823 Tests to see if this driver supports a given controller. If a child device is provided,
1824 it further tests to see if this driver supports creating a handle for the specified child device.
1826 This function checks to see if the driver specified by This supports the device specified by
1827 ControllerHandle. Drivers will typically use the device path attached to
1828 ControllerHandle and/or the services from the bus I/O abstraction attached to
1829 ControllerHandle to determine if the driver supports ControllerHandle. This function
1830 may be called many times during platform initialization. In order to reduce boot times, the tests
1831 performed by this function must be very small, and take as little time as possible to execute. This
1832 function must not change the state of any hardware devices, and this function must be aware that the
1833 device specified by ControllerHandle may already be managed by the same driver or a
1834 different driver. This function must match its calls to AllocatePages() with FreePages(),
1835 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
1836 Because ControllerHandle may have been previously started by the same driver, if a protocol is
1837 already in the opened state, then it must not be closed with CloseProtocol(). This is required
1838 to guarantee the state of ControllerHandle is not modified by this function.
1840 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1841 @param[in] ControllerHandle The handle of the controller to test. This handle
1842 must support a protocol interface that supplies
1843 an I/O abstraction to the driver.
1844 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
1845 parameter is ignored by device drivers, and is optional for bus
1846 drivers. For bus drivers, if this parameter is not NULL, then
1847 the bus driver must determine if the bus controller specified
1848 by ControllerHandle and the child controller specified
1849 by RemainingDevicePath are both supported by this
1852 @retval EFI_SUCCESS The device specified by ControllerHandle and
1853 RemainingDevicePath is supported by the driver specified by This.
1854 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
1855 RemainingDevicePath is already being managed by the driver
1857 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
1858 RemainingDevicePath is already being managed by a different
1859 driver or an application that requires exclusive access.
1860 Currently not implemented.
1861 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
1862 RemainingDevicePath is not supported by the driver specified by This.
1866 RedfishDiscoverDriverBindingSupported (
1867 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1868 IN EFI_HANDLE ControllerHandle
,
1869 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1872 return TestForRequiredProtocols (This
, ControllerHandle
);
1876 Starts a device controller or a bus controller.
1878 The Start() function is designed to be invoked from the EFI boot service ConnectController().
1879 As a result, much of the error checking on the parameters to Start() has been moved into this
1880 common boot service. It is legal to call Start() from other locations,
1881 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
1882 1. ControllerHandle must be a valid EFI_HANDLE.
1883 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
1884 EFI_DEVICE_PATH_PROTOCOL.
1885 3. Prior to calling Start(), the Supported() function for the driver specified by This must
1886 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
1888 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1889 @param[in] ControllerHandle The handle of the controller to start. This handle
1890 must support a protocol interface that supplies
1891 an I/O abstraction to the driver.
1892 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
1893 parameter is ignored by device drivers, and is optional for bus
1894 drivers. For a bus driver, if this parameter is NULL, then handles
1895 for all the children of Controller are created by this driver.
1896 If this parameter is not NULL and the first Device Path Node is
1897 not the End of Device Path Node, then only the handle for the
1898 child device specified by the first Device Path Node of
1899 RemainingDevicePath is created by this driver.
1900 If the first Device Path Node of RemainingDevicePath is
1901 the End of Device Path Node, no child handle is created by this
1904 @retval EFI_SUCCESS The device was started.
1905 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
1906 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1907 @retval Others The driver failded to start the device.
1912 RedfishDiscoverDriverBindingStart (
1913 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1914 IN EFI_HANDLE ControllerHandle
,
1915 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1918 return BuildupNetworkInterface (This
, ControllerHandle
);
1922 Stops a device controller or a bus controller.
1924 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
1925 As a result, much of the error checking on the parameters to Stop() has been moved
1926 into this common boot service. It is legal to call Stop() from other locations,
1927 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
1928 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
1929 same driver's Start() function.
1930 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
1931 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
1932 Start() function, and the Start() function must have called OpenProtocol() on
1933 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
1935 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1936 @param[in] ControllerHandle A handle to the device being stopped. The handle must
1937 support a bus specific I/O protocol for the driver
1938 to use to stop the device.
1939 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
1940 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
1941 if NumberOfChildren is 0.
1943 @retval EFI_SUCCESS The device was stopped.
1944 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
1949 RedfishDiscoverDriverBindingStop (
1950 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1951 IN EFI_HANDLE ControllerHandle
,
1952 IN UINTN NumberOfChildren
,
1953 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
1956 return StopServiceOnNetworkInterface (This
, ControllerHandle
);
1959 EFI_DRIVER_BINDING_PROTOCOL gRedfishDiscoverDriverBinding
= {
1960 RedfishDiscoverDriverBindingSupported
,
1961 RedfishDiscoverDriverBindingStart
,
1962 RedfishDiscoverDriverBindingStop
,
1963 REDFISH_DISCOVER_VERSION
,
1969 This is the declaration of an EFI image entry point.
1971 @param ImageHandle The firmware allocated handle for the UEFI image.
1972 @param SystemTable A pointer to the EFI System Table.
1974 @retval EFI_SUCCESS The operation completed successfully.
1975 @retval Others An unexpected error occurred.
1979 RedfishDiscoverEntryPoint (
1980 IN EFI_HANDLE ImageHandle
,
1981 IN EFI_SYSTEM_TABLE
*SystemTable
1986 Status
= EFI_SUCCESS
;
1987 InitializeListHead (&mRedfishDiscoverList
);
1988 InitializeListHead (&mRedfishInstanceList
);
1989 InitializeListHead (&mEfiRedfishDiscoverNetworkInterface
);
1990 InitializeListHead (&mEfiRedfishDiscoverRestExInstance
);
1992 // Install binding protoocl to obtain UDP and REST EX protocol.
1994 Status
= EfiLibInstallDriverBindingComponentName2 (
1997 &gRedfishDiscoverDriverBinding
,
1999 &gRedfishDiscoverComponentName
,
2000 &gRedfishDiscoverComponentName2
2006 This is the unload handle for Redfish discover module.
2008 Disconnect the driver specified by ImageHandle from all the devices in the handle database.
2009 Uninstall all the protocols installed in the driver entry point.
2011 @param[in] ImageHandle The drivers' driver image.
2013 @retval EFI_SUCCESS The image is unloaded.
2014 @retval Others Failed to unload the image.
2019 RedfishDiscoverUnload (
2020 IN EFI_HANDLE ImageHandle
2024 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*ThisNetworkInterface
;
2026 Status
= EFI_SUCCESS
;
2027 // Destroy all network interfaces found by EFI Redfish Discover driver and
2028 // stop services created for Redfish Discover.
2030 while (!IsListEmpty (&mEfiRedfishDiscoverNetworkInterface
)) {
2031 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface
);
2032 StopServiceOnNetworkInterface (&gRedfishDiscoverDriverBinding
, ThisNetworkInterface
->NetworkInterfaceProtocolInfo
.ProtocolControllerHandle
);
2035 // Disconnect EFI Redfish discover driver controller to notify the
2036 // clinet which uses .EFI Redfish discover protocol.
2038 if (EfiRedfishDiscoverProtocolHandle
!= NULL
) {
2040 // Notify user EFI_REDFISH_DISCOVER_PROTOCOL is unloaded.
2042 gBS
->DisconnectController (EfiRedfishDiscoverProtocolHandle
, NULL
, NULL
);
2043 Status
= gBS
->UninstallProtocolInterface (
2044 EfiRedfishDiscoverProtocolHandle
,
2045 &gEfiRedfishDiscoverProtocolGuid
,
2046 (VOID
*)&mRedfishDiscover