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