]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Dxe/Hand/DriverSupport.c
Add comments and DoxyGen format for these files.
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Hand / DriverSupport.c
1 /** @file
2
3 Support functions to connect/disconnect UEFI Driver model Protocol
4
5 Copyright (c) 2006 - 2008, Intel Corporation
6 All rights reserved. This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include <DxeMain.h>
17
18 //
19 // Driver Support Function Prototypes
20 //
21 EFI_STATUS
22 CoreConnectSingleController (
23 IN EFI_HANDLE ControllerHandle,
24 IN EFI_HANDLE *DriverImageHandle OPTIONAL,
25 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
26 );
27
28 //
29 // Driver Support Functions
30 //
31 EFI_STATUS
32 EFIAPI
33 CoreConnectController (
34 IN EFI_HANDLE ControllerHandle,
35 IN EFI_HANDLE *DriverImageHandle OPTIONAL,
36 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL,
37 IN BOOLEAN Recursive
38 )
39 /*++
40
41 Routine Description:
42
43 Connects one or more drivers to a controller.
44
45 Arguments:
46
47 ControllerHandle - Handle of the controller to be connected.
48
49 DriverImageHandle - DriverImageHandle A pointer to an ordered list of driver image handles.
50
51 RemainingDevicePath - RemainingDevicePath A pointer to the device path that specifies a child of the
52 controller specified by ControllerHandle.
53
54 Recursive - Whether the function would be called recursively or not.
55
56 Returns:
57
58 Status code.
59
60 --*/
61 {
62 EFI_STATUS Status;
63 EFI_STATUS ReturnStatus;
64 IHANDLE *Handle;
65 PROTOCOL_INTERFACE *Prot;
66 LIST_ENTRY *Link;
67 LIST_ENTRY *ProtLink;
68 OPEN_PROTOCOL_DATA *OpenData;
69 EFI_DEVICE_PATH_PROTOCOL *AlignedRemainingDevicePath;
70 EFI_HANDLE *ChildHandleBuffer;
71 UINTN ChildHandleCount;
72 UINTN Index;
73
74 //
75 // Make sure ControllerHandle is valid
76 //
77 Status = CoreValidateHandle (ControllerHandle);
78 if (EFI_ERROR (Status)) {
79 return Status;
80 }
81
82 Handle = ControllerHandle;
83
84 //
85 // Make a copy of RemainingDevicePath to guanatee it is aligned
86 //
87 AlignedRemainingDevicePath = NULL;
88 if (RemainingDevicePath != NULL) {
89 AlignedRemainingDevicePath = CoreDuplicateDevicePath (RemainingDevicePath);
90 }
91
92 //
93 // Connect all drivers to ControllerHandle
94 // If CoreConnectSingleController returns EFI_NOT_READY, then the number of
95 // Driver Binding Protocols in the handle database has increased during the call
96 // so the connect operation must be restarted
97 //
98 do {
99 ReturnStatus = CoreConnectSingleController (
100 ControllerHandle,
101 DriverImageHandle,
102 AlignedRemainingDevicePath
103 );
104 } while (ReturnStatus == EFI_NOT_READY);
105
106 //
107 // Free the aligned copy of RemainingDevicePath
108 //
109 if (AlignedRemainingDevicePath != NULL) {
110 CoreFreePool (AlignedRemainingDevicePath);
111 }
112
113 //
114 // If recursive, then connect all drivers to all of ControllerHandle's children
115 //
116 if (Recursive) {
117 //
118 // Acquire the protocol lock on the handle database so the child handles can be collected
119 //
120 CoreAcquireProtocolLock ();
121
122 //
123 // Make sure the DriverBindingHandle is valid
124 //
125 Status = CoreValidateHandle (ControllerHandle);
126 if (EFI_ERROR (Status)) {
127 //
128 // Release the protocol lock on the handle database
129 //
130 CoreReleaseProtocolLock ();
131
132 return ReturnStatus;
133 }
134
135
136 //
137 // Count ControllerHandle's children
138 //
139 for (Link = Handle->Protocols.ForwardLink, ChildHandleCount = 0; Link != &Handle->Protocols; Link = Link->ForwardLink) {
140 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
141 for (ProtLink = Prot->OpenList.ForwardLink;
142 ProtLink != &Prot->OpenList;
143 ProtLink = ProtLink->ForwardLink) {
144 OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
145 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
146 ChildHandleCount++;
147 }
148 }
149 }
150
151 //
152 // Allocate a handle buffer for ControllerHandle's children
153 //
154 ChildHandleBuffer = CoreAllocateBootServicesPool (ChildHandleCount * sizeof(EFI_HANDLE));
155
156 //
157 // Fill in a handle buffer with ControllerHandle's children
158 //
159 for (Link = Handle->Protocols.ForwardLink, ChildHandleCount = 0; Link != &Handle->Protocols; Link = Link->ForwardLink) {
160 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
161 for (ProtLink = Prot->OpenList.ForwardLink;
162 ProtLink != &Prot->OpenList;
163 ProtLink = ProtLink->ForwardLink) {
164 OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
165 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
166 ChildHandleBuffer[ChildHandleCount] = OpenData->ControllerHandle;
167 ChildHandleCount++;
168 }
169 }
170 }
171
172 //
173 // Release the protocol lock on the handle database
174 //
175 CoreReleaseProtocolLock ();
176
177 //
178 // Recursively connect each child handle
179 //
180 for (Index = 0; Index < ChildHandleCount; Index++) {
181 CoreConnectController (
182 ChildHandleBuffer[Index],
183 NULL,
184 NULL,
185 TRUE
186 );
187 }
188
189 //
190 // Free the handle buffer of ControllerHandle's children
191 //
192 CoreFreePool (ChildHandleBuffer);
193 }
194
195 return ReturnStatus;
196 }
197
198 VOID
199 AddSortedDriverBindingProtocol (
200 IN EFI_HANDLE DriverBindingHandle,
201 IN OUT UINTN *NumberOfSortedDriverBindingProtocols,
202 IN OUT EFI_DRIVER_BINDING_PROTOCOL **SortedDriverBindingProtocols,
203 IN UINTN DriverBindingHandleCount,
204 IN OUT EFI_HANDLE *DriverBindingHandleBuffer,
205 IN BOOLEAN IsImageHandle
206 )
207 /*++
208
209 Routine Description:
210
211 Add Driver Binding Protocols from Context Driver Image Handles to sorted
212 Driver Binding Protocol list.
213
214 Arguments:
215
216 DriverBindingHandle - Handle of the driver binding protocol.
217
218 NumberOfSortedDriverBindingProtocols - Number Of sorted driver binding protocols
219
220 SortedDriverBindingProtocols - The sorted protocol list.
221
222 DriverBindingHandleCount - Driver Binding Handle Count.
223
224 DriverBindingHandleBuffer - The buffer of driver binding protocol to be modified.
225
226 IsImageHandle - Indicate whether DriverBindingHandle is an image handle
227
228 Returns:
229
230 None.
231
232 --*/
233 {
234 EFI_STATUS Status;
235 EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
236 UINTN Index;
237
238 //
239 // Make sure the DriverBindingHandle is valid
240 //
241 Status = CoreValidateHandle (DriverBindingHandle);
242 if (EFI_ERROR (Status)) {
243 return;
244 }
245
246 //
247 // If IsImageHandle is TRUE, then DriverBindingHandle is an image handle
248 // Find all the DriverBindingHandles associated with that image handle and add them to the sorted list
249 //
250 if (IsImageHandle) {
251 //
252 // Loop through all the Driver Binding Handles
253 //
254 for (Index = 0; Index < DriverBindingHandleCount; Index++) {
255 //
256 // Retrieve the Driver Binding Protocol associated with each Driver Binding Handle
257 //
258 Status = CoreHandleProtocol (
259 DriverBindingHandleBuffer[Index],
260 &gEfiDriverBindingProtocolGuid,
261 (VOID **)&DriverBinding
262 );
263 if (EFI_ERROR (Status) || DriverBinding == NULL) {
264 continue;
265 }
266
267 //
268 // If the ImageHandle associated with DriverBinding matches DriverBindingHandle,
269 // then add the DriverBindingProtocol[Index] to the sorted list
270 //
271 if (DriverBinding->ImageHandle == DriverBindingHandle) {
272 AddSortedDriverBindingProtocol (
273 DriverBindingHandleBuffer[Index],
274 NumberOfSortedDriverBindingProtocols,
275 SortedDriverBindingProtocols,
276 DriverBindingHandleCount,
277 DriverBindingHandleBuffer,
278 FALSE
279 );
280 }
281 }
282 return;
283 }
284
285 //
286 // Retrieve the Driver Binding Protocol from DriverBindingHandle
287 //
288 Status = CoreHandleProtocol(
289 DriverBindingHandle,
290 &gEfiDriverBindingProtocolGuid,
291 (VOID **)&DriverBinding
292 );
293 //
294 // If DriverBindingHandle does not support the Driver Binding Protocol then return
295 //
296 if (EFI_ERROR (Status) || DriverBinding == NULL) {
297 return;
298 }
299
300 //
301 // See if DriverBinding is already in the sorted list
302 //
303 for (Index = 0; Index < *NumberOfSortedDriverBindingProtocols && Index < DriverBindingHandleCount; Index++) {
304 if (DriverBinding == SortedDriverBindingProtocols[Index]) {
305 return;
306 }
307 }
308
309 //
310 // Add DriverBinding to the end of the list
311 //
312 if (*NumberOfSortedDriverBindingProtocols < DriverBindingHandleCount) {
313 SortedDriverBindingProtocols[*NumberOfSortedDriverBindingProtocols] = DriverBinding;
314 }
315 *NumberOfSortedDriverBindingProtocols = *NumberOfSortedDriverBindingProtocols + 1;
316
317 //
318 // Mark the cooresponding handle in DriverBindingHandleBuffer as used
319 //
320 for (Index = 0; Index < DriverBindingHandleCount; Index++) {
321 if (DriverBindingHandleBuffer[Index] == DriverBindingHandle) {
322 DriverBindingHandleBuffer[Index] = NULL;
323 }
324 }
325 }
326
327 EFI_STATUS
328 CoreConnectSingleController (
329 IN EFI_HANDLE ControllerHandle,
330 IN EFI_HANDLE *ContextDriverImageHandles OPTIONAL,
331 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
332 )
333 /*++
334
335 Routine Description:
336
337 Connects a controller to a driver.
338
339 Arguments:
340
341 ControllerHandle - Handle of the controller to be connected.
342 ContextDriverImageHandles - DriverImageHandle A pointer to an ordered list of driver image handles.
343 RemainingDevicePath - RemainingDevicePath A pointer to the device path that specifies a child
344 of the controller specified by ControllerHandle.
345
346 Returns:
347
348 EFI_SUCCESS - One or more drivers were connected to ControllerHandle.
349 EFI_OUT_OF_RESOURCES - No enough system resources to complete the request.
350 EFI_NOT_FOUND - No drivers were connected to ControllerHandle.
351
352 --*/
353 {
354 EFI_STATUS Status;
355 UINTN Index;
356 EFI_HANDLE DriverImageHandle;
357 EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL *PlatformDriverOverride;
358 EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *BusSpecificDriverOverride;
359 UINTN DriverBindingHandleCount;
360 EFI_HANDLE *DriverBindingHandleBuffer;
361 UINTN NewDriverBindingHandleCount;
362 EFI_HANDLE *NewDriverBindingHandleBuffer;
363 EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
364 UINTN NumberOfSortedDriverBindingProtocols;
365 EFI_DRIVER_BINDING_PROTOCOL **SortedDriverBindingProtocols;
366 UINT32 HighestVersion;
367 UINTN HighestIndex;
368 UINTN SortIndex;
369 BOOLEAN OneStarted;
370 BOOLEAN DriverFound;
371
372 //
373 // Initialize local variables
374 //
375 DriverBindingHandleCount = 0;
376 DriverBindingHandleBuffer = NULL;
377 NumberOfSortedDriverBindingProtocols = 0;
378 SortedDriverBindingProtocols = NULL;
379
380 //
381 // Get list of all Driver Binding Protocol Instances
382 //
383 Status = CoreLocateHandleBuffer (
384 ByProtocol,
385 &gEfiDriverBindingProtocolGuid,
386 NULL,
387 &DriverBindingHandleCount,
388 &DriverBindingHandleBuffer
389 );
390 if (EFI_ERROR (Status) || (DriverBindingHandleCount == 0)) {
391 return EFI_NOT_FOUND;
392 }
393
394 //
395 // Allocate a duplicate array for the sorted Driver Binding Protocol Instances
396 //
397 SortedDriverBindingProtocols = CoreAllocateBootServicesPool (sizeof (VOID *) * DriverBindingHandleCount);
398 if (SortedDriverBindingProtocols == NULL) {
399 CoreFreePool (DriverBindingHandleBuffer);
400 return EFI_OUT_OF_RESOURCES;
401 }
402
403 //
404 // Add Driver Binding Protocols from Context Driver Image Handles first
405 //
406 if (ContextDriverImageHandles != NULL) {
407 for (Index = 0; ContextDriverImageHandles[Index] != NULL; Index++) {
408 AddSortedDriverBindingProtocol (
409 ContextDriverImageHandles[Index],
410 &NumberOfSortedDriverBindingProtocols,
411 SortedDriverBindingProtocols,
412 DriverBindingHandleCount,
413 DriverBindingHandleBuffer,
414 FALSE
415 );
416 }
417 }
418
419 //
420 // Add the Platform Driver Override Protocol drivers for ControllerHandle next
421 //
422 Status = CoreLocateProtocol (
423 &gEfiPlatformDriverOverrideProtocolGuid,
424 NULL,
425 (VOID **)&PlatformDriverOverride
426 );
427 if (!EFI_ERROR (Status) && (PlatformDriverOverride != NULL)) {
428 DriverImageHandle = NULL;
429 do {
430 Status = PlatformDriverOverride->GetDriver (
431 PlatformDriverOverride,
432 ControllerHandle,
433 &DriverImageHandle
434 );
435 if (!EFI_ERROR (Status)) {
436 AddSortedDriverBindingProtocol (
437 DriverImageHandle,
438 &NumberOfSortedDriverBindingProtocols,
439 SortedDriverBindingProtocols,
440 DriverBindingHandleCount,
441 DriverBindingHandleBuffer,
442 TRUE
443 );
444 }
445 } while (!EFI_ERROR (Status));
446 }
447
448 //
449 // Get the Bus Specific Driver Override Protocol instance on the Controller Handle
450 //
451 Status = CoreHandleProtocol (
452 ControllerHandle,
453 &gEfiBusSpecificDriverOverrideProtocolGuid,
454 (VOID **)&BusSpecificDriverOverride
455 );
456 if (!EFI_ERROR (Status) && (BusSpecificDriverOverride != NULL)) {
457 DriverImageHandle = NULL;
458 do {
459 Status = BusSpecificDriverOverride->GetDriver (
460 BusSpecificDriverOverride,
461 &DriverImageHandle
462 );
463 if (!EFI_ERROR (Status)) {
464 AddSortedDriverBindingProtocol (
465 DriverImageHandle,
466 &NumberOfSortedDriverBindingProtocols,
467 SortedDriverBindingProtocols,
468 DriverBindingHandleCount,
469 DriverBindingHandleBuffer,
470 TRUE
471 );
472 }
473 } while (!EFI_ERROR (Status));
474 }
475
476 //
477 // Then add all the remaining Driver Binding Protocols
478 //
479 SortIndex = NumberOfSortedDriverBindingProtocols;
480 for (Index = 0; Index < DriverBindingHandleCount; Index++) {
481 AddSortedDriverBindingProtocol (
482 DriverBindingHandleBuffer[Index],
483 &NumberOfSortedDriverBindingProtocols,
484 SortedDriverBindingProtocols,
485 DriverBindingHandleCount,
486 DriverBindingHandleBuffer,
487 FALSE
488 );
489 }
490
491 //
492 // Free the Driver Binding Handle Buffer
493 //
494 CoreFreePool (DriverBindingHandleBuffer);
495
496 //
497 // If the number of Driver Binding Protocols has increased since this function started, then return
498 // EFI_NOT_READY, so it will be restarted
499 //
500 Status = CoreLocateHandleBuffer (
501 ByProtocol,
502 &gEfiDriverBindingProtocolGuid,
503 NULL,
504 &NewDriverBindingHandleCount,
505 &NewDriverBindingHandleBuffer
506 );
507 CoreFreePool (NewDriverBindingHandleBuffer);
508 if (NewDriverBindingHandleCount > DriverBindingHandleCount) {
509 //
510 // Free any buffers that were allocated with AllocatePool()
511 //
512 CoreFreePool (SortedDriverBindingProtocols);
513
514 return EFI_NOT_READY;
515 }
516
517 //
518 // Sort the remaining DriverBinding Protocol based on their Version field from
519 // highest to lowest.
520 //
521 for ( ; SortIndex < NumberOfSortedDriverBindingProtocols; SortIndex++) {
522 HighestVersion = SortedDriverBindingProtocols[SortIndex]->Version;
523 HighestIndex = SortIndex;
524 for (Index = SortIndex + 1; Index < NumberOfSortedDriverBindingProtocols; Index++) {
525 if (SortedDriverBindingProtocols[Index]->Version > HighestVersion) {
526 HighestVersion = SortedDriverBindingProtocols[Index]->Version;
527 HighestIndex = Index;
528 }
529 }
530 if (SortIndex != HighestIndex) {
531 DriverBinding = SortedDriverBindingProtocols[SortIndex];
532 SortedDriverBindingProtocols[SortIndex] = SortedDriverBindingProtocols[HighestIndex];
533 SortedDriverBindingProtocols[HighestIndex] = DriverBinding;
534 }
535 }
536
537 //
538 // Loop until no more drivers can be started on ControllerHandle
539 //
540 OneStarted = FALSE;
541 do {
542
543 //
544 // Loop through the sorted Driver Binding Protocol Instances in order, and see if
545 // any of the Driver Binding Protocols support the controller specified by
546 // ControllerHandle.
547 //
548 DriverBinding = NULL;
549 DriverFound = FALSE;
550 for (Index = 0; (Index < NumberOfSortedDriverBindingProtocols) && !DriverFound; Index++) {
551 if (SortedDriverBindingProtocols[Index] != NULL) {
552 DriverBinding = SortedDriverBindingProtocols[Index];
553 Status = DriverBinding->Supported(
554 DriverBinding,
555 ControllerHandle,
556 RemainingDevicePath
557 );
558 if (!EFI_ERROR (Status)) {
559 SortedDriverBindingProtocols[Index] = NULL;
560 DriverFound = TRUE;
561
562 //
563 // A driver was found that supports ControllerHandle, so attempt to start the driver
564 // on ControllerHandle.
565 //
566 PERF_START (DriverBinding->DriverBindingHandle, DRIVERBINDING_START_TOK, NULL, 0);
567 Status = DriverBinding->Start (
568 DriverBinding,
569 ControllerHandle,
570 RemainingDevicePath
571 );
572 PERF_END (DriverBinding->DriverBindingHandle, DRIVERBINDING_START_TOK, NULL, 0);
573
574 if (!EFI_ERROR (Status)) {
575 //
576 // The driver was successfully started on ControllerHandle, so set a flag
577 //
578 OneStarted = TRUE;
579 }
580 }
581 }
582 }
583 } while (DriverFound);
584
585 //
586 // Free any buffers that were allocated with AllocatePool()
587 //
588 CoreFreePool (SortedDriverBindingProtocols);
589
590 //
591 // If at least one driver was started on ControllerHandle, then return EFI_SUCCESS.
592 //
593 if (OneStarted) {
594 return EFI_SUCCESS;
595 }
596
597 //
598 // If no drivers started and RemainingDevicePath is an End Device Path Node, then return EFI_SUCCESS
599 //
600 if (RemainingDevicePath != NULL) {
601 if (IsDevicePathEnd (RemainingDevicePath)) {
602 return EFI_SUCCESS;
603 }
604 }
605
606 //
607 // Otherwise, no drivers were started on ControllerHandle, so return EFI_NOT_FOUND
608 //
609 return EFI_NOT_FOUND;
610 }
611
612
613 EFI_STATUS
614 EFIAPI
615 CoreDisconnectController (
616 IN EFI_HANDLE ControllerHandle,
617 IN EFI_HANDLE DriverImageHandle OPTIONAL,
618 IN EFI_HANDLE ChildHandle OPTIONAL
619 )
620 /*++
621
622 Routine Description:
623
624 Disonnects a controller from a driver
625
626 Arguments:
627
628 ControllerHandle - ControllerHandle The handle of the controller from which driver(s)
629 are to be disconnected.
630 DriverImageHandle - DriverImageHandle The driver to disconnect from ControllerHandle.
631 ChildHandle - ChildHandle The handle of the child to destroy.
632
633 Returns:
634
635 EFI_SUCCESS - One or more drivers were disconnected from the controller.
636 EFI_SUCCESS - On entry, no drivers are managing ControllerHandle.
637 EFI_SUCCESS - DriverImageHandle is not NULL, and on entry DriverImageHandle is not managing ControllerHandle.
638 EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
639 EFI_INVALID_PARAMETER - DriverImageHandle is not NULL, and it is not a valid EFI_HANDLE.
640 EFI_INVALID_PARAMETER - ChildHandle is not NULL, and it is not a valid EFI_HANDLE.
641 EFI_OUT_OF_RESOURCES - There are not enough resources available to disconnect any drivers from ControllerHandle.
642 EFI_DEVICE_ERROR - The controller could not be disconnected because of a device error.
643
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 = CoreAllocateBootServicesPool (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 = CoreAllocateBootServicesPool (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 }