Check in DxeCore for Nt32 platform. Currently, it does not follow PI/UEFI2.1.
[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 \r
27 \r
28 STATIC\r
29 EFI_STATUS\r
30 GetHandleFromDriverBinding (\r
31   IN EFI_DRIVER_BINDING_PROTOCOL           *DriverBindingNeed,\r
32   OUT  EFI_HANDLE                          *Handle \r
33   );\r
34 \r
35 \r
36 //\r
37 // Driver Support Function Prototypes\r
38 //\r
39 STATIC\r
40 EFI_STATUS \r
41 CoreConnectSingleController (\r
42   IN  EFI_HANDLE                ControllerHandle,\r
43   IN  EFI_HANDLE                *DriverImageHandle    OPTIONAL,\r
44   IN  EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath  OPTIONAL\r
45   );\r
46 \r
47 //\r
48 // Driver Support Functions\r
49 //\r
50 \r
51 \r
52 EFI_STATUS \r
53 EFIAPI\r
54 CoreConnectController (\r
55   IN  EFI_HANDLE                ControllerHandle,\r
56   IN  EFI_HANDLE                *DriverImageHandle    OPTIONAL,\r
57   IN  EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath  OPTIONAL,\r
58   IN  BOOLEAN                   Recursive\r
59   )\r
60 /*++\r
61 \r
62 Routine Description:\r
63 \r
64   Connects one or more drivers to a controller.\r
65 \r
66 Arguments:\r
67 \r
68   ControllerHandle            - Handle of the controller to be connected.\r
69 \r
70   DriverImageHandle           - DriverImageHandle A pointer to an ordered list of driver image handles.\r
71 \r
72   RemainingDevicePath         - RemainingDevicePath A pointer to the device path that specifies a child of the\r
73                                 controller specified by ControllerHandle.\r
74     \r
75   Recursive                   - Whether the function would be called recursively or not.\r
76 \r
77 Returns:\r
78 \r
79   Status code.\r
80 \r
81 --*/\r
82 {\r
83   EFI_STATUS                           Status;\r
84   EFI_STATUS                           ReturnStatus;\r
85   IHANDLE                              *Handle;\r
86   PROTOCOL_INTERFACE                   *Prot;\r
87   LIST_ENTRY                           *Link;\r
88   LIST_ENTRY                           *ProtLink;\r
89   OPEN_PROTOCOL_DATA                   *OpenData;\r
90   EFI_DEVICE_PATH_PROTOCOL             *AlignedRemainingDevicePath;\r
91   \r
92   //\r
93   // Make sure ControllerHandle is valid\r
94   //\r
95   Status = CoreValidateHandle (ControllerHandle);\r
96   if (EFI_ERROR (Status)) {\r
97     return Status;\r
98   }\r
99 \r
100   Handle = ControllerHandle;\r
101 \r
102   //\r
103   // Connect all drivers to ControllerHandle \r
104   //\r
105   AlignedRemainingDevicePath = NULL;\r
106   if (RemainingDevicePath != NULL) {\r
107     AlignedRemainingDevicePath = CoreDuplicateDevicePath (RemainingDevicePath);\r
108   }\r
109   ReturnStatus = CoreConnectSingleController (\r
110                    ControllerHandle,\r
111                    DriverImageHandle,\r
112                    AlignedRemainingDevicePath\r
113                    );\r
114   if (AlignedRemainingDevicePath != NULL) {\r
115     CoreFreePool (AlignedRemainingDevicePath);\r
116   }\r
117 \r
118   //\r
119   // If not recursive, then just return after connecting drivers to ControllerHandle\r
120   //\r
121   if (!Recursive) {\r
122     return ReturnStatus;\r
123   }\r
124 \r
125   //\r
126   // If recursive, then connect all drivers to all of ControllerHandle's children\r
127   //\r
128   CoreAcquireProtocolLock ();\r
129   for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
130     Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
131     for (ProtLink = Prot->OpenList.ForwardLink; \r
132            ProtLink != &Prot->OpenList; \r
133            ProtLink = ProtLink->ForwardLink) {\r
134         OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
135         if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
136           CoreReleaseProtocolLock ();\r
137           Status = CoreConnectController (\r
138                           OpenData->ControllerHandle,\r
139                           NULL,\r
140                           NULL,\r
141                           TRUE\r
142                           ); \r
143           CoreAcquireProtocolLock ();\r
144         }\r
145     }\r
146   }\r
147   CoreReleaseProtocolLock ();\r
148   \r
149   return ReturnStatus;\r
150 }\r
151 \r
152 STATIC\r
153 VOID\r
154 AddSortedDriverBindingProtocol (\r
155   IN      EFI_HANDLE                   DriverBindingHandle,\r
156   IN OUT  UINTN                        *NumberOfSortedDriverBindingProtocols, \r
157   IN OUT  EFI_DRIVER_BINDING_PROTOCOL  **SortedDriverBindingProtocols,\r
158   IN      UINTN                        DriverBindingHandleCount,\r
159   IN OUT  EFI_HANDLE                   *DriverBindingHandleBuffer\r
160   )\r
161 /*++\r
162 \r
163 Routine Description:\r
164 \r
165   Add Driver Binding Protocols from Context Driver Image Handles to sorted \r
166    Driver Binding Protocol list.\r
167 \r
168 Arguments:\r
169 \r
170   DriverBindingHandle - Handle of the driver binding protocol.\r
171 \r
172   NumberOfSortedDriverBindingProtocols - Number Of sorted driver binding protocols\r
173 \r
174   SortedDriverBindingProtocols - The sorted protocol list.                        \r
175     \r
176   DriverBindingHandleCount - Driver Binding Handle Count.\r
177 \r
178   DriverBindingHandleBuffer - The buffer of driver binding protocol to be modified.\r
179 \r
180 Returns:\r
181 \r
182   None.\r
183 \r
184 --*/\r
185 {\r
186   EFI_STATUS                   Status;\r
187   EFI_DRIVER_BINDING_PROTOCOL  *DriverBinding;\r
188   UINTN                        Index;\r
189 \r
190   //\r
191   // Make sure the DriverBindingHandle is valid\r
192   //\r
193   Status = CoreValidateHandle (DriverBindingHandle);\r
194   if (EFI_ERROR (Status)) {\r
195     return;\r
196   }\r
197 \r
198   //\r
199   // Retrieve the Driver Binding Protocol from DriverBindingHandle\r
200   //\r
201   Status = CoreHandleProtocol(\r
202              DriverBindingHandle,\r
203              &gEfiDriverBindingProtocolGuid,\r
204              (VOID **)&DriverBinding\r
205              );\r
206   //\r
207   // If DriverBindingHandle does not support the Driver Binding Protocol then return\r
208   //\r
209   if (EFI_ERROR (Status) || DriverBinding == NULL) {\r
210     return;\r
211   }\r
212 \r
213   //\r
214   // See if DriverBinding is already in the sorted list\r
215   //\r
216   for (Index = 0; Index < *NumberOfSortedDriverBindingProtocols; Index++) {\r
217     if (DriverBinding == SortedDriverBindingProtocols[Index]) {\r
218       return;\r
219     }\r
220   }\r
221 \r
222   //\r
223   // Add DriverBinding to the end of the list\r
224   //\r
225   SortedDriverBindingProtocols[*NumberOfSortedDriverBindingProtocols] = DriverBinding;\r
226   *NumberOfSortedDriverBindingProtocols = *NumberOfSortedDriverBindingProtocols + 1;\r
227 \r
228   //\r
229   // Mark the cooresponding handle in DriverBindingHandleBuffer as used\r
230   //\r
231   for (Index = 0; Index < DriverBindingHandleCount; Index++) {\r
232     if (DriverBindingHandleBuffer[Index] == DriverBindingHandle) {\r
233       DriverBindingHandleBuffer[Index] = NULL;\r
234     }\r
235   }\r
236 }\r
237  \r
238 STATIC\r
239 EFI_STATUS \r
240 CoreConnectSingleController (\r
241   IN  EFI_HANDLE                ControllerHandle,\r
242   IN  EFI_HANDLE                *ContextDriverImageHandles OPTIONAL,\r
243   IN  EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath       OPTIONAL     \r
244   )\r
245 /*++\r
246 \r
247 Routine Description:\r
248 \r
249   Connects a controller to a driver.\r
250 \r
251 Arguments:\r
252 \r
253   ControllerHandle            - Handle of the controller to be connected.\r
254   ContextDriverImageHandles   - DriverImageHandle A pointer to an ordered list of driver image handles.\r
255   RemainingDevicePath         - RemainingDevicePath A pointer to the device path that specifies a child \r
256                                 of the controller specified by ControllerHandle.\r
257     \r
258 Returns:\r
259 \r
260   EFI_SUCCESS           - One or more drivers were connected to ControllerHandle.\r
261   EFI_OUT_OF_RESOURCES  - No enough system resources to complete the request.\r
262   EFI_NOT_FOUND         - No drivers were connected to ControllerHandle.\r
263 \r
264 --*/\r
265 {\r
266   EFI_STATUS                                 Status;\r
267   UINTN                                      Index;\r
268   EFI_HANDLE                                 DriverImageHandle;\r
269   EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL      *PlatformDriverOverride;\r
270   EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL  *BusSpecificDriverOverride;\r
271   UINTN                                      DriverBindingHandleCount;\r
272   EFI_HANDLE                                 *DriverBindingHandleBuffer;\r
273   EFI_DRIVER_BINDING_PROTOCOL                *DriverBinding;\r
274   UINTN                                      NumberOfSortedDriverBindingProtocols;\r
275   EFI_DRIVER_BINDING_PROTOCOL                **SortedDriverBindingProtocols;\r
276   UINT32                                     HighestVersion;\r
277   UINTN                                      HighestIndex;\r
278   UINTN                                      SortIndex;\r
279   BOOLEAN                                    OneStarted;\r
280   BOOLEAN                                    DriverFound;\r
281   EFI_HANDLE                                 DriverBindingHandle;\r
282 \r
283   //\r
284   // DriverBindingHandle is used for performance measurement, initialize it here just in case.\r
285   //\r
286   DriverBindingHandle                   = NULL;\r
287   //\r
288   // Initialize local variables\r
289   //\r
290   DriverBindingHandleCount              = 0;\r
291   DriverBindingHandleBuffer             = NULL;\r
292   NumberOfSortedDriverBindingProtocols  = 0;\r
293   SortedDriverBindingProtocols          = NULL;\r
294 \r
295   //\r
296   // Get list of all Driver Binding Protocol Instances\r
297   //\r
298   Status = CoreLocateHandleBuffer (\r
299              ByProtocol,   \r
300              &gEfiDriverBindingProtocolGuid,  \r
301              NULL,\r
302              &DriverBindingHandleCount, \r
303              &DriverBindingHandleBuffer\r
304              );\r
305   if (EFI_ERROR (Status) || (DriverBindingHandleCount == 0)) {\r
306     return EFI_NOT_FOUND;\r
307   }\r
308 \r
309   //\r
310   // Allocate a duplicate array for the sorted Driver Binding Protocol Instances\r
311   //\r
312   SortedDriverBindingProtocols = CoreAllocateBootServicesPool (sizeof (VOID *) * DriverBindingHandleCount);\r
313   if (SortedDriverBindingProtocols == NULL) {\r
314     CoreFreePool (DriverBindingHandleBuffer);\r
315     return EFI_OUT_OF_RESOURCES;\r
316   }\r
317 \r
318   //\r
319   // Add Driver Binding Protocols from Context Driver Image Handles first\r
320   //\r
321   if (ContextDriverImageHandles != NULL) {\r
322     for (Index = 0; ContextDriverImageHandles[Index] != NULL; Index++) {\r
323       AddSortedDriverBindingProtocol (\r
324         ContextDriverImageHandles[Index],\r
325         &NumberOfSortedDriverBindingProtocols, \r
326         SortedDriverBindingProtocols,\r
327         DriverBindingHandleCount,\r
328         DriverBindingHandleBuffer\r
329         );\r
330     }\r
331   }\r
332 \r
333   //\r
334   // Add the Platform Driver Override Protocol drivers for ControllerHandle next\r
335   //\r
336   Status = CoreLocateProtocol (\r
337              &gEfiPlatformDriverOverrideProtocolGuid, \r
338              NULL, \r
339              (VOID **)&PlatformDriverOverride\r
340              );\r
341   if (!EFI_ERROR (Status) && (PlatformDriverOverride != NULL)) {\r
342     DriverImageHandle = NULL;\r
343     do {\r
344       Status = PlatformDriverOverride->GetDriver (\r
345                                          PlatformDriverOverride,\r
346                                          ControllerHandle,\r
347                                          &DriverImageHandle\r
348                                          );\r
349       if (!EFI_ERROR (Status)) {\r
350         AddSortedDriverBindingProtocol (\r
351           DriverImageHandle,\r
352           &NumberOfSortedDriverBindingProtocols, \r
353           SortedDriverBindingProtocols,\r
354           DriverBindingHandleCount,\r
355           DriverBindingHandleBuffer\r
356           );\r
357       }\r
358     } while (!EFI_ERROR (Status));\r
359   }\r
360 \r
361   //\r
362   // Get the Bus Specific Driver Override Protocol instance on the Controller Handle\r
363   //\r
364   Status = CoreHandleProtocol(\r
365              ControllerHandle,  \r
366              &gEfiBusSpecificDriverOverrideProtocolGuid, \r
367              (VOID **)&BusSpecificDriverOverride\r
368              );\r
369   if (!EFI_ERROR (Status) && (BusSpecificDriverOverride != NULL)) {\r
370     DriverImageHandle = NULL;\r
371     do {\r
372       Status = BusSpecificDriverOverride->GetDriver (\r
373                                             BusSpecificDriverOverride,\r
374                                             &DriverImageHandle\r
375                                             );\r
376       if (!EFI_ERROR (Status)) {\r
377         AddSortedDriverBindingProtocol (\r
378           DriverImageHandle,\r
379           &NumberOfSortedDriverBindingProtocols, \r
380           SortedDriverBindingProtocols,\r
381           DriverBindingHandleCount,\r
382           DriverBindingHandleBuffer\r
383           );\r
384       }\r
385     } while (!EFI_ERROR (Status));\r
386   }\r
387 \r
388   //\r
389   // Then add all the remaining Driver Binding Protocols\r
390   //\r
391   SortIndex = NumberOfSortedDriverBindingProtocols;\r
392   for (Index = 0; Index < DriverBindingHandleCount; Index++) {\r
393     AddSortedDriverBindingProtocol (\r
394       DriverBindingHandleBuffer[Index],\r
395       &NumberOfSortedDriverBindingProtocols, \r
396       SortedDriverBindingProtocols,\r
397       DriverBindingHandleCount,\r
398       DriverBindingHandleBuffer\r
399       );\r
400   }\r
401 \r
402   //\r
403   // Free the Driver Binding Handle Buffer\r
404   //\r
405   CoreFreePool (DriverBindingHandleBuffer);\r
406 \r
407   //\r
408   // Sort the remaining DriverBinding Protocol based on their Version field from\r
409   // highest to lowest.\r
410   //\r
411   for ( ; SortIndex < NumberOfSortedDriverBindingProtocols; SortIndex++) {\r
412     HighestVersion = SortedDriverBindingProtocols[SortIndex]->Version;\r
413     HighestIndex   = SortIndex;\r
414     for (Index = SortIndex + 1; Index < NumberOfSortedDriverBindingProtocols; Index++) {\r
415       if (SortedDriverBindingProtocols[Index]->Version > HighestVersion) {\r
416         HighestVersion = SortedDriverBindingProtocols[Index]->Version;\r
417         HighestIndex   = Index;\r
418       }\r
419     }\r
420     if (SortIndex != HighestIndex) {\r
421       DriverBinding = SortedDriverBindingProtocols[SortIndex];\r
422       SortedDriverBindingProtocols[SortIndex] = SortedDriverBindingProtocols[HighestIndex];\r
423       SortedDriverBindingProtocols[HighestIndex] = DriverBinding;\r
424     }\r
425   }\r
426 \r
427   //\r
428   // Loop until no more drivers can be started on ControllerHandle\r
429   //\r
430   OneStarted = FALSE;\r
431   do {\r
432 \r
433     //\r
434     // Loop through the sorted Driver Binding Protocol Instances in order, and see if\r
435     // any of the Driver Binding Protocols support the controller specified by \r
436     // ControllerHandle.\r
437     //\r
438     DriverBinding = NULL;\r
439     DriverFound = FALSE;\r
440     for (Index = 0; (Index < NumberOfSortedDriverBindingProtocols) && !DriverFound; Index++) {\r
441       if (SortedDriverBindingProtocols[Index] != NULL) {\r
442         DriverBinding = SortedDriverBindingProtocols[Index];\r
443         Status = DriverBinding->Supported(\r
444                                   DriverBinding, \r
445                                   ControllerHandle,\r
446                                   RemainingDevicePath\r
447                                   );\r
448         if (!EFI_ERROR (Status)) {\r
449           SortedDriverBindingProtocols[Index] = NULL;\r
450           DriverFound = TRUE;\r
451 \r
452           //\r
453           // A driver was found that supports ControllerHandle, so attempt to start the driver\r
454           // on ControllerHandle.\r
455           //\r
456           PERF_CODE_BEGIN ();\r
457           GetHandleFromDriverBinding (DriverBinding, &DriverBindingHandle);\r
458           PERF_CODE_END ();\r
459 \r
460           PERF_START (DriverBindingHandle, DRIVERBINDING_START_TOK, NULL, 0);\r
461           Status = DriverBinding->Start (\r
462                                     DriverBinding, \r
463                                     ControllerHandle,\r
464                                     RemainingDevicePath\r
465                                     );\r
466           PERF_END (DriverBindingHandle, DRIVERBINDING_START_TOK, NULL, 0);\r
467 \r
468           if (!EFI_ERROR (Status)) {\r
469             //\r
470             // The driver was successfully started on ControllerHandle, so set a flag\r
471             //\r
472             OneStarted = TRUE;\r
473           }\r
474         }\r
475       }\r
476     }\r
477   } while (DriverFound);\r
478 \r
479   //\r
480   // Free any buffers that were allocated with AllocatePool()\r
481   //\r
482   CoreFreePool (SortedDriverBindingProtocols);\r
483 \r
484   //\r
485   // If at least one driver was started on ControllerHandle, then return EFI_SUCCESS.\r
486   //\r
487   if (OneStarted) {\r
488     return EFI_SUCCESS;\r
489   } \r
490 \r
491   //\r
492   // If no drivers started and RemainingDevicePath is an End Device Path Node, then return EFI_SUCCESS\r
493   //\r
494   if (RemainingDevicePath != NULL) {\r
495     if (IsDevicePathEnd (RemainingDevicePath)) {\r
496       return EFI_SUCCESS;\r
497     }\r
498   } \r
499 \r
500   //\r
501   // Otherwise, no drivers were started on ControllerHandle, so return EFI_NOT_FOUND\r
502   //\r
503   return EFI_NOT_FOUND;\r
504 }\r
505 \r
506 \r
507 EFI_STATUS \r
508 EFIAPI\r
509 CoreDisconnectController (\r
510   IN  EFI_HANDLE  ControllerHandle,\r
511   IN  EFI_HANDLE  DriverImageHandle  OPTIONAL,\r
512   IN  EFI_HANDLE  ChildHandle        OPTIONAL\r
513   )\r
514 /*++\r
515 \r
516 Routine Description:\r
517 \r
518   Disonnects a controller from a driver\r
519 \r
520 Arguments:\r
521 \r
522   ControllerHandle  - ControllerHandle The handle of the controller from which driver(s) \r
523                         are to be disconnected.\r
524   DriverImageHandle - DriverImageHandle The driver to disconnect from ControllerHandle.\r
525   ChildHandle       - ChildHandle The handle of the child to destroy.\r
526 \r
527 Returns:\r
528 \r
529   EFI_SUCCESS           -  One or more drivers were disconnected from the controller.\r
530   EFI_SUCCESS           -  On entry, no drivers are managing ControllerHandle.\r
531   EFI_SUCCESS           -  DriverImageHandle is not NULL, and on entry DriverImageHandle is not managing ControllerHandle.\r
532   EFI_INVALID_PARAMETER -  ControllerHandle is not a valid EFI_HANDLE.\r
533   EFI_INVALID_PARAMETER -  DriverImageHandle is not NULL, and it is not a valid EFI_HANDLE.\r
534   EFI_INVALID_PARAMETER -  ChildHandle is not NULL, and it is not a valid EFI_HANDLE.\r
535   EFI_OUT_OF_RESOURCES  -  There are not enough resources available to disconnect any drivers from ControllerHandle.\r
536   EFI_DEVICE_ERROR      -  The controller could not be disconnected because of a device error.\r
537 \r
538 --*/\r
539 {\r
540   EFI_STATUS                          Status;\r
541   IHANDLE                             *Handle;\r
542   EFI_HANDLE                          *DriverImageHandleBuffer;\r
543   EFI_HANDLE                          *ChildBuffer;\r
544   UINTN                               Index;\r
545   UINTN                               HandleIndex;\r
546   UINTN                               DriverImageHandleCount;\r
547   UINTN                               ChildrenToStop;\r
548   UINTN                               ChildBufferCount;\r
549   UINTN                               StopCount;\r
550   BOOLEAN                             Duplicate;\r
551   BOOLEAN                             ChildHandleValid;\r
552   BOOLEAN                             DriverImageHandleValid;\r
553   LIST_ENTRY                          *Link;\r
554   LIST_ENTRY                          *ProtLink;\r
555   OPEN_PROTOCOL_DATA                  *OpenData;\r
556   PROTOCOL_INTERFACE                  *Prot;\r
557   EFI_DRIVER_BINDING_PROTOCOL         *DriverBinding;\r
558 \r
559   //\r
560   // Make sure ControllerHandle is valid\r
561   //\r
562   Status = CoreValidateHandle (ControllerHandle);\r
563   if (EFI_ERROR (Status)) {\r
564     return Status;\r
565   }\r
566 \r
567   //\r
568   // Make sure ChildHandle is valid if it is not NULL\r
569   //\r
570   if (ChildHandle != NULL) {\r
571     Status = CoreValidateHandle (ChildHandle);\r
572     if (EFI_ERROR (Status)) {\r
573       return Status;\r
574     }\r
575   }\r
576 \r
577   Handle = ControllerHandle;\r
578 \r
579   //\r
580   // Get list of drivers that are currently managing ControllerHandle\r
581   //\r
582   DriverImageHandleBuffer = NULL;\r
583   DriverImageHandleCount  = 1;  \r
584   \r
585   if (DriverImageHandle == NULL) {\r
586     //\r
587     // Look at each protocol interface for a match\r
588     //\r
589     DriverImageHandleCount = 0;\r
590 \r
591     CoreAcquireProtocolLock ();\r
592     for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
593       Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
594       for (ProtLink = Prot->OpenList.ForwardLink; \r
595            ProtLink != &Prot->OpenList; \r
596            ProtLink = ProtLink->ForwardLink) {\r
597         OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
598         if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {\r
599           DriverImageHandleCount++;\r
600         }\r
601       }\r
602     }\r
603     CoreReleaseProtocolLock ();\r
604     \r
605     //\r
606     // If there are no drivers managing this controller, then return EFI_SUCCESS\r
607     //\r
608     if (DriverImageHandleCount == 0) {\r
609       Status = EFI_SUCCESS;\r
610       goto Done;\r
611     }\r
612 \r
613     DriverImageHandleBuffer = CoreAllocateBootServicesPool (sizeof (EFI_HANDLE) * DriverImageHandleCount);\r
614     if (DriverImageHandleBuffer == NULL) {\r
615       Status = EFI_OUT_OF_RESOURCES;\r
616       goto Done;\r
617     }\r
618 \r
619     DriverImageHandleCount = 0;\r
620 \r
621     CoreAcquireProtocolLock ();\r
622     for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
623       Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
624       for (ProtLink = Prot->OpenList.ForwardLink; \r
625            ProtLink != &Prot->OpenList; \r
626            ProtLink = ProtLink->ForwardLink) {\r
627         OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
628         if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {\r
629           Duplicate = FALSE;\r
630           for (Index = 0; Index< DriverImageHandleCount; Index++) {\r
631             if (DriverImageHandleBuffer[Index] == OpenData->AgentHandle) {\r
632               Duplicate = TRUE;\r
633               break;\r
634             }\r
635           }\r
636           if (!Duplicate) {\r
637             DriverImageHandleBuffer[DriverImageHandleCount] = OpenData->AgentHandle;\r
638             DriverImageHandleCount++;\r
639           }\r
640         }\r
641       }\r
642     }\r
643     CoreReleaseProtocolLock ();\r
644   }\r
645 \r
646   StopCount = 0;\r
647   for (HandleIndex = 0; HandleIndex < DriverImageHandleCount; HandleIndex++) {\r
648 \r
649     if (DriverImageHandleBuffer != NULL) {\r
650       DriverImageHandle = DriverImageHandleBuffer[HandleIndex];\r
651     }\r
652 \r
653     //\r
654     // Get the Driver Binding Protocol of the driver that is managing this controller\r
655     //\r
656     Status = CoreHandleProtocol (\r
657                DriverImageHandle,  \r
658                &gEfiDriverBindingProtocolGuid,   \r
659                (VOID **)&DriverBinding\r
660                );\r
661     if (EFI_ERROR (Status)) {\r
662       Status = EFI_INVALID_PARAMETER;\r
663       goto Done;\r
664     }\r
665 \r
666     //\r
667     // Look at each protocol interface for a match\r
668     //\r
669     DriverImageHandleValid = FALSE;\r
670     ChildBufferCount = 0;\r
671 \r
672     CoreAcquireProtocolLock ();\r
673     for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
674       Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
675       for (ProtLink = Prot->OpenList.ForwardLink; \r
676            ProtLink != &Prot->OpenList; \r
677            ProtLink = ProtLink->ForwardLink) {\r
678         OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
679         if (OpenData->AgentHandle == DriverImageHandle) {\r
680           if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
681             ChildBufferCount++;\r
682           } \r
683           if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {\r
684             DriverImageHandleValid = TRUE;\r
685           }\r
686         }\r
687       }\r
688     }\r
689     CoreReleaseProtocolLock ();\r
690 \r
691     if (DriverImageHandleValid) {\r
692       ChildHandleValid = FALSE;\r
693       ChildBuffer = NULL;\r
694       if (ChildBufferCount != 0) {\r
695         ChildBuffer = CoreAllocateBootServicesPool (sizeof (EFI_HANDLE) * ChildBufferCount);\r
696         if (ChildBuffer == NULL) {\r
697           Status = EFI_OUT_OF_RESOURCES;\r
698           goto Done;\r
699         }\r
700 \r
701         ChildBufferCount = 0;\r
702 \r
703         CoreAcquireProtocolLock ();\r
704         for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
705           Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
706           for (ProtLink = Prot->OpenList.ForwardLink; \r
707                ProtLink != &Prot->OpenList; \r
708                ProtLink = ProtLink->ForwardLink) {\r
709             OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
710             if ((OpenData->AgentHandle == DriverImageHandle) &&\r
711                 ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0)) {\r
712               Duplicate = FALSE;\r
713               for (Index = 0; Index < ChildBufferCount; Index++) {\r
714                 if (ChildBuffer[Index] == OpenData->ControllerHandle) {\r
715                   Duplicate = TRUE;\r
716                   break;\r
717                 }\r
718               }\r
719               if (!Duplicate) {\r
720                 ChildBuffer[ChildBufferCount] = OpenData->ControllerHandle;\r
721                 if (ChildHandle == ChildBuffer[ChildBufferCount]) {\r
722                   ChildHandleValid = TRUE;\r
723                 }\r
724                 ChildBufferCount++;\r
725               }\r
726             }\r
727           }\r
728         }\r
729         CoreReleaseProtocolLock ();\r
730       }\r
731 \r
732       if (ChildHandle == NULL || ChildHandleValid) {\r
733         ChildrenToStop = 0;\r
734         Status = EFI_SUCCESS;\r
735         if (ChildBufferCount > 0) {\r
736           if (ChildHandle != NULL) {\r
737             ChildrenToStop = 1;\r
738             Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, &ChildHandle);\r
739           } else {\r
740             ChildrenToStop = ChildBufferCount;\r
741             Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, ChildBuffer);\r
742           }\r
743         }\r
744         if (!EFI_ERROR (Status) && ((ChildHandle == NULL) || (ChildBufferCount == ChildrenToStop))) {\r
745           Status = DriverBinding->Stop (DriverBinding, ControllerHandle, 0, NULL);\r
746         }\r
747         if (!EFI_ERROR (Status)) {\r
748           StopCount++;\r
749         }\r
750       }\r
751 \r
752       if (ChildBuffer != NULL) {\r
753         CoreFreePool (ChildBuffer);\r
754       }\r
755     }\r
756   }\r
757 \r
758   if (StopCount > 0) {\r
759     Status = EFI_SUCCESS;\r
760   } else {\r
761     Status = EFI_NOT_FOUND;\r
762   }\r
763   \r
764 Done:  \r
765 \r
766   if (DriverImageHandleBuffer != NULL) {\r
767     CoreFreePool (DriverImageHandleBuffer);\r
768   }\r
769 \r
770   return Status;\r
771 }\r
772 \r
773 \r
774 \r
775 STATIC\r
776 EFI_STATUS\r
777 GetHandleFromDriverBinding (\r
778   IN   EFI_DRIVER_BINDING_PROTOCOL           *DriverBindingNeed,\r
779   OUT  EFI_HANDLE                            *Handle \r
780  )\r
781 /*++\r
782 \r
783 Routine Description:\r
784 \r
785   Locate the driver binding handle which a specified driver binding protocol installed on.\r
786 \r
787 Arguments:\r
788 \r
789   DriverBindingNeed  - The specified driver binding protocol.\r
790   \r
791   Handle             - The driver binding handle which the protocol installed on.\r
792   \r
793 \r
794 Returns:\r
795 \r
796   EFI_NOT_FOUND         - Could not find the handle.\r
797   \r
798   EFI_SUCCESS           - Successfully find the associated driver binding handle.\r
799   \r
800 --*/ \r
801  {\r
802   EFI_STATUS                          Status ;\r
803   EFI_DRIVER_BINDING_PROTOCOL         *DriverBinding;\r
804   UINTN                               DriverBindingHandleCount;\r
805   EFI_HANDLE                          *DriverBindingHandleBuffer;\r
806   UINTN                               Index;\r
807   \r
808   DriverBindingHandleCount = 0;\r
809   DriverBindingHandleBuffer = NULL;\r
810   *Handle = NULL_HANDLE;\r
811   Status = CoreLocateHandleBuffer (\r
812               ByProtocol,   \r
813               &gEfiDriverBindingProtocolGuid,  \r
814               NULL,\r
815               &DriverBindingHandleCount, \r
816               &DriverBindingHandleBuffer\r
817               );\r
818   if (EFI_ERROR (Status) || DriverBindingHandleCount == 0) {\r
819     return EFI_NOT_FOUND;\r
820   }\r
821   \r
822   for (Index = 0 ; Index < DriverBindingHandleCount; Index++ ) {\r
823     Status = CoreOpenProtocol(\r
824                       DriverBindingHandleBuffer[Index],\r
825                       &gEfiDriverBindingProtocolGuid,\r
826                       (VOID **)&DriverBinding,\r
827                       gDxeCoreImageHandle,\r
828                       NULL,\r
829                       EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
830                       );\r
831                       \r
832    if (!EFI_ERROR (Status) && DriverBinding != NULL) {\r
833     \r
834     if ( DriverBinding == DriverBindingNeed ) {\r
835       *Handle = DriverBindingHandleBuffer[Index];\r
836       CoreFreePool (DriverBindingHandleBuffer);         \r
837       return EFI_SUCCESS ;\r
838     }\r
839    }\r
840  }\r
841  \r
842  CoreFreePool (DriverBindingHandleBuffer);\r
843  return EFI_NOT_FOUND ;\r
844 }\r
845 \r