]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Dxe/Hand/DriverSupport.c
Fix several coding style violations
[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 #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 Status = DriverBinding->Supported(
545 DriverBinding,
546 ControllerHandle,
547 RemainingDevicePath
548 );
549 if (!EFI_ERROR (Status)) {
550 SortedDriverBindingProtocols[Index] = NULL;
551 DriverFound = TRUE;
552
553 //
554 // A driver was found that supports ControllerHandle, so attempt to start the driver
555 // on ControllerHandle.
556 //
557 PERF_START (DriverBinding->DriverBindingHandle, DRIVERBINDING_START_TOK, NULL, 0);
558 Status = DriverBinding->Start (
559 DriverBinding,
560 ControllerHandle,
561 RemainingDevicePath
562 );
563 PERF_END (DriverBinding->DriverBindingHandle, DRIVERBINDING_START_TOK, NULL, 0);
564
565 if (!EFI_ERROR (Status)) {
566 //
567 // The driver was successfully started on ControllerHandle, so set a flag
568 //
569 OneStarted = TRUE;
570 }
571 }
572 }
573 }
574 } while (DriverFound);
575
576 //
577 // Free any buffers that were allocated with AllocatePool()
578 //
579 CoreFreePool (SortedDriverBindingProtocols);
580
581 //
582 // If at least one driver was started on ControllerHandle, then return EFI_SUCCESS.
583 //
584 if (OneStarted) {
585 return EFI_SUCCESS;
586 }
587
588 //
589 // If no drivers started and RemainingDevicePath is an End Device Path Node, then return EFI_SUCCESS
590 //
591 if (RemainingDevicePath != NULL) {
592 if (IsDevicePathEnd (RemainingDevicePath)) {
593 return EFI_SUCCESS;
594 }
595 }
596
597 //
598 // Otherwise, no drivers were started on ControllerHandle, so return EFI_NOT_FOUND
599 //
600 return EFI_NOT_FOUND;
601 }
602
603
604
605 /**
606 Disonnects a controller from a driver
607
608 @param ControllerHandle ControllerHandle The handle of
609 the controller from which
610 driver(s) are to be
611 disconnected.
612 @param DriverImageHandle DriverImageHandle The driver to
613 disconnect from ControllerHandle.
614 @param ChildHandle ChildHandle The handle of the
615 child to destroy.
616
617 @retval EFI_SUCCESS One or more drivers were
618 disconnected from the controller.
619 @retval EFI_SUCCESS On entry, no drivers are managing
620 ControllerHandle.
621 @retval EFI_SUCCESS DriverImageHandle is not NULL,
622 and on entry DriverImageHandle is
623 not managing ControllerHandle.
624 @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid
625 EFI_HANDLE.
626 @retval EFI_INVALID_PARAMETER DriverImageHandle is not NULL,
627 and it is not a valid EFI_HANDLE.
628 @retval EFI_INVALID_PARAMETER ChildHandle is not NULL, and it
629 is not a valid EFI_HANDLE.
630 @retval EFI_OUT_OF_RESOURCES There are not enough resources
631 available to disconnect any
632 drivers from ControllerHandle.
633 @retval EFI_DEVICE_ERROR The controller could not be
634 disconnected because of a device
635 error.
636
637 **/
638 EFI_STATUS
639 EFIAPI
640 CoreDisconnectController (
641 IN EFI_HANDLE ControllerHandle,
642 IN EFI_HANDLE DriverImageHandle OPTIONAL,
643 IN EFI_HANDLE ChildHandle OPTIONAL
644 )
645 {
646 EFI_STATUS Status;
647 IHANDLE *Handle;
648 EFI_HANDLE *DriverImageHandleBuffer;
649 EFI_HANDLE *ChildBuffer;
650 UINTN Index;
651 UINTN HandleIndex;
652 UINTN DriverImageHandleCount;
653 UINTN ChildrenToStop;
654 UINTN ChildBufferCount;
655 UINTN StopCount;
656 BOOLEAN Duplicate;
657 BOOLEAN ChildHandleValid;
658 BOOLEAN DriverImageHandleValid;
659 LIST_ENTRY *Link;
660 LIST_ENTRY *ProtLink;
661 OPEN_PROTOCOL_DATA *OpenData;
662 PROTOCOL_INTERFACE *Prot;
663 EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
664
665 //
666 // Make sure ControllerHandle is valid
667 //
668 Status = CoreValidateHandle (ControllerHandle);
669 if (EFI_ERROR (Status)) {
670 return Status;
671 }
672
673 //
674 // Make sure ChildHandle is valid if it is not NULL
675 //
676 if (ChildHandle != NULL) {
677 Status = CoreValidateHandle (ChildHandle);
678 if (EFI_ERROR (Status)) {
679 return Status;
680 }
681 }
682
683 Handle = ControllerHandle;
684
685 //
686 // Get list of drivers that are currently managing ControllerHandle
687 //
688 DriverImageHandleBuffer = NULL;
689 DriverImageHandleCount = 1;
690
691 if (DriverImageHandle == NULL) {
692 //
693 // Look at each protocol interface for a match
694 //
695 DriverImageHandleCount = 0;
696
697 CoreAcquireProtocolLock ();
698 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
699 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
700 for (ProtLink = Prot->OpenList.ForwardLink;
701 ProtLink != &Prot->OpenList;
702 ProtLink = ProtLink->ForwardLink) {
703 OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
704 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
705 DriverImageHandleCount++;
706 }
707 }
708 }
709 CoreReleaseProtocolLock ();
710
711 //
712 // If there are no drivers managing this controller, then return EFI_SUCCESS
713 //
714 if (DriverImageHandleCount == 0) {
715 Status = EFI_SUCCESS;
716 goto Done;
717 }
718
719 DriverImageHandleBuffer = AllocatePool (sizeof (EFI_HANDLE) * DriverImageHandleCount);
720 if (DriverImageHandleBuffer == NULL) {
721 Status = EFI_OUT_OF_RESOURCES;
722 goto Done;
723 }
724
725 DriverImageHandleCount = 0;
726
727 CoreAcquireProtocolLock ();
728 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
729 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
730 for (ProtLink = Prot->OpenList.ForwardLink;
731 ProtLink != &Prot->OpenList;
732 ProtLink = ProtLink->ForwardLink) {
733 OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
734 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
735 Duplicate = FALSE;
736 for (Index = 0; Index< DriverImageHandleCount; Index++) {
737 if (DriverImageHandleBuffer[Index] == OpenData->AgentHandle) {
738 Duplicate = TRUE;
739 break;
740 }
741 }
742 if (!Duplicate) {
743 DriverImageHandleBuffer[DriverImageHandleCount] = OpenData->AgentHandle;
744 DriverImageHandleCount++;
745 }
746 }
747 }
748 }
749 CoreReleaseProtocolLock ();
750 }
751
752 StopCount = 0;
753 for (HandleIndex = 0; HandleIndex < DriverImageHandleCount; HandleIndex++) {
754
755 if (DriverImageHandleBuffer != NULL) {
756 DriverImageHandle = DriverImageHandleBuffer[HandleIndex];
757 }
758
759 //
760 // Get the Driver Binding Protocol of the driver that is managing this controller
761 //
762 Status = CoreHandleProtocol (
763 DriverImageHandle,
764 &gEfiDriverBindingProtocolGuid,
765 (VOID **)&DriverBinding
766 );
767 if (EFI_ERROR (Status)) {
768 Status = EFI_INVALID_PARAMETER;
769 goto Done;
770 }
771
772 //
773 // Look at each protocol interface for a match
774 //
775 DriverImageHandleValid = FALSE;
776 ChildBufferCount = 0;
777
778 CoreAcquireProtocolLock ();
779 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
780 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
781 for (ProtLink = Prot->OpenList.ForwardLink;
782 ProtLink != &Prot->OpenList;
783 ProtLink = ProtLink->ForwardLink) {
784 OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
785 if (OpenData->AgentHandle == DriverImageHandle) {
786 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
787 ChildBufferCount++;
788 }
789 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
790 DriverImageHandleValid = TRUE;
791 }
792 }
793 }
794 }
795 CoreReleaseProtocolLock ();
796
797 if (DriverImageHandleValid) {
798 ChildHandleValid = FALSE;
799 ChildBuffer = NULL;
800 if (ChildBufferCount != 0) {
801 ChildBuffer = AllocatePool (sizeof (EFI_HANDLE) * ChildBufferCount);
802 if (ChildBuffer == NULL) {
803 Status = EFI_OUT_OF_RESOURCES;
804 goto Done;
805 }
806
807 ChildBufferCount = 0;
808
809 CoreAcquireProtocolLock ();
810 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
811 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
812 for (ProtLink = Prot->OpenList.ForwardLink;
813 ProtLink != &Prot->OpenList;
814 ProtLink = ProtLink->ForwardLink) {
815 OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
816 if ((OpenData->AgentHandle == DriverImageHandle) &&
817 ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0)) {
818 Duplicate = FALSE;
819 for (Index = 0; Index < ChildBufferCount; Index++) {
820 if (ChildBuffer[Index] == OpenData->ControllerHandle) {
821 Duplicate = TRUE;
822 break;
823 }
824 }
825 if (!Duplicate) {
826 ChildBuffer[ChildBufferCount] = OpenData->ControllerHandle;
827 if (ChildHandle == ChildBuffer[ChildBufferCount]) {
828 ChildHandleValid = TRUE;
829 }
830 ChildBufferCount++;
831 }
832 }
833 }
834 }
835 CoreReleaseProtocolLock ();
836 }
837
838 if (ChildHandle == NULL || ChildHandleValid) {
839 ChildrenToStop = 0;
840 Status = EFI_SUCCESS;
841 if (ChildBufferCount > 0) {
842 if (ChildHandle != NULL) {
843 ChildrenToStop = 1;
844 Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, &ChildHandle);
845 } else {
846 ChildrenToStop = ChildBufferCount;
847 Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, ChildBuffer);
848 }
849 }
850 if (!EFI_ERROR (Status) && ((ChildHandle == NULL) || (ChildBufferCount == ChildrenToStop))) {
851 Status = DriverBinding->Stop (DriverBinding, ControllerHandle, 0, NULL);
852 }
853 if (!EFI_ERROR (Status)) {
854 StopCount++;
855 }
856 }
857
858 if (ChildBuffer != NULL) {
859 CoreFreePool (ChildBuffer);
860 }
861 }
862 }
863
864 if (StopCount > 0) {
865 Status = EFI_SUCCESS;
866 } else {
867 Status = EFI_NOT_FOUND;
868 }
869
870 Done:
871
872 if (DriverImageHandleBuffer != NULL) {
873 CoreFreePool (DriverImageHandleBuffer);
874 }
875
876 return Status;
877 }