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
CoreConnectController(IN EFI_HANDLE ControllerHandle,IN EFI_HANDLE * DriverImageHandle OPTIONAL,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL,IN BOOLEAN Recursive)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
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)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
CoreConnectSingleController(IN EFI_HANDLE ControllerHandle,IN EFI_HANDLE * ContextDriverImageHandles OPTIONAL,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)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
CoreDisconnectController(IN EFI_HANDLE ControllerHandle,IN EFI_HANDLE DriverImageHandle OPTIONAL,IN EFI_HANDLE ChildHandle OPTIONAL)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 }
959