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