2 The driver binding and service binding protocol for Redfish RestExDxe driver.
4 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
12 #include "RedfishRestExDriver.h"
14 EFI_DRIVER_BINDING_PROTOCOL gRedfishRestExDriverBinding
= {
15 RedfishRestExDriverBindingSupported
,
16 RedfishRestExDriverBindingStart
,
17 RedfishRestExDriverBindingStop
,
18 REDFISH_RESTEX_DRIVER_VERSION
,
23 EFI_SERVICE_BINDING_PROTOCOL mRedfishRestExServiceBinding
= {
24 RedfishRestExServiceBindingCreateChild
,
25 RedfishRestExServiceBindingDestroyChild
29 Callback function which provided by user to remove one node in NetDestroyLinkList process.
31 @param[in] Entry The entry to be removed.
32 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
34 @retval EFI_SUCCESS The entry has been removed successfully.
35 @retval Others Fail to remove the entry.
40 RestExDestroyChildEntryInHandleBuffer (
45 RESTEX_INSTANCE
*Instance
;
46 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
47 UINTN NumberOfChildren
;
48 EFI_HANDLE
*ChildHandleBuffer
;
50 if (Entry
== NULL
|| Context
== NULL
) {
51 return EFI_INVALID_PARAMETER
;
54 Instance
= NET_LIST_USER_STRUCT_S (Entry
, RESTEX_INSTANCE
, Link
, RESTEX_INSTANCE_SIGNATURE
);
55 ServiceBinding
= ((RESTEX_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*) Context
)->ServiceBinding
;
56 NumberOfChildren
= ((RESTEX_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*) Context
)->NumberOfChildren
;
57 ChildHandleBuffer
= ((RESTEX_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*) Context
)->ChildHandleBuffer
;
59 if (!NetIsInHandleBuffer (Instance
->ChildHandle
, NumberOfChildren
, ChildHandleBuffer
)) {
63 return ServiceBinding
->DestroyChild (ServiceBinding
, Instance
->ChildHandle
);
67 Destroy the RestEx instance and recycle the resources.
69 @param[in] Instance The pointer to the RestEx instance.
73 RestExDestroyInstance (
74 IN RESTEX_INSTANCE
*Instance
77 HttpIoDestroyIo (&(Instance
->HttpIo
));
83 Create the RestEx instance and initialize it.
85 @param[in] Service The pointer to the RestEx service.
86 @param[out] Instance The pointer to the RestEx instance.
88 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
89 @retval EFI_SUCCESS The RestEx instance is created.
93 RestExCreateInstance (
94 IN RESTEX_SERVICE
*Service
,
95 OUT RESTEX_INSTANCE
**Instance
98 RESTEX_INSTANCE
*RestExIns
;
102 Status
= EFI_SUCCESS
;
104 RestExIns
= AllocateZeroPool (sizeof (RESTEX_INSTANCE
));
105 if (RestExIns
== NULL
) {
106 return EFI_OUT_OF_RESOURCES
;
109 RestExIns
->Signature
= RESTEX_INSTANCE_SIGNATURE
;
110 InitializeListHead (&RestExIns
->Link
);
111 RestExIns
->InDestroy
= FALSE
;
112 RestExIns
->Service
= Service
;
114 CopyMem (&RestExIns
->RestEx
, &mRedfishRestExProtocol
, sizeof (RestExIns
->RestEx
));
117 // Create a HTTP_IO to access the HTTP service.
119 Status
= HttpIoCreateIo (
120 RestExIns
->Service
->ImageHandle
,
121 RestExIns
->Service
->ControllerHandle
,
128 if (EFI_ERROR (Status
)) {
129 FreePool (RestExIns
);
133 *Instance
= RestExIns
;
139 Release all the resource used the RestEx service binding instance.
141 @param[in] RestExSb The RestEx service binding instance.
145 RestExDestroyService (
146 IN RESTEX_SERVICE
*RestExSb
149 if (RestExSb
->HttpChildHandle
!= NULL
) {
151 RestExSb
->HttpChildHandle
,
152 &gEfiHttpProtocolGuid
,
153 RestExSb
->ImageHandle
,
154 RestExSb
->ControllerHandle
157 NetLibDestroyServiceChild (
158 RestExSb
->ControllerHandle
,
159 RestExSb
->ImageHandle
,
160 &gEfiHttpServiceBindingProtocolGuid
,
161 RestExSb
->HttpChildHandle
164 RestExSb
->HttpChildHandle
= NULL
;
167 gBS
->UninstallProtocolInterface (
168 RestExSb
->ControllerHandle
,
177 Check the NIC controller handle represents an in-band or out-of-band Redfish host
178 interface device. If not in-band, treat it as out-of-band interface device.
180 @param[in] Controller The NIC controller handle needs to be checked.
182 @return EFI_REST_EX_SERVICE_ACCESS_MODE of the device.
185 EFI_REST_EX_SERVICE_ACCESS_MODE
186 RestExServiceAccessMode (
187 IN EFI_HANDLE Controller
191 // This is EFI REST EX driver instance to connect
192 // to Redfish service using HTTP in out of band.
194 if (FixedPcdGetBool (PcdRedfishRestExServiceAccessModeInBand
)) {
195 return EfiRestExServiceInBandAccess
;
197 return EfiRestExServiceOutOfBandAccess
;
202 Create then initialize a RestEx service binding instance.
204 @param[in] Controller The controller to install the RestEx service
206 @param[in] Image The driver binding image of the RestEx driver.
207 @param[out] Service The variable to receive the created service
210 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the instance.
211 @retval EFI_SUCCESS The service instance is created for the controller.
215 RestExCreateService (
216 IN EFI_HANDLE Controller
,
218 OUT RESTEX_SERVICE
**Service
222 RESTEX_SERVICE
*RestExSb
;
224 Status
= EFI_SUCCESS
;
229 RestExSb
= AllocateZeroPool (sizeof (RESTEX_SERVICE
));
230 if (RestExSb
== NULL
) {
231 return EFI_OUT_OF_RESOURCES
;
234 RestExSb
->Signature
= RESTEX_SERVICE_SIGNATURE
;
236 RestExSb
->ServiceBinding
= mRedfishRestExServiceBinding
;
238 RestExSb
->RestExChildrenNum
= 0;
239 InitializeListHead (&RestExSb
->RestExChildrenList
);
241 RestExSb
->ControllerHandle
= Controller
;
242 RestExSb
->ImageHandle
= Image
;
244 RestExSb
->RestExServiceInfo
.EfiRestExServiceInfoV10
.EfiRestExServiceInfoHeader
.Length
= sizeof (EFI_REST_EX_SERVICE_INFO
);
245 RestExSb
->RestExServiceInfo
.EfiRestExServiceInfoV10
.EfiRestExServiceInfoHeader
.RestServiceInfoVer
.Major
= 1;
246 RestExSb
->RestExServiceInfo
.EfiRestExServiceInfoV10
.EfiRestExServiceInfoHeader
.RestServiceInfoVer
.Minor
= 0;
247 RestExSb
->RestExServiceInfo
.EfiRestExServiceInfoV10
.RestServiceType
= EfiRestExServiceRedfish
;
248 RestExSb
->RestExServiceInfo
.EfiRestExServiceInfoV10
.RestServiceAccessMode
= RestExServiceAccessMode (Controller
);
249 RestExSb
->RestExServiceInfo
.EfiRestExServiceInfoV10
.RestExConfigType
= EfiRestExConfigHttp
;
250 RestExSb
->RestExServiceInfo
.EfiRestExServiceInfoV10
.RestExConfigDataLength
= sizeof (EFI_REST_EX_HTTP_CONFIG_DATA
);
252 Status
= gBS
->InstallProtocolInterface (
255 EFI_NATIVE_INTERFACE
,
258 if (EFI_ERROR (Status
)) {
268 This is the declaration of an EFI image entry point. This entry point is
269 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
270 both device drivers and bus drivers.
272 @param[in] ImageHandle The firmware allocated handle for the UEFI image.
273 @param[in] SystemTable A pointer to the EFI System Table.
275 @retval EFI_SUCCESS The operation completed successfully.
276 @retval Others An unexpected error occurred.
280 RedfishRestExDriverEntryPoint (
281 IN EFI_HANDLE ImageHandle
,
282 IN EFI_SYSTEM_TABLE
*SystemTable
287 Status
= EFI_SUCCESS
;
290 // Install the RestEx Driver Binding Protocol.
292 Status
= EfiLibInstallDriverBindingComponentName2 (
295 &gRedfishRestExDriverBinding
,
297 &gRedfishRestExComponentName
,
298 &gRedfishRestExComponentName2
300 if (EFI_ERROR (Status
)) {
308 Tests to see if this driver supports a given controller. If a child device is provided,
309 it further tests to see if this driver supports creating a handle for the specified child device.
311 This function checks to see if the driver specified by This supports the device specified by
312 ControllerHandle. Drivers will typically use the device path attached to
313 ControllerHandle and/or the services from the bus I/O abstraction attached to
314 ControllerHandle to determine if the driver supports ControllerHandle. This function
315 may be called many times during platform initialization. In order to reduce boot times, the tests
316 performed by this function must be very small, and take as little time as possible to execute. This
317 function must not change the state of any hardware devices, and this function must be aware that the
318 device specified by ControllerHandle may already be managed by the same driver or a
319 different driver. This function must match its calls to AllocatePages() with FreePages(),
320 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
321 Because ControllerHandle may have been previously started by the same driver, if a protocol is
322 already in the opened state, then it must not be closed with CloseProtocol(). This is required
323 to guarantee the state of ControllerHandle is not modified by this function.
325 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
326 @param[in] ControllerHandle The handle of the controller to test. This handle
327 must support a protocol interface that supplies
328 an I/O abstraction to the driver.
329 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
330 parameter is ignored by device drivers, and is optional for bus
331 drivers. For bus drivers, if this parameter is not NULL, then
332 the bus driver must determine if the bus controller specified
333 by ControllerHandle and the child controller specified
334 by RemainingDevicePath are both supported by this
337 @retval EFI_SUCCESS The device specified by ControllerHandle and
338 RemainingDevicePath is supported by the driver specified by This.
339 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
340 RemainingDevicePath is already being managed by the driver
342 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
343 RemainingDevicePath is already being managed by a different
344 driver or an application that requires exclusive access.
345 Currently not implemented.
346 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
347 RemainingDevicePath is not supported by the driver specified by This.
351 RedfishRestExDriverBindingSupported (
352 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
353 IN EFI_HANDLE ControllerHandle
,
354 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
359 // Test for the HttpServiceBinding Protocol.
361 return gBS
->OpenProtocol (
363 &gEfiHttpServiceBindingProtocolGuid
,
365 This
->DriverBindingHandle
,
367 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
373 Starts a device controller or a bus controller.
375 The Start() function is designed to be invoked from the EFI boot service ConnectController().
376 As a result, much of the error checking on the parameters to Start() has been moved into this
377 common boot service. It is legal to call Start() from other locations,
378 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
379 1. ControllerHandle must be a valid EFI_HANDLE.
380 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
381 EFI_DEVICE_PATH_PROTOCOL.
382 3. Prior to calling Start(), the Supported() function for the driver specified by This must
383 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
385 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
386 @param[in] ControllerHandle The handle of the controller to start. This handle
387 must support a protocol interface that supplies
388 an I/O abstraction to the driver.
389 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
390 parameter is ignored by device drivers, and is optional for bus
391 drivers. For a bus driver, if this parameter is NULL, then handles
392 for all the children of Controller are created by this driver.
393 If this parameter is not NULL and the first Device Path Node is
394 not the End of Device Path Node, then only the handle for the
395 child device specified by the first Device Path Node of
396 RemainingDevicePath is created by this driver.
397 If the first Device Path Node of RemainingDevicePath is
398 the End of Device Path Node, no child handle is created by this
401 @retval EFI_SUCCESS The device was started.
402 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
403 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
404 @retval Others The driver failded to start the device.
409 RedfishRestExDriverBindingStart (
410 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
411 IN EFI_HANDLE ControllerHandle
,
412 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
415 RESTEX_SERVICE
*RestExSb
;
420 Status
= gBS
->OpenProtocol (
424 This
->DriverBindingHandle
,
426 EFI_OPEN_PROTOCOL_GET_PROTOCOL
428 if (!EFI_ERROR (Status
)) {
429 return EFI_ALREADY_STARTED
;
432 Status
= RestExCreateService (ControllerHandle
, This
->DriverBindingHandle
, &RestExSb
);
433 if (EFI_ERROR (Status
)) {
437 ASSERT (RestExSb
!= NULL
);
440 // Create a Http child instance, but do not configure it.
441 // This will establish the parent-child relationship.
443 Status
= NetLibCreateServiceChild (
445 This
->DriverBindingHandle
,
446 &gEfiHttpServiceBindingProtocolGuid
,
447 &RestExSb
->HttpChildHandle
449 if (EFI_ERROR (Status
)) {
453 Status
= gBS
->OpenProtocol (
454 RestExSb
->HttpChildHandle
,
455 &gEfiHttpProtocolGuid
,
457 This
->DriverBindingHandle
,
459 EFI_OPEN_PROTOCOL_BY_DRIVER
461 if (EFI_ERROR (Status
)) {
466 // Install the RestEx ServiceBinding Protocol onto ControllerHandle.
468 Status
= gBS
->InstallMultipleProtocolInterfaces (
470 &gEfiRestExServiceBindingProtocolGuid
,
471 &RestExSb
->ServiceBinding
,
474 if (EFI_ERROR (Status
)) {
481 RestExDestroyService (RestExSb
);
487 Stops a device controller or a bus controller.
489 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
490 As a result, much of the error checking on the parameters to Stop() has been moved
491 into this common boot service. It is legal to call Stop() from other locations,
492 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
493 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
494 same driver's Start() function.
495 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
496 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
497 Start() function, and the Start() function must have called OpenProtocol() on
498 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
500 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
501 @param[in] ControllerHandle A handle to the device being stopped. The handle must
502 support a bus specific I/O protocol for the driver
503 to use to stop the device.
504 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
505 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
506 if NumberOfChildren is 0.
508 @retval EFI_SUCCESS The device was stopped.
509 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
514 RedfishRestExDriverBindingStop (
515 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
516 IN EFI_HANDLE ControllerHandle
,
517 IN UINTN NumberOfChildren
,
518 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
521 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
522 RESTEX_SERVICE
*RestExSb
;
523 EFI_HANDLE NicHandle
;
526 RESTEX_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context
;
529 // RestEx driver opens HTTP child, So, Controller is a HTTP
530 // child handle. Locate the Nic handle first. Then get the
531 // RestEx private data back.
533 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiHttpProtocolGuid
);
534 if (NicHandle
== NULL
) {
538 Status
= gBS
->OpenProtocol (
540 &gEfiRestExServiceBindingProtocolGuid
,
541 (VOID
**) &ServiceBinding
,
542 This
->DriverBindingHandle
,
544 EFI_OPEN_PROTOCOL_GET_PROTOCOL
546 if (EFI_ERROR (Status
)) {
547 return EFI_DEVICE_ERROR
;
550 RestExSb
= RESTEX_SERVICE_FROM_THIS (ServiceBinding
);
552 if (!IsListEmpty (&RestExSb
->RestExChildrenList
)) {
554 // Destroy the RestEx child instance in ChildHandleBuffer.
556 List
= &RestExSb
->RestExChildrenList
;
557 Context
.ServiceBinding
= ServiceBinding
;
558 Context
.NumberOfChildren
= NumberOfChildren
;
559 Context
.ChildHandleBuffer
= ChildHandleBuffer
;
560 Status
= NetDestroyLinkList (
562 RestExDestroyChildEntryInHandleBuffer
,
568 if (NumberOfChildren
== 0 && IsListEmpty (&RestExSb
->RestExChildrenList
)) {
569 gBS
->UninstallProtocolInterface (
571 &gEfiRestExServiceBindingProtocolGuid
,
575 RestExDestroyService (RestExSb
);
577 if (gRedfishRestExControllerNameTable
!= NULL
) {
578 FreeUnicodeStringTable (gRedfishRestExControllerNameTable
);
579 gRedfishRestExControllerNameTable
= NULL
;
582 Status
= EFI_SUCCESS
;
589 Creates a child handle and installs a protocol.
591 The CreateChild() function installs a protocol on ChildHandle.
592 If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
593 If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
595 @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
596 @param[in] ChildHandle Pointer to the handle of the child to create. If it is NULL,
597 then a new handle is created. If it is a pointer to an existing UEFI handle,
598 then the protocol is added to the existing UEFI handle.
600 @retval EFI_SUCCES The protocol was added to ChildHandle.
601 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
602 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create
604 @retval other The child handle was not created
609 RedfishRestExServiceBindingCreateChild (
610 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
611 IN EFI_HANDLE
*ChildHandle
614 RESTEX_SERVICE
*RestExSb
;
615 RESTEX_INSTANCE
*Instance
;
620 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
621 return EFI_INVALID_PARAMETER
;
624 RestExSb
= RESTEX_SERVICE_FROM_THIS (This
);
626 Status
= RestExCreateInstance (RestExSb
, &Instance
);
627 if (EFI_ERROR (Status
)) {
630 ASSERT (Instance
!= NULL
);
633 // Install the RestEx protocol onto ChildHandle
635 Status
= gBS
->InstallMultipleProtocolInterfaces (
637 &gEfiRestExProtocolGuid
,
641 if (EFI_ERROR (Status
)) {
645 Instance
->ChildHandle
= *ChildHandle
;
648 // Open the Http protocol BY_CHILD.
650 Status
= gBS
->OpenProtocol (
651 RestExSb
->HttpChildHandle
,
652 &gEfiHttpProtocolGuid
,
654 gRedfishRestExDriverBinding
.DriverBindingHandle
,
655 Instance
->ChildHandle
,
656 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
658 if (EFI_ERROR (Status
)) {
659 gBS
->UninstallMultipleProtocolInterfaces (
660 Instance
->ChildHandle
,
661 &gEfiRestExProtocolGuid
,
670 // Open the Http protocol by child.
672 Status
= gBS
->OpenProtocol (
673 Instance
->HttpIo
.Handle
,
674 &gEfiHttpProtocolGuid
,
676 gRedfishRestExDriverBinding
.DriverBindingHandle
,
677 Instance
->ChildHandle
,
678 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
680 if (EFI_ERROR (Status
)) {
682 // Close the Http protocol.
685 RestExSb
->HttpChildHandle
,
686 &gEfiHttpProtocolGuid
,
687 gRedfishRestExDriverBinding
.DriverBindingHandle
,
691 gBS
->UninstallMultipleProtocolInterfaces (
692 Instance
->ChildHandle
,
693 &gEfiRestExProtocolGuid
,
702 // Add it to the parent's child list.
704 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
706 InsertTailList (&RestExSb
->RestExChildrenList
, &Instance
->Link
);
707 RestExSb
->RestExChildrenNum
++;
709 gBS
->RestoreTPL (OldTpl
);
715 RestExDestroyInstance (Instance
);
720 Destroys a child handle with a protocol installed on it.
722 The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
723 that was installed by CreateChild() from ChildHandle. If the removed protocol is the
724 last protocol on ChildHandle, then ChildHandle is destroyed.
726 @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
727 @param[in] ChildHandle Handle of the child to destroy
729 @retval EFI_SUCCES The protocol was removed from ChildHandle.
730 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
731 @retval EFI_INVALID_PARAMETER Child handle is NULL.
732 @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
733 because its services are being used.
734 @retval other The child handle was not destroyed
739 RedfishRestExServiceBindingDestroyChild (
740 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
741 IN EFI_HANDLE ChildHandle
744 RESTEX_SERVICE
*RestExSb
;
745 RESTEX_INSTANCE
*Instance
;
747 EFI_REST_EX_PROTOCOL
*RestEx
;
751 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
752 return EFI_INVALID_PARAMETER
;
756 // Retrieve the private context data structures
758 Status
= gBS
->OpenProtocol (
760 &gEfiRestExProtocolGuid
,
764 EFI_OPEN_PROTOCOL_GET_PROTOCOL
767 if (EFI_ERROR (Status
)) {
768 return EFI_UNSUPPORTED
;
771 Instance
= RESTEX_INSTANCE_FROM_THIS (RestEx
);
772 RestExSb
= RESTEX_SERVICE_FROM_THIS (This
);
774 if (Instance
->Service
!= RestExSb
) {
775 return EFI_INVALID_PARAMETER
;
778 if (Instance
->InDestroy
) {
782 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
784 Instance
->InDestroy
= TRUE
;
787 // Close the Http protocol.
790 RestExSb
->HttpChildHandle
,
791 &gEfiHttpProtocolGuid
,
792 gRedfishRestExDriverBinding
.DriverBindingHandle
,
797 Instance
->HttpIo
.Handle
,
798 &gEfiHttpProtocolGuid
,
799 gRedfishRestExDriverBinding
.DriverBindingHandle
,
804 gBS
->RestoreTPL (OldTpl
);
807 // Uninstall the RestEx protocol first to enable a top down destruction.
809 Status
= gBS
->UninstallProtocolInterface (
811 &gEfiRestExProtocolGuid
,
815 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
817 if (EFI_ERROR (Status
)) {
818 Instance
->InDestroy
= FALSE
;
819 gBS
->RestoreTPL (OldTpl
);
823 RemoveEntryList (&Instance
->Link
);
824 RestExSb
->RestExChildrenNum
--;
826 gBS
->RestoreTPL (OldTpl
);
828 RestExDestroyInstance (Instance
);