VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.c@ 106655

Last change on this file since 106655 was 105670, checked in by vboxsync, 6 months ago

Devices/EFI/FirmwareNew: Merge edk2-stable-202405 and make it build on aarch64, bugref:4643

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette