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