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