]> git.proxmox.com Git - mirror_edk2.git/blob - RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.c
bf50c78c9280da25c1c33c38660adc1b1dcc8f9a
[mirror_edk2.git] / RedfishPkg / RedfishDiscoverDxe / RedfishDiscoverDxe.c
1 /** @file
2
3 The implementation of EFI Redfidh Discover Protocol.
4
5 (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
6
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9 **/
10
11 #include "RedfishDiscoverInternal.h"
12
13 LIST_ENTRY mRedfishDiscoverList;
14 LIST_ENTRY mRedfishInstanceList;
15 EFI_SMBIOS_PROTOCOL *mSmbios = NULL;
16
17 UINTN mNumNetworkInterface = 0;
18 UINTN mNumRestExInstance = 0;
19 LIST_ENTRY mEfiRedfishDiscoverNetworkInterface;
20 LIST_ENTRY mEfiRedfishDiscoverRestExInstance;
21
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;
25
26 EFI_HANDLE EfiRedfishDiscoverProtocolHandle = NULL;
27
28 EFI_STATUS
29 EFIAPI
30 Tcp4GetSubnetInfo (
31 IN EFI_HANDLE ImageHandle,
32 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *Instance
33 );
34
35 EFI_STATUS
36 EFIAPI
37 Tcp6GetSubnetInfo (
38 IN EFI_HANDLE ImageHandle,
39 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *Instance
40 );
41
42 static REDFISH_DISCOVER_REQUIRED_PROTOCOL gRequiredProtocol[] = {
43 {
44 ProtocolTypeTcp4,
45 L"TCP4 Service Binding Protocol",
46 &gEfiTcp4ProtocolGuid,
47 &gEfiTcp4ServiceBindingProtocolGuid,
48 &mRedfishDiscoverTcp4InstanceGuid,
49 Tcp4GetSubnetInfo
50 },
51 {
52 ProtocolTypeTcp6,
53 L"TCP6 Service Binding Protocol",
54 &gEfiTcp6ProtocolGuid,
55 &gEfiTcp6ServiceBindingProtocolGuid,
56 &mRedfishDiscoverTcp6InstanceGuid,
57 Tcp6GetSubnetInfo
58 },
59 {
60 ProtocolTypeRestEx,
61 L"REST EX Service Binding Protocol",
62 &gEfiRestExProtocolGuid,
63 &gEfiRestExServiceBindingProtocolGuid,
64 &mRedfishDiscoverRestExInstanceGuid,
65 NULL
66 }
67 };
68
69 /**
70 This function creates REST EX instance for the found Resfish service.
71 by known owner handle.
72
73 @param[in] Instance EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
74 @param[in] Token Client token.
75
76 @retval NULL Instance not found.
77 @retval EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE The instance owned by this owner.
78
79 **/
80 EFI_STATUS
81 CreateRestExInstance (
82 IN EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *Instance,
83 IN EFI_REDFISH_DISCOVERED_TOKEN *Token
84 )
85 {
86 EFI_STATUS Status;
87
88 Status = RestExLibCreateChild (
89 Instance->Owner,
90 FixedPcdGetBool (PcdRedfishDiscoverAccessModeInBand) ? EfiRestExServiceInBandAccess : EfiRestExServiceOutOfBandAccess,
91 EfiRestExConfigHttp,
92 EfiRestExServiceRedfish,
93 &Token->DiscoverList.RedfishInstances->Information.RedfishRestExHandle
94 );
95 return Status;
96 }
97
98 /**
99 This function gets EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
100 by known owner handle.
101
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
105
106 @retval NULL Instance not found.
107 @retval EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE The instance owned by this owner.
108
109 **/
110 EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *
111 GetInstanceByOwner (
112 IN EFI_HANDLE ImageHandle,
113 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *TargetNetworkInterface,
114 IN EFI_REDFISH_DISCOVER_FLAG DiscoverFlags
115 )
116 {
117 EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *ThisInstance;
118
119 if (IsListEmpty (&mRedfishDiscoverList)) {
120 return NULL;
121 }
122
123 ThisInstance =
124 (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *)GetFirstNode (&mRedfishDiscoverList);
125 while (TRUE) {
126 if ((ThisInstance->Owner == ImageHandle) &&
127 (ThisInstance->DiscoverFlags == DiscoverFlags) &&
128 (ThisInstance->NetworkInterface == TargetNetworkInterface))
129 {
130 return ThisInstance;
131 }
132
133 if (IsNodeAtEnd (&mRedfishDiscoverList, &ThisInstance->Entry)) {
134 break;
135 }
136
137 ThisInstance =
138 (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *)GetNextNode (&mRedfishDiscoverList, &ThisInstance->Entry);
139 }
140
141 return NULL;
142 }
143
144 /**
145 This function gets the subnet information of this TCP4 instance.
146
147 @param[in] ImageHandle EFI handle with this image.
148 @param[in] Instance Instance of Network interface.
149 @retval EFI_STATUS Get subnet information successfully.
150 @retval Otherwise Fail to get subnet information.
151 **/
152 EFI_STATUS
153 EFIAPI
154 Tcp4GetSubnetInfo (
155 IN EFI_HANDLE ImageHandle,
156 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *Instance
157 )
158 {
159 EFI_STATUS Status;
160 EFI_TCP4_PROTOCOL *Tcp4;
161 EFI_TCP4_CONFIG_DATA Tcp4CfgData;
162 EFI_TCP4_OPTION Tcp4Option;
163 EFI_IP4_MODE_DATA IpModedata;
164 UINT8 SubnetMaskIndex;
165 UINT8 BitMask;
166 UINT8 PrefixLength;
167 BOOLEAN GotPrefixLength;
168
169 if (Instance == NULL) {
170 return EFI_INVALID_PARAMETER;
171 }
172
173 Tcp4 = (EFI_TCP4_PROTOCOL *)Instance->NetworkInterfaceProtocolInfo.NetworkProtocolInterface;
174
175 ZeroMem ((VOID *)&Tcp4CfgData, sizeof (EFI_TCP4_CONFIG_DATA));
176 ZeroMem ((VOID *)&Tcp4Option, sizeof (EFI_TCP4_OPTION));
177 // Give a local host IP address just for getting subnet information.
178 Tcp4CfgData.AccessPoint.UseDefaultAddress = TRUE;
179 Tcp4CfgData.AccessPoint.RemoteAddress.Addr[0] = 127;
180 Tcp4CfgData.AccessPoint.RemoteAddress.Addr[1] = 0;
181 Tcp4CfgData.AccessPoint.RemoteAddress.Addr[2] = 0;
182 Tcp4CfgData.AccessPoint.RemoteAddress.Addr[3] = 1;
183 Tcp4CfgData.AccessPoint.RemotePort = 80;
184 Tcp4CfgData.AccessPoint.ActiveFlag = TRUE;
185
186 Tcp4CfgData.ControlOption = &Tcp4Option;
187 Tcp4Option.ReceiveBufferSize = 65535;
188 Tcp4Option.SendBufferSize = 65535;
189 Tcp4Option.MaxSynBackLog = 5;
190 Tcp4Option.ConnectionTimeout = 60;
191 Tcp4Option.DataRetries = 12;
192 Tcp4Option.FinTimeout = 2;
193 Tcp4Option.KeepAliveProbes = 6;
194 Tcp4Option.KeepAliveTime = 7200;
195 Tcp4Option.KeepAliveInterval = 30;
196 Tcp4Option.EnableNagle = TRUE;
197 Status = Tcp4->Configure (Tcp4, &Tcp4CfgData);
198 if (EFI_ERROR (Status)) {
199 DEBUG ((DEBUG_ERROR, "%a: Can't get subnet information\n", __FUNCTION__));
200 return Status;
201 }
202
203 Status = Tcp4->GetModeData (Tcp4, NULL, NULL, &IpModedata, NULL, NULL);
204 if (EFI_ERROR (Status)) {
205 DEBUG ((DEBUG_ERROR, "%a: Can't get IP mode data information\n", __FUNCTION__));
206 return Status;
207 }
208
209 IP4_COPY_ADDRESS (&Instance->SubnetMask, &IpModedata.ConfigData.SubnetMask);
210 Instance->SubnetAddr.v4.Addr[0] = IpModedata.ConfigData.StationAddress.Addr[0] & Instance->SubnetMask.v4.Addr[0];
211 Instance->SubnetAddr.v4.Addr[1] = IpModedata.ConfigData.StationAddress.Addr[1] & Instance->SubnetMask.v4.Addr[1];
212 Instance->SubnetAddr.v4.Addr[2] = IpModedata.ConfigData.StationAddress.Addr[2] & Instance->SubnetMask.v4.Addr[2];
213 Instance->SubnetAddr.v4.Addr[3] = IpModedata.ConfigData.StationAddress.Addr[3] & Instance->SubnetMask.v4.Addr[3];
214 //
215 // Calculate the subnet mask prefix.
216 //
217 GotPrefixLength = FALSE;
218 PrefixLength = 0;
219 SubnetMaskIndex = 0;
220 while (GotPrefixLength == FALSE && SubnetMaskIndex < 4) {
221 BitMask = 0x80;
222 while (BitMask != 0) {
223 if ((Instance->SubnetMask.v4.Addr[SubnetMaskIndex] & BitMask) != 0) {
224 PrefixLength++;
225 } else {
226 GotPrefixLength = TRUE;
227 break;
228 }
229
230 BitMask = BitMask >> 1;
231 }
232
233 SubnetMaskIndex++;
234 }
235
236 Instance->SubnetPrefixLength = PrefixLength;
237 return EFI_SUCCESS;
238 }
239
240 /**
241 This function gets the subnet information of this TCP6 instance.
242
243 @param[in] ImageHandle EFI handle with this image.
244 @param[in] Instance Instance of Network interface.
245 @retval EFI_STATUS Get subnet information successfully.
246 @retval Otherwise Fail to get subnet information.
247 **/
248 EFI_STATUS
249 EFIAPI
250 Tcp6GetSubnetInfo (
251 IN EFI_HANDLE ImageHandle,
252 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *Instance
253 )
254 {
255 EFI_STATUS Status;
256 EFI_TCP6_PROTOCOL *Tcp6;
257 EFI_IP6_MODE_DATA IpModedata;
258
259 if (Instance == NULL) {
260 return EFI_INVALID_PARAMETER;
261 }
262
263 Tcp6 = (EFI_TCP6_PROTOCOL *)Instance->NetworkInterfaceProtocolInfo.NetworkProtocolInterface;
264
265 Status = Tcp6->GetModeData (Tcp6, NULL, NULL, &IpModedata, NULL, NULL);
266 if (EFI_ERROR (Status)) {
267 DEBUG ((DEBUG_ERROR, "%a: Can't get IP mode data information\n"));
268 return Status;
269 }
270
271 if (IpModedata.AddressCount == 0) {
272 DEBUG ((DEBUG_INFO, "%a: No IPv6 address configured.\n"));
273 }
274
275 if (Instance->SubnetAddrInfoIPv6 != NULL) {
276 FreePool (Instance->SubnetAddrInfoIPv6);
277 }
278
279 Instance->SubnetAddrInfoIPv6 = AllocateZeroPool (IpModedata.AddressCount * sizeof (EFI_IP6_ADDRESS_INFO));
280 if (Instance->SubnetAddrInfoIPv6 == NULL) {
281 DEBUG ((DEBUG_ERROR, "%a: Failed to allocate memory fir IPv6 subnet address information\n"));
282 return EFI_OUT_OF_RESOURCES;
283 }
284
285 Instance->SubnetAddrInfoIPv6Number = IpModedata.AddressCount;
286 CopyMem (
287 (VOID *)Instance->SubnetAddrInfoIPv6,
288 (VOID *)&IpModedata.AddressList,
289 IpModedata.AddressCount * sizeof (EFI_IP6_ADDRESS_INFO)
290 );
291 FreePool (IpModedata.AddressList);
292 return EFI_SUCCESS;
293 }
294
295 /**
296 This function searches EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
297 instance with the given EFI_REDFISH_DISCOVER_NETWORK_INTERFACE.
298
299 @param[in] TargetNetworkInterface EFI_REDFISH_DISCOVER_NETWORK_INTERFACE.
300 NULL for all EFI_REDFISH_DISCOVER_NETWORK_INTERFACEs.
301
302 @retval Non-NULL EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL is returned.
303 @retval NULL Non of EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL instance is returned.
304 **/
305 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *
306 GetTargetNetworkInterfaceInternal (
307 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *TargetNetworkInterface
308 )
309 {
310 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterface;
311
312 ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface);
313 while (TRUE) {
314 if (CompareMem ((VOID *)&ThisNetworkInterface->MacAddress, &TargetNetworkInterface->MacAddress, ThisNetworkInterface->HwAddressSize) == 0) {
315 return ThisNetworkInterface;
316 }
317
318 if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry)) {
319 return NULL;
320 }
321
322 ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry);
323 }
324
325 return NULL;
326 }
327
328 /**
329 This function validate if target network interface is ready for discovering
330 Redfish service.
331
332 @param[in] TargetNetworkInterface EFI_REDFISH_DISCOVER_NETWORK_INTERFACE.
333 NULL for all EFI_REDFISH_DISCOVER_NETWORK_INTERFACEs.
334 @param[in] Flags EFI_REDFISH_DISCOVER_FLAG
335
336 @retval EFI_SUCCESS Target network interface is ready to use.
337 @retval EFI_UNSUPPORTED Target network interface is not ready to use.
338 **/
339 EFI_STATUS
340 ValidateTargetNetworkInterface (
341 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *TargetNetworkInterface,
342 IN EFI_REDFISH_DISCOVER_FLAG Flags
343 )
344 {
345 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterface;
346
347 if (IsListEmpty (&mEfiRedfishDiscoverNetworkInterface) && (TargetNetworkInterface == NULL)) {
348 return EFI_UNSUPPORTED;
349 }
350
351 if (TargetNetworkInterface == NULL) {
352 return EFI_SUCCESS; // Return EFI_SUCCESS if no network interface is specified.
353 }
354
355 ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface);
356 while (TRUE) {
357 if (CompareMem ((VOID *)&ThisNetworkInterface->MacAddress, &TargetNetworkInterface->MacAddress, ThisNetworkInterface->HwAddressSize) == 0) {
358 break;
359 }
360
361 if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry)) {
362 return EFI_UNSUPPORTED;
363 }
364
365 ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry);
366 }
367
368 if ((Flags & EFI_REDFISH_DISCOVER_SSDP) != 0) {
369 // Validate if UDP4/6 is supported on the given network interface.
370 // SSDP is not supported.
371
372 return EFI_SUCCESS;
373 }
374
375 if (ThisNetworkInterface->NetworkInterfaceProtocolInfo.ProtocolControllerHandle == NULL) {
376 return EFI_UNSUPPORTED; // The required protocol on this network interface is not found.
377 }
378
379 return EFI_SUCCESS;
380 }
381
382 /**
383 This function returns number of network interface instance.
384
385 @retval UINTN Number of network interface instances.
386 **/
387 UINTN
388 NumberOfNetworkInterface (
389 VOID
390 )
391 {
392 UINTN Num;
393 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterface;
394
395 if (IsListEmpty (&mEfiRedfishDiscoverNetworkInterface)) {
396 return 0;
397 }
398
399 Num = 1;
400 ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface);
401 while (TRUE) {
402 if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry)) {
403 break;
404 }
405
406 ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry);
407 Num++;
408 }
409
410 return Num;
411 }
412
413 /**
414 This function checks the IP version supported on this
415 netwoek interface.
416
417 @param[in] ThisNetworkInterface EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
418
419 @retval TRUE Is IPv6, otherwise IPv4.
420
421 **/
422 BOOLEAN
423 CheckIsIpVersion6 (
424 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterface
425 )
426 {
427 if (ThisNetworkInterface->NetworkProtocolType == ProtocolTypeTcp6) {
428 return TRUE;
429 }
430
431 return FALSE;
432 }
433
434 /**
435 This function discover Redfish service through SMBIOS host interface.
436
437 @param[in] Instance EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
438
439 @retval EFI_SUCCESS Redfish service is discovered through SMBIOS Host interface.
440 @retval Others Fail to discover Redfish service throught SMBIOS host interface
441
442 **/
443 EFI_STATUS
444 DiscoverRedfishHostInterface (
445 IN EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *Instance
446 )
447 {
448 EFI_STATUS Status;
449 REDFISH_OVER_IP_PROTOCOL_DATA *Data;
450 REDFISH_INTERFACE_DATA *DeviceDescriptor;
451 CHAR8 UuidStr[sizeof "00000000-0000-0000-0000-000000000000" + 1];
452 CHAR16 Ipv6Str[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" + 1];
453 CHAR8 RedfishServiceLocateStr[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" + 1];
454 UINTN StrSize;
455 UINTN MacCompareStstus;
456 BOOLEAN IsHttps;
457
458 Data = NULL;
459 DeviceDescriptor = NULL;
460
461 if (mSmbios == NULL) {
462 Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **)&mSmbios);
463 if (EFI_ERROR (Status)) {
464 return Status;
465 }
466 }
467
468 Status = RedfishGetHostInterfaceProtocolData (mSmbios, &DeviceDescriptor, &Data); // Search for SMBIOS type 42h
469 if (!EFI_ERROR (Status) && (Data != NULL) && (DeviceDescriptor != NULL)) {
470 //
471 // Chceck if we can reach out Redfish service using this network interface.
472 // Check with MAC address using Device Descroptor Data Device Type 04 and Type 05.
473 // Those two types of Redfish host interface device has MAC information.
474 //
475 if (DeviceDescriptor->DeviceType == REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE_V2) {
476 MacCompareStstus = CompareMem (&Instance->NetworkInterface->MacAddress, &DeviceDescriptor->DeviceDescriptor.PciPcieDeviceV2.MacAddress, 6);
477 } else if (DeviceDescriptor->DeviceType == REDFISH_HOST_INTERFACE_DEVICE_TYPE_USB_V2) {
478 MacCompareStstus = CompareMem (&Instance->NetworkInterface->MacAddress, &DeviceDescriptor->DeviceDescriptor.UsbDeviceV2.MacAddress, 6);
479 } else {
480 return EFI_UNSUPPORTED;
481 }
482
483 if (MacCompareStstus != 0) {
484 return EFI_UNSUPPORTED;
485 }
486
487 if (Data->RedfishServiceIpAddressFormat == 1) {
488 IP4_COPY_ADDRESS ((VOID *)&Instance->TargetIpAddress.v4, (VOID *)Data->RedfishServiceIpAddress);
489 } else {
490 IP6_COPY_ADDRESS ((VOID *)&Instance->TargetIpAddress.v6, (VOID *)Data->RedfishServiceIpAddress);
491 }
492
493 if (Instance->HostIntfValidation) {
494 DEBUG ((DEBUG_ERROR, "%a:Send UPnP unicast SSDP to validate this Redfish Host Interface is not supported.\n", __FUNCTION__));
495 Status = EFI_UNSUPPORTED;
496 } else {
497 //
498 // Add this istance to list without detial information of Redfish
499 // service.
500 //
501 IsHttps = FALSE;
502 if (Data->RedfishServiceIpPort == 443) {
503 IsHttps = TRUE;
504 }
505
506 StrSize = sizeof (UuidStr);
507 AsciiSPrint (UuidStr, StrSize, "%g", &Data->ServiceUuid);
508 //
509 // Generate Redfish service location string.
510 //
511 if (Data->RedfishServiceIpAddressFormat == REDFISH_HOST_INTERFACE_HOST_IP_ADDRESS_FORMAT_IP6) {
512 NetLibIp6ToStr ((IPv6_ADDRESS *)&Data->RedfishServiceIpAddress, Ipv6Str, sizeof (Ipv6Str));
513 if ((Data->RedfishServiceIpPort == 0) || (IsHttps == TRUE)) {
514 AsciiSPrintUnicodeFormat (
515 RedfishServiceLocateStr,
516 sizeof (RedfishServiceLocateStr),
517 L"%s",
518 Ipv6Str
519 );
520 } else {
521 AsciiSPrintUnicodeFormat (
522 RedfishServiceLocateStr,
523 sizeof (RedfishServiceLocateStr),
524 L"[%s]:%d",
525 Ipv6Str,
526 Data->RedfishServiceIpPort
527 );
528 }
529 } else {
530 if ((Data->RedfishServiceIpPort == 0) || (IsHttps == TRUE)) {
531 AsciiSPrint (
532 RedfishServiceLocateStr,
533 sizeof (RedfishServiceLocateStr),
534 "%d.%d.%d.%d",
535 Data->RedfishServiceIpAddress[0],
536 Data->RedfishServiceIpAddress[1],
537 Data->RedfishServiceIpAddress[2],
538 Data->RedfishServiceIpAddress[3]
539 );
540 } else {
541 AsciiSPrint (
542 RedfishServiceLocateStr,
543 sizeof (RedfishServiceLocateStr),
544 "%d.%d.%d.%d:%d",
545 Data->RedfishServiceIpAddress[0],
546 Data->RedfishServiceIpAddress[1],
547 Data->RedfishServiceIpAddress[2],
548 Data->RedfishServiceIpAddress[3],
549 Data->RedfishServiceIpPort
550 );
551 }
552 }
553
554 Status = AddAndSignalNewRedfishService (
555 Instance,
556 NULL,
557 RedfishServiceLocateStr,
558 UuidStr,
559 NULL,
560 NULL,
561 NULL,
562 NULL,
563 IsHttps
564 );
565 }
566 }
567
568 return Status;
569 }
570
571 /**
572 The function adds a new found Redfish service to internal list and
573 notify client.
574
575 @param[in] Instance EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE.
576 @param[in] RedfishVersion Redfish version.
577 @param[in] RedfishLocation Redfish location.
578 @param[in] Uuid Service UUID string.
579 @param[in] Os OS string.
580 @param[in] OsVer OS version string.
581 @param[in] Product Product string.
582 @param[in] ProductVer Product verison string.
583 @param[in] UseHttps Redfish service requires secured connection.
584 @retval EFI_SUCCESS Redfish service is added to list successfully.
585
586 **/
587 EFI_STATUS
588 AddAndSignalNewRedfishService (
589 IN EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *Instance,
590 IN UINTN *RedfishVersion OPTIONAL,
591 IN CHAR8 *RedfishLocation OPTIONAL,
592 IN CHAR8 *Uuid OPTIONAL,
593 IN CHAR8 *Os OPTIONAL,
594 IN CHAR8 *OsVer OPTIONAL,
595 IN CHAR8 *Product OPTIONAL,
596 IN CHAR8 *ProductVer OPTIONAL,
597 IN BOOLEAN UseHttps
598 )
599 {
600 BOOLEAN NewFound;
601 BOOLEAN InfoRefresh;
602 BOOLEAN RestExOpened;
603 BOOLEAN DeleteRestEx;
604 EFI_STATUS Status;
605 EFI_REDFISH_DISCOVERED_INTERNAL_LIST *DiscoveredList;
606 EFI_REDFISH_DISCOVERED_INSTANCE *DiscoveredInstance;
607 CHAR16 *Char16Uuid;
608 EFI_REST_EX_PROTOCOL *RestEx;
609 EFI_REST_EX_HTTP_CONFIG_DATA *RestExHttpConfigData;
610 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *NetworkInterface;
611
612 NewFound = TRUE;
613 InfoRefresh = FALSE;
614 Char16Uuid = NULL;
615 RestExOpened = FALSE;
616 DeleteRestEx = FALSE;
617
618 DEBUG ((DEBUG_INFO, "%a:Add this instance to Redfish instance list.\n", __FUNCTION__));
619
620 if (Uuid != NULL) {
621 Char16Uuid = (CHAR16 *)AllocateZeroPool (AsciiStrSize ((const CHAR8 *)Uuid) * sizeof (CHAR16));
622 AsciiStrToUnicodeStrS ((const CHAR8 *)Uuid, Char16Uuid, AsciiStrSize ((const CHAR8 *)Uuid) * sizeof (CHAR16));
623 }
624
625 DiscoveredList = NULL;
626 DiscoveredInstance = NULL;
627 RestExHttpConfigData = NULL;
628
629 NetworkInterface = Instance->NetworkInterface;
630 if (!IsListEmpty (&mRedfishInstanceList)) {
631 //
632 // Is this a duplicate redfish service.
633 //
634 DiscoveredList = (EFI_REDFISH_DISCOVERED_INTERNAL_LIST *)GetFirstNode (&mRedfishInstanceList);
635 NewFound = FALSE;
636 do {
637 if ((Char16Uuid == NULL) || (DiscoveredList->Instance->Information.Uuid == NULL)) {
638 //
639 // Check if this Redfish instance already found using IP addrress.
640 //
641 if (!CheckIsIpVersion6 (NetworkInterface)) {
642 if (CompareMem (
643 (VOID *)&Instance->TargetIpAddress.v4,
644 (VOID *)&DiscoveredList->Instance->Information.RedfishHostIpAddress.v4,
645 sizeof (EFI_IPv4_ADDRESS)
646 ) == 0)
647 {
648 DiscoveredInstance = DiscoveredList->Instance;
649 if ((DiscoveredList->Instance->Information.Uuid == NULL) &&
650 (Char16Uuid != NULL))
651 {
652 InfoRefresh = TRUE;
653 DiscoveredInstance = DiscoveredList->Instance;
654 DEBUG ((DEBUG_INFO, "*** This Redfish Service information refresh ***\n"));
655 }
656
657 break;
658 }
659 } else {
660 if (CompareMem (
661 (VOID *)&Instance->TargetIpAddress.v6,
662 (VOID *)&DiscoveredList->Instance->Information.RedfishHostIpAddress.v6,
663 sizeof (EFI_IPv6_ADDRESS)
664 ) == 0)
665 {
666 DiscoveredInstance = DiscoveredList->Instance;
667 break;
668 }
669 }
670 } else {
671 //
672 // Check if this Redfish instance already found using UUID.
673 //
674 if (StrCmp ((const CHAR16 *)Char16Uuid, (const CHAR16 *)DiscoveredList->Instance->Information.Uuid) == 0) {
675 DiscoveredInstance = DiscoveredList->Instance;
676 break;
677 }
678 }
679
680 if (IsNodeAtEnd (&mRedfishInstanceList, &DiscoveredList->NextInstance)) {
681 NewFound = TRUE;
682 break;
683 }
684
685 DiscoveredList = (EFI_REDFISH_DISCOVERED_INTERNAL_LIST *)GetNextNode (&mRedfishInstanceList, &DiscoveredList->NextInstance);
686 } while (TRUE);
687 }
688
689 if (NewFound || InfoRefresh) {
690 if (!InfoRefresh) {
691 DiscoveredList = (EFI_REDFISH_DISCOVERED_INTERNAL_LIST *)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVERED_INTERNAL_LIST));
692 if (DiscoveredList == NULL) {
693 return EFI_OUT_OF_RESOURCES;
694 }
695
696 InitializeListHead (&DiscoveredList->NextInstance);
697 DiscoveredInstance = (EFI_REDFISH_DISCOVERED_INSTANCE *)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVERED_INSTANCE));
698 if (DiscoveredInstance == NULL) {
699 FreePool ((VOID *)DiscoveredList);
700 return EFI_OUT_OF_RESOURCES;
701 }
702 }
703
704 DEBUG ((DEBUG_INFO, "*** Redfish Service Information ***\n"));
705
706 DiscoveredInstance->Information.UseHttps = UseHttps;
707 if (RedfishVersion != NULL) {
708 DiscoveredInstance->Information.RedfishVersion = *RedfishVersion;
709 DEBUG ((DEBUG_INFO, "Redfish service version: %d.\n", DiscoveredInstance->Information.RedfishVersion));
710 }
711
712 if (RedfishLocation != NULL) {
713 DiscoveredInstance->Information.Location = (CHAR16 *)AllocatePool (AsciiStrSize ((const CHAR8 *)RedfishLocation) * sizeof (CHAR16));
714 AsciiStrToUnicodeStrS ((const CHAR8 *)RedfishLocation, DiscoveredInstance->Information.Location, AsciiStrSize ((const CHAR8 *)RedfishLocation) * sizeof (CHAR16));
715 DEBUG ((DEBUG_INFO, "Redfish service location: %s.\n", DiscoveredInstance->Information.Location));
716 }
717
718 if (Uuid != NULL) {
719 DiscoveredInstance->Information.Uuid = (CHAR16 *)AllocatePool (AsciiStrSize ((const CHAR8 *)Uuid) * sizeof (CHAR16));
720 AsciiStrToUnicodeStrS ((const CHAR8 *)Uuid, DiscoveredInstance->Information.Uuid, AsciiStrSize ((const CHAR8 *)Uuid) * sizeof (CHAR16));
721 DEBUG ((DEBUG_INFO, "Service UUID: %s.\n", DiscoveredInstance->Information.Uuid));
722 }
723
724 if (Os != NULL) {
725 DiscoveredInstance->Information.Os = (CHAR16 *)AllocatePool (AsciiStrSize ((const CHAR8 *)Os) * sizeof (CHAR16));
726 AsciiStrToUnicodeStrS ((const CHAR8 *)Os, DiscoveredInstance->Information.Os, AsciiStrSize ((const CHAR8 *)Os) * sizeof (CHAR16));
727 DEBUG ((DEBUG_INFO, "Redfish service OS: %s, Version:%s.\n", DiscoveredInstance->Information.Os, DiscoveredInstance->Information.OsVersion));
728 }
729
730 if (OsVer != NULL) {
731 DiscoveredInstance->Information.OsVersion = (CHAR16 *)AllocatePool (AsciiStrSize ((const CHAR8 *)OsVer) * sizeof (CHAR16));
732 AsciiStrToUnicodeStrS ((const CHAR8 *)OsVer, DiscoveredInstance->Information.OsVersion, AsciiStrSize ((const CHAR8 *)OsVer) * sizeof (CHAR16));
733 }
734
735 if ((Product != NULL) && (ProductVer != NULL)) {
736 DiscoveredInstance->Information.Product = (CHAR16 *)AllocatePool (AsciiStrSize ((const CHAR8 *)Product) * sizeof (CHAR16));
737 AsciiStrToUnicodeStrS ((const CHAR8 *)Product, DiscoveredInstance->Information.Product, AsciiStrSize ((const CHAR8 *)Product) * sizeof (CHAR16));
738 DiscoveredInstance->Information.ProductVer = (CHAR16 *)AllocatePool (AsciiStrSize ((const CHAR8 *)ProductVer) * sizeof (CHAR16));
739 AsciiStrToUnicodeStrS ((const CHAR8 *)ProductVer, DiscoveredInstance->Information.ProductVer, AsciiStrSize ((const CHAR8 *)ProductVer) * sizeof (CHAR16));
740 DEBUG ((DEBUG_INFO, "Redfish service product: %s, Version:%s.\n", DiscoveredInstance->Information.Product, DiscoveredInstance->Information.ProductVer));
741 }
742
743 if (RedfishLocation == NULL) {
744 // This is the Redfish reported from SMBIOS 42h
745 // without validation.
746
747 IP4_COPY_ADDRESS ((VOID *)&DiscoveredInstance->Information.RedfishHostIpAddress.v4, (VOID *)&Instance->TargetIpAddress.v4);
748 }
749
750 if (!InfoRefresh) {
751 DiscoveredList->Instance = DiscoveredInstance;
752 InsertTailList (&mRedfishInstanceList, &DiscoveredList->NextInstance);
753 }
754
755 DiscoveredInstance->Status = EFI_SUCCESS;
756 } else {
757 if (DiscoveredList != NULL) {
758 DEBUG ((DEBUG_INFO, "*** This Redfish Service was already found ***\n"));
759 if (DiscoveredInstance->Information.Uuid != NULL) {
760 DEBUG ((DEBUG_INFO, "Service UUID: %s.\n", DiscoveredInstance->Information.Uuid));
761 } else {
762 DEBUG ((DEBUG_INFO, "Service UUID: unknown.\n"));
763 }
764 }
765 }
766
767 if (Char16Uuid != NULL) {
768 FreePool ((VOID *)Char16Uuid);
769 }
770
771 Status = EFI_SUCCESS;
772 if (NewFound || InfoRefresh) {
773 //
774 // Build up EFI_REDFISH_DISCOVERED_LIST in token.
775 //
776 Instance->DiscoverToken->DiscoverList.NumberOfServiceFound = 1;
777 Instance->DiscoverToken->DiscoverList.RedfishInstances = DiscoveredInstance;
778 DiscoveredInstance->Status = EFI_SUCCESS;
779 if (!InfoRefresh) {
780 Status = CreateRestExInstance (Instance, Instance->DiscoverToken); // Create REST EX child.
781 if (EFI_ERROR (Status)) {
782 DEBUG ((DEBUG_ERROR, "%a:Can't create REST EX child instance.\n", __FUNCTION__));
783 goto ON_EXIT;
784 }
785
786 Status = gBS->OpenProtocol (
787 // Configure local host information.
788 Instance->DiscoverToken->DiscoverList.RedfishInstances->Information.RedfishRestExHandle,
789 &gEfiRestExProtocolGuid,
790 (VOID **)&RestEx,
791 Instance->NetworkInterface->OpenDriverAgentHandle,
792 Instance->NetworkInterface->OpenDriverControllerHandle,
793 EFI_OPEN_PROTOCOL_BY_DRIVER
794 );
795 if (EFI_ERROR (Status)) {
796 DeleteRestEx = TRUE;
797 goto ERROR_EXIT;
798 }
799
800 RestExOpened = TRUE;
801 RestExHttpConfigData = AllocateZeroPool (sizeof (EFI_REST_EX_HTTP_CONFIG_DATA));
802 if (RestExHttpConfigData == NULL) {
803 Status = EFI_OUT_OF_RESOURCES;
804 DeleteRestEx = TRUE;
805 goto EXIT_FREE_CONFIG_DATA;
806 }
807
808 RestExHttpConfigData->SendReceiveTimeout = 5000;
809 RestExHttpConfigData->HttpConfigData.HttpVersion = HttpVersion11;
810 RestExHttpConfigData->HttpConfigData.LocalAddressIsIPv6 = CheckIsIpVersion6 (NetworkInterface);
811 if (RestExHttpConfigData->HttpConfigData.LocalAddressIsIPv6) {
812 RestExHttpConfigData->HttpConfigData.AccessPoint.IPv6Node = AllocateZeroPool (sizeof (EFI_HTTPv6_ACCESS_POINT));
813 if (RestExHttpConfigData->HttpConfigData.AccessPoint.IPv6Node == NULL) {
814 Status = EFI_OUT_OF_RESOURCES;
815 goto EXIT_FREE_CONFIG_DATA;
816 }
817 } else {
818 RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node = AllocateZeroPool (sizeof (EFI_HTTPv4_ACCESS_POINT));
819 if (RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node == NULL) {
820 Status = EFI_OUT_OF_RESOURCES;
821 goto EXIT_FREE_CONFIG_DATA;
822 }
823
824 RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node->UseDefaultAddress = TRUE;
825 }
826
827 Status = RestEx->Configure (
828 RestEx,
829 (EFI_REST_EX_CONFIG_DATA)(UINT8 *)RestExHttpConfigData
830 );
831 if (EFI_ERROR (Status)) {
832 DEBUG ((DEBUG_ERROR, "%a:REST EX configured..\n", __FUNCTION__));
833 DeleteRestEx = TRUE;
834 goto EXIT_FREE_ALL;
835 }
836
837 //
838 // Signal client, close REST EX before signaling client.
839 //
840 if (RestExOpened) {
841 gBS->CloseProtocol (
842 Instance->DiscoverToken->DiscoverList.RedfishInstances->Information.RedfishRestExHandle,
843 &gEfiRestExProtocolGuid,
844 Instance->NetworkInterface->OpenDriverAgentHandle,
845 Instance->NetworkInterface->OpenDriverControllerHandle
846 );
847 RestExOpened = FALSE;
848 }
849 }
850
851 Status = gBS->SignalEvent (Instance->DiscoverToken->Event);
852 if (!EFI_ERROR (Status)) {
853 DEBUG ((DEBUG_ERROR, "%a:No event to signal!\n", __FUNCTION__));
854 }
855 }
856
857 EXIT_FREE_ALL:;
858 if ((RestExHttpConfigData != NULL) && (RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node != NULL)) {
859 FreePool (RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node);
860 }
861
862 EXIT_FREE_CONFIG_DATA:;
863 if (RestExHttpConfigData != NULL) {
864 FreePool ((VOID *)RestExHttpConfigData);
865 }
866
867 if (RestExOpened) {
868 gBS->CloseProtocol (
869 Instance->DiscoverToken->DiscoverList.RedfishInstances->Information.RedfishRestExHandle,
870 &gEfiRestExProtocolGuid,
871 Instance->NetworkInterface->OpenDriverAgentHandle,
872 Instance->NetworkInterface->OpenDriverControllerHandle
873 );
874 }
875
876 ERROR_EXIT:;
877 if (DeleteRestEx && RestExOpened) {
878 gBS->CloseProtocol (
879 Instance->DiscoverToken->DiscoverList.RedfishInstances->Information.RedfishRestExHandle,
880 &gEfiRestExProtocolGuid,
881 Instance->NetworkInterface->OpenDriverAgentHandle,
882 Instance->NetworkInterface->OpenDriverControllerHandle
883 );
884 }
885
886 ON_EXIT:;
887 return Status;
888 }
889
890 /**
891 This function gets the subnet information of this network interface instance.
892 can discover Redfish service on it.
893
894 @param[in] Instance EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL instance.
895 @param[in] ImageHandle EFI Image handle request the network interface list.
896
897 @retval EFI_SUCCESS
898
899 **/
900 EFI_STATUS
901 NetworkInterfaceGetSubnetInfo (
902 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *Instance,
903 IN EFI_HANDLE ImageHandle
904 )
905 {
906 EFI_STATUS Status;
907 UINT32 ProtocolType;
908 UINT32 IPv6InfoIndex;
909 EFI_IP6_ADDRESS_INFO *ThisSubnetAddrInfoIPv6;
910 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *NewNetworkInterface;
911
912 if (Instance->GotSubnetInfo) {
913 return EFI_SUCCESS;
914 }
915
916 ProtocolType = Instance->NetworkProtocolType;
917 if ((gRequiredProtocol[ProtocolType].GetSubnetInfo != NULL) && (Instance->GotSubnetInfo == FALSE)) {
918 Status = gRequiredProtocol[ProtocolType].GetSubnetInfo (
919 ImageHandle,
920 Instance
921 );
922 if (EFI_ERROR (Status)) {
923 DEBUG ((DEBUG_ERROR, "%a:Faile to get Subnet infomation.\n", __FUNCTION__));
924 return Status;
925 } else {
926 DEBUG ((DEBUG_INFO, "%a:MAC address: %s\n", __FUNCTION__, Instance->StrMacAddr));
927 if (CheckIsIpVersion6 (Instance)) {
928 if (Instance->SubnetAddrInfoIPv6Number == 0) {
929 DEBUG ((DEBUG_ERROR, "%a: There is no Subnet infomation for IPv6 network interface.\n", __FUNCTION__));
930 return EFI_NOT_FOUND;
931 }
932
933 ThisSubnetAddrInfoIPv6 = Instance->SubnetAddrInfoIPv6; // First IPv6 address information.
934 IP6_COPY_ADDRESS (&Instance->SubnetAddr.v6, &ThisSubnetAddrInfoIPv6->Address);
935 Instance->SubnetPrefixLength = ThisSubnetAddrInfoIPv6->PrefixLength;
936 DEBUG ((
937 DEBUG_INFO,
938 " IPv6 Subnet ID:%d, Prefix length: %d.\n",
939 ThisSubnetAddrInfoIPv6->Address.Addr[7] + (UINT16)ThisSubnetAddrInfoIPv6->Address.Addr[6] * 256,
940 ThisSubnetAddrInfoIPv6->PrefixLength
941 )
942 );
943 //
944 // If this is IPv6, then we may have to propagate network interface for IPv6 network scopes
945 // according to the Ipv6 address information.
946 //
947 ThisSubnetAddrInfoIPv6++;
948 for (IPv6InfoIndex = 0; IPv6InfoIndex < Instance->SubnetAddrInfoIPv6Number - 1; IPv6InfoIndex++) {
949 //
950 // Build up addtional EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL instances.
951 //
952 NewNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL));
953 if (NewNetworkInterface != NULL) {
954 CopyMem ((VOID *)NewNetworkInterface, (VOID *)Instance, sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL)); // Clone information of first instance.
955 IP6_COPY_ADDRESS (&NewNetworkInterface->SubnetAddr.v6, &ThisSubnetAddrInfoIPv6->Address);
956 NewNetworkInterface->SubnetPrefixLength = ThisSubnetAddrInfoIPv6->PrefixLength;
957 NewNetworkInterface->GotSubnetInfo = TRUE;
958 InsertTailList (&mEfiRedfishDiscoverNetworkInterface, &NewNetworkInterface->Entry);
959 ThisSubnetAddrInfoIPv6++;
960 mNumNetworkInterface++;
961 DEBUG ((
962 DEBUG_INFO,
963 " IPv6 Subnet ID:%d, Prefix length: %d.\n",
964 ThisSubnetAddrInfoIPv6->Address.Addr[7] + (UINT16)ThisSubnetAddrInfoIPv6->Address.Addr[6] * 256,
965 ThisSubnetAddrInfoIPv6->PrefixLength
966 )
967 );
968 } else {
969 return EFI_OUT_OF_RESOURCES;
970 }
971 }
972 } else {
973 DEBUG ((
974 DEBUG_INFO,
975 " IPv4 Subnet:%d.%d.%d.%d Subnet mask: %d.%d.%d.%d.\n",
976 Instance->SubnetAddr.v4.Addr[0],
977 Instance->SubnetAddr.v4.Addr[1],
978 Instance->SubnetAddr.v4.Addr[2],
979 Instance->SubnetAddr.v4.Addr[3],
980 Instance->SubnetMask.v4.Addr[0],
981 Instance->SubnetMask.v4.Addr[1],
982 Instance->SubnetMask.v4.Addr[2],
983 Instance->SubnetMask.v4.Addr[3]
984 ));
985 }
986 }
987 }
988
989 Instance->GotSubnetInfo = TRUE; // Only try to get Subnet Info once.
990 return EFI_SUCCESS;
991 }
992
993 /**
994 This function gets the network interface list which Redfish discover protocol
995 can discover Redfish service on it.
996
997 @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instance.
998 @param[in] ImageHandle EFI Image handle request the network interface list,
999 @param[out] NumberOfNetworkIntfs Number of network interfaces can do Redfish service discovery.
1000 @param[out] NetworkIntfInstances Network interface instances. It's an array of instance. The number of entries
1001 in array is indicated by NumberOfNetworkIntfs.
1002 Caller has to release the memory
1003 allocated by Redfish discover protocol.
1004
1005 @retval EFI_SUCCESS The information of network interface is returned in NumberOfNetworkIntfs and
1006 NetworkIntfInstances.
1007 @retval Others Fail to return the information of network interface.
1008
1009 **/
1010 EFI_STATUS
1011 EFIAPI
1012 RedfishServiceGetNetworkInterface (
1013 IN EFI_REDFISH_DISCOVER_PROTOCOL *This,
1014 IN EFI_HANDLE ImageHandle,
1015 OUT UINTN *NumberOfNetworkIntfs,
1016 OUT EFI_REDFISH_DISCOVER_NETWORK_INTERFACE **NetworkIntfInstances
1017 )
1018 {
1019 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterfaceIntn;
1020 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *ThisNetworkInterface;
1021
1022 if ((NetworkIntfInstances == NULL) || (NumberOfNetworkIntfs == NULL) || (ImageHandle == NULL)) {
1023 return EFI_INVALID_PARAMETER;
1024 }
1025
1026 *NumberOfNetworkIntfs = 0;
1027 *NetworkIntfInstances = NULL;
1028
1029 if (IsListEmpty ((const LIST_ENTRY *)&mEfiRedfishDiscoverNetworkInterface)) {
1030 return EFI_NOT_FOUND;
1031 }
1032
1033 ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE) * mNumNetworkInterface);
1034 if (ThisNetworkInterface == NULL) {
1035 return EFI_OUT_OF_RESOURCES;
1036 }
1037
1038 *NetworkIntfInstances = ThisNetworkInterface;
1039 ThisNetworkInterfaceIntn = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface);
1040 while (TRUE) {
1041 ThisNetworkInterface->IsIpv6 = FALSE;
1042 if (CheckIsIpVersion6 (ThisNetworkInterfaceIntn)) {
1043 ThisNetworkInterface->IsIpv6 = TRUE;
1044 }
1045
1046 CopyMem ((VOID *)&ThisNetworkInterface->MacAddress, &ThisNetworkInterfaceIntn->MacAddress, ThisNetworkInterfaceIntn->HwAddressSize);
1047 NetworkInterfaceGetSubnetInfo (ThisNetworkInterfaceIntn, ImageHandle); // Get subnet info.
1048 if (!ThisNetworkInterface->IsIpv6) {
1049 IP4_COPY_ADDRESS (&ThisNetworkInterface->SubnetId.v4, &ThisNetworkInterfaceIntn->SubnetAddr.v4); // IPv4 subnet information.
1050 } else {
1051 IP6_COPY_ADDRESS (&ThisNetworkInterface->SubnetId.v6, &ThisNetworkInterfaceIntn->SubnetAddr.v6); // IPv6 subnet information in IPv6 address information.
1052 }
1053
1054 ThisNetworkInterface->SubnetPrefixLength = ThisNetworkInterfaceIntn->SubnetPrefixLength;
1055 ThisNetworkInterface->VlanId = ThisNetworkInterfaceIntn->VlanId;
1056 (*NumberOfNetworkIntfs)++;
1057 if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterfaceIntn->Entry)) {
1058 break;
1059 }
1060
1061 ThisNetworkInterfaceIntn = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterfaceIntn->Entry);
1062 ThisNetworkInterface++;
1063 }
1064
1065 return EFI_SUCCESS;
1066 }
1067
1068 /**
1069 This function acquires Redfish services by discovering static Redfish setting
1070 according to Redfish Host Interface or through SSDP. Returns a list of EFI
1071 handles in EFI_REDFISH_DISCOVERED_LIST. Each of EFI handle has cooresponding
1072 EFI REST EX instance installed on it. Each REST EX isntance is a child instance which
1073 created through EFI REST EX serivce protoocl for communicating with specific
1074 Redfish service.
1075
1076 @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instance.
1077 @param[in] ImageHandle EFI image owns these Redfish service instances.
1078 @param[in] TargetNetworkInterface Target network interface to do the discovery.
1079 NULL means discover Redfish service on all network interfaces on platform.
1080 @param[in] Flags Redfish service discover flags.
1081 @param[in] Token EFI_REDFISH_DISCOVERED_TOKEN instance.
1082 The memory of EFI_REDFISH_DISCOVERED_LIST and the strings in
1083 EFI_REDFISH_DISCOVERED_INFORMATION are all allocated by Acquire()
1084 and must be freed when caller invoke Release().
1085
1086 @retval EFI_SUCCESS REST EX instance of discovered Redfish services are returned.
1087 @retval EFI_INVALID_PARAMETERS ImageHandle == NULL, Flags == 0, Token == NULL, Token->Timeout > 5,
1088 or Token->Event == NULL.
1089 @retval Others Fail acquire Redfish services.
1090
1091 **/
1092 EFI_STATUS
1093 EFIAPI
1094 RedfishServiceAcquireService (
1095 IN EFI_REDFISH_DISCOVER_PROTOCOL *This,
1096 IN EFI_HANDLE ImageHandle,
1097 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *TargetNetworkInterface,
1098 IN EFI_REDFISH_DISCOVER_FLAG Flags,
1099 IN EFI_REDFISH_DISCOVERED_TOKEN *Token
1100 )
1101 {
1102 EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *Instance;
1103 EFI_STATUS Status1;
1104 EFI_STATUS Status2;
1105 BOOLEAN NewInstance;
1106 UINTN NumNetworkInterfaces;
1107 UINTN NetworkInterfacesIndex;
1108 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *TargetNetworkInterfaceInternal;
1109
1110 DEBUG ((DEBUG_INFO, "%a:Entry.\n", __FUNCTION__));
1111
1112 //
1113 // Validate parameters.
1114 //
1115 if ((ImageHandle == NULL) || (Token == NULL) || ((Flags & ~EFI_REDFISH_DISCOVER_VALIDATION) == 0)) {
1116 DEBUG ((DEBUG_ERROR, "%a:Invalid parameters.\n", __FUNCTION__));
1117 return EFI_INVALID_PARAMETER;
1118 }
1119
1120 //
1121 // Validate target network interface.
1122 //
1123 if (EFI_ERROR (ValidateTargetNetworkInterface (TargetNetworkInterface, Flags))) {
1124 return EFI_UNSUPPORTED;
1125 }
1126
1127 if (TargetNetworkInterface != NULL) {
1128 TargetNetworkInterfaceInternal = GetTargetNetworkInterfaceInternal (TargetNetworkInterface);
1129 NumNetworkInterfaces = 1;
1130 } else {
1131 TargetNetworkInterfaceInternal = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface);
1132 NumNetworkInterfaces = NumberOfNetworkInterface ();
1133 if (NumNetworkInterfaces == 0) {
1134 DEBUG ((DEBUG_ERROR, "%a:No network interface on platform.\n", __FUNCTION__));
1135 return EFI_UNSUPPORTED;
1136 }
1137 }
1138
1139 for (NetworkInterfacesIndex = 0; NetworkInterfacesIndex < NumNetworkInterfaces; NetworkInterfacesIndex++) {
1140 Status1 = EFI_SUCCESS;
1141 Status2 = EFI_SUCCESS;
1142 NewInstance = FALSE;
1143 Instance = GetInstanceByOwner (ImageHandle, TargetNetworkInterfaceInternal, Flags & ~EFI_REDFISH_DISCOVER_VALIDATION); // Check if we can re-use previous instance.
1144 if (Instance == NULL) {
1145 DEBUG ((DEBUG_INFO, "%a:Create new EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE.\n", __FUNCTION__));
1146 Instance = (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE));
1147 if (Instance == NULL) {
1148 DEBUG ((DEBUG_ERROR, "%a:Memory allocation fail.\n", __FUNCTION__));
1149 }
1150
1151 InitializeListHead (&Instance->Entry);
1152 Instance->Owner = ImageHandle;
1153 Instance->DiscoverFlags = Flags & ~EFI_REDFISH_DISCOVER_VALIDATION;
1154 Instance->NetworkInterface = TargetNetworkInterfaceInternal;
1155 //
1156 // Get subnet information in case subnet information is not set because
1157 // RedfishServiceGetNetworkInterfaces hasn't been called yet.
1158 //
1159 NetworkInterfaceGetSubnetInfo (TargetNetworkInterfaceInternal, ImageHandle);
1160 NewInstance = TRUE;
1161 }
1162
1163 if (TargetNetworkInterfaceInternal->StrMacAddr != NULL) {
1164 DEBUG ((DEBUG_INFO, "%a:Acquire Redfish service on network interface MAC address:%s.\n", __FUNCTION__, TargetNetworkInterfaceInternal->StrMacAddr));
1165 } else {
1166 DEBUG ((DEBUG_INFO, "%a:WARNING: No MAC address on this network interface.\n", __FUNCTION__));
1167 }
1168
1169 Instance->DiscoverToken = Token; // Always use the latest Token passed by caller.
1170 if ((Flags & EFI_REDFISH_DISCOVER_HOST_INTERFACE) != 0) {
1171 DEBUG ((DEBUG_INFO, "%a:Redfish HOST interface discovery.\n", __FUNCTION__));
1172 Instance->HostIntfValidation = FALSE;
1173 if ((Flags & EFI_REDFISH_DISCOVER_VALIDATION) != 0) {
1174 Instance->HostIntfValidation = TRUE;
1175 }
1176
1177 Status1 = DiscoverRedfishHostInterface (Instance); // Discover Redfish service through Redfish Host Interface.
1178 }
1179
1180 if ((Flags & EFI_REDFISH_DISCOVER_SSDP) != 0) {
1181 DEBUG ((DEBUG_ERROR, "%a:Redfish service discovery through SSDP is not supported\n", __FUNCTION__));
1182 return EFI_UNSUPPORTED;
1183 } else {
1184 if (EFI_ERROR (Status1) && EFI_ERROR (Status2)) {
1185 FreePool ((VOID *)Instance);
1186 DEBUG ((DEBUG_ERROR, "%a:Something wrong on Redfish service discovery Status1=%x, Status2=%x.\n", __FUNCTION__, Status1, Status2));
1187 } else {
1188 if (NewInstance) {
1189 InsertTailList (&mRedfishDiscoverList, &Instance->Entry);
1190 }
1191 }
1192 }
1193
1194 if (TargetNetworkInterface == NULL) {
1195 //
1196 // Discover Redfish services on all of network interfaces.
1197 //
1198 TargetNetworkInterfaceInternal = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode (&mEfiRedfishDiscoverNetworkInterface, &TargetNetworkInterfaceInternal->Entry);
1199 }
1200 }
1201
1202 return EFI_SUCCESS;
1203 }
1204
1205 /**
1206 This function aborts Redfish service discovery on the given network interface.
1207
1208 @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instance.
1209 @param[in] TargetNetworkInterface Target network interface to do the discovery.
1210
1211 @retval EFI_SUCCESS REST EX instance of discovered Redfish services are returned.
1212 @retval Others Fail to abort Redfish service discovery.
1213
1214 **/
1215 EFI_STATUS
1216 EFIAPI
1217 RedfishServiceAbortAcquire (
1218 IN EFI_REDFISH_DISCOVER_PROTOCOL *This,
1219 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *TargetNetworkInterface OPTIONAL
1220 )
1221 {
1222 // This function is used to abort Redfish service discovery through SSDP
1223 // on the network interface. SSDP is optionally supprted by EFI_REDFISH_DISCOVER_PROTOCOL,
1224 // we dont have implementation for SSDP now.
1225
1226 return EFI_UNSUPPORTED;
1227 }
1228
1229 /**
1230 This function releases Redfish services found by RedfishServiceAcquire().
1231
1232 @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instance.
1233 @param[in] InstanceList The Redfish service to release.
1234
1235 @retval EFI_SUCCESS REST EX instances of discovered Redfish are released.
1236 @retval Others Fail to remove the entry
1237
1238 **/
1239 EFI_STATUS
1240 EFIAPI
1241 RedfishServiceReleaseService (
1242 IN EFI_REDFISH_DISCOVER_PROTOCOL *This,
1243 IN EFI_REDFISH_DISCOVERED_LIST *InstanceList
1244 )
1245 {
1246 UINTN NumService;
1247 BOOLEAN AnyFailRelease;
1248 EFI_REDFISH_DISCOVERED_INSTANCE *ThisRedfishInstance;
1249 EFI_REDFISH_DISCOVERED_INTERNAL_LIST *DiscoveredRedfishInstance;
1250
1251 if (IsListEmpty (&mRedfishInstanceList)) {
1252 DEBUG ((DEBUG_ERROR, "%a:No any discovered Redfish service.\n", __FUNCTION__));
1253 return EFI_NOT_FOUND;
1254 }
1255
1256 AnyFailRelease = FALSE;
1257 ThisRedfishInstance = InstanceList->RedfishInstances;
1258 for (NumService = 0; NumService < InstanceList->NumberOfServiceFound; NumService++) {
1259 DiscoveredRedfishInstance = (EFI_REDFISH_DISCOVERED_INTERNAL_LIST *)GetFirstNode (&mRedfishInstanceList);
1260 do {
1261 if (DiscoveredRedfishInstance->Instance == ThisRedfishInstance) {
1262 RemoveEntryList (&DiscoveredRedfishInstance->NextInstance);
1263 if (ThisRedfishInstance->Information.Location != NULL) {
1264 FreePool (ThisRedfishInstance->Information.Location);
1265 }
1266
1267 if (ThisRedfishInstance->Information.Uuid != NULL) {
1268 FreePool (ThisRedfishInstance->Information.Uuid);
1269 }
1270
1271 if (ThisRedfishInstance->Information.Os != NULL) {
1272 FreePool (ThisRedfishInstance->Information.Os);
1273 }
1274
1275 if (ThisRedfishInstance->Information.OsVersion != NULL) {
1276 FreePool (ThisRedfishInstance->Information.OsVersion);
1277 }
1278
1279 if (ThisRedfishInstance->Information.Product != NULL) {
1280 FreePool (ThisRedfishInstance->Information.Product);
1281 }
1282
1283 if (ThisRedfishInstance->Information.ProductVer != NULL) {
1284 FreePool (ThisRedfishInstance->Information.ProductVer);
1285 }
1286
1287 FreePool ((VOID *)ThisRedfishInstance);
1288 goto ReleaseNext;
1289 }
1290
1291 if (IsNodeAtEnd (&mRedfishInstanceList, &DiscoveredRedfishInstance->NextInstance)) {
1292 break;
1293 }
1294
1295 DiscoveredRedfishInstance = (EFI_REDFISH_DISCOVERED_INTERNAL_LIST *)GetNextNode (&mRedfishInstanceList, &DiscoveredRedfishInstance->NextInstance);
1296 } while (TRUE);
1297
1298 AnyFailRelease = TRUE;
1299 ReleaseNext:;
1300 //
1301 // Release next discovered Redfish Service.
1302 //
1303 ThisRedfishInstance = (EFI_REDFISH_DISCOVERED_INSTANCE *)((UINT8 *)ThisRedfishInstance + sizeof (EFI_REDFISH_DISCOVERED_INSTANCE));
1304 }
1305
1306 if (AnyFailRelease) {
1307 return EFI_NOT_FOUND;
1308 } else {
1309 return EFI_SUCCESS;
1310 }
1311 }
1312
1313 EFI_REDFISH_DISCOVER_PROTOCOL mRedfishDiscover = {
1314 RedfishServiceGetNetworkInterface,
1315 RedfishServiceAcquireService,
1316 RedfishServiceAbortAcquire,
1317 RedfishServiceReleaseService
1318 };
1319
1320 /**
1321 This function create an EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL for the
1322 given network interface.
1323
1324
1325 @param[in] ControllerHandle MAC address of this network interface.
1326 @param[in] NetworkProtocolType Network protocol type.
1327 @param[out] IsNewInstance BOOLEAN means new instance or not.
1328 @param[out] NetworkInterface Pointer to to EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL.
1329
1330 @retval EFI_STATUS
1331 **/
1332 EFI_STATUS
1333 CreateRedfishDiscoverNetworkInterface (
1334 IN EFI_HANDLE ControllerHandle,
1335 IN UINT32 NetworkProtocolType,
1336 OUT BOOLEAN *IsNewInstance,
1337 OUT EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL **NetworkInterface
1338 )
1339 {
1340 EFI_MAC_ADDRESS MacAddress;
1341 UINTN HwAddressSize;
1342 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterface;
1343 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *NewNetworkInterface;
1344
1345 NetLibGetMacAddress (ControllerHandle, &MacAddress, &HwAddressSize);
1346 NewNetworkInterface = NULL;
1347 *IsNewInstance = TRUE;
1348 if (!IsListEmpty ((const LIST_ENTRY *)&mEfiRedfishDiscoverNetworkInterface)) {
1349 //
1350 // Check if this instance already exist.
1351 //
1352 ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface);
1353 if (ThisNetworkInterface != NULL) {
1354 while (TRUE) {
1355 if ((CompareMem ((CONST VOID *)&ThisNetworkInterface->MacAddress.Addr, (CONST VOID *)&MacAddress.Addr, HwAddressSize) == 0) &&
1356 (ThisNetworkInterface->NetworkProtocolType == NetworkProtocolType))
1357 {
1358 NewNetworkInterface = ThisNetworkInterface;
1359 *IsNewInstance = FALSE;
1360 break;
1361 }
1362
1363 if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry)) {
1364 NewNetworkInterface = NULL;
1365 break;
1366 }
1367
1368 ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry);
1369 }
1370 }
1371 }
1372
1373 if (NewNetworkInterface == NULL) {
1374 //
1375 // Create a new instance.
1376 //
1377 NewNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL));
1378 if (NewNetworkInterface == NULL) {
1379 return EFI_OUT_OF_RESOURCES;
1380 }
1381
1382 NewNetworkInterface->HwAddressSize = HwAddressSize;
1383 CopyMem (&NewNetworkInterface->MacAddress.Addr, &MacAddress.Addr, NewNetworkInterface->HwAddressSize);
1384 NetLibGetMacString (ControllerHandle, NULL, &NewNetworkInterface->StrMacAddr);
1385 NewNetworkInterface->VlanId = NetLibGetVlanId (ControllerHandle);
1386 }
1387
1388 *NetworkInterface = NewNetworkInterface;
1389 return EFI_SUCCESS;
1390 }
1391
1392 /**
1393 This function destory network interface
1394
1395
1396 @param[in] ThisNetworkInterface EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL instance.
1397
1398 @retval EFI_STATUS
1399 **/
1400 EFI_STATUS
1401 DestroyRedfishNetwrokInterface (
1402 IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterface
1403 )
1404 {
1405 EFI_STATUS Status;
1406
1407 Status = gBS->UninstallProtocolInterface (
1408 ThisNetworkInterface->OpenDriverControllerHandle,
1409 gRequiredProtocol[ThisNetworkInterface->NetworkProtocolType].DiscoveredProtocolGuid,
1410 &ThisNetworkInterface->NetworkInterfaceProtocolInfo.ProtocolDiscoverId
1411 );
1412 RemoveEntryList (&ThisNetworkInterface->Entry);
1413 mNumNetworkInterface--;
1414 FreePool (ThisNetworkInterface);
1415 return Status;
1416 }
1417
1418 /**
1419 Tests to see if the required protocols are provided on the given
1420 controller handle.
1421
1422 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1423 @param[in] ControllerHandle The handle of the controller to test. This handle
1424 must support a protocol interface that supplies
1425 an I/O abstraction to the driver.
1426 @retval EFI_SUCCESS One of required protocol is found.
1427 @retval EFI_UNSUPPORTED None of required protocol is found.
1428 **/
1429 EFI_STATUS
1430 TestForRequiredProtocols (
1431 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1432 IN EFI_HANDLE ControllerHandle
1433 )
1434 {
1435 UINT32 Id;
1436 UINTN Index;
1437 EFI_STATUS Status;
1438
1439 for (Index = 0; Index < (sizeof (gRequiredProtocol) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL)); Index++) {
1440 Status = gBS->OpenProtocol (
1441 ControllerHandle,
1442 gRequiredProtocol[Index].RequiredServiceBindingProtocolGuid,
1443 NULL,
1444 This->DriverBindingHandle,
1445 ControllerHandle,
1446 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
1447 );
1448 if (!EFI_ERROR (Status)) {
1449 Status = gBS->OpenProtocol (
1450 ControllerHandle,
1451 gRequiredProtocol[Index].DiscoveredProtocolGuid,
1452 (VOID **)&Id,
1453 This->DriverBindingHandle,
1454 ControllerHandle,
1455 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1456 );
1457 if (EFI_ERROR (Status)) {
1458 DEBUG ((DEBUG_ERROR, "%a: %s is found on this controller handle.\n", __FUNCTION__, gRequiredProtocol[Index].ProtocolName));
1459 return EFI_SUCCESS;
1460 }
1461 }
1462 }
1463
1464 return EFI_UNSUPPORTED;
1465 }
1466
1467 /**
1468 Build up network interface and create corresponding service through the given
1469 controller handle.
1470
1471 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1472 @param[in] ControllerHandle The handle of the controller to test. This handle
1473 must support a protocol interface that supplies
1474 an I/O abstraction to the driver.
1475 @retval EFI_SUCCESS One of required protocol is found.
1476 @retval EFI_UNSUPPORTED None of required protocol is found.
1477 @retval EFI_UNSUPPORTED Failed to build up network interface.
1478 **/
1479 EFI_STATUS
1480 BuildupNetworkInterface (
1481 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1482 IN EFI_HANDLE ControllerHandle
1483 )
1484 {
1485 UINT32 Id;
1486 UINT32 Index;
1487 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *NetworkInterface;
1488 BOOLEAN IsNew;
1489 EFI_STATUS Status;
1490 VOID *TempInterface;
1491 VOID **Interface;
1492 UINT32 *ProtocolDiscoverIdPtr;
1493 EFI_HANDLE OpenDriverAgentHandle;
1494 EFI_HANDLE OpenDriverControllerHandle;
1495 EFI_HANDLE *HandleOfProtocolInterfacePtr;
1496 EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL *RestExInstance;
1497 EFI_TPL OldTpl;
1498 BOOLEAN NewNetworkInterfaceInstalled;
1499
1500 NewNetworkInterfaceInstalled = FALSE;
1501 Index = 0;
1502 do {
1503 Status = gBS->OpenProtocol (
1504 // Already in list?
1505 ControllerHandle,
1506 gRequiredProtocol[Index].DiscoveredProtocolGuid,
1507 (VOID **)&Id,
1508 This->DriverBindingHandle,
1509 ControllerHandle,
1510 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1511 );
1512 if (!EFI_ERROR (Status)) {
1513 Index++;
1514 if (Index == (sizeof (gRequiredProtocol) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL))) {
1515 break;
1516 }
1517
1518 continue;
1519 }
1520
1521 Status = gBS->OpenProtocol (
1522 ControllerHandle,
1523 gRequiredProtocol[Index].RequiredServiceBindingProtocolGuid,
1524 &TempInterface,
1525 This->DriverBindingHandle,
1526 ControllerHandle,
1527 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1528 );
1529 if (EFI_ERROR (Status)) {
1530 Index++;
1531 if (Index == (sizeof (gRequiredProtocol) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL))) {
1532 break;
1533 }
1534
1535 continue;
1536 }
1537
1538 if (gRequiredProtocol[Index].ProtocolType != ProtocolTypeRestEx) {
1539 OldTpl = gBS->RaiseTPL (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL);
1540 Status = CreateRedfishDiscoverNetworkInterface (ControllerHandle, gRequiredProtocol[Index].ProtocolType, &IsNew, &NetworkInterface);
1541 if (EFI_ERROR (Status)) {
1542 gBS->RestoreTPL (OldTpl);
1543 return Status;
1544 }
1545
1546 NetworkInterface->NetworkProtocolType = gRequiredProtocol[Index].ProtocolType;
1547 NetworkInterface->OpenDriverAgentHandle = This->DriverBindingHandle;
1548 NetworkInterface->OpenDriverControllerHandle = ControllerHandle;
1549 NetworkInterface->NetworkInterfaceProtocolInfo.ProtocolGuid = \
1550 *gRequiredProtocol[Index].RequiredProtocolGuid;
1551 NetworkInterface->NetworkInterfaceProtocolInfo.ProtocolServiceGuid = \
1552 *gRequiredProtocol[Index].RequiredServiceBindingProtocolGuid;
1553 ProtocolDiscoverIdPtr = &NetworkInterface->NetworkInterfaceProtocolInfo.ProtocolDiscoverId;
1554 OpenDriverAgentHandle = NetworkInterface->OpenDriverAgentHandle;
1555 OpenDriverControllerHandle = NetworkInterface->OpenDriverControllerHandle;
1556 HandleOfProtocolInterfacePtr = &NetworkInterface->NetworkInterfaceProtocolInfo.ProtocolControllerHandle;
1557 Interface = &NetworkInterface->NetworkInterfaceProtocolInfo.NetworkProtocolInterface;
1558 NewNetworkInterfaceInstalled = TRUE;
1559 if (IsNew) {
1560 InsertTailList (&mEfiRedfishDiscoverNetworkInterface, &NetworkInterface->Entry);
1561 mNumNetworkInterface++;
1562 }
1563
1564 gBS->RestoreTPL (OldTpl);
1565 } else {
1566 // Record REST_EX instance. REST_EX is created when clinet asks for Redfish service discovery.
1567 // Redfish Service Discover protocol will match REST EX to the corresponding EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
1568 // when discovery.
1569
1570 RestExInstance = (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL *)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL));
1571 if (RestExInstance == NULL) {
1572 return EFI_OUT_OF_RESOURCES;
1573 }
1574
1575 RestExInstance->OpenDriverAgentHandle = This->DriverBindingHandle;
1576 RestExInstance->OpenDriverControllerHandle = ControllerHandle;
1577 RestExInstance->RestExControllerHandle = ControllerHandle;
1578 InitializeListHead (&RestExInstance->Entry);
1579 InsertTailList (&mEfiRedfishDiscoverRestExInstance, &RestExInstance->Entry);
1580 mNumRestExInstance++;
1581 ProtocolDiscoverIdPtr = &RestExInstance->RestExId;
1582 OpenDriverAgentHandle = RestExInstance->OpenDriverAgentHandle;
1583 OpenDriverControllerHandle = RestExInstance->OpenDriverControllerHandle;
1584 HandleOfProtocolInterfacePtr = &RestExInstance->RestExChildHandle;
1585 Interface = (VOID **)&RestExInstance->RestExProtocolInterface;
1586 }
1587
1588 Status = gBS->InstallProtocolInterface (
1589 &ControllerHandle,
1590 gRequiredProtocol[Index].DiscoveredProtocolGuid,
1591 EFI_NATIVE_INTERFACE,
1592 ProtocolDiscoverIdPtr
1593 );
1594 if (EFI_ERROR (Status)) {
1595 Index++;
1596 if (Index == (sizeof (gRequiredProtocol) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL))) {
1597 break;
1598 }
1599
1600 continue;
1601 }
1602
1603 //
1604 // Create service binding child and open it BY_DRIVER.
1605 //
1606 Status = NetLibCreateServiceChild (
1607 ControllerHandle,
1608 This->ImageHandle,
1609 gRequiredProtocol[Index].RequiredServiceBindingProtocolGuid,
1610 HandleOfProtocolInterfacePtr
1611 );
1612 if (!EFI_ERROR (Status)) {
1613 Status = gBS->OpenProtocol (
1614 *HandleOfProtocolInterfacePtr,
1615 gRequiredProtocol[Index].RequiredProtocolGuid,
1616 Interface,
1617 OpenDriverAgentHandle,
1618 OpenDriverControllerHandle,
1619 EFI_OPEN_PROTOCOL_BY_DRIVER
1620 );
1621 if (!EFI_ERROR (Status)) {
1622 if ((EfiRedfishDiscoverProtocolHandle == NULL) &&
1623 (gRequiredProtocol[Index].ProtocolType == ProtocolTypeRestEx) &&
1624 !IsListEmpty (&mEfiRedfishDiscoverNetworkInterface)
1625 )
1626 {
1627 // Install the fisrt Redfish Discover Protocol when EFI REST EX protcol is discovered.
1628 // This ensures EFI REST EX is ready while EFI_REDFISH_DISCOVER_PROTOCOL consumer acquires
1629 // Redfish serivce over network interface.
1630
1631 Status = gBS->InstallProtocolInterface (
1632 &EfiRedfishDiscoverProtocolHandle,
1633 &gEfiRedfishDiscoverProtocolGuid,
1634 EFI_NATIVE_INTERFACE,
1635 (VOID *)&mRedfishDiscover
1636 );
1637 } else if ((EfiRedfishDiscoverProtocolHandle != NULL) && NewNetworkInterfaceInstalled) {
1638 Status = gBS->ReinstallProtocolInterface (
1639 EfiRedfishDiscoverProtocolHandle,
1640 &gEfiRedfishDiscoverProtocolGuid,
1641 (VOID *)&mRedfishDiscover,
1642 (VOID *)&mRedfishDiscover
1643 );
1644 NewNetworkInterfaceInstalled = FALSE;
1645 }
1646 }
1647
1648 return Status;
1649 } else {
1650 Index++;
1651 if (Index == (sizeof (gRequiredProtocol) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL))) {
1652 break;
1653 }
1654
1655 continue;
1656 }
1657 } while (Index < (sizeof (gRequiredProtocol) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL)));
1658
1659 return EFI_UNSUPPORTED;
1660 }
1661
1662 /**
1663 Close the protocol opened for Redfish discovery. This function also destories
1664 the network services.
1665
1666 @param[in] ThisBindingProtocol A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1667 @param[in] ControllerHandle The handle of the controller to test. This handle
1668 must support a protocol interface that supplies
1669 an I/O abstraction to the driver.
1670 @param[in] ThisRequiredProtocol Pointer to the instance of REDFISH_DISCOVER_REQUIRED_PROTOCOL.
1671 @param[in] DriverAgentHandle Driver agent handle which used to open protocol earlier.
1672 @param[in] DriverControllerHandle Driver controller handle which used to open protocol earlier.
1673
1674 @retval EFI_SUCCESS Prorocol is closed successfully.
1675 @retval Others Prorocol is closed unsuccessfully.
1676
1677 **/
1678 EFI_STATUS
1679 CloseProtocolService (
1680 IN EFI_DRIVER_BINDING_PROTOCOL *ThisBindingProtocol,
1681 IN EFI_HANDLE ControllerHandle,
1682 IN REDFISH_DISCOVER_REQUIRED_PROTOCOL *ThisRequiredProtocol,
1683 IN EFI_HANDLE DriverAgentHandle,
1684 IN EFI_HANDLE DriverControllerHandle
1685 )
1686 {
1687 EFI_STATUS Status;
1688
1689 Status = gBS->CloseProtocol (
1690 ControllerHandle,
1691 ThisRequiredProtocol->RequiredProtocolGuid,
1692 DriverAgentHandle,
1693 DriverControllerHandle
1694 );
1695 if (!EFI_ERROR (Status)) {
1696 NetLibDestroyServiceChild (
1697 ControllerHandle,
1698 ThisBindingProtocol->ImageHandle,
1699 ThisRequiredProtocol->RequiredServiceBindingProtocolGuid,
1700 ControllerHandle
1701 );
1702 }
1703
1704 return Status;
1705 }
1706
1707 /**
1708 Stop the services on network interface.
1709
1710 @param[in] ThisBindingProtocol A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1711 @param[in] ControllerHandle The handle of the controller to test. This handle
1712 must support a protocol interface that supplies
1713 an I/O abstraction to the driver.
1714 @retval EFI_SUCCESS One of required protocol is found.
1715 @retval Others Faile to stop the services on network interface.
1716 **/
1717 EFI_STATUS
1718 StopServiceOnNetworkInterface (
1719 IN EFI_DRIVER_BINDING_PROTOCOL *ThisBindingProtocol,
1720 IN EFI_HANDLE ControllerHandle
1721 )
1722 {
1723 UINT32 Index;
1724 EFI_STATUS Status;
1725 VOID *Interface;
1726 EFI_TPL OldTpl;
1727 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterface;
1728 EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL *RestExInstance;
1729
1730 for (Index = 0; Index < (sizeof (gRequiredProtocol) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL)); Index++) {
1731 Status = gBS->HandleProtocol (
1732 ControllerHandle,
1733 gRequiredProtocol[Index].RequiredProtocolGuid,
1734 (VOID **)&Interface
1735 );
1736 if (!EFI_ERROR (Status)) {
1737 if (gRequiredProtocol[Index].ProtocolType != ProtocolTypeRestEx) {
1738 if (IsListEmpty (&mEfiRedfishDiscoverNetworkInterface)) {
1739 return EFI_NOT_FOUND;
1740 }
1741
1742 OldTpl = gBS->RaiseTPL (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL);
1743 ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface);
1744 while (TRUE) {
1745 if (ThisNetworkInterface->NetworkInterfaceProtocolInfo.ProtocolControllerHandle == ControllerHandle) {
1746 Status = CloseProtocolService (
1747 // Close protocol and destroy service.
1748 ThisBindingProtocol,
1749 ControllerHandle,
1750 &gRequiredProtocol[Index],
1751 ThisNetworkInterface->OpenDriverAgentHandle,
1752 ThisNetworkInterface->OpenDriverControllerHandle
1753 );
1754 if (!EFI_ERROR (Status)) {
1755 Status = DestroyRedfishNetwrokInterface (ThisNetworkInterface);
1756 }
1757
1758 gBS->RestoreTPL (OldTpl);
1759 // Reinstall Redfish Discover protocol to notify network
1760 // interface change.
1761
1762 Status = gBS->ReinstallProtocolInterface (
1763 EfiRedfishDiscoverProtocolHandle,
1764 &gEfiRedfishDiscoverProtocolGuid,
1765 (VOID *)&mRedfishDiscover,
1766 (VOID *)&mRedfishDiscover
1767 );
1768 if (EFI_ERROR (Status)) {
1769 DEBUG ((DEBUG_ERROR, "%a: Reinstall gEfiRedfishDiscoverProtocolGuid fail.", __FUNCTION__));
1770 }
1771
1772 return Status;
1773 }
1774
1775 if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry)) {
1776 break;
1777 }
1778
1779 ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry);
1780 }
1781
1782 gBS->RestoreTPL (OldTpl);
1783 } else {
1784 if (IsListEmpty (&mEfiRedfishDiscoverRestExInstance)) {
1785 return EFI_NOT_FOUND;
1786 }
1787
1788 OldTpl = gBS->RaiseTPL (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL);
1789 RestExInstance = (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverRestExInstance);
1790 while (TRUE) {
1791 if (RestExInstance->RestExChildHandle == ControllerHandle) {
1792 Status = CloseProtocolService (
1793 // Close REST_EX protocol.
1794 ThisBindingProtocol,
1795 ControllerHandle,
1796 &gRequiredProtocol[Index],
1797 RestExInstance->OpenDriverAgentHandle,
1798 RestExInstance->OpenDriverControllerHandle
1799 );
1800 RemoveEntryList (&RestExInstance->Entry);
1801 FreePool ((VOID *)RestExInstance);
1802 mNumRestExInstance--;
1803 gBS->RestoreTPL (OldTpl);
1804 return Status;
1805 }
1806
1807 if (IsNodeAtEnd (&mEfiRedfishDiscoverRestExInstance, &RestExInstance->Entry)) {
1808 break;
1809 }
1810
1811 RestExInstance = (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL *)GetNextNode (&mEfiRedfishDiscoverRestExInstance, &RestExInstance->Entry);
1812 }
1813
1814 gBS->RestoreTPL (OldTpl);
1815 }
1816 }
1817 }
1818
1819 return EFI_NOT_FOUND;
1820 }
1821
1822 /**
1823 Tests to see if this driver supports a given controller. If a child device is provided,
1824 it further tests to see if this driver supports creating a handle for the specified child device.
1825
1826 This function checks to see if the driver specified by This supports the device specified by
1827 ControllerHandle. Drivers will typically use the device path attached to
1828 ControllerHandle and/or the services from the bus I/O abstraction attached to
1829 ControllerHandle to determine if the driver supports ControllerHandle. This function
1830 may be called many times during platform initialization. In order to reduce boot times, the tests
1831 performed by this function must be very small, and take as little time as possible to execute. This
1832 function must not change the state of any hardware devices, and this function must be aware that the
1833 device specified by ControllerHandle may already be managed by the same driver or a
1834 different driver. This function must match its calls to AllocatePages() with FreePages(),
1835 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
1836 Because ControllerHandle may have been previously started by the same driver, if a protocol is
1837 already in the opened state, then it must not be closed with CloseProtocol(). This is required
1838 to guarantee the state of ControllerHandle is not modified by this function.
1839
1840 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1841 @param[in] ControllerHandle The handle of the controller to test. This handle
1842 must support a protocol interface that supplies
1843 an I/O abstraction to the driver.
1844 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
1845 parameter is ignored by device drivers, and is optional for bus
1846 drivers. For bus drivers, if this parameter is not NULL, then
1847 the bus driver must determine if the bus controller specified
1848 by ControllerHandle and the child controller specified
1849 by RemainingDevicePath are both supported by this
1850 bus driver.
1851
1852 @retval EFI_SUCCESS The device specified by ControllerHandle and
1853 RemainingDevicePath is supported by the driver specified by This.
1854 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
1855 RemainingDevicePath is already being managed by the driver
1856 specified by This.
1857 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
1858 RemainingDevicePath is already being managed by a different
1859 driver or an application that requires exclusive access.
1860 Currently not implemented.
1861 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
1862 RemainingDevicePath is not supported by the driver specified by This.
1863 **/
1864 EFI_STATUS
1865 EFIAPI
1866 RedfishDiscoverDriverBindingSupported (
1867 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1868 IN EFI_HANDLE ControllerHandle,
1869 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
1870 )
1871 {
1872 return TestForRequiredProtocols (This, ControllerHandle);
1873 }
1874
1875 /**
1876 Starts a device controller or a bus controller.
1877
1878 The Start() function is designed to be invoked from the EFI boot service ConnectController().
1879 As a result, much of the error checking on the parameters to Start() has been moved into this
1880 common boot service. It is legal to call Start() from other locations,
1881 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
1882 1. ControllerHandle must be a valid EFI_HANDLE.
1883 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
1884 EFI_DEVICE_PATH_PROTOCOL.
1885 3. Prior to calling Start(), the Supported() function for the driver specified by This must
1886 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
1887
1888 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1889 @param[in] ControllerHandle The handle of the controller to start. This handle
1890 must support a protocol interface that supplies
1891 an I/O abstraction to the driver.
1892 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
1893 parameter is ignored by device drivers, and is optional for bus
1894 drivers. For a bus driver, if this parameter is NULL, then handles
1895 for all the children of Controller are created by this driver.
1896 If this parameter is not NULL and the first Device Path Node is
1897 not the End of Device Path Node, then only the handle for the
1898 child device specified by the first Device Path Node of
1899 RemainingDevicePath is created by this driver.
1900 If the first Device Path Node of RemainingDevicePath is
1901 the End of Device Path Node, no child handle is created by this
1902 driver.
1903
1904 @retval EFI_SUCCESS The device was started.
1905 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
1906 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1907 @retval Others The driver failded to start the device.
1908
1909 **/
1910 EFI_STATUS
1911 EFIAPI
1912 RedfishDiscoverDriverBindingStart (
1913 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1914 IN EFI_HANDLE ControllerHandle,
1915 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
1916 )
1917 {
1918 return BuildupNetworkInterface (This, ControllerHandle);
1919 }
1920
1921 /**
1922 Stops a device controller or a bus controller.
1923
1924 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
1925 As a result, much of the error checking on the parameters to Stop() has been moved
1926 into this common boot service. It is legal to call Stop() from other locations,
1927 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
1928 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
1929 same driver's Start() function.
1930 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
1931 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
1932 Start() function, and the Start() function must have called OpenProtocol() on
1933 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
1934
1935 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1936 @param[in] ControllerHandle A handle to the device being stopped. The handle must
1937 support a bus specific I/O protocol for the driver
1938 to use to stop the device.
1939 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
1940 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
1941 if NumberOfChildren is 0.
1942
1943 @retval EFI_SUCCESS The device was stopped.
1944 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
1945
1946 **/
1947 EFI_STATUS
1948 EFIAPI
1949 RedfishDiscoverDriverBindingStop (
1950 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1951 IN EFI_HANDLE ControllerHandle,
1952 IN UINTN NumberOfChildren,
1953 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
1954 )
1955 {
1956 return StopServiceOnNetworkInterface (This, ControllerHandle);
1957 }
1958
1959 EFI_DRIVER_BINDING_PROTOCOL gRedfishDiscoverDriverBinding = {
1960 RedfishDiscoverDriverBindingSupported,
1961 RedfishDiscoverDriverBindingStart,
1962 RedfishDiscoverDriverBindingStop,
1963 REDFISH_DISCOVER_VERSION,
1964 NULL,
1965 NULL
1966 };
1967
1968 /**
1969 This is the declaration of an EFI image entry point.
1970
1971 @param ImageHandle The firmware allocated handle for the UEFI image.
1972 @param SystemTable A pointer to the EFI System Table.
1973
1974 @retval EFI_SUCCESS The operation completed successfully.
1975 @retval Others An unexpected error occurred.
1976 **/
1977 EFI_STATUS
1978 EFIAPI
1979 RedfishDiscoverEntryPoint (
1980 IN EFI_HANDLE ImageHandle,
1981 IN EFI_SYSTEM_TABLE *SystemTable
1982 )
1983 {
1984 EFI_STATUS Status;
1985
1986 Status = EFI_SUCCESS;
1987 InitializeListHead (&mRedfishDiscoverList);
1988 InitializeListHead (&mRedfishInstanceList);
1989 InitializeListHead (&mEfiRedfishDiscoverNetworkInterface);
1990 InitializeListHead (&mEfiRedfishDiscoverRestExInstance);
1991 //
1992 // Install binding protoocl to obtain UDP and REST EX protocol.
1993 //
1994 Status = EfiLibInstallDriverBindingComponentName2 (
1995 ImageHandle,
1996 SystemTable,
1997 &gRedfishDiscoverDriverBinding,
1998 ImageHandle,
1999 &gRedfishDiscoverComponentName,
2000 &gRedfishDiscoverComponentName2
2001 );
2002 return Status;
2003 }
2004
2005 /**
2006 This is the unload handle for Redfish discover module.
2007
2008 Disconnect the driver specified by ImageHandle from all the devices in the handle database.
2009 Uninstall all the protocols installed in the driver entry point.
2010
2011 @param[in] ImageHandle The drivers' driver image.
2012
2013 @retval EFI_SUCCESS The image is unloaded.
2014 @retval Others Failed to unload the image.
2015
2016 **/
2017 EFI_STATUS
2018 EFIAPI
2019 RedfishDiscoverUnload (
2020 IN EFI_HANDLE ImageHandle
2021 )
2022 {
2023 EFI_STATUS Status;
2024 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterface;
2025
2026 Status = EFI_SUCCESS;
2027 // Destroy all network interfaces found by EFI Redfish Discover driver and
2028 // stop services created for Redfish Discover.
2029
2030 while (!IsListEmpty (&mEfiRedfishDiscoverNetworkInterface)) {
2031 ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface);
2032 StopServiceOnNetworkInterface (&gRedfishDiscoverDriverBinding, ThisNetworkInterface->NetworkInterfaceProtocolInfo.ProtocolControllerHandle);
2033 }
2034
2035 // Disconnect EFI Redfish discover driver controller to notify the
2036 // clinet which uses .EFI Redfish discover protocol.
2037
2038 if (EfiRedfishDiscoverProtocolHandle != NULL) {
2039 //
2040 // Notify user EFI_REDFISH_DISCOVER_PROTOCOL is unloaded.
2041 //
2042 gBS->DisconnectController (EfiRedfishDiscoverProtocolHandle, NULL, NULL);
2043 Status = gBS->UninstallProtocolInterface (
2044 EfiRedfishDiscoverProtocolHandle,
2045 &gEfiRedfishDiscoverProtocolGuid,
2046 (VOID *)&mRedfishDiscover
2047 );
2048 }
2049
2050 return Status;
2051 }