]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Hand/DriverSupport.c
Update DxeCore for the performance infrastructure updates: Use Raw sting to replace...
[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
23c98c94 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
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
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
28a00297 362\r
28a00297 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
022c6d45 375 ByProtocol,\r
376 &gEfiDriverBindingProtocolGuid,\r
28a00297 377 NULL,\r
022c6d45 378 &DriverBindingHandleCount,\r
28a00297 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
9c4ac31c 388 SortedDriverBindingProtocols = AllocatePool (sizeof (VOID *) * DriverBindingHandleCount);\r
28a00297 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
022c6d45 401 &NumberOfSortedDriverBindingProtocols,\r
28a00297 402 SortedDriverBindingProtocols,\r
403 DriverBindingHandleCount,\r
adc8840a 404 DriverBindingHandleBuffer,\r
405 FALSE\r
28a00297 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
022c6d45 414 &gEfiPlatformDriverOverrideProtocolGuid,\r
415 NULL,\r
e94a9ff7 416 (VOID **) &PlatformDriverOverride\r
28a00297 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
022c6d45 429 &NumberOfSortedDriverBindingProtocols,\r
28a00297 430 SortedDriverBindingProtocols,\r
431 DriverBindingHandleCount,\r
adc8840a 432 DriverBindingHandleBuffer,\r
433 TRUE\r
28a00297 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
adc8840a 442 Status = CoreHandleProtocol (\r
022c6d45 443 ControllerHandle,\r
444 &gEfiBusSpecificDriverOverrideProtocolGuid,\r
e94a9ff7 445 (VOID **) &BusSpecificDriverOverride\r
28a00297 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
022c6d45 457 &NumberOfSortedDriverBindingProtocols,\r
28a00297 458 SortedDriverBindingProtocols,\r
459 DriverBindingHandleCount,\r
adc8840a 460 DriverBindingHandleBuffer,\r
461 TRUE\r
28a00297 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
022c6d45 474 &NumberOfSortedDriverBindingProtocols,\r
28a00297 475 SortedDriverBindingProtocols,\r
476 DriverBindingHandleCount,\r
adc8840a 477 DriverBindingHandleBuffer,\r
478 FALSE\r
28a00297 479 );\r
480 }\r
481\r
482 //\r
483 // Free the Driver Binding Handle Buffer\r
484 //\r
485 CoreFreePool (DriverBindingHandleBuffer);\r
486\r
85658066 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
70279390 491 Status = CoreLocateHandleBuffer (\r
022c6d45 492 ByProtocol,\r
493 &gEfiDriverBindingProtocolGuid,\r
70279390 494 NULL,\r
022c6d45 495 &NewDriverBindingHandleCount,\r
70279390 496 &NewDriverBindingHandleBuffer\r
497 );\r
498 CoreFreePool (NewDriverBindingHandleBuffer);\r
499 if (NewDriverBindingHandleCount > DriverBindingHandleCount) {\r
85658066 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
28a00297 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
022c6d45 536 // any of the Driver Binding Protocols support the controller specified by\r
28a00297 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
bc6b5892 544 PERF_START (DriverBinding->DriverBindingHandle, "DB:Support:", NULL, 0);\r
28a00297 545 Status = DriverBinding->Supported(\r
022c6d45 546 DriverBinding,\r
28a00297 547 ControllerHandle,\r
548 RemainingDevicePath\r
549 );\r
bc6b5892 550 PERF_END (DriverBinding->DriverBindingHandle, "DB:Support:", NULL, 0);\r
28a00297 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
bc6b5892 559 PERF_START (DriverBinding->DriverBindingHandle, "DB:Start:", NULL, 0);\r
28a00297 560 Status = DriverBinding->Start (\r
022c6d45 561 DriverBinding,\r
28a00297 562 ControllerHandle,\r
563 RemainingDevicePath\r
564 );\r
bc6b5892 565 PERF_END (DriverBinding->DriverBindingHandle, "DB:Start:", NULL, 0);\r
28a00297 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
022c6d45 588 }\r
28a00297 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
022c6d45 597 }\r
28a00297 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
162ed594 606\r
607/**\r
608 Disonnects a controller from a driver\r
609\r
022c6d45 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
162ed594 637 error.\r
638\r
639**/\r
022c6d45 640EFI_STATUS\r
28a00297 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
28a00297 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
022c6d45 691 DriverImageHandleCount = 1;\r
692\r
28a00297 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
022c6d45 702 for (ProtLink = Prot->OpenList.ForwardLink;\r
703 ProtLink != &Prot->OpenList;\r
28a00297 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
022c6d45 712\r
28a00297 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
9c4ac31c 721 DriverImageHandleBuffer = AllocatePool (sizeof (EFI_HANDLE) * DriverImageHandleCount);\r
28a00297 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
022c6d45 732 for (ProtLink = Prot->OpenList.ForwardLink;\r
733 ProtLink != &Prot->OpenList;\r
28a00297 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
022c6d45 765 DriverImageHandle,\r
766 &gEfiDriverBindingProtocolGuid,\r
28a00297 767 (VOID **)&DriverBinding\r
768 );\r
769 if (EFI_ERROR (Status)) {\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
022c6d45 783 for (ProtLink = Prot->OpenList.ForwardLink;\r
784 ProtLink != &Prot->OpenList;\r
28a00297 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
022c6d45 790 }\r
28a00297 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
9c4ac31c 803 ChildBuffer = AllocatePool (sizeof (EFI_HANDLE) * ChildBufferCount);\r
28a00297 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
022c6d45 814 for (ProtLink = Prot->OpenList.ForwardLink;\r
815 ProtLink != &Prot->OpenList;\r
28a00297 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
022c6d45 871\r
872Done:\r
28a00297 873\r
874 if (DriverImageHandleBuffer != NULL) {\r
875 CoreFreePool (DriverImageHandleBuffer);\r
876 }\r
877\r
878 return Status;\r
879}\r