]> git.proxmox.com Git - mirror_edk2.git/blame - 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
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
544 Status = DriverBinding->Supported(\r
022c6d45 545 DriverBinding,\r
28a00297 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
adc8840a 557 PERF_START (DriverBinding->DriverBindingHandle, DRIVERBINDING_START_TOK, NULL, 0);\r
28a00297 558 Status = DriverBinding->Start (\r
022c6d45 559 DriverBinding,\r
28a00297 560 ControllerHandle,\r
561 RemainingDevicePath\r
562 );\r
adc8840a 563 PERF_END (DriverBinding->DriverBindingHandle, DRIVERBINDING_START_TOK, NULL, 0);\r
28a00297 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
022c6d45 586 }\r
28a00297 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
022c6d45 595 }\r
28a00297 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
162ed594 604\r
605/**\r
606 Disonnects a controller from a driver\r
607\r
022c6d45 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
162ed594 635 error.\r
636\r
637**/\r
022c6d45 638EFI_STATUS\r
28a00297 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
28a00297 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
022c6d45 689 DriverImageHandleCount = 1;\r
690\r
28a00297 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
022c6d45 700 for (ProtLink = Prot->OpenList.ForwardLink;\r
701 ProtLink != &Prot->OpenList;\r
28a00297 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
022c6d45 710\r
28a00297 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
9c4ac31c 719 DriverImageHandleBuffer = AllocatePool (sizeof (EFI_HANDLE) * DriverImageHandleCount);\r
28a00297 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
022c6d45 730 for (ProtLink = Prot->OpenList.ForwardLink;\r
731 ProtLink != &Prot->OpenList;\r
28a00297 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
022c6d45 763 DriverImageHandle,\r
764 &gEfiDriverBindingProtocolGuid,\r
28a00297 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
022c6d45 781 for (ProtLink = Prot->OpenList.ForwardLink;\r
782 ProtLink != &Prot->OpenList;\r
28a00297 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
022c6d45 788 }\r
28a00297 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
9c4ac31c 801 ChildBuffer = AllocatePool (sizeof (EFI_HANDLE) * ChildBufferCount);\r
28a00297 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
022c6d45 812 for (ProtLink = Prot->OpenList.ForwardLink;\r
813 ProtLink != &Prot->OpenList;\r
28a00297 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
022c6d45 869\r
870Done:\r
28a00297 871\r
872 if (DriverImageHandleBuffer != NULL) {\r
873 CoreFreePool (DriverImageHandleBuffer);\r
874 }\r
875\r
876 return Status;\r
877}\r