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