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