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