2 Support functions to connect/disconnect UEFI Driver model Protocol
4 Copyright (c) 2006 - 2012, 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 FilePath
= HandleFilePath
;
90 if (RemainingDevicePath
!= NULL
&& !Recursive
) {
91 HandleFilePathSize
= GetDevicePathSize (HandleFilePath
) - sizeof (EFI_DEVICE_PATH_PROTOCOL
);
92 RemainingDevicePathSize
= GetDevicePathSize (RemainingDevicePath
);
93 TempFilePath
= AllocateZeroPool (HandleFilePathSize
+ RemainingDevicePathSize
);
94 ASSERT (TempFilePath
!= NULL
);
95 CopyMem (TempFilePath
, HandleFilePath
, HandleFilePathSize
);
96 CopyMem ((UINT8
*) TempFilePath
+ HandleFilePathSize
, RemainingDevicePath
, RemainingDevicePathSize
);
97 FilePath
= TempFilePath
;
99 Status
= gSecurity2
->FileAuthentication (
106 if (TempFilePath
!= NULL
) {
107 FreePool (TempFilePath
);
109 if (EFI_ERROR (Status
)) {
115 Handle
= ControllerHandle
;
118 // Make a copy of RemainingDevicePath to guanatee it is aligned
120 AlignedRemainingDevicePath
= NULL
;
121 if (RemainingDevicePath
!= NULL
) {
122 AlignedRemainingDevicePath
= DuplicateDevicePath (RemainingDevicePath
);
124 if (AlignedRemainingDevicePath
== NULL
) {
125 return EFI_OUT_OF_RESOURCES
;
130 // Connect all drivers to ControllerHandle
131 // If CoreConnectSingleController returns EFI_NOT_READY, then the number of
132 // Driver Binding Protocols in the handle database has increased during the call
133 // so the connect operation must be restarted
136 ReturnStatus
= CoreConnectSingleController (
139 AlignedRemainingDevicePath
141 } while (ReturnStatus
== EFI_NOT_READY
);
144 // Free the aligned copy of RemainingDevicePath
146 if (AlignedRemainingDevicePath
!= NULL
) {
147 CoreFreePool (AlignedRemainingDevicePath
);
151 // If recursive, then connect all drivers to all of ControllerHandle's children
155 // Acquire the protocol lock on the handle database so the child handles can be collected
157 CoreAcquireProtocolLock ();
160 // Make sure the DriverBindingHandle is valid
162 Status
= CoreValidateHandle (ControllerHandle
);
163 if (EFI_ERROR (Status
)) {
165 // Release the protocol lock on the handle database
167 CoreReleaseProtocolLock ();
174 // Count ControllerHandle's children
176 for (Link
= Handle
->Protocols
.ForwardLink
, ChildHandleCount
= 0; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
177 Prot
= CR(Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
178 for (ProtLink
= Prot
->OpenList
.ForwardLink
;
179 ProtLink
!= &Prot
->OpenList
;
180 ProtLink
= ProtLink
->ForwardLink
) {
181 OpenData
= CR (ProtLink
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
182 if ((OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
189 // Allocate a handle buffer for ControllerHandle's children
191 ChildHandleBuffer
= AllocatePool (ChildHandleCount
* sizeof(EFI_HANDLE
));
192 if (ChildHandleBuffer
== NULL
) {
193 CoreReleaseProtocolLock ();
194 return EFI_OUT_OF_RESOURCES
;
198 // Fill in a handle buffer with ControllerHandle's children
200 for (Link
= Handle
->Protocols
.ForwardLink
, ChildHandleCount
= 0; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
201 Prot
= CR(Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
202 for (ProtLink
= Prot
->OpenList
.ForwardLink
;
203 ProtLink
!= &Prot
->OpenList
;
204 ProtLink
= ProtLink
->ForwardLink
) {
205 OpenData
= CR (ProtLink
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
206 if ((OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
207 ChildHandleBuffer
[ChildHandleCount
] = OpenData
->ControllerHandle
;
214 // Release the protocol lock on the handle database
216 CoreReleaseProtocolLock ();
219 // Recursively connect each child handle
221 for (Index
= 0; Index
< ChildHandleCount
; Index
++) {
222 CoreConnectController (
223 ChildHandleBuffer
[Index
],
231 // Free the handle buffer of ControllerHandle's children
233 CoreFreePool (ChildHandleBuffer
);
241 Add Driver Binding Protocols from Context Driver Image Handles to sorted
242 Driver Binding Protocol list.
244 @param DriverBindingHandle Handle of the driver binding
246 @param NumberOfSortedDriverBindingProtocols Number Of sorted driver binding
248 @param SortedDriverBindingProtocols The sorted protocol list.
249 @param DriverBindingHandleCount Driver Binding Handle Count.
250 @param DriverBindingHandleBuffer The buffer of driver binding
251 protocol to be modified.
252 @param IsImageHandle Indicate whether
253 DriverBindingHandle is an image
260 AddSortedDriverBindingProtocol (
261 IN EFI_HANDLE DriverBindingHandle
,
262 IN OUT UINTN
*NumberOfSortedDriverBindingProtocols
,
263 IN OUT EFI_DRIVER_BINDING_PROTOCOL
**SortedDriverBindingProtocols
,
264 IN UINTN DriverBindingHandleCount
,
265 IN OUT EFI_HANDLE
*DriverBindingHandleBuffer
,
266 IN BOOLEAN IsImageHandle
270 EFI_DRIVER_BINDING_PROTOCOL
*DriverBinding
;
274 // Make sure the DriverBindingHandle is valid
276 Status
= CoreValidateHandle (DriverBindingHandle
);
277 if (EFI_ERROR (Status
)) {
282 // If IsImageHandle is TRUE, then DriverBindingHandle is an image handle
283 // Find all the DriverBindingHandles associated with that image handle and add them to the sorted list
287 // Loop through all the Driver Binding Handles
289 for (Index
= 0; Index
< DriverBindingHandleCount
; Index
++) {
291 // Retrieve the Driver Binding Protocol associated with each Driver Binding Handle
293 Status
= CoreHandleProtocol (
294 DriverBindingHandleBuffer
[Index
],
295 &gEfiDriverBindingProtocolGuid
,
296 (VOID
**) &DriverBinding
298 if (EFI_ERROR (Status
) || DriverBinding
== NULL
) {
303 // If the ImageHandle associated with DriverBinding matches DriverBindingHandle,
304 // then add the DriverBindingProtocol[Index] to the sorted list
306 if (DriverBinding
->ImageHandle
== DriverBindingHandle
) {
307 AddSortedDriverBindingProtocol (
308 DriverBindingHandleBuffer
[Index
],
309 NumberOfSortedDriverBindingProtocols
,
310 SortedDriverBindingProtocols
,
311 DriverBindingHandleCount
,
312 DriverBindingHandleBuffer
,
321 // Retrieve the Driver Binding Protocol from DriverBindingHandle
323 Status
= CoreHandleProtocol(
325 &gEfiDriverBindingProtocolGuid
,
326 (VOID
**) &DriverBinding
329 // If DriverBindingHandle does not support the Driver Binding Protocol then return
331 if (EFI_ERROR (Status
) || DriverBinding
== NULL
) {
336 // See if DriverBinding is already in the sorted list
338 for (Index
= 0; Index
< *NumberOfSortedDriverBindingProtocols
&& Index
< DriverBindingHandleCount
; Index
++) {
339 if (DriverBinding
== SortedDriverBindingProtocols
[Index
]) {
345 // Add DriverBinding to the end of the list
347 if (*NumberOfSortedDriverBindingProtocols
< DriverBindingHandleCount
) {
348 SortedDriverBindingProtocols
[*NumberOfSortedDriverBindingProtocols
] = DriverBinding
;
350 *NumberOfSortedDriverBindingProtocols
= *NumberOfSortedDriverBindingProtocols
+ 1;
353 // Mark the cooresponding handle in DriverBindingHandleBuffer as used
355 for (Index
= 0; Index
< DriverBindingHandleCount
; Index
++) {
356 if (DriverBindingHandleBuffer
[Index
] == DriverBindingHandle
) {
357 DriverBindingHandleBuffer
[Index
] = NULL
;
364 Connects a controller to a driver.
366 @param ControllerHandle Handle of the controller to be
368 @param ContextDriverImageHandles DriverImageHandle A pointer to an
369 ordered list of driver image
371 @param RemainingDevicePath RemainingDevicePath A pointer to
372 the device path that specifies a
373 child of the controller
374 specified by ControllerHandle.
376 @retval EFI_SUCCESS One or more drivers were
377 connected to ControllerHandle.
378 @retval EFI_OUT_OF_RESOURCES No enough system resources to
379 complete the request.
380 @retval EFI_NOT_FOUND No drivers were connected to
385 CoreConnectSingleController (
386 IN EFI_HANDLE ControllerHandle
,
387 IN EFI_HANDLE
*ContextDriverImageHandles OPTIONAL
,
388 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
393 EFI_HANDLE DriverImageHandle
;
394 EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL
*PlatformDriverOverride
;
395 EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL
*BusSpecificDriverOverride
;
396 UINTN DriverBindingHandleCount
;
397 EFI_HANDLE
*DriverBindingHandleBuffer
;
398 UINTN NewDriverBindingHandleCount
;
399 EFI_HANDLE
*NewDriverBindingHandleBuffer
;
400 EFI_DRIVER_BINDING_PROTOCOL
*DriverBinding
;
401 EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL
*DriverFamilyOverride
;
402 UINTN NumberOfSortedDriverBindingProtocols
;
403 EFI_DRIVER_BINDING_PROTOCOL
**SortedDriverBindingProtocols
;
404 UINT32 DriverFamilyOverrideVersion
;
405 UINT32 HighestVersion
;
412 // Initialize local variables
414 DriverBindingHandleCount
= 0;
415 DriverBindingHandleBuffer
= NULL
;
416 NumberOfSortedDriverBindingProtocols
= 0;
417 SortedDriverBindingProtocols
= NULL
;
420 // Get list of all Driver Binding Protocol Instances
422 Status
= CoreLocateHandleBuffer (
424 &gEfiDriverBindingProtocolGuid
,
426 &DriverBindingHandleCount
,
427 &DriverBindingHandleBuffer
429 if (EFI_ERROR (Status
) || (DriverBindingHandleCount
== 0)) {
430 return EFI_NOT_FOUND
;
434 // Allocate a duplicate array for the sorted Driver Binding Protocol Instances
436 SortedDriverBindingProtocols
= AllocatePool (sizeof (VOID
*) * DriverBindingHandleCount
);
437 if (SortedDriverBindingProtocols
== NULL
) {
438 CoreFreePool (DriverBindingHandleBuffer
);
439 return EFI_OUT_OF_RESOURCES
;
443 // Add Driver Binding Protocols from Context Driver Image Handles first
445 if (ContextDriverImageHandles
!= NULL
) {
446 for (Index
= 0; ContextDriverImageHandles
[Index
] != NULL
; Index
++) {
447 AddSortedDriverBindingProtocol (
448 ContextDriverImageHandles
[Index
],
449 &NumberOfSortedDriverBindingProtocols
,
450 SortedDriverBindingProtocols
,
451 DriverBindingHandleCount
,
452 DriverBindingHandleBuffer
,
459 // Add the Platform Driver Override Protocol drivers for ControllerHandle next
461 Status
= CoreLocateProtocol (
462 &gEfiPlatformDriverOverrideProtocolGuid
,
464 (VOID
**) &PlatformDriverOverride
466 if (!EFI_ERROR (Status
) && (PlatformDriverOverride
!= NULL
)) {
467 DriverImageHandle
= NULL
;
469 Status
= PlatformDriverOverride
->GetDriver (
470 PlatformDriverOverride
,
474 if (!EFI_ERROR (Status
)) {
475 AddSortedDriverBindingProtocol (
477 &NumberOfSortedDriverBindingProtocols
,
478 SortedDriverBindingProtocols
,
479 DriverBindingHandleCount
,
480 DriverBindingHandleBuffer
,
484 } while (!EFI_ERROR (Status
));
488 // Add the Driver Family Override Protocol drivers for ControllerHandle
491 HighestIndex
= DriverBindingHandleCount
;
493 for (Index
= 0; Index
< DriverBindingHandleCount
; Index
++) {
494 Status
= CoreHandleProtocol (
495 DriverBindingHandleBuffer
[Index
],
496 &gEfiDriverFamilyOverrideProtocolGuid
,
497 (VOID
**) &DriverFamilyOverride
499 if (!EFI_ERROR (Status
) && (DriverFamilyOverride
!= NULL
)) {
500 DriverFamilyOverrideVersion
= DriverFamilyOverride
->GetVersion (DriverFamilyOverride
);
501 if ((HighestIndex
== DriverBindingHandleCount
) || (DriverFamilyOverrideVersion
> HighestVersion
)) {
502 HighestVersion
= DriverFamilyOverrideVersion
;
503 HighestIndex
= Index
;
508 if (HighestIndex
== DriverBindingHandleCount
) {
512 AddSortedDriverBindingProtocol (
513 DriverBindingHandleBuffer
[HighestIndex
],
514 &NumberOfSortedDriverBindingProtocols
,
515 SortedDriverBindingProtocols
,
516 DriverBindingHandleCount
,
517 DriverBindingHandleBuffer
,
523 // Get the Bus Specific Driver Override Protocol instance on the Controller Handle
525 Status
= CoreHandleProtocol (
527 &gEfiBusSpecificDriverOverrideProtocolGuid
,
528 (VOID
**) &BusSpecificDriverOverride
530 if (!EFI_ERROR (Status
) && (BusSpecificDriverOverride
!= NULL
)) {
531 DriverImageHandle
= NULL
;
533 Status
= BusSpecificDriverOverride
->GetDriver (
534 BusSpecificDriverOverride
,
537 if (!EFI_ERROR (Status
)) {
538 AddSortedDriverBindingProtocol (
540 &NumberOfSortedDriverBindingProtocols
,
541 SortedDriverBindingProtocols
,
542 DriverBindingHandleCount
,
543 DriverBindingHandleBuffer
,
547 } while (!EFI_ERROR (Status
));
551 // Then add all the remaining Driver Binding Protocols
553 SortIndex
= NumberOfSortedDriverBindingProtocols
;
554 for (Index
= 0; Index
< DriverBindingHandleCount
; Index
++) {
555 AddSortedDriverBindingProtocol (
556 DriverBindingHandleBuffer
[Index
],
557 &NumberOfSortedDriverBindingProtocols
,
558 SortedDriverBindingProtocols
,
559 DriverBindingHandleCount
,
560 DriverBindingHandleBuffer
,
566 // Free the Driver Binding Handle Buffer
568 CoreFreePool (DriverBindingHandleBuffer
);
571 // If the number of Driver Binding Protocols has increased since this function started, then return
572 // EFI_NOT_READY, so it will be restarted
574 Status
= CoreLocateHandleBuffer (
576 &gEfiDriverBindingProtocolGuid
,
578 &NewDriverBindingHandleCount
,
579 &NewDriverBindingHandleBuffer
581 CoreFreePool (NewDriverBindingHandleBuffer
);
582 if (NewDriverBindingHandleCount
> DriverBindingHandleCount
) {
584 // Free any buffers that were allocated with AllocatePool()
586 CoreFreePool (SortedDriverBindingProtocols
);
588 return EFI_NOT_READY
;
592 // Sort the remaining DriverBinding Protocol based on their Version field from
593 // highest to lowest.
595 for ( ; SortIndex
< NumberOfSortedDriverBindingProtocols
; SortIndex
++) {
596 HighestVersion
= SortedDriverBindingProtocols
[SortIndex
]->Version
;
597 HighestIndex
= SortIndex
;
598 for (Index
= SortIndex
+ 1; Index
< NumberOfSortedDriverBindingProtocols
; Index
++) {
599 if (SortedDriverBindingProtocols
[Index
]->Version
> HighestVersion
) {
600 HighestVersion
= SortedDriverBindingProtocols
[Index
]->Version
;
601 HighestIndex
= Index
;
604 if (SortIndex
!= HighestIndex
) {
605 DriverBinding
= SortedDriverBindingProtocols
[SortIndex
];
606 SortedDriverBindingProtocols
[SortIndex
] = SortedDriverBindingProtocols
[HighestIndex
];
607 SortedDriverBindingProtocols
[HighestIndex
] = DriverBinding
;
612 // Loop until no more drivers can be started on ControllerHandle
618 // Loop through the sorted Driver Binding Protocol Instances in order, and see if
619 // any of the Driver Binding Protocols support the controller specified by
622 DriverBinding
= NULL
;
624 for (Index
= 0; (Index
< NumberOfSortedDriverBindingProtocols
) && !DriverFound
; Index
++) {
625 if (SortedDriverBindingProtocols
[Index
] != NULL
) {
626 DriverBinding
= SortedDriverBindingProtocols
[Index
];
627 PERF_START (DriverBinding
->DriverBindingHandle
, "DB:Support:", NULL
, 0);
628 Status
= DriverBinding
->Supported(
633 PERF_END (DriverBinding
->DriverBindingHandle
, "DB:Support:", NULL
, 0);
634 if (!EFI_ERROR (Status
)) {
635 SortedDriverBindingProtocols
[Index
] = NULL
;
639 // A driver was found that supports ControllerHandle, so attempt to start the driver
640 // on ControllerHandle.
642 PERF_START (DriverBinding
->DriverBindingHandle
, "DB:Start:", NULL
, 0);
643 Status
= DriverBinding
->Start (
648 PERF_END (DriverBinding
->DriverBindingHandle
, "DB:Start:", NULL
, 0);
650 if (!EFI_ERROR (Status
)) {
652 // The driver was successfully started on ControllerHandle, so set a flag
659 } while (DriverFound
);
662 // Free any buffers that were allocated with AllocatePool()
664 CoreFreePool (SortedDriverBindingProtocols
);
667 // If at least one driver was started on ControllerHandle, then return EFI_SUCCESS.
674 // If no drivers started and RemainingDevicePath is an End Device Path Node, then return EFI_SUCCESS
676 if (RemainingDevicePath
!= NULL
) {
677 if (IsDevicePathEnd (RemainingDevicePath
)) {
683 // Otherwise, no drivers were started on ControllerHandle, so return EFI_NOT_FOUND
685 return EFI_NOT_FOUND
;
691 Disonnects a controller from a driver
693 @param ControllerHandle ControllerHandle The handle of
694 the controller from which
697 @param DriverImageHandle DriverImageHandle The driver to
698 disconnect from ControllerHandle.
699 @param ChildHandle ChildHandle The handle of the
702 @retval EFI_SUCCESS One or more drivers were
703 disconnected from the controller.
704 @retval EFI_SUCCESS On entry, no drivers are managing
706 @retval EFI_SUCCESS DriverImageHandle is not NULL,
707 and on entry DriverImageHandle is
708 not managing ControllerHandle.
709 @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
710 @retval EFI_INVALID_PARAMETER DriverImageHandle is not NULL,
711 and it is not a valid EFI_HANDLE.
712 @retval EFI_INVALID_PARAMETER ChildHandle is not NULL, and it
713 is not a valid EFI_HANDLE.
714 @retval EFI_OUT_OF_RESOURCES There are not enough resources
715 available to disconnect any
716 drivers from ControllerHandle.
717 @retval EFI_DEVICE_ERROR The controller could not be
718 disconnected because of a device
724 CoreDisconnectController (
725 IN EFI_HANDLE ControllerHandle
,
726 IN EFI_HANDLE DriverImageHandle OPTIONAL
,
727 IN EFI_HANDLE ChildHandle OPTIONAL
732 EFI_HANDLE
*DriverImageHandleBuffer
;
733 EFI_HANDLE
*ChildBuffer
;
736 UINTN DriverImageHandleCount
;
737 UINTN ChildrenToStop
;
738 UINTN ChildBufferCount
;
741 BOOLEAN ChildHandleValid
;
742 BOOLEAN DriverImageHandleValid
;
744 LIST_ENTRY
*ProtLink
;
745 OPEN_PROTOCOL_DATA
*OpenData
;
746 PROTOCOL_INTERFACE
*Prot
;
747 EFI_DRIVER_BINDING_PROTOCOL
*DriverBinding
;
750 // Make sure ControllerHandle is valid
752 Status
= CoreValidateHandle (ControllerHandle
);
753 if (EFI_ERROR (Status
)) {
758 // Make sure ChildHandle is valid if it is not NULL
760 if (ChildHandle
!= NULL
) {
761 Status
= CoreValidateHandle (ChildHandle
);
762 if (EFI_ERROR (Status
)) {
767 Handle
= ControllerHandle
;
770 // Get list of drivers that are currently managing ControllerHandle
772 DriverImageHandleBuffer
= NULL
;
773 DriverImageHandleCount
= 1;
775 if (DriverImageHandle
== NULL
) {
777 // Look at each protocol interface for a match
779 DriverImageHandleCount
= 0;
781 CoreAcquireProtocolLock ();
782 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
783 Prot
= CR(Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
784 for (ProtLink
= Prot
->OpenList
.ForwardLink
;
785 ProtLink
!= &Prot
->OpenList
;
786 ProtLink
= ProtLink
->ForwardLink
) {
787 OpenData
= CR (ProtLink
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
788 if ((OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) != 0) {
789 DriverImageHandleCount
++;
793 CoreReleaseProtocolLock ();
796 // If there are no drivers managing this controller, then return EFI_SUCCESS
798 if (DriverImageHandleCount
== 0) {
799 Status
= EFI_SUCCESS
;
803 DriverImageHandleBuffer
= AllocatePool (sizeof (EFI_HANDLE
) * DriverImageHandleCount
);
804 if (DriverImageHandleBuffer
== NULL
) {
805 Status
= EFI_OUT_OF_RESOURCES
;
809 DriverImageHandleCount
= 0;
811 CoreAcquireProtocolLock ();
812 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
813 Prot
= CR(Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
814 for (ProtLink
= Prot
->OpenList
.ForwardLink
;
815 ProtLink
!= &Prot
->OpenList
;
816 ProtLink
= ProtLink
->ForwardLink
) {
817 OpenData
= CR (ProtLink
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
818 if ((OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) != 0) {
820 for (Index
= 0; Index
< DriverImageHandleCount
; Index
++) {
821 if (DriverImageHandleBuffer
[Index
] == OpenData
->AgentHandle
) {
827 DriverImageHandleBuffer
[DriverImageHandleCount
] = OpenData
->AgentHandle
;
828 DriverImageHandleCount
++;
833 CoreReleaseProtocolLock ();
837 for (HandleIndex
= 0; HandleIndex
< DriverImageHandleCount
; HandleIndex
++) {
839 if (DriverImageHandleBuffer
!= NULL
) {
840 DriverImageHandle
= DriverImageHandleBuffer
[HandleIndex
];
844 // Get the Driver Binding Protocol of the driver that is managing this controller
846 Status
= CoreHandleProtocol (
848 &gEfiDriverBindingProtocolGuid
,
849 (VOID
**)&DriverBinding
851 if (EFI_ERROR (Status
) || DriverBinding
== NULL
) {
852 Status
= EFI_INVALID_PARAMETER
;
857 // Look at each protocol interface for a match
859 DriverImageHandleValid
= FALSE
;
860 ChildBufferCount
= 0;
862 CoreAcquireProtocolLock ();
863 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
864 Prot
= CR(Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
865 for (ProtLink
= Prot
->OpenList
.ForwardLink
;
866 ProtLink
!= &Prot
->OpenList
;
867 ProtLink
= ProtLink
->ForwardLink
) {
868 OpenData
= CR (ProtLink
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
869 if (OpenData
->AgentHandle
== DriverImageHandle
) {
870 if ((OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
873 if ((OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) != 0) {
874 DriverImageHandleValid
= TRUE
;
879 CoreReleaseProtocolLock ();
881 if (DriverImageHandleValid
) {
882 ChildHandleValid
= FALSE
;
884 if (ChildBufferCount
!= 0) {
885 ChildBuffer
= AllocatePool (sizeof (EFI_HANDLE
) * ChildBufferCount
);
886 if (ChildBuffer
== NULL
) {
887 Status
= EFI_OUT_OF_RESOURCES
;
891 ChildBufferCount
= 0;
893 CoreAcquireProtocolLock ();
894 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
895 Prot
= CR(Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
896 for (ProtLink
= Prot
->OpenList
.ForwardLink
;
897 ProtLink
!= &Prot
->OpenList
;
898 ProtLink
= ProtLink
->ForwardLink
) {
899 OpenData
= CR (ProtLink
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
900 if ((OpenData
->AgentHandle
== DriverImageHandle
) &&
901 ((OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0)) {
903 for (Index
= 0; Index
< ChildBufferCount
; Index
++) {
904 if (ChildBuffer
[Index
] == OpenData
->ControllerHandle
) {
910 ChildBuffer
[ChildBufferCount
] = OpenData
->ControllerHandle
;
911 if (ChildHandle
== ChildBuffer
[ChildBufferCount
]) {
912 ChildHandleValid
= TRUE
;
919 CoreReleaseProtocolLock ();
922 if (ChildHandle
== NULL
|| ChildHandleValid
) {
924 Status
= EFI_SUCCESS
;
925 if (ChildBufferCount
> 0) {
926 if (ChildHandle
!= NULL
) {
928 Status
= DriverBinding
->Stop (DriverBinding
, ControllerHandle
, ChildrenToStop
, &ChildHandle
);
930 ChildrenToStop
= ChildBufferCount
;
931 Status
= DriverBinding
->Stop (DriverBinding
, ControllerHandle
, ChildrenToStop
, ChildBuffer
);
934 if (!EFI_ERROR (Status
) && ((ChildHandle
== NULL
) || (ChildBufferCount
== ChildrenToStop
))) {
935 Status
= DriverBinding
->Stop (DriverBinding
, ControllerHandle
, 0, NULL
);
937 if (!EFI_ERROR (Status
)) {
942 if (ChildBuffer
!= NULL
) {
943 CoreFreePool (ChildBuffer
);
949 Status
= EFI_SUCCESS
;
951 Status
= EFI_NOT_FOUND
;
956 if (DriverImageHandleBuffer
!= NULL
) {
957 CoreFreePool (DriverImageHandleBuffer
);