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