3 The implementation of EFI Redfidh Discover Protocol.
5 (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
6 Copyright (c) 2022, AMD Incorporated. All rights reserved.
8 SPDX-License-Identifier: BSD-2-Clause-Patent
12 #include "RedfishDiscoverInternal.h"
14 LIST_ENTRY mRedfishDiscoverList
;
15 LIST_ENTRY mRedfishInstanceList
;
16 EFI_SMBIOS_PROTOCOL
*mSmbios
= NULL
;
18 UINTN mNumNetworkInterface
= 0;
19 UINTN mNumRestExInstance
= 0;
20 LIST_ENTRY mEfiRedfishDiscoverNetworkInterface
;
21 LIST_ENTRY mEfiRedfishDiscoverRestExInstance
;
23 EFI_GUID mRedfishDiscoverTcp4InstanceGuid
= EFI_REDFISH_DISCOVER_TCP4_INSTANCE_GUID
;
24 EFI_GUID mRedfishDiscoverTcp6InstanceGuid
= EFI_REDFISH_DISCOVER_TCP6_INSTANCE_GUID
;
25 EFI_GUID mRedfishDiscoverRestExInstanceGuid
= EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_GUID
;
30 IN EFI_HANDLE ImageHandle
,
31 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*Instance
37 IN EFI_HANDLE ImageHandle
,
38 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*Instance
41 static REDFISH_DISCOVER_REQUIRED_PROTOCOL gRequiredProtocol
[] = {
44 L
"TCP4 Service Binding Protocol",
45 &gEfiTcp4ProtocolGuid
,
46 &gEfiTcp4ServiceBindingProtocolGuid
,
47 &mRedfishDiscoverTcp4InstanceGuid
,
52 L
"TCP6 Service Binding Protocol",
53 &gEfiTcp6ProtocolGuid
,
54 &gEfiTcp6ServiceBindingProtocolGuid
,
55 &mRedfishDiscoverTcp6InstanceGuid
,
60 L
"REST EX Service Binding Protocol",
61 &gEfiRestExProtocolGuid
,
62 &gEfiRestExServiceBindingProtocolGuid
,
63 &mRedfishDiscoverRestExInstanceGuid
,
69 This function creates REST EX instance for the found Resfish service.
70 by known owner handle.
72 @param[in] Instance EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
73 @param[in] Token Client token.
75 @retval NULL Instance not found.
76 @retval EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE The instance owned by this owner.
80 CreateRestExInstance (
81 IN EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
*Instance
,
82 IN EFI_REDFISH_DISCOVERED_TOKEN
*Token
87 Status
= RestExLibCreateChild (
89 FixedPcdGetBool (PcdRedfishDiscoverAccessModeInBand
) ? EfiRestExServiceInBandAccess
: EfiRestExServiceOutOfBandAccess
,
91 EfiRestExServiceRedfish
,
92 &Token
->DiscoverList
.RedfishInstances
->Information
.RedfishRestExHandle
98 This function gets EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
99 by known owner handle.
101 @param[in] ImageHandle Image handle owns EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE.
102 @param[in] TargetNetworkInterface Target network interface used by this EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE.
103 @param[in] DiscoverFlags EFI_REDFISH_DISCOVER_FLAG
105 @retval NULL Instance not found.
106 @retval EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE The instance owned by this owner.
109 EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
*
111 IN EFI_HANDLE ImageHandle
,
112 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*TargetNetworkInterface
,
113 IN EFI_REDFISH_DISCOVER_FLAG DiscoverFlags
116 EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
*ThisInstance
;
118 if (IsListEmpty (&mRedfishDiscoverList
)) {
123 (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
*)GetFirstNode (&mRedfishDiscoverList
);
125 if ((ThisInstance
->Owner
== ImageHandle
) &&
126 (ThisInstance
->DiscoverFlags
== DiscoverFlags
) &&
127 (ThisInstance
->NetworkInterface
== TargetNetworkInterface
))
132 if (IsNodeAtEnd (&mRedfishDiscoverList
, &ThisInstance
->Entry
)) {
137 (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
*)GetNextNode (&mRedfishDiscoverList
, &ThisInstance
->Entry
);
144 This function gets the subnet information of this TCP4 instance.
146 @param[in] ImageHandle EFI handle with this image.
147 @param[in] Instance Instance of Network interface.
148 @retval EFI_STATUS Get subnet information successfully.
149 @retval Otherwise Fail to get subnet information.
154 IN EFI_HANDLE ImageHandle
,
155 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*Instance
159 EFI_TCP4_PROTOCOL
*Tcp4
;
160 EFI_TCP4_CONFIG_DATA Tcp4CfgData
;
161 EFI_TCP4_OPTION Tcp4Option
;
162 EFI_IP4_MODE_DATA IpModedata
;
163 UINT8 SubnetMaskIndex
;
166 BOOLEAN GotPrefixLength
;
168 if (Instance
== NULL
) {
169 return EFI_INVALID_PARAMETER
;
172 Tcp4
= (EFI_TCP4_PROTOCOL
*)Instance
->NetworkInterfaceProtocolInfo
.NetworkProtocolInterface
;
174 ZeroMem ((VOID
*)&Tcp4CfgData
, sizeof (EFI_TCP4_CONFIG_DATA
));
175 ZeroMem ((VOID
*)&Tcp4Option
, sizeof (EFI_TCP4_OPTION
));
176 // Give a local host IP address just for getting subnet information.
177 Tcp4CfgData
.AccessPoint
.UseDefaultAddress
= TRUE
;
178 Tcp4CfgData
.AccessPoint
.RemoteAddress
.Addr
[0] = 127;
179 Tcp4CfgData
.AccessPoint
.RemoteAddress
.Addr
[1] = 0;
180 Tcp4CfgData
.AccessPoint
.RemoteAddress
.Addr
[2] = 0;
181 Tcp4CfgData
.AccessPoint
.RemoteAddress
.Addr
[3] = 1;
182 Tcp4CfgData
.AccessPoint
.RemotePort
= 80;
183 Tcp4CfgData
.AccessPoint
.ActiveFlag
= TRUE
;
185 Tcp4CfgData
.ControlOption
= &Tcp4Option
;
186 Tcp4Option
.ReceiveBufferSize
= 65535;
187 Tcp4Option
.SendBufferSize
= 65535;
188 Tcp4Option
.MaxSynBackLog
= 5;
189 Tcp4Option
.ConnectionTimeout
= 60;
190 Tcp4Option
.DataRetries
= 12;
191 Tcp4Option
.FinTimeout
= 2;
192 Tcp4Option
.KeepAliveProbes
= 6;
193 Tcp4Option
.KeepAliveTime
= 7200;
194 Tcp4Option
.KeepAliveInterval
= 30;
195 Tcp4Option
.EnableNagle
= TRUE
;
196 Status
= Tcp4
->Configure (Tcp4
, &Tcp4CfgData
);
197 if (EFI_ERROR (Status
)) {
198 DEBUG ((DEBUG_ERROR
, "%a: Can't get subnet information\n", __FUNCTION__
));
202 Status
= Tcp4
->GetModeData (Tcp4
, NULL
, NULL
, &IpModedata
, NULL
, NULL
);
203 if (EFI_ERROR (Status
)) {
204 DEBUG ((DEBUG_ERROR
, "%a: Can't get IP mode data information\n", __FUNCTION__
));
208 IP4_COPY_ADDRESS (&Instance
->SubnetMask
, &IpModedata
.ConfigData
.SubnetMask
);
209 Instance
->SubnetAddr
.v4
.Addr
[0] = IpModedata
.ConfigData
.StationAddress
.Addr
[0] & Instance
->SubnetMask
.v4
.Addr
[0];
210 Instance
->SubnetAddr
.v4
.Addr
[1] = IpModedata
.ConfigData
.StationAddress
.Addr
[1] & Instance
->SubnetMask
.v4
.Addr
[1];
211 Instance
->SubnetAddr
.v4
.Addr
[2] = IpModedata
.ConfigData
.StationAddress
.Addr
[2] & Instance
->SubnetMask
.v4
.Addr
[2];
212 Instance
->SubnetAddr
.v4
.Addr
[3] = IpModedata
.ConfigData
.StationAddress
.Addr
[3] & Instance
->SubnetMask
.v4
.Addr
[3];
214 // Calculate the subnet mask prefix.
216 GotPrefixLength
= FALSE
;
219 while (GotPrefixLength
== FALSE
&& SubnetMaskIndex
< 4) {
221 while (BitMask
!= 0) {
222 if ((Instance
->SubnetMask
.v4
.Addr
[SubnetMaskIndex
] & BitMask
) != 0) {
225 GotPrefixLength
= TRUE
;
229 BitMask
= BitMask
>> 1;
235 Instance
->SubnetPrefixLength
= PrefixLength
;
240 This function gets the subnet information of this TCP6 instance.
242 @param[in] ImageHandle EFI handle with this image.
243 @param[in] Instance Instance of Network interface.
244 @retval EFI_STATUS Get subnet information successfully.
245 @retval Otherwise Fail to get subnet information.
250 IN EFI_HANDLE ImageHandle
,
251 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*Instance
255 EFI_TCP6_PROTOCOL
*Tcp6
;
256 EFI_IP6_MODE_DATA IpModedata
;
258 if (Instance
== NULL
) {
259 return EFI_INVALID_PARAMETER
;
262 Tcp6
= (EFI_TCP6_PROTOCOL
*)Instance
->NetworkInterfaceProtocolInfo
.NetworkProtocolInterface
;
264 Status
= Tcp6
->GetModeData (Tcp6
, NULL
, NULL
, &IpModedata
, NULL
, NULL
);
265 if (EFI_ERROR (Status
)) {
266 DEBUG ((DEBUG_ERROR
, "%a: Can't get IP mode data information\n"));
270 if (IpModedata
.AddressCount
== 0) {
271 DEBUG ((DEBUG_INFO
, "%a: No IPv6 address configured.\n"));
274 if (Instance
->SubnetAddrInfoIPv6
!= NULL
) {
275 FreePool (Instance
->SubnetAddrInfoIPv6
);
278 Instance
->SubnetAddrInfoIPv6
= AllocateZeroPool (IpModedata
.AddressCount
* sizeof (EFI_IP6_ADDRESS_INFO
));
279 if (Instance
->SubnetAddrInfoIPv6
== NULL
) {
280 DEBUG ((DEBUG_ERROR
, "%a: Failed to allocate memory fir IPv6 subnet address information\n"));
281 return EFI_OUT_OF_RESOURCES
;
284 Instance
->SubnetAddrInfoIPv6Number
= IpModedata
.AddressCount
;
286 (VOID
*)Instance
->SubnetAddrInfoIPv6
,
287 (VOID
*)&IpModedata
.AddressList
,
288 IpModedata
.AddressCount
* sizeof (EFI_IP6_ADDRESS_INFO
)
290 FreePool (IpModedata
.AddressList
);
295 This function searches EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
296 instance with the given EFI_REDFISH_DISCOVER_NETWORK_INTERFACE.
298 @param[in] TargetNetworkInterface EFI_REDFISH_DISCOVER_NETWORK_INTERFACE.
299 NULL for all EFI_REDFISH_DISCOVER_NETWORK_INTERFACEs.
301 @retval Non-NULL EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL is returned.
302 @retval NULL Non of EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL instance is returned.
304 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*
305 GetTargetNetworkInterfaceInternal (
306 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE
*TargetNetworkInterface
309 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*ThisNetworkInterface
;
311 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface
);
313 if (CompareMem ((VOID
*)&ThisNetworkInterface
->MacAddress
, &TargetNetworkInterface
->MacAddress
, ThisNetworkInterface
->HwAddressSize
) == 0) {
314 return ThisNetworkInterface
;
317 if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterface
->Entry
)) {
321 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetNextNode (&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterface
->Entry
);
328 This function searches EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
329 instance with the given Controller handle.
331 @param[in] ControllerHandle The controller handle associated with network interface.
333 @retval Non-NULL EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL is returned.
334 @retval NULL Non of EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL instance is returned.
336 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*
337 GetTargetNetworkInterfaceInternalByController (
338 IN EFI_HANDLE ControllerHandle
341 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*ThisNetworkInterface
;
343 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface
);
345 if (ThisNetworkInterface
->OpenDriverControllerHandle
== ControllerHandle
) {
346 return ThisNetworkInterface
;
349 if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterface
->Entry
)) {
353 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetNextNode (&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterface
->Entry
);
360 This function validate if target network interface is ready for discovering
363 @param[in] TargetNetworkInterface EFI_REDFISH_DISCOVER_NETWORK_INTERFACE.
364 NULL for all EFI_REDFISH_DISCOVER_NETWORK_INTERFACEs.
365 @param[in] Flags EFI_REDFISH_DISCOVER_FLAG
367 @retval EFI_SUCCESS Target network interface is ready to use.
368 @retval EFI_UNSUPPORTED Target network interface is not ready to use.
371 ValidateTargetNetworkInterface (
372 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE
*TargetNetworkInterface
,
373 IN EFI_REDFISH_DISCOVER_FLAG Flags
376 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*ThisNetworkInterface
;
378 if (IsListEmpty (&mEfiRedfishDiscoverNetworkInterface
) && (TargetNetworkInterface
== NULL
)) {
379 return EFI_UNSUPPORTED
;
382 if (TargetNetworkInterface
== NULL
) {
383 return EFI_SUCCESS
; // Return EFI_SUCCESS if no network interface is specified.
386 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface
);
388 if (CompareMem ((VOID
*)&ThisNetworkInterface
->MacAddress
, &TargetNetworkInterface
->MacAddress
, ThisNetworkInterface
->HwAddressSize
) == 0) {
392 if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterface
->Entry
)) {
393 return EFI_UNSUPPORTED
;
396 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetNextNode (&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterface
->Entry
);
399 if ((Flags
& EFI_REDFISH_DISCOVER_SSDP
) != 0) {
400 // Validate if UDP4/6 is supported on the given network interface.
401 // SSDP is not supported.
406 if (ThisNetworkInterface
->NetworkInterfaceProtocolInfo
.ProtocolControllerHandle
== NULL
) {
407 return EFI_UNSUPPORTED
; // The required protocol on this network interface is not found.
414 This function returns number of network interface instance.
416 @retval UINTN Number of network interface instances.
419 NumberOfNetworkInterface (
424 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*ThisNetworkInterface
;
426 if (IsListEmpty (&mEfiRedfishDiscoverNetworkInterface
)) {
431 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface
);
433 if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterface
->Entry
)) {
437 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetNextNode (&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterface
->Entry
);
445 This function checks the IP version supported on this
448 @param[in] ThisNetworkInterface EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
450 @retval TRUE Is IPv6, otherwise IPv4.
455 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*ThisNetworkInterface
458 if (ThisNetworkInterface
->NetworkProtocolType
== ProtocolTypeTcp6
) {
466 This function discover Redfish service through SMBIOS host interface.
468 @param[in] Instance EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
470 @retval EFI_SUCCESS Redfish service is discovered through SMBIOS Host interface.
471 @retval Others Fail to discover Redfish service throught SMBIOS host interface
475 DiscoverRedfishHostInterface (
476 IN EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
*Instance
480 REDFISH_OVER_IP_PROTOCOL_DATA
*Data
;
481 REDFISH_INTERFACE_DATA
*DeviceDescriptor
;
482 CHAR8 UuidStr
[sizeof "00000000-0000-0000-0000-000000000000" + 1];
483 CHAR16 Ipv6Str
[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" + 1];
484 CHAR8 RedfishServiceLocateStr
[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" + 1];
486 UINTN MacCompareStstus
;
490 DeviceDescriptor
= NULL
;
492 if (mSmbios
== NULL
) {
493 Status
= gBS
->LocateProtocol (&gEfiSmbiosProtocolGuid
, NULL
, (VOID
**)&mSmbios
);
494 if (EFI_ERROR (Status
)) {
499 Status
= RedfishGetHostInterfaceProtocolData (mSmbios
, &DeviceDescriptor
, &Data
); // Search for SMBIOS type 42h
500 if (!EFI_ERROR (Status
) && (Data
!= NULL
) && (DeviceDescriptor
!= NULL
)) {
502 // Chceck if we can reach out Redfish service using this network interface.
503 // Check with MAC address using Device Descroptor Data Device Type 04 and Type 05.
504 // Those two types of Redfish host interface device has MAC information.
506 if (DeviceDescriptor
->DeviceType
== REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE_V2
) {
507 MacCompareStstus
= CompareMem (&Instance
->NetworkInterface
->MacAddress
, &DeviceDescriptor
->DeviceDescriptor
.PciPcieDeviceV2
.MacAddress
, 6);
508 } else if (DeviceDescriptor
->DeviceType
== REDFISH_HOST_INTERFACE_DEVICE_TYPE_USB_V2
) {
509 MacCompareStstus
= CompareMem (&Instance
->NetworkInterface
->MacAddress
, &DeviceDescriptor
->DeviceDescriptor
.UsbDeviceV2
.MacAddress
, 6);
511 return EFI_UNSUPPORTED
;
514 if (MacCompareStstus
!= 0) {
515 return EFI_UNSUPPORTED
;
518 if (Data
->RedfishServiceIpAddressFormat
== 1) {
519 IP4_COPY_ADDRESS ((VOID
*)&Instance
->TargetIpAddress
.v4
, (VOID
*)Data
->RedfishServiceIpAddress
);
521 IP6_COPY_ADDRESS ((VOID
*)&Instance
->TargetIpAddress
.v6
, (VOID
*)Data
->RedfishServiceIpAddress
);
524 if (Instance
->HostIntfValidation
) {
525 DEBUG ((DEBUG_ERROR
, "%a:Send UPnP unicast SSDP to validate this Redfish Host Interface is not supported.\n", __FUNCTION__
));
526 Status
= EFI_UNSUPPORTED
;
529 // Add this istance to list without detial information of Redfish
533 if (Data
->RedfishServiceIpPort
== 443) {
537 StrSize
= sizeof (UuidStr
);
538 AsciiSPrint (UuidStr
, StrSize
, "%g", &Data
->ServiceUuid
);
540 // Generate Redfish service location string.
542 if (Data
->RedfishServiceIpAddressFormat
== REDFISH_HOST_INTERFACE_HOST_IP_ADDRESS_FORMAT_IP6
) {
543 NetLibIp6ToStr ((IPv6_ADDRESS
*)&Data
->RedfishServiceIpAddress
, Ipv6Str
, sizeof (Ipv6Str
));
544 if ((Data
->RedfishServiceIpPort
== 0) || (IsHttps
== TRUE
)) {
545 AsciiSPrintUnicodeFormat (
546 RedfishServiceLocateStr
,
547 sizeof (RedfishServiceLocateStr
),
552 AsciiSPrintUnicodeFormat (
553 RedfishServiceLocateStr
,
554 sizeof (RedfishServiceLocateStr
),
557 Data
->RedfishServiceIpPort
561 if ((Data
->RedfishServiceIpPort
== 0) || (IsHttps
== TRUE
)) {
563 RedfishServiceLocateStr
,
564 sizeof (RedfishServiceLocateStr
),
566 Data
->RedfishServiceIpAddress
[0],
567 Data
->RedfishServiceIpAddress
[1],
568 Data
->RedfishServiceIpAddress
[2],
569 Data
->RedfishServiceIpAddress
[3]
573 RedfishServiceLocateStr
,
574 sizeof (RedfishServiceLocateStr
),
576 Data
->RedfishServiceIpAddress
[0],
577 Data
->RedfishServiceIpAddress
[1],
578 Data
->RedfishServiceIpAddress
[2],
579 Data
->RedfishServiceIpAddress
[3],
580 Data
->RedfishServiceIpPort
585 Status
= AddAndSignalNewRedfishService (
588 RedfishServiceLocateStr
,
603 The function adds a new found Redfish service to internal list and
606 @param[in] Instance EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE.
607 @param[in] RedfishVersion Redfish version.
608 @param[in] RedfishLocation Redfish location.
609 @param[in] Uuid Service UUID string.
610 @param[in] Os OS string.
611 @param[in] OsVer OS version string.
612 @param[in] Product Product string.
613 @param[in] ProductVer Product verison string.
614 @param[in] UseHttps Redfish service requires secured connection.
615 @retval EFI_SUCCESS Redfish service is added to list successfully.
619 AddAndSignalNewRedfishService (
620 IN EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
*Instance
,
621 IN UINTN
*RedfishVersion OPTIONAL
,
622 IN CHAR8
*RedfishLocation OPTIONAL
,
623 IN CHAR8
*Uuid OPTIONAL
,
624 IN CHAR8
*Os OPTIONAL
,
625 IN CHAR8
*OsVer OPTIONAL
,
626 IN CHAR8
*Product OPTIONAL
,
627 IN CHAR8
*ProductVer OPTIONAL
,
633 BOOLEAN RestExOpened
;
634 BOOLEAN DeleteRestEx
;
636 EFI_REDFISH_DISCOVERED_INTERNAL_LIST
*DiscoveredList
;
637 EFI_REDFISH_DISCOVERED_INSTANCE
*DiscoveredInstance
;
639 EFI_REST_EX_PROTOCOL
*RestEx
;
640 EFI_REST_EX_HTTP_CONFIG_DATA
*RestExHttpConfigData
;
641 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*NetworkInterface
;
646 RestExOpened
= FALSE
;
647 DeleteRestEx
= FALSE
;
649 DEBUG ((DEBUG_INFO
, "%a:Add this instance to Redfish instance list.\n", __FUNCTION__
));
652 Char16Uuid
= (CHAR16
*)AllocateZeroPool (AsciiStrSize ((const CHAR8
*)Uuid
) * sizeof (CHAR16
));
653 AsciiStrToUnicodeStrS ((const CHAR8
*)Uuid
, Char16Uuid
, AsciiStrSize ((const CHAR8
*)Uuid
) * sizeof (CHAR16
));
656 DiscoveredList
= NULL
;
657 DiscoveredInstance
= NULL
;
658 RestExHttpConfigData
= NULL
;
660 NetworkInterface
= Instance
->NetworkInterface
;
661 if (!IsListEmpty (&mRedfishInstanceList
)) {
663 // Is this a duplicate redfish service.
665 DiscoveredList
= (EFI_REDFISH_DISCOVERED_INTERNAL_LIST
*)GetFirstNode (&mRedfishInstanceList
);
668 if ((Char16Uuid
== NULL
) || (DiscoveredList
->Instance
->Information
.Uuid
== NULL
)) {
670 // Check if this Redfish instance already found using IP addrress.
672 if (!CheckIsIpVersion6 (NetworkInterface
)) {
674 (VOID
*)&Instance
->TargetIpAddress
.v4
,
675 (VOID
*)&DiscoveredList
->Instance
->Information
.RedfishHostIpAddress
.v4
,
676 sizeof (EFI_IPv4_ADDRESS
)
679 DiscoveredInstance
= DiscoveredList
->Instance
;
680 if ((DiscoveredList
->Instance
->Information
.Uuid
== NULL
) &&
681 (Char16Uuid
!= NULL
))
684 DiscoveredInstance
= DiscoveredList
->Instance
;
685 DEBUG ((DEBUG_INFO
, "*** This Redfish Service information refresh ***\n"));
692 (VOID
*)&Instance
->TargetIpAddress
.v6
,
693 (VOID
*)&DiscoveredList
->Instance
->Information
.RedfishHostIpAddress
.v6
,
694 sizeof (EFI_IPv6_ADDRESS
)
697 DiscoveredInstance
= DiscoveredList
->Instance
;
703 // Check if this Redfish instance already found using UUID.
705 if (StrCmp ((const CHAR16
*)Char16Uuid
, (const CHAR16
*)DiscoveredList
->Instance
->Information
.Uuid
) == 0) {
706 DiscoveredInstance
= DiscoveredList
->Instance
;
711 if (IsNodeAtEnd (&mRedfishInstanceList
, &DiscoveredList
->NextInstance
)) {
716 DiscoveredList
= (EFI_REDFISH_DISCOVERED_INTERNAL_LIST
*)GetNextNode (&mRedfishInstanceList
, &DiscoveredList
->NextInstance
);
720 if (NewFound
|| InfoRefresh
) {
722 DiscoveredList
= (EFI_REDFISH_DISCOVERED_INTERNAL_LIST
*)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVERED_INTERNAL_LIST
));
723 if (DiscoveredList
== NULL
) {
724 return EFI_OUT_OF_RESOURCES
;
727 InitializeListHead (&DiscoveredList
->NextInstance
);
728 DiscoveredInstance
= (EFI_REDFISH_DISCOVERED_INSTANCE
*)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVERED_INSTANCE
));
729 if (DiscoveredInstance
== NULL
) {
730 FreePool ((VOID
*)DiscoveredList
);
731 return EFI_OUT_OF_RESOURCES
;
735 DEBUG ((DEBUG_INFO
, "*** Redfish Service Information ***\n"));
737 DiscoveredInstance
->Information
.UseHttps
= UseHttps
;
738 if (RedfishVersion
!= NULL
) {
739 DiscoveredInstance
->Information
.RedfishVersion
= *RedfishVersion
;
740 DEBUG ((DEBUG_INFO
, "Redfish service version: %d.\n", DiscoveredInstance
->Information
.RedfishVersion
));
743 if (RedfishLocation
!= NULL
) {
744 DiscoveredInstance
->Information
.Location
= (CHAR16
*)AllocatePool (AsciiStrSize ((const CHAR8
*)RedfishLocation
) * sizeof (CHAR16
));
745 AsciiStrToUnicodeStrS ((const CHAR8
*)RedfishLocation
, DiscoveredInstance
->Information
.Location
, AsciiStrSize ((const CHAR8
*)RedfishLocation
) * sizeof (CHAR16
));
746 DEBUG ((DEBUG_INFO
, "Redfish service location: %s.\n", DiscoveredInstance
->Information
.Location
));
750 DiscoveredInstance
->Information
.Uuid
= (CHAR16
*)AllocatePool (AsciiStrSize ((const CHAR8
*)Uuid
) * sizeof (CHAR16
));
751 AsciiStrToUnicodeStrS ((const CHAR8
*)Uuid
, DiscoveredInstance
->Information
.Uuid
, AsciiStrSize ((const CHAR8
*)Uuid
) * sizeof (CHAR16
));
752 DEBUG ((DEBUG_INFO
, "Service UUID: %s.\n", DiscoveredInstance
->Information
.Uuid
));
756 DiscoveredInstance
->Information
.Os
= (CHAR16
*)AllocatePool (AsciiStrSize ((const CHAR8
*)Os
) * sizeof (CHAR16
));
757 AsciiStrToUnicodeStrS ((const CHAR8
*)Os
, DiscoveredInstance
->Information
.Os
, AsciiStrSize ((const CHAR8
*)Os
) * sizeof (CHAR16
));
758 DEBUG ((DEBUG_INFO
, "Redfish service OS: %s, Version:%s.\n", DiscoveredInstance
->Information
.Os
, DiscoveredInstance
->Information
.OsVersion
));
762 DiscoveredInstance
->Information
.OsVersion
= (CHAR16
*)AllocatePool (AsciiStrSize ((const CHAR8
*)OsVer
) * sizeof (CHAR16
));
763 AsciiStrToUnicodeStrS ((const CHAR8
*)OsVer
, DiscoveredInstance
->Information
.OsVersion
, AsciiStrSize ((const CHAR8
*)OsVer
) * sizeof (CHAR16
));
766 if ((Product
!= NULL
) && (ProductVer
!= NULL
)) {
767 DiscoveredInstance
->Information
.Product
= (CHAR16
*)AllocatePool (AsciiStrSize ((const CHAR8
*)Product
) * sizeof (CHAR16
));
768 AsciiStrToUnicodeStrS ((const CHAR8
*)Product
, DiscoveredInstance
->Information
.Product
, AsciiStrSize ((const CHAR8
*)Product
) * sizeof (CHAR16
));
769 DiscoveredInstance
->Information
.ProductVer
= (CHAR16
*)AllocatePool (AsciiStrSize ((const CHAR8
*)ProductVer
) * sizeof (CHAR16
));
770 AsciiStrToUnicodeStrS ((const CHAR8
*)ProductVer
, DiscoveredInstance
->Information
.ProductVer
, AsciiStrSize ((const CHAR8
*)ProductVer
) * sizeof (CHAR16
));
771 DEBUG ((DEBUG_INFO
, "Redfish service product: %s, Version:%s.\n", DiscoveredInstance
->Information
.Product
, DiscoveredInstance
->Information
.ProductVer
));
774 if (RedfishLocation
== NULL
) {
775 // This is the Redfish reported from SMBIOS 42h
776 // without validation.
778 IP4_COPY_ADDRESS ((VOID
*)&DiscoveredInstance
->Information
.RedfishHostIpAddress
.v4
, (VOID
*)&Instance
->TargetIpAddress
.v4
);
782 DiscoveredList
->Instance
= DiscoveredInstance
;
783 InsertTailList (&mRedfishInstanceList
, &DiscoveredList
->NextInstance
);
786 DiscoveredInstance
->Status
= EFI_SUCCESS
;
788 if (DiscoveredList
!= NULL
) {
789 DEBUG ((DEBUG_INFO
, "*** This Redfish Service was already found ***\n"));
790 if (DiscoveredInstance
->Information
.Uuid
!= NULL
) {
791 DEBUG ((DEBUG_INFO
, "Service UUID: %s.\n", DiscoveredInstance
->Information
.Uuid
));
793 DEBUG ((DEBUG_INFO
, "Service UUID: unknown.\n"));
798 if (Char16Uuid
!= NULL
) {
799 FreePool ((VOID
*)Char16Uuid
);
802 Status
= EFI_SUCCESS
;
803 if (NewFound
|| InfoRefresh
) {
805 // Build up EFI_REDFISH_DISCOVERED_LIST in token.
807 Instance
->DiscoverToken
->DiscoverList
.NumberOfServiceFound
= 1;
808 Instance
->DiscoverToken
->DiscoverList
.RedfishInstances
= DiscoveredInstance
;
809 DiscoveredInstance
->Status
= EFI_SUCCESS
;
811 Status
= CreateRestExInstance (Instance
, Instance
->DiscoverToken
); // Create REST EX child.
812 if (EFI_ERROR (Status
)) {
813 DEBUG ((DEBUG_ERROR
, "%a:Can't create REST EX child instance.\n", __FUNCTION__
));
817 Status
= gBS
->OpenProtocol (
818 // Configure local host information.
819 Instance
->DiscoverToken
->DiscoverList
.RedfishInstances
->Information
.RedfishRestExHandle
,
820 &gEfiRestExProtocolGuid
,
822 Instance
->NetworkInterface
->OpenDriverAgentHandle
,
823 Instance
->NetworkInterface
->OpenDriverControllerHandle
,
824 EFI_OPEN_PROTOCOL_BY_DRIVER
826 if (EFI_ERROR (Status
)) {
832 RestExHttpConfigData
= AllocateZeroPool (sizeof (EFI_REST_EX_HTTP_CONFIG_DATA
));
833 if (RestExHttpConfigData
== NULL
) {
834 Status
= EFI_OUT_OF_RESOURCES
;
836 goto EXIT_FREE_CONFIG_DATA
;
839 RestExHttpConfigData
->SendReceiveTimeout
= 5000;
840 RestExHttpConfigData
->HttpConfigData
.HttpVersion
= HttpVersion11
;
841 RestExHttpConfigData
->HttpConfigData
.LocalAddressIsIPv6
= CheckIsIpVersion6 (NetworkInterface
);
842 if (RestExHttpConfigData
->HttpConfigData
.LocalAddressIsIPv6
) {
843 RestExHttpConfigData
->HttpConfigData
.AccessPoint
.IPv6Node
= AllocateZeroPool (sizeof (EFI_HTTPv6_ACCESS_POINT
));
844 if (RestExHttpConfigData
->HttpConfigData
.AccessPoint
.IPv6Node
== NULL
) {
845 Status
= EFI_OUT_OF_RESOURCES
;
846 goto EXIT_FREE_CONFIG_DATA
;
849 RestExHttpConfigData
->HttpConfigData
.AccessPoint
.IPv4Node
= AllocateZeroPool (sizeof (EFI_HTTPv4_ACCESS_POINT
));
850 if (RestExHttpConfigData
->HttpConfigData
.AccessPoint
.IPv4Node
== NULL
) {
851 Status
= EFI_OUT_OF_RESOURCES
;
852 goto EXIT_FREE_CONFIG_DATA
;
855 RestExHttpConfigData
->HttpConfigData
.AccessPoint
.IPv4Node
->UseDefaultAddress
= TRUE
;
858 Status
= RestEx
->Configure (
860 (EFI_REST_EX_CONFIG_DATA
)(UINT8
*)RestExHttpConfigData
862 if (EFI_ERROR (Status
)) {
863 DEBUG ((DEBUG_ERROR
, "%a:REST EX configured..\n", __FUNCTION__
));
869 // Signal client, close REST EX before signaling client.
873 Instance
->DiscoverToken
->DiscoverList
.RedfishInstances
->Information
.RedfishRestExHandle
,
874 &gEfiRestExProtocolGuid
,
875 Instance
->NetworkInterface
->OpenDriverAgentHandle
,
876 Instance
->NetworkInterface
->OpenDriverControllerHandle
878 RestExOpened
= FALSE
;
882 Status
= gBS
->SignalEvent (Instance
->DiscoverToken
->Event
);
883 if (!EFI_ERROR (Status
)) {
884 DEBUG ((DEBUG_ERROR
, "%a:No event to signal!\n", __FUNCTION__
));
889 if ((RestExHttpConfigData
!= NULL
) && (RestExHttpConfigData
->HttpConfigData
.AccessPoint
.IPv4Node
!= NULL
)) {
890 FreePool (RestExHttpConfigData
->HttpConfigData
.AccessPoint
.IPv4Node
);
893 EXIT_FREE_CONFIG_DATA
:;
894 if (RestExHttpConfigData
!= NULL
) {
895 FreePool ((VOID
*)RestExHttpConfigData
);
900 Instance
->DiscoverToken
->DiscoverList
.RedfishInstances
->Information
.RedfishRestExHandle
,
901 &gEfiRestExProtocolGuid
,
902 Instance
->NetworkInterface
->OpenDriverAgentHandle
,
903 Instance
->NetworkInterface
->OpenDriverControllerHandle
908 if (DeleteRestEx
&& RestExOpened
) {
910 Instance
->DiscoverToken
->DiscoverList
.RedfishInstances
->Information
.RedfishRestExHandle
,
911 &gEfiRestExProtocolGuid
,
912 Instance
->NetworkInterface
->OpenDriverAgentHandle
,
913 Instance
->NetworkInterface
->OpenDriverControllerHandle
922 This function gets the subnet information of this network interface instance.
923 can discover Redfish service on it.
925 @param[in] Instance EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL instance.
926 @param[in] ImageHandle EFI Image handle request the network interface list.
932 NetworkInterfaceGetSubnetInfo (
933 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*Instance
,
934 IN EFI_HANDLE ImageHandle
939 UINT32 IPv6InfoIndex
;
940 EFI_IP6_ADDRESS_INFO
*ThisSubnetAddrInfoIPv6
;
941 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*NewNetworkInterface
;
943 if (Instance
->GotSubnetInfo
) {
947 ProtocolType
= Instance
->NetworkProtocolType
;
948 if ((gRequiredProtocol
[ProtocolType
].GetSubnetInfo
!= NULL
) && (Instance
->GotSubnetInfo
== FALSE
)) {
949 Status
= gRequiredProtocol
[ProtocolType
].GetSubnetInfo (
953 if (EFI_ERROR (Status
)) {
954 DEBUG ((DEBUG_ERROR
, "%a:Faile to get Subnet infomation.\n", __FUNCTION__
));
957 DEBUG ((DEBUG_INFO
, "%a:MAC address: %s\n", __FUNCTION__
, Instance
->StrMacAddr
));
958 if (CheckIsIpVersion6 (Instance
)) {
959 if (Instance
->SubnetAddrInfoIPv6Number
== 0) {
960 DEBUG ((DEBUG_ERROR
, "%a: There is no Subnet infomation for IPv6 network interface.\n", __FUNCTION__
));
961 return EFI_NOT_FOUND
;
964 ThisSubnetAddrInfoIPv6
= Instance
->SubnetAddrInfoIPv6
; // First IPv6 address information.
965 IP6_COPY_ADDRESS (&Instance
->SubnetAddr
.v6
, &ThisSubnetAddrInfoIPv6
->Address
);
966 Instance
->SubnetPrefixLength
= ThisSubnetAddrInfoIPv6
->PrefixLength
;
969 " IPv6 Subnet ID:%d, Prefix length: %d.\n",
970 ThisSubnetAddrInfoIPv6
->Address
.Addr
[7] + (UINT16
)ThisSubnetAddrInfoIPv6
->Address
.Addr
[6] * 256,
971 ThisSubnetAddrInfoIPv6
->PrefixLength
975 // If this is IPv6, then we may have to propagate network interface for IPv6 network scopes
976 // according to the Ipv6 address information.
978 ThisSubnetAddrInfoIPv6
++;
979 for (IPv6InfoIndex
= 0; IPv6InfoIndex
< Instance
->SubnetAddrInfoIPv6Number
- 1; IPv6InfoIndex
++) {
981 // Build up addtional EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL instances.
983 NewNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
));
984 if (NewNetworkInterface
!= NULL
) {
985 CopyMem ((VOID
*)NewNetworkInterface
, (VOID
*)Instance
, sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
)); // Clone information of first instance.
986 IP6_COPY_ADDRESS (&NewNetworkInterface
->SubnetAddr
.v6
, &ThisSubnetAddrInfoIPv6
->Address
);
987 NewNetworkInterface
->SubnetPrefixLength
= ThisSubnetAddrInfoIPv6
->PrefixLength
;
988 NewNetworkInterface
->GotSubnetInfo
= TRUE
;
989 InsertTailList (&mEfiRedfishDiscoverNetworkInterface
, &NewNetworkInterface
->Entry
);
990 ThisSubnetAddrInfoIPv6
++;
991 mNumNetworkInterface
++;
994 " IPv6 Subnet ID:%d, Prefix length: %d.\n",
995 ThisSubnetAddrInfoIPv6
->Address
.Addr
[7] + (UINT16
)ThisSubnetAddrInfoIPv6
->Address
.Addr
[6] * 256,
996 ThisSubnetAddrInfoIPv6
->PrefixLength
1000 return EFI_OUT_OF_RESOURCES
;
1006 " IPv4 Subnet:%d.%d.%d.%d Subnet mask: %d.%d.%d.%d.\n",
1007 Instance
->SubnetAddr
.v4
.Addr
[0],
1008 Instance
->SubnetAddr
.v4
.Addr
[1],
1009 Instance
->SubnetAddr
.v4
.Addr
[2],
1010 Instance
->SubnetAddr
.v4
.Addr
[3],
1011 Instance
->SubnetMask
.v4
.Addr
[0],
1012 Instance
->SubnetMask
.v4
.Addr
[1],
1013 Instance
->SubnetMask
.v4
.Addr
[2],
1014 Instance
->SubnetMask
.v4
.Addr
[3]
1020 Instance
->GotSubnetInfo
= TRUE
; // Only try to get Subnet Info once.
1025 This function gets the network interface list which Redfish discover protocol
1026 can discover Redfish service on it.
1028 @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instance.
1029 @param[in] ImageHandle EFI Image handle request the network interface list,
1030 @param[out] NumberOfNetworkIntfs Number of network interfaces can do Redfish service discovery.
1031 @param[out] NetworkIntfInstances Network interface instances. It's an array of instance. The number of entries
1032 in array is indicated by NumberOfNetworkIntfs.
1033 Caller has to release the memory
1034 allocated by Redfish discover protocol.
1036 @retval EFI_SUCCESS The information of network interface is returned in NumberOfNetworkIntfs and
1037 NetworkIntfInstances.
1038 @retval Others Fail to return the information of network interface.
1043 RedfishServiceGetNetworkInterface (
1044 IN EFI_REDFISH_DISCOVER_PROTOCOL
*This
,
1045 IN EFI_HANDLE ImageHandle
,
1046 OUT UINTN
*NumberOfNetworkIntfs
,
1047 OUT EFI_REDFISH_DISCOVER_NETWORK_INTERFACE
**NetworkIntfInstances
1050 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*ThisNetworkInterfaceIntn
;
1051 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE
*ThisNetworkInterface
;
1053 if ((NetworkIntfInstances
== NULL
) || (NumberOfNetworkIntfs
== NULL
) || (ImageHandle
== NULL
)) {
1054 return EFI_INVALID_PARAMETER
;
1057 *NumberOfNetworkIntfs
= 0;
1058 *NetworkIntfInstances
= NULL
;
1060 if (IsListEmpty ((const LIST_ENTRY
*)&mEfiRedfishDiscoverNetworkInterface
)) {
1061 return EFI_NOT_FOUND
;
1064 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE
*)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE
) * mNumNetworkInterface
);
1065 if (ThisNetworkInterface
== NULL
) {
1066 return EFI_OUT_OF_RESOURCES
;
1069 *NetworkIntfInstances
= ThisNetworkInterface
;
1070 ThisNetworkInterfaceIntn
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface
);
1072 ThisNetworkInterface
->IsIpv6
= FALSE
;
1073 if (CheckIsIpVersion6 (ThisNetworkInterfaceIntn
)) {
1074 ThisNetworkInterface
->IsIpv6
= TRUE
;
1077 CopyMem ((VOID
*)&ThisNetworkInterface
->MacAddress
, &ThisNetworkInterfaceIntn
->MacAddress
, ThisNetworkInterfaceIntn
->HwAddressSize
);
1078 NetworkInterfaceGetSubnetInfo (ThisNetworkInterfaceIntn
, ImageHandle
); // Get subnet info.
1079 if (!ThisNetworkInterface
->IsIpv6
) {
1080 IP4_COPY_ADDRESS (&ThisNetworkInterface
->SubnetId
.v4
, &ThisNetworkInterfaceIntn
->SubnetAddr
.v4
); // IPv4 subnet information.
1082 IP6_COPY_ADDRESS (&ThisNetworkInterface
->SubnetId
.v6
, &ThisNetworkInterfaceIntn
->SubnetAddr
.v6
); // IPv6 subnet information in IPv6 address information.
1085 ThisNetworkInterface
->SubnetPrefixLength
= ThisNetworkInterfaceIntn
->SubnetPrefixLength
;
1086 ThisNetworkInterface
->VlanId
= ThisNetworkInterfaceIntn
->VlanId
;
1087 (*NumberOfNetworkIntfs
)++;
1088 if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterfaceIntn
->Entry
)) {
1092 ThisNetworkInterfaceIntn
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetNextNode (&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterfaceIntn
->Entry
);
1093 ThisNetworkInterface
++;
1100 This function acquires Redfish services by discovering static Redfish setting
1101 according to Redfish Host Interface or through SSDP. Returns a list of EFI
1102 handles in EFI_REDFISH_DISCOVERED_LIST. Each of EFI handle has cooresponding
1103 EFI REST EX instance installed on it. Each REST EX isntance is a child instance which
1104 created through EFI REST EX serivce protoocl for communicating with specific
1107 @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instance.
1108 @param[in] ImageHandle EFI image owns these Redfish service instances.
1109 @param[in] TargetNetworkInterface Target network interface to do the discovery.
1110 NULL means discover Redfish service on all network interfaces on platform.
1111 @param[in] Flags Redfish service discover flags.
1112 @param[in] Token EFI_REDFISH_DISCOVERED_TOKEN instance.
1113 The memory of EFI_REDFISH_DISCOVERED_LIST and the strings in
1114 EFI_REDFISH_DISCOVERED_INFORMATION are all allocated by Acquire()
1115 and must be freed when caller invoke Release().
1117 @retval EFI_SUCCESS REST EX instance of discovered Redfish services are returned.
1118 @retval EFI_INVALID_PARAMETERS ImageHandle == NULL, Flags == 0, Token == NULL, Token->Timeout > 5,
1119 or Token->Event == NULL.
1120 @retval Others Fail acquire Redfish services.
1125 RedfishServiceAcquireService (
1126 IN EFI_REDFISH_DISCOVER_PROTOCOL
*This
,
1127 IN EFI_HANDLE ImageHandle
,
1128 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE
*TargetNetworkInterface
,
1129 IN EFI_REDFISH_DISCOVER_FLAG Flags
,
1130 IN EFI_REDFISH_DISCOVERED_TOKEN
*Token
1133 EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
*Instance
;
1136 BOOLEAN NewInstance
;
1137 UINTN NumNetworkInterfaces
;
1138 UINTN NetworkInterfacesIndex
;
1139 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*TargetNetworkInterfaceInternal
;
1141 DEBUG ((DEBUG_INFO
, "%a:Entry.\n", __FUNCTION__
));
1144 // Validate parameters.
1146 if ((ImageHandle
== NULL
) || (Token
== NULL
) || ((Flags
& ~EFI_REDFISH_DISCOVER_VALIDATION
) == 0)) {
1147 DEBUG ((DEBUG_ERROR
, "%a:Invalid parameters.\n", __FUNCTION__
));
1148 return EFI_INVALID_PARAMETER
;
1152 // Validate target network interface.
1154 if (EFI_ERROR (ValidateTargetNetworkInterface (TargetNetworkInterface
, Flags
))) {
1155 return EFI_UNSUPPORTED
;
1158 if (TargetNetworkInterface
!= NULL
) {
1159 TargetNetworkInterfaceInternal
= GetTargetNetworkInterfaceInternal (TargetNetworkInterface
);
1160 NumNetworkInterfaces
= 1;
1162 TargetNetworkInterfaceInternal
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface
);
1163 NumNetworkInterfaces
= NumberOfNetworkInterface ();
1164 if (NumNetworkInterfaces
== 0) {
1165 DEBUG ((DEBUG_ERROR
, "%a:No network interface on platform.\n", __FUNCTION__
));
1166 return EFI_UNSUPPORTED
;
1170 for (NetworkInterfacesIndex
= 0; NetworkInterfacesIndex
< NumNetworkInterfaces
; NetworkInterfacesIndex
++) {
1171 Status1
= EFI_SUCCESS
;
1172 Status2
= EFI_SUCCESS
;
1173 NewInstance
= FALSE
;
1174 Instance
= GetInstanceByOwner (ImageHandle
, TargetNetworkInterfaceInternal
, Flags
& ~EFI_REDFISH_DISCOVER_VALIDATION
); // Check if we can re-use previous instance.
1175 if (Instance
== NULL
) {
1176 DEBUG ((DEBUG_INFO
, "%a:Create new EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE.\n", __FUNCTION__
));
1177 Instance
= (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
*)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
));
1178 if (Instance
== NULL
) {
1179 DEBUG ((DEBUG_ERROR
, "%a:Memory allocation fail.\n", __FUNCTION__
));
1182 InitializeListHead (&Instance
->Entry
);
1183 Instance
->Owner
= ImageHandle
;
1184 Instance
->DiscoverFlags
= Flags
& ~EFI_REDFISH_DISCOVER_VALIDATION
;
1185 Instance
->NetworkInterface
= TargetNetworkInterfaceInternal
;
1187 // Get subnet information in case subnet information is not set because
1188 // RedfishServiceGetNetworkInterfaces hasn't been called yet.
1190 NetworkInterfaceGetSubnetInfo (TargetNetworkInterfaceInternal
, ImageHandle
);
1194 if (TargetNetworkInterfaceInternal
->StrMacAddr
!= NULL
) {
1195 DEBUG ((DEBUG_INFO
, "%a:Acquire Redfish service on network interface MAC address:%s.\n", __FUNCTION__
, TargetNetworkInterfaceInternal
->StrMacAddr
));
1197 DEBUG ((DEBUG_INFO
, "%a:WARNING: No MAC address on this network interface.\n", __FUNCTION__
));
1200 Instance
->DiscoverToken
= Token
; // Always use the latest Token passed by caller.
1201 if ((Flags
& EFI_REDFISH_DISCOVER_HOST_INTERFACE
) != 0) {
1202 DEBUG ((DEBUG_INFO
, "%a:Redfish HOST interface discovery.\n", __FUNCTION__
));
1203 Instance
->HostIntfValidation
= FALSE
;
1204 if ((Flags
& EFI_REDFISH_DISCOVER_VALIDATION
) != 0) {
1205 Instance
->HostIntfValidation
= TRUE
;
1208 Status1
= DiscoverRedfishHostInterface (Instance
); // Discover Redfish service through Redfish Host Interface.
1211 if ((Flags
& EFI_REDFISH_DISCOVER_SSDP
) != 0) {
1212 DEBUG ((DEBUG_ERROR
, "%a:Redfish service discovery through SSDP is not supported\n", __FUNCTION__
));
1213 return EFI_UNSUPPORTED
;
1215 if (EFI_ERROR (Status1
) && EFI_ERROR (Status2
)) {
1216 FreePool ((VOID
*)Instance
);
1217 DEBUG ((DEBUG_ERROR
, "%a:Something wrong on Redfish service discovery Status1=%x, Status2=%x.\n", __FUNCTION__
, Status1
, Status2
));
1220 InsertTailList (&mRedfishDiscoverList
, &Instance
->Entry
);
1225 if (TargetNetworkInterface
== NULL
) {
1227 // Discover Redfish services on all of network interfaces.
1229 TargetNetworkInterfaceInternal
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetNextNode (&mEfiRedfishDiscoverNetworkInterface
, &TargetNetworkInterfaceInternal
->Entry
);
1237 This function aborts Redfish service discovery on the given network interface.
1239 @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instance.
1240 @param[in] TargetNetworkInterface Target network interface to do the discovery.
1242 @retval EFI_SUCCESS REST EX instance of discovered Redfish services are returned.
1243 @retval Others Fail to abort Redfish service discovery.
1248 RedfishServiceAbortAcquire (
1249 IN EFI_REDFISH_DISCOVER_PROTOCOL
*This
,
1250 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE
*TargetNetworkInterface OPTIONAL
1253 // This function is used to abort Redfish service discovery through SSDP
1254 // on the network interface. SSDP is optionally supprted by EFI_REDFISH_DISCOVER_PROTOCOL,
1255 // we dont have implementation for SSDP now.
1257 return EFI_UNSUPPORTED
;
1261 This function releases Redfish services found by RedfishServiceAcquire().
1263 @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instance.
1264 @param[in] InstanceList The Redfish service to release.
1266 @retval EFI_SUCCESS REST EX instances of discovered Redfish are released.
1267 @retval Others Fail to remove the entry
1272 RedfishServiceReleaseService (
1273 IN EFI_REDFISH_DISCOVER_PROTOCOL
*This
,
1274 IN EFI_REDFISH_DISCOVERED_LIST
*InstanceList
1278 BOOLEAN AnyFailRelease
;
1279 EFI_REDFISH_DISCOVERED_INSTANCE
*ThisRedfishInstance
;
1280 EFI_REDFISH_DISCOVERED_INTERNAL_LIST
*DiscoveredRedfishInstance
;
1282 if (IsListEmpty (&mRedfishInstanceList
)) {
1283 DEBUG ((DEBUG_ERROR
, "%a:No any discovered Redfish service.\n", __FUNCTION__
));
1284 return EFI_NOT_FOUND
;
1287 AnyFailRelease
= FALSE
;
1288 ThisRedfishInstance
= InstanceList
->RedfishInstances
;
1289 for (NumService
= 0; NumService
< InstanceList
->NumberOfServiceFound
; NumService
++) {
1290 DiscoveredRedfishInstance
= (EFI_REDFISH_DISCOVERED_INTERNAL_LIST
*)GetFirstNode (&mRedfishInstanceList
);
1292 if (DiscoveredRedfishInstance
->Instance
== ThisRedfishInstance
) {
1293 RemoveEntryList (&DiscoveredRedfishInstance
->NextInstance
);
1294 if (ThisRedfishInstance
->Information
.Location
!= NULL
) {
1295 FreePool (ThisRedfishInstance
->Information
.Location
);
1298 if (ThisRedfishInstance
->Information
.Uuid
!= NULL
) {
1299 FreePool (ThisRedfishInstance
->Information
.Uuid
);
1302 if (ThisRedfishInstance
->Information
.Os
!= NULL
) {
1303 FreePool (ThisRedfishInstance
->Information
.Os
);
1306 if (ThisRedfishInstance
->Information
.OsVersion
!= NULL
) {
1307 FreePool (ThisRedfishInstance
->Information
.OsVersion
);
1310 if (ThisRedfishInstance
->Information
.Product
!= NULL
) {
1311 FreePool (ThisRedfishInstance
->Information
.Product
);
1314 if (ThisRedfishInstance
->Information
.ProductVer
!= NULL
) {
1315 FreePool (ThisRedfishInstance
->Information
.ProductVer
);
1318 FreePool ((VOID
*)ThisRedfishInstance
);
1322 if (IsNodeAtEnd (&mRedfishInstanceList
, &DiscoveredRedfishInstance
->NextInstance
)) {
1326 DiscoveredRedfishInstance
= (EFI_REDFISH_DISCOVERED_INTERNAL_LIST
*)GetNextNode (&mRedfishInstanceList
, &DiscoveredRedfishInstance
->NextInstance
);
1329 AnyFailRelease
= TRUE
;
1332 // Release next discovered Redfish Service.
1334 ThisRedfishInstance
= (EFI_REDFISH_DISCOVERED_INSTANCE
*)((UINT8
*)ThisRedfishInstance
+ sizeof (EFI_REDFISH_DISCOVERED_INSTANCE
));
1337 if (AnyFailRelease
) {
1338 return EFI_NOT_FOUND
;
1344 EFI_REDFISH_DISCOVER_PROTOCOL mRedfishDiscover
= {
1345 RedfishServiceGetNetworkInterface
,
1346 RedfishServiceAcquireService
,
1347 RedfishServiceAbortAcquire
,
1348 RedfishServiceReleaseService
1352 This function create an EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL for the
1353 given network interface.
1356 @param[in] ControllerHandle MAC address of this network interface.
1357 @param[in] NetworkProtocolType Network protocol type.
1358 @param[out] IsNewInstance BOOLEAN means new instance or not.
1359 @param[out] NetworkInterface Pointer to to EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL.
1364 CreateRedfishDiscoverNetworkInterface (
1365 IN EFI_HANDLE ControllerHandle
,
1366 IN UINT32 NetworkProtocolType
,
1367 OUT BOOLEAN
*IsNewInstance
,
1368 OUT EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
**NetworkInterface
1371 EFI_MAC_ADDRESS MacAddress
;
1372 UINTN HwAddressSize
;
1373 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*ThisNetworkInterface
;
1374 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*NewNetworkInterface
;
1376 NetLibGetMacAddress (ControllerHandle
, &MacAddress
, &HwAddressSize
);
1377 NewNetworkInterface
= NULL
;
1378 *IsNewInstance
= TRUE
;
1379 if (!IsListEmpty ((const LIST_ENTRY
*)&mEfiRedfishDiscoverNetworkInterface
)) {
1381 // Check if this instance already exist.
1383 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface
);
1384 if (ThisNetworkInterface
!= NULL
) {
1386 if ((CompareMem ((CONST VOID
*)&ThisNetworkInterface
->MacAddress
.Addr
, (CONST VOID
*)&MacAddress
.Addr
, HwAddressSize
) == 0) &&
1387 (ThisNetworkInterface
->NetworkProtocolType
== NetworkProtocolType
))
1389 NewNetworkInterface
= ThisNetworkInterface
;
1390 *IsNewInstance
= FALSE
;
1394 if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterface
->Entry
)) {
1395 NewNetworkInterface
= NULL
;
1399 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetNextNode (&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterface
->Entry
);
1404 if (NewNetworkInterface
== NULL
) {
1406 // Create a new instance.
1408 NewNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
));
1409 if (NewNetworkInterface
== NULL
) {
1410 return EFI_OUT_OF_RESOURCES
;
1413 NewNetworkInterface
->HwAddressSize
= HwAddressSize
;
1414 CopyMem (&NewNetworkInterface
->MacAddress
.Addr
, &MacAddress
.Addr
, NewNetworkInterface
->HwAddressSize
);
1415 NetLibGetMacString (ControllerHandle
, NULL
, &NewNetworkInterface
->StrMacAddr
);
1416 NewNetworkInterface
->VlanId
= NetLibGetVlanId (ControllerHandle
);
1419 *NetworkInterface
= NewNetworkInterface
;
1424 This function destory network interface
1427 @param[in] ThisNetworkInterface EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL instance.
1432 DestroyRedfishNetwrokInterface (
1433 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*ThisNetworkInterface
1438 Status
= gBS
->UninstallProtocolInterface (
1439 ThisNetworkInterface
->OpenDriverControllerHandle
,
1440 gRequiredProtocol
[ThisNetworkInterface
->NetworkProtocolType
].DiscoveredProtocolGuid
,
1441 &ThisNetworkInterface
->NetworkInterfaceProtocolInfo
.ProtocolDiscoverId
1443 RemoveEntryList (&ThisNetworkInterface
->Entry
);
1444 mNumNetworkInterface
--;
1445 FreePool (ThisNetworkInterface
);
1450 Tests to see if the required protocols are provided on the given
1453 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1454 @param[in] ControllerHandle The handle of the controller to test. This handle
1455 must support a protocol interface that supplies
1456 an I/O abstraction to the driver.
1457 @retval EFI_SUCCESS One of required protocol is found.
1458 @retval EFI_UNSUPPORTED None of required protocol is found.
1461 TestForRequiredProtocols (
1462 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1463 IN EFI_HANDLE ControllerHandle
1470 for (Index
= 0; Index
< (sizeof (gRequiredProtocol
) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL
)); Index
++) {
1471 Status
= gBS
->OpenProtocol (
1473 gRequiredProtocol
[Index
].RequiredServiceBindingProtocolGuid
,
1475 This
->DriverBindingHandle
,
1477 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
1479 if (!EFI_ERROR (Status
)) {
1480 Status
= gBS
->OpenProtocol (
1482 gRequiredProtocol
[Index
].DiscoveredProtocolGuid
,
1484 This
->DriverBindingHandle
,
1486 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1488 if (EFI_ERROR (Status
)) {
1489 DEBUG ((DEBUG_ERROR
, "%a: %s is found on this controller handle.\n", __FUNCTION__
, gRequiredProtocol
[Index
].ProtocolName
));
1495 return EFI_UNSUPPORTED
;
1499 Build up network interface and create corresponding service through the given
1502 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1503 @param[in] ControllerHandle The handle of the controller to test. This handle
1504 must support a protocol interface that supplies
1505 an I/O abstraction to the driver.
1506 @retval EFI_SUCCESS One of required protocol is found.
1507 @retval EFI_UNSUPPORTED None of required protocol is found.
1508 @retval EFI_UNSUPPORTED Failed to build up network interface.
1511 BuildupNetworkInterface (
1512 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1513 IN EFI_HANDLE ControllerHandle
1518 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*NetworkInterface
;
1521 VOID
*TempInterface
;
1523 UINT32
*ProtocolDiscoverIdPtr
;
1524 EFI_HANDLE OpenDriverAgentHandle
;
1525 EFI_HANDLE OpenDriverControllerHandle
;
1526 EFI_HANDLE
*HandleOfProtocolInterfacePtr
;
1527 EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL
*RestExInstance
;
1529 BOOLEAN NewNetworkInterfaceInstalled
;
1531 NewNetworkInterfaceInstalled
= FALSE
;
1534 Status
= gBS
->OpenProtocol (
1537 gRequiredProtocol
[Index
].DiscoveredProtocolGuid
,
1539 This
->DriverBindingHandle
,
1541 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1543 if (!EFI_ERROR (Status
)) {
1545 if (Index
== (sizeof (gRequiredProtocol
) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL
))) {
1552 Status
= gBS
->OpenProtocol (
1554 gRequiredProtocol
[Index
].RequiredServiceBindingProtocolGuid
,
1556 This
->DriverBindingHandle
,
1558 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1560 if (EFI_ERROR (Status
)) {
1562 if (Index
== (sizeof (gRequiredProtocol
) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL
))) {
1569 if (gRequiredProtocol
[Index
].ProtocolType
!= ProtocolTypeRestEx
) {
1570 OldTpl
= gBS
->RaiseTPL (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL
);
1571 Status
= CreateRedfishDiscoverNetworkInterface (ControllerHandle
, gRequiredProtocol
[Index
].ProtocolType
, &IsNew
, &NetworkInterface
);
1572 if (EFI_ERROR (Status
)) {
1573 gBS
->RestoreTPL (OldTpl
);
1577 NetworkInterface
->NetworkProtocolType
= gRequiredProtocol
[Index
].ProtocolType
;
1578 NetworkInterface
->OpenDriverAgentHandle
= This
->DriverBindingHandle
;
1579 NetworkInterface
->OpenDriverControllerHandle
= ControllerHandle
;
1580 NetworkInterface
->NetworkInterfaceProtocolInfo
.ProtocolGuid
= \
1581 *gRequiredProtocol
[Index
].RequiredProtocolGuid
;
1582 NetworkInterface
->NetworkInterfaceProtocolInfo
.ProtocolServiceGuid
= \
1583 *gRequiredProtocol
[Index
].RequiredServiceBindingProtocolGuid
;
1584 ProtocolDiscoverIdPtr
= &NetworkInterface
->NetworkInterfaceProtocolInfo
.ProtocolDiscoverId
;
1585 OpenDriverAgentHandle
= NetworkInterface
->OpenDriverAgentHandle
;
1586 OpenDriverControllerHandle
= NetworkInterface
->OpenDriverControllerHandle
;
1587 HandleOfProtocolInterfacePtr
= &NetworkInterface
->NetworkInterfaceProtocolInfo
.ProtocolControllerHandle
;
1588 Interface
= &NetworkInterface
->NetworkInterfaceProtocolInfo
.NetworkProtocolInterface
;
1589 NewNetworkInterfaceInstalled
= TRUE
;
1591 InsertTailList (&mEfiRedfishDiscoverNetworkInterface
, &NetworkInterface
->Entry
);
1592 mNumNetworkInterface
++;
1595 gBS
->RestoreTPL (OldTpl
);
1597 // Record REST_EX instance. REST_EX is created when clinet asks for Redfish service discovery.
1598 // Redfish Service Discover protocol will match REST EX to the corresponding EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
1601 RestExInstance
= (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL
*)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL
));
1602 if (RestExInstance
== NULL
) {
1603 return EFI_OUT_OF_RESOURCES
;
1606 RestExInstance
->OpenDriverAgentHandle
= This
->DriverBindingHandle
;
1607 RestExInstance
->OpenDriverControllerHandle
= ControllerHandle
;
1608 RestExInstance
->RestExControllerHandle
= ControllerHandle
;
1609 InitializeListHead (&RestExInstance
->Entry
);
1610 InsertTailList (&mEfiRedfishDiscoverRestExInstance
, &RestExInstance
->Entry
);
1611 mNumRestExInstance
++;
1612 ProtocolDiscoverIdPtr
= &RestExInstance
->RestExId
;
1613 OpenDriverAgentHandle
= RestExInstance
->OpenDriverAgentHandle
;
1614 OpenDriverControllerHandle
= RestExInstance
->OpenDriverControllerHandle
;
1615 HandleOfProtocolInterfacePtr
= &RestExInstance
->RestExChildHandle
;
1616 Interface
= (VOID
**)&RestExInstance
->RestExProtocolInterface
;
1619 Status
= gBS
->InstallProtocolInterface (
1621 gRequiredProtocol
[Index
].DiscoveredProtocolGuid
,
1622 EFI_NATIVE_INTERFACE
,
1623 ProtocolDiscoverIdPtr
1625 if (EFI_ERROR (Status
)) {
1627 if (Index
== (sizeof (gRequiredProtocol
) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL
))) {
1635 // Create service binding child and open it BY_DRIVER.
1637 Status
= NetLibCreateServiceChild (
1640 gRequiredProtocol
[Index
].RequiredServiceBindingProtocolGuid
,
1641 HandleOfProtocolInterfacePtr
1643 if (!EFI_ERROR (Status
)) {
1644 Status
= gBS
->OpenProtocol (
1645 *HandleOfProtocolInterfacePtr
,
1646 gRequiredProtocol
[Index
].RequiredProtocolGuid
,
1648 OpenDriverAgentHandle
,
1649 OpenDriverControllerHandle
,
1650 EFI_OPEN_PROTOCOL_BY_DRIVER
1652 if (!EFI_ERROR (Status
)) {
1653 if ((gRequiredProtocol
[Index
].ProtocolType
== ProtocolTypeRestEx
)) {
1654 // Install Redfish Discover Protocol when EFI REST EX protcol is discovered.
1655 // This ensures EFI REST EX is ready while the consumer of EFI_REDFISH_DISCOVER_PROTOCOL
1656 // acquires Redfish serivce over network interface.
1658 if (!NewNetworkInterfaceInstalled
) {
1659 NetworkInterface
= GetTargetNetworkInterfaceInternalByController (ControllerHandle
);
1660 if (NetworkInterface
== NULL
) {
1661 DEBUG ((DEBUG_ERROR
, "%a: Can't find network interface by ControllerHandle\n", __FUNCTION__
));
1666 NewNetworkInterfaceInstalled
= FALSE
;
1667 NetworkInterface
->EfiRedfishDiscoverProtocolHandle
= NULL
;
1668 Status
= gBS
->InstallProtocolInterface (
1669 &NetworkInterface
->EfiRedfishDiscoverProtocolHandle
,
1670 &gEfiRedfishDiscoverProtocolGuid
,
1671 EFI_NATIVE_INTERFACE
,
1672 (VOID
*)&mRedfishDiscover
1674 if (EFI_ERROR (Status
)) {
1675 DEBUG ((DEBUG_ERROR
, "%a: Fail to install EFI_REDFISH_DISCOVER_PROTOCOL\n", __FUNCTION__
));
1683 if (Index
== (sizeof (gRequiredProtocol
) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL
))) {
1689 } while (Index
< (sizeof (gRequiredProtocol
) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL
)));
1691 return EFI_UNSUPPORTED
;
1695 Close the protocol opened for Redfish discovery. This function also destories
1696 the network services.
1698 @param[in] ThisBindingProtocol A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1699 @param[in] ControllerHandle The handle of the controller to test. This handle
1700 must support a protocol interface that supplies
1701 an I/O abstraction to the driver.
1702 @param[in] ThisRequiredProtocol Pointer to the instance of REDFISH_DISCOVER_REQUIRED_PROTOCOL.
1703 @param[in] DriverAgentHandle Driver agent handle which used to open protocol earlier.
1704 @param[in] DriverControllerHandle Driver controller handle which used to open protocol earlier.
1706 @retval EFI_SUCCESS Prorocol is closed successfully.
1707 @retval Others Prorocol is closed unsuccessfully.
1711 CloseProtocolService (
1712 IN EFI_DRIVER_BINDING_PROTOCOL
*ThisBindingProtocol
,
1713 IN EFI_HANDLE ControllerHandle
,
1714 IN REDFISH_DISCOVER_REQUIRED_PROTOCOL
*ThisRequiredProtocol
,
1715 IN EFI_HANDLE DriverAgentHandle
,
1716 IN EFI_HANDLE DriverControllerHandle
1721 Status
= gBS
->CloseProtocol (
1723 ThisRequiredProtocol
->RequiredProtocolGuid
,
1725 DriverControllerHandle
1727 if (!EFI_ERROR (Status
)) {
1728 NetLibDestroyServiceChild (
1730 ThisBindingProtocol
->ImageHandle
,
1731 ThisRequiredProtocol
->RequiredServiceBindingProtocolGuid
,
1740 Stop the services on network interface.
1742 @param[in] ThisBindingProtocol A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1743 @param[in] ControllerHandle The handle of the controller to test. This handle
1744 must support a protocol interface that supplies
1745 an I/O abstraction to the driver.
1746 @retval EFI_SUCCESS One of required protocol is found.
1747 @retval Others Faile to stop the services on network interface.
1750 StopServiceOnNetworkInterface (
1751 IN EFI_DRIVER_BINDING_PROTOCOL
*ThisBindingProtocol
,
1752 IN EFI_HANDLE ControllerHandle
1759 EFI_HANDLE DiscoverProtocolHandle
;
1760 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*ThisNetworkInterface
;
1761 EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL
*RestExInstance
;
1763 for (Index
= 0; Index
< (sizeof (gRequiredProtocol
) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL
)); Index
++) {
1764 Status
= gBS
->HandleProtocol (
1766 gRequiredProtocol
[Index
].RequiredProtocolGuid
,
1769 if (!EFI_ERROR (Status
)) {
1770 if (gRequiredProtocol
[Index
].ProtocolType
!= ProtocolTypeRestEx
) {
1771 if (IsListEmpty (&mEfiRedfishDiscoverNetworkInterface
)) {
1772 return EFI_NOT_FOUND
;
1775 OldTpl
= gBS
->RaiseTPL (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL
);
1776 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface
);
1778 if (ThisNetworkInterface
->NetworkInterfaceProtocolInfo
.ProtocolControllerHandle
== ControllerHandle
) {
1779 DiscoverProtocolHandle
= ThisNetworkInterface
->EfiRedfishDiscoverProtocolHandle
;
1781 // Close protocol and destroy service.
1783 Status
= CloseProtocolService (
1784 ThisBindingProtocol
,
1786 &gRequiredProtocol
[Index
],
1787 ThisNetworkInterface
->OpenDriverAgentHandle
,
1788 ThisNetworkInterface
->OpenDriverControllerHandle
1790 if (!EFI_ERROR (Status
)) {
1791 Status
= DestroyRedfishNetwrokInterface (ThisNetworkInterface
);
1794 gBS
->RestoreTPL (OldTpl
);
1797 // Disconnect EFI Redfish discover driver controller to notify the
1798 // clinet which uses .EFI Redfish discover protocol.
1800 if (DiscoverProtocolHandle
!= NULL
) {
1801 gBS
->DisconnectController (DiscoverProtocolHandle
, NULL
, NULL
);
1802 Status
= gBS
->UninstallProtocolInterface (
1803 DiscoverProtocolHandle
,
1804 &gEfiRedfishDiscoverProtocolGuid
,
1805 (VOID
*)&mRedfishDiscover
1812 if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterface
->Entry
)) {
1816 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetNextNode (&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterface
->Entry
);
1819 gBS
->RestoreTPL (OldTpl
);
1821 if (IsListEmpty (&mEfiRedfishDiscoverRestExInstance
)) {
1822 return EFI_NOT_FOUND
;
1825 OldTpl
= gBS
->RaiseTPL (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL
);
1826 RestExInstance
= (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL
*)GetFirstNode (&mEfiRedfishDiscoverRestExInstance
);
1828 if (RestExInstance
->RestExChildHandle
== ControllerHandle
) {
1829 Status
= CloseProtocolService (
1830 // Close REST_EX protocol.
1831 ThisBindingProtocol
,
1833 &gRequiredProtocol
[Index
],
1834 RestExInstance
->OpenDriverAgentHandle
,
1835 RestExInstance
->OpenDriverControllerHandle
1837 RemoveEntryList (&RestExInstance
->Entry
);
1838 FreePool ((VOID
*)RestExInstance
);
1839 mNumRestExInstance
--;
1840 gBS
->RestoreTPL (OldTpl
);
1844 if (IsNodeAtEnd (&mEfiRedfishDiscoverRestExInstance
, &RestExInstance
->Entry
)) {
1848 RestExInstance
= (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL
*)GetNextNode (&mEfiRedfishDiscoverRestExInstance
, &RestExInstance
->Entry
);
1851 gBS
->RestoreTPL (OldTpl
);
1856 return EFI_NOT_FOUND
;
1860 Tests to see if this driver supports a given controller. If a child device is provided,
1861 it further tests to see if this driver supports creating a handle for the specified child device.
1863 This function checks to see if the driver specified by This supports the device specified by
1864 ControllerHandle. Drivers will typically use the device path attached to
1865 ControllerHandle and/or the services from the bus I/O abstraction attached to
1866 ControllerHandle to determine if the driver supports ControllerHandle. This function
1867 may be called many times during platform initialization. In order to reduce boot times, the tests
1868 performed by this function must be very small, and take as little time as possible to execute. This
1869 function must not change the state of any hardware devices, and this function must be aware that the
1870 device specified by ControllerHandle may already be managed by the same driver or a
1871 different driver. This function must match its calls to AllocatePages() with FreePages(),
1872 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
1873 Because ControllerHandle may have been previously started by the same driver, if a protocol is
1874 already in the opened state, then it must not be closed with CloseProtocol(). This is required
1875 to guarantee the state of ControllerHandle is not modified by this function.
1877 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1878 @param[in] ControllerHandle The handle of the controller to test. This handle
1879 must support a protocol interface that supplies
1880 an I/O abstraction to the driver.
1881 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
1882 parameter is ignored by device drivers, and is optional for bus
1883 drivers. For bus drivers, if this parameter is not NULL, then
1884 the bus driver must determine if the bus controller specified
1885 by ControllerHandle and the child controller specified
1886 by RemainingDevicePath are both supported by this
1889 @retval EFI_SUCCESS The device specified by ControllerHandle and
1890 RemainingDevicePath is supported by the driver specified by This.
1891 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
1892 RemainingDevicePath is already being managed by the driver
1894 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
1895 RemainingDevicePath is already being managed by a different
1896 driver or an application that requires exclusive access.
1897 Currently not implemented.
1898 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
1899 RemainingDevicePath is not supported by the driver specified by This.
1903 RedfishDiscoverDriverBindingSupported (
1904 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1905 IN EFI_HANDLE ControllerHandle
,
1906 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1909 return TestForRequiredProtocols (This
, ControllerHandle
);
1913 Starts a device controller or a bus controller.
1915 The Start() function is designed to be invoked from the EFI boot service ConnectController().
1916 As a result, much of the error checking on the parameters to Start() has been moved into this
1917 common boot service. It is legal to call Start() from other locations,
1918 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
1919 1. ControllerHandle must be a valid EFI_HANDLE.
1920 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
1921 EFI_DEVICE_PATH_PROTOCOL.
1922 3. Prior to calling Start(), the Supported() function for the driver specified by This must
1923 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
1925 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1926 @param[in] ControllerHandle The handle of the controller to start. This handle
1927 must support a protocol interface that supplies
1928 an I/O abstraction to the driver.
1929 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
1930 parameter is ignored by device drivers, and is optional for bus
1931 drivers. For a bus driver, if this parameter is NULL, then handles
1932 for all the children of Controller are created by this driver.
1933 If this parameter is not NULL and the first Device Path Node is
1934 not the End of Device Path Node, then only the handle for the
1935 child device specified by the first Device Path Node of
1936 RemainingDevicePath is created by this driver.
1937 If the first Device Path Node of RemainingDevicePath is
1938 the End of Device Path Node, no child handle is created by this
1941 @retval EFI_SUCCESS The device was started.
1942 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
1943 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1944 @retval Others The driver failded to start the device.
1949 RedfishDiscoverDriverBindingStart (
1950 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1951 IN EFI_HANDLE ControllerHandle
,
1952 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1955 return BuildupNetworkInterface (This
, ControllerHandle
);
1959 Stops a device controller or a bus controller.
1961 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
1962 As a result, much of the error checking on the parameters to Stop() has been moved
1963 into this common boot service. It is legal to call Stop() from other locations,
1964 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
1965 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
1966 same driver's Start() function.
1967 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
1968 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
1969 Start() function, and the Start() function must have called OpenProtocol() on
1970 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
1972 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1973 @param[in] ControllerHandle A handle to the device being stopped. The handle must
1974 support a bus specific I/O protocol for the driver
1975 to use to stop the device.
1976 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
1977 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
1978 if NumberOfChildren is 0.
1980 @retval EFI_SUCCESS The device was stopped.
1981 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
1986 RedfishDiscoverDriverBindingStop (
1987 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1988 IN EFI_HANDLE ControllerHandle
,
1989 IN UINTN NumberOfChildren
,
1990 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
1993 return StopServiceOnNetworkInterface (This
, ControllerHandle
);
1996 EFI_DRIVER_BINDING_PROTOCOL gRedfishDiscoverDriverBinding
= {
1997 RedfishDiscoverDriverBindingSupported
,
1998 RedfishDiscoverDriverBindingStart
,
1999 RedfishDiscoverDriverBindingStop
,
2000 REDFISH_DISCOVER_VERSION
,
2006 This is the declaration of an EFI image entry point.
2008 @param ImageHandle The firmware allocated handle for the UEFI image.
2009 @param SystemTable A pointer to the EFI System Table.
2011 @retval EFI_SUCCESS The operation completed successfully.
2012 @retval Others An unexpected error occurred.
2016 RedfishDiscoverEntryPoint (
2017 IN EFI_HANDLE ImageHandle
,
2018 IN EFI_SYSTEM_TABLE
*SystemTable
2023 Status
= EFI_SUCCESS
;
2024 InitializeListHead (&mRedfishDiscoverList
);
2025 InitializeListHead (&mRedfishInstanceList
);
2026 InitializeListHead (&mEfiRedfishDiscoverNetworkInterface
);
2027 InitializeListHead (&mEfiRedfishDiscoverRestExInstance
);
2029 // Install binding protoocl to obtain UDP and REST EX protocol.
2031 Status
= EfiLibInstallDriverBindingComponentName2 (
2034 &gRedfishDiscoverDriverBinding
,
2036 &gRedfishDiscoverComponentName
,
2037 &gRedfishDiscoverComponentName2
2043 This is the unload handle for Redfish discover module.
2045 Disconnect the driver specified by ImageHandle from all the devices in the handle database.
2046 Uninstall all the protocols installed in the driver entry point.
2048 @param[in] ImageHandle The drivers' driver image.
2050 @retval EFI_SUCCESS The image is unloaded.
2051 @retval Others Failed to unload the image.
2056 RedfishDiscoverUnload (
2057 IN EFI_HANDLE ImageHandle
2061 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*ThisNetworkInterface
;
2063 Status
= EFI_SUCCESS
;
2064 // Destroy all network interfaces found by EFI Redfish Discover driver and
2065 // stop services created for Redfish Discover.
2067 while (!IsListEmpty (&mEfiRedfishDiscoverNetworkInterface
)) {
2068 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface
);
2069 StopServiceOnNetworkInterface (&gRedfishDiscoverDriverBinding
, ThisNetworkInterface
->NetworkInterfaceProtocolInfo
.ProtocolControllerHandle
);