VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.c@ 105668

最後變更 在這個檔案從105668是 101291,由 vboxsync 提交於 18 月 前

EFI/FirmwareNew: Make edk2-stable202308 build on all supported platforms (using gcc at least, msvc not tested yet), bugref:4643

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

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