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