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
)) {
123 (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
*)GetFirstNode (&mRedfishDiscoverList
);
125 if ((ThisInstance
->Owner
== ImageHandle
) &&
126 (ThisInstance
->DiscoverFlags
== DiscoverFlags
) &&
127 (ThisInstance
->NetworkInterface
== TargetNetworkInterface
)) {
130 if (IsNodeAtEnd (&mRedfishDiscoverList
, &ThisInstance
->Entry
)) {
134 (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
*)GetNextNode (&mRedfishDiscoverList
, &ThisInstance
->Entry
);
140 This function gets the subnet information of this TCP4 instance.
142 @param[in] ImageHandle EFI handle with this image.
143 @param[in] Instance Instance of Network interface.
144 @retval EFI_STATUS Get subnet information successfully.
145 @retval Otherwise Fail to get subnet information.
150 IN EFI_HANDLE ImageHandle
,
151 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*Instance
155 EFI_TCP4_PROTOCOL
*Tcp4
;
156 EFI_TCP4_CONFIG_DATA Tcp4CfgData
;
157 EFI_TCP4_OPTION Tcp4Option
;
158 EFI_IP4_MODE_DATA IpModedata
;
159 UINT8 SubnetMaskIndex
;
162 BOOLEAN GotPrefixLength
;
164 if (Instance
== NULL
) {
165 return EFI_INVALID_PARAMETER
;
167 Tcp4
= (EFI_TCP4_PROTOCOL
*)Instance
->NetworkInterfaceProtocolInfo
.NetworkProtocolInterface
;
169 ZeroMem ((VOID
*)&Tcp4CfgData
, sizeof (EFI_TCP4_CONFIG_DATA
));
170 ZeroMem ((VOID
*)&Tcp4Option
, sizeof (EFI_TCP4_OPTION
));
171 // Give a local host IP address just for getting subnet information.
172 Tcp4CfgData
.AccessPoint
.UseDefaultAddress
= TRUE
;
173 Tcp4CfgData
.AccessPoint
.RemoteAddress
.Addr
[0] = 127;
174 Tcp4CfgData
.AccessPoint
.RemoteAddress
.Addr
[1] = 0;
175 Tcp4CfgData
.AccessPoint
.RemoteAddress
.Addr
[2] = 0;
176 Tcp4CfgData
.AccessPoint
.RemoteAddress
.Addr
[3] = 1;
177 Tcp4CfgData
.AccessPoint
.RemotePort
= 80;
178 Tcp4CfgData
.AccessPoint
.ActiveFlag
= TRUE
;
180 Tcp4CfgData
.ControlOption
= &Tcp4Option
;
181 Tcp4Option
.ReceiveBufferSize
= 65535;
182 Tcp4Option
.SendBufferSize
= 65535;
183 Tcp4Option
.MaxSynBackLog
= 5;
184 Tcp4Option
.ConnectionTimeout
= 60;
185 Tcp4Option
.DataRetries
= 12;
186 Tcp4Option
.FinTimeout
= 2;
187 Tcp4Option
.KeepAliveProbes
= 6;
188 Tcp4Option
.KeepAliveTime
= 7200;
189 Tcp4Option
.KeepAliveInterval
= 30;
190 Tcp4Option
.EnableNagle
= TRUE
;
191 Status
= Tcp4
->Configure (Tcp4
, &Tcp4CfgData
);
192 if (EFI_ERROR (Status
)) {
193 DEBUG ((DEBUG_ERROR
, "%a: Can't get subnet information\n", __FUNCTION__
));
196 Status
= Tcp4
->GetModeData (Tcp4
, NULL
, NULL
, &IpModedata
, NULL
, NULL
);
197 if (EFI_ERROR (Status
)) {
198 DEBUG ((DEBUG_ERROR
, "%a: Can't get IP mode data information\n", __FUNCTION__
));
201 IP4_COPY_ADDRESS (&Instance
->SubnetMask
, &IpModedata
.ConfigData
.SubnetMask
);
202 Instance
->SubnetAddr
.v4
.Addr
[0] = IpModedata
.ConfigData
.StationAddress
.Addr
[0] & Instance
->SubnetMask
.v4
.Addr
[0];
203 Instance
->SubnetAddr
.v4
.Addr
[1] = IpModedata
.ConfigData
.StationAddress
.Addr
[1] & Instance
->SubnetMask
.v4
.Addr
[1];
204 Instance
->SubnetAddr
.v4
.Addr
[2] = IpModedata
.ConfigData
.StationAddress
.Addr
[2] & Instance
->SubnetMask
.v4
.Addr
[2];
205 Instance
->SubnetAddr
.v4
.Addr
[3] = IpModedata
.ConfigData
.StationAddress
.Addr
[3] & Instance
->SubnetMask
.v4
.Addr
[3];
207 // Calculate the subnet mask prefix.
209 GotPrefixLength
= FALSE
;
212 while (GotPrefixLength
== FALSE
&& SubnetMaskIndex
< 4) {
214 while (BitMask
!= 0) {
215 if ((Instance
->SubnetMask
.v4
.Addr
[SubnetMaskIndex
] & BitMask
) != 0) {
218 GotPrefixLength
= TRUE
;
221 BitMask
= BitMask
>> 1;
225 Instance
->SubnetPrefixLength
= PrefixLength
;
230 This function gets the subnet information of this TCP6 instance.
232 @param[in] ImageHandle EFI handle with this image.
233 @param[in] Instance Instance of Network interface.
234 @retval EFI_STATUS Get subnet information successfully.
235 @retval Otherwise Fail to get subnet information.
240 IN EFI_HANDLE ImageHandle
,
241 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*Instance
245 EFI_TCP6_PROTOCOL
*Tcp6
;
246 EFI_IP6_MODE_DATA IpModedata
;
248 if (Instance
== NULL
) {
249 return EFI_INVALID_PARAMETER
;
251 Tcp6
= (EFI_TCP6_PROTOCOL
*)Instance
->NetworkInterfaceProtocolInfo
.NetworkProtocolInterface
;
253 Status
= Tcp6
->GetModeData (Tcp6
, NULL
, NULL
, &IpModedata
, NULL
, NULL
);
254 if (EFI_ERROR (Status
)) {
255 DEBUG ((DEBUG_ERROR
, "%a: Can't get IP mode data information\n"));
258 if (IpModedata
.AddressCount
== 0) {
259 DEBUG ((DEBUG_INFO
, "%a: No IPv6 address configured.\n"));
261 if (Instance
->SubnetAddrInfoIPv6
!= NULL
) {
262 FreePool (Instance
->SubnetAddrInfoIPv6
);
264 Instance
->SubnetAddrInfoIPv6
= AllocateZeroPool (IpModedata
.AddressCount
* sizeof (EFI_IP6_ADDRESS_INFO
));
265 if (Instance
->SubnetAddrInfoIPv6
== NULL
) {
266 DEBUG ((DEBUG_ERROR
, "%a: Failed to allocate memory fir IPv6 subnet address information\n"));
267 return EFI_OUT_OF_RESOURCES
;
269 Instance
->SubnetAddrInfoIPv6Number
= IpModedata
.AddressCount
;
271 (VOID
*)Instance
->SubnetAddrInfoIPv6
,
272 (VOID
*)&IpModedata
.AddressList
,
273 IpModedata
.AddressCount
* sizeof (EFI_IP6_ADDRESS_INFO
)
275 FreePool (IpModedata
.AddressList
);
280 This function searches EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
281 instance with the given EFI_REDFISH_DISCOVER_NETWORK_INTERFACE.
283 @param[in] TargetNetworkInterface EFI_REDFISH_DISCOVER_NETWORK_INTERFACE.
284 NULL for all EFI_REDFISH_DISCOVER_NETWORK_INTERFACEs.
286 @retval Non-NULL EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL is returned.
287 @retval NULL Non of EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL instance is returned.
289 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*
290 GetTargetNetworkInterfaceInternal (
291 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE
*TargetNetworkInterface
294 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*ThisNetworkInterface
;
296 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface
);
298 if (CompareMem((VOID
*)&ThisNetworkInterface
->MacAddress
, &TargetNetworkInterface
->MacAddress
, ThisNetworkInterface
->HwAddressSize
) == 0) {
299 return ThisNetworkInterface
;
301 if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterface
->Entry
)) {
304 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetNextNode(&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterface
->Entry
);
310 This function validate if target network interface is ready for discovering
313 @param[in] TargetNetworkInterface EFI_REDFISH_DISCOVER_NETWORK_INTERFACE.
314 NULL for all EFI_REDFISH_DISCOVER_NETWORK_INTERFACEs.
315 @param[in] Flags EFI_REDFISH_DISCOVER_FLAG
317 @retval EFI_SUCCESS Target network interface is ready to use.
318 @retval EFI_UNSUPPORTED Target network interface is not ready to use.
321 ValidateTargetNetworkInterface (
322 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE
*TargetNetworkInterface
,
323 IN EFI_REDFISH_DISCOVER_FLAG Flags
326 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*ThisNetworkInterface
;
328 if (IsListEmpty (&mEfiRedfishDiscoverNetworkInterface
) && TargetNetworkInterface
== NULL
) {
329 return EFI_UNSUPPORTED
;
331 if (TargetNetworkInterface
== NULL
) {
332 return EFI_SUCCESS
; // Return EFI_SUCCESS if no network interface is specified.
335 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetFirstNode(&mEfiRedfishDiscoverNetworkInterface
);
337 if (CompareMem((VOID
*)&ThisNetworkInterface
->MacAddress
, &TargetNetworkInterface
->MacAddress
, ThisNetworkInterface
->HwAddressSize
) == 0) {
340 if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterface
->Entry
)) {
341 return EFI_UNSUPPORTED
;
343 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetNextNode(&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterface
->Entry
);
345 if ((Flags
& EFI_REDFISH_DISCOVER_SSDP
) != 0) {
346 // Validate if UDP4/6 is supported on the given network interface.
347 // SSDP is not supported.
351 if (ThisNetworkInterface
->NetworkInterfaceProtocolInfo
.ProtocolControllerHandle
== NULL
) {
352 return EFI_UNSUPPORTED
; // The required protocol on this network interface is not found.
357 This function returns number of network interface instance.
359 @retval UINTN Number of network interface instances.
362 NumberOfNetworkInterface (VOID
)
365 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*ThisNetworkInterface
;
367 if (IsListEmpty (&mEfiRedfishDiscoverNetworkInterface
)) {
372 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface
);
374 if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterface
->Entry
)) {
377 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetNextNode(&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterface
->Entry
);
384 This function checks the IP version supported on this
387 @param[in] ThisNetworkInterface EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
389 @retval TRUE Is IPv6, otherwise IPv4.
394 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*ThisNetworkInterface
397 if (ThisNetworkInterface
->NetworkProtocolType
== ProtocolTypeTcp6
) {
404 This function discover Redfish service through SMBIOS host interface.
406 @param[in] Instance EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
408 @retval EFI_SUCCESS Redfish service is discovered through SMBIOS Host interface.
409 @retval Others Fail to discover Redfish service throught SMBIOS host interface
413 DiscoverRedfishHostInterface (IN EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
*Instance
)
416 REDFISH_OVER_IP_PROTOCOL_DATA
*Data
;
417 REDFISH_INTERFACE_DATA
*DeviceDescriptor
;
418 CHAR8 UuidStr
[sizeof"00000000-0000-0000-0000-000000000000" + 1];
419 CHAR16 Ipv6Str
[sizeof"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" + 1];
420 CHAR8 RedfishServiceLocateStr
[sizeof"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" + 1];
422 UINTN MacCompareStstus
;
426 DeviceDescriptor
= NULL
;
428 if (mSmbios
== NULL
) {
429 Status
= gBS
->LocateProtocol(&gEfiSmbiosProtocolGuid
, NULL
, (VOID
**)&mSmbios
);
430 if (EFI_ERROR (Status
)) {
434 Status
= RedfishGetHostInterfaceProtocolData (mSmbios
, &DeviceDescriptor
, &Data
); // Search for SMBIOS type 42h
435 if (!EFI_ERROR (Status
) && Data
!= NULL
&& DeviceDescriptor
!= NULL
) {
437 // Chceck if we can reach out Redfish service using this network interface.
438 // Check with MAC address using Device Descroptor Data Device Type 04 and Type 05.
439 // Those two types of Redfish host interface device has MAC information.
441 if (DeviceDescriptor
->DeviceType
== REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE_V2
) {
442 MacCompareStstus
= CompareMem(&Instance
->NetworkInterface
->MacAddress
, &DeviceDescriptor
->DeviceDescriptor
.PciPcieDeviceV2
.MacAddress
, 6);
443 } else if (DeviceDescriptor
->DeviceType
== REDFISH_HOST_INTERFACE_DEVICE_TYPE_USB_V2
){
444 MacCompareStstus
= CompareMem(&Instance
->NetworkInterface
->MacAddress
, &DeviceDescriptor
->DeviceDescriptor
.UsbDeviceV2
.MacAddress
, 6);
446 return EFI_UNSUPPORTED
;
448 if (MacCompareStstus
!= 0) {
449 return EFI_UNSUPPORTED
;
452 if (Data
->RedfishServiceIpAddressFormat
== 1) {
453 IP4_COPY_ADDRESS ((VOID
*)&Instance
->TargetIpAddress
.v4
, (VOID
*)Data
->RedfishServiceIpAddress
);
455 IP6_COPY_ADDRESS ((VOID
*)&Instance
->TargetIpAddress
.v6
, (VOID
*)Data
->RedfishServiceIpAddress
);
458 if (Instance
->HostIntfValidation
) {
459 DEBUG ((DEBUG_ERROR
,"%a:Send UPnP unicast SSDP to validate this Redfish Host Interface is not supported.\n", __FUNCTION__
));
460 Status
= EFI_UNSUPPORTED
;
463 // Add this istance to list without detial information of Redfish
467 if (Data
->RedfishServiceIpPort
== 443) {
470 StrSize
= sizeof(UuidStr
);
471 AsciiSPrint(UuidStr
, StrSize
, "%g", &Data
->ServiceUuid
);
473 // Generate Redfish service location string.
475 if (Data
->RedfishServiceIpAddressFormat
== REDFISH_HOST_INTERFACE_HOST_IP_ADDRESS_FORMAT_IP6
) {
476 NetLibIp6ToStr((IPv6_ADDRESS
*)&Data
->RedfishServiceIpAddress
, Ipv6Str
, sizeof (Ipv6Str
));
477 if (Data
->RedfishServiceIpPort
== 0 || IsHttps
== TRUE
) {
478 AsciiSPrintUnicodeFormat (
479 RedfishServiceLocateStr
,
480 sizeof (RedfishServiceLocateStr
),
485 AsciiSPrintUnicodeFormat(
486 RedfishServiceLocateStr
,
487 sizeof (RedfishServiceLocateStr
),
490 Data
->RedfishServiceIpPort
494 if (Data
->RedfishServiceIpPort
== 0 || IsHttps
== TRUE
) {
496 RedfishServiceLocateStr
,
497 sizeof (RedfishServiceLocateStr
),
499 Data
->RedfishServiceIpAddress
[0],
500 Data
->RedfishServiceIpAddress
[1],
501 Data
->RedfishServiceIpAddress
[2],
502 Data
->RedfishServiceIpAddress
[3]
506 RedfishServiceLocateStr
,
507 sizeof (RedfishServiceLocateStr
),
509 Data
->RedfishServiceIpAddress
[0],
510 Data
->RedfishServiceIpAddress
[1],
511 Data
->RedfishServiceIpAddress
[2],
512 Data
->RedfishServiceIpAddress
[3],
513 Data
->RedfishServiceIpPort
517 Status
= AddAndSignalNewRedfishService (
520 RedfishServiceLocateStr
,
534 The function adds a new found Redfish service to internal list and
537 @param[in] Instance EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE.
538 @param[in] RedfishVersion Redfish version.
539 @param[in] RedfishLocation Redfish location.
540 @param[in] Uuid Service UUID string.
541 @param[in] Os OS string.
542 @param[in] OsVer OS version string.
543 @param[in] Product Product string.
544 @param[in] ProductVer Product verison string.
545 @param[in] UseHttps Redfish service requires secured connection.
546 @retval EFI_SUCCESS Redfish service is added to list successfully.
550 AddAndSignalNewRedfishService (
551 IN EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
*Instance
,
552 IN UINTN
*RedfishVersion OPTIONAL
,
553 IN CHAR8
*RedfishLocation OPTIONAL
,
554 IN CHAR8
*Uuid OPTIONAL
,
555 IN CHAR8
*Os OPTIONAL
,
556 IN CHAR8
*OsVer OPTIONAL
,
557 IN CHAR8
*Product OPTIONAL
,
558 IN CHAR8
*ProductVer OPTIONAL
,
564 BOOLEAN RestExOpened
;
565 BOOLEAN DeleteRestEx
;
567 EFI_REDFISH_DISCOVERED_INTERNAL_LIST
*DiscoveredList
;
568 EFI_REDFISH_DISCOVERED_INSTANCE
*DiscoveredInstance
;
570 EFI_REST_EX_PROTOCOL
*RestEx
;
571 EFI_REST_EX_HTTP_CONFIG_DATA
*RestExHttpConfigData
;
572 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*NetworkInterface
;
577 RestExOpened
= FALSE
;
578 DeleteRestEx
= FALSE
;
580 DEBUG ((DEBUG_INFO
,"%a:Add this instance to Redfish instance list.\n", __FUNCTION__
));
583 Char16Uuid
= (CHAR16
*)AllocateZeroPool(AsciiStrSize((const CHAR8
*)Uuid
) * sizeof(CHAR16
));
584 AsciiStrToUnicodeStrS ((const CHAR8
*)Uuid
, Char16Uuid
, AsciiStrSize((const CHAR8
*)Uuid
) * sizeof(CHAR16
));
586 DiscoveredList
= NULL
;
587 DiscoveredInstance
= NULL
;
588 RestExHttpConfigData
= NULL
;
590 NetworkInterface
= Instance
->NetworkInterface
;
591 if (!IsListEmpty (&mRedfishInstanceList
)) {
593 // Is this a duplicate redfish service.
595 DiscoveredList
= (EFI_REDFISH_DISCOVERED_INTERNAL_LIST
*)GetFirstNode (&mRedfishInstanceList
);
598 if (Char16Uuid
== NULL
|| DiscoveredList
->Instance
->Information
.Uuid
== NULL
) {
600 // Check if this Redfish instance already found using IP addrress.
602 if (!CheckIsIpVersion6(NetworkInterface
)) {
603 if (CompareMem ((VOID
*)&Instance
->TargetIpAddress
.v4
,
604 (VOID
*)&DiscoveredList
->Instance
->Information
.RedfishHostIpAddress
.v4
,
605 sizeof (EFI_IPv4_ADDRESS
)
608 DiscoveredInstance
= DiscoveredList
->Instance
;
609 if (DiscoveredList
->Instance
->Information
.Uuid
== NULL
&&
610 Char16Uuid
!= NULL
) {
612 DiscoveredInstance
= DiscoveredList
->Instance
;
613 DEBUG((DEBUG_INFO
,"*** This Redfish Service information refresh ***\n"));
618 if (CompareMem ((VOID
*)&Instance
->TargetIpAddress
.v6
,
619 (VOID
*)&DiscoveredList
->Instance
->Information
.RedfishHostIpAddress
.v6
,
620 sizeof (EFI_IPv6_ADDRESS
)
623 DiscoveredInstance
= DiscoveredList
->Instance
;
629 // Check if this Redfish instance already found using UUID.
631 if (StrCmp((const CHAR16
*)Char16Uuid
, (const CHAR16
*)DiscoveredList
->Instance
->Information
.Uuid
) == 0) {
632 DiscoveredInstance
= DiscoveredList
->Instance
;
636 if (IsNodeAtEnd (&mRedfishInstanceList
, &DiscoveredList
->NextInstance
)) {
640 DiscoveredList
= (EFI_REDFISH_DISCOVERED_INTERNAL_LIST
*)GetNextNode (&mRedfishInstanceList
, &DiscoveredList
->NextInstance
);
643 if (NewFound
|| InfoRefresh
) {
645 DiscoveredList
= (EFI_REDFISH_DISCOVERED_INTERNAL_LIST
*)AllocateZeroPool(sizeof(EFI_REDFISH_DISCOVERED_INTERNAL_LIST
));
646 if (DiscoveredList
== NULL
) {
647 return EFI_OUT_OF_RESOURCES
;
649 InitializeListHead (&DiscoveredList
->NextInstance
);
650 DiscoveredInstance
= (EFI_REDFISH_DISCOVERED_INSTANCE
*)AllocateZeroPool(sizeof(EFI_REDFISH_DISCOVERED_INSTANCE
));
651 if (DiscoveredInstance
== NULL
) {
652 FreePool ((VOID
*)DiscoveredList
);
653 return EFI_OUT_OF_RESOURCES
;
656 DEBUG ((DEBUG_INFO
,"*** Redfish Service Information ***\n"));
658 DiscoveredInstance
->Information
.UseHttps
= UseHttps
;
659 if (RedfishVersion
!= NULL
) {
660 DiscoveredInstance
->Information
.RedfishVersion
= *RedfishVersion
;
661 DEBUG ((DEBUG_INFO
,"Redfish service version: %d.\n", DiscoveredInstance
->Information
.RedfishVersion
));
663 if (RedfishLocation
!= NULL
) {
664 DiscoveredInstance
->Information
.Location
= (CHAR16
*)AllocatePool(AsciiStrSize((const CHAR8
*)RedfishLocation
) * sizeof(CHAR16
));
665 AsciiStrToUnicodeStrS ((const CHAR8
*)RedfishLocation
, DiscoveredInstance
->Information
.Location
, AsciiStrSize((const CHAR8
*)RedfishLocation
) * sizeof(CHAR16
));
666 DEBUG ((DEBUG_INFO
,"Redfish service location: %s.\n", DiscoveredInstance
->Information
.Location
));
669 DiscoveredInstance
->Information
.Uuid
= (CHAR16
*)AllocatePool(AsciiStrSize((const CHAR8
*)Uuid
) * sizeof(CHAR16
));
670 AsciiStrToUnicodeStrS ((const CHAR8
*)Uuid
, DiscoveredInstance
->Information
.Uuid
, AsciiStrSize((const CHAR8
*)Uuid
) * sizeof(CHAR16
));
671 DEBUG ((DEBUG_INFO
,"Service UUID: %s.\n", DiscoveredInstance
->Information
.Uuid
));
674 DiscoveredInstance
->Information
.Os
= (CHAR16
*)AllocatePool(AsciiStrSize((const CHAR8
*)Os
) * sizeof(CHAR16
));
675 AsciiStrToUnicodeStrS ((const CHAR8
*)Os
, DiscoveredInstance
->Information
.Os
, AsciiStrSize((const CHAR8
*)Os
) * sizeof(CHAR16
));
676 DEBUG ((DEBUG_INFO
,"Redfish service OS: %s, Version:%s.\n", DiscoveredInstance
->Information
.Os
, DiscoveredInstance
->Information
.OsVersion
));
679 DiscoveredInstance
->Information
.OsVersion
= (CHAR16
*)AllocatePool(AsciiStrSize((const CHAR8
*)OsVer
) * sizeof(CHAR16
));
680 AsciiStrToUnicodeStrS ((const CHAR8
*)OsVer
, DiscoveredInstance
->Information
.OsVersion
, AsciiStrSize((const CHAR8
*)OsVer
) * sizeof(CHAR16
));
682 if (Product
!= NULL
&& ProductVer
!= NULL
) {
683 DiscoveredInstance
->Information
.Product
= (CHAR16
*)AllocatePool(AsciiStrSize((const CHAR8
*)Product
) * sizeof(CHAR16
));
684 AsciiStrToUnicodeStrS ((const CHAR8
*)Product
, DiscoveredInstance
->Information
.Product
, AsciiStrSize((const CHAR8
*)Product
) * sizeof(CHAR16
));
685 DiscoveredInstance
->Information
.ProductVer
= (CHAR16
*)AllocatePool(AsciiStrSize((const CHAR8
*)ProductVer
) * sizeof(CHAR16
));
686 AsciiStrToUnicodeStrS ((const CHAR8
*)ProductVer
, DiscoveredInstance
->Information
.ProductVer
, AsciiStrSize((const CHAR8
*)ProductVer
) * sizeof(CHAR16
));
687 DEBUG ((DEBUG_INFO
,"Redfish service product: %s, Version:%s.\n", DiscoveredInstance
->Information
.Product
, DiscoveredInstance
->Information
.ProductVer
));
690 if (RedfishLocation
== NULL
) {
691 // This is the Redfish reported from SMBIOS 42h
692 // without validation.
694 IP4_COPY_ADDRESS((VOID
*)&DiscoveredInstance
->Information
.RedfishHostIpAddress
.v4
, (VOID
*)&Instance
->TargetIpAddress
.v4
);
697 DiscoveredList
->Instance
= DiscoveredInstance
;
698 InsertTailList(&mRedfishInstanceList
, &DiscoveredList
->NextInstance
);
700 DiscoveredInstance
->Status
= EFI_SUCCESS
;
702 if (DiscoveredList
!= NULL
) {
703 DEBUG((DEBUG_INFO
,"*** This Redfish Service was already found ***\n"));
704 if (DiscoveredInstance
->Information
.Uuid
!= NULL
) {
705 DEBUG((DEBUG_INFO
,"Service UUID: %s.\n", DiscoveredInstance
->Information
.Uuid
));
707 DEBUG((DEBUG_INFO
,"Service UUID: unknown.\n"));
711 if (Char16Uuid
!= NULL
) {
712 FreePool((VOID
*)Char16Uuid
);
715 Status
= EFI_SUCCESS
;
716 if (NewFound
|| InfoRefresh
) {
718 // Build up EFI_REDFISH_DISCOVERED_LIST in token.
720 Instance
->DiscoverToken
->DiscoverList
.NumberOfServiceFound
= 1;
721 Instance
->DiscoverToken
->DiscoverList
.RedfishInstances
= DiscoveredInstance
;
722 DiscoveredInstance
->Status
= EFI_SUCCESS
;
724 Status
= CreateRestExInstance (Instance
, Instance
->DiscoverToken
); // Create REST EX child.
725 if (EFI_ERROR (Status
)) {
726 DEBUG ((DEBUG_ERROR
, "%a:Can't create REST EX child instance.\n",__FUNCTION__
));
729 Status
= gBS
->OpenProtocol ( // Configure local host information.
730 Instance
->DiscoverToken
->DiscoverList
.RedfishInstances
->Information
.RedfishRestExHandle
,
731 &gEfiRestExProtocolGuid
,
733 Instance
->NetworkInterface
->OpenDriverAgentHandle
,
734 Instance
->NetworkInterface
->OpenDriverControllerHandle
,
735 EFI_OPEN_PROTOCOL_BY_DRIVER
737 if (EFI_ERROR (Status
)) {
742 RestExHttpConfigData
= AllocateZeroPool (sizeof (EFI_REST_EX_HTTP_CONFIG_DATA
));
743 if (RestExHttpConfigData
== NULL
) {
744 Status
= EFI_OUT_OF_RESOURCES
;
746 goto EXIT_FREE_CONFIG_DATA
;
748 RestExHttpConfigData
->SendReceiveTimeout
= 5000;
749 RestExHttpConfigData
->HttpConfigData
.HttpVersion
= HttpVersion11
;
750 RestExHttpConfigData
->HttpConfigData
.LocalAddressIsIPv6
= CheckIsIpVersion6(NetworkInterface
);
751 if (RestExHttpConfigData
->HttpConfigData
.LocalAddressIsIPv6
) {
752 RestExHttpConfigData
->HttpConfigData
.AccessPoint
.IPv6Node
= AllocateZeroPool (sizeof (EFI_HTTPv6_ACCESS_POINT
));
753 if (RestExHttpConfigData
->HttpConfigData
.AccessPoint
.IPv6Node
== NULL
) {
754 Status
= EFI_OUT_OF_RESOURCES
;
755 goto EXIT_FREE_CONFIG_DATA
;
758 RestExHttpConfigData
->HttpConfigData
.AccessPoint
.IPv4Node
= AllocateZeroPool (sizeof (EFI_HTTPv4_ACCESS_POINT
));
759 if (RestExHttpConfigData
->HttpConfigData
.AccessPoint
.IPv4Node
== NULL
) {
760 Status
= EFI_OUT_OF_RESOURCES
;
761 goto EXIT_FREE_CONFIG_DATA
;
763 RestExHttpConfigData
->HttpConfigData
.AccessPoint
.IPv4Node
->UseDefaultAddress
= TRUE
;
765 Status
= RestEx
->Configure (
767 (EFI_REST_EX_CONFIG_DATA
)(UINT8
*)RestExHttpConfigData
769 if (EFI_ERROR (Status
)) {
770 DEBUG ((DEBUG_ERROR
,"%a:REST EX configured..\n", __FUNCTION__
));
775 // Signal client, close REST EX before signaling client.
779 Instance
->DiscoverToken
->DiscoverList
.RedfishInstances
->Information
.RedfishRestExHandle
,
780 &gEfiRestExProtocolGuid
,
781 Instance
->NetworkInterface
->OpenDriverAgentHandle
,
782 Instance
->NetworkInterface
->OpenDriverControllerHandle
784 RestExOpened
= FALSE
;
787 Status
= gBS
->SignalEvent(Instance
->DiscoverToken
->Event
);
788 if (!EFI_ERROR (Status
)) {
789 DEBUG ((DEBUG_ERROR
,"%a:No event to signal!\n", __FUNCTION__
));
794 if (RestExHttpConfigData
!= NULL
&& RestExHttpConfigData
->HttpConfigData
.AccessPoint
.IPv4Node
!= NULL
) {
795 FreePool (RestExHttpConfigData
->HttpConfigData
.AccessPoint
.IPv4Node
);
798 EXIT_FREE_CONFIG_DATA
:;
799 if (RestExHttpConfigData
!= NULL
) {
800 FreePool((VOID
*)RestExHttpConfigData
);
804 Instance
->DiscoverToken
->DiscoverList
.RedfishInstances
->Information
.RedfishRestExHandle
,
805 &gEfiRestExProtocolGuid
,
806 Instance
->NetworkInterface
->OpenDriverAgentHandle
,
807 Instance
->NetworkInterface
->OpenDriverControllerHandle
811 if (DeleteRestEx
&& RestExOpened
) {
813 Instance
->DiscoverToken
->DiscoverList
.RedfishInstances
->Information
.RedfishRestExHandle
,
814 &gEfiRestExProtocolGuid
,
815 Instance
->NetworkInterface
->OpenDriverAgentHandle
,
816 Instance
->NetworkInterface
->OpenDriverControllerHandle
824 This function gets the subnet information of this network interface instance.
825 can discover Redfish service on it.
827 @param[in] Instance EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL instance.
828 @param[in] ImageHandle EFI Image handle request the network interface list.
834 NetworkInterfaceGetSubnetInfo (
835 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*Instance
,
836 IN EFI_HANDLE ImageHandle
841 UINT32 IPv6InfoIndex
;
842 EFI_IP6_ADDRESS_INFO
*ThisSubnetAddrInfoIPv6
;
843 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*NewNetworkInterface
;
845 if (Instance
->GotSubnetInfo
) {
849 ProtocolType
= Instance
->NetworkProtocolType
;
850 if (gRequiredProtocol
[ProtocolType
].GetSubnetInfo
!= NULL
&& Instance
->GotSubnetInfo
== FALSE
) {
851 Status
= gRequiredProtocol
[ProtocolType
].GetSubnetInfo (
855 if (EFI_ERROR (Status
)) {
856 DEBUG ((DEBUG_ERROR
,"%a:Faile to get Subnet infomation.\n", __FUNCTION__
));
859 DEBUG ((DEBUG_INFO
,"%a:MAC address: %s\n", __FUNCTION__
, Instance
->StrMacAddr
));
860 if (CheckIsIpVersion6 (Instance
)) {
861 if (Instance
->SubnetAddrInfoIPv6Number
== 0) {
862 DEBUG ((DEBUG_ERROR
,"%a: There is no Subnet infomation for IPv6 network interface.\n", __FUNCTION__
));
863 return EFI_NOT_FOUND
;
865 ThisSubnetAddrInfoIPv6
= Instance
->SubnetAddrInfoIPv6
; // First IPv6 address information.
866 IP6_COPY_ADDRESS (&Instance
->SubnetAddr
.v6
, &ThisSubnetAddrInfoIPv6
->Address
);
867 Instance
->SubnetPrefixLength
= ThisSubnetAddrInfoIPv6
->PrefixLength
;
868 DEBUG((DEBUG_INFO
," IPv6 Subnet ID:%d, Prefix length: %d.\n",
869 ThisSubnetAddrInfoIPv6
->Address
.Addr
[7] + (UINT16
)ThisSubnetAddrInfoIPv6
->Address
.Addr
[6] * 256,
870 ThisSubnetAddrInfoIPv6
->PrefixLength
)
873 // If this is IPv6, then we may have to propagate network interface for IPv6 network scopes
874 // according to the Ipv6 address information.
876 ThisSubnetAddrInfoIPv6
++;
877 for (IPv6InfoIndex
= 0; IPv6InfoIndex
< Instance
->SubnetAddrInfoIPv6Number
- 1; IPv6InfoIndex
++) {
879 // Build up addtional EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL instances.
881 NewNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
));
882 if (NewNetworkInterface
!= NULL
) {
883 CopyMem ((VOID
*)NewNetworkInterface
, (VOID
*)Instance
, sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
)); // Clone information of first instance.
884 IP6_COPY_ADDRESS (&NewNetworkInterface
->SubnetAddr
.v6
, &ThisSubnetAddrInfoIPv6
->Address
);
885 NewNetworkInterface
->SubnetPrefixLength
= ThisSubnetAddrInfoIPv6
->PrefixLength
;
886 NewNetworkInterface
->GotSubnetInfo
= TRUE
;
887 InsertTailList (&mEfiRedfishDiscoverNetworkInterface
, &NewNetworkInterface
->Entry
);
888 ThisSubnetAddrInfoIPv6
++;
889 mNumNetworkInterface
++;
890 DEBUG((DEBUG_INFO
," IPv6 Subnet ID:%d, Prefix length: %d.\n",
891 ThisSubnetAddrInfoIPv6
->Address
.Addr
[7] + (UINT16
)ThisSubnetAddrInfoIPv6
->Address
.Addr
[6] * 256,
892 ThisSubnetAddrInfoIPv6
->PrefixLength
)
895 return EFI_OUT_OF_RESOURCES
;
899 DEBUG ((DEBUG_INFO
," IPv4 Subnet:%d.%d.%d.%d Subnet mask: %d.%d.%d.%d.\n",
900 Instance
->SubnetAddr
.v4
.Addr
[0],
901 Instance
->SubnetAddr
.v4
.Addr
[1],
902 Instance
->SubnetAddr
.v4
.Addr
[2],
903 Instance
->SubnetAddr
.v4
.Addr
[3],
904 Instance
->SubnetMask
.v4
.Addr
[0],
905 Instance
->SubnetMask
.v4
.Addr
[1],
906 Instance
->SubnetMask
.v4
.Addr
[2],
907 Instance
->SubnetMask
.v4
.Addr
[3]
912 Instance
->GotSubnetInfo
= TRUE
; // Only try to get Subnet Info once.
917 This function gets the network interface list which Redfish discover protocol
918 can discover Redfish service on it.
920 @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instance.
921 @param[in] ImageHandle EFI Image handle request the network interface list,
922 @param[out] NumberOfNetworkIntfs Number of network interfaces can do Redfish service discovery.
923 @param[out] NetworkIntfInstances Network interface instances. It's an array of instance. The number of entries
924 in array is indicated by NumberOfNetworkIntfs.
925 Caller has to release the memory
926 allocated by Redfish discover protocol.
928 @retval EFI_SUCCESS The information of network interface is returned in NumberOfNetworkIntfs and
929 NetworkIntfInstances.
930 @retval Others Fail to return the information of network interface.
935 RedfishServiceGetNetworkInterface (
936 IN EFI_REDFISH_DISCOVER_PROTOCOL
*This
,
937 IN EFI_HANDLE ImageHandle
,
938 OUT UINTN
*NumberOfNetworkIntfs
,
939 OUT EFI_REDFISH_DISCOVER_NETWORK_INTERFACE
**NetworkIntfInstances
942 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*ThisNetworkInterfaceIntn
;
943 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE
*ThisNetworkInterface
;
945 if (NetworkIntfInstances
== NULL
|| NumberOfNetworkIntfs
== NULL
|| ImageHandle
== NULL
) {
946 return EFI_INVALID_PARAMETER
;
949 *NumberOfNetworkIntfs
= 0;
950 *NetworkIntfInstances
= NULL
;
952 if (IsListEmpty ((const LIST_ENTRY
*)&mEfiRedfishDiscoverNetworkInterface
)) {
953 return EFI_NOT_FOUND
;
956 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE
*)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE
) * mNumNetworkInterface
);
957 if (ThisNetworkInterface
== NULL
) {
958 return EFI_OUT_OF_RESOURCES
;
960 *NetworkIntfInstances
= ThisNetworkInterface
;
961 ThisNetworkInterfaceIntn
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface
);
963 ThisNetworkInterface
->IsIpv6
= FALSE
;
964 if (CheckIsIpVersion6 (ThisNetworkInterfaceIntn
)) {
965 ThisNetworkInterface
->IsIpv6
= TRUE
;
967 CopyMem((VOID
*)&ThisNetworkInterface
->MacAddress
, &ThisNetworkInterfaceIntn
->MacAddress
, ThisNetworkInterfaceIntn
->HwAddressSize
);
968 NetworkInterfaceGetSubnetInfo(ThisNetworkInterfaceIntn
, ImageHandle
); // Get subnet info.
969 if (!ThisNetworkInterface
->IsIpv6
) {
970 IP4_COPY_ADDRESS(&ThisNetworkInterface
->SubnetId
.v4
, &ThisNetworkInterfaceIntn
->SubnetAddr
.v4
); // IPv4 subnet information.
972 IP6_COPY_ADDRESS (&ThisNetworkInterface
->SubnetId
.v6
, &ThisNetworkInterfaceIntn
->SubnetAddr
.v6
); // IPv6 subnet information in IPv6 address information.
974 ThisNetworkInterface
->SubnetPrefixLength
= ThisNetworkInterfaceIntn
->SubnetPrefixLength
;
975 ThisNetworkInterface
->VlanId
= ThisNetworkInterfaceIntn
->VlanId
;
976 (*NumberOfNetworkIntfs
) ++;
977 if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterfaceIntn
->Entry
)) {
980 ThisNetworkInterfaceIntn
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetNextNode(&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterfaceIntn
->Entry
);
981 ThisNetworkInterface
++;
986 This function acquires Redfish services by discovering static Redfish setting
987 according to Redfish Host Interface or through SSDP. Returns a list of EFI
988 handles in EFI_REDFISH_DISCOVERED_LIST. Each of EFI handle has cooresponding
989 EFI REST EX instance installed on it. Each REST EX isntance is a child instance which
990 created through EFI REST EX serivce protoocl for communicating with specific
993 @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instance.
994 @param[in] ImageHandle EFI image owns these Redfish service instances.
995 @param[in] TargetNetworkInterface Target network interface to do the discovery.
996 NULL means discover Redfish service on all network interfaces on platform.
997 @param[in] Flags Redfish service discover flags.
998 @param[in] Token EFI_REDFISH_DISCOVERED_TOKEN instance.
999 The memory of EFI_REDFISH_DISCOVERED_LIST and the strings in
1000 EFI_REDFISH_DISCOVERED_INFORMATION are all allocated by Acquire()
1001 and must be freed when caller invoke Release().
1003 @retval EFI_SUCCESS REST EX instance of discovered Redfish services are returned.
1004 @retval EFI_INVALID_PARAMETERS ImageHandle == NULL, Flags == 0, Token == NULL, Token->Timeout > 5,
1005 or Token->Event == NULL.
1006 @retval Others Fail acquire Redfish services.
1011 RedfishServiceAcquireService (
1012 IN EFI_REDFISH_DISCOVER_PROTOCOL
*This
,
1013 IN EFI_HANDLE ImageHandle
,
1014 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE
*TargetNetworkInterface
,
1015 IN EFI_REDFISH_DISCOVER_FLAG Flags
,
1016 IN EFI_REDFISH_DISCOVERED_TOKEN
*Token
1019 EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
*Instance
;
1022 BOOLEAN NewInstance
;
1023 UINTN NumNetworkInterfaces
;
1024 UINTN NetworkInterfacesIndex
;
1025 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*TargetNetworkInterfaceInternal
;
1027 DEBUG ((DEBUG_INFO
,"%a:Entry.\n", __FUNCTION__
));
1030 // Validate parameters.
1032 if (ImageHandle
== NULL
|| Token
== NULL
|| ((Flags
& ~EFI_REDFISH_DISCOVER_VALIDATION
) == 0)) {
1033 DEBUG ((DEBUG_ERROR
,"%a:Invalid parameters.\n", __FUNCTION__
));
1034 return EFI_INVALID_PARAMETER
;
1037 // Validate target network interface.
1039 if (EFI_ERROR (ValidateTargetNetworkInterface (TargetNetworkInterface
, Flags
))) {
1040 return EFI_UNSUPPORTED
;
1042 if (TargetNetworkInterface
!= NULL
) {
1043 TargetNetworkInterfaceInternal
= GetTargetNetworkInterfaceInternal (TargetNetworkInterface
);
1044 NumNetworkInterfaces
= 1;
1046 TargetNetworkInterfaceInternal
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface
);
1047 NumNetworkInterfaces
= NumberOfNetworkInterface ();
1048 if (NumNetworkInterfaces
== 0) {
1049 DEBUG ((DEBUG_ERROR
,"%a:No network interface on platform.\n", __FUNCTION__
));
1050 return EFI_UNSUPPORTED
;
1053 for (NetworkInterfacesIndex
= 0; NetworkInterfacesIndex
< NumNetworkInterfaces
; NetworkInterfacesIndex
++) {
1054 Status1
= EFI_SUCCESS
;
1055 Status2
= EFI_SUCCESS
;
1056 NewInstance
= FALSE
;
1057 Instance
= GetInstanceByOwner (ImageHandle
, TargetNetworkInterfaceInternal
, Flags
& ~EFI_REDFISH_DISCOVER_VALIDATION
); // Check if we can re-use previous instance.
1058 if (Instance
== NULL
) {
1059 DEBUG ((DEBUG_INFO
,"%a:Create new EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE.\n", __FUNCTION__
));
1060 Instance
= (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
*)AllocateZeroPool(sizeof(EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
));
1061 if (Instance
== NULL
) {
1062 DEBUG ((DEBUG_ERROR
,"%a:Memory allocation fail.\n", __FUNCTION__
));
1064 InitializeListHead (&Instance
->Entry
);
1065 Instance
->Owner
= ImageHandle
;
1066 Instance
->DiscoverFlags
= Flags
& ~EFI_REDFISH_DISCOVER_VALIDATION
;
1067 Instance
->NetworkInterface
= TargetNetworkInterfaceInternal
;
1069 // Get subnet information in case subnet information is not set because
1070 // RedfishServiceGetNetworkInterfaces hasn't been called yet.
1072 NetworkInterfaceGetSubnetInfo (TargetNetworkInterfaceInternal
, ImageHandle
);
1075 if (TargetNetworkInterfaceInternal
->StrMacAddr
!= NULL
) {
1076 DEBUG((DEBUG_INFO
,"%a:Acquire Redfish service on network interface MAC address:%s.\n", __FUNCTION__
, TargetNetworkInterfaceInternal
->StrMacAddr
));
1078 DEBUG((DEBUG_INFO
,"%a:WARNING: No MAC address on this network interface.\n", __FUNCTION__
));
1081 Instance
->DiscoverToken
= Token
; // Always use the latest Token passed by caller.
1082 if ((Flags
& EFI_REDFISH_DISCOVER_HOST_INTERFACE
) != 0) {
1083 DEBUG ((DEBUG_INFO
,"%a:Redfish HOST interface discovery.\n", __FUNCTION__
));
1084 Instance
->HostIntfValidation
= FALSE
;
1085 if ((Flags
& EFI_REDFISH_DISCOVER_VALIDATION
) != 0) {
1086 Instance
->HostIntfValidation
= TRUE
;
1088 Status1
= DiscoverRedfishHostInterface (Instance
); // Discover Redfish service through Redfish Host Interface.
1090 if ((Flags
& EFI_REDFISH_DISCOVER_SSDP
) != 0) {
1091 DEBUG ((DEBUG_ERROR
,"%a:Redfish service discovery through SSDP is not supported\n", __FUNCTION__
));
1092 return EFI_UNSUPPORTED
;
1094 if (EFI_ERROR (Status1
) && EFI_ERROR (Status2
)) {
1095 FreePool ((VOID
*)Instance
);
1096 DEBUG ((DEBUG_ERROR
,"%a:Something wrong on Redfish service discovery Status1=%x, Status2=%x.\n", __FUNCTION__
, Status1
, Status2
));
1099 InsertTailList(&mRedfishDiscoverList
, &Instance
->Entry
);
1103 if (TargetNetworkInterface
== NULL
) {
1105 // Discover Redfish services on all of network interfaces.
1107 TargetNetworkInterfaceInternal
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetNextNode(&mEfiRedfishDiscoverNetworkInterface
, &TargetNetworkInterfaceInternal
->Entry
);
1114 This function aborts Redfish service discovery on the given network interface.
1116 @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instance.
1117 @param[in] TargetNetworkInterface Target network interface to do the discovery.
1119 @retval EFI_SUCCESS REST EX instance of discovered Redfish services are returned.
1120 @retval Others Fail to abort Redfish service discovery.
1125 RedfishServiceAbortAcquire (
1126 IN EFI_REDFISH_DISCOVER_PROTOCOL
*This
,
1127 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE
*TargetNetworkInterface OPTIONAL
1130 // This function is used to abort Redfish service discovery through SSDP
1131 // on the network interface. SSDP is optionally supprted by EFI_REDFISH_DISCOVER_PROTOCOL,
1132 // we dont have implementation for SSDP now.
1134 return EFI_UNSUPPORTED
;
1138 This function releases Redfish services found by RedfishServiceAcquire().
1140 @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instance.
1141 @param[in] InstanceList The Redfish service to release.
1143 @retval EFI_SUCCESS REST EX instances of discovered Redfish are released.
1144 @retval Others Fail to remove the entry
1149 RedfishServiceReleaseService (
1150 IN EFI_REDFISH_DISCOVER_PROTOCOL
*This
,
1151 IN EFI_REDFISH_DISCOVERED_LIST
*InstanceList
1155 BOOLEAN AnyFailRelease
;
1156 EFI_REDFISH_DISCOVERED_INSTANCE
*ThisRedfishInstance
;
1157 EFI_REDFISH_DISCOVERED_INTERNAL_LIST
*DiscoveredRedfishInstance
;
1159 if (IsListEmpty (&mRedfishInstanceList
)) {
1160 DEBUG ((DEBUG_ERROR
,"%a:No any discovered Redfish service.\n", __FUNCTION__
));
1161 return EFI_NOT_FOUND
;
1163 AnyFailRelease
= FALSE
;
1164 ThisRedfishInstance
= InstanceList
->RedfishInstances
;
1165 for (NumService
= 0; NumService
< InstanceList
->NumberOfServiceFound
; NumService
++) {
1166 DiscoveredRedfishInstance
= (EFI_REDFISH_DISCOVERED_INTERNAL_LIST
*)GetFirstNode(&mRedfishInstanceList
);
1168 if (DiscoveredRedfishInstance
->Instance
== ThisRedfishInstance
) {
1169 RemoveEntryList (&DiscoveredRedfishInstance
->NextInstance
);
1170 if (ThisRedfishInstance
->Information
.Location
!= NULL
) {
1171 FreePool (ThisRedfishInstance
->Information
.Location
);
1173 if (ThisRedfishInstance
->Information
.Uuid
!= NULL
) {
1174 FreePool (ThisRedfishInstance
->Information
.Uuid
);
1176 if (ThisRedfishInstance
->Information
.Os
!= NULL
) {
1177 FreePool (ThisRedfishInstance
->Information
.Os
);
1179 if (ThisRedfishInstance
->Information
.OsVersion
!= NULL
) {
1180 FreePool (ThisRedfishInstance
->Information
.OsVersion
);
1182 if (ThisRedfishInstance
->Information
.Product
!= NULL
) {
1183 FreePool (ThisRedfishInstance
->Information
.Product
);
1185 if (ThisRedfishInstance
->Information
.ProductVer
!= NULL
) {
1186 FreePool (ThisRedfishInstance
->Information
.ProductVer
);
1188 FreePool((VOID
*)ThisRedfishInstance
);
1192 if (IsNodeAtEnd(&mRedfishInstanceList
, &DiscoveredRedfishInstance
->NextInstance
)) {
1195 DiscoveredRedfishInstance
= (EFI_REDFISH_DISCOVERED_INTERNAL_LIST
*)GetNextNode(&mRedfishInstanceList
, &DiscoveredRedfishInstance
->NextInstance
);
1197 AnyFailRelease
= TRUE
;
1200 // Release next discovered Redfish Service.
1202 ThisRedfishInstance
= (EFI_REDFISH_DISCOVERED_INSTANCE
*)((UINT8
*)ThisRedfishInstance
+ sizeof (EFI_REDFISH_DISCOVERED_INSTANCE
));
1204 if (AnyFailRelease
) {
1205 return EFI_NOT_FOUND
;
1211 EFI_REDFISH_DISCOVER_PROTOCOL mRedfishDiscover
= {
1212 RedfishServiceGetNetworkInterface
,
1213 RedfishServiceAcquireService
,
1214 RedfishServiceAbortAcquire
,
1215 RedfishServiceReleaseService
1219 This function create an EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL for the
1220 given network interface.
1223 @param[in] ControllerHandle MAC address of this network interface.
1224 @param[in] NetworkProtocolType Network protocol type.
1225 @param[out] IsNewInstance BOOLEAN means new instance or not.
1226 @param[out] NetworkInterface Pointer to to EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL.
1231 CreateRedfishDiscoverNetworkInterface (
1232 IN EFI_HANDLE ControllerHandle
,
1233 IN UINT32 NetworkProtocolType
,
1234 OUT BOOLEAN
*IsNewInstance
,
1235 OUT EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
**NetworkInterface
1238 EFI_MAC_ADDRESS MacAddress
;
1239 UINTN HwAddressSize
;
1240 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*ThisNetworkInterface
;
1241 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*NewNetworkInterface
;
1243 NetLibGetMacAddress (ControllerHandle
, &MacAddress
, &HwAddressSize
);
1244 NewNetworkInterface
= NULL
;
1245 *IsNewInstance
= TRUE
;
1246 if (!IsListEmpty ((const LIST_ENTRY
*)&mEfiRedfishDiscoverNetworkInterface
)) {
1248 // Check if this instance already exist.
1250 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface
);
1251 if (ThisNetworkInterface
!= NULL
) {
1253 if ((CompareMem ((CONST VOID
*)&ThisNetworkInterface
->MacAddress
.Addr
, (CONST VOID
*)&MacAddress
.Addr
, HwAddressSize
) == 0) &&
1254 (ThisNetworkInterface
->NetworkProtocolType
== NetworkProtocolType
)){
1255 NewNetworkInterface
= ThisNetworkInterface
;
1256 *IsNewInstance
= FALSE
;
1259 if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterface
->Entry
)) {
1260 NewNetworkInterface
= NULL
;
1263 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetNextNode(&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterface
->Entry
);
1267 if (NewNetworkInterface
== NULL
) {
1269 // Create a new instance.
1271 NewNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
));
1272 if (NewNetworkInterface
== NULL
) {
1273 return EFI_OUT_OF_RESOURCES
;
1275 NewNetworkInterface
->HwAddressSize
= HwAddressSize
;
1276 CopyMem (&NewNetworkInterface
->MacAddress
.Addr
, &MacAddress
.Addr
, NewNetworkInterface
->HwAddressSize
);
1277 NetLibGetMacString (ControllerHandle
, NULL
, &NewNetworkInterface
->StrMacAddr
);
1278 NewNetworkInterface
->VlanId
= NetLibGetVlanId (ControllerHandle
);
1280 *NetworkInterface
= NewNetworkInterface
;
1285 This function destory network interface
1288 @param[in] ThisNetworkInterface EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL instance.
1293 DestroyRedfishNetwrokInterface (
1294 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*ThisNetworkInterface
1299 Status
= gBS
->UninstallProtocolInterface(
1300 ThisNetworkInterface
->OpenDriverControllerHandle
,
1301 gRequiredProtocol
[ThisNetworkInterface
->NetworkProtocolType
].DiscoveredProtocolGuid
,
1302 &ThisNetworkInterface
->NetworkInterfaceProtocolInfo
.ProtocolDiscoverId
1304 RemoveEntryList (&ThisNetworkInterface
->Entry
);
1305 mNumNetworkInterface
--;
1306 FreePool (ThisNetworkInterface
);
1311 Tests to see if the required protocols are provided on the given
1314 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1315 @param[in] ControllerHandle The handle of the controller to test. This handle
1316 must support a protocol interface that supplies
1317 an I/O abstraction to the driver.
1318 @retval EFI_SUCCESS One of required protocol is found.
1319 @retval EFI_UNSUPPORTED None of required protocol is found.
1322 TestForRequiredProtocols (
1323 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1324 IN EFI_HANDLE ControllerHandle
1331 for (Index
= 0; Index
< (sizeof (gRequiredProtocol
) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL
)); Index
++) {
1332 Status
= gBS
->OpenProtocol (
1334 gRequiredProtocol
[Index
].RequiredServiceBindingProtocolGuid
,
1336 This
->DriverBindingHandle
,
1338 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
1340 if (!EFI_ERROR (Status
)) {
1341 Status
= gBS
->OpenProtocol (
1343 gRequiredProtocol
[Index
].DiscoveredProtocolGuid
,
1345 This
->DriverBindingHandle
,
1347 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1349 if (EFI_ERROR (Status
)) {
1350 DEBUG((DEBUG_ERROR
, "%a: %s is found on this controller handle.\n", __FUNCTION__
, gRequiredProtocol
[Index
].ProtocolName
));
1355 return EFI_UNSUPPORTED
;
1359 Build up network interface and create corresponding service through the given
1362 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1363 @param[in] ControllerHandle The handle of the controller to test. This handle
1364 must support a protocol interface that supplies
1365 an I/O abstraction to the driver.
1366 @retval EFI_SUCCESS One of required protocol is found.
1367 @retval EFI_UNSUPPORTED None of required protocol is found.
1368 @retval EFI_UNSUPPORTED Failed to build up network interface.
1371 BuildupNetworkInterface (
1372 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1373 IN EFI_HANDLE ControllerHandle
1378 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*NetworkInterface
;
1381 VOID
*TempInterface
;
1383 UINT32
*ProtocolDiscoverIdPtr
;
1384 EFI_HANDLE OpenDriverAgentHandle
;
1385 EFI_HANDLE OpenDriverControllerHandle
;
1386 EFI_HANDLE
*HandleOfProtocolInterfacePtr
;
1387 EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL
*RestExInstance
;
1389 BOOLEAN NewNetworkInterfaceInstalled
;
1391 NewNetworkInterfaceInstalled
= FALSE
;
1394 Status
= gBS
->OpenProtocol ( // Already in list?
1396 gRequiredProtocol
[Index
].DiscoveredProtocolGuid
,
1398 This
->DriverBindingHandle
,
1400 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1402 if (!EFI_ERROR (Status
)) {
1404 if (Index
== (sizeof(gRequiredProtocol
) / sizeof(REDFISH_DISCOVER_REQUIRED_PROTOCOL
))) {
1410 Status
= gBS
->OpenProtocol (
1412 gRequiredProtocol
[Index
].RequiredServiceBindingProtocolGuid
,
1414 This
->DriverBindingHandle
,
1416 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1418 if (EFI_ERROR (Status
)) {
1420 if (Index
== (sizeof(gRequiredProtocol
) / sizeof(REDFISH_DISCOVER_REQUIRED_PROTOCOL
))) {
1425 if (gRequiredProtocol
[Index
].ProtocolType
!= ProtocolTypeRestEx
) {
1426 OldTpl
= gBS
->RaiseTPL (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL
);
1427 Status
= CreateRedfishDiscoverNetworkInterface(ControllerHandle
, gRequiredProtocol
[Index
].ProtocolType
, &IsNew
, &NetworkInterface
);
1428 if (EFI_ERROR (Status
)) {
1429 gBS
->RestoreTPL (OldTpl
);
1432 NetworkInterface
->NetworkProtocolType
= gRequiredProtocol
[Index
].ProtocolType
;
1433 NetworkInterface
->OpenDriverAgentHandle
= This
->DriverBindingHandle
;
1434 NetworkInterface
->OpenDriverControllerHandle
= ControllerHandle
;
1435 NetworkInterface
->NetworkInterfaceProtocolInfo
.ProtocolGuid
= \
1436 *gRequiredProtocol
[Index
].RequiredProtocolGuid
;
1437 NetworkInterface
->NetworkInterfaceProtocolInfo
.ProtocolServiceGuid
= \
1438 *gRequiredProtocol
[Index
].RequiredServiceBindingProtocolGuid
;
1439 ProtocolDiscoverIdPtr
= &NetworkInterface
->NetworkInterfaceProtocolInfo
.ProtocolDiscoverId
;
1440 OpenDriverAgentHandle
= NetworkInterface
->OpenDriverAgentHandle
;
1441 OpenDriverControllerHandle
= NetworkInterface
->OpenDriverControllerHandle
;
1442 HandleOfProtocolInterfacePtr
= &NetworkInterface
->NetworkInterfaceProtocolInfo
.ProtocolControllerHandle
;
1443 Interface
= &NetworkInterface
->NetworkInterfaceProtocolInfo
.NetworkProtocolInterface
;
1444 NewNetworkInterfaceInstalled
= TRUE
;
1446 InsertTailList (&mEfiRedfishDiscoverNetworkInterface
, &NetworkInterface
->Entry
);
1447 mNumNetworkInterface
++;
1449 gBS
->RestoreTPL (OldTpl
);
1451 // Record REST_EX instance. REST_EX is created when clinet asks for Redfish service discovery.
1452 // Redfish Service Discover protocol will match REST EX to the corresponding EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
1455 RestExInstance
= (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL
*)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL
));
1456 if (RestExInstance
== NULL
) {
1457 return EFI_OUT_OF_RESOURCES
;
1459 RestExInstance
->OpenDriverAgentHandle
= This
->DriverBindingHandle
;
1460 RestExInstance
->OpenDriverControllerHandle
= ControllerHandle
;
1461 RestExInstance
->RestExControllerHandle
= ControllerHandle
;
1462 InitializeListHead (&RestExInstance
->Entry
);
1463 InsertTailList (&mEfiRedfishDiscoverRestExInstance
, &RestExInstance
->Entry
);
1464 mNumRestExInstance
++;
1465 ProtocolDiscoverIdPtr
= &RestExInstance
->RestExId
;
1466 OpenDriverAgentHandle
= RestExInstance
->OpenDriverAgentHandle
;
1467 OpenDriverControllerHandle
= RestExInstance
->OpenDriverControllerHandle
;
1468 HandleOfProtocolInterfacePtr
= &RestExInstance
->RestExChildHandle
;
1469 Interface
= (VOID
**)&RestExInstance
->RestExProtocolInterface
;
1471 Status
= gBS
->InstallProtocolInterface (
1473 gRequiredProtocol
[Index
].DiscoveredProtocolGuid
,
1474 EFI_NATIVE_INTERFACE
,
1475 ProtocolDiscoverIdPtr
1477 if (EFI_ERROR (Status
)) {
1479 if (Index
== (sizeof(gRequiredProtocol
) / sizeof(REDFISH_DISCOVER_REQUIRED_PROTOCOL
))) {
1485 // Create service binding child and open it BY_DRIVER.
1487 Status
= NetLibCreateServiceChild (
1490 gRequiredProtocol
[Index
].RequiredServiceBindingProtocolGuid
,
1491 HandleOfProtocolInterfacePtr
1493 if (!EFI_ERROR (Status
)) {
1494 Status
= gBS
->OpenProtocol (
1495 *HandleOfProtocolInterfacePtr
,
1496 gRequiredProtocol
[Index
].RequiredProtocolGuid
,
1498 OpenDriverAgentHandle
,
1499 OpenDriverControllerHandle
,
1500 EFI_OPEN_PROTOCOL_BY_DRIVER
1502 if (!EFI_ERROR (Status
)) {
1503 if (EfiRedfishDiscoverProtocolHandle
== NULL
&&
1504 (gRequiredProtocol
[Index
].ProtocolType
== ProtocolTypeRestEx
) &&
1505 !IsListEmpty (&mEfiRedfishDiscoverNetworkInterface
)
1507 // Install the fisrt Redfish Discover Protocol when EFI REST EX protcol is discovered.
1508 // This ensures EFI REST EX is ready while EFI_REDFISH_DISCOVER_PROTOCOL consumer acquires
1509 // Redfish serivce over network interface.
1511 Status
= gBS
->InstallProtocolInterface (
1512 &EfiRedfishDiscoverProtocolHandle
,
1513 &gEfiRedfishDiscoverProtocolGuid
,
1514 EFI_NATIVE_INTERFACE
,
1515 (VOID
*)&mRedfishDiscover
1517 } else if (EfiRedfishDiscoverProtocolHandle
!= NULL
&& NewNetworkInterfaceInstalled
) {
1518 Status
= gBS
->ReinstallProtocolInterface (
1519 EfiRedfishDiscoverProtocolHandle
,
1520 &gEfiRedfishDiscoverProtocolGuid
,
1521 (VOID
*)&mRedfishDiscover
,
1522 (VOID
*)&mRedfishDiscover
1524 NewNetworkInterfaceInstalled
= FALSE
;
1530 if (Index
== (sizeof(gRequiredProtocol
) / sizeof(REDFISH_DISCOVER_REQUIRED_PROTOCOL
))) {
1535 } while (Index
< (sizeof(gRequiredProtocol
) / sizeof(REDFISH_DISCOVER_REQUIRED_PROTOCOL
)));
1536 return EFI_UNSUPPORTED
;
1539 Close the protocol opened for Redfish discovery. This function also destories
1540 the network services.
1542 @param[in] ThisBindingProtocol A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1543 @param[in] ControllerHandle The handle of the controller to test. This handle
1544 must support a protocol interface that supplies
1545 an I/O abstraction to the driver.
1546 @param[in] ThisRequiredProtocol Pointer to the instance of REDFISH_DISCOVER_REQUIRED_PROTOCOL.
1547 @param[in] DriverAgentHandle Driver agent handle which used to open protocol earlier.
1548 @param[in] DriverControllerHandle Driver controller handle which used to open protocol earlier.
1550 @retval EFI_SUCCESS Prorocol is closed successfully.
1551 @retval Others Prorocol is closed unsuccessfully.
1555 CloseProtocolService (
1556 IN EFI_DRIVER_BINDING_PROTOCOL
*ThisBindingProtocol
,
1557 IN EFI_HANDLE ControllerHandle
,
1558 IN REDFISH_DISCOVER_REQUIRED_PROTOCOL
*ThisRequiredProtocol
,
1559 IN EFI_HANDLE DriverAgentHandle
,
1560 IN EFI_HANDLE DriverControllerHandle
1565 Status
= gBS
->CloseProtocol (
1567 ThisRequiredProtocol
->RequiredProtocolGuid
,
1569 DriverControllerHandle
1571 if (!EFI_ERROR (Status
)) {
1572 NetLibDestroyServiceChild(
1574 ThisBindingProtocol
->ImageHandle
,
1575 ThisRequiredProtocol
->RequiredServiceBindingProtocolGuid
,
1582 Stop the services on network interface.
1584 @param[in] ThisBindingProtocol A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1585 @param[in] ControllerHandle The handle of the controller to test. This handle
1586 must support a protocol interface that supplies
1587 an I/O abstraction to the driver.
1588 @retval EFI_SUCCESS One of required protocol is found.
1589 @retval Others Faile to stop the services on network interface.
1592 StopServiceOnNetworkInterface (
1593 IN EFI_DRIVER_BINDING_PROTOCOL
*ThisBindingProtocol
,
1594 IN EFI_HANDLE ControllerHandle
1601 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*ThisNetworkInterface
;
1602 EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL
*RestExInstance
;
1604 for (Index
= 0; Index
< (sizeof (gRequiredProtocol
) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL
)); Index
++) {
1605 Status
= gBS
->HandleProtocol (
1607 gRequiredProtocol
[Index
].RequiredProtocolGuid
,
1610 if (!EFI_ERROR (Status
)) {
1611 if (gRequiredProtocol
[Index
].ProtocolType
!= ProtocolTypeRestEx
) {
1612 if (IsListEmpty (&mEfiRedfishDiscoverNetworkInterface
)) {
1613 return EFI_NOT_FOUND
;
1615 OldTpl
= gBS
->RaiseTPL (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL
);
1616 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface
);
1618 if (ThisNetworkInterface
->NetworkInterfaceProtocolInfo
.ProtocolControllerHandle
== ControllerHandle
) {
1620 Status
= CloseProtocolService ( // Close protocol and destroy service.
1621 ThisBindingProtocol
,
1623 &gRequiredProtocol
[Index
],
1624 ThisNetworkInterface
->OpenDriverAgentHandle
,
1625 ThisNetworkInterface
->OpenDriverControllerHandle
1627 if (!EFI_ERROR (Status
)) {
1628 Status
= DestroyRedfishNetwrokInterface (ThisNetworkInterface
);
1630 gBS
->RestoreTPL (OldTpl
);
1631 // Reinstall Redfish Discover protocol to notify network
1632 // interface change.
1634 Status
= gBS
->ReinstallProtocolInterface (
1635 EfiRedfishDiscoverProtocolHandle
,
1636 &gEfiRedfishDiscoverProtocolGuid
,
1637 (VOID
*)&mRedfishDiscover
,
1638 (VOID
*)&mRedfishDiscover
1640 if (EFI_ERROR (Status
)) {
1641 DEBUG((DEBUG_ERROR
, "%a: Reinstall gEfiRedfishDiscoverProtocolGuid fail.", __FUNCTION__
));
1645 if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterface
->Entry
)) {
1648 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetNextNode(&mEfiRedfishDiscoverNetworkInterface
, &ThisNetworkInterface
->Entry
);
1650 gBS
->RestoreTPL (OldTpl
);
1652 if (IsListEmpty (&mEfiRedfishDiscoverRestExInstance
)) {
1653 return EFI_NOT_FOUND
;
1655 OldTpl
= gBS
->RaiseTPL (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL
);
1656 RestExInstance
= (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL
*)GetFirstNode (&mEfiRedfishDiscoverRestExInstance
);
1658 if (RestExInstance
->RestExChildHandle
== ControllerHandle
) {
1659 Status
= CloseProtocolService ( // Close REST_EX protocol.
1660 ThisBindingProtocol
,
1662 &gRequiredProtocol
[Index
],
1663 RestExInstance
->OpenDriverAgentHandle
,
1664 RestExInstance
->OpenDriverControllerHandle
1666 RemoveEntryList (&RestExInstance
->Entry
);
1667 FreePool ((VOID
*)RestExInstance
);
1668 mNumRestExInstance
--;
1669 gBS
->RestoreTPL (OldTpl
);
1672 if (IsNodeAtEnd (&mEfiRedfishDiscoverRestExInstance
, &RestExInstance
->Entry
)) {
1675 RestExInstance
= (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL
*)GetNextNode(&mEfiRedfishDiscoverRestExInstance
, &RestExInstance
->Entry
);
1677 gBS
->RestoreTPL (OldTpl
);
1681 return EFI_NOT_FOUND
;
1684 Tests to see if this driver supports a given controller. If a child device is provided,
1685 it further tests to see if this driver supports creating a handle for the specified child device.
1687 This function checks to see if the driver specified by This supports the device specified by
1688 ControllerHandle. Drivers will typically use the device path attached to
1689 ControllerHandle and/or the services from the bus I/O abstraction attached to
1690 ControllerHandle to determine if the driver supports ControllerHandle. This function
1691 may be called many times during platform initialization. In order to reduce boot times, the tests
1692 performed by this function must be very small, and take as little time as possible to execute. This
1693 function must not change the state of any hardware devices, and this function must be aware that the
1694 device specified by ControllerHandle may already be managed by the same driver or a
1695 different driver. This function must match its calls to AllocatePages() with FreePages(),
1696 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
1697 Because ControllerHandle may have been previously started by the same driver, if a protocol is
1698 already in the opened state, then it must not be closed with CloseProtocol(). This is required
1699 to guarantee the state of ControllerHandle is not modified by this function.
1701 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1702 @param[in] ControllerHandle The handle of the controller to test. This handle
1703 must support a protocol interface that supplies
1704 an I/O abstraction to the driver.
1705 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
1706 parameter is ignored by device drivers, and is optional for bus
1707 drivers. For bus drivers, if this parameter is not NULL, then
1708 the bus driver must determine if the bus controller specified
1709 by ControllerHandle and the child controller specified
1710 by RemainingDevicePath are both supported by this
1713 @retval EFI_SUCCESS The device specified by ControllerHandle and
1714 RemainingDevicePath is supported by the driver specified by This.
1715 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
1716 RemainingDevicePath is already being managed by the driver
1718 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
1719 RemainingDevicePath is already being managed by a different
1720 driver or an application that requires exclusive access.
1721 Currently not implemented.
1722 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
1723 RemainingDevicePath is not supported by the driver specified by This.
1727 RedfishDiscoverDriverBindingSupported (
1728 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1729 IN EFI_HANDLE ControllerHandle
,
1730 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1733 return TestForRequiredProtocols (This
, ControllerHandle
);
1737 Starts a device controller or a bus controller.
1739 The Start() function is designed to be invoked from the EFI boot service ConnectController().
1740 As a result, much of the error checking on the parameters to Start() has been moved into this
1741 common boot service. It is legal to call Start() from other locations,
1742 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
1743 1. ControllerHandle must be a valid EFI_HANDLE.
1744 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
1745 EFI_DEVICE_PATH_PROTOCOL.
1746 3. Prior to calling Start(), the Supported() function for the driver specified by This must
1747 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
1749 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1750 @param[in] ControllerHandle The handle of the controller to start. This handle
1751 must support a protocol interface that supplies
1752 an I/O abstraction to the driver.
1753 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
1754 parameter is ignored by device drivers, and is optional for bus
1755 drivers. For a bus driver, if this parameter is NULL, then handles
1756 for all the children of Controller are created by this driver.
1757 If this parameter is not NULL and the first Device Path Node is
1758 not the End of Device Path Node, then only the handle for the
1759 child device specified by the first Device Path Node of
1760 RemainingDevicePath is created by this driver.
1761 If the first Device Path Node of RemainingDevicePath is
1762 the End of Device Path Node, no child handle is created by this
1765 @retval EFI_SUCCESS The device was started.
1766 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
1767 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1768 @retval Others The driver failded to start the device.
1773 RedfishDiscoverDriverBindingStart (
1774 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1775 IN EFI_HANDLE ControllerHandle
,
1776 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1779 return BuildupNetworkInterface (This
, ControllerHandle
);
1783 Stops a device controller or a bus controller.
1785 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
1786 As a result, much of the error checking on the parameters to Stop() has been moved
1787 into this common boot service. It is legal to call Stop() from other locations,
1788 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
1789 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
1790 same driver's Start() function.
1791 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
1792 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
1793 Start() function, and the Start() function must have called OpenProtocol() on
1794 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
1796 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1797 @param[in] ControllerHandle A handle to the device being stopped. The handle must
1798 support a bus specific I/O protocol for the driver
1799 to use to stop the device.
1800 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
1801 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
1802 if NumberOfChildren is 0.
1804 @retval EFI_SUCCESS The device was stopped.
1805 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
1810 RedfishDiscoverDriverBindingStop (
1811 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1812 IN EFI_HANDLE ControllerHandle
,
1813 IN UINTN NumberOfChildren
,
1814 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
1817 return StopServiceOnNetworkInterface (This
, ControllerHandle
);
1820 EFI_DRIVER_BINDING_PROTOCOL gRedfishDiscoverDriverBinding
= {
1821 RedfishDiscoverDriverBindingSupported
,
1822 RedfishDiscoverDriverBindingStart
,
1823 RedfishDiscoverDriverBindingStop
,
1824 REDFISH_DISCOVER_VERSION
,
1830 This is the declaration of an EFI image entry point.
1832 @param ImageHandle The firmware allocated handle for the UEFI image.
1833 @param SystemTable A pointer to the EFI System Table.
1835 @retval EFI_SUCCESS The operation completed successfully.
1836 @retval Others An unexpected error occurred.
1840 RedfishDiscoverEntryPoint (
1841 IN EFI_HANDLE ImageHandle
,
1842 IN EFI_SYSTEM_TABLE
*SystemTable
1847 Status
= EFI_SUCCESS
;
1848 InitializeListHead (&mRedfishDiscoverList
);
1849 InitializeListHead (&mRedfishInstanceList
);
1850 InitializeListHead (&mEfiRedfishDiscoverNetworkInterface
);
1851 InitializeListHead (&mEfiRedfishDiscoverRestExInstance
);
1853 // Install binding protoocl to obtain UDP and REST EX protocol.
1855 Status
= EfiLibInstallDriverBindingComponentName2 (
1858 &gRedfishDiscoverDriverBinding
,
1860 &gRedfishDiscoverComponentName
,
1861 &gRedfishDiscoverComponentName2
1867 This is the unload handle for Redfish discover module.
1869 Disconnect the driver specified by ImageHandle from all the devices in the handle database.
1870 Uninstall all the protocols installed in the driver entry point.
1872 @param[in] ImageHandle The drivers' driver image.
1874 @retval EFI_SUCCESS The image is unloaded.
1875 @retval Others Failed to unload the image.
1880 RedfishDiscoverUnload (
1881 IN EFI_HANDLE ImageHandle
1885 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*ThisNetworkInterface
;
1887 Status
= EFI_SUCCESS
;
1888 // Destroy all network interfaces found by EFI Redfish Discover driver and
1889 // stop services created for Redfish Discover.
1891 while (!IsListEmpty (&mEfiRedfishDiscoverNetworkInterface
)) {
1892 ThisNetworkInterface
= (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
*)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface
);
1893 StopServiceOnNetworkInterface (&gRedfishDiscoverDriverBinding
, ThisNetworkInterface
->NetworkInterfaceProtocolInfo
.ProtocolControllerHandle
);
1895 // Disconnect EFI Redfish discover driver controller to notify the
1896 // clinet which uses .EFI Redfish discover protocol.
1898 if (EfiRedfishDiscoverProtocolHandle
!= NULL
) {
1900 // Notify user EFI_REDFISH_DISCOVER_PROTOCOL is unloaded.
1902 gBS
->DisconnectController (EfiRedfishDiscoverProtocolHandle
, NULL
, NULL
);
1903 Status
= gBS
->UninstallProtocolInterface(
1904 EfiRedfishDiscoverProtocolHandle
,
1905 &gEfiRedfishDiscoverProtocolGuid
,
1906 (VOID
*)&mRedfishDiscover