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
;
421 // Get list of all Driver Binding Protocol Instances
423 Status
= CoreLocateHandleBuffer (
425 &gEfiDriverBindingProtocolGuid
,
427 &DriverBindingHandleCount
,
428 &DriverBindingHandleBuffer
430 if (EFI_ERROR (Status
) || (DriverBindingHandleCount
== 0)) {
431 return EFI_NOT_FOUND
;
435 // Allocate a duplicate array for the sorted Driver Binding Protocol Instances
437 SortedDriverBindingProtocols
= AllocatePool (sizeof (VOID
*) * DriverBindingHandleCount
);
438 if (SortedDriverBindingProtocols
== NULL
) {
439 CoreFreePool (DriverBindingHandleBuffer
);
440 return EFI_OUT_OF_RESOURCES
;
444 // Add Driver Binding Protocols from Context Driver Image Handles first
446 if (ContextDriverImageHandles
!= NULL
) {
447 for (Index
= 0; ContextDriverImageHandles
[Index
] != NULL
; Index
++) {
448 AddSortedDriverBindingProtocol (
449 ContextDriverImageHandles
[Index
],
450 &NumberOfSortedDriverBindingProtocols
,
451 SortedDriverBindingProtocols
,
452 DriverBindingHandleCount
,
453 DriverBindingHandleBuffer
,
460 // Add the Platform Driver Override Protocol drivers for ControllerHandle next
462 Status
= CoreLocateProtocol (
463 &gEfiPlatformDriverOverrideProtocolGuid
,
465 (VOID
**) &PlatformDriverOverride
467 if (!EFI_ERROR (Status
) && (PlatformDriverOverride
!= NULL
)) {
468 DriverImageHandle
= NULL
;
470 Status
= PlatformDriverOverride
->GetDriver (
471 PlatformDriverOverride
,
475 if (!EFI_ERROR (Status
)) {
476 AddSortedDriverBindingProtocol (
478 &NumberOfSortedDriverBindingProtocols
,
479 SortedDriverBindingProtocols
,
480 DriverBindingHandleCount
,
481 DriverBindingHandleBuffer
,
485 } while (!EFI_ERROR (Status
));
489 // Add the Driver Family Override Protocol drivers for ControllerHandle
492 HighestIndex
= DriverBindingHandleCount
;
494 for (Index
= 0; Index
< DriverBindingHandleCount
; Index
++) {
495 Status
= CoreHandleProtocol (
496 DriverBindingHandleBuffer
[Index
],
497 &gEfiDriverFamilyOverrideProtocolGuid
,
498 (VOID
**) &DriverFamilyOverride
500 if (!EFI_ERROR (Status
) && (DriverFamilyOverride
!= NULL
)) {
501 DriverFamilyOverrideVersion
= DriverFamilyOverride
->GetVersion (DriverFamilyOverride
);
502 if ((HighestIndex
== DriverBindingHandleCount
) || (DriverFamilyOverrideVersion
> HighestVersion
)) {
503 HighestVersion
= DriverFamilyOverrideVersion
;
504 HighestIndex
= Index
;
509 if (HighestIndex
== DriverBindingHandleCount
) {
513 AddSortedDriverBindingProtocol (
514 DriverBindingHandleBuffer
[HighestIndex
],
515 &NumberOfSortedDriverBindingProtocols
,
516 SortedDriverBindingProtocols
,
517 DriverBindingHandleCount
,
518 DriverBindingHandleBuffer
,
524 // Get the Bus Specific Driver Override Protocol instance on the Controller Handle
526 Status
= CoreHandleProtocol (
528 &gEfiBusSpecificDriverOverrideProtocolGuid
,
529 (VOID
**) &BusSpecificDriverOverride
531 if (!EFI_ERROR (Status
) && (BusSpecificDriverOverride
!= NULL
)) {
532 DriverImageHandle
= NULL
;
534 Status
= BusSpecificDriverOverride
->GetDriver (
535 BusSpecificDriverOverride
,
538 if (!EFI_ERROR (Status
)) {
539 AddSortedDriverBindingProtocol (
541 &NumberOfSortedDriverBindingProtocols
,
542 SortedDriverBindingProtocols
,
543 DriverBindingHandleCount
,
544 DriverBindingHandleBuffer
,
548 } while (!EFI_ERROR (Status
));
552 // Then add all the remaining Driver Binding Protocols
554 SortIndex
= NumberOfSortedDriverBindingProtocols
;
555 for (Index
= 0; Index
< DriverBindingHandleCount
; Index
++) {
556 AddSortedDriverBindingProtocol (
557 DriverBindingHandleBuffer
[Index
],
558 &NumberOfSortedDriverBindingProtocols
,
559 SortedDriverBindingProtocols
,
560 DriverBindingHandleCount
,
561 DriverBindingHandleBuffer
,
567 // Free the Driver Binding Handle Buffer
569 CoreFreePool (DriverBindingHandleBuffer
);
572 // If the number of Driver Binding Protocols has increased since this function started, then return
573 // EFI_NOT_READY, so it will be restarted
575 Status
= CoreLocateHandleBuffer (
577 &gEfiDriverBindingProtocolGuid
,
579 &NewDriverBindingHandleCount
,
580 &NewDriverBindingHandleBuffer
582 CoreFreePool (NewDriverBindingHandleBuffer
);
583 if (NewDriverBindingHandleCount
> DriverBindingHandleCount
) {
585 // Free any buffers that were allocated with AllocatePool()
587 CoreFreePool (SortedDriverBindingProtocols
);
589 return EFI_NOT_READY
;
593 // Sort the remaining DriverBinding Protocol based on their Version field from
594 // highest to lowest.
596 for ( ; SortIndex
< NumberOfSortedDriverBindingProtocols
; SortIndex
++) {
597 HighestVersion
= SortedDriverBindingProtocols
[SortIndex
]->Version
;
598 HighestIndex
= SortIndex
;
599 for (Index
= SortIndex
+ 1; Index
< NumberOfSortedDriverBindingProtocols
; Index
++) {
600 if (SortedDriverBindingProtocols
[Index
]->Version
> HighestVersion
) {
601 HighestVersion
= SortedDriverBindingProtocols
[Index
]->Version
;
602 HighestIndex
= Index
;
605 if (SortIndex
!= HighestIndex
) {
606 DriverBinding
= SortedDriverBindingProtocols
[SortIndex
];
607 SortedDriverBindingProtocols
[SortIndex
] = SortedDriverBindingProtocols
[HighestIndex
];
608 SortedDriverBindingProtocols
[HighestIndex
] = DriverBinding
;
613 // Loop until no more drivers can be started on ControllerHandle
619 // Loop through the sorted Driver Binding Protocol Instances in order, and see if
620 // any of the Driver Binding Protocols support the controller specified by
623 DriverBinding
= NULL
;
625 for (Index
= 0; (Index
< NumberOfSortedDriverBindingProtocols
) && !DriverFound
; Index
++) {
626 if (SortedDriverBindingProtocols
[Index
] != NULL
) {
627 DriverBinding
= SortedDriverBindingProtocols
[Index
];
628 PERF_START (DriverBinding
->DriverBindingHandle
, "DB:Support:", NULL
, 0);
629 Status
= DriverBinding
->Supported(
634 PERF_END (DriverBinding
->DriverBindingHandle
, "DB:Support:", NULL
, 0);
635 if (!EFI_ERROR (Status
)) {
636 SortedDriverBindingProtocols
[Index
] = NULL
;
640 // A driver was found that supports ControllerHandle, so attempt to start the driver
641 // on ControllerHandle.
643 PERF_START (DriverBinding
->DriverBindingHandle
, "DB:Start:", NULL
, 0);
644 Status
= DriverBinding
->Start (
649 PERF_END (DriverBinding
->DriverBindingHandle
, "DB:Start:", NULL
, 0);
651 if (!EFI_ERROR (Status
)) {
653 // The driver was successfully started on ControllerHandle, so set a flag
660 } while (DriverFound
);
663 // Free any buffers that were allocated with AllocatePool()
665 CoreFreePool (SortedDriverBindingProtocols
);
668 // If at least one driver was started on ControllerHandle, then return EFI_SUCCESS.
675 // If no drivers started and RemainingDevicePath is an End Device Path Node, then return EFI_SUCCESS
677 if (RemainingDevicePath
!= NULL
) {
678 if (IsDevicePathEnd (RemainingDevicePath
)) {
684 // Otherwise, no drivers were started on ControllerHandle, so return EFI_NOT_FOUND
686 return EFI_NOT_FOUND
;
692 Disonnects a controller from a driver
694 @param ControllerHandle ControllerHandle The handle of
695 the controller from which
698 @param DriverImageHandle DriverImageHandle The driver to
699 disconnect from ControllerHandle.
700 @param ChildHandle ChildHandle The handle of the
703 @retval EFI_SUCCESS One or more drivers were
704 disconnected from the controller.
705 @retval EFI_SUCCESS On entry, no drivers are managing
707 @retval EFI_SUCCESS DriverImageHandle is not NULL,
708 and on entry DriverImageHandle is
709 not managing ControllerHandle.
710 @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
711 @retval EFI_INVALID_PARAMETER DriverImageHandle is not NULL,
712 and it is not a valid EFI_HANDLE.
713 @retval EFI_INVALID_PARAMETER ChildHandle is not NULL, and it
714 is not a valid EFI_HANDLE.
715 @retval EFI_OUT_OF_RESOURCES There are not enough resources
716 available to disconnect any
717 drivers from ControllerHandle.
718 @retval EFI_DEVICE_ERROR The controller could not be
719 disconnected because of a device
725 CoreDisconnectController (
726 IN EFI_HANDLE ControllerHandle
,
727 IN EFI_HANDLE DriverImageHandle OPTIONAL
,
728 IN EFI_HANDLE ChildHandle OPTIONAL
733 EFI_HANDLE
*DriverImageHandleBuffer
;
734 EFI_HANDLE
*ChildBuffer
;
737 UINTN DriverImageHandleCount
;
738 UINTN ChildrenToStop
;
739 UINTN ChildBufferCount
;
742 BOOLEAN ChildHandleValid
;
743 BOOLEAN DriverImageHandleValid
;
745 LIST_ENTRY
*ProtLink
;
746 OPEN_PROTOCOL_DATA
*OpenData
;
747 PROTOCOL_INTERFACE
*Prot
;
748 EFI_DRIVER_BINDING_PROTOCOL
*DriverBinding
;
751 // Make sure ControllerHandle is valid
753 Status
= CoreValidateHandle (ControllerHandle
);
754 if (EFI_ERROR (Status
)) {
759 // Make sure ChildHandle is valid if it is not NULL
761 if (ChildHandle
!= NULL
) {
762 Status
= CoreValidateHandle (ChildHandle
);
763 if (EFI_ERROR (Status
)) {
768 Handle
= ControllerHandle
;
771 // Get list of drivers that are currently managing ControllerHandle
773 DriverImageHandleBuffer
= NULL
;
774 DriverImageHandleCount
= 1;
776 if (DriverImageHandle
== NULL
) {
778 // Look at each protocol interface for a match
780 DriverImageHandleCount
= 0;
782 CoreAcquireProtocolLock ();
783 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
784 Prot
= CR(Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
785 for (ProtLink
= Prot
->OpenList
.ForwardLink
;
786 ProtLink
!= &Prot
->OpenList
;
787 ProtLink
= ProtLink
->ForwardLink
) {
788 OpenData
= CR (ProtLink
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
789 if ((OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) != 0) {
790 DriverImageHandleCount
++;
794 CoreReleaseProtocolLock ();
797 // If there are no drivers managing this controller, then return EFI_SUCCESS
799 if (DriverImageHandleCount
== 0) {
800 Status
= EFI_SUCCESS
;
804 DriverImageHandleBuffer
= AllocatePool (sizeof (EFI_HANDLE
) * DriverImageHandleCount
);
805 if (DriverImageHandleBuffer
== NULL
) {
806 Status
= EFI_OUT_OF_RESOURCES
;
810 DriverImageHandleCount
= 0;
812 CoreAcquireProtocolLock ();
813 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
814 Prot
= CR(Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
815 for (ProtLink
= Prot
->OpenList
.ForwardLink
;
816 ProtLink
!= &Prot
->OpenList
;
817 ProtLink
= ProtLink
->ForwardLink
) {
818 OpenData
= CR (ProtLink
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
819 if ((OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) != 0) {
821 for (Index
= 0; Index
< DriverImageHandleCount
; Index
++) {
822 if (DriverImageHandleBuffer
[Index
] == OpenData
->AgentHandle
) {
828 DriverImageHandleBuffer
[DriverImageHandleCount
] = OpenData
->AgentHandle
;
829 DriverImageHandleCount
++;
834 CoreReleaseProtocolLock ();
838 for (HandleIndex
= 0; HandleIndex
< DriverImageHandleCount
; HandleIndex
++) {
840 if (DriverImageHandleBuffer
!= NULL
) {
841 DriverImageHandle
= DriverImageHandleBuffer
[HandleIndex
];
845 // Get the Driver Binding Protocol of the driver that is managing this controller
847 Status
= CoreHandleProtocol (
849 &gEfiDriverBindingProtocolGuid
,
850 (VOID
**)&DriverBinding
852 if (EFI_ERROR (Status
) || DriverBinding
== NULL
) {
853 Status
= EFI_INVALID_PARAMETER
;
858 // Look at each protocol interface for a match
860 DriverImageHandleValid
= FALSE
;
861 ChildBufferCount
= 0;
863 CoreAcquireProtocolLock ();
864 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
865 Prot
= CR(Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
866 for (ProtLink
= Prot
->OpenList
.ForwardLink
;
867 ProtLink
!= &Prot
->OpenList
;
868 ProtLink
= ProtLink
->ForwardLink
) {
869 OpenData
= CR (ProtLink
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
870 if (OpenData
->AgentHandle
== DriverImageHandle
) {
871 if ((OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
874 if ((OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) != 0) {
875 DriverImageHandleValid
= TRUE
;
880 CoreReleaseProtocolLock ();
882 if (DriverImageHandleValid
) {
883 ChildHandleValid
= FALSE
;
885 if (ChildBufferCount
!= 0) {
886 ChildBuffer
= AllocatePool (sizeof (EFI_HANDLE
) * ChildBufferCount
);
887 if (ChildBuffer
== NULL
) {
888 Status
= EFI_OUT_OF_RESOURCES
;
892 ChildBufferCount
= 0;
894 CoreAcquireProtocolLock ();
895 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
896 Prot
= CR(Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
897 for (ProtLink
= Prot
->OpenList
.ForwardLink
;
898 ProtLink
!= &Prot
->OpenList
;
899 ProtLink
= ProtLink
->ForwardLink
) {
900 OpenData
= CR (ProtLink
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
901 if ((OpenData
->AgentHandle
== DriverImageHandle
) &&
902 ((OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0)) {
904 for (Index
= 0; Index
< ChildBufferCount
; Index
++) {
905 if (ChildBuffer
[Index
] == OpenData
->ControllerHandle
) {
911 ChildBuffer
[ChildBufferCount
] = OpenData
->ControllerHandle
;
912 if (ChildHandle
== ChildBuffer
[ChildBufferCount
]) {
913 ChildHandleValid
= TRUE
;
920 CoreReleaseProtocolLock ();
923 if (ChildHandle
== NULL
|| ChildHandleValid
) {
925 Status
= EFI_SUCCESS
;
926 if (ChildBufferCount
> 0) {
927 if (ChildHandle
!= NULL
) {
929 Status
= DriverBinding
->Stop (DriverBinding
, ControllerHandle
, ChildrenToStop
, &ChildHandle
);
931 ChildrenToStop
= ChildBufferCount
;
932 Status
= DriverBinding
->Stop (DriverBinding
, ControllerHandle
, ChildrenToStop
, ChildBuffer
);
935 if (!EFI_ERROR (Status
) && ((ChildHandle
== NULL
) || (ChildBufferCount
== ChildrenToStop
))) {
936 Status
= DriverBinding
->Stop (DriverBinding
, ControllerHandle
, 0, NULL
);
938 if (!EFI_ERROR (Status
)) {
943 if (ChildBuffer
!= NULL
) {
944 CoreFreePool (ChildBuffer
);
950 Status
= EFI_SUCCESS
;
952 Status
= EFI_NOT_FOUND
;
957 if (DriverImageHandleBuffer
!= NULL
) {
958 CoreFreePool (DriverImageHandleBuffer
);