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