]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Hand/DriverSupport.c
Check the parameter before use it.
[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
5fef1a34 4Copyright (c) 2006 - 2014, 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
43 @retval EFI_SECURITY_VIOLATION \r
44 The user has no permission to start UEFI device drivers on the device path \r
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
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
419\r
420 //\r
421 // Get list of all Driver Binding Protocol Instances\r
422 //\r
423 Status = CoreLocateHandleBuffer (\r
022c6d45 424 ByProtocol,\r
425 &gEfiDriverBindingProtocolGuid,\r
28a00297 426 NULL,\r
022c6d45 427 &DriverBindingHandleCount,\r
28a00297 428 &DriverBindingHandleBuffer\r
429 );\r
430 if (EFI_ERROR (Status) || (DriverBindingHandleCount == 0)) {\r
431 return EFI_NOT_FOUND;\r
432 }\r
433\r
434 //\r
435 // Allocate a duplicate array for the sorted Driver Binding Protocol Instances\r
436 //\r
9c4ac31c 437 SortedDriverBindingProtocols = AllocatePool (sizeof (VOID *) * DriverBindingHandleCount);\r
28a00297 438 if (SortedDriverBindingProtocols == NULL) {\r
439 CoreFreePool (DriverBindingHandleBuffer);\r
440 return EFI_OUT_OF_RESOURCES;\r
441 }\r
442\r
443 //\r
444 // Add Driver Binding Protocols from Context Driver Image Handles first\r
445 //\r
446 if (ContextDriverImageHandles != NULL) {\r
447 for (Index = 0; ContextDriverImageHandles[Index] != NULL; Index++) {\r
448 AddSortedDriverBindingProtocol (\r
449 ContextDriverImageHandles[Index],\r
022c6d45 450 &NumberOfSortedDriverBindingProtocols,\r
28a00297 451 SortedDriverBindingProtocols,\r
452 DriverBindingHandleCount,\r
adc8840a 453 DriverBindingHandleBuffer,\r
454 FALSE\r
28a00297 455 );\r
456 }\r
457 }\r
458\r
459 //\r
460 // Add the Platform Driver Override Protocol drivers for ControllerHandle next\r
461 //\r
462 Status = CoreLocateProtocol (\r
022c6d45 463 &gEfiPlatformDriverOverrideProtocolGuid,\r
464 NULL,\r
e94a9ff7 465 (VOID **) &PlatformDriverOverride\r
28a00297 466 );\r
467 if (!EFI_ERROR (Status) && (PlatformDriverOverride != NULL)) {\r
468 DriverImageHandle = NULL;\r
469 do {\r
470 Status = PlatformDriverOverride->GetDriver (\r
471 PlatformDriverOverride,\r
472 ControllerHandle,\r
473 &DriverImageHandle\r
474 );\r
475 if (!EFI_ERROR (Status)) {\r
476 AddSortedDriverBindingProtocol (\r
477 DriverImageHandle,\r
022c6d45 478 &NumberOfSortedDriverBindingProtocols,\r
28a00297 479 SortedDriverBindingProtocols,\r
480 DriverBindingHandleCount,\r
adc8840a 481 DriverBindingHandleBuffer,\r
482 TRUE\r
28a00297 483 );\r
484 }\r
485 } while (!EFI_ERROR (Status));\r
486 }\r
487\r
396e9039
RN
488 //\r
489 // Add the Driver Family Override Protocol drivers for ControllerHandle\r
490 //\r
491 while (TRUE) {\r
492 HighestIndex = DriverBindingHandleCount;\r
493 HighestVersion = 0;\r
494 for (Index = 0; Index < DriverBindingHandleCount; Index++) {\r
495 Status = CoreHandleProtocol (\r
496 DriverBindingHandleBuffer[Index],\r
497 &gEfiDriverFamilyOverrideProtocolGuid,\r
498 (VOID **) &DriverFamilyOverride\r
499 );\r
500 if (!EFI_ERROR (Status) && (DriverFamilyOverride != NULL)) {\r
501 DriverFamilyOverrideVersion = DriverFamilyOverride->GetVersion (DriverFamilyOverride);\r
502 if ((HighestIndex == DriverBindingHandleCount) || (DriverFamilyOverrideVersion > HighestVersion)) {\r
503 HighestVersion = DriverFamilyOverrideVersion;\r
504 HighestIndex = Index;\r
505 }\r
506 }\r
507 }\r
508\r
509 if (HighestIndex == DriverBindingHandleCount) {\r
510 break;\r
511 }\r
512\r
513 AddSortedDriverBindingProtocol (\r
514 DriverBindingHandleBuffer[HighestIndex],\r
515 &NumberOfSortedDriverBindingProtocols,\r
516 SortedDriverBindingProtocols,\r
517 DriverBindingHandleCount,\r
518 DriverBindingHandleBuffer,\r
519 FALSE\r
520 );\r
521 }\r
522\r
28a00297 523 //\r
524 // Get the Bus Specific Driver Override Protocol instance on the Controller Handle\r
525 //\r
adc8840a 526 Status = CoreHandleProtocol (\r
022c6d45 527 ControllerHandle,\r
528 &gEfiBusSpecificDriverOverrideProtocolGuid,\r
e94a9ff7 529 (VOID **) &BusSpecificDriverOverride\r
28a00297 530 );\r
531 if (!EFI_ERROR (Status) && (BusSpecificDriverOverride != NULL)) {\r
532 DriverImageHandle = NULL;\r
533 do {\r
534 Status = BusSpecificDriverOverride->GetDriver (\r
535 BusSpecificDriverOverride,\r
536 &DriverImageHandle\r
537 );\r
538 if (!EFI_ERROR (Status)) {\r
539 AddSortedDriverBindingProtocol (\r
540 DriverImageHandle,\r
022c6d45 541 &NumberOfSortedDriverBindingProtocols,\r
28a00297 542 SortedDriverBindingProtocols,\r
543 DriverBindingHandleCount,\r
adc8840a 544 DriverBindingHandleBuffer,\r
545 TRUE\r
28a00297 546 );\r
547 }\r
548 } while (!EFI_ERROR (Status));\r
549 }\r
550\r
551 //\r
552 // Then add all the remaining Driver Binding Protocols\r
553 //\r
554 SortIndex = NumberOfSortedDriverBindingProtocols;\r
555 for (Index = 0; Index < DriverBindingHandleCount; Index++) {\r
556 AddSortedDriverBindingProtocol (\r
557 DriverBindingHandleBuffer[Index],\r
022c6d45 558 &NumberOfSortedDriverBindingProtocols,\r
28a00297 559 SortedDriverBindingProtocols,\r
560 DriverBindingHandleCount,\r
adc8840a 561 DriverBindingHandleBuffer,\r
562 FALSE\r
28a00297 563 );\r
564 }\r
565\r
566 //\r
567 // Free the Driver Binding Handle Buffer\r
568 //\r
569 CoreFreePool (DriverBindingHandleBuffer);\r
570\r
85658066 571 //\r
572 // If the number of Driver Binding Protocols has increased since this function started, then return\r
573 // EFI_NOT_READY, so it will be restarted\r
574 //\r
70279390 575 Status = CoreLocateHandleBuffer (\r
022c6d45 576 ByProtocol,\r
577 &gEfiDriverBindingProtocolGuid,\r
70279390 578 NULL,\r
022c6d45 579 &NewDriverBindingHandleCount,\r
70279390 580 &NewDriverBindingHandleBuffer\r
581 );\r
582 CoreFreePool (NewDriverBindingHandleBuffer);\r
583 if (NewDriverBindingHandleCount > DriverBindingHandleCount) {\r
85658066 584 //\r
585 // Free any buffers that were allocated with AllocatePool()\r
586 //\r
587 CoreFreePool (SortedDriverBindingProtocols);\r
588\r
589 return EFI_NOT_READY;\r
590 }\r
591\r
28a00297 592 //\r
593 // Sort the remaining DriverBinding Protocol based on their Version field from\r
594 // highest to lowest.\r
595 //\r
596 for ( ; SortIndex < NumberOfSortedDriverBindingProtocols; SortIndex++) {\r
597 HighestVersion = SortedDriverBindingProtocols[SortIndex]->Version;\r
598 HighestIndex = SortIndex;\r
599 for (Index = SortIndex + 1; Index < NumberOfSortedDriverBindingProtocols; Index++) {\r
600 if (SortedDriverBindingProtocols[Index]->Version > HighestVersion) {\r
601 HighestVersion = SortedDriverBindingProtocols[Index]->Version;\r
602 HighestIndex = Index;\r
603 }\r
604 }\r
605 if (SortIndex != HighestIndex) {\r
606 DriverBinding = SortedDriverBindingProtocols[SortIndex];\r
607 SortedDriverBindingProtocols[SortIndex] = SortedDriverBindingProtocols[HighestIndex];\r
608 SortedDriverBindingProtocols[HighestIndex] = DriverBinding;\r
609 }\r
610 }\r
611\r
612 //\r
613 // Loop until no more drivers can be started on ControllerHandle\r
614 //\r
615 OneStarted = FALSE;\r
616 do {\r
617\r
618 //\r
619 // Loop through the sorted Driver Binding Protocol Instances in order, and see if\r
022c6d45 620 // any of the Driver Binding Protocols support the controller specified by\r
28a00297 621 // ControllerHandle.\r
622 //\r
623 DriverBinding = NULL;\r
624 DriverFound = FALSE;\r
625 for (Index = 0; (Index < NumberOfSortedDriverBindingProtocols) && !DriverFound; Index++) {\r
626 if (SortedDriverBindingProtocols[Index] != NULL) {\r
627 DriverBinding = SortedDriverBindingProtocols[Index];\r
bc6b5892 628 PERF_START (DriverBinding->DriverBindingHandle, "DB:Support:", NULL, 0);\r
28a00297 629 Status = DriverBinding->Supported(\r
022c6d45 630 DriverBinding,\r
28a00297 631 ControllerHandle,\r
632 RemainingDevicePath\r
633 );\r
bc6b5892 634 PERF_END (DriverBinding->DriverBindingHandle, "DB:Support:", NULL, 0);\r
28a00297 635 if (!EFI_ERROR (Status)) {\r
636 SortedDriverBindingProtocols[Index] = NULL;\r
637 DriverFound = TRUE;\r
638\r
639 //\r
640 // A driver was found that supports ControllerHandle, so attempt to start the driver\r
641 // on ControllerHandle.\r
642 //\r
bc6b5892 643 PERF_START (DriverBinding->DriverBindingHandle, "DB:Start:", NULL, 0);\r
28a00297 644 Status = DriverBinding->Start (\r
022c6d45 645 DriverBinding,\r
28a00297 646 ControllerHandle,\r
647 RemainingDevicePath\r
648 );\r
bc6b5892 649 PERF_END (DriverBinding->DriverBindingHandle, "DB:Start:", NULL, 0);\r
28a00297 650\r
651 if (!EFI_ERROR (Status)) {\r
652 //\r
653 // The driver was successfully started on ControllerHandle, so set a flag\r
654 //\r
655 OneStarted = TRUE;\r
656 }\r
657 }\r
658 }\r
659 }\r
660 } while (DriverFound);\r
661\r
662 //\r
663 // Free any buffers that were allocated with AllocatePool()\r
664 //\r
665 CoreFreePool (SortedDriverBindingProtocols);\r
666\r
667 //\r
668 // If at least one driver was started on ControllerHandle, then return EFI_SUCCESS.\r
669 //\r
670 if (OneStarted) {\r
671 return EFI_SUCCESS;\r
022c6d45 672 }\r
28a00297 673\r
674 //\r
675 // If no drivers started and RemainingDevicePath is an End Device Path Node, then return EFI_SUCCESS\r
676 //\r
677 if (RemainingDevicePath != NULL) {\r
678 if (IsDevicePathEnd (RemainingDevicePath)) {\r
679 return EFI_SUCCESS;\r
680 }\r
022c6d45 681 }\r
28a00297 682\r
683 //\r
684 // Otherwise, no drivers were started on ControllerHandle, so return EFI_NOT_FOUND\r
685 //\r
686 return EFI_NOT_FOUND;\r
687}\r
688\r
689\r
162ed594 690\r
691/**\r
692 Disonnects a controller from a driver\r
693\r
022c6d45 694 @param ControllerHandle ControllerHandle The handle of\r
695 the controller from which\r
696 driver(s) are to be\r
697 disconnected.\r
698 @param DriverImageHandle DriverImageHandle The driver to\r
699 disconnect from ControllerHandle.\r
700 @param ChildHandle ChildHandle The handle of the\r
701 child to destroy.\r
702\r
703 @retval EFI_SUCCESS One or more drivers were\r
704 disconnected from the controller.\r
705 @retval EFI_SUCCESS On entry, no drivers are managing\r
706 ControllerHandle.\r
707 @retval EFI_SUCCESS DriverImageHandle is not NULL,\r
708 and on entry DriverImageHandle is\r
709 not managing ControllerHandle.\r
284ee2e8 710 @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.\r
022c6d45 711 @retval EFI_INVALID_PARAMETER DriverImageHandle is not NULL,\r
712 and it is not a valid EFI_HANDLE.\r
713 @retval EFI_INVALID_PARAMETER ChildHandle is not NULL, and it\r
714 is not a valid EFI_HANDLE.\r
715 @retval EFI_OUT_OF_RESOURCES There are not enough resources\r
716 available to disconnect any\r
717 drivers from ControllerHandle.\r
718 @retval EFI_DEVICE_ERROR The controller could not be\r
719 disconnected because of a device\r
162ed594 720 error.\r
721\r
722**/\r
022c6d45 723EFI_STATUS\r
28a00297 724EFIAPI\r
725CoreDisconnectController (\r
726 IN EFI_HANDLE ControllerHandle,\r
727 IN EFI_HANDLE DriverImageHandle OPTIONAL,\r
728 IN EFI_HANDLE ChildHandle OPTIONAL\r
729 )\r
28a00297 730{\r
731 EFI_STATUS Status;\r
732 IHANDLE *Handle;\r
733 EFI_HANDLE *DriverImageHandleBuffer;\r
734 EFI_HANDLE *ChildBuffer;\r
735 UINTN Index;\r
736 UINTN HandleIndex;\r
737 UINTN DriverImageHandleCount;\r
738 UINTN ChildrenToStop;\r
739 UINTN ChildBufferCount;\r
740 UINTN StopCount;\r
741 BOOLEAN Duplicate;\r
742 BOOLEAN ChildHandleValid;\r
743 BOOLEAN DriverImageHandleValid;\r
744 LIST_ENTRY *Link;\r
745 LIST_ENTRY *ProtLink;\r
746 OPEN_PROTOCOL_DATA *OpenData;\r
747 PROTOCOL_INTERFACE *Prot;\r
748 EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;\r
749\r
750 //\r
751 // Make sure ControllerHandle is valid\r
752 //\r
753 Status = CoreValidateHandle (ControllerHandle);\r
754 if (EFI_ERROR (Status)) {\r
755 return Status;\r
756 }\r
757\r
758 //\r
759 // Make sure ChildHandle is valid if it is not NULL\r
760 //\r
761 if (ChildHandle != NULL) {\r
762 Status = CoreValidateHandle (ChildHandle);\r
763 if (EFI_ERROR (Status)) {\r
764 return Status;\r
765 }\r
766 }\r
767\r
768 Handle = ControllerHandle;\r
769\r
770 //\r
771 // Get list of drivers that are currently managing ControllerHandle\r
772 //\r
773 DriverImageHandleBuffer = NULL;\r
022c6d45 774 DriverImageHandleCount = 1;\r
775\r
28a00297 776 if (DriverImageHandle == NULL) {\r
777 //\r
778 // Look at each protocol interface for a match\r
779 //\r
780 DriverImageHandleCount = 0;\r
781\r
782 CoreAcquireProtocolLock ();\r
783 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
784 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
022c6d45 785 for (ProtLink = Prot->OpenList.ForwardLink;\r
786 ProtLink != &Prot->OpenList;\r
28a00297 787 ProtLink = ProtLink->ForwardLink) {\r
788 OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
789 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {\r
790 DriverImageHandleCount++;\r
791 }\r
792 }\r
793 }\r
794 CoreReleaseProtocolLock ();\r
022c6d45 795\r
28a00297 796 //\r
797 // If there are no drivers managing this controller, then return EFI_SUCCESS\r
798 //\r
799 if (DriverImageHandleCount == 0) {\r
800 Status = EFI_SUCCESS;\r
801 goto Done;\r
802 }\r
803\r
9c4ac31c 804 DriverImageHandleBuffer = AllocatePool (sizeof (EFI_HANDLE) * DriverImageHandleCount);\r
28a00297 805 if (DriverImageHandleBuffer == NULL) {\r
806 Status = EFI_OUT_OF_RESOURCES;\r
807 goto Done;\r
808 }\r
809\r
810 DriverImageHandleCount = 0;\r
811\r
812 CoreAcquireProtocolLock ();\r
813 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
814 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
022c6d45 815 for (ProtLink = Prot->OpenList.ForwardLink;\r
816 ProtLink != &Prot->OpenList;\r
28a00297 817 ProtLink = ProtLink->ForwardLink) {\r
818 OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
819 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {\r
820 Duplicate = FALSE;\r
821 for (Index = 0; Index< DriverImageHandleCount; Index++) {\r
822 if (DriverImageHandleBuffer[Index] == OpenData->AgentHandle) {\r
823 Duplicate = TRUE;\r
824 break;\r
825 }\r
826 }\r
827 if (!Duplicate) {\r
828 DriverImageHandleBuffer[DriverImageHandleCount] = OpenData->AgentHandle;\r
829 DriverImageHandleCount++;\r
830 }\r
831 }\r
832 }\r
833 }\r
834 CoreReleaseProtocolLock ();\r
835 }\r
836\r
837 StopCount = 0;\r
838 for (HandleIndex = 0; HandleIndex < DriverImageHandleCount; HandleIndex++) {\r
839\r
840 if (DriverImageHandleBuffer != NULL) {\r
841 DriverImageHandle = DriverImageHandleBuffer[HandleIndex];\r
842 }\r
843\r
844 //\r
845 // Get the Driver Binding Protocol of the driver that is managing this controller\r
846 //\r
847 Status = CoreHandleProtocol (\r
022c6d45 848 DriverImageHandle,\r
849 &gEfiDriverBindingProtocolGuid,\r
28a00297 850 (VOID **)&DriverBinding\r
851 );\r
d2fbaaab 852 if (EFI_ERROR (Status) || DriverBinding == NULL) {\r
28a00297 853 Status = EFI_INVALID_PARAMETER;\r
854 goto Done;\r
855 }\r
856\r
857 //\r
858 // Look at each protocol interface for a match\r
859 //\r
860 DriverImageHandleValid = FALSE;\r
861 ChildBufferCount = 0;\r
862\r
863 CoreAcquireProtocolLock ();\r
864 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
865 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
022c6d45 866 for (ProtLink = Prot->OpenList.ForwardLink;\r
867 ProtLink != &Prot->OpenList;\r
28a00297 868 ProtLink = ProtLink->ForwardLink) {\r
869 OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
870 if (OpenData->AgentHandle == DriverImageHandle) {\r
871 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
872 ChildBufferCount++;\r
022c6d45 873 }\r
28a00297 874 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {\r
875 DriverImageHandleValid = TRUE;\r
876 }\r
877 }\r
878 }\r
879 }\r
880 CoreReleaseProtocolLock ();\r
881\r
882 if (DriverImageHandleValid) {\r
883 ChildHandleValid = FALSE;\r
884 ChildBuffer = NULL;\r
885 if (ChildBufferCount != 0) {\r
9c4ac31c 886 ChildBuffer = AllocatePool (sizeof (EFI_HANDLE) * ChildBufferCount);\r
28a00297 887 if (ChildBuffer == NULL) {\r
888 Status = EFI_OUT_OF_RESOURCES;\r
889 goto Done;\r
890 }\r
891\r
892 ChildBufferCount = 0;\r
893\r
894 CoreAcquireProtocolLock ();\r
895 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
896 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
022c6d45 897 for (ProtLink = Prot->OpenList.ForwardLink;\r
898 ProtLink != &Prot->OpenList;\r
28a00297 899 ProtLink = ProtLink->ForwardLink) {\r
900 OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
901 if ((OpenData->AgentHandle == DriverImageHandle) &&\r
902 ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0)) {\r
903 Duplicate = FALSE;\r
904 for (Index = 0; Index < ChildBufferCount; Index++) {\r
905 if (ChildBuffer[Index] == OpenData->ControllerHandle) {\r
906 Duplicate = TRUE;\r
907 break;\r
908 }\r
909 }\r
910 if (!Duplicate) {\r
911 ChildBuffer[ChildBufferCount] = OpenData->ControllerHandle;\r
912 if (ChildHandle == ChildBuffer[ChildBufferCount]) {\r
913 ChildHandleValid = TRUE;\r
914 }\r
915 ChildBufferCount++;\r
916 }\r
917 }\r
918 }\r
919 }\r
920 CoreReleaseProtocolLock ();\r
921 }\r
922\r
923 if (ChildHandle == NULL || ChildHandleValid) {\r
924 ChildrenToStop = 0;\r
925 Status = EFI_SUCCESS;\r
926 if (ChildBufferCount > 0) {\r
927 if (ChildHandle != NULL) {\r
928 ChildrenToStop = 1;\r
929 Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, &ChildHandle);\r
930 } else {\r
931 ChildrenToStop = ChildBufferCount;\r
932 Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, ChildBuffer);\r
933 }\r
934 }\r
935 if (!EFI_ERROR (Status) && ((ChildHandle == NULL) || (ChildBufferCount == ChildrenToStop))) {\r
936 Status = DriverBinding->Stop (DriverBinding, ControllerHandle, 0, NULL);\r
937 }\r
938 if (!EFI_ERROR (Status)) {\r
939 StopCount++;\r
940 }\r
941 }\r
942\r
943 if (ChildBuffer != NULL) {\r
944 CoreFreePool (ChildBuffer);\r
945 }\r
946 }\r
947 }\r
948\r
949 if (StopCount > 0) {\r
950 Status = EFI_SUCCESS;\r
951 } else {\r
952 Status = EFI_NOT_FOUND;\r
953 }\r
022c6d45 954\r
955Done:\r
28a00297 956\r
957 if (DriverImageHandleBuffer != NULL) {\r
958 CoreFreePool (DriverImageHandleBuffer);\r
959 }\r
960\r
961 return Status;\r
962}\r