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