2 Support functions to connect/disconnect UEFI Driver model Protocol
4 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 // Driver Support Functions
23 Connects one or more drivers to a controller.
25 @param ControllerHandle The handle of the controller to which driver(s) are to be connected.
26 @param DriverImageHandle A pointer to an ordered list handles that support the
27 EFI_DRIVER_BINDING_PROTOCOL.
28 @param RemainingDevicePath A pointer to the device path that specifies a child of the
29 controller specified by ControllerHandle.
30 @param Recursive If TRUE, then ConnectController() is called recursively
31 until the entire tree of controllers below the controller specified
32 by ControllerHandle have been created. If FALSE, then
33 the tree of controllers is only expanded one level.
35 @retval EFI_SUCCESS 1) One or more drivers were connected to ControllerHandle.
36 2) No drivers were connected to ControllerHandle, but
37 RemainingDevicePath is not NULL, and it is an End Device
39 @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
40 @retval EFI_NOT_FOUND 1) There are no EFI_DRIVER_BINDING_PROTOCOL instances
41 present in the system.
42 2) No drivers were connected to ControllerHandle.
43 @retval EFI_SECURITY_VIOLATION
44 The user has no permission to start UEFI device drivers on the device path
45 associated with the ControllerHandle or specified by the RemainingDevicePath.
50 CoreConnectController (
51 IN EFI_HANDLE ControllerHandle
,
52 IN EFI_HANDLE
*DriverImageHandle OPTIONAL
,
53 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
,
58 EFI_STATUS ReturnStatus
;
60 PROTOCOL_INTERFACE
*Prot
;
63 OPEN_PROTOCOL_DATA
*OpenData
;
64 EFI_DEVICE_PATH_PROTOCOL
*AlignedRemainingDevicePath
;
65 EFI_HANDLE
*ChildHandleBuffer
;
66 UINTN ChildHandleCount
;
68 UINTN HandleFilePathSize
;
69 UINTN RemainingDevicePathSize
;
70 EFI_DEVICE_PATH_PROTOCOL
*HandleFilePath
;
71 EFI_DEVICE_PATH_PROTOCOL
*FilePath
;
72 EFI_DEVICE_PATH_PROTOCOL
*TempFilePath
;
75 // Make sure ControllerHandle is valid
77 Status
= CoreValidateHandle (ControllerHandle
);
78 if (EFI_ERROR (Status
)) {
82 if (gSecurity2
!= NULL
) {
84 // Check whether the user has permission to start UEFI device drivers.
86 Status
= CoreHandleProtocol (ControllerHandle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&HandleFilePath
);
87 if (!EFI_ERROR (Status
)) {
88 ASSERT (HandleFilePath
!= NULL
);
89 FilePath
= HandleFilePath
;
91 if (RemainingDevicePath
!= NULL
&& !Recursive
) {
92 HandleFilePathSize
= GetDevicePathSize (HandleFilePath
) - sizeof (EFI_DEVICE_PATH_PROTOCOL
);
93 RemainingDevicePathSize
= GetDevicePathSize (RemainingDevicePath
);
94 TempFilePath
= AllocateZeroPool (HandleFilePathSize
+ RemainingDevicePathSize
);
95 ASSERT (TempFilePath
!= NULL
);
96 CopyMem (TempFilePath
, HandleFilePath
, HandleFilePathSize
);
97 CopyMem ((UINT8
*) TempFilePath
+ HandleFilePathSize
, RemainingDevicePath
, RemainingDevicePathSize
);
98 FilePath
= TempFilePath
;
100 Status
= gSecurity2
->FileAuthentication (
107 if (TempFilePath
!= NULL
) {
108 FreePool (TempFilePath
);
110 if (EFI_ERROR (Status
)) {
116 Handle
= ControllerHandle
;
119 // Make a copy of RemainingDevicePath to guanatee it is aligned
121 AlignedRemainingDevicePath
= NULL
;
122 if (RemainingDevicePath
!= NULL
) {
123 AlignedRemainingDevicePath
= DuplicateDevicePath (RemainingDevicePath
);
125 if (AlignedRemainingDevicePath
== NULL
) {
126 return EFI_OUT_OF_RESOURCES
;
131 // Connect all drivers to ControllerHandle
132 // If CoreConnectSingleController returns EFI_NOT_READY, then the number of
133 // Driver Binding Protocols in the handle database has increased during the call
134 // so the connect operation must be restarted
137 ReturnStatus
= CoreConnectSingleController (
140 AlignedRemainingDevicePath
142 } while (ReturnStatus
== EFI_NOT_READY
);
145 // Free the aligned copy of RemainingDevicePath
147 if (AlignedRemainingDevicePath
!= NULL
) {
148 CoreFreePool (AlignedRemainingDevicePath
);
152 // If recursive, then connect all drivers to all of ControllerHandle's children
156 // Acquire the protocol lock on the handle database so the child handles can be collected
158 CoreAcquireProtocolLock ();
161 // Make sure the DriverBindingHandle is valid
163 Status
= CoreValidateHandle (ControllerHandle
);
164 if (EFI_ERROR (Status
)) {
166 // Release the protocol lock on the handle database
168 CoreReleaseProtocolLock ();
175 // Count ControllerHandle's children
177 for (Link
= Handle
->Protocols
.ForwardLink
, ChildHandleCount
= 0; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
178 Prot
= CR(Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
179 for (ProtLink
= Prot
->OpenList
.ForwardLink
;
180 ProtLink
!= &Prot
->OpenList
;
181 ProtLink
= ProtLink
->ForwardLink
) {
182 OpenData
= CR (ProtLink
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
183 if ((OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
190 // Allocate a handle buffer for ControllerHandle's children
192 ChildHandleBuffer
= AllocatePool (ChildHandleCount
* sizeof(EFI_HANDLE
));
193 if (ChildHandleBuffer
== NULL
) {
194 CoreReleaseProtocolLock ();
195 return EFI_OUT_OF_RESOURCES
;
199 // Fill in a handle buffer with ControllerHandle's children
201 for (Link
= Handle
->Protocols
.ForwardLink
, ChildHandleCount
= 0; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
202 Prot
= CR(Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
203 for (ProtLink
= Prot
->OpenList
.ForwardLink
;
204 ProtLink
!= &Prot
->OpenList
;
205 ProtLink
= ProtLink
->ForwardLink
) {
206 OpenData
= CR (ProtLink
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
207 if ((OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
208 ChildHandleBuffer
[ChildHandleCount
] = OpenData
->ControllerHandle
;
215 // Release the protocol lock on the handle database
217 CoreReleaseProtocolLock ();
220 // Recursively connect each child handle
222 for (Index
= 0; Index
< ChildHandleCount
; Index
++) {
223 CoreConnectController (
224 ChildHandleBuffer
[Index
],
232 // Free the handle buffer of ControllerHandle's children
234 CoreFreePool (ChildHandleBuffer
);
242 Add Driver Binding Protocols from Context Driver Image Handles to sorted
243 Driver Binding Protocol list.
245 @param DriverBindingHandle Handle of the driver binding
247 @param NumberOfSortedDriverBindingProtocols Number Of sorted driver binding
249 @param SortedDriverBindingProtocols The sorted protocol list.
250 @param DriverBindingHandleCount Driver Binding Handle Count.
251 @param DriverBindingHandleBuffer The buffer of driver binding
252 protocol to be modified.
253 @param IsImageHandle Indicate whether
254 DriverBindingHandle is an image
261 AddSortedDriverBindingProtocol (
262 IN EFI_HANDLE DriverBindingHandle
,
263 IN OUT UINTN
*NumberOfSortedDriverBindingProtocols
,
264 IN OUT EFI_DRIVER_BINDING_PROTOCOL
**SortedDriverBindingProtocols
,
265 IN UINTN DriverBindingHandleCount
,
266 IN OUT EFI_HANDLE
*DriverBindingHandleBuffer
,
267 IN BOOLEAN IsImageHandle
271 EFI_DRIVER_BINDING_PROTOCOL
*DriverBinding
;
275 // Make sure the DriverBindingHandle is valid
277 Status
= CoreValidateHandle (DriverBindingHandle
);
278 if (EFI_ERROR (Status
)) {
283 // If IsImageHandle is TRUE, then DriverBindingHandle is an image handle
284 // Find all the DriverBindingHandles associated with that image handle and add them to the sorted list
288 // Loop through all the Driver Binding Handles
290 for (Index
= 0; Index
< DriverBindingHandleCount
; Index
++) {
292 // Retrieve the Driver Binding Protocol associated with each Driver Binding Handle
294 Status
= CoreHandleProtocol (
295 DriverBindingHandleBuffer
[Index
],
296 &gEfiDriverBindingProtocolGuid
,
297 (VOID
**) &DriverBinding
299 if (EFI_ERROR (Status
) || DriverBinding
== NULL
) {
304 // If the ImageHandle associated with DriverBinding matches DriverBindingHandle,
305 // then add the DriverBindingProtocol[Index] to the sorted list
307 if (DriverBinding
->ImageHandle
== DriverBindingHandle
) {
308 AddSortedDriverBindingProtocol (
309 DriverBindingHandleBuffer
[Index
],
310 NumberOfSortedDriverBindingProtocols
,
311 SortedDriverBindingProtocols
,
312 DriverBindingHandleCount
,
313 DriverBindingHandleBuffer
,
322 // Retrieve the Driver Binding Protocol from DriverBindingHandle
324 Status
= CoreHandleProtocol(
326 &gEfiDriverBindingProtocolGuid
,
327 (VOID
**) &DriverBinding
330 // If DriverBindingHandle does not support the Driver Binding Protocol then return
332 if (EFI_ERROR (Status
) || DriverBinding
== NULL
) {
337 // See if DriverBinding is already in the sorted list
339 for (Index
= 0; Index
< *NumberOfSortedDriverBindingProtocols
&& Index
< DriverBindingHandleCount
; Index
++) {
340 if (DriverBinding
== SortedDriverBindingProtocols
[Index
]) {
346 // Add DriverBinding to the end of the list
348 if (*NumberOfSortedDriverBindingProtocols
< DriverBindingHandleCount
) {
349 SortedDriverBindingProtocols
[*NumberOfSortedDriverBindingProtocols
] = DriverBinding
;
351 *NumberOfSortedDriverBindingProtocols
= *NumberOfSortedDriverBindingProtocols
+ 1;
354 // Mark the cooresponding handle in DriverBindingHandleBuffer as used
356 for (Index
= 0; Index
< DriverBindingHandleCount
; Index
++) {
357 if (DriverBindingHandleBuffer
[Index
] == DriverBindingHandle
) {
358 DriverBindingHandleBuffer
[Index
] = NULL
;
365 Connects a controller to a driver.
367 @param ControllerHandle Handle of the controller to be
369 @param ContextDriverImageHandles DriverImageHandle A pointer to an
370 ordered list of driver image
372 @param RemainingDevicePath RemainingDevicePath A pointer to
373 the device path that specifies a
374 child of the controller
375 specified by ControllerHandle.
377 @retval EFI_SUCCESS One or more drivers were
378 connected to ControllerHandle.
379 @retval EFI_OUT_OF_RESOURCES No enough system resources to
380 complete the request.
381 @retval EFI_NOT_FOUND No drivers were connected to
386 CoreConnectSingleController (
387 IN EFI_HANDLE ControllerHandle
,
388 IN EFI_HANDLE
*ContextDriverImageHandles OPTIONAL
,
389 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
394 EFI_HANDLE DriverImageHandle
;
395 EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL
*PlatformDriverOverride
;
396 EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL
*BusSpecificDriverOverride
;
397 UINTN DriverBindingHandleCount
;
398 EFI_HANDLE
*DriverBindingHandleBuffer
;
399 UINTN NewDriverBindingHandleCount
;
400 EFI_HANDLE
*NewDriverBindingHandleBuffer
;
401 EFI_DRIVER_BINDING_PROTOCOL
*DriverBinding
;
402 EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL
*DriverFamilyOverride
;
403 UINTN NumberOfSortedDriverBindingProtocols
;
404 EFI_DRIVER_BINDING_PROTOCOL
**SortedDriverBindingProtocols
;
405 UINT32 DriverFamilyOverrideVersion
;
406 UINT32 HighestVersion
;
413 // Initialize local variables
415 DriverBindingHandleCount
= 0;
416 DriverBindingHandleBuffer
= NULL
;
417 NumberOfSortedDriverBindingProtocols
= 0;
418 SortedDriverBindingProtocols
= NULL
;
419 PlatformDriverOverride
= NULL
;
420 NewDriverBindingHandleBuffer
= NULL
;
423 // Get list of all Driver Binding Protocol Instances
425 Status
= CoreLocateHandleBuffer (
427 &gEfiDriverBindingProtocolGuid
,
429 &DriverBindingHandleCount
,
430 &DriverBindingHandleBuffer
432 if (EFI_ERROR (Status
) || (DriverBindingHandleCount
== 0)) {
433 return EFI_NOT_FOUND
;
437 // Allocate a duplicate array for the sorted Driver Binding Protocol Instances
439 SortedDriverBindingProtocols
= AllocatePool (sizeof (VOID
*) * DriverBindingHandleCount
);
440 if (SortedDriverBindingProtocols
== NULL
) {
441 CoreFreePool (DriverBindingHandleBuffer
);
442 return EFI_OUT_OF_RESOURCES
;
446 // Add Driver Binding Protocols from Context Driver Image Handles first
448 if (ContextDriverImageHandles
!= NULL
) {
449 for (Index
= 0; ContextDriverImageHandles
[Index
] != NULL
; Index
++) {
450 AddSortedDriverBindingProtocol (
451 ContextDriverImageHandles
[Index
],
452 &NumberOfSortedDriverBindingProtocols
,
453 SortedDriverBindingProtocols
,
454 DriverBindingHandleCount
,
455 DriverBindingHandleBuffer
,
462 // Add the Platform Driver Override Protocol drivers for ControllerHandle next
464 Status
= CoreLocateProtocol (
465 &gEfiPlatformDriverOverrideProtocolGuid
,
467 (VOID
**) &PlatformDriverOverride
469 if (!EFI_ERROR (Status
) && (PlatformDriverOverride
!= NULL
)) {
470 DriverImageHandle
= NULL
;
472 Status
= PlatformDriverOverride
->GetDriver (
473 PlatformDriverOverride
,
477 if (!EFI_ERROR (Status
)) {
478 AddSortedDriverBindingProtocol (
480 &NumberOfSortedDriverBindingProtocols
,
481 SortedDriverBindingProtocols
,
482 DriverBindingHandleCount
,
483 DriverBindingHandleBuffer
,
487 } while (!EFI_ERROR (Status
));
491 // Add the Driver Family Override Protocol drivers for ControllerHandle
494 HighestIndex
= DriverBindingHandleCount
;
496 for (Index
= 0; Index
< DriverBindingHandleCount
; Index
++) {
497 Status
= CoreHandleProtocol (
498 DriverBindingHandleBuffer
[Index
],
499 &gEfiDriverFamilyOverrideProtocolGuid
,
500 (VOID
**) &DriverFamilyOverride
502 if (!EFI_ERROR (Status
) && (DriverFamilyOverride
!= NULL
)) {
503 DriverFamilyOverrideVersion
= DriverFamilyOverride
->GetVersion (DriverFamilyOverride
);
504 if ((HighestIndex
== DriverBindingHandleCount
) || (DriverFamilyOverrideVersion
> HighestVersion
)) {
505 HighestVersion
= DriverFamilyOverrideVersion
;
506 HighestIndex
= Index
;
511 if (HighestIndex
== DriverBindingHandleCount
) {
515 AddSortedDriverBindingProtocol (
516 DriverBindingHandleBuffer
[HighestIndex
],
517 &NumberOfSortedDriverBindingProtocols
,
518 SortedDriverBindingProtocols
,
519 DriverBindingHandleCount
,
520 DriverBindingHandleBuffer
,
526 // Get the Bus Specific Driver Override Protocol instance on the Controller Handle
528 Status
= CoreHandleProtocol (
530 &gEfiBusSpecificDriverOverrideProtocolGuid
,
531 (VOID
**) &BusSpecificDriverOverride
533 if (!EFI_ERROR (Status
) && (BusSpecificDriverOverride
!= NULL
)) {
534 DriverImageHandle
= NULL
;
536 Status
= BusSpecificDriverOverride
->GetDriver (
537 BusSpecificDriverOverride
,
540 if (!EFI_ERROR (Status
)) {
541 AddSortedDriverBindingProtocol (
543 &NumberOfSortedDriverBindingProtocols
,
544 SortedDriverBindingProtocols
,
545 DriverBindingHandleCount
,
546 DriverBindingHandleBuffer
,
550 } while (!EFI_ERROR (Status
));
554 // Then add all the remaining Driver Binding Protocols
556 SortIndex
= NumberOfSortedDriverBindingProtocols
;
557 for (Index
= 0; Index
< DriverBindingHandleCount
; Index
++) {
558 AddSortedDriverBindingProtocol (
559 DriverBindingHandleBuffer
[Index
],
560 &NumberOfSortedDriverBindingProtocols
,
561 SortedDriverBindingProtocols
,
562 DriverBindingHandleCount
,
563 DriverBindingHandleBuffer
,
569 // Free the Driver Binding Handle Buffer
571 CoreFreePool (DriverBindingHandleBuffer
);
574 // If the number of Driver Binding Protocols has increased since this function started, then return
575 // EFI_NOT_READY, so it will be restarted
577 Status
= CoreLocateHandleBuffer (
579 &gEfiDriverBindingProtocolGuid
,
581 &NewDriverBindingHandleCount
,
582 &NewDriverBindingHandleBuffer
584 CoreFreePool (NewDriverBindingHandleBuffer
);
585 if (NewDriverBindingHandleCount
> DriverBindingHandleCount
) {
587 // Free any buffers that were allocated with AllocatePool()
589 CoreFreePool (SortedDriverBindingProtocols
);
591 return EFI_NOT_READY
;
595 // Sort the remaining DriverBinding Protocol based on their Version field from
596 // highest to lowest.
598 for ( ; SortIndex
< NumberOfSortedDriverBindingProtocols
; SortIndex
++) {
599 HighestVersion
= SortedDriverBindingProtocols
[SortIndex
]->Version
;
600 HighestIndex
= SortIndex
;
601 for (Index
= SortIndex
+ 1; Index
< NumberOfSortedDriverBindingProtocols
; Index
++) {
602 if (SortedDriverBindingProtocols
[Index
]->Version
> HighestVersion
) {
603 HighestVersion
= SortedDriverBindingProtocols
[Index
]->Version
;
604 HighestIndex
= Index
;
607 if (SortIndex
!= HighestIndex
) {
608 DriverBinding
= SortedDriverBindingProtocols
[SortIndex
];
609 SortedDriverBindingProtocols
[SortIndex
] = SortedDriverBindingProtocols
[HighestIndex
];
610 SortedDriverBindingProtocols
[HighestIndex
] = DriverBinding
;
615 // Loop until no more drivers can be started on ControllerHandle
621 // Loop through the sorted Driver Binding Protocol Instances in order, and see if
622 // any of the Driver Binding Protocols support the controller specified by
625 DriverBinding
= NULL
;
627 for (Index
= 0; (Index
< NumberOfSortedDriverBindingProtocols
) && !DriverFound
; Index
++) {
628 if (SortedDriverBindingProtocols
[Index
] != NULL
) {
629 DriverBinding
= SortedDriverBindingProtocols
[Index
];
630 PERF_START (DriverBinding
->DriverBindingHandle
, "DB:Support:", NULL
, 0);
631 Status
= DriverBinding
->Supported(
636 PERF_END (DriverBinding
->DriverBindingHandle
, "DB:Support:", NULL
, 0);
637 if (!EFI_ERROR (Status
)) {
638 SortedDriverBindingProtocols
[Index
] = NULL
;
642 // A driver was found that supports ControllerHandle, so attempt to start the driver
643 // on ControllerHandle.
645 PERF_START (DriverBinding
->DriverBindingHandle
, "DB:Start:", NULL
, 0);
646 Status
= DriverBinding
->Start (
651 PERF_END (DriverBinding
->DriverBindingHandle
, "DB:Start:", NULL
, 0);
653 if (!EFI_ERROR (Status
)) {
655 // The driver was successfully started on ControllerHandle, so set a flag
662 } while (DriverFound
);
665 // Free any buffers that were allocated with AllocatePool()
667 CoreFreePool (SortedDriverBindingProtocols
);
670 // If at least one driver was started on ControllerHandle, then return EFI_SUCCESS.
677 // If no drivers started and RemainingDevicePath is an End Device Path Node, then return EFI_SUCCESS
679 if (RemainingDevicePath
!= NULL
) {
680 if (IsDevicePathEnd (RemainingDevicePath
)) {
686 // Otherwise, no drivers were started on ControllerHandle, so return EFI_NOT_FOUND
688 return EFI_NOT_FOUND
;
694 Disonnects a controller from a driver
696 @param ControllerHandle ControllerHandle The handle of
697 the controller from which
700 @param DriverImageHandle DriverImageHandle The driver to
701 disconnect from ControllerHandle.
702 @param ChildHandle ChildHandle The handle of the
705 @retval EFI_SUCCESS One or more drivers were
706 disconnected from the controller.
707 @retval EFI_SUCCESS On entry, no drivers are managing
709 @retval EFI_SUCCESS DriverImageHandle is not NULL,
710 and on entry DriverImageHandle is
711 not managing ControllerHandle.
712 @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
713 @retval EFI_INVALID_PARAMETER DriverImageHandle is not NULL,
714 and it is not a valid EFI_HANDLE.
715 @retval EFI_INVALID_PARAMETER ChildHandle is not NULL, and it
716 is not a valid EFI_HANDLE.
717 @retval EFI_OUT_OF_RESOURCES There are not enough resources
718 available to disconnect any
719 drivers from ControllerHandle.
720 @retval EFI_DEVICE_ERROR The controller could not be
721 disconnected because of a device
727 CoreDisconnectController (
728 IN EFI_HANDLE ControllerHandle
,
729 IN EFI_HANDLE DriverImageHandle OPTIONAL
,
730 IN EFI_HANDLE ChildHandle OPTIONAL
735 EFI_HANDLE
*DriverImageHandleBuffer
;
736 EFI_HANDLE
*ChildBuffer
;
739 UINTN DriverImageHandleCount
;
740 UINTN ChildrenToStop
;
741 UINTN ChildBufferCount
;
744 BOOLEAN ChildHandleValid
;
745 BOOLEAN DriverImageHandleValid
;
747 LIST_ENTRY
*ProtLink
;
748 OPEN_PROTOCOL_DATA
*OpenData
;
749 PROTOCOL_INTERFACE
*Prot
;
750 EFI_DRIVER_BINDING_PROTOCOL
*DriverBinding
;
753 // Make sure ControllerHandle is valid
755 Status
= CoreValidateHandle (ControllerHandle
);
756 if (EFI_ERROR (Status
)) {
761 // Make sure ChildHandle is valid if it is not NULL
763 if (ChildHandle
!= NULL
) {
764 Status
= CoreValidateHandle (ChildHandle
);
765 if (EFI_ERROR (Status
)) {
770 Handle
= ControllerHandle
;
773 // Get list of drivers that are currently managing ControllerHandle
775 DriverImageHandleBuffer
= NULL
;
776 DriverImageHandleCount
= 1;
778 if (DriverImageHandle
== NULL
) {
780 // Look at each protocol interface for a match
782 DriverImageHandleCount
= 0;
784 CoreAcquireProtocolLock ();
785 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
786 Prot
= CR(Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
787 for (ProtLink
= Prot
->OpenList
.ForwardLink
;
788 ProtLink
!= &Prot
->OpenList
;
789 ProtLink
= ProtLink
->ForwardLink
) {
790 OpenData
= CR (ProtLink
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
791 if ((OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) != 0) {
792 DriverImageHandleCount
++;
796 CoreReleaseProtocolLock ();
799 // If there are no drivers managing this controller, then return EFI_SUCCESS
801 if (DriverImageHandleCount
== 0) {
802 Status
= EFI_SUCCESS
;
806 DriverImageHandleBuffer
= AllocatePool (sizeof (EFI_HANDLE
) * DriverImageHandleCount
);
807 if (DriverImageHandleBuffer
== NULL
) {
808 Status
= EFI_OUT_OF_RESOURCES
;
812 DriverImageHandleCount
= 0;
814 CoreAcquireProtocolLock ();
815 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
816 Prot
= CR(Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
817 for (ProtLink
= Prot
->OpenList
.ForwardLink
;
818 ProtLink
!= &Prot
->OpenList
;
819 ProtLink
= ProtLink
->ForwardLink
) {
820 OpenData
= CR (ProtLink
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
821 if ((OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) != 0) {
823 for (Index
= 0; Index
< DriverImageHandleCount
; Index
++) {
824 if (DriverImageHandleBuffer
[Index
] == OpenData
->AgentHandle
) {
830 DriverImageHandleBuffer
[DriverImageHandleCount
] = OpenData
->AgentHandle
;
831 DriverImageHandleCount
++;
836 CoreReleaseProtocolLock ();
840 for (HandleIndex
= 0; HandleIndex
< DriverImageHandleCount
; HandleIndex
++) {
842 if (DriverImageHandleBuffer
!= NULL
) {
843 DriverImageHandle
= DriverImageHandleBuffer
[HandleIndex
];
847 // Get the Driver Binding Protocol of the driver that is managing this controller
849 Status
= CoreHandleProtocol (
851 &gEfiDriverBindingProtocolGuid
,
852 (VOID
**)&DriverBinding
854 if (EFI_ERROR (Status
) || DriverBinding
== NULL
) {
855 Status
= EFI_INVALID_PARAMETER
;
860 // Look at each protocol interface for a match
862 DriverImageHandleValid
= FALSE
;
863 ChildBufferCount
= 0;
865 CoreAcquireProtocolLock ();
866 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
867 Prot
= CR(Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
868 for (ProtLink
= Prot
->OpenList
.ForwardLink
;
869 ProtLink
!= &Prot
->OpenList
;
870 ProtLink
= ProtLink
->ForwardLink
) {
871 OpenData
= CR (ProtLink
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
872 if (OpenData
->AgentHandle
== DriverImageHandle
) {
873 if ((OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
876 if ((OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) != 0) {
877 DriverImageHandleValid
= TRUE
;
882 CoreReleaseProtocolLock ();
884 if (DriverImageHandleValid
) {
885 ChildHandleValid
= FALSE
;
887 if (ChildBufferCount
!= 0) {
888 ChildBuffer
= AllocatePool (sizeof (EFI_HANDLE
) * ChildBufferCount
);
889 if (ChildBuffer
== NULL
) {
890 Status
= EFI_OUT_OF_RESOURCES
;
894 ChildBufferCount
= 0;
896 CoreAcquireProtocolLock ();
897 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
898 Prot
= CR(Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
899 for (ProtLink
= Prot
->OpenList
.ForwardLink
;
900 ProtLink
!= &Prot
->OpenList
;
901 ProtLink
= ProtLink
->ForwardLink
) {
902 OpenData
= CR (ProtLink
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
903 if ((OpenData
->AgentHandle
== DriverImageHandle
) &&
904 ((OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0)) {
906 for (Index
= 0; Index
< ChildBufferCount
; Index
++) {
907 if (ChildBuffer
[Index
] == OpenData
->ControllerHandle
) {
913 ChildBuffer
[ChildBufferCount
] = OpenData
->ControllerHandle
;
914 if (ChildHandle
== ChildBuffer
[ChildBufferCount
]) {
915 ChildHandleValid
= TRUE
;
922 CoreReleaseProtocolLock ();
925 if (ChildHandle
== NULL
|| ChildHandleValid
) {
927 Status
= EFI_SUCCESS
;
928 if (ChildBufferCount
> 0) {
929 if (ChildHandle
!= NULL
) {
931 Status
= DriverBinding
->Stop (DriverBinding
, ControllerHandle
, ChildrenToStop
, &ChildHandle
);
933 ChildrenToStop
= ChildBufferCount
;
934 Status
= DriverBinding
->Stop (DriverBinding
, ControllerHandle
, ChildrenToStop
, ChildBuffer
);
937 if (!EFI_ERROR (Status
) && ((ChildHandle
== NULL
) || (ChildBufferCount
== ChildrenToStop
))) {
938 Status
= DriverBinding
->Stop (DriverBinding
, ControllerHandle
, 0, NULL
);
940 if (!EFI_ERROR (Status
)) {
945 if (ChildBuffer
!= NULL
) {
946 CoreFreePool (ChildBuffer
);
952 Status
= EFI_SUCCESS
;
954 Status
= EFI_NOT_FOUND
;
959 if (DriverImageHandleBuffer
!= NULL
) {
960 CoreFreePool (DriverImageHandleBuffer
);