]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Dxe/Hand/DriverSupport.c
56050a1f9fa71ffd677e73cdf7afa6ab271d0b43
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Hand / DriverSupport.c
1 /** @file
2 Support functions to connect/disconnect UEFI Driver model Protocol
3
4 Copyright (c) 2006 - 2010, Intel Corporation. <BR>
5 All rights reserved. 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
9
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.
12
13 **/
14
15 #include "DxeMain.h"
16 #include "Handle.h"
17
18
19 //
20 // Driver Support Functions
21 //
22 /**
23 Connects one or more drivers to a controller.
24
25 @param ControllerHandle Handle of the controller to be
26 connected.
27 @param DriverImageHandle DriverImageHandle A pointer to an
28 ordered list of driver image
29 handles.
30 @param RemainingDevicePath RemainingDevicePath A pointer to
31 the device path that specifies a
32 child of the controller specified
33 by ControllerHandle.
34 @param Recursive Whether the function would be
35 called recursively or not.
36
37 @return Status code.
38
39 **/
40 EFI_STATUS
41 EFIAPI
42 CoreConnectController (
43 IN EFI_HANDLE ControllerHandle,
44 IN EFI_HANDLE *DriverImageHandle OPTIONAL,
45 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL,
46 IN BOOLEAN Recursive
47 )
48 {
49 EFI_STATUS Status;
50 EFI_STATUS ReturnStatus;
51 IHANDLE *Handle;
52 PROTOCOL_INTERFACE *Prot;
53 LIST_ENTRY *Link;
54 LIST_ENTRY *ProtLink;
55 OPEN_PROTOCOL_DATA *OpenData;
56 EFI_DEVICE_PATH_PROTOCOL *AlignedRemainingDevicePath;
57 EFI_HANDLE *ChildHandleBuffer;
58 UINTN ChildHandleCount;
59 UINTN Index;
60
61 //
62 // Make sure ControllerHandle is valid
63 //
64 Status = CoreValidateHandle (ControllerHandle);
65 if (EFI_ERROR (Status)) {
66 return Status;
67 }
68
69 Handle = ControllerHandle;
70
71 //
72 // Make a copy of RemainingDevicePath to guanatee it is aligned
73 //
74 AlignedRemainingDevicePath = NULL;
75 if (RemainingDevicePath != NULL) {
76 AlignedRemainingDevicePath = DuplicateDevicePath (RemainingDevicePath);
77
78 if (AlignedRemainingDevicePath == NULL) {
79 return EFI_OUT_OF_RESOURCES;
80 }
81 }
82
83 //
84 // Connect all drivers to ControllerHandle
85 // If CoreConnectSingleController returns EFI_NOT_READY, then the number of
86 // Driver Binding Protocols in the handle database has increased during the call
87 // so the connect operation must be restarted
88 //
89 do {
90 ReturnStatus = CoreConnectSingleController (
91 ControllerHandle,
92 DriverImageHandle,
93 AlignedRemainingDevicePath
94 );
95 } while (ReturnStatus == EFI_NOT_READY);
96
97 //
98 // Free the aligned copy of RemainingDevicePath
99 //
100 if (AlignedRemainingDevicePath != NULL) {
101 CoreFreePool (AlignedRemainingDevicePath);
102 }
103
104 //
105 // If recursive, then connect all drivers to all of ControllerHandle's children
106 //
107 if (Recursive) {
108 //
109 // Acquire the protocol lock on the handle database so the child handles can be collected
110 //
111 CoreAcquireProtocolLock ();
112
113 //
114 // Make sure the DriverBindingHandle is valid
115 //
116 Status = CoreValidateHandle (ControllerHandle);
117 if (EFI_ERROR (Status)) {
118 //
119 // Release the protocol lock on the handle database
120 //
121 CoreReleaseProtocolLock ();
122
123 return ReturnStatus;
124 }
125
126
127 //
128 // Count ControllerHandle's children
129 //
130 for (Link = Handle->Protocols.ForwardLink, ChildHandleCount = 0; Link != &Handle->Protocols; Link = Link->ForwardLink) {
131 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
132 for (ProtLink = Prot->OpenList.ForwardLink;
133 ProtLink != &Prot->OpenList;
134 ProtLink = ProtLink->ForwardLink) {
135 OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
136 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
137 ChildHandleCount++;
138 }
139 }
140 }
141
142 //
143 // Allocate a handle buffer for ControllerHandle's children
144 //
145 ChildHandleBuffer = AllocatePool (ChildHandleCount * sizeof(EFI_HANDLE));
146 if (ChildHandleBuffer == NULL) {
147 CoreReleaseProtocolLock ();
148 return EFI_OUT_OF_RESOURCES;
149 }
150
151 //
152 // Fill in a handle buffer with ControllerHandle's children
153 //
154 for (Link = Handle->Protocols.ForwardLink, ChildHandleCount = 0; Link != &Handle->Protocols; Link = Link->ForwardLink) {
155 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
156 for (ProtLink = Prot->OpenList.ForwardLink;
157 ProtLink != &Prot->OpenList;
158 ProtLink = ProtLink->ForwardLink) {
159 OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
160 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
161 ChildHandleBuffer[ChildHandleCount] = OpenData->ControllerHandle;
162 ChildHandleCount++;
163 }
164 }
165 }
166
167 //
168 // Release the protocol lock on the handle database
169 //
170 CoreReleaseProtocolLock ();
171
172 //
173 // Recursively connect each child handle
174 //
175 for (Index = 0; Index < ChildHandleCount; Index++) {
176 CoreConnectController (
177 ChildHandleBuffer[Index],
178 NULL,
179 NULL,
180 TRUE
181 );
182 }
183
184 //
185 // Free the handle buffer of ControllerHandle's children
186 //
187 CoreFreePool (ChildHandleBuffer);
188 }
189
190 return ReturnStatus;
191 }
192
193
194 /**
195 Add Driver Binding Protocols from Context Driver Image Handles to sorted
196 Driver Binding Protocol list.
197
198 @param DriverBindingHandle Handle of the driver binding
199 protocol.
200 @param NumberOfSortedDriverBindingProtocols Number Of sorted driver binding
201 protocols
202 @param SortedDriverBindingProtocols The sorted protocol list.
203 @param DriverBindingHandleCount Driver Binding Handle Count.
204 @param DriverBindingHandleBuffer The buffer of driver binding
205 protocol to be modified.
206 @param IsImageHandle Indicate whether
207 DriverBindingHandle is an image
208 handle
209
210 @return None.
211
212 **/
213 VOID
214 AddSortedDriverBindingProtocol (
215 IN EFI_HANDLE DriverBindingHandle,
216 IN OUT UINTN *NumberOfSortedDriverBindingProtocols,
217 IN OUT EFI_DRIVER_BINDING_PROTOCOL **SortedDriverBindingProtocols,
218 IN UINTN DriverBindingHandleCount,
219 IN OUT EFI_HANDLE *DriverBindingHandleBuffer,
220 IN BOOLEAN IsImageHandle
221 )
222 {
223 EFI_STATUS Status;
224 EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
225 UINTN Index;
226
227 //
228 // Make sure the DriverBindingHandle is valid
229 //
230 Status = CoreValidateHandle (DriverBindingHandle);
231 if (EFI_ERROR (Status)) {
232 return;
233 }
234
235 //
236 // If IsImageHandle is TRUE, then DriverBindingHandle is an image handle
237 // Find all the DriverBindingHandles associated with that image handle and add them to the sorted list
238 //
239 if (IsImageHandle) {
240 //
241 // Loop through all the Driver Binding Handles
242 //
243 for (Index = 0; Index < DriverBindingHandleCount; Index++) {
244 //
245 // Retrieve the Driver Binding Protocol associated with each Driver Binding Handle
246 //
247 Status = CoreHandleProtocol (
248 DriverBindingHandleBuffer[Index],
249 &gEfiDriverBindingProtocolGuid,
250 (VOID **) &DriverBinding
251 );
252 if (EFI_ERROR (Status) || DriverBinding == NULL) {
253 continue;
254 }
255
256 //
257 // If the ImageHandle associated with DriverBinding matches DriverBindingHandle,
258 // then add the DriverBindingProtocol[Index] to the sorted list
259 //
260 if (DriverBinding->ImageHandle == DriverBindingHandle) {
261 AddSortedDriverBindingProtocol (
262 DriverBindingHandleBuffer[Index],
263 NumberOfSortedDriverBindingProtocols,
264 SortedDriverBindingProtocols,
265 DriverBindingHandleCount,
266 DriverBindingHandleBuffer,
267 FALSE
268 );
269 }
270 }
271 return;
272 }
273
274 //
275 // Retrieve the Driver Binding Protocol from DriverBindingHandle
276 //
277 Status = CoreHandleProtocol(
278 DriverBindingHandle,
279 &gEfiDriverBindingProtocolGuid,
280 (VOID **) &DriverBinding
281 );
282 //
283 // If DriverBindingHandle does not support the Driver Binding Protocol then return
284 //
285 if (EFI_ERROR (Status) || DriverBinding == NULL) {
286 return;
287 }
288
289 //
290 // See if DriverBinding is already in the sorted list
291 //
292 for (Index = 0; Index < *NumberOfSortedDriverBindingProtocols && Index < DriverBindingHandleCount; Index++) {
293 if (DriverBinding == SortedDriverBindingProtocols[Index]) {
294 return;
295 }
296 }
297
298 //
299 // Add DriverBinding to the end of the list
300 //
301 if (*NumberOfSortedDriverBindingProtocols < DriverBindingHandleCount) {
302 SortedDriverBindingProtocols[*NumberOfSortedDriverBindingProtocols] = DriverBinding;
303 }
304 *NumberOfSortedDriverBindingProtocols = *NumberOfSortedDriverBindingProtocols + 1;
305
306 //
307 // Mark the cooresponding handle in DriverBindingHandleBuffer as used
308 //
309 for (Index = 0; Index < DriverBindingHandleCount; Index++) {
310 if (DriverBindingHandleBuffer[Index] == DriverBindingHandle) {
311 DriverBindingHandleBuffer[Index] = NULL;
312 }
313 }
314 }
315
316
317 /**
318 Connects a controller to a driver.
319
320 @param ControllerHandle Handle of the controller to be
321 connected.
322 @param ContextDriverImageHandles DriverImageHandle A pointer to an
323 ordered list of driver image
324 handles.
325 @param RemainingDevicePath RemainingDevicePath A pointer to
326 the device path that specifies a
327 child of the controller
328 specified by ControllerHandle.
329
330 @retval EFI_SUCCESS One or more drivers were
331 connected to ControllerHandle.
332 @retval EFI_OUT_OF_RESOURCES No enough system resources to
333 complete the request.
334 @retval EFI_NOT_FOUND No drivers were connected to
335 ControllerHandle.
336
337 **/
338 EFI_STATUS
339 CoreConnectSingleController (
340 IN EFI_HANDLE ControllerHandle,
341 IN EFI_HANDLE *ContextDriverImageHandles OPTIONAL,
342 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
343 )
344 {
345 EFI_STATUS Status;
346 UINTN Index;
347 EFI_HANDLE DriverImageHandle;
348 EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL *PlatformDriverOverride;
349 EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *BusSpecificDriverOverride;
350 UINTN DriverBindingHandleCount;
351 EFI_HANDLE *DriverBindingHandleBuffer;
352 UINTN NewDriverBindingHandleCount;
353 EFI_HANDLE *NewDriverBindingHandleBuffer;
354 EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
355 UINTN NumberOfSortedDriverBindingProtocols;
356 EFI_DRIVER_BINDING_PROTOCOL **SortedDriverBindingProtocols;
357 UINT32 HighestVersion;
358 UINTN HighestIndex;
359 UINTN SortIndex;
360 BOOLEAN OneStarted;
361 BOOLEAN DriverFound;
362
363 //
364 // Initialize local variables
365 //
366 DriverBindingHandleCount = 0;
367 DriverBindingHandleBuffer = NULL;
368 NumberOfSortedDriverBindingProtocols = 0;
369 SortedDriverBindingProtocols = NULL;
370
371 //
372 // Get list of all Driver Binding Protocol Instances
373 //
374 Status = CoreLocateHandleBuffer (
375 ByProtocol,
376 &gEfiDriverBindingProtocolGuid,
377 NULL,
378 &DriverBindingHandleCount,
379 &DriverBindingHandleBuffer
380 );
381 if (EFI_ERROR (Status) || (DriverBindingHandleCount == 0)) {
382 return EFI_NOT_FOUND;
383 }
384
385 //
386 // Allocate a duplicate array for the sorted Driver Binding Protocol Instances
387 //
388 SortedDriverBindingProtocols = AllocatePool (sizeof (VOID *) * DriverBindingHandleCount);
389 if (SortedDriverBindingProtocols == NULL) {
390 CoreFreePool (DriverBindingHandleBuffer);
391 return EFI_OUT_OF_RESOURCES;
392 }
393
394 //
395 // Add Driver Binding Protocols from Context Driver Image Handles first
396 //
397 if (ContextDriverImageHandles != NULL) {
398 for (Index = 0; ContextDriverImageHandles[Index] != NULL; Index++) {
399 AddSortedDriverBindingProtocol (
400 ContextDriverImageHandles[Index],
401 &NumberOfSortedDriverBindingProtocols,
402 SortedDriverBindingProtocols,
403 DriverBindingHandleCount,
404 DriverBindingHandleBuffer,
405 FALSE
406 );
407 }
408 }
409
410 //
411 // Add the Platform Driver Override Protocol drivers for ControllerHandle next
412 //
413 Status = CoreLocateProtocol (
414 &gEfiPlatformDriverOverrideProtocolGuid,
415 NULL,
416 (VOID **) &PlatformDriverOverride
417 );
418 if (!EFI_ERROR (Status) && (PlatformDriverOverride != NULL)) {
419 DriverImageHandle = NULL;
420 do {
421 Status = PlatformDriverOverride->GetDriver (
422 PlatformDriverOverride,
423 ControllerHandle,
424 &DriverImageHandle
425 );
426 if (!EFI_ERROR (Status)) {
427 AddSortedDriverBindingProtocol (
428 DriverImageHandle,
429 &NumberOfSortedDriverBindingProtocols,
430 SortedDriverBindingProtocols,
431 DriverBindingHandleCount,
432 DriverBindingHandleBuffer,
433 TRUE
434 );
435 }
436 } while (!EFI_ERROR (Status));
437 }
438
439 //
440 // Get the Bus Specific Driver Override Protocol instance on the Controller Handle
441 //
442 Status = CoreHandleProtocol (
443 ControllerHandle,
444 &gEfiBusSpecificDriverOverrideProtocolGuid,
445 (VOID **) &BusSpecificDriverOverride
446 );
447 if (!EFI_ERROR (Status) && (BusSpecificDriverOverride != NULL)) {
448 DriverImageHandle = NULL;
449 do {
450 Status = BusSpecificDriverOverride->GetDriver (
451 BusSpecificDriverOverride,
452 &DriverImageHandle
453 );
454 if (!EFI_ERROR (Status)) {
455 AddSortedDriverBindingProtocol (
456 DriverImageHandle,
457 &NumberOfSortedDriverBindingProtocols,
458 SortedDriverBindingProtocols,
459 DriverBindingHandleCount,
460 DriverBindingHandleBuffer,
461 TRUE
462 );
463 }
464 } while (!EFI_ERROR (Status));
465 }
466
467 //
468 // Then add all the remaining Driver Binding Protocols
469 //
470 SortIndex = NumberOfSortedDriverBindingProtocols;
471 for (Index = 0; Index < DriverBindingHandleCount; Index++) {
472 AddSortedDriverBindingProtocol (
473 DriverBindingHandleBuffer[Index],
474 &NumberOfSortedDriverBindingProtocols,
475 SortedDriverBindingProtocols,
476 DriverBindingHandleCount,
477 DriverBindingHandleBuffer,
478 FALSE
479 );
480 }
481
482 //
483 // Free the Driver Binding Handle Buffer
484 //
485 CoreFreePool (DriverBindingHandleBuffer);
486
487 //
488 // If the number of Driver Binding Protocols has increased since this function started, then return
489 // EFI_NOT_READY, so it will be restarted
490 //
491 Status = CoreLocateHandleBuffer (
492 ByProtocol,
493 &gEfiDriverBindingProtocolGuid,
494 NULL,
495 &NewDriverBindingHandleCount,
496 &NewDriverBindingHandleBuffer
497 );
498 CoreFreePool (NewDriverBindingHandleBuffer);
499 if (NewDriverBindingHandleCount > DriverBindingHandleCount) {
500 //
501 // Free any buffers that were allocated with AllocatePool()
502 //
503 CoreFreePool (SortedDriverBindingProtocols);
504
505 return EFI_NOT_READY;
506 }
507
508 //
509 // Sort the remaining DriverBinding Protocol based on their Version field from
510 // highest to lowest.
511 //
512 for ( ; SortIndex < NumberOfSortedDriverBindingProtocols; SortIndex++) {
513 HighestVersion = SortedDriverBindingProtocols[SortIndex]->Version;
514 HighestIndex = SortIndex;
515 for (Index = SortIndex + 1; Index < NumberOfSortedDriverBindingProtocols; Index++) {
516 if (SortedDriverBindingProtocols[Index]->Version > HighestVersion) {
517 HighestVersion = SortedDriverBindingProtocols[Index]->Version;
518 HighestIndex = Index;
519 }
520 }
521 if (SortIndex != HighestIndex) {
522 DriverBinding = SortedDriverBindingProtocols[SortIndex];
523 SortedDriverBindingProtocols[SortIndex] = SortedDriverBindingProtocols[HighestIndex];
524 SortedDriverBindingProtocols[HighestIndex] = DriverBinding;
525 }
526 }
527
528 //
529 // Loop until no more drivers can be started on ControllerHandle
530 //
531 OneStarted = FALSE;
532 do {
533
534 //
535 // Loop through the sorted Driver Binding Protocol Instances in order, and see if
536 // any of the Driver Binding Protocols support the controller specified by
537 // ControllerHandle.
538 //
539 DriverBinding = NULL;
540 DriverFound = FALSE;
541 for (Index = 0; (Index < NumberOfSortedDriverBindingProtocols) && !DriverFound; Index++) {
542 if (SortedDriverBindingProtocols[Index] != NULL) {
543 DriverBinding = SortedDriverBindingProtocols[Index];
544 PERF_START (DriverBinding->DriverBindingHandle, "DB:Support:", NULL, 0);
545 Status = DriverBinding->Supported(
546 DriverBinding,
547 ControllerHandle,
548 RemainingDevicePath
549 );
550 PERF_END (DriverBinding->DriverBindingHandle, "DB:Support:", NULL, 0);
551 if (!EFI_ERROR (Status)) {
552 SortedDriverBindingProtocols[Index] = NULL;
553 DriverFound = TRUE;
554
555 //
556 // A driver was found that supports ControllerHandle, so attempt to start the driver
557 // on ControllerHandle.
558 //
559 PERF_START (DriverBinding->DriverBindingHandle, "DB:Start:", NULL, 0);
560 Status = DriverBinding->Start (
561 DriverBinding,
562 ControllerHandle,
563 RemainingDevicePath
564 );
565 PERF_END (DriverBinding->DriverBindingHandle, "DB:Start:", NULL, 0);
566
567 if (!EFI_ERROR (Status)) {
568 //
569 // The driver was successfully started on ControllerHandle, so set a flag
570 //
571 OneStarted = TRUE;
572 }
573 }
574 }
575 }
576 } while (DriverFound);
577
578 //
579 // Free any buffers that were allocated with AllocatePool()
580 //
581 CoreFreePool (SortedDriverBindingProtocols);
582
583 //
584 // If at least one driver was started on ControllerHandle, then return EFI_SUCCESS.
585 //
586 if (OneStarted) {
587 return EFI_SUCCESS;
588 }
589
590 //
591 // If no drivers started and RemainingDevicePath is an End Device Path Node, then return EFI_SUCCESS
592 //
593 if (RemainingDevicePath != NULL) {
594 if (IsDevicePathEnd (RemainingDevicePath)) {
595 return EFI_SUCCESS;
596 }
597 }
598
599 //
600 // Otherwise, no drivers were started on ControllerHandle, so return EFI_NOT_FOUND
601 //
602 return EFI_NOT_FOUND;
603 }
604
605
606
607 /**
608 Disonnects a controller from a driver
609
610 @param ControllerHandle ControllerHandle The handle of
611 the controller from which
612 driver(s) are to be
613 disconnected.
614 @param DriverImageHandle DriverImageHandle The driver to
615 disconnect from ControllerHandle.
616 @param ChildHandle ChildHandle The handle of the
617 child to destroy.
618
619 @retval EFI_SUCCESS One or more drivers were
620 disconnected from the controller.
621 @retval EFI_SUCCESS On entry, no drivers are managing
622 ControllerHandle.
623 @retval EFI_SUCCESS DriverImageHandle is not NULL,
624 and on entry DriverImageHandle is
625 not managing ControllerHandle.
626 @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid
627 EFI_HANDLE.
628 @retval EFI_INVALID_PARAMETER DriverImageHandle is not NULL,
629 and it is not a valid EFI_HANDLE.
630 @retval EFI_INVALID_PARAMETER ChildHandle is not NULL, and it
631 is not a valid EFI_HANDLE.
632 @retval EFI_OUT_OF_RESOURCES There are not enough resources
633 available to disconnect any
634 drivers from ControllerHandle.
635 @retval EFI_DEVICE_ERROR The controller could not be
636 disconnected because of a device
637 error.
638
639 **/
640 EFI_STATUS
641 EFIAPI
642 CoreDisconnectController (
643 IN EFI_HANDLE ControllerHandle,
644 IN EFI_HANDLE DriverImageHandle OPTIONAL,
645 IN EFI_HANDLE ChildHandle OPTIONAL
646 )
647 {
648 EFI_STATUS Status;
649 IHANDLE *Handle;
650 EFI_HANDLE *DriverImageHandleBuffer;
651 EFI_HANDLE *ChildBuffer;
652 UINTN Index;
653 UINTN HandleIndex;
654 UINTN DriverImageHandleCount;
655 UINTN ChildrenToStop;
656 UINTN ChildBufferCount;
657 UINTN StopCount;
658 BOOLEAN Duplicate;
659 BOOLEAN ChildHandleValid;
660 BOOLEAN DriverImageHandleValid;
661 LIST_ENTRY *Link;
662 LIST_ENTRY *ProtLink;
663 OPEN_PROTOCOL_DATA *OpenData;
664 PROTOCOL_INTERFACE *Prot;
665 EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
666
667 //
668 // Make sure ControllerHandle is valid
669 //
670 Status = CoreValidateHandle (ControllerHandle);
671 if (EFI_ERROR (Status)) {
672 return Status;
673 }
674
675 //
676 // Make sure ChildHandle is valid if it is not NULL
677 //
678 if (ChildHandle != NULL) {
679 Status = CoreValidateHandle (ChildHandle);
680 if (EFI_ERROR (Status)) {
681 return Status;
682 }
683 }
684
685 Handle = ControllerHandle;
686
687 //
688 // Get list of drivers that are currently managing ControllerHandle
689 //
690 DriverImageHandleBuffer = NULL;
691 DriverImageHandleCount = 1;
692
693 if (DriverImageHandle == NULL) {
694 //
695 // Look at each protocol interface for a match
696 //
697 DriverImageHandleCount = 0;
698
699 CoreAcquireProtocolLock ();
700 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
701 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
702 for (ProtLink = Prot->OpenList.ForwardLink;
703 ProtLink != &Prot->OpenList;
704 ProtLink = ProtLink->ForwardLink) {
705 OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
706 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
707 DriverImageHandleCount++;
708 }
709 }
710 }
711 CoreReleaseProtocolLock ();
712
713 //
714 // If there are no drivers managing this controller, then return EFI_SUCCESS
715 //
716 if (DriverImageHandleCount == 0) {
717 Status = EFI_SUCCESS;
718 goto Done;
719 }
720
721 DriverImageHandleBuffer = AllocatePool (sizeof (EFI_HANDLE) * DriverImageHandleCount);
722 if (DriverImageHandleBuffer == NULL) {
723 Status = EFI_OUT_OF_RESOURCES;
724 goto Done;
725 }
726
727 DriverImageHandleCount = 0;
728
729 CoreAcquireProtocolLock ();
730 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
731 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
732 for (ProtLink = Prot->OpenList.ForwardLink;
733 ProtLink != &Prot->OpenList;
734 ProtLink = ProtLink->ForwardLink) {
735 OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
736 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
737 Duplicate = FALSE;
738 for (Index = 0; Index< DriverImageHandleCount; Index++) {
739 if (DriverImageHandleBuffer[Index] == OpenData->AgentHandle) {
740 Duplicate = TRUE;
741 break;
742 }
743 }
744 if (!Duplicate) {
745 DriverImageHandleBuffer[DriverImageHandleCount] = OpenData->AgentHandle;
746 DriverImageHandleCount++;
747 }
748 }
749 }
750 }
751 CoreReleaseProtocolLock ();
752 }
753
754 StopCount = 0;
755 for (HandleIndex = 0; HandleIndex < DriverImageHandleCount; HandleIndex++) {
756
757 if (DriverImageHandleBuffer != NULL) {
758 DriverImageHandle = DriverImageHandleBuffer[HandleIndex];
759 }
760
761 //
762 // Get the Driver Binding Protocol of the driver that is managing this controller
763 //
764 Status = CoreHandleProtocol (
765 DriverImageHandle,
766 &gEfiDriverBindingProtocolGuid,
767 (VOID **)&DriverBinding
768 );
769 if (EFI_ERROR (Status) || DriverBinding == NULL) {
770 Status = EFI_INVALID_PARAMETER;
771 goto Done;
772 }
773
774 //
775 // Look at each protocol interface for a match
776 //
777 DriverImageHandleValid = FALSE;
778 ChildBufferCount = 0;
779
780 CoreAcquireProtocolLock ();
781 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
782 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
783 for (ProtLink = Prot->OpenList.ForwardLink;
784 ProtLink != &Prot->OpenList;
785 ProtLink = ProtLink->ForwardLink) {
786 OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
787 if (OpenData->AgentHandle == DriverImageHandle) {
788 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
789 ChildBufferCount++;
790 }
791 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
792 DriverImageHandleValid = TRUE;
793 }
794 }
795 }
796 }
797 CoreReleaseProtocolLock ();
798
799 if (DriverImageHandleValid) {
800 ChildHandleValid = FALSE;
801 ChildBuffer = NULL;
802 if (ChildBufferCount != 0) {
803 ChildBuffer = AllocatePool (sizeof (EFI_HANDLE) * ChildBufferCount);
804 if (ChildBuffer == NULL) {
805 Status = EFI_OUT_OF_RESOURCES;
806 goto Done;
807 }
808
809 ChildBufferCount = 0;
810
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->AgentHandle == DriverImageHandle) &&
819 ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0)) {
820 Duplicate = FALSE;
821 for (Index = 0; Index < ChildBufferCount; Index++) {
822 if (ChildBuffer[Index] == OpenData->ControllerHandle) {
823 Duplicate = TRUE;
824 break;
825 }
826 }
827 if (!Duplicate) {
828 ChildBuffer[ChildBufferCount] = OpenData->ControllerHandle;
829 if (ChildHandle == ChildBuffer[ChildBufferCount]) {
830 ChildHandleValid = TRUE;
831 }
832 ChildBufferCount++;
833 }
834 }
835 }
836 }
837 CoreReleaseProtocolLock ();
838 }
839
840 if (ChildHandle == NULL || ChildHandleValid) {
841 ChildrenToStop = 0;
842 Status = EFI_SUCCESS;
843 if (ChildBufferCount > 0) {
844 if (ChildHandle != NULL) {
845 ChildrenToStop = 1;
846 Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, &ChildHandle);
847 } else {
848 ChildrenToStop = ChildBufferCount;
849 Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, ChildBuffer);
850 }
851 }
852 if (!EFI_ERROR (Status) && ((ChildHandle == NULL) || (ChildBufferCount == ChildrenToStop))) {
853 Status = DriverBinding->Stop (DriverBinding, ControllerHandle, 0, NULL);
854 }
855 if (!EFI_ERROR (Status)) {
856 StopCount++;
857 }
858 }
859
860 if (ChildBuffer != NULL) {
861 CoreFreePool (ChildBuffer);
862 }
863 }
864 }
865
866 if (StopCount > 0) {
867 Status = EFI_SUCCESS;
868 } else {
869 Status = EFI_NOT_FOUND;
870 }
871
872 Done:
873
874 if (DriverImageHandleBuffer != NULL) {
875 CoreFreePool (DriverImageHandleBuffer);
876 }
877
878 return Status;
879 }