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