]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Hand/DriverSupport.c
Fix the typo in InstallMultipleProtocolInterfaces comments
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Hand / DriverSupport.c
CommitLineData
23c98c94 1/** @file\r
504214c4
LG
2 Support functions to connect/disconnect UEFI Driver model Protocol\r
3\r
396e9039 4Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
cd5ebaa0 5This program and the accompanying materials\r
23c98c94 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
28a00297 12\r
504214c4 13**/\r
28a00297 14\r
9c4ac31c 15#include "DxeMain.h"\r
ec90508b 16#include "Handle.h"\r
28a00297 17\r
28a00297 18\r
19//\r
20// Driver Support Functions\r
21//\r
162ed594 22/**\r
23 Connects one or more drivers to a controller.\r
24\r
022c6d45 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
162ed594 36\r
37 @return Status code.\r
38\r
39**/\r
022c6d45 40EFI_STATUS\r
28a00297 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
28a00297 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
85658066 57 EFI_HANDLE *ChildHandleBuffer;\r
58 UINTN ChildHandleCount;\r
59 UINTN Index;\r
022c6d45 60\r
28a00297 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
85658066 72 // Make a copy of RemainingDevicePath to guanatee it is aligned\r
28a00297 73 //\r
74 AlignedRemainingDevicePath = NULL;\r
75 if (RemainingDevicePath != NULL) {\r
9c4ac31c 76 AlignedRemainingDevicePath = DuplicateDevicePath (RemainingDevicePath);\r
6c857d66 77\r
78 if (AlignedRemainingDevicePath == NULL) {\r
79 return EFI_OUT_OF_RESOURCES;\r
80 }\r
28a00297 81 }\r
28a00297 82\r
83 //\r
85658066 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
28a00297 88 //\r
85658066 89 do {\r
90 ReturnStatus = CoreConnectSingleController (\r
e94a9ff7 91 ControllerHandle,\r
92 DriverImageHandle,\r
93 AlignedRemainingDevicePath\r
94 );\r
85658066 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
28a00297 102 }\r
103\r
104 //\r
105 // If recursive, then connect all drivers to all of ControllerHandle's children\r
106 //\r
85658066 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
022c6d45 132 for (ProtLink = Prot->OpenList.ForwardLink;\r
133 ProtLink != &Prot->OpenList;\r
85658066 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
9c4ac31c 145 ChildHandleBuffer = AllocatePool (ChildHandleCount * sizeof(EFI_HANDLE));\r
6c857d66 146 if (ChildHandleBuffer == NULL) {\r
fa3c419f 147 CoreReleaseProtocolLock ();\r
6c857d66 148 return EFI_OUT_OF_RESOURCES;\r
149 }\r
85658066 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
022c6d45 156 for (ProtLink = Prot->OpenList.ForwardLink;\r
157 ProtLink != &Prot->OpenList;\r
85658066 158 ProtLink = ProtLink->ForwardLink) {\r
28a00297 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
85658066 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
022c6d45 181 );\r
85658066 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
28a00297 190 return ReturnStatus;\r
191}\r
192\r
162ed594 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
022c6d45 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
162ed594 209\r
210 @return None.\r
211\r
212**/\r
28a00297 213VOID\r
214AddSortedDriverBindingProtocol (\r
215 IN EFI_HANDLE DriverBindingHandle,\r
022c6d45 216 IN OUT UINTN *NumberOfSortedDriverBindingProtocols,\r
28a00297 217 IN OUT EFI_DRIVER_BINDING_PROTOCOL **SortedDriverBindingProtocols,\r
218 IN UINTN DriverBindingHandleCount,\r
adc8840a 219 IN OUT EFI_HANDLE *DriverBindingHandleBuffer,\r
220 IN BOOLEAN IsImageHandle\r
28a00297 221 )\r
28a00297 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
adc8840a 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
e94a9ff7 250 (VOID **) &DriverBinding\r
adc8840a 251 );\r
70279390 252 if (EFI_ERROR (Status) || DriverBinding == NULL) {\r
253 continue;\r
254 }\r
255\r
adc8840a 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
022c6d45 263 NumberOfSortedDriverBindingProtocols,\r
adc8840a 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
28a00297 274 //\r
275 // Retrieve the Driver Binding Protocol from DriverBindingHandle\r
276 //\r
277 Status = CoreHandleProtocol(\r
278 DriverBindingHandle,\r
279 &gEfiDriverBindingProtocolGuid,\r
e94a9ff7 280 (VOID **) &DriverBinding\r
28a00297 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
85658066 292 for (Index = 0; Index < *NumberOfSortedDriverBindingProtocols && Index < DriverBindingHandleCount; Index++) {\r
28a00297 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
85658066 301 if (*NumberOfSortedDriverBindingProtocols < DriverBindingHandleCount) {\r
302 SortedDriverBindingProtocols[*NumberOfSortedDriverBindingProtocols] = DriverBinding;\r
303 }\r
28a00297 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
022c6d45 315\r
162ed594 316\r
317/**\r
318 Connects a controller to a driver.\r
319\r
022c6d45 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
162ed594 335 ControllerHandle.\r
336\r
337**/\r
022c6d45 338EFI_STATUS\r
28a00297 339CoreConnectSingleController (\r
340 IN EFI_HANDLE ControllerHandle,\r
341 IN EFI_HANDLE *ContextDriverImageHandles OPTIONAL,\r
022c6d45 342 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
28a00297 343 )\r
28a00297 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
70279390 352 UINTN NewDriverBindingHandleCount;\r
353 EFI_HANDLE *NewDriverBindingHandleBuffer;\r
28a00297 354 EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;\r
396e9039 355 EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL *DriverFamilyOverride;\r
28a00297 356 UINTN NumberOfSortedDriverBindingProtocols;\r
357 EFI_DRIVER_BINDING_PROTOCOL **SortedDriverBindingProtocols;\r
396e9039 358 UINT32 DriverFamilyOverrideVersion;\r
28a00297 359 UINT32 HighestVersion;\r
360 UINTN HighestIndex;\r
361 UINTN SortIndex;\r
362 BOOLEAN OneStarted;\r
363 BOOLEAN DriverFound;\r
28a00297 364\r
28a00297 365 //\r
366 // Initialize local variables\r
367 //\r
368 DriverBindingHandleCount = 0;\r
369 DriverBindingHandleBuffer = NULL;\r
370 NumberOfSortedDriverBindingProtocols = 0;\r
371 SortedDriverBindingProtocols = NULL;\r
372\r
373 //\r
374 // Get list of all Driver Binding Protocol Instances\r
375 //\r
376 Status = CoreLocateHandleBuffer (\r
022c6d45 377 ByProtocol,\r
378 &gEfiDriverBindingProtocolGuid,\r
28a00297 379 NULL,\r
022c6d45 380 &DriverBindingHandleCount,\r
28a00297 381 &DriverBindingHandleBuffer\r
382 );\r
383 if (EFI_ERROR (Status) || (DriverBindingHandleCount == 0)) {\r
384 return EFI_NOT_FOUND;\r
385 }\r
386\r
387 //\r
388 // Allocate a duplicate array for the sorted Driver Binding Protocol Instances\r
389 //\r
9c4ac31c 390 SortedDriverBindingProtocols = AllocatePool (sizeof (VOID *) * DriverBindingHandleCount);\r
28a00297 391 if (SortedDriverBindingProtocols == NULL) {\r
392 CoreFreePool (DriverBindingHandleBuffer);\r
393 return EFI_OUT_OF_RESOURCES;\r
394 }\r
395\r
396 //\r
397 // Add Driver Binding Protocols from Context Driver Image Handles first\r
398 //\r
399 if (ContextDriverImageHandles != NULL) {\r
400 for (Index = 0; ContextDriverImageHandles[Index] != NULL; Index++) {\r
401 AddSortedDriverBindingProtocol (\r
402 ContextDriverImageHandles[Index],\r
022c6d45 403 &NumberOfSortedDriverBindingProtocols,\r
28a00297 404 SortedDriverBindingProtocols,\r
405 DriverBindingHandleCount,\r
adc8840a 406 DriverBindingHandleBuffer,\r
407 FALSE\r
28a00297 408 );\r
409 }\r
410 }\r
411\r
412 //\r
413 // Add the Platform Driver Override Protocol drivers for ControllerHandle next\r
414 //\r
415 Status = CoreLocateProtocol (\r
022c6d45 416 &gEfiPlatformDriverOverrideProtocolGuid,\r
417 NULL,\r
e94a9ff7 418 (VOID **) &PlatformDriverOverride\r
28a00297 419 );\r
420 if (!EFI_ERROR (Status) && (PlatformDriverOverride != NULL)) {\r
421 DriverImageHandle = NULL;\r
422 do {\r
423 Status = PlatformDriverOverride->GetDriver (\r
424 PlatformDriverOverride,\r
425 ControllerHandle,\r
426 &DriverImageHandle\r
427 );\r
428 if (!EFI_ERROR (Status)) {\r
429 AddSortedDriverBindingProtocol (\r
430 DriverImageHandle,\r
022c6d45 431 &NumberOfSortedDriverBindingProtocols,\r
28a00297 432 SortedDriverBindingProtocols,\r
433 DriverBindingHandleCount,\r
adc8840a 434 DriverBindingHandleBuffer,\r
435 TRUE\r
28a00297 436 );\r
437 }\r
438 } while (!EFI_ERROR (Status));\r
439 }\r
440\r
396e9039
RN
441 //\r
442 // Add the Driver Family Override Protocol drivers for ControllerHandle\r
443 //\r
444 while (TRUE) {\r
445 HighestIndex = DriverBindingHandleCount;\r
446 HighestVersion = 0;\r
447 for (Index = 0; Index < DriverBindingHandleCount; Index++) {\r
448 Status = CoreHandleProtocol (\r
449 DriverBindingHandleBuffer[Index],\r
450 &gEfiDriverFamilyOverrideProtocolGuid,\r
451 (VOID **) &DriverFamilyOverride\r
452 );\r
453 if (!EFI_ERROR (Status) && (DriverFamilyOverride != NULL)) {\r
454 DriverFamilyOverrideVersion = DriverFamilyOverride->GetVersion (DriverFamilyOverride);\r
455 if ((HighestIndex == DriverBindingHandleCount) || (DriverFamilyOverrideVersion > HighestVersion)) {\r
456 HighestVersion = DriverFamilyOverrideVersion;\r
457 HighestIndex = Index;\r
458 }\r
459 }\r
460 }\r
461\r
462 if (HighestIndex == DriverBindingHandleCount) {\r
463 break;\r
464 }\r
465\r
466 AddSortedDriverBindingProtocol (\r
467 DriverBindingHandleBuffer[HighestIndex],\r
468 &NumberOfSortedDriverBindingProtocols,\r
469 SortedDriverBindingProtocols,\r
470 DriverBindingHandleCount,\r
471 DriverBindingHandleBuffer,\r
472 FALSE\r
473 );\r
474 }\r
475\r
28a00297 476 //\r
477 // Get the Bus Specific Driver Override Protocol instance on the Controller Handle\r
478 //\r
adc8840a 479 Status = CoreHandleProtocol (\r
022c6d45 480 ControllerHandle,\r
481 &gEfiBusSpecificDriverOverrideProtocolGuid,\r
e94a9ff7 482 (VOID **) &BusSpecificDriverOverride\r
28a00297 483 );\r
484 if (!EFI_ERROR (Status) && (BusSpecificDriverOverride != NULL)) {\r
485 DriverImageHandle = NULL;\r
486 do {\r
487 Status = BusSpecificDriverOverride->GetDriver (\r
488 BusSpecificDriverOverride,\r
489 &DriverImageHandle\r
490 );\r
491 if (!EFI_ERROR (Status)) {\r
492 AddSortedDriverBindingProtocol (\r
493 DriverImageHandle,\r
022c6d45 494 &NumberOfSortedDriverBindingProtocols,\r
28a00297 495 SortedDriverBindingProtocols,\r
496 DriverBindingHandleCount,\r
adc8840a 497 DriverBindingHandleBuffer,\r
498 TRUE\r
28a00297 499 );\r
500 }\r
501 } while (!EFI_ERROR (Status));\r
502 }\r
503\r
504 //\r
505 // Then add all the remaining Driver Binding Protocols\r
506 //\r
507 SortIndex = NumberOfSortedDriverBindingProtocols;\r
508 for (Index = 0; Index < DriverBindingHandleCount; Index++) {\r
509 AddSortedDriverBindingProtocol (\r
510 DriverBindingHandleBuffer[Index],\r
022c6d45 511 &NumberOfSortedDriverBindingProtocols,\r
28a00297 512 SortedDriverBindingProtocols,\r
513 DriverBindingHandleCount,\r
adc8840a 514 DriverBindingHandleBuffer,\r
515 FALSE\r
28a00297 516 );\r
517 }\r
518\r
519 //\r
520 // Free the Driver Binding Handle Buffer\r
521 //\r
522 CoreFreePool (DriverBindingHandleBuffer);\r
523\r
85658066 524 //\r
525 // If the number of Driver Binding Protocols has increased since this function started, then return\r
526 // EFI_NOT_READY, so it will be restarted\r
527 //\r
70279390 528 Status = CoreLocateHandleBuffer (\r
022c6d45 529 ByProtocol,\r
530 &gEfiDriverBindingProtocolGuid,\r
70279390 531 NULL,\r
022c6d45 532 &NewDriverBindingHandleCount,\r
70279390 533 &NewDriverBindingHandleBuffer\r
534 );\r
535 CoreFreePool (NewDriverBindingHandleBuffer);\r
536 if (NewDriverBindingHandleCount > DriverBindingHandleCount) {\r
85658066 537 //\r
538 // Free any buffers that were allocated with AllocatePool()\r
539 //\r
540 CoreFreePool (SortedDriverBindingProtocols);\r
541\r
542 return EFI_NOT_READY;\r
543 }\r
544\r
28a00297 545 //\r
546 // Sort the remaining DriverBinding Protocol based on their Version field from\r
547 // highest to lowest.\r
548 //\r
549 for ( ; SortIndex < NumberOfSortedDriverBindingProtocols; SortIndex++) {\r
550 HighestVersion = SortedDriverBindingProtocols[SortIndex]->Version;\r
551 HighestIndex = SortIndex;\r
552 for (Index = SortIndex + 1; Index < NumberOfSortedDriverBindingProtocols; Index++) {\r
553 if (SortedDriverBindingProtocols[Index]->Version > HighestVersion) {\r
554 HighestVersion = SortedDriverBindingProtocols[Index]->Version;\r
555 HighestIndex = Index;\r
556 }\r
557 }\r
558 if (SortIndex != HighestIndex) {\r
559 DriverBinding = SortedDriverBindingProtocols[SortIndex];\r
560 SortedDriverBindingProtocols[SortIndex] = SortedDriverBindingProtocols[HighestIndex];\r
561 SortedDriverBindingProtocols[HighestIndex] = DriverBinding;\r
562 }\r
563 }\r
564\r
565 //\r
566 // Loop until no more drivers can be started on ControllerHandle\r
567 //\r
568 OneStarted = FALSE;\r
569 do {\r
570\r
571 //\r
572 // Loop through the sorted Driver Binding Protocol Instances in order, and see if\r
022c6d45 573 // any of the Driver Binding Protocols support the controller specified by\r
28a00297 574 // ControllerHandle.\r
575 //\r
576 DriverBinding = NULL;\r
577 DriverFound = FALSE;\r
578 for (Index = 0; (Index < NumberOfSortedDriverBindingProtocols) && !DriverFound; Index++) {\r
579 if (SortedDriverBindingProtocols[Index] != NULL) {\r
580 DriverBinding = SortedDriverBindingProtocols[Index];\r
bc6b5892 581 PERF_START (DriverBinding->DriverBindingHandle, "DB:Support:", NULL, 0);\r
28a00297 582 Status = DriverBinding->Supported(\r
022c6d45 583 DriverBinding,\r
28a00297 584 ControllerHandle,\r
585 RemainingDevicePath\r
586 );\r
bc6b5892 587 PERF_END (DriverBinding->DriverBindingHandle, "DB:Support:", NULL, 0);\r
28a00297 588 if (!EFI_ERROR (Status)) {\r
589 SortedDriverBindingProtocols[Index] = NULL;\r
590 DriverFound = TRUE;\r
591\r
592 //\r
593 // A driver was found that supports ControllerHandle, so attempt to start the driver\r
594 // on ControllerHandle.\r
595 //\r
bc6b5892 596 PERF_START (DriverBinding->DriverBindingHandle, "DB:Start:", NULL, 0);\r
28a00297 597 Status = DriverBinding->Start (\r
022c6d45 598 DriverBinding,\r
28a00297 599 ControllerHandle,\r
600 RemainingDevicePath\r
601 );\r
bc6b5892 602 PERF_END (DriverBinding->DriverBindingHandle, "DB:Start:", NULL, 0);\r
28a00297 603\r
604 if (!EFI_ERROR (Status)) {\r
605 //\r
606 // The driver was successfully started on ControllerHandle, so set a flag\r
607 //\r
608 OneStarted = TRUE;\r
609 }\r
610 }\r
611 }\r
612 }\r
613 } while (DriverFound);\r
614\r
615 //\r
616 // Free any buffers that were allocated with AllocatePool()\r
617 //\r
618 CoreFreePool (SortedDriverBindingProtocols);\r
619\r
620 //\r
621 // If at least one driver was started on ControllerHandle, then return EFI_SUCCESS.\r
622 //\r
623 if (OneStarted) {\r
624 return EFI_SUCCESS;\r
022c6d45 625 }\r
28a00297 626\r
627 //\r
628 // If no drivers started and RemainingDevicePath is an End Device Path Node, then return EFI_SUCCESS\r
629 //\r
630 if (RemainingDevicePath != NULL) {\r
631 if (IsDevicePathEnd (RemainingDevicePath)) {\r
632 return EFI_SUCCESS;\r
633 }\r
022c6d45 634 }\r
28a00297 635\r
636 //\r
637 // Otherwise, no drivers were started on ControllerHandle, so return EFI_NOT_FOUND\r
638 //\r
639 return EFI_NOT_FOUND;\r
640}\r
641\r
642\r
162ed594 643\r
644/**\r
645 Disonnects a controller from a driver\r
646\r
022c6d45 647 @param ControllerHandle ControllerHandle The handle of\r
648 the controller from which\r
649 driver(s) are to be\r
650 disconnected.\r
651 @param DriverImageHandle DriverImageHandle The driver to\r
652 disconnect from ControllerHandle.\r
653 @param ChildHandle ChildHandle The handle of the\r
654 child to destroy.\r
655\r
656 @retval EFI_SUCCESS One or more drivers were\r
657 disconnected from the controller.\r
658 @retval EFI_SUCCESS On entry, no drivers are managing\r
659 ControllerHandle.\r
660 @retval EFI_SUCCESS DriverImageHandle is not NULL,\r
661 and on entry DriverImageHandle is\r
662 not managing ControllerHandle.\r
284ee2e8 663 @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.\r
022c6d45 664 @retval EFI_INVALID_PARAMETER DriverImageHandle is not NULL,\r
665 and it is not a valid EFI_HANDLE.\r
666 @retval EFI_INVALID_PARAMETER ChildHandle is not NULL, and it\r
667 is not a valid EFI_HANDLE.\r
668 @retval EFI_OUT_OF_RESOURCES There are not enough resources\r
669 available to disconnect any\r
670 drivers from ControllerHandle.\r
671 @retval EFI_DEVICE_ERROR The controller could not be\r
672 disconnected because of a device\r
162ed594 673 error.\r
674\r
675**/\r
022c6d45 676EFI_STATUS\r
28a00297 677EFIAPI\r
678CoreDisconnectController (\r
679 IN EFI_HANDLE ControllerHandle,\r
680 IN EFI_HANDLE DriverImageHandle OPTIONAL,\r
681 IN EFI_HANDLE ChildHandle OPTIONAL\r
682 )\r
28a00297 683{\r
684 EFI_STATUS Status;\r
685 IHANDLE *Handle;\r
686 EFI_HANDLE *DriverImageHandleBuffer;\r
687 EFI_HANDLE *ChildBuffer;\r
688 UINTN Index;\r
689 UINTN HandleIndex;\r
690 UINTN DriverImageHandleCount;\r
691 UINTN ChildrenToStop;\r
692 UINTN ChildBufferCount;\r
693 UINTN StopCount;\r
694 BOOLEAN Duplicate;\r
695 BOOLEAN ChildHandleValid;\r
696 BOOLEAN DriverImageHandleValid;\r
697 LIST_ENTRY *Link;\r
698 LIST_ENTRY *ProtLink;\r
699 OPEN_PROTOCOL_DATA *OpenData;\r
700 PROTOCOL_INTERFACE *Prot;\r
701 EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;\r
702\r
703 //\r
704 // Make sure ControllerHandle is valid\r
705 //\r
706 Status = CoreValidateHandle (ControllerHandle);\r
707 if (EFI_ERROR (Status)) {\r
708 return Status;\r
709 }\r
710\r
711 //\r
712 // Make sure ChildHandle is valid if it is not NULL\r
713 //\r
714 if (ChildHandle != NULL) {\r
715 Status = CoreValidateHandle (ChildHandle);\r
716 if (EFI_ERROR (Status)) {\r
717 return Status;\r
718 }\r
719 }\r
720\r
721 Handle = ControllerHandle;\r
722\r
723 //\r
724 // Get list of drivers that are currently managing ControllerHandle\r
725 //\r
726 DriverImageHandleBuffer = NULL;\r
022c6d45 727 DriverImageHandleCount = 1;\r
728\r
28a00297 729 if (DriverImageHandle == NULL) {\r
730 //\r
731 // Look at each protocol interface for a match\r
732 //\r
733 DriverImageHandleCount = 0;\r
734\r
735 CoreAcquireProtocolLock ();\r
736 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
737 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
022c6d45 738 for (ProtLink = Prot->OpenList.ForwardLink;\r
739 ProtLink != &Prot->OpenList;\r
28a00297 740 ProtLink = ProtLink->ForwardLink) {\r
741 OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
742 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {\r
743 DriverImageHandleCount++;\r
744 }\r
745 }\r
746 }\r
747 CoreReleaseProtocolLock ();\r
022c6d45 748\r
28a00297 749 //\r
750 // If there are no drivers managing this controller, then return EFI_SUCCESS\r
751 //\r
752 if (DriverImageHandleCount == 0) {\r
753 Status = EFI_SUCCESS;\r
754 goto Done;\r
755 }\r
756\r
9c4ac31c 757 DriverImageHandleBuffer = AllocatePool (sizeof (EFI_HANDLE) * DriverImageHandleCount);\r
28a00297 758 if (DriverImageHandleBuffer == NULL) {\r
759 Status = EFI_OUT_OF_RESOURCES;\r
760 goto Done;\r
761 }\r
762\r
763 DriverImageHandleCount = 0;\r
764\r
765 CoreAcquireProtocolLock ();\r
766 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
767 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
022c6d45 768 for (ProtLink = Prot->OpenList.ForwardLink;\r
769 ProtLink != &Prot->OpenList;\r
28a00297 770 ProtLink = ProtLink->ForwardLink) {\r
771 OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
772 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {\r
773 Duplicate = FALSE;\r
774 for (Index = 0; Index< DriverImageHandleCount; Index++) {\r
775 if (DriverImageHandleBuffer[Index] == OpenData->AgentHandle) {\r
776 Duplicate = TRUE;\r
777 break;\r
778 }\r
779 }\r
780 if (!Duplicate) {\r
781 DriverImageHandleBuffer[DriverImageHandleCount] = OpenData->AgentHandle;\r
782 DriverImageHandleCount++;\r
783 }\r
784 }\r
785 }\r
786 }\r
787 CoreReleaseProtocolLock ();\r
788 }\r
789\r
790 StopCount = 0;\r
791 for (HandleIndex = 0; HandleIndex < DriverImageHandleCount; HandleIndex++) {\r
792\r
793 if (DriverImageHandleBuffer != NULL) {\r
794 DriverImageHandle = DriverImageHandleBuffer[HandleIndex];\r
795 }\r
796\r
797 //\r
798 // Get the Driver Binding Protocol of the driver that is managing this controller\r
799 //\r
800 Status = CoreHandleProtocol (\r
022c6d45 801 DriverImageHandle,\r
802 &gEfiDriverBindingProtocolGuid,\r
28a00297 803 (VOID **)&DriverBinding\r
804 );\r
d2fbaaab 805 if (EFI_ERROR (Status) || DriverBinding == NULL) {\r
28a00297 806 Status = EFI_INVALID_PARAMETER;\r
807 goto Done;\r
808 }\r
809\r
810 //\r
811 // Look at each protocol interface for a match\r
812 //\r
813 DriverImageHandleValid = FALSE;\r
814 ChildBufferCount = 0;\r
815\r
816 CoreAcquireProtocolLock ();\r
817 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
818 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
022c6d45 819 for (ProtLink = Prot->OpenList.ForwardLink;\r
820 ProtLink != &Prot->OpenList;\r
28a00297 821 ProtLink = ProtLink->ForwardLink) {\r
822 OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
823 if (OpenData->AgentHandle == DriverImageHandle) {\r
824 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
825 ChildBufferCount++;\r
022c6d45 826 }\r
28a00297 827 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {\r
828 DriverImageHandleValid = TRUE;\r
829 }\r
830 }\r
831 }\r
832 }\r
833 CoreReleaseProtocolLock ();\r
834\r
835 if (DriverImageHandleValid) {\r
836 ChildHandleValid = FALSE;\r
837 ChildBuffer = NULL;\r
838 if (ChildBufferCount != 0) {\r
9c4ac31c 839 ChildBuffer = AllocatePool (sizeof (EFI_HANDLE) * ChildBufferCount);\r
28a00297 840 if (ChildBuffer == NULL) {\r
841 Status = EFI_OUT_OF_RESOURCES;\r
842 goto Done;\r
843 }\r
844\r
845 ChildBufferCount = 0;\r
846\r
847 CoreAcquireProtocolLock ();\r
848 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
849 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
022c6d45 850 for (ProtLink = Prot->OpenList.ForwardLink;\r
851 ProtLink != &Prot->OpenList;\r
28a00297 852 ProtLink = ProtLink->ForwardLink) {\r
853 OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
854 if ((OpenData->AgentHandle == DriverImageHandle) &&\r
855 ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0)) {\r
856 Duplicate = FALSE;\r
857 for (Index = 0; Index < ChildBufferCount; Index++) {\r
858 if (ChildBuffer[Index] == OpenData->ControllerHandle) {\r
859 Duplicate = TRUE;\r
860 break;\r
861 }\r
862 }\r
863 if (!Duplicate) {\r
864 ChildBuffer[ChildBufferCount] = OpenData->ControllerHandle;\r
865 if (ChildHandle == ChildBuffer[ChildBufferCount]) {\r
866 ChildHandleValid = TRUE;\r
867 }\r
868 ChildBufferCount++;\r
869 }\r
870 }\r
871 }\r
872 }\r
873 CoreReleaseProtocolLock ();\r
874 }\r
875\r
876 if (ChildHandle == NULL || ChildHandleValid) {\r
877 ChildrenToStop = 0;\r
878 Status = EFI_SUCCESS;\r
879 if (ChildBufferCount > 0) {\r
880 if (ChildHandle != NULL) {\r
881 ChildrenToStop = 1;\r
882 Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, &ChildHandle);\r
883 } else {\r
884 ChildrenToStop = ChildBufferCount;\r
885 Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, ChildBuffer);\r
886 }\r
887 }\r
888 if (!EFI_ERROR (Status) && ((ChildHandle == NULL) || (ChildBufferCount == ChildrenToStop))) {\r
889 Status = DriverBinding->Stop (DriverBinding, ControllerHandle, 0, NULL);\r
890 }\r
891 if (!EFI_ERROR (Status)) {\r
892 StopCount++;\r
893 }\r
894 }\r
895\r
896 if (ChildBuffer != NULL) {\r
897 CoreFreePool (ChildBuffer);\r
898 }\r
899 }\r
900 }\r
901\r
902 if (StopCount > 0) {\r
903 Status = EFI_SUCCESS;\r
904 } else {\r
905 Status = EFI_NOT_FOUND;\r
906 }\r
022c6d45 907\r
908Done:\r
28a00297 909\r
910 if (DriverImageHandleBuffer != NULL) {\r
911 CoreFreePool (DriverImageHandleBuffer);\r
912 }\r
913\r
914 return Status;\r
915}\r