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