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