]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Dxe/Hand/DriverSupport.c
Fix the comments to follow UEFI Spec regarding how to check an EFI_HANDLE is valid...
[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 - 2011, Intel Corporation. All rights reserved.<BR>
5 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 EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL *DriverFamilyOverride;
356 UINTN NumberOfSortedDriverBindingProtocols;
357 EFI_DRIVER_BINDING_PROTOCOL **SortedDriverBindingProtocols;
358 UINT32 DriverFamilyOverrideVersion;
359 UINT32 HighestVersion;
360 UINTN HighestIndex;
361 UINTN SortIndex;
362 BOOLEAN OneStarted;
363 BOOLEAN DriverFound;
364
365 //
366 // Initialize local variables
367 //
368 DriverBindingHandleCount = 0;
369 DriverBindingHandleBuffer = NULL;
370 NumberOfSortedDriverBindingProtocols = 0;
371 SortedDriverBindingProtocols = NULL;
372
373 //
374 // Get list of all Driver Binding Protocol Instances
375 //
376 Status = CoreLocateHandleBuffer (
377 ByProtocol,
378 &gEfiDriverBindingProtocolGuid,
379 NULL,
380 &DriverBindingHandleCount,
381 &DriverBindingHandleBuffer
382 );
383 if (EFI_ERROR (Status) || (DriverBindingHandleCount == 0)) {
384 return EFI_NOT_FOUND;
385 }
386
387 //
388 // Allocate a duplicate array for the sorted Driver Binding Protocol Instances
389 //
390 SortedDriverBindingProtocols = AllocatePool (sizeof (VOID *) * DriverBindingHandleCount);
391 if (SortedDriverBindingProtocols == NULL) {
392 CoreFreePool (DriverBindingHandleBuffer);
393 return EFI_OUT_OF_RESOURCES;
394 }
395
396 //
397 // Add Driver Binding Protocols from Context Driver Image Handles first
398 //
399 if (ContextDriverImageHandles != NULL) {
400 for (Index = 0; ContextDriverImageHandles[Index] != NULL; Index++) {
401 AddSortedDriverBindingProtocol (
402 ContextDriverImageHandles[Index],
403 &NumberOfSortedDriverBindingProtocols,
404 SortedDriverBindingProtocols,
405 DriverBindingHandleCount,
406 DriverBindingHandleBuffer,
407 FALSE
408 );
409 }
410 }
411
412 //
413 // Add the Platform Driver Override Protocol drivers for ControllerHandle next
414 //
415 Status = CoreLocateProtocol (
416 &gEfiPlatformDriverOverrideProtocolGuid,
417 NULL,
418 (VOID **) &PlatformDriverOverride
419 );
420 if (!EFI_ERROR (Status) && (PlatformDriverOverride != NULL)) {
421 DriverImageHandle = NULL;
422 do {
423 Status = PlatformDriverOverride->GetDriver (
424 PlatformDriverOverride,
425 ControllerHandle,
426 &DriverImageHandle
427 );
428 if (!EFI_ERROR (Status)) {
429 AddSortedDriverBindingProtocol (
430 DriverImageHandle,
431 &NumberOfSortedDriverBindingProtocols,
432 SortedDriverBindingProtocols,
433 DriverBindingHandleCount,
434 DriverBindingHandleBuffer,
435 TRUE
436 );
437 }
438 } while (!EFI_ERROR (Status));
439 }
440
441 //
442 // Add the Driver Family Override Protocol drivers for ControllerHandle
443 //
444 while (TRUE) {
445 HighestIndex = DriverBindingHandleCount;
446 HighestVersion = 0;
447 for (Index = 0; Index < DriverBindingHandleCount; Index++) {
448 Status = CoreHandleProtocol (
449 DriverBindingHandleBuffer[Index],
450 &gEfiDriverFamilyOverrideProtocolGuid,
451 (VOID **) &DriverFamilyOverride
452 );
453 if (!EFI_ERROR (Status) && (DriverFamilyOverride != NULL)) {
454 DriverFamilyOverrideVersion = DriverFamilyOverride->GetVersion (DriverFamilyOverride);
455 if ((HighestIndex == DriverBindingHandleCount) || (DriverFamilyOverrideVersion > HighestVersion)) {
456 HighestVersion = DriverFamilyOverrideVersion;
457 HighestIndex = Index;
458 }
459 }
460 }
461
462 if (HighestIndex == DriverBindingHandleCount) {
463 break;
464 }
465
466 AddSortedDriverBindingProtocol (
467 DriverBindingHandleBuffer[HighestIndex],
468 &NumberOfSortedDriverBindingProtocols,
469 SortedDriverBindingProtocols,
470 DriverBindingHandleCount,
471 DriverBindingHandleBuffer,
472 FALSE
473 );
474 }
475
476 //
477 // Get the Bus Specific Driver Override Protocol instance on the Controller Handle
478 //
479 Status = CoreHandleProtocol (
480 ControllerHandle,
481 &gEfiBusSpecificDriverOverrideProtocolGuid,
482 (VOID **) &BusSpecificDriverOverride
483 );
484 if (!EFI_ERROR (Status) && (BusSpecificDriverOverride != NULL)) {
485 DriverImageHandle = NULL;
486 do {
487 Status = BusSpecificDriverOverride->GetDriver (
488 BusSpecificDriverOverride,
489 &DriverImageHandle
490 );
491 if (!EFI_ERROR (Status)) {
492 AddSortedDriverBindingProtocol (
493 DriverImageHandle,
494 &NumberOfSortedDriverBindingProtocols,
495 SortedDriverBindingProtocols,
496 DriverBindingHandleCount,
497 DriverBindingHandleBuffer,
498 TRUE
499 );
500 }
501 } while (!EFI_ERROR (Status));
502 }
503
504 //
505 // Then add all the remaining Driver Binding Protocols
506 //
507 SortIndex = NumberOfSortedDriverBindingProtocols;
508 for (Index = 0; Index < DriverBindingHandleCount; Index++) {
509 AddSortedDriverBindingProtocol (
510 DriverBindingHandleBuffer[Index],
511 &NumberOfSortedDriverBindingProtocols,
512 SortedDriverBindingProtocols,
513 DriverBindingHandleCount,
514 DriverBindingHandleBuffer,
515 FALSE
516 );
517 }
518
519 //
520 // Free the Driver Binding Handle Buffer
521 //
522 CoreFreePool (DriverBindingHandleBuffer);
523
524 //
525 // If the number of Driver Binding Protocols has increased since this function started, then return
526 // EFI_NOT_READY, so it will be restarted
527 //
528 Status = CoreLocateHandleBuffer (
529 ByProtocol,
530 &gEfiDriverBindingProtocolGuid,
531 NULL,
532 &NewDriverBindingHandleCount,
533 &NewDriverBindingHandleBuffer
534 );
535 CoreFreePool (NewDriverBindingHandleBuffer);
536 if (NewDriverBindingHandleCount > DriverBindingHandleCount) {
537 //
538 // Free any buffers that were allocated with AllocatePool()
539 //
540 CoreFreePool (SortedDriverBindingProtocols);
541
542 return EFI_NOT_READY;
543 }
544
545 //
546 // Sort the remaining DriverBinding Protocol based on their Version field from
547 // highest to lowest.
548 //
549 for ( ; SortIndex < NumberOfSortedDriverBindingProtocols; SortIndex++) {
550 HighestVersion = SortedDriverBindingProtocols[SortIndex]->Version;
551 HighestIndex = SortIndex;
552 for (Index = SortIndex + 1; Index < NumberOfSortedDriverBindingProtocols; Index++) {
553 if (SortedDriverBindingProtocols[Index]->Version > HighestVersion) {
554 HighestVersion = SortedDriverBindingProtocols[Index]->Version;
555 HighestIndex = Index;
556 }
557 }
558 if (SortIndex != HighestIndex) {
559 DriverBinding = SortedDriverBindingProtocols[SortIndex];
560 SortedDriverBindingProtocols[SortIndex] = SortedDriverBindingProtocols[HighestIndex];
561 SortedDriverBindingProtocols[HighestIndex] = DriverBinding;
562 }
563 }
564
565 //
566 // Loop until no more drivers can be started on ControllerHandle
567 //
568 OneStarted = FALSE;
569 do {
570
571 //
572 // Loop through the sorted Driver Binding Protocol Instances in order, and see if
573 // any of the Driver Binding Protocols support the controller specified by
574 // ControllerHandle.
575 //
576 DriverBinding = NULL;
577 DriverFound = FALSE;
578 for (Index = 0; (Index < NumberOfSortedDriverBindingProtocols) && !DriverFound; Index++) {
579 if (SortedDriverBindingProtocols[Index] != NULL) {
580 DriverBinding = SortedDriverBindingProtocols[Index];
581 PERF_START (DriverBinding->DriverBindingHandle, "DB:Support:", NULL, 0);
582 Status = DriverBinding->Supported(
583 DriverBinding,
584 ControllerHandle,
585 RemainingDevicePath
586 );
587 PERF_END (DriverBinding->DriverBindingHandle, "DB:Support:", NULL, 0);
588 if (!EFI_ERROR (Status)) {
589 SortedDriverBindingProtocols[Index] = NULL;
590 DriverFound = TRUE;
591
592 //
593 // A driver was found that supports ControllerHandle, so attempt to start the driver
594 // on ControllerHandle.
595 //
596 PERF_START (DriverBinding->DriverBindingHandle, "DB:Start:", NULL, 0);
597 Status = DriverBinding->Start (
598 DriverBinding,
599 ControllerHandle,
600 RemainingDevicePath
601 );
602 PERF_END (DriverBinding->DriverBindingHandle, "DB:Start:", NULL, 0);
603
604 if (!EFI_ERROR (Status)) {
605 //
606 // The driver was successfully started on ControllerHandle, so set a flag
607 //
608 OneStarted = TRUE;
609 }
610 }
611 }
612 }
613 } while (DriverFound);
614
615 //
616 // Free any buffers that were allocated with AllocatePool()
617 //
618 CoreFreePool (SortedDriverBindingProtocols);
619
620 //
621 // If at least one driver was started on ControllerHandle, then return EFI_SUCCESS.
622 //
623 if (OneStarted) {
624 return EFI_SUCCESS;
625 }
626
627 //
628 // If no drivers started and RemainingDevicePath is an End Device Path Node, then return EFI_SUCCESS
629 //
630 if (RemainingDevicePath != NULL) {
631 if (IsDevicePathEnd (RemainingDevicePath)) {
632 return EFI_SUCCESS;
633 }
634 }
635
636 //
637 // Otherwise, no drivers were started on ControllerHandle, so return EFI_NOT_FOUND
638 //
639 return EFI_NOT_FOUND;
640 }
641
642
643
644 /**
645 Disonnects a controller from a driver
646
647 @param ControllerHandle ControllerHandle The handle of
648 the controller from which
649 driver(s) are to be
650 disconnected.
651 @param DriverImageHandle DriverImageHandle The driver to
652 disconnect from ControllerHandle.
653 @param ChildHandle ChildHandle The handle of the
654 child to destroy.
655
656 @retval EFI_SUCCESS One or more drivers were
657 disconnected from the controller.
658 @retval EFI_SUCCESS On entry, no drivers are managing
659 ControllerHandle.
660 @retval EFI_SUCCESS DriverImageHandle is not NULL,
661 and on entry DriverImageHandle is
662 not managing ControllerHandle.
663 @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
664 @retval EFI_INVALID_PARAMETER DriverImageHandle is not NULL,
665 and it is not a valid EFI_HANDLE.
666 @retval EFI_INVALID_PARAMETER ChildHandle is not NULL, and it
667 is not a valid EFI_HANDLE.
668 @retval EFI_OUT_OF_RESOURCES There are not enough resources
669 available to disconnect any
670 drivers from ControllerHandle.
671 @retval EFI_DEVICE_ERROR The controller could not be
672 disconnected because of a device
673 error.
674
675 **/
676 EFI_STATUS
677 EFIAPI
678 CoreDisconnectController (
679 IN EFI_HANDLE ControllerHandle,
680 IN EFI_HANDLE DriverImageHandle OPTIONAL,
681 IN EFI_HANDLE ChildHandle OPTIONAL
682 )
683 {
684 EFI_STATUS Status;
685 IHANDLE *Handle;
686 EFI_HANDLE *DriverImageHandleBuffer;
687 EFI_HANDLE *ChildBuffer;
688 UINTN Index;
689 UINTN HandleIndex;
690 UINTN DriverImageHandleCount;
691 UINTN ChildrenToStop;
692 UINTN ChildBufferCount;
693 UINTN StopCount;
694 BOOLEAN Duplicate;
695 BOOLEAN ChildHandleValid;
696 BOOLEAN DriverImageHandleValid;
697 LIST_ENTRY *Link;
698 LIST_ENTRY *ProtLink;
699 OPEN_PROTOCOL_DATA *OpenData;
700 PROTOCOL_INTERFACE *Prot;
701 EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
702
703 //
704 // Make sure ControllerHandle is valid
705 //
706 Status = CoreValidateHandle (ControllerHandle);
707 if (EFI_ERROR (Status)) {
708 return Status;
709 }
710
711 //
712 // Make sure ChildHandle is valid if it is not NULL
713 //
714 if (ChildHandle != NULL) {
715 Status = CoreValidateHandle (ChildHandle);
716 if (EFI_ERROR (Status)) {
717 return Status;
718 }
719 }
720
721 Handle = ControllerHandle;
722
723 //
724 // Get list of drivers that are currently managing ControllerHandle
725 //
726 DriverImageHandleBuffer = NULL;
727 DriverImageHandleCount = 1;
728
729 if (DriverImageHandle == NULL) {
730 //
731 // Look at each protocol interface for a match
732 //
733 DriverImageHandleCount = 0;
734
735 CoreAcquireProtocolLock ();
736 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
737 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
738 for (ProtLink = Prot->OpenList.ForwardLink;
739 ProtLink != &Prot->OpenList;
740 ProtLink = ProtLink->ForwardLink) {
741 OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
742 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
743 DriverImageHandleCount++;
744 }
745 }
746 }
747 CoreReleaseProtocolLock ();
748
749 //
750 // If there are no drivers managing this controller, then return EFI_SUCCESS
751 //
752 if (DriverImageHandleCount == 0) {
753 Status = EFI_SUCCESS;
754 goto Done;
755 }
756
757 DriverImageHandleBuffer = AllocatePool (sizeof (EFI_HANDLE) * DriverImageHandleCount);
758 if (DriverImageHandleBuffer == NULL) {
759 Status = EFI_OUT_OF_RESOURCES;
760 goto Done;
761 }
762
763 DriverImageHandleCount = 0;
764
765 CoreAcquireProtocolLock ();
766 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
767 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
768 for (ProtLink = Prot->OpenList.ForwardLink;
769 ProtLink != &Prot->OpenList;
770 ProtLink = ProtLink->ForwardLink) {
771 OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
772 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
773 Duplicate = FALSE;
774 for (Index = 0; Index< DriverImageHandleCount; Index++) {
775 if (DriverImageHandleBuffer[Index] == OpenData->AgentHandle) {
776 Duplicate = TRUE;
777 break;
778 }
779 }
780 if (!Duplicate) {
781 DriverImageHandleBuffer[DriverImageHandleCount] = OpenData->AgentHandle;
782 DriverImageHandleCount++;
783 }
784 }
785 }
786 }
787 CoreReleaseProtocolLock ();
788 }
789
790 StopCount = 0;
791 for (HandleIndex = 0; HandleIndex < DriverImageHandleCount; HandleIndex++) {
792
793 if (DriverImageHandleBuffer != NULL) {
794 DriverImageHandle = DriverImageHandleBuffer[HandleIndex];
795 }
796
797 //
798 // Get the Driver Binding Protocol of the driver that is managing this controller
799 //
800 Status = CoreHandleProtocol (
801 DriverImageHandle,
802 &gEfiDriverBindingProtocolGuid,
803 (VOID **)&DriverBinding
804 );
805 if (EFI_ERROR (Status) || DriverBinding == NULL) {
806 Status = EFI_INVALID_PARAMETER;
807 goto Done;
808 }
809
810 //
811 // Look at each protocol interface for a match
812 //
813 DriverImageHandleValid = FALSE;
814 ChildBufferCount = 0;
815
816 CoreAcquireProtocolLock ();
817 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
818 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
819 for (ProtLink = Prot->OpenList.ForwardLink;
820 ProtLink != &Prot->OpenList;
821 ProtLink = ProtLink->ForwardLink) {
822 OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
823 if (OpenData->AgentHandle == DriverImageHandle) {
824 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
825 ChildBufferCount++;
826 }
827 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
828 DriverImageHandleValid = TRUE;
829 }
830 }
831 }
832 }
833 CoreReleaseProtocolLock ();
834
835 if (DriverImageHandleValid) {
836 ChildHandleValid = FALSE;
837 ChildBuffer = NULL;
838 if (ChildBufferCount != 0) {
839 ChildBuffer = AllocatePool (sizeof (EFI_HANDLE) * ChildBufferCount);
840 if (ChildBuffer == NULL) {
841 Status = EFI_OUT_OF_RESOURCES;
842 goto Done;
843 }
844
845 ChildBufferCount = 0;
846
847 CoreAcquireProtocolLock ();
848 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
849 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
850 for (ProtLink = Prot->OpenList.ForwardLink;
851 ProtLink != &Prot->OpenList;
852 ProtLink = ProtLink->ForwardLink) {
853 OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
854 if ((OpenData->AgentHandle == DriverImageHandle) &&
855 ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0)) {
856 Duplicate = FALSE;
857 for (Index = 0; Index < ChildBufferCount; Index++) {
858 if (ChildBuffer[Index] == OpenData->ControllerHandle) {
859 Duplicate = TRUE;
860 break;
861 }
862 }
863 if (!Duplicate) {
864 ChildBuffer[ChildBufferCount] = OpenData->ControllerHandle;
865 if (ChildHandle == ChildBuffer[ChildBufferCount]) {
866 ChildHandleValid = TRUE;
867 }
868 ChildBufferCount++;
869 }
870 }
871 }
872 }
873 CoreReleaseProtocolLock ();
874 }
875
876 if (ChildHandle == NULL || ChildHandleValid) {
877 ChildrenToStop = 0;
878 Status = EFI_SUCCESS;
879 if (ChildBufferCount > 0) {
880 if (ChildHandle != NULL) {
881 ChildrenToStop = 1;
882 Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, &ChildHandle);
883 } else {
884 ChildrenToStop = ChildBufferCount;
885 Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, ChildBuffer);
886 }
887 }
888 if (!EFI_ERROR (Status) && ((ChildHandle == NULL) || (ChildBufferCount == ChildrenToStop))) {
889 Status = DriverBinding->Stop (DriverBinding, ControllerHandle, 0, NULL);
890 }
891 if (!EFI_ERROR (Status)) {
892 StopCount++;
893 }
894 }
895
896 if (ChildBuffer != NULL) {
897 CoreFreePool (ChildBuffer);
898 }
899 }
900 }
901
902 if (StopCount > 0) {
903 Status = EFI_SUCCESS;
904 } else {
905 Status = EFI_NOT_FOUND;
906 }
907
908 Done:
909
910 if (DriverImageHandleBuffer != NULL) {
911 CoreFreePool (DriverImageHandleBuffer);
912 }
913
914 return Status;
915 }