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