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