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