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