]>
Commit | Line | Data |
---|---|---|
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 |
13 | LIST_ENTRY mRedfishDiscoverList;\r |
14 | LIST_ENTRY mRedfishInstanceList;\r | |
15 | EFI_SMBIOS_PROTOCOL *mSmbios = NULL;\r | |
7e7b729f | 16 | \r |
39de741e MK |
17 | UINTN mNumNetworkInterface = 0;\r |
18 | UINTN mNumRestExInstance = 0;\r | |
19 | LIST_ENTRY mEfiRedfishDiscoverNetworkInterface;\r | |
20 | LIST_ENTRY mEfiRedfishDiscoverRestExInstance;\r | |
7e7b729f | 21 | \r |
39de741e MK |
22 | EFI_GUID mRedfishDiscoverTcp4InstanceGuid = EFI_REDFISH_DISCOVER_TCP4_INSTANCE_GUID;\r |
23 | EFI_GUID mRedfishDiscoverTcp6InstanceGuid = EFI_REDFISH_DISCOVER_TCP6_INSTANCE_GUID;\r | |
24 | EFI_GUID mRedfishDiscoverRestExInstanceGuid = EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_GUID;\r | |
7e7b729f | 25 | \r |
39de741e | 26 | EFI_HANDLE EfiRedfishDiscoverProtocolHandle = NULL;\r |
7e7b729f AC |
27 | \r |
28 | EFI_STATUS\r | |
29 | EFIAPI\r | |
30 | Tcp4GetSubnetInfo (\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 |
35 | EFI_STATUS\r | |
36 | EFIAPI\r | |
37 | Tcp6GetSubnetInfo (\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 | 42 | static 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 | |
80 | EFI_STATUS\r | |
81 | CreateRestExInstance (\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 | |
110 | EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *\r | |
111 | GetInstanceByOwner (\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 | |
152 | EFI_STATUS\r | |
153 | EFIAPI\r | |
154 | Tcp4GetSubnetInfo (\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 | |
248 | EFI_STATUS\r | |
249 | EFIAPI\r | |
250 | Tcp6GetSubnetInfo (\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 | |
305 | EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *\r | |
306 | GetTargetNetworkInterfaceInternal (\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 | |
339 | EFI_STATUS\r | |
340 | ValidateTargetNetworkInterface (\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 | |
387 | UINTN\r | |
39de741e MK |
388 | NumberOfNetworkInterface (\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 | |
422 | BOOLEAN\r | |
423 | CheckIsIpVersion6 (\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 | |
443 | EFI_STATUS\r | |
39de741e MK |
444 | DiscoverRedfishHostInterface (\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 | |
587 | EFI_STATUS\r | |
588 | AddAndSignalNewRedfishService (\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 | |
857 | EXIT_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 | |
862 | EXIT_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 | 876 | ERROR_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 |
886 | ON_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 | |
900 | EFI_STATUS\r | |
901 | NetworkInterfaceGetSubnetInfo (\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 | |
1010 | EFI_STATUS\r | |
1011 | EFIAPI\r | |
1012 | RedfishServiceGetNetworkInterface (\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 | |
1092 | EFI_STATUS\r | |
1093 | EFIAPI\r | |
1094 | RedfishServiceAcquireService (\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 | |
1215 | EFI_STATUS\r | |
1216 | EFIAPI\r | |
1217 | RedfishServiceAbortAcquire (\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 | |
1239 | EFI_STATUS\r | |
1240 | EFIAPI\r | |
1241 | RedfishServiceReleaseService (\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 |
1299 | ReleaseNext:;\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 | 1313 | EFI_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 | |
1332 | EFI_STATUS\r | |
1333 | CreateRedfishDiscoverNetworkInterface (\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 | |
1400 | EFI_STATUS\r | |
1401 | DestroyRedfishNetwrokInterface (\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 | |
1429 | EFI_STATUS\r | |
1430 | TestForRequiredProtocols (\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 | |
1479 | EFI_STATUS\r | |
1480 | BuildupNetworkInterface (\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 | |
1678 | EFI_STATUS\r | |
1679 | CloseProtocolService (\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 | |
1717 | EFI_STATUS\r | |
1718 | StopServiceOnNetworkInterface (\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 | |
1864 | EFI_STATUS\r | |
1865 | EFIAPI\r | |
1866 | RedfishDiscoverDriverBindingSupported (\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 | |
1910 | EFI_STATUS\r | |
1911 | EFIAPI\r | |
1912 | RedfishDiscoverDriverBindingStart (\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 | |
1947 | EFI_STATUS\r | |
1948 | EFIAPI\r | |
1949 | RedfishDiscoverDriverBindingStop (\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 | 1959 | EFI_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 | |
1977 | EFI_STATUS\r | |
1978 | EFIAPI\r | |
1979 | RedfishDiscoverEntryPoint (\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 | |
2017 | EFI_STATUS\r | |
2018 | EFIAPI\r | |
2019 | RedfishDiscoverUnload (\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 |