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