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