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