]> git.proxmox.com Git - mirror_edk2.git/blame - RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.c
CryptoPkg: Remove RVCT support
[mirror_edk2.git] / RedfishPkg / RedfishRestExDxe / RedfishRestExDriver.c
CommitLineData
10dc8c56
AC
1/** @file\r
2 The driver binding and service binding protocol for Redfish RestExDxe driver.\r
3\r
4 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
5 (C) Copyright 2020 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 <Uefi.h>\r
12#include "RedfishRestExDriver.h"\r
13\r
39de741e 14EFI_DRIVER_BINDING_PROTOCOL gRedfishRestExDriverBinding = {\r
10dc8c56
AC
15 RedfishRestExDriverBindingSupported,\r
16 RedfishRestExDriverBindingStart,\r
17 RedfishRestExDriverBindingStop,\r
18 REDFISH_RESTEX_DRIVER_VERSION,\r
19 NULL,\r
20 NULL\r
21};\r
22\r
39de741e 23EFI_SERVICE_BINDING_PROTOCOL mRedfishRestExServiceBinding = {\r
10dc8c56
AC
24 RedfishRestExServiceBindingCreateChild,\r
25 RedfishRestExServiceBindingDestroyChild\r
26};\r
27\r
28/**\r
29 Callback function which provided by user to remove one node in NetDestroyLinkList process.\r
30\r
31 @param[in] Entry The entry to be removed.\r
32 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.\r
33\r
34 @retval EFI_SUCCESS The entry has been removed successfully.\r
35 @retval Others Fail to remove the entry.\r
36\r
37**/\r
38EFI_STATUS\r
39EFIAPI\r
40RestExDestroyChildEntryInHandleBuffer (\r
39de741e
MK
41 IN LIST_ENTRY *Entry,\r
42 IN VOID *Context\r
10dc8c56
AC
43 )\r
44{\r
45 RESTEX_INSTANCE *Instance;\r
46 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
47 UINTN NumberOfChildren;\r
48 EFI_HANDLE *ChildHandleBuffer;\r
49\r
39de741e 50 if ((Entry == NULL) || (Context == NULL)) {\r
10dc8c56
AC
51 return EFI_INVALID_PARAMETER;\r
52 }\r
53\r
39de741e
MK
54 Instance = NET_LIST_USER_STRUCT_S (Entry, RESTEX_INSTANCE, Link, RESTEX_INSTANCE_SIGNATURE);\r
55 ServiceBinding = ((RESTEX_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *)Context)->ServiceBinding;\r
56 NumberOfChildren = ((RESTEX_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *)Context)->NumberOfChildren;\r
57 ChildHandleBuffer = ((RESTEX_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *)Context)->ChildHandleBuffer;\r
10dc8c56
AC
58\r
59 if (!NetIsInHandleBuffer (Instance->ChildHandle, NumberOfChildren, ChildHandleBuffer)) {\r
60 return EFI_SUCCESS;\r
61 }\r
62\r
63 return ServiceBinding->DestroyChild (ServiceBinding, Instance->ChildHandle);\r
64}\r
65\r
66/**\r
67 Destroy the RestEx instance and recycle the resources.\r
68\r
69 @param[in] Instance The pointer to the RestEx instance.\r
70\r
71**/\r
72VOID\r
73RestExDestroyInstance (\r
39de741e 74 IN RESTEX_INSTANCE *Instance\r
10dc8c56
AC
75 )\r
76{\r
77 HttpIoDestroyIo (&(Instance->HttpIo));\r
78\r
79 FreePool (Instance);\r
80}\r
81\r
82/**\r
83 Create the RestEx instance and initialize it.\r
84\r
85 @param[in] Service The pointer to the RestEx service.\r
86 @param[out] Instance The pointer to the RestEx instance.\r
87\r
88 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.\r
89 @retval EFI_SUCCESS The RestEx instance is created.\r
90\r
91**/\r
92EFI_STATUS\r
93RestExCreateInstance (\r
39de741e
MK
94 IN RESTEX_SERVICE *Service,\r
95 OUT RESTEX_INSTANCE **Instance\r
10dc8c56
AC
96 )\r
97{\r
39de741e
MK
98 RESTEX_INSTANCE *RestExIns;\r
99 EFI_STATUS Status;\r
10dc8c56
AC
100\r
101 *Instance = NULL;\r
102 Status = EFI_SUCCESS;\r
103\r
104 RestExIns = AllocateZeroPool (sizeof (RESTEX_INSTANCE));\r
105 if (RestExIns == NULL) {\r
106 return EFI_OUT_OF_RESOURCES;\r
107 }\r
108\r
109 RestExIns->Signature = RESTEX_INSTANCE_SIGNATURE;\r
110 InitializeListHead (&RestExIns->Link);\r
111 RestExIns->InDestroy = FALSE;\r
112 RestExIns->Service = Service;\r
113\r
114 CopyMem (&RestExIns->RestEx, &mRedfishRestExProtocol, sizeof (RestExIns->RestEx));\r
115\r
116 //\r
117 // Create a HTTP_IO to access the HTTP service.\r
118 //\r
119 Status = HttpIoCreateIo (\r
120 RestExIns->Service->ImageHandle,\r
121 RestExIns->Service->ControllerHandle,\r
122 IP_VERSION_4,\r
123 NULL,\r
124 NULL,\r
125 NULL,\r
126 &(RestExIns->HttpIo)\r
127 );\r
128 if (EFI_ERROR (Status)) {\r
129 FreePool (RestExIns);\r
130 return Status;\r
131 }\r
132\r
133 *Instance = RestExIns;\r
134\r
135 return EFI_SUCCESS;\r
136}\r
137\r
138/**\r
139 Release all the resource used the RestEx service binding instance.\r
140\r
141 @param[in] RestExSb The RestEx service binding instance.\r
142\r
143**/\r
144VOID\r
145RestExDestroyService (\r
39de741e 146 IN RESTEX_SERVICE *RestExSb\r
10dc8c56
AC
147 )\r
148{\r
149 if (RestExSb->HttpChildHandle != NULL) {\r
150 gBS->CloseProtocol (\r
151 RestExSb->HttpChildHandle,\r
152 &gEfiHttpProtocolGuid,\r
153 RestExSb->ImageHandle,\r
154 RestExSb->ControllerHandle\r
155 );\r
156\r
157 NetLibDestroyServiceChild (\r
158 RestExSb->ControllerHandle,\r
159 RestExSb->ImageHandle,\r
160 &gEfiHttpServiceBindingProtocolGuid,\r
161 RestExSb->HttpChildHandle\r
162 );\r
163\r
164 RestExSb->HttpChildHandle = NULL;\r
165 }\r
166\r
167 gBS->UninstallProtocolInterface (\r
168 RestExSb->ControllerHandle,\r
169 &gEfiCallerIdGuid,\r
170 &RestExSb->Id\r
171 );\r
172\r
173 FreePool (RestExSb);\r
174}\r
175\r
176/**\r
177 Check the NIC controller handle represents an in-band or out-of-band Redfish host\r
178 interface device. If not in-band, treat it as out-of-band interface device.\r
179\r
180 @param[in] Controller The NIC controller handle needs to be checked.\r
181\r
182 @return EFI_REST_EX_SERVICE_ACCESS_MODE of the device.\r
183\r
184**/\r
185EFI_REST_EX_SERVICE_ACCESS_MODE\r
186RestExServiceAccessMode (\r
39de741e 187 IN EFI_HANDLE Controller\r
10dc8c56
AC
188 )\r
189{\r
190 //\r
191 // This is EFI REST EX driver instance to connect\r
192 // to Redfish service using HTTP in out of band.\r
193 //\r
194 if (FixedPcdGetBool (PcdRedfishRestExServiceAccessModeInBand)) {\r
195 return EfiRestExServiceInBandAccess;\r
196 } else {\r
197 return EfiRestExServiceOutOfBandAccess;\r
198 }\r
199}\r
200\r
201/**\r
202 Create then initialize a RestEx service binding instance.\r
203\r
204 @param[in] Controller The controller to install the RestEx service\r
205 binding on.\r
206 @param[in] Image The driver binding image of the RestEx driver.\r
207 @param[out] Service The variable to receive the created service\r
208 binding instance.\r
209\r
210 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the instance.\r
211 @retval EFI_SUCCESS The service instance is created for the controller.\r
212\r
213**/\r
214EFI_STATUS\r
215RestExCreateService (\r
39de741e
MK
216 IN EFI_HANDLE Controller,\r
217 IN EFI_HANDLE Image,\r
218 OUT RESTEX_SERVICE **Service\r
10dc8c56
AC
219 )\r
220{\r
39de741e
MK
221 EFI_STATUS Status;\r
222 RESTEX_SERVICE *RestExSb;\r
10dc8c56 223\r
39de741e
MK
224 Status = EFI_SUCCESS;\r
225 RestExSb = NULL;\r
10dc8c56 226\r
39de741e 227 *Service = NULL;\r
10dc8c56
AC
228\r
229 RestExSb = AllocateZeroPool (sizeof (RESTEX_SERVICE));\r
230 if (RestExSb == NULL) {\r
231 return EFI_OUT_OF_RESOURCES;\r
232 }\r
233\r
234 RestExSb->Signature = RESTEX_SERVICE_SIGNATURE;\r
235\r
236 RestExSb->ServiceBinding = mRedfishRestExServiceBinding;\r
237\r
238 RestExSb->RestExChildrenNum = 0;\r
239 InitializeListHead (&RestExSb->RestExChildrenList);\r
240\r
241 RestExSb->ControllerHandle = Controller;\r
242 RestExSb->ImageHandle = Image;\r
243\r
39de741e 244 RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.EfiRestExServiceInfoHeader.Length = sizeof (EFI_REST_EX_SERVICE_INFO);\r
10dc8c56
AC
245 RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.EfiRestExServiceInfoHeader.RestServiceInfoVer.Major = 1;\r
246 RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.EfiRestExServiceInfoHeader.RestServiceInfoVer.Minor = 0;\r
39de741e
MK
247 RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.RestServiceType = EfiRestExServiceRedfish;\r
248 RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.RestServiceAccessMode = RestExServiceAccessMode (Controller);\r
249 RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.RestExConfigType = EfiRestExConfigHttp;\r
250 RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.RestExConfigDataLength = sizeof (EFI_REST_EX_HTTP_CONFIG_DATA);\r
10dc8c56
AC
251\r
252 Status = gBS->InstallProtocolInterface (\r
253 &Controller,\r
254 &gEfiCallerIdGuid,\r
255 EFI_NATIVE_INTERFACE,\r
256 &RestExSb->Id\r
257 );\r
258 if (EFI_ERROR (Status)) {\r
259 FreePool (RestExSb);\r
260 RestExSb = NULL;\r
261 }\r
262\r
263 *Service = RestExSb;\r
264 return Status;\r
265}\r
266\r
267/**\r
268 This is the declaration of an EFI image entry point. This entry point is\r
269 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including\r
270 both device drivers and bus drivers.\r
271\r
272 @param[in] ImageHandle The firmware allocated handle for the UEFI image.\r
273 @param[in] SystemTable A pointer to the EFI System Table.\r
274\r
275 @retval EFI_SUCCESS The operation completed successfully.\r
276 @retval Others An unexpected error occurred.\r
277**/\r
278EFI_STATUS\r
279EFIAPI\r
280RedfishRestExDriverEntryPoint (\r
281 IN EFI_HANDLE ImageHandle,\r
282 IN EFI_SYSTEM_TABLE *SystemTable\r
283 )\r
284{\r
285 EFI_STATUS Status;\r
286\r
287 Status = EFI_SUCCESS;\r
288\r
289 //\r
290 // Install the RestEx Driver Binding Protocol.\r
291 //\r
292 Status = EfiLibInstallDriverBindingComponentName2 (\r
293 ImageHandle,\r
294 SystemTable,\r
295 &gRedfishRestExDriverBinding,\r
296 ImageHandle,\r
297 &gRedfishRestExComponentName,\r
298 &gRedfishRestExComponentName2\r
299 );\r
300 if (EFI_ERROR (Status)) {\r
301 return Status;\r
302 }\r
303\r
304 return Status;\r
305}\r
306\r
307/**\r
308 Tests to see if this driver supports a given controller. If a child device is provided,\r
309 it further tests to see if this driver supports creating a handle for the specified child device.\r
310\r
311 This function checks to see if the driver specified by This supports the device specified by\r
312 ControllerHandle. Drivers will typically use the device path attached to\r
313 ControllerHandle and/or the services from the bus I/O abstraction attached to\r
314 ControllerHandle to determine if the driver supports ControllerHandle. This function\r
315 may be called many times during platform initialization. In order to reduce boot times, the tests\r
316 performed by this function must be very small, and take as little time as possible to execute. This\r
317 function must not change the state of any hardware devices, and this function must be aware that the\r
318 device specified by ControllerHandle may already be managed by the same driver or a\r
319 different driver. This function must match its calls to AllocatePages() with FreePages(),\r
320 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().\r
321 Because ControllerHandle may have been previously started by the same driver, if a protocol is\r
322 already in the opened state, then it must not be closed with CloseProtocol(). This is required\r
323 to guarantee the state of ControllerHandle is not modified by this function.\r
324\r
325 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
326 @param[in] ControllerHandle The handle of the controller to test. This handle\r
327 must support a protocol interface that supplies\r
328 an I/O abstraction to the driver.\r
329 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This\r
330 parameter is ignored by device drivers, and is optional for bus\r
331 drivers. For bus drivers, if this parameter is not NULL, then\r
332 the bus driver must determine if the bus controller specified\r
333 by ControllerHandle and the child controller specified\r
334 by RemainingDevicePath are both supported by this\r
335 bus driver.\r
336\r
337 @retval EFI_SUCCESS The device specified by ControllerHandle and\r
338 RemainingDevicePath is supported by the driver specified by This.\r
339 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
340 RemainingDevicePath is already being managed by the driver\r
341 specified by This.\r
342 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
343 RemainingDevicePath is already being managed by a different\r
344 driver or an application that requires exclusive access.\r
345 Currently not implemented.\r
346 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and\r
347 RemainingDevicePath is not supported by the driver specified by This.\r
348**/\r
349EFI_STATUS\r
350EFIAPI\r
351RedfishRestExDriverBindingSupported (\r
352 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
353 IN EFI_HANDLE ControllerHandle,\r
354 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
355 )\r
356{\r
10dc8c56
AC
357 //\r
358 // Test for the HttpServiceBinding Protocol.\r
359 //\r
360 return gBS->OpenProtocol (\r
361 ControllerHandle,\r
362 &gEfiHttpServiceBindingProtocolGuid,\r
363 NULL,\r
364 This->DriverBindingHandle,\r
365 ControllerHandle,\r
366 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
367 );\r
10dc8c56
AC
368}\r
369\r
370/**\r
371 Starts a device controller or a bus controller.\r
372\r
373 The Start() function is designed to be invoked from the EFI boot service ConnectController().\r
374 As a result, much of the error checking on the parameters to Start() has been moved into this\r
375 common boot service. It is legal to call Start() from other locations,\r
376 but the following calling restrictions must be followed, or the system behavior will not be deterministic.\r
377 1. ControllerHandle must be a valid EFI_HANDLE.\r
378 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned\r
379 EFI_DEVICE_PATH_PROTOCOL.\r
380 3. Prior to calling Start(), the Supported() function for the driver specified by This must\r
381 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.\r
382\r
383 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
384 @param[in] ControllerHandle The handle of the controller to start. This handle\r
385 must support a protocol interface that supplies\r
386 an I/O abstraction to the driver.\r
387 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This\r
388 parameter is ignored by device drivers, and is optional for bus\r
389 drivers. For a bus driver, if this parameter is NULL, then handles\r
390 for all the children of Controller are created by this driver.\r
391 If this parameter is not NULL and the first Device Path Node is\r
392 not the End of Device Path Node, then only the handle for the\r
393 child device specified by the first Device Path Node of\r
394 RemainingDevicePath is created by this driver.\r
395 If the first Device Path Node of RemainingDevicePath is\r
396 the End of Device Path Node, no child handle is created by this\r
397 driver.\r
398\r
399 @retval EFI_SUCCESS The device was started.\r
400 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.\r
401 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
402 @retval Others The driver failded to start the device.\r
403\r
404**/\r
405EFI_STATUS\r
406EFIAPI\r
407RedfishRestExDriverBindingStart (\r
408 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
409 IN EFI_HANDLE ControllerHandle,\r
410 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
411 )\r
412{\r
39de741e
MK
413 RESTEX_SERVICE *RestExSb;\r
414 EFI_STATUS Status;\r
415 UINT32 *Id;\r
416 VOID *Interface;\r
10dc8c56
AC
417\r
418 Status = gBS->OpenProtocol (\r
419 ControllerHandle,\r
420 &gEfiCallerIdGuid,\r
39de741e 421 (VOID **)&Id,\r
10dc8c56
AC
422 This->DriverBindingHandle,\r
423 ControllerHandle,\r
424 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
425 );\r
426 if (!EFI_ERROR (Status)) {\r
427 return EFI_ALREADY_STARTED;\r
428 }\r
429\r
430 Status = RestExCreateService (ControllerHandle, This->DriverBindingHandle, &RestExSb);\r
431 if (EFI_ERROR (Status)) {\r
432 return Status;\r
433 }\r
434\r
435 ASSERT (RestExSb != NULL);\r
436\r
437 //\r
438 // Create a Http child instance, but do not configure it.\r
439 // This will establish the parent-child relationship.\r
440 //\r
441 Status = NetLibCreateServiceChild (\r
442 ControllerHandle,\r
443 This->DriverBindingHandle,\r
444 &gEfiHttpServiceBindingProtocolGuid,\r
445 &RestExSb->HttpChildHandle\r
446 );\r
447 if (EFI_ERROR (Status)) {\r
448 goto ON_ERROR;\r
449 }\r
450\r
451 Status = gBS->OpenProtocol (\r
452 RestExSb->HttpChildHandle,\r
453 &gEfiHttpProtocolGuid,\r
454 &Interface,\r
455 This->DriverBindingHandle,\r
456 ControllerHandle,\r
457 EFI_OPEN_PROTOCOL_BY_DRIVER\r
458 );\r
459 if (EFI_ERROR (Status)) {\r
460 goto ON_ERROR;\r
461 }\r
462\r
463 //\r
464 // Install the RestEx ServiceBinding Protocol onto ControllerHandle.\r
465 //\r
466 Status = gBS->InstallMultipleProtocolInterfaces (\r
467 &ControllerHandle,\r
468 &gEfiRestExServiceBindingProtocolGuid,\r
469 &RestExSb->ServiceBinding,\r
470 NULL\r
471 );\r
472 if (EFI_ERROR (Status)) {\r
473 goto ON_ERROR;\r
474 }\r
475\r
476 return EFI_SUCCESS;\r
477\r
478ON_ERROR:\r
479 RestExDestroyService (RestExSb);\r
480\r
481 return Status;\r
482}\r
483\r
484/**\r
485 Stops a device controller or a bus controller.\r
486\r
487 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().\r
488 As a result, much of the error checking on the parameters to Stop() has been moved\r
489 into this common boot service. It is legal to call Stop() from other locations,\r
490 but the following calling restrictions must be followed, or the system behavior will not be deterministic.\r
491 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this\r
492 same driver's Start() function.\r
493 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid\r
494 EFI_HANDLE. In addition, all of these handles must have been created in this driver's\r
495 Start() function, and the Start() function must have called OpenProtocol() on\r
496 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
497\r
498 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
499 @param[in] ControllerHandle A handle to the device being stopped. The handle must\r
500 support a bus specific I/O protocol for the driver\r
501 to use to stop the device.\r
502 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
503 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL\r
504 if NumberOfChildren is 0.\r
505\r
506 @retval EFI_SUCCESS The device was stopped.\r
507 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
508\r
509**/\r
510EFI_STATUS\r
511EFIAPI\r
512RedfishRestExDriverBindingStop (\r
513 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
514 IN EFI_HANDLE ControllerHandle,\r
515 IN UINTN NumberOfChildren,\r
516 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL\r
517 )\r
518{\r
39de741e
MK
519 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
520 RESTEX_SERVICE *RestExSb;\r
521 EFI_HANDLE NicHandle;\r
522 EFI_STATUS Status;\r
523 LIST_ENTRY *List;\r
524 RESTEX_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;\r
10dc8c56
AC
525\r
526 //\r
527 // RestEx driver opens HTTP child, So, Controller is a HTTP\r
528 // child handle. Locate the Nic handle first. Then get the\r
529 // RestEx private data back.\r
530 //\r
531 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiHttpProtocolGuid);\r
532 if (NicHandle == NULL) {\r
533 return EFI_SUCCESS;\r
534 }\r
535\r
536 Status = gBS->OpenProtocol (\r
537 NicHandle,\r
538 &gEfiRestExServiceBindingProtocolGuid,\r
39de741e 539 (VOID **)&ServiceBinding,\r
10dc8c56
AC
540 This->DriverBindingHandle,\r
541 NicHandle,\r
542 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
543 );\r
544 if (EFI_ERROR (Status)) {\r
545 return EFI_DEVICE_ERROR;\r
546 }\r
547\r
548 RestExSb = RESTEX_SERVICE_FROM_THIS (ServiceBinding);\r
549\r
550 if (!IsListEmpty (&RestExSb->RestExChildrenList)) {\r
551 //\r
552 // Destroy the RestEx child instance in ChildHandleBuffer.\r
553 //\r
39de741e 554 List = &RestExSb->RestExChildrenList;\r
10dc8c56
AC
555 Context.ServiceBinding = ServiceBinding;\r
556 Context.NumberOfChildren = NumberOfChildren;\r
557 Context.ChildHandleBuffer = ChildHandleBuffer;\r
39de741e
MK
558 Status = NetDestroyLinkList (\r
559 List,\r
560 RestExDestroyChildEntryInHandleBuffer,\r
561 &Context,\r
562 NULL\r
563 );\r
10dc8c56
AC
564 }\r
565\r
39de741e 566 if ((NumberOfChildren == 0) && IsListEmpty (&RestExSb->RestExChildrenList)) {\r
10dc8c56
AC
567 gBS->UninstallProtocolInterface (\r
568 NicHandle,\r
569 &gEfiRestExServiceBindingProtocolGuid,\r
570 ServiceBinding\r
571 );\r
572\r
573 RestExDestroyService (RestExSb);\r
574\r
575 if (gRedfishRestExControllerNameTable != NULL) {\r
576 FreeUnicodeStringTable (gRedfishRestExControllerNameTable);\r
577 gRedfishRestExControllerNameTable = NULL;\r
578 }\r
579\r
580 Status = EFI_SUCCESS;\r
581 }\r
582\r
583 return Status;\r
584}\r
585\r
586/**\r
587 Creates a child handle and installs a protocol.\r
588\r
589 The CreateChild() function installs a protocol on ChildHandle.\r
590 If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.\r
591 If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.\r
592\r
593 @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
594 @param[in] ChildHandle Pointer to the handle of the child to create. If it is NULL,\r
595 then a new handle is created. If it is a pointer to an existing UEFI handle,\r
596 then the protocol is added to the existing UEFI handle.\r
597\r
598 @retval EFI_SUCCES The protocol was added to ChildHandle.\r
599 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.\r
600 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create\r
601 the child\r
602 @retval other The child handle was not created\r
603\r
604**/\r
605EFI_STATUS\r
606EFIAPI\r
607RedfishRestExServiceBindingCreateChild (\r
608 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
609 IN EFI_HANDLE *ChildHandle\r
610 )\r
611{\r
39de741e
MK
612 RESTEX_SERVICE *RestExSb;\r
613 RESTEX_INSTANCE *Instance;\r
614 EFI_STATUS Status;\r
615 EFI_TPL OldTpl;\r
616 VOID *Http;\r
10dc8c56
AC
617\r
618 if ((This == NULL) || (ChildHandle == NULL)) {\r
619 return EFI_INVALID_PARAMETER;\r
620 }\r
621\r
622 RestExSb = RESTEX_SERVICE_FROM_THIS (This);\r
623\r
624 Status = RestExCreateInstance (RestExSb, &Instance);\r
625 if (EFI_ERROR (Status)) {\r
626 return Status;\r
627 }\r
39de741e 628\r
10dc8c56
AC
629 ASSERT (Instance != NULL);\r
630\r
631 //\r
632 // Install the RestEx protocol onto ChildHandle\r
633 //\r
634 Status = gBS->InstallMultipleProtocolInterfaces (\r
635 ChildHandle,\r
636 &gEfiRestExProtocolGuid,\r
637 &Instance->RestEx,\r
638 NULL\r
639 );\r
640 if (EFI_ERROR (Status)) {\r
641 goto ON_ERROR;\r
642 }\r
643\r
644 Instance->ChildHandle = *ChildHandle;\r
645\r
646 //\r
647 // Open the Http protocol BY_CHILD.\r
648 //\r
649 Status = gBS->OpenProtocol (\r
650 RestExSb->HttpChildHandle,\r
651 &gEfiHttpProtocolGuid,\r
39de741e 652 (VOID **)&Http,\r
10dc8c56
AC
653 gRedfishRestExDriverBinding.DriverBindingHandle,\r
654 Instance->ChildHandle,\r
655 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
656 );\r
657 if (EFI_ERROR (Status)) {\r
658 gBS->UninstallMultipleProtocolInterfaces (\r
659 Instance->ChildHandle,\r
660 &gEfiRestExProtocolGuid,\r
661 &Instance->RestEx,\r
662 NULL\r
663 );\r
664\r
665 goto ON_ERROR;\r
666 }\r
667\r
668 //\r
669 // Open the Http protocol by child.\r
670 //\r
671 Status = gBS->OpenProtocol (\r
672 Instance->HttpIo.Handle,\r
673 &gEfiHttpProtocolGuid,\r
39de741e 674 (VOID **)&Http,\r
10dc8c56
AC
675 gRedfishRestExDriverBinding.DriverBindingHandle,\r
676 Instance->ChildHandle,\r
677 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
678 );\r
679 if (EFI_ERROR (Status)) {\r
680 //\r
681 // Close the Http protocol.\r
682 //\r
683 gBS->CloseProtocol (\r
684 RestExSb->HttpChildHandle,\r
685 &gEfiHttpProtocolGuid,\r
686 gRedfishRestExDriverBinding.DriverBindingHandle,\r
687 ChildHandle\r
688 );\r
689\r
39de741e
MK
690 gBS->UninstallMultipleProtocolInterfaces (\r
691 Instance->ChildHandle,\r
692 &gEfiRestExProtocolGuid,\r
693 &Instance->RestEx,\r
694 NULL\r
695 );\r
10dc8c56
AC
696\r
697 goto ON_ERROR;\r
698 }\r
699\r
700 //\r
701 // Add it to the parent's child list.\r
702 //\r
703 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
704\r
705 InsertTailList (&RestExSb->RestExChildrenList, &Instance->Link);\r
706 RestExSb->RestExChildrenNum++;\r
707\r
708 gBS->RestoreTPL (OldTpl);\r
709\r
710 return EFI_SUCCESS;\r
711\r
712ON_ERROR:\r
713\r
714 RestExDestroyInstance (Instance);\r
715 return Status;\r
716}\r
717\r
718/**\r
719 Destroys a child handle with a protocol installed on it.\r
720\r
721 The DestroyChild() function does the opposite of CreateChild(). It removes a protocol\r
722 that was installed by CreateChild() from ChildHandle. If the removed protocol is the\r
723 last protocol on ChildHandle, then ChildHandle is destroyed.\r
724\r
725 @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
726 @param[in] ChildHandle Handle of the child to destroy\r
727\r
728 @retval EFI_SUCCES The protocol was removed from ChildHandle.\r
729 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.\r
730 @retval EFI_INVALID_PARAMETER Child handle is NULL.\r
731 @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle\r
732 because its services are being used.\r
733 @retval other The child handle was not destroyed\r
734\r
735**/\r
736EFI_STATUS\r
737EFIAPI\r
738RedfishRestExServiceBindingDestroyChild (\r
739 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
740 IN EFI_HANDLE ChildHandle\r
741 )\r
742{\r
39de741e
MK
743 RESTEX_SERVICE *RestExSb;\r
744 RESTEX_INSTANCE *Instance;\r
10dc8c56 745\r
39de741e
MK
746 EFI_REST_EX_PROTOCOL *RestEx;\r
747 EFI_STATUS Status;\r
748 EFI_TPL OldTpl;\r
10dc8c56
AC
749\r
750 if ((This == NULL) || (ChildHandle == NULL)) {\r
751 return EFI_INVALID_PARAMETER;\r
752 }\r
753\r
754 //\r
755 // Retrieve the private context data structures\r
756 //\r
757 Status = gBS->OpenProtocol (\r
758 ChildHandle,\r
759 &gEfiRestExProtocolGuid,\r
39de741e 760 (VOID **)&RestEx,\r
10dc8c56
AC
761 NULL,\r
762 NULL,\r
763 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
764 );\r
765\r
766 if (EFI_ERROR (Status)) {\r
767 return EFI_UNSUPPORTED;\r
768 }\r
769\r
39de741e
MK
770 Instance = RESTEX_INSTANCE_FROM_THIS (RestEx);\r
771 RestExSb = RESTEX_SERVICE_FROM_THIS (This);\r
10dc8c56
AC
772\r
773 if (Instance->Service != RestExSb) {\r
774 return EFI_INVALID_PARAMETER;\r
775 }\r
776\r
777 if (Instance->InDestroy) {\r
778 return EFI_SUCCESS;\r
779 }\r
780\r
781 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
782\r
783 Instance->InDestroy = TRUE;\r
784\r
785 //\r
786 // Close the Http protocol.\r
787 //\r
788 gBS->CloseProtocol (\r
789 RestExSb->HttpChildHandle,\r
790 &gEfiHttpProtocolGuid,\r
791 gRedfishRestExDriverBinding.DriverBindingHandle,\r
792 ChildHandle\r
793 );\r
794\r
795 gBS->CloseProtocol (\r
796 Instance->HttpIo.Handle,\r
797 &gEfiHttpProtocolGuid,\r
798 gRedfishRestExDriverBinding.DriverBindingHandle,\r
799 ChildHandle\r
800 );\r
801\r
10dc8c56
AC
802 gBS->RestoreTPL (OldTpl);\r
803\r
804 //\r
805 // Uninstall the RestEx protocol first to enable a top down destruction.\r
806 //\r
807 Status = gBS->UninstallProtocolInterface (\r
808 ChildHandle,\r
809 &gEfiRestExProtocolGuid,\r
810 RestEx\r
811 );\r
812\r
813 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
814\r
815 if (EFI_ERROR (Status)) {\r
816 Instance->InDestroy = FALSE;\r
817 gBS->RestoreTPL (OldTpl);\r
818 return Status;\r
819 }\r
820\r
821 RemoveEntryList (&Instance->Link);\r
822 RestExSb->RestExChildrenNum--;\r
823\r
824 gBS->RestoreTPL (OldTpl);\r
825\r
826 RestExDestroyInstance (Instance);\r
827 return EFI_SUCCESS;\r
828}\r