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