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