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