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