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