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
CoreConnectController(IN EFI_HANDLE ControllerHandle,IN EFI_HANDLE * DriverImageHandle OPTIONAL,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL,IN BOOLEAN Recursive)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
AddSortedDriverBindingProtocol(IN EFI_HANDLE DriverBindingHandle,IN OUT UINTN * NumberOfSortedDriverBindingProtocols,IN OUT EFI_DRIVER_BINDING_PROTOCOL ** SortedDriverBindingProtocols,IN UINTN DriverBindingHandleCount,IN OUT EFI_HANDLE * DriverBindingHandleBuffer,IN BOOLEAN IsImageHandle)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
CoreConnectSingleController(IN EFI_HANDLE ControllerHandle,IN EFI_HANDLE * ContextDriverImageHandles OPTIONAL,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)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   PlatformDriverOverride                = NULL;
420   NewDriverBindingHandleBuffer          = 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 = AllocatePool (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         FALSE
457         );
458     }
459   }
460 
461   //
462   // Add the Platform Driver Override Protocol drivers for ControllerHandle next
463   //
464   Status = CoreLocateProtocol (
465              &gEfiPlatformDriverOverrideProtocolGuid,
466              NULL,
467              (VOID **) &PlatformDriverOverride
468              );
469   if (!EFI_ERROR (Status) && (PlatformDriverOverride != NULL)) {
470     DriverImageHandle = NULL;
471     do {
472       Status = PlatformDriverOverride->GetDriver (
473                                          PlatformDriverOverride,
474                                          ControllerHandle,
475                                          &DriverImageHandle
476                                          );
477       if (!EFI_ERROR (Status)) {
478         AddSortedDriverBindingProtocol (
479           DriverImageHandle,
480           &NumberOfSortedDriverBindingProtocols,
481           SortedDriverBindingProtocols,
482           DriverBindingHandleCount,
483           DriverBindingHandleBuffer,
484           TRUE
485           );
486       }
487     } while (!EFI_ERROR (Status));
488   }
489 
490   //
491   // Add the Driver Family Override Protocol drivers for ControllerHandle
492   //
493   while (TRUE) {
494     HighestIndex   = DriverBindingHandleCount;
495     HighestVersion = 0;
496     for (Index = 0; Index < DriverBindingHandleCount; Index++) {
497       Status = CoreHandleProtocol (
498                  DriverBindingHandleBuffer[Index],
499                  &gEfiDriverFamilyOverrideProtocolGuid,
500                  (VOID **) &DriverFamilyOverride
501                  );
502       if (!EFI_ERROR (Status) && (DriverFamilyOverride != NULL)) {
503         DriverFamilyOverrideVersion = DriverFamilyOverride->GetVersion (DriverFamilyOverride);
504         if ((HighestIndex == DriverBindingHandleCount) || (DriverFamilyOverrideVersion > HighestVersion)) {
505           HighestVersion = DriverFamilyOverrideVersion;
506           HighestIndex   = Index;
507         }
508       }
509     }
510 
511     if (HighestIndex == DriverBindingHandleCount) {
512       break;
513     }
514 
515     AddSortedDriverBindingProtocol (
516       DriverBindingHandleBuffer[HighestIndex],
517       &NumberOfSortedDriverBindingProtocols,
518       SortedDriverBindingProtocols,
519       DriverBindingHandleCount,
520       DriverBindingHandleBuffer,
521       FALSE
522       );
523   }
524 
525   //
526   // Get the Bus Specific Driver Override Protocol instance on the Controller Handle
527   //
528   Status = CoreHandleProtocol (
529              ControllerHandle,
530              &gEfiBusSpecificDriverOverrideProtocolGuid,
531              (VOID **) &BusSpecificDriverOverride
532              );
533   if (!EFI_ERROR (Status) && (BusSpecificDriverOverride != NULL)) {
534     DriverImageHandle = NULL;
535     do {
536       Status = BusSpecificDriverOverride->GetDriver (
537                                             BusSpecificDriverOverride,
538                                             &DriverImageHandle
539                                             );
540       if (!EFI_ERROR (Status)) {
541         AddSortedDriverBindingProtocol (
542           DriverImageHandle,
543           &NumberOfSortedDriverBindingProtocols,
544           SortedDriverBindingProtocols,
545           DriverBindingHandleCount,
546           DriverBindingHandleBuffer,
547           TRUE
548           );
549       }
550     } while (!EFI_ERROR (Status));
551   }
552 
553   //
554   // Then add all the remaining Driver Binding Protocols
555   //
556   SortIndex = NumberOfSortedDriverBindingProtocols;
557   for (Index = 0; Index < DriverBindingHandleCount; Index++) {
558     AddSortedDriverBindingProtocol (
559       DriverBindingHandleBuffer[Index],
560       &NumberOfSortedDriverBindingProtocols,
561       SortedDriverBindingProtocols,
562       DriverBindingHandleCount,
563       DriverBindingHandleBuffer,
564       FALSE
565       );
566   }
567 
568   //
569   // Free the Driver Binding Handle Buffer
570   //
571   CoreFreePool (DriverBindingHandleBuffer);
572 
573   //
574   // If the number of Driver Binding Protocols has increased since this function started, then return
575   // EFI_NOT_READY, so it will be restarted
576   //
577   Status = CoreLocateHandleBuffer (
578              ByProtocol,
579              &gEfiDriverBindingProtocolGuid,
580              NULL,
581              &NewDriverBindingHandleCount,
582              &NewDriverBindingHandleBuffer
583              );
584   CoreFreePool (NewDriverBindingHandleBuffer);
585   if (NewDriverBindingHandleCount > DriverBindingHandleCount) {
586     //
587     // Free any buffers that were allocated with AllocatePool()
588     //
589     CoreFreePool (SortedDriverBindingProtocols);
590 
591     return EFI_NOT_READY;
592   }
593 
594   //
595   // Sort the remaining DriverBinding Protocol based on their Version field from
596   // highest to lowest.
597   //
598   for ( ; SortIndex < NumberOfSortedDriverBindingProtocols; SortIndex++) {
599     HighestVersion = SortedDriverBindingProtocols[SortIndex]->Version;
600     HighestIndex   = SortIndex;
601     for (Index = SortIndex + 1; Index < NumberOfSortedDriverBindingProtocols; Index++) {
602       if (SortedDriverBindingProtocols[Index]->Version > HighestVersion) {
603         HighestVersion = SortedDriverBindingProtocols[Index]->Version;
604         HighestIndex   = Index;
605       }
606     }
607     if (SortIndex != HighestIndex) {
608       DriverBinding = SortedDriverBindingProtocols[SortIndex];
609       SortedDriverBindingProtocols[SortIndex] = SortedDriverBindingProtocols[HighestIndex];
610       SortedDriverBindingProtocols[HighestIndex] = DriverBinding;
611     }
612   }
613 
614   //
615   // Loop until no more drivers can be started on ControllerHandle
616   //
617   OneStarted = FALSE;
618   do {
619 
620     //
621     // Loop through the sorted Driver Binding Protocol Instances in order, and see if
622     // any of the Driver Binding Protocols support the controller specified by
623     // ControllerHandle.
624     //
625     DriverBinding = NULL;
626     DriverFound = FALSE;
627     for (Index = 0; (Index < NumberOfSortedDriverBindingProtocols) && !DriverFound; Index++) {
628       if (SortedDriverBindingProtocols[Index] != NULL) {
629         DriverBinding = SortedDriverBindingProtocols[Index];
630         PERF_START (DriverBinding->DriverBindingHandle, "DB:Support:", NULL, 0);
631         Status = DriverBinding->Supported(
632                                   DriverBinding,
633                                   ControllerHandle,
634                                   RemainingDevicePath
635                                   );
636         PERF_END (DriverBinding->DriverBindingHandle, "DB:Support:", NULL, 0);
637         if (!EFI_ERROR (Status)) {
638           SortedDriverBindingProtocols[Index] = NULL;
639           DriverFound = TRUE;
640 
641           //
642           // A driver was found that supports ControllerHandle, so attempt to start the driver
643           // on ControllerHandle.
644           //
645           PERF_START (DriverBinding->DriverBindingHandle, "DB:Start:", NULL, 0);
646           Status = DriverBinding->Start (
647                                     DriverBinding,
648                                     ControllerHandle,
649                                     RemainingDevicePath
650                                     );
651           PERF_END (DriverBinding->DriverBindingHandle, "DB:Start:", NULL, 0);
652 
653           if (!EFI_ERROR (Status)) {
654             //
655             // The driver was successfully started on ControllerHandle, so set a flag
656             //
657             OneStarted = TRUE;
658           }
659         }
660       }
661     }
662   } while (DriverFound);
663 
664   //
665   // Free any buffers that were allocated with AllocatePool()
666   //
667   CoreFreePool (SortedDriverBindingProtocols);
668 
669   //
670   // If at least one driver was started on ControllerHandle, then return EFI_SUCCESS.
671   //
672   if (OneStarted) {
673     return EFI_SUCCESS;
674   }
675 
676   //
677   // If no drivers started and RemainingDevicePath is an End Device Path Node, then return EFI_SUCCESS
678   //
679   if (RemainingDevicePath != NULL) {
680     if (IsDevicePathEnd (RemainingDevicePath)) {
681       return EFI_SUCCESS;
682     }
683   }
684 
685   //
686   // Otherwise, no drivers were started on ControllerHandle, so return EFI_NOT_FOUND
687   //
688   return EFI_NOT_FOUND;
689 }
690 
691 
692 
693 /**
694   Disonnects a controller from a driver
695 
696   @param  ControllerHandle                      ControllerHandle The handle of
697                                                 the controller from which
698                                                 driver(s)  are to be
699                                                 disconnected.
700   @param  DriverImageHandle                     DriverImageHandle The driver to
701                                                 disconnect from ControllerHandle.
702   @param  ChildHandle                           ChildHandle The handle of the
703                                                 child to destroy.
704 
705   @retval EFI_SUCCESS                           One or more drivers were
706                                                 disconnected from the controller.
707   @retval EFI_SUCCESS                           On entry, no drivers are managing
708                                                 ControllerHandle.
709   @retval EFI_SUCCESS                           DriverImageHandle is not NULL,
710                                                 and on entry DriverImageHandle is
711                                                 not managing ControllerHandle.
712   @retval EFI_INVALID_PARAMETER                 ControllerHandle is NULL.
713   @retval EFI_INVALID_PARAMETER                 DriverImageHandle is not NULL,
714                                                 and it is not a valid EFI_HANDLE.
715   @retval EFI_INVALID_PARAMETER                 ChildHandle is not NULL, and it
716                                                 is not a valid EFI_HANDLE.
717   @retval EFI_OUT_OF_RESOURCES                  There are not enough resources
718                                                 available to disconnect any
719                                                 drivers from ControllerHandle.
720   @retval EFI_DEVICE_ERROR                      The controller could not be
721                                                 disconnected because of a device
722                                                 error.
723 
724 **/
725 EFI_STATUS
726 EFIAPI
CoreDisconnectController(IN EFI_HANDLE ControllerHandle,IN EFI_HANDLE DriverImageHandle OPTIONAL,IN EFI_HANDLE ChildHandle OPTIONAL)727 CoreDisconnectController (
728   IN  EFI_HANDLE  ControllerHandle,
729   IN  EFI_HANDLE  DriverImageHandle  OPTIONAL,
730   IN  EFI_HANDLE  ChildHandle        OPTIONAL
731   )
732 {
733   EFI_STATUS                          Status;
734   IHANDLE                             *Handle;
735   EFI_HANDLE                          *DriverImageHandleBuffer;
736   EFI_HANDLE                          *ChildBuffer;
737   UINTN                               Index;
738   UINTN                               HandleIndex;
739   UINTN                               DriverImageHandleCount;
740   UINTN                               ChildrenToStop;
741   UINTN                               ChildBufferCount;
742   UINTN                               StopCount;
743   BOOLEAN                             Duplicate;
744   BOOLEAN                             ChildHandleValid;
745   BOOLEAN                             DriverImageHandleValid;
746   LIST_ENTRY                          *Link;
747   LIST_ENTRY                          *ProtLink;
748   OPEN_PROTOCOL_DATA                  *OpenData;
749   PROTOCOL_INTERFACE                  *Prot;
750   EFI_DRIVER_BINDING_PROTOCOL         *DriverBinding;
751 
752   //
753   // Make sure ControllerHandle is valid
754   //
755   Status = CoreValidateHandle (ControllerHandle);
756   if (EFI_ERROR (Status)) {
757     return Status;
758   }
759 
760   //
761   // Make sure ChildHandle is valid if it is not NULL
762   //
763   if (ChildHandle != NULL) {
764     Status = CoreValidateHandle (ChildHandle);
765     if (EFI_ERROR (Status)) {
766       return Status;
767     }
768   }
769 
770   Handle = ControllerHandle;
771 
772   //
773   // Get list of drivers that are currently managing ControllerHandle
774   //
775   DriverImageHandleBuffer = NULL;
776   DriverImageHandleCount  = 1;
777 
778   if (DriverImageHandle == NULL) {
779     //
780     // Look at each protocol interface for a match
781     //
782     DriverImageHandleCount = 0;
783 
784     CoreAcquireProtocolLock ();
785     for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
786       Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
787       for (ProtLink = Prot->OpenList.ForwardLink;
788            ProtLink != &Prot->OpenList;
789            ProtLink = ProtLink->ForwardLink) {
790         OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
791         if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
792           DriverImageHandleCount++;
793         }
794       }
795     }
796     CoreReleaseProtocolLock ();
797 
798     //
799     // If there are no drivers managing this controller, then return EFI_SUCCESS
800     //
801     if (DriverImageHandleCount == 0) {
802       Status = EFI_SUCCESS;
803       goto Done;
804     }
805 
806     DriverImageHandleBuffer = AllocatePool (sizeof (EFI_HANDLE) * DriverImageHandleCount);
807     if (DriverImageHandleBuffer == NULL) {
808       Status = EFI_OUT_OF_RESOURCES;
809       goto Done;
810     }
811 
812     DriverImageHandleCount = 0;
813 
814     CoreAcquireProtocolLock ();
815     for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
816       Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
817       for (ProtLink = Prot->OpenList.ForwardLink;
818            ProtLink != &Prot->OpenList;
819            ProtLink = ProtLink->ForwardLink) {
820         OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
821         if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
822           Duplicate = FALSE;
823           for (Index = 0; Index< DriverImageHandleCount; Index++) {
824             if (DriverImageHandleBuffer[Index] == OpenData->AgentHandle) {
825               Duplicate = TRUE;
826               break;
827             }
828           }
829           if (!Duplicate) {
830             DriverImageHandleBuffer[DriverImageHandleCount] = OpenData->AgentHandle;
831             DriverImageHandleCount++;
832           }
833         }
834       }
835     }
836     CoreReleaseProtocolLock ();
837   }
838 
839   StopCount = 0;
840   for (HandleIndex = 0; HandleIndex < DriverImageHandleCount; HandleIndex++) {
841 
842     if (DriverImageHandleBuffer != NULL) {
843       DriverImageHandle = DriverImageHandleBuffer[HandleIndex];
844     }
845 
846     //
847     // Get the Driver Binding Protocol of the driver that is managing this controller
848     //
849     Status = CoreHandleProtocol (
850                DriverImageHandle,
851                &gEfiDriverBindingProtocolGuid,
852                (VOID **)&DriverBinding
853                );
854     if (EFI_ERROR (Status) || DriverBinding == NULL) {
855       Status = EFI_INVALID_PARAMETER;
856       goto Done;
857     }
858 
859     //
860     // Look at each protocol interface for a match
861     //
862     DriverImageHandleValid = FALSE;
863     ChildBufferCount = 0;
864 
865     CoreAcquireProtocolLock ();
866     for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
867       Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
868       for (ProtLink = Prot->OpenList.ForwardLink;
869            ProtLink != &Prot->OpenList;
870            ProtLink = ProtLink->ForwardLink) {
871         OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
872         if (OpenData->AgentHandle == DriverImageHandle) {
873           if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
874             ChildBufferCount++;
875           }
876           if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
877             DriverImageHandleValid = TRUE;
878           }
879         }
880       }
881     }
882     CoreReleaseProtocolLock ();
883 
884     if (DriverImageHandleValid) {
885       ChildHandleValid = FALSE;
886       ChildBuffer = NULL;
887       if (ChildBufferCount != 0) {
888         ChildBuffer = AllocatePool (sizeof (EFI_HANDLE) * ChildBufferCount);
889         if (ChildBuffer == NULL) {
890           Status = EFI_OUT_OF_RESOURCES;
891           goto Done;
892         }
893 
894         ChildBufferCount = 0;
895 
896         CoreAcquireProtocolLock ();
897         for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
898           Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
899           for (ProtLink = Prot->OpenList.ForwardLink;
900                ProtLink != &Prot->OpenList;
901                ProtLink = ProtLink->ForwardLink) {
902             OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
903             if ((OpenData->AgentHandle == DriverImageHandle) &&
904                 ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0)) {
905               Duplicate = FALSE;
906               for (Index = 0; Index < ChildBufferCount; Index++) {
907                 if (ChildBuffer[Index] == OpenData->ControllerHandle) {
908                   Duplicate = TRUE;
909                   break;
910                 }
911               }
912               if (!Duplicate) {
913                 ChildBuffer[ChildBufferCount] = OpenData->ControllerHandle;
914                 if (ChildHandle == ChildBuffer[ChildBufferCount]) {
915                   ChildHandleValid = TRUE;
916                 }
917                 ChildBufferCount++;
918               }
919             }
920           }
921         }
922         CoreReleaseProtocolLock ();
923       }
924 
925       if (ChildHandle == NULL || ChildHandleValid) {
926         ChildrenToStop = 0;
927         Status = EFI_SUCCESS;
928         if (ChildBufferCount > 0) {
929           if (ChildHandle != NULL) {
930             ChildrenToStop = 1;
931             Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, &ChildHandle);
932           } else {
933             ChildrenToStop = ChildBufferCount;
934             Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, ChildBuffer);
935           }
936         }
937         if (!EFI_ERROR (Status) && ((ChildHandle == NULL) || (ChildBufferCount == ChildrenToStop))) {
938           Status = DriverBinding->Stop (DriverBinding, ControllerHandle, 0, NULL);
939         }
940         if (!EFI_ERROR (Status)) {
941           StopCount++;
942         }
943       }
944 
945       if (ChildBuffer != NULL) {
946         CoreFreePool (ChildBuffer);
947       }
948     }
949   }
950 
951   if (StopCount > 0) {
952     Status = EFI_SUCCESS;
953   } else {
954     Status = EFI_NOT_FOUND;
955   }
956 
957 Done:
958 
959   if (DriverImageHandleBuffer != NULL) {
960     CoreFreePool (DriverImageHandleBuffer);
961   }
962 
963   return Status;
964 }
965