]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Core/Dxe/Hand/DriverSupport.c
Update DXE Core so its own PE/COFF image is passed to the PeCoffExtraActionLib
[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 - 2010, Intel Corporation. All rights reserved.<BR>\r
5This 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 PERF_START (DriverBinding->DriverBindingHandle, "DB:Support:", NULL, 0);\r
545 Status = DriverBinding->Supported(\r
546 DriverBinding,\r
547 ControllerHandle,\r
548 RemainingDevicePath\r
549 );\r
550 PERF_END (DriverBinding->DriverBindingHandle, "DB:Support:", NULL, 0);\r
551 if (!EFI_ERROR (Status)) {\r
552 SortedDriverBindingProtocols[Index] = NULL;\r
553 DriverFound = TRUE;\r
554\r
555 //\r
556 // A driver was found that supports ControllerHandle, so attempt to start the driver\r
557 // on ControllerHandle.\r
558 //\r
559 PERF_START (DriverBinding->DriverBindingHandle, "DB:Start:", NULL, 0);\r
560 Status = DriverBinding->Start (\r
561 DriverBinding,\r
562 ControllerHandle,\r
563 RemainingDevicePath\r
564 );\r
565 PERF_END (DriverBinding->DriverBindingHandle, "DB:Start:", NULL, 0);\r
566\r
567 if (!EFI_ERROR (Status)) {\r
568 //\r
569 // The driver was successfully started on ControllerHandle, so set a flag\r
570 //\r
571 OneStarted = TRUE;\r
572 }\r
573 }\r
574 }\r
575 }\r
576 } while (DriverFound);\r
577\r
578 //\r
579 // Free any buffers that were allocated with AllocatePool()\r
580 //\r
581 CoreFreePool (SortedDriverBindingProtocols);\r
582\r
583 //\r
584 // If at least one driver was started on ControllerHandle, then return EFI_SUCCESS.\r
585 //\r
586 if (OneStarted) {\r
587 return EFI_SUCCESS;\r
588 }\r
589\r
590 //\r
591 // If no drivers started and RemainingDevicePath is an End Device Path Node, then return EFI_SUCCESS\r
592 //\r
593 if (RemainingDevicePath != NULL) {\r
594 if (IsDevicePathEnd (RemainingDevicePath)) {\r
595 return EFI_SUCCESS;\r
596 }\r
597 }\r
598\r
599 //\r
600 // Otherwise, no drivers were started on ControllerHandle, so return EFI_NOT_FOUND\r
601 //\r
602 return EFI_NOT_FOUND;\r
603}\r
604\r
605\r
606\r
607/**\r
608 Disonnects a controller from a driver\r
609\r
610 @param ControllerHandle ControllerHandle The handle of\r
611 the controller from which\r
612 driver(s) are to be\r
613 disconnected.\r
614 @param DriverImageHandle DriverImageHandle The driver to\r
615 disconnect from ControllerHandle.\r
616 @param ChildHandle ChildHandle The handle of the\r
617 child to destroy.\r
618\r
619 @retval EFI_SUCCESS One or more drivers were\r
620 disconnected from the controller.\r
621 @retval EFI_SUCCESS On entry, no drivers are managing\r
622 ControllerHandle.\r
623 @retval EFI_SUCCESS DriverImageHandle is not NULL,\r
624 and on entry DriverImageHandle is\r
625 not managing ControllerHandle.\r
626 @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid\r
627 EFI_HANDLE.\r
628 @retval EFI_INVALID_PARAMETER DriverImageHandle is not NULL,\r
629 and it is not a valid EFI_HANDLE.\r
630 @retval EFI_INVALID_PARAMETER ChildHandle is not NULL, and it\r
631 is not a valid EFI_HANDLE.\r
632 @retval EFI_OUT_OF_RESOURCES There are not enough resources\r
633 available to disconnect any\r
634 drivers from ControllerHandle.\r
635 @retval EFI_DEVICE_ERROR The controller could not be\r
636 disconnected because of a device\r
637 error.\r
638\r
639**/\r
640EFI_STATUS\r
641EFIAPI\r
642CoreDisconnectController (\r
643 IN EFI_HANDLE ControllerHandle,\r
644 IN EFI_HANDLE DriverImageHandle OPTIONAL,\r
645 IN EFI_HANDLE ChildHandle OPTIONAL\r
646 )\r
647{\r
648 EFI_STATUS Status;\r
649 IHANDLE *Handle;\r
650 EFI_HANDLE *DriverImageHandleBuffer;\r
651 EFI_HANDLE *ChildBuffer;\r
652 UINTN Index;\r
653 UINTN HandleIndex;\r
654 UINTN DriverImageHandleCount;\r
655 UINTN ChildrenToStop;\r
656 UINTN ChildBufferCount;\r
657 UINTN StopCount;\r
658 BOOLEAN Duplicate;\r
659 BOOLEAN ChildHandleValid;\r
660 BOOLEAN DriverImageHandleValid;\r
661 LIST_ENTRY *Link;\r
662 LIST_ENTRY *ProtLink;\r
663 OPEN_PROTOCOL_DATA *OpenData;\r
664 PROTOCOL_INTERFACE *Prot;\r
665 EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;\r
666\r
667 //\r
668 // Make sure ControllerHandle is valid\r
669 //\r
670 Status = CoreValidateHandle (ControllerHandle);\r
671 if (EFI_ERROR (Status)) {\r
672 return Status;\r
673 }\r
674\r
675 //\r
676 // Make sure ChildHandle is valid if it is not NULL\r
677 //\r
678 if (ChildHandle != NULL) {\r
679 Status = CoreValidateHandle (ChildHandle);\r
680 if (EFI_ERROR (Status)) {\r
681 return Status;\r
682 }\r
683 }\r
684\r
685 Handle = ControllerHandle;\r
686\r
687 //\r
688 // Get list of drivers that are currently managing ControllerHandle\r
689 //\r
690 DriverImageHandleBuffer = NULL;\r
691 DriverImageHandleCount = 1;\r
692\r
693 if (DriverImageHandle == NULL) {\r
694 //\r
695 // Look at each protocol interface for a match\r
696 //\r
697 DriverImageHandleCount = 0;\r
698\r
699 CoreAcquireProtocolLock ();\r
700 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
701 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
702 for (ProtLink = Prot->OpenList.ForwardLink;\r
703 ProtLink != &Prot->OpenList;\r
704 ProtLink = ProtLink->ForwardLink) {\r
705 OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
706 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {\r
707 DriverImageHandleCount++;\r
708 }\r
709 }\r
710 }\r
711 CoreReleaseProtocolLock ();\r
712\r
713 //\r
714 // If there are no drivers managing this controller, then return EFI_SUCCESS\r
715 //\r
716 if (DriverImageHandleCount == 0) {\r
717 Status = EFI_SUCCESS;\r
718 goto Done;\r
719 }\r
720\r
721 DriverImageHandleBuffer = AllocatePool (sizeof (EFI_HANDLE) * DriverImageHandleCount);\r
722 if (DriverImageHandleBuffer == NULL) {\r
723 Status = EFI_OUT_OF_RESOURCES;\r
724 goto Done;\r
725 }\r
726\r
727 DriverImageHandleCount = 0;\r
728\r
729 CoreAcquireProtocolLock ();\r
730 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
731 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
732 for (ProtLink = Prot->OpenList.ForwardLink;\r
733 ProtLink != &Prot->OpenList;\r
734 ProtLink = ProtLink->ForwardLink) {\r
735 OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
736 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {\r
737 Duplicate = FALSE;\r
738 for (Index = 0; Index< DriverImageHandleCount; Index++) {\r
739 if (DriverImageHandleBuffer[Index] == OpenData->AgentHandle) {\r
740 Duplicate = TRUE;\r
741 break;\r
742 }\r
743 }\r
744 if (!Duplicate) {\r
745 DriverImageHandleBuffer[DriverImageHandleCount] = OpenData->AgentHandle;\r
746 DriverImageHandleCount++;\r
747 }\r
748 }\r
749 }\r
750 }\r
751 CoreReleaseProtocolLock ();\r
752 }\r
753\r
754 StopCount = 0;\r
755 for (HandleIndex = 0; HandleIndex < DriverImageHandleCount; HandleIndex++) {\r
756\r
757 if (DriverImageHandleBuffer != NULL) {\r
758 DriverImageHandle = DriverImageHandleBuffer[HandleIndex];\r
759 }\r
760\r
761 //\r
762 // Get the Driver Binding Protocol of the driver that is managing this controller\r
763 //\r
764 Status = CoreHandleProtocol (\r
765 DriverImageHandle,\r
766 &gEfiDriverBindingProtocolGuid,\r
767 (VOID **)&DriverBinding\r
768 );\r
769 if (EFI_ERROR (Status) || DriverBinding == NULL) {\r
770 Status = EFI_INVALID_PARAMETER;\r
771 goto Done;\r
772 }\r
773\r
774 //\r
775 // Look at each protocol interface for a match\r
776 //\r
777 DriverImageHandleValid = FALSE;\r
778 ChildBufferCount = 0;\r
779\r
780 CoreAcquireProtocolLock ();\r
781 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
782 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
783 for (ProtLink = Prot->OpenList.ForwardLink;\r
784 ProtLink != &Prot->OpenList;\r
785 ProtLink = ProtLink->ForwardLink) {\r
786 OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
787 if (OpenData->AgentHandle == DriverImageHandle) {\r
788 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
789 ChildBufferCount++;\r
790 }\r
791 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {\r
792 DriverImageHandleValid = TRUE;\r
793 }\r
794 }\r
795 }\r
796 }\r
797 CoreReleaseProtocolLock ();\r
798\r
799 if (DriverImageHandleValid) {\r
800 ChildHandleValid = FALSE;\r
801 ChildBuffer = NULL;\r
802 if (ChildBufferCount != 0) {\r
803 ChildBuffer = AllocatePool (sizeof (EFI_HANDLE) * ChildBufferCount);\r
804 if (ChildBuffer == NULL) {\r
805 Status = EFI_OUT_OF_RESOURCES;\r
806 goto Done;\r
807 }\r
808\r
809 ChildBufferCount = 0;\r
810\r
811 CoreAcquireProtocolLock ();\r
812 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
813 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
814 for (ProtLink = Prot->OpenList.ForwardLink;\r
815 ProtLink != &Prot->OpenList;\r
816 ProtLink = ProtLink->ForwardLink) {\r
817 OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
818 if ((OpenData->AgentHandle == DriverImageHandle) &&\r
819 ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0)) {\r
820 Duplicate = FALSE;\r
821 for (Index = 0; Index < ChildBufferCount; Index++) {\r
822 if (ChildBuffer[Index] == OpenData->ControllerHandle) {\r
823 Duplicate = TRUE;\r
824 break;\r
825 }\r
826 }\r
827 if (!Duplicate) {\r
828 ChildBuffer[ChildBufferCount] = OpenData->ControllerHandle;\r
829 if (ChildHandle == ChildBuffer[ChildBufferCount]) {\r
830 ChildHandleValid = TRUE;\r
831 }\r
832 ChildBufferCount++;\r
833 }\r
834 }\r
835 }\r
836 }\r
837 CoreReleaseProtocolLock ();\r
838 }\r
839\r
840 if (ChildHandle == NULL || ChildHandleValid) {\r
841 ChildrenToStop = 0;\r
842 Status = EFI_SUCCESS;\r
843 if (ChildBufferCount > 0) {\r
844 if (ChildHandle != NULL) {\r
845 ChildrenToStop = 1;\r
846 Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, &ChildHandle);\r
847 } else {\r
848 ChildrenToStop = ChildBufferCount;\r
849 Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, ChildBuffer);\r
850 }\r
851 }\r
852 if (!EFI_ERROR (Status) && ((ChildHandle == NULL) || (ChildBufferCount == ChildrenToStop))) {\r
853 Status = DriverBinding->Stop (DriverBinding, ControllerHandle, 0, NULL);\r
854 }\r
855 if (!EFI_ERROR (Status)) {\r
856 StopCount++;\r
857 }\r
858 }\r
859\r
860 if (ChildBuffer != NULL) {\r
861 CoreFreePool (ChildBuffer);\r
862 }\r
863 }\r
864 }\r
865\r
866 if (StopCount > 0) {\r
867 Status = EFI_SUCCESS;\r
868 } else {\r
869 Status = EFI_NOT_FOUND;\r
870 }\r
871\r
872Done:\r
873\r
874 if (DriverImageHandleBuffer != NULL) {\r
875 CoreFreePool (DriverImageHandleBuffer);\r
876 }\r
877\r
878 return Status;\r
879}\r