]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Core/Dxe/Hand/DriverSupport.c
Partially make EdkModulePkg pass intel IPF compiler with /W4 /WX switched on.
[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
1cc8ee78 152STATIC\r
878ddf1f 153VOID\r
154AddSortedDriverBindingProtocol (\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
163Routine 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
168Arguments:\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
180Returns:\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
238STATIC\r
239EFI_STATUS \r
240CoreConnectSingleController (\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
247Routine Description:\r
248\r
249 Connects a controller to a driver.\r
250\r
251Arguments:\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
258Returns:\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
878ddf1f 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
878ddf1f 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
30a60d29 411 for ( ; SortIndex < NumberOfSortedDriverBindingProtocols; SortIndex++) {\r
878ddf1f 412 HighestVersion = SortedDriverBindingProtocols[SortIndex]->Version;\r
413 HighestIndex = SortIndex;\r
30a60d29 414 for (Index = SortIndex + 1; Index < NumberOfSortedDriverBindingProtocols; Index++) {\r
878ddf1f 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
507EFI_STATUS \r
508EFIAPI\r
509CoreDisconnectController (\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
516Routine Description:\r
517\r
518 Disonnects a controller from a driver\r
519\r
520Arguments:\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
527Returns:\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
764Done: \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
775STATIC\r
776EFI_STATUS\r
777GetHandleFromDriverBinding (\r
778 IN EFI_DRIVER_BINDING_PROTOCOL *DriverBindingNeed,\r
779 OUT EFI_HANDLE *Handle \r
780 )\r
781/*++\r
782\r
783Routine Description:\r
784\r
785 Locate the driver binding handle which a specified driver binding protocol installed on.\r
786\r
787Arguments:\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
794Returns:\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